Coordinates
Overview
Coordinates are used to:
Evaluate nodes which retrieve and process data
Define the coordinates of data sources
Podpac Coordinates are modeled after the coords in xarray,
with some additional restrictions and enhancements. Coordinates are created from a list of coordinate values
and a corresponding list of dims
:
podpac.Coordinates(values, dims=dims, ...)
Unlike xarray, podpac coordinate values are always either float
or np.datetime64
. For convenience, podpac
automatically converts datetime strings such as '2018-01-01'
to np.datetime64
. In addition, the allowed dimensions
are 'lat'
, 'lon'
, 'time'
, and 'alt'
.
Coordinate Creation
Unstacked Coordinates
Unstacked multidimensional coordinates form a grid of points. For example, the following Coordinates contain three dimensions and a total of 24 points.
[.] from podpac import Coordinates
[.] lat = [0, 1, 2]
[.] lon = [10, 20, 30, 40]
[.] time = ['2018-01-01', '2018-01-02']
[.] Coordinates([lat, lon], dims=['lat', 'lon'])
Coordinates
lat: ArrayCoordinates1d(lat): Bounds[0.0, 2.0], N[3]
lon: ArrayCoordinates1d(lon): Bounds[10.0, 40.0], N[4]
[.] Coordinates([lat, lon, time], dims=['lat', 'lon', 'time'])
Coordinates
lat: ArrayCoordinates1d(lat): Bounds[0.0, 2.0], N[3]
lon: ArrayCoordinates1d(lon): Bounds[10.0, 40.0], N[4]
time: ArrayCoordinates1d(time): Bounds[2018-01-01, 2018-01-02], N[2]
You can also create coordinates with just one dimension the same way:
>>> from podpac import Coordinates
>>> Coordinates([time], dims=['time'])
Coordinates
time: ArrayCoordinates1d(time): Bounds[2018-01-01, 2018-01-02], N[2]
Stacked Coordinates
Coordinates from multiple dimensions can be stacked together in a list (rather than representing a grid).
For example, Coordinates with stacked latitude and longitude contain one point for each (lat, lon) pair. Note that the name for this stacked dimension is ‘lat_lon’, using an underscore to combine the underlying dimensions. The following example has a single stacked dimension and a total of 3 points.
[.] from podpac import Coordinates
[.] lat = [0, 1, 2]
[.] lon = [10, 20, 30]
[.] c = Coordinates([[lat, lon]], dims=['lat_lon'])
[.] c
Coordinates
lat_lon[lat]: ArrayCoordinates1d(lat): Bounds[0.0, 2.0], N[3]
lat_lon[lon]: ArrayCoordinates1d(lon): Bounds[10.0, 30.0], N[3]
[.] c['lat_lon'].coordinates[0]
(0.0, 10.0)
Coordinates can combine stacked dimensions and unstacked dimensions. For example, in the following Coordinates the (lat, lon)
values and the time
values form a grid of 6 total points.
[.] from podpac import Coordinates
[.] lat = [0, 1, 2]
[.] lon = [10, 20, 30]
[.] time = ['2018-01-01', '2018-01-02']
[.] c = Coordinates([[lat, lon], time], dims=['lat_lon', 'time'])
Coordinates
lat_lon[lat]: ArrayCoordinates1d(lat): Bounds[0.0, 2.0], N[3]
lat_lon[lon]: ArrayCoordinates1d(lon): Bounds[10.0, 30.0], N[3]
time: ArrayCoordinates1d(time): Bounds[2018-01-01, 2018-01-02], N[2]
[.] c['lat_lon'].coordinates[0]
(0.0, 10.0)
[.] c['time'].coordinates[0]
numpy.datetime64('2018-01-01')
Uniformly-Spaced Coordinates
Podpac provides two convenience functions crange
and clinspace
for creating uniformly-spaced coordinates, similar to the arange
and linspace
functions provided by numpy.
Coordinates Range
podpac.crange
creates uniformly-spaced coordinates from a start, stop, and step.
Unlike np.arange
:
string inputs are supported for datetimes and timedeltas
the stop value will be included in the coordinates if it falls an exact number of steps from the start
>>> import podpac
>>> c = podpac.crange(0, 7, 2)
>>> c.coordinates
array([0., 2., 4., 6.])
>>> c = podpac.crange(0, 8, 2)
>>> c.coordinates
array([0., 2., 4., 6., 8.])
>>> c = podpac.crange('2018-01-01', '2018-03-01', '1,M')
>>> c.coordinates
array(['2018-01-01', '2018-02-01', '2018-03-01'], dtype='datetime64[D]')
Coordinates Linspace
podpac.clinspace
creates uniformly-spaced coordinates from a start, stop, and size.
Unlike np.linspace
:
string inputs are supported for datetimes
tuple inputs are supported for stacked coordinates
>>> import podpac
>>> c = podpac.clinspace(0, 8, 5)
>>> c.coordinates
array([0., 2., 4., 6., 8.])
>>> c = podpac.clinspace('2018-01-01', '2018-03-01', 3)
>>> c.coordinates
array(['2018-01-01', '2018-01-30', '2018-02-28'], dtype='datetime64[D]')
>>> c = podpac.clinspace((0, 10), (1, 20), 3)
>>> c.coordinates
MultiIndex(levels=[[0.0, 0.5, 1.0], [10.0, 15.0, 20.0]],
labels=[[0, 1, 2], [0, 1, 2]])
These functions wrap UniformCoordinates1d (see Advanced Usage), which is particularly useful for coordinates with an extremely large number of points.
Rotated Coordinates
TODO
Alternate Constructors
Unstacked coordinates can also be created using the Coordinates.grid
alternate constructor:
>>> from podpac import Coordinates
>>> Coordinates.grid(lat=[0, 1, 2], lon=[10, 20, 30, 40])
Coordinates
lat: ArrayCoordinates1d(lat): Bounds[0.0, 2.0], N[3]
lon: ArrayCoordinates1d(lon): Bounds[10.0, 40.0], N[4]
Stacked coordinates can be created using the Coordinates.points
alternate constructor:
>>> from podpac import Coordinates
>>> Coordinates.points(lat=[0, 1, 2], lon=[10, 20, 30])
Coordinates
lat_lon[lat]: ArrayCoordinates1d(lat): Bounds[0.0, 2.0], N[3]
lat_lon[lon]: ArrayCoordinates1d(lon): Bounds[10.0, 30.0], N[3]
For convenience, a tuple can be used to generate uniformly-spaced coordinates. If the third item is an integer, it is interpreted as a size, otherwise it is interpreted as a step. The following will all be equivalent:
Coordinates.grid(lat=(0, 2, 3), lon=(10, 40, 4))
Coordinates.grid(lat=(0, 2, 1.0), lon=(10, 40, 10.0))
Coordinates.grid(lat=clinspace(0, 2, 3), lon=clinspace(10, 40, 4))
Coordinates.grid(lat=crange(0, 2, 1), lon=crange(10, 40, 10))
Note that in Python 3.5 and below, the order
argument is required to both grid
and points
Coordinates.grid(lat=[0, 1, 2], lon=[10, 20, 30], order=['lat', 'lon'])
Coordinates.points(lat=[0, 1, 2], lon=[10, 20, 30], order=['lat', 'lon'])
Advanced Usage
TODO
from podpac.coordinates import UniformCoordinates1d, ArrayCoordinates1d, Coordinates, StackedCoordinates
>>> lat = UniformCoordinates1d(0, 1, size=100, name='lat')
>>> lon = UniformCoordinates1d(10, 20, size=100, name='lon')
>>> time = ArrayCoordinates1d(['2018-01-01', '2018-02-03'], name='time')
>>> Coordinates([StackedCoordinates([lat, lon]), time])
Coordinates
lat_lon[lat]: UniformCoordinates1d(lat): Bounds[0.0, 1.0], N[100]
lat_lon[lon]: UniformCoordinates1d(lon): Bounds[10.0, 20.0], N[100]
time: ArrayCoordinates1d(time): Bounds[2018-01-01, 2018-02-03], N[2]
Coordinate API
TODO
Coordinates contain some useful properties relating to its dimensions and underlying coordinate values.
>>> from podpac import Coordinates
>>> c = Coordinates([lat, lon, time], dims=['lat', 'lon', 'time'])
>>> c.ndims
>>> c.dims
>>> c.shape
>>> c.size
Coordinates are dict-like. The keys()
, values()
, and items()
Coordinates Groups
TODO