Generic OGC API-EDR 1.1 xarray backend
Project description
edr-xarray
Lazy xarray backend for OGC API - Environmental Data Retrieval (EDR) 1.1 /cubes endpoint.
Status: alpha (v0.1.2)
Overview
edr-xarray registers engine="edr" with xarray, letting you open any EDR 1.1-compliant
collection as a lazy xarray.Dataset. Data is only fetched from the server when you
call .values, .load(), or .compute() on a DataArray — opening the dataset
issues lightweight metadata requests for the collection, for the selected instance when
instance= is supplied, and optionally one axis-discovery probe.
Designed to be subclassed: downstream packages can override transport, metadata parsing,
CoverageJSON handling, and URL routing via seven documented hook methods on EdrDataStore.
Installation
pip install edr-xarray
Or with uv:
uv add edr-xarray
Requires Python 3.11 or 3.12 and xarray 2024.6+.
Usage
import xarray as xr
# Open an EDR collection (lazy — metadata plus an optional axis probe on open)
ds = xr.open_dataset(
"https://edr.example.com/collections/temperature_2m",
engine="edr",
parameter_names=["t2m"],
bbox=(-3.5, 50.2, -2.1, 51.0),
datetime="2023-01-01T00:00:00Z/2023-01-07T00:00:00Z",
)
# Inspect structure (no data fetched yet)
print(ds.dims) # {'t': 168, 'y': 50, 'x': 50}
print(ds.data_vars) # {'t2m': <xarray.Variable>}
print(ds["t2m"].attrs) # {'units': 'K', 'long_name': 'Air temperature', ...}
# Fetch a subset (triggers one EDR /cube query)
sub = ds["t2m"].sel(x=slice(-3.0, -2.5)).load()
print(sub.shape) # (168, 50, N)
Discovery modes
By default (discovery="probe"), open_dataset issues one extra GET request to the cube
endpoint to discover the exact grid axes (resolution, coordinate arrays). Two alternative modes:
When bbox=, datetime=, or z= are supplied, probe discovery uses those open-time
subsets to declare xarray coordinates. For collections with long time axes and abbreviated
temporal metadata, pass a bounded datetime interval so ds.t matches the analysis window.
If the server advertises explicit temporal values, those values are used for the time
coordinate. If it only advertises a temporal interval and no datetime= is supplied,
edr-xarray opens the first instant as a small, consistent default.
# metadata_only: use only selected collection/instance metadata (bbox + temporal extent)
# Fewer requests but lower resolution coordinate arrays
ds = xr.open_dataset(url, engine="edr", discovery="metadata_only")
# strict: requires explicit temporal/vertical coordinate values in metadata
# and uses spatial bbox endpoints for x/y axes
ds = xr.open_dataset(url, engine="edr", discovery="strict")
Collections with instances (forecast runs)
When instance= is supplied, edr-xarray fetches the selected instance metadata
and builds coordinates, variables, attributes, fallback bbox, and fallback
datetime from that instance. Data values are still lazy and are fetched only
when xarray requests concrete array values.
ds = xr.open_dataset(
"https://edr.example.com/collections/model_output",
engine="edr",
instance="f024",
parameter_names=["temperature"],
)
Vertical levels (z)
# Single level
ds = xr.open_dataset(url, engine="edr", z=850)
# Level range
ds = xr.open_dataset(url, engine="edr", z="1000/500")
Authentication
Pass a pre-configured httpx.Client for any auth style (API key, Bearer token, Basic, mTLS):
import httpx
import xarray as xr
client = httpx.Client(headers={"X-Api-Key": "your-key-here"})
ds = xr.open_dataset(url, engine="edr", session=client)
The injected client is not closed by edr-xarray — manage its lifecycle yourself.
Dask integration
Install the optional Dask extra before opening datasets with chunks=...:
pip install "edr-xarray[dask]"
# Chunk along time for out-of-core analysis
ds = xr.open_dataset(url, engine="edr", chunks={"t": 1})
result = ds["t2m"].mean(dim="t").compute()
Subclassing
Override EdrDataStore hooks to customize transport, URL routing, or response parsing:
from typing import Any, Mapping
import httpx
from edr_xarray import EdrDataStore
class AuthenticatedStore(EdrDataStore):
def _request(
self, method: str, url: str, *,
params: Mapping[str, str] | None = None,
headers: Mapping[str, str] | None = None,
) -> httpx.Response:
merged = dict(headers or {})
merged["X-Api-Key"] = "my-secret"
return super()._request(method, url, params=params, headers=merged)
Available hooks: _request, _parse_collection_metadata, _negotiate_output_format,
_build_cube_url, _parse_coveragejson, _translate_indexer, _discover_axes.
See tests/test_subclass_extensibility.py for full usage examples.
Examples
Guided Jupyter notebooks live in examples/. They use
live EDR endpoints and make the lazy open, indexing, and fetch boundaries
explicit.
Limitations (v1)
- Only
/cubesqueries are supported (no/position,/area,/trajectory, etc.). - Only CoverageJSON responses (Grid domain, flat NdArray values).
bboxinput uses CRS84 axis order(lon_min, lat_min, lon_max, lat_max).- No antimeridian-crossing bbox support.
- No exotic z syntax (
R14/.../..., comma-separated level lists). - No automatic retry, caching, or async HTTP client.
Development
git clone https://github.com/armagankaratosun/edr-xarray
cd edr-xarray
uv sync
uv run pytest
Run type checks and lint:
uv run ruff check src tests
uv run ruff format --check src tests
uv run mypy --strict src/edr_xarray
uv run pyright
uv run pyright --verifytypes edr_xarray --ignoreexternal
uv run pytest --cov=src/edr_xarray --cov-fail-under=95 -v -m "not live"
Run opt-in live tests against an EDR server:
EDR_LIVE_URL=http://localhost:8000 uv run pytest -m live
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file edr_xarray-0.1.2.tar.gz.
File metadata
- Download URL: edr_xarray-0.1.2.tar.gz
- Upload date:
- Size: 62.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d18d249dfefad2342836b8d6d225458da10aaf549dfc7d9d370a6acc0e010c0a
|
|
| MD5 |
fbae60ca75103be9a78c2564dca7488d
|
|
| BLAKE2b-256 |
35245639337c32afcb08a65a040970cda53e96b3753ecc060636eba1ffe524c0
|
Provenance
The following attestation bundles were made for edr_xarray-0.1.2.tar.gz:
Publisher:
publish.yml on armagankaratosun/edr-xarray
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
edr_xarray-0.1.2.tar.gz -
Subject digest:
d18d249dfefad2342836b8d6d225458da10aaf549dfc7d9d370a6acc0e010c0a - Sigstore transparency entry: 1497874575
- Sigstore integration time:
-
Permalink:
armagankaratosun/edr-xarray@366ae57cb9c9f3718448446056a95285ee2616e2 -
Branch / Tag:
refs/tags/0.1.2 - Owner: https://github.com/armagankaratosun
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@366ae57cb9c9f3718448446056a95285ee2616e2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file edr_xarray-0.1.2-py3-none-any.whl.
File metadata
- Download URL: edr_xarray-0.1.2-py3-none-any.whl
- Upload date:
- Size: 32.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
496ac1fe6ade30d01bea0aba202adfe2eb5a0e0a314d6786ee721d72a07ef1d3
|
|
| MD5 |
9598d480d55a48f6cde0c55520817ff0
|
|
| BLAKE2b-256 |
7a08ecd6161d0b3632e3c700200ccba45967bc28e90716667f5d71d9fd07232c
|
Provenance
The following attestation bundles were made for edr_xarray-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on armagankaratosun/edr-xarray
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
edr_xarray-0.1.2-py3-none-any.whl -
Subject digest:
496ac1fe6ade30d01bea0aba202adfe2eb5a0e0a314d6786ee721d72a07ef1d3 - Sigstore transparency entry: 1497874727
- Sigstore integration time:
-
Permalink:
armagankaratosun/edr-xarray@366ae57cb9c9f3718448446056a95285ee2616e2 -
Branch / Tag:
refs/tags/0.1.2 - Owner: https://github.com/armagankaratosun
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@366ae57cb9c9f3718448446056a95285ee2616e2 -
Trigger Event:
release
-
Statement type: