Working with Sentinel-3 in xarray EOPF backend
Direct access to analysis-ready data cubes

Table of Contents¶
Run this notebook interactively with all dependencies pre-installed
Introduction¶
xarray-eopf is a Python package that extends xarray with a custom backend called "eopf-zarr"
. This backend enables seamless access to ESA EOPF data products stored in the Zarr format, presenting them as analysis-ready data structures.
This notebook demonstrates how to use the xarray-eopf backend to explore and analyze Sentinel-3 EOPF Zarr datasets. It highlights the key features currently supported by the backend.
- 🐙 GitHub: EOPF Sample Service – xarray-eopf
- ❗ Issue Tracker: Submit or view issues
- 📘 Documentation: xarray-eopf Docs
Install the xarray-eopf Backend¶
The backend is implemented as an xarray plugin and can be installed using either pip
or conda/mamba
from the conda-forge channel.
- 📦 PyPI: xarray-eopf on PyPI
pip install xarray-eopf
- 🐍 Conda (conda-forge): xarray-eopf on Anaconda
conda install -c conda-forge xarray-eopf
You can also use Mamba as a faster alternative to Conda: mamba install -c conda-forge xarray-eopf
⚠️ Please ensure you install version 0.2.0 or newer, as this release introduces important new features for Sentinel-3 products.
Import Modules¶
The xarray-eopf
backend is implemented as a plugin for xarray
. Once installed, it registers automatically and requires no additional import. You can simply import xarray
as usual:
import pystac_client
import xarray as xr
Main Features of the xarray-eopf Backend¶
The xarray-eopf backend for EOPF data products can be selecterd by setting engine="eopf-zarr"
in xarray.open_dataset(..)
and xarray.open_datatree(..)
method. It supports two modes of operation:
- Analysis Mode (default)
- Native Mode
Native Mode¶
Represents EOPF products without modification using xarray
’s DataTree
and Dataset
.
open_dataset(..)
— Returns a flattened version of the data treeopen_datatree(..)
— Returns the fullDataTree
, same asxr.open_datatree(.., engine="zarr")
Analysis Mode¶
Provides an analysis-ready, resampled view of the data (currently for Sentinel-2 and Sentinel-3).
open_dataset(..)
— Loads Sentinel-2 products in a harmonized, analysis-ready formatopen_datatree(..)
— Not implemented in this mode (NotImplementedError
)
📚 More info: xarray-eopf Guide
Open the Product in Native Mode¶
Sentinel-3 OLCI L1 EFR¶
We begin with a simple example by accessing a Sentinel-3 OLCI L1 EFR product in native mode. To obtain the product URL, you can use the STAC Browser to locate a tile and retrieve the URL from the “EOPF Product” asset, or you can search programmatically using the STAC API to search of a respective tile, as shown below.
catalog = pystac_client.Client.open("https://stac.core.eopf.eodc.eu")
items = list(
catalog.search(
collections=["sentinel-3-olci-l1-efr"],
bbox=[14.8, 37.45, 15.3, 37.85],
datetime=["2025-08-25", "2025-08-30"],
).items()
)
items
[<Item id=S3A_OL_1_EFR____20250830T214425_20250830T214725_20250830T233501_0179_130_029_2340_PS1_O_NR_004>,
<Item id=S3A_OL_1_EFR____20250830T214425_20250830T214725_20250831T224749_0179_130_029_2340_PS1_O_NT_004>,
<Item id=S3B_OL_1_EFR____20250830T091856_20250830T092156_20250830T112205_0179_110_264_2340_ESA_O_NR_004>,
<Item id=S3B_OL_1_EFR____20250830T091856_20250830T092156_20250831T093652_0179_110_264_2340_ESA_O_NT_004>,
<Item id=S3A_OL_1_EFR____20250829T221037_20250829T221337_20250829T235839_0179_130_015_2340_PS1_O_NR_004>,
<Item id=S3A_OL_1_EFR____20250829T221037_20250829T221337_20250830T230823_0179_130_015_2340_PS1_O_NT_004>,
<Item id=S3A_OL_1_EFR____20250829T084243_20250829T084543_20250829T103526_0179_130_007_2340_PS1_O_NR_004>,
<Item id=S3A_OL_1_EFR____20250829T084243_20250829T084543_20250830T094042_0179_130_007_2340_PS1_O_NT_004>,
<Item id=S3A_OL_1_EFR____20250828T223648_20250828T223948_20250829T002602_0180_130_001_2340_PS1_O_NR_004>,
<Item id=S3A_OL_1_EFR____20250828T223648_20250828T223948_20250829T233617_0179_130_001_2340_PS1_O_NT_004>,
<Item id=S3B_OL_1_EFR____20250828T215812_20250828T220112_20250828T235445_0179_110_243_2340_ESA_O_NR_004>,
<Item id=S3B_OL_1_EFR____20250828T215812_20250828T220112_20250829T223042_0179_110_243_2340_ESA_O_NT_004>,
<Item id=S3A_OL_1_EFR____20250828T090854_20250828T091154_20250828T110316_0179_129_378_2340_PS1_O_NR_004>,
<Item id=S3A_OL_1_EFR____20250828T090854_20250828T091154_20250829T101239_0179_129_378_2340_PS1_O_NT_004>,
<Item id=S3B_OL_1_EFR____20250827T222423_20250827T222723_20250828T232121_0180_110_229_2340_ESA_O_NT_004>,
<Item id=S3A_OL_1_EFR____20250827T093505_20250827T093805_20250828T103639_0179_129_364_2340_PS1_O_NT_004>,
<Item id=S3B_OL_1_EFR____20250827T085629_20250827T085929_20250828T094631_0180_110_221_2340_ESA_O_NT_004>,
<Item id=S3A_OL_1_EFR____20250825T221422_20250825T221722_20250826T000558_0179_129_343_2340_PS1_O_NR_004>,
<Item id=S3A_OL_1_EFR____20250825T084628_20250825T084928_20250826T094526_0179_129_335_2340_PS1_O_NT_004>,
<Item id=S3A_OL_1_EFR____20250825T084628_20250825T084928_20250825T104112_0179_129_335_2340_PS1_O_NR_004>]
Next we can use the href and open parameters stored in the STAC item to open the data tree using xr.open_datatree
.
item = items[-4]
dt = xr.open_datatree(
item.assets["product"].href,
**item.assets["product"].extra_fields["xarray:open_datatree_kwargs"],
)
dt
We can access the spectral data by navigating through the data tree and visualize the data with the usual xarray plotting routines.
ds = dt.measurements.to_dataset()
ds
⚠️ Note: The dataset is loaded lazily.
Actual data access/download is triggered when the data is written to disk or visualized.
%%time
ds.oa02_radiance[::4, ::4].plot(robust=True)
CPU times: user 6.69 s, sys: 2.53 s, total: 9.22 s
Wall time: 25.2 s

