Skip to article frontmatterSkip to article content
earth and related environmental sciences

Working with Sentinel-3 in xarray EOPF backend

Direct access to analysis-ready data cubes

Brockmann Consult GmbH
ESA EOPF Zarr Logo

🚀 Launch in JupyterHub

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.


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.

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 tree
  • open_datatree(..) — Returns the full DataTree, same as xr.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 format
  • open_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
Loading...

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
Loading...

⚠️ 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
<Figure size 640x480 with 2 Axes>

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
Loading...

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
Loading...

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
<Figure size 640x480 with 2 Axes>

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
Loading...
%%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
<Figure size 640x480 with 2 Axes>

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’s DataTree and Dataset structures.
    For example, opening a dataset with xr.open_dataset(path, engine="eopf-zarr", op_mode="native") returns the data tree as a flattened xr.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.