xcube-eopf is a Python package and xcube plugin that adds a data store
named eopf-zarr to xcube. The data store is used to access ESA EOPF data products as an
analysis-ready datacube (ARDC).
IMPORTANT
xcube-eopfis currently under active development.
Some features may be partially implemented or still in progress.
The EOPF xcube data store is designed to provide analysis-ready data cubes from the EOPF Sentinel Zarr samples for Sentinel-1, Sentinel-2, and Sentinel-3 missions. The main features are summarized below. A more in depth documentation is given in the User Guide.
Currently, support is focused on Sentinel-2 products.
Support for Sentinel-1 will be added in an upcoming release.
The current implementation supports two Sentinel-2 product levels, available as
data_id values:
sentinel-2-l1c: Level-1C top-of-atmosphere reflectancesentinel-2-l2a: Level-2A atmospherically corrected surface reflectance
The workflow for building 3D analysis-ready cubes from Sentinel-2 products involves the following steps:
- Query products using the EOPF STAC API for a given time range and spatial extent.
- Retrieve observations as cloud-optimized Zarr chunks via the xarray-eopf backend.
- Mosaic spatial tiles into single images per timestamp.
- Stack the mosaicked scenes along the temporal axis to form a 3D cube.
- Surface reflectance bands:
b01,b02,b03,b04,b05,b06,b07,b08,b8a,b09,b11,b12 - Classification/Quality layers (L2A only):
cld,scl,snw
Example: Sentinel-2 L2A
from xcube.core.store import new_data_store
store = new_data_store("eopf-zarr")
ds = store.open_data(
data_id="sentinel-2-l2a",
bbox=[9.7, 53.4, 10.3, 53.7],
time_range=["2025-05-01", "2025-05-07"],
spatial_res=10 / 111320, # meters to degrees (approx.)
crs="EPSG:4326",
variables=["b02", "b03", "b04", "scl"],
)Support for Sentinel-3 products will be added in an upcoming release.
The xcube-eopf package can be installed from PyPI (pip install xcube-eopf)
or conda-forge (conda install -c conda-forge xcube-eopf).
After installation, you are ready to go and use the "eopf-zarr" argument to initiate
a xcube EOPF data store.
from xcube.core.store import new_data_store
store = new_data_store("eopf-zarr")
ds = store.open_data(
data_id="sentinel-2-l2a",
bbox=[9.7, 53.4, 10.3, 53.7],
time_range=["2025-05-01", "2025-05-07"],
spatial_res=10 / 111320, # meters converted to degrees (approx.)
crs="EPSG:4326",
variables=["b02", "b03", "b04", "scl"],
)The recommended Python distribution for development is miniforge which includes conda, mamba, and their dependencies.
git clone https://github.com/EOPF-Sample-Service/xcube-eopf.git
cd xcube-eopf
mamba env create
mamba activate xcube-eopf
pip install -ve .mamba activate xcube-eopf
pip install -ve .
pytestBy default, this will run all unit tests. To run integration tests, use:
pytest integrationTo run tests and generate a coverage report, use:
pytest --cov xcube_eopf --cov-report html testsThe unit test suite uses pytest-recording
to mock STAC catalogs. During development an actual HTTP request is performed
to a STAC catalog and the responses are saved in cassettes/**.yaml files.
During testing, only the cassettes/**.yaml files are used without an actual
HTTP request. During development, to save the responses to cassettes/**.yaml, run
pytest -v -s --record-mode new_episodesNote that --record-mode new_episodes overwrites all cassettes. If the user only
wants to write cassettes which are not saved already, --record-mode once can be used.
pytest-recording supports all records modes given by VCR.py.
After recording the cassettes, testing can be performed as usual.
mamba activate xcube-eopf
pip install .[doc]mkdocs servemkdocs gh-deploy