We can also open the product with xr.open_dataset
, which returns a flattened DataTree represented as an xr.Dataset
.
ds = xr.open_dataset(
item.assets["product"].href,
**item.assets["product"].extra_fields["xarray:open_datatree_kwargs"],
)
ds
We can filter the returned variables using the variables
keyword argument, which accepts a string, an iterable of names, or a regular expression (regex) pattern.
ds = xr.open_dataset(
item.assets["product"].href,
**item.assets["product"].extra_fields["xarray:open_datatree_kwargs"],
variables="measurements*",
)
ds
Following the previous steps, we can now select a data variable and display a spectral band as an example.
%%time
ds.measurements_oa02_radiance[::4, ::4].plot(robust=True)
CPU times: user 5.01 s, sys: 1.79 s, total: 6.8 s
Wall time: 25.5 s

Open the Product in Analysis Mode¶
Analysis mode is currently available for Sentinel-2 and Sentinel-3 products. Support for Sentinel-1 will be added in future releases.
Sentinel-3 products are provided on their native grid mapping, where each pixel is defined by a latitude/longitude pair, forming a 2D irregular grid.
The analysis mode applies the rectification algorithm in xcube-resampling to transform the irregular dataset into a regular grid with 1D latitude/longitude coordinates.
Suported Products:
Analysis mode for Sentinel-3¶
The analysis mode for Sentinel-3 has the following key properties:
- Default mode when using the
"eopf-zarr"
backend. - Spatial resolution options: Users can choose freely a resolution in degree via the parameter
resolution
. If not given, the avaragend resolution of the 2d irregular grid is taken. - Upsampling / interpolation: Performed via 2D interpolation controlled by the
interp_methods
argument and propagated to xcube_resampling .resample _in _space - Downsampling / Aggregation: Performed through aggregation methods governed by the
agg_methods
argument and propagated to xcube_resampling .resample _in _space - Variable selection: Specific variables can be selected via the
variables
argument, which accepts a variable name, a regex pattern, or an iterable of either.
More details are available in the documentation.
%%time
ds = xr.open_dataset(
item.assets["product"].href,
engine="eopf-zarr",
chunks={},
resolution=400 / 111320, # convert meter into degree approx.
interp_methods="nearest",
)
ds
%%time
ds.oa02_radiance[::4, ::4].plot(robust=True)
CPU times: user 56 s, sys: 21.2 s, total: 1min 17s
Wall time: 4min 4s

Conclusion¶
This notebook showcases the new functionalities of the xarray-eopf backend for accessing Sentinel-3 EOPF Zarr products.
It enables seamless access using familiar Xarray methods such as xr.open_dataset
and xr.open_datatree
by specifying engine="eopf-zarr"
.
The key takeaways are summarized below:
Operation Modes¶
op_mode="native"
Represents EOPF products without modification using Xarray’sDataTree
andDataset
structures.
For example, opening a dataset withxr.open_dataset(path, engine="eopf-zarr", op_mode="native")
returns the data tree as a flattenedxr.Dataset
.op_mode="analysis"
Provides an analysis-ready, resampled view of Sentinel-3 data.
It applies the rectification algorithm in xcube-resampling to transform the irregular dataset into a regular grid with 1D latitude and longitude coordinates.
Future Development Steps¶
- Extend analysis mode support to the remaining Sentinel-3 products once data becomes available.
- Add analysis mode support for Sentinel-1 products.
