EDR Router
Contents
EDR Router#
The OGC Environmental Data Retrieval API is designed to be a common web mapping focused method for querying data.
In restful-grids/xpublish/edr_router.py
, we’ve implemented edr_router
which currently provides an EDR position endpoint. This endpoint is especially useful for querying a time series from a gridded dataset.
The default response for EDR endpoints is CoverageJSON, but we’ve also decided to support NetCDF responses if f=nc
is added to the query parameters, or CSV with f=csv
.
Setting up the router#
The edr_router expects datasets that have CF conventions attributes that cf-xarray can read. Specifically it’s looking for attributes that the ds.cf.axes
can find X
and Y
axes (Z
and T
will also be used if found).
If a dataset doesn’t have full CF attributes, you can set them with ds[X_COORD].attrs["axis"] = "X"
and similar for the other axes.
Then you can import and include edr_router
when instantiating xpublish.Rest
or subclass. We suggest including a prefix for routers to avoid conflicts, similar to:
rest = xpublish.Rest(
DATASETS_DICT,
routers=[
(base_router, {"tags": ["info"]}),
(edr_router, {"tags": ["edr"], "prefix": "/edr"}),
(zarr_router, {"tags": ["zarr"], "prefix": "/zarr"}),
]
)
At this point you will get an EDR endpoint at /datasets/{dataset_id}/edr/position
(or /edr/position
if you only have a single dataset).
Making a request#
The minimum path and query params you need for a request is a dataset_id
(see /datasets/
) and a Well Known Text point for the coords
query string.
The endpoint will try to find the nearest values to the point.
parameter-name
#
We are also going to add a parameter-name
to keep this somewhat reasonable, though that is not necessary and the endpoint will respond with all variables.
Multiple parameters (variables) can also be given by comma seperating them, and due to the magic of cf-xarray, CF standard names can also be used and will return the associated variables. (in this case ¶meter-name=sea_surface_wave_significant_height
would return the hs
variable.
import requests
r = requests.get(
"http://0.0.0.0:9005/datasets/ww3/edr/position"
"?coords=POINT(-69.35 43.72)"
"¶meter-name=sea_surface_wave_significant_height"
)
r.json()
{'type': 'Coverage',
'domain': {'type': 'Domain',
'domainType': 'Grid',
'axes': {'t': {'values': ['2022-04-11T12:00:00',
'2022-04-11T12:59:59',
'2022-04-11T14:00:00',
'2022-04-11T15:00:00',
'2022-04-11T15:59:59',
'2022-04-11T17:00:00',
'2022-04-11T18:00:00',
'2022-04-11T18:59:59',
'2022-04-11T20:00:00',
'2022-04-11T21:00:00',
'2022-04-11T21:59:59',
'2022-04-11T23:00:00',
'2022-04-12T00:00:00',
'2022-04-12T00:59:59',
'2022-04-12T02:00:00',
'2022-04-12T03:00:00',
'2022-04-12T03:59:59',
'2022-04-12T05:00:00',
'2022-04-12T06:00:00',
'2022-04-12T06:59:59',
'2022-04-12T08:00:00',
'2022-04-12T09:00:00',
'2022-04-12T09:59:59',
'2022-04-12T11:00:00',
'2022-04-12T12:00:00',
'2022-04-12T12:59:59',
'2022-04-12T14:00:00',
'2022-04-12T15:00:00',
'2022-04-12T15:59:59',
'2022-04-12T17:00:00',
'2022-04-12T18:00:00',
'2022-04-12T18:59:59',
'2022-04-12T20:00:00',
'2022-04-12T21:00:00',
'2022-04-12T21:59:59',
'2022-04-12T23:00:00',
'2022-04-13T00:00:00',
'2022-04-13T00:59:59',
'2022-04-13T02:00:00',
'2022-04-13T03:00:00',
'2022-04-13T03:59:59',
'2022-04-13T05:00:00',
'2022-04-13T06:00:00',
'2022-04-13T06:59:59',
'2022-04-13T08:00:00',
'2022-04-13T09:00:00',
'2022-04-13T09:59:59',
'2022-04-13T11:00:00',
'2022-04-13T12:00:00',
'2022-04-13T12:59:59',
'2022-04-13T14:00:00',
'2022-04-13T15:00:00',
'2022-04-13T15:59:59',
'2022-04-13T17:00:00',
'2022-04-13T18:00:00',
'2022-04-13T18:59:59',
'2022-04-13T20:00:00',
'2022-04-13T21:00:00',
'2022-04-13T21:59:59',
'2022-04-13T23:00:00',
'2022-04-14T00:00:00',
'2022-04-14T00:59:59',
'2022-04-14T02:00:00',
'2022-04-14T03:00:00',
'2022-04-14T03:59:59',
'2022-04-14T05:00:00',
'2022-04-14T06:00:00',
'2022-04-14T06:59:59',
'2022-04-14T08:00:00',
'2022-04-14T09:00:00',
'2022-04-14T09:59:59',
'2022-04-14T11:00:00',
'2022-04-14T12:00:00']},
'forecast_reference_time': {'values': ['2022-04-11T12:00:00']}},
'referencing': []},
'parameters': {'hs': {'type': 'Parameter',
'observedProperty': {'label': {'en': 'significant height of wind and swell waves'}},
'description': {'en': 'significant height of wind and swell waves'},
'unit': {'label': {'en': 'm'}}}},
'ranges': {'hs': {'type': 'NdArray',
'dataType': 'float',
'axisNames': ['forecast_reference_time', 't'],
'shape': [1, 73],
'values': [0.33467215299606323,
0.3588910698890686,
0.3660368025302887,
0.3152061402797699,
0.2875429093837738,
0.33364781737327576,
0.42414912581443787,
0.5218766927719116,
0.599566638469696,
0.6628382802009583,
0.6959347724914551,
0.7017455697059631,
0.6900897026062012,
0.6990023255348206,
0.7459676861763,
0.8135576248168945,
0.8708090782165527,
0.9190717339515686,
0.9822579026222229,
1.0730650424957275,
1.1682802438735962,
1.2368590831756592,
1.2590762376785278,
1.2461904287338257,
1.2177737951278687,
1.190627098083496,
1.1743522882461548,
1.1686142683029175,
1.168257474899292,
1.1705492734909058,
1.1713541746139526,
1.1505155563354492,
1.1002039909362793,
1.029807448387146,
0.9527088403701782,
0.8763468265533447,
0.8059961199760437,
0.7473487257957458,
0.6959123611450195,
0.6488614678382874,
0.6027891635894775,
0.5554247498512268,
0.5091127157211304,
0.4687694013118744,
0.4349559545516968,
0.40602195262908936,
0.3779057264328003,
0.3484857380390167,
0.3213227689266205,
0.30005601048469543,
0.2922517955303192,
0.3058054745197296,
0.34318259358406067,
0.39665448665618896,
0.4514908790588379,
0.4962618947029114,
0.5274868011474609,
0.5485127568244934,
0.5546026825904846,
0.5439878106117249,
0.5306615829467773,
0.521487832069397,
0.5167329907417297,
0.513405442237854,
0.5168517827987671,
0.531062662601471,
0.5381449460983276,
0.5489262938499451,
0.570189356803894,
0.6079721450805664,
0.6753485798835754,
0.7782320976257324,
0.9024170637130737]}}}
datetime
#
The next query param of interest to most users will be datetime. This will take either a single datetime and a range as ISO formatted string. To use a range, put a slash between the two times.
The trouble with timezones
The date format needs to match if the dataset is timezone aware, or not.
So we can add &datetime=2022-04-11T12:00:00/2022-04-11T23:00:00
to our previous query to restrict down the response further.
r = requests.get(
"http://0.0.0.0:9005/datasets/ww3/edr/position"
"?coords=POINT(-69.35 43.72)"
"¶meter-name=sea_surface_wave_significant_height"
"&datetime=2022-04-11T12:00:00/2022-04-11T23:00:00"
)
r.json()
{'type': 'Coverage',
'domain': {'type': 'Domain',
'domainType': 'Grid',
'axes': {'t': {'values': ['2022-04-11T12:00:00',
'2022-04-11T12:59:59',
'2022-04-11T14:00:00',
'2022-04-11T15:00:00',
'2022-04-11T15:59:59',
'2022-04-11T17:00:00',
'2022-04-11T18:00:00',
'2022-04-11T18:59:59',
'2022-04-11T20:00:00',
'2022-04-11T21:00:00',
'2022-04-11T21:59:59',
'2022-04-11T23:00:00']},
'forecast_reference_time': {'values': ['2022-04-11T12:00:00']}},
'referencing': []},
'parameters': {'hs': {'type': 'Parameter',
'observedProperty': {'label': {'en': 'significant height of wind and swell waves'}},
'description': {'en': 'significant height of wind and swell waves'},
'unit': {'label': {'en': 'm'}}}},
'ranges': {'hs': {'type': 'NdArray',
'dataType': 'float',
'axisNames': ['forecast_reference_time', 't'],
'shape': [1, 12],
'values': [0.33467215299606323,
0.3588910698890686,
0.3660368025302887,
0.3152061402797699,
0.2875429093837738,
0.33364781737327576,
0.42414912581443787,
0.5218766927719116,
0.599566638469696,
0.6628382802009583,
0.6959347724914551,
0.7017455697059631]}}}
f
for format#
While CoverageJSON is useful for browser based access, other formats can be useful in other contexts. For that the f
query parameter can be passed.
Currently csv
for CSV files, and nc
for NetCDF files have been added.
Extra coordinates#
If there are extra coordinates they can also be included as query parameters. Similar to the datetime
query param, /
is supported for a range to slice on in place of selecting.
For this dataset, if we used &time=2022-04-11T12:00:00/2022-04-11T23:00:00
we would have gotten the same result as the last query.
full_url = "http://0.0.0.0:9005/datasets/ww3/edr/position?coords=POINT(-69.35 43.72)¶meter-name=sea_surface_wave_significant_height,dir,t02&datetime=2022-04-11T12:00:00/2022-04-11T23:00:00&f=csv"
API Reference#
- GET /datasets/{dataset_id}/edr/position#
Position query
Return position data based on WKT Point(lon lat) coordinate.
Extra selecting/slicing parameters can be provided as additional query strings.
- Parameters
dataset_id (string) –
- Query Parameters
coords (string) – Well Known Text coordinates (Required)
z (string) – Height or depth of query
datetime (string) – Query by a single ISO time or a range of ISO times. To query by a range, split the times with a slash
parameter-name (string) – xarray variables to query
crs (string) – CRS is not yet implemented
f (string) – Data is returned as a CoverageJSON by default, but NetCDF is supported with f=nc, or CSV with csv
- Status Codes
200 OK – Successful Response
422 Unprocessable Entity – Validation Error