[](https://github.com/EOPF-Sample-Service/xcube-eopf/actions)
[](https://codecov.io/gh/EOPF-Sample-Service/xcube-eopf)
[](https://pypi.org/project/xcube-eopf/)
[](https://anaconda.org/conda-forge/xcube-eopf)
[](https://github.com/charliermarsh/ruff)
[](https://anaconda.org/conda-forge/xcube-eopf)
# xcube-eopf
`xcube-eopf` is a Python package and [xcube plugin](https://xcube.readthedocs.io/en/latest/plugins.html) that adds a [data store](https://xcube.readthedocs.io/en/latest/api.html#data-store-framework)
named `eopf-zarr` to xcube. The data store is used to access ESA EOPF data products as an
analysis-ready datacube (ARDC).
## Features
> **IMPORTANT**
> `xcube-eopf` is 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](guide.md).
Currently, support is focused on **Sentinel-2** products.
### Sentinel-1
Support for Sentinel-1 will be added in an upcoming release.
### Sentinel-2
The current implementation supports two Sentinel-2 product levels, available as
`data_id` values:
- `sentinel-2-l1c`: Level-1C top-of-atmosphere reflectance
- `sentinel-2-l2a`: Level-2A atmospherically corrected surface reflectance
#### Cube Generation Workflow
The workflow for building 3D analysis-ready cubes from Sentinel-2 products involves
the following steps:
1. **Query** products using the [EOPF STAC API](https://stac.browser.user.eopf.eodc.eu/) for a given time range and
spatial extent.
2. **Retrieve** observations as cloud-optimized Zarr chunks via the
[xarray-eopf backend](https://eopf-sample-service.github.io/xarray-eopf/).
3. **Mosaic** spatial tiles into single images per timestamp.
4. **Stack** the mosaicked scenes along the temporal axis to form a 3D cube.
#### Supported Variables
- **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**
```python
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"],
)
```
### Sentinel-3
Support for Sentinel-3 products will be added in an upcoming release.
## Usage
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.
```python
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"],
)
```
## Development
### Setting up a development environment
The recommended Python distribution for development is
[miniforge](https://conda-forge.org/download/) which includes
conda, mamba, and their dependencies.
```shell
git clone https://github.com/EOPF-Sample-Service/xcube-eopf.git
cd xcube-eopf
mamba env create
mamba activate xcube-eopf
pip install -ve .
```
### Install the library locally and test
```shell
mamba activate xcube-eopf
pip install -ve .
pytest
```
By default, this will run all unit tests. To run integration tests, use:
```shell
pytest integration
```
To run tests and generate a coverage report, use:
```shell
pytest --cov xcube_eopf --cov-report html tests
```
### Some notes on the strategy of unit-testing
The unit test suite uses [pytest-recording](https://pypi.org/project/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
```bash
pytest -v -s --record-mode new_episodes
```
Note 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](https://pypi.org/project/pytest-recording/) supports all records modes given by [VCR.py](https://vcrpy.readthedocs.io/en/latest/usage.html#record-modes).
After recording the cassettes, testing can be performed as usual.
### Setting up a documentation environment
```shell
mamba activate xcube-eopf
pip install .[doc]
```
### Testing documentation changes
```shell
mkdocs serve
```
### Deploying documentation changes
```shell
mkdocs gh-deploy
```
Raw data
{
"_id": null,
"home_page": null,
"name": "xcube-eopf",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "copernicus, esa, eopf, sentinel, xarray, zarr",
"author": "Konstantin Ntokas (Brockmann Consult GmbH), Norman Fomferra (Brockmann Consult GmbH)",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/b3/09/f93786eaf34704d54d8e371f5579cecc558c8fd92c7453f0b318edef65e7/xcube_eopf-0.2.0.tar.gz",
"platform": null,
"description": "[](https://github.com/EOPF-Sample-Service/xcube-eopf/actions)\n[](https://codecov.io/gh/EOPF-Sample-Service/xcube-eopf)\n[](https://pypi.org/project/xcube-eopf/)\n[](https://anaconda.org/conda-forge/xcube-eopf)\n[](https://github.com/charliermarsh/ruff)\n[](https://anaconda.org/conda-forge/xcube-eopf)\n\n\n# xcube-eopf\n\n`xcube-eopf` is a Python package and [xcube plugin](https://xcube.readthedocs.io/en/latest/plugins.html) that adds a [data store](https://xcube.readthedocs.io/en/latest/api.html#data-store-framework)\nnamed `eopf-zarr` to xcube. The data store is used to access ESA EOPF data products as an \nanalysis-ready datacube (ARDC).\n\n## Features\n\n> **IMPORTANT** \n> `xcube-eopf` is currently under active development. \n> Some features may be partially implemented or still in progress.\n\nThe EOPF xcube data store is designed to provide analysis-ready data cubes from the \nEOPF Sentinel Zarr samples for Sentinel-1, Sentinel-2, and Sentinel-3 missions. The\nmain features are summarized below. A more in depth documentation is given in the \n[User Guide](guide.md). \n\nCurrently, support is focused on **Sentinel-2** products.\n\n\n### Sentinel-1\n\nSupport for Sentinel-1 will be added in an upcoming release.\n\n\n### Sentinel-2\n\nThe current implementation supports two Sentinel-2 product levels, available as \n`data_id` values:\n\n- `sentinel-2-l1c`: Level-1C top-of-atmosphere reflectance\n- `sentinel-2-l2a`: Level-2A atmospherically corrected surface reflectance\n\n#### Cube Generation Workflow\n\nThe workflow for building 3D analysis-ready cubes from Sentinel-2 products involves \nthe following steps:\n\n1. **Query** products using the [EOPF STAC API](https://stac.browser.user.eopf.eodc.eu/) for a given time range and \n spatial extent.\n2. **Retrieve** observations as cloud-optimized Zarr chunks via the \n [xarray-eopf backend](https://eopf-sample-service.github.io/xarray-eopf/).\n3. **Mosaic** spatial tiles into single images per timestamp.\n4. **Stack** the mosaicked scenes along the temporal axis to form a 3D cube.\n\n#### Supported Variables\n\n- **Surface reflectance bands**: \n `b01`, `b02`, `b03`, `b04`, `b05`, `b06`, `b07`, `b08`, `b8a`, `b09`, `b11`, `b12`\n- **Classification/Quality layers** (L2A only): \n `cld`, `scl`, `snw`\n\n**Example: Sentinel-2 L2A**\n```python\nfrom xcube.core.store import new_data_store\n\nstore = new_data_store(\"eopf-zarr\")\nds = store.open_data(\n data_id=\"sentinel-2-l2a\",\n bbox=[9.7, 53.4, 10.3, 53.7],\n time_range=[\"2025-05-01\", \"2025-05-07\"],\n spatial_res=10 / 111320, # meters to degrees (approx.)\n crs=\"EPSG:4326\",\n variables=[\"b02\", \"b03\", \"b04\", \"scl\"],\n)\n```\n\n### Sentinel-3\n\nSupport for Sentinel-3 products will be added in an upcoming release.\n\n\n\n## Usage\n\nThe `xcube-eopf` package can be installed from PyPI (`pip install xcube-eopf`)\nor conda-forge (`conda install -c conda-forge xcube-eopf`).\nAfter installation, you are ready to go and use the `\"eopf-zarr\"` argument to initiate \na xcube EOPF data store.\n\n```python\nfrom xcube.core.store import new_data_store\n\nstore = new_data_store(\"eopf-zarr\")\nds = store.open_data(\n data_id=\"sentinel-2-l2a\",\n bbox=[9.7, 53.4, 10.3, 53.7],\n time_range=[\"2025-05-01\", \"2025-05-07\"],\n spatial_res=10 / 111320, # meters converted to degrees (approx.)\n crs=\"EPSG:4326\",\n variables=[\"b02\", \"b03\", \"b04\", \"scl\"],\n)\n```\n\n## Development\n\n### Setting up a development environment\n\nThe recommended Python distribution for development is \n[miniforge](https://conda-forge.org/download/) which includes \nconda, mamba, and their dependencies.\n\n```shell\ngit clone https://github.com/EOPF-Sample-Service/xcube-eopf.git\ncd xcube-eopf\nmamba env create\nmamba activate xcube-eopf\npip install -ve .\n```\n\n### Install the library locally and test\n\n```shell\nmamba activate xcube-eopf\npip install -ve .\npytest\n```\nBy default, this will run all unit tests. To run integration tests, use: \n\n```shell\npytest integration\n```\n\nTo run tests and generate a coverage report, use:\n\n```shell\npytest --cov xcube_eopf --cov-report html tests\n```\n\n### Some notes on the strategy of unit-testing\n\nThe unit test suite uses [pytest-recording](https://pypi.org/project/pytest-recording/)\nto mock STAC catalogs. During development an actual HTTP request is performed\nto a STAC catalog and the responses are saved in `cassettes/**.yaml` files.\nDuring testing, only the `cassettes/**.yaml` files are used without an actual\nHTTP request. During development, to save the responses to `cassettes/**.yaml`, run\n\n```bash\npytest -v -s --record-mode new_episodes\n```\nNote that `--record-mode new_episodes` overwrites all cassettes. If the user only\nwants to write cassettes which are not saved already, `--record-mode once` can be used.\n[pytest-recording](https://pypi.org/project/pytest-recording/) supports all records modes given by [VCR.py](https://vcrpy.readthedocs.io/en/latest/usage.html#record-modes).\nAfter recording the cassettes, testing can be performed as usual.\n\n\n### Setting up a documentation environment\n\n```shell\nmamba activate xcube-eopf\npip install .[doc]\n```\n\n### Testing documentation changes\n\n```shell\nmkdocs serve\n```\n\n### Deploying documentation changes\n\n```shell\nmkdocs gh-deploy\n```\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "xcube datastore for accessing datasets of ESA EOPF data products.",
"version": "0.2.0",
"project_urls": {
"Changelog": "https://github.com/EOPF-Sample-Service/xcube-eopf/blob/main/CHANGES.md",
"Documentation": "https://eopf-sample-service.github.io/xcube-eopf",
"Issues": "https://github.com/EOPF-Sample-Service/xcube-eopf/issues",
"Repository": "https://github.com/EOPF-Sample-Service/xcube-eopf"
},
"split_keywords": [
"copernicus",
" esa",
" eopf",
" sentinel",
" xarray",
" zarr"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "fbf6fdcc68337fdf3f65962eeca9dc93dc454546388bf76e0d9517155464a294",
"md5": "fd1955ee3415fca4bb9076faa0766d70",
"sha256": "9fffa9ba3ffd4dce70b71a6e42a2c41e70d71cf71fb3e1f78f287b3ff10e8164"
},
"downloads": -1,
"filename": "xcube_eopf-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fd1955ee3415fca4bb9076faa0766d70",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 28751,
"upload_time": "2025-08-21T14:40:12",
"upload_time_iso_8601": "2025-08-21T14:40:12.775535Z",
"url": "https://files.pythonhosted.org/packages/fb/f6/fdcc68337fdf3f65962eeca9dc93dc454546388bf76e0d9517155464a294/xcube_eopf-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "b309f93786eaf34704d54d8e371f5579cecc558c8fd92c7453f0b318edef65e7",
"md5": "9fae3b73c9d1bb587d6c7cdf6bee9a57",
"sha256": "3ceeb4c9d516a27e9741eb7a2dcf0b86fea1d446fcdfac47cbdbaaa8ebe03e88"
},
"downloads": -1,
"filename": "xcube_eopf-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "9fae3b73c9d1bb587d6c7cdf6bee9a57",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 29335,
"upload_time": "2025-08-21T14:40:14",
"upload_time_iso_8601": "2025-08-21T14:40:14.001498Z",
"url": "https://files.pythonhosted.org/packages/b3/09/f93786eaf34704d54d8e371f5579cecc558c8fd92c7453f0b318edef65e7/xcube_eopf-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-21 14:40:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "EOPF-Sample-Service",
"github_project": "xcube-eopf",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "xcube-eopf"
}