4.2.3.1. Using the ESA CCI Toolbox with the xcube Viewer

The xcube viewer is an easy way to display gridded data. In this notebook, we show how the viewer can be started from a notebook and how cci datasets can be added to it.

To run this Notebook, make sure the ESA CCI Toolbox is setup correctly.

The viewer requires datasets. For this notebook, we will access them from the Zarr store and the regular store.

[1]:
from xcube.core.store import new_data_store

zarr_store = new_data_store('esa-cci-zarr')
cci_store = new_data_store('esa-cci')

If you want, you can execute the following lines to see which datasets are available. For now, this part is in a comment as we do not want to print all the datasets for reasons of readability.

[2]:
# zarr_store.list_data_ids()
[3]:
# cci_store.list_data_ids()

From the Zarr store, we pick a snow dataset.

[4]:
snow_ds = zarr_store.open_data('ESACCI-L3C_SNOW-SWE-1979-2020-fv2.0.zarr')
snow_ds
[4]:
<xarray.Dataset> Size: 823GB
Dimensions:   (lat: 1800, nv: 2, lon: 3600, time: 7934)
Coordinates:
  * lat       (lat) float64 14kB -89.95 -89.85 -89.75 ... 89.75 89.85 89.95
    lat_bnds  (lat, nv) float64 29kB dask.array<chunksize=(900, 2), meta=np.ndarray>
  * lon       (lon) float64 29kB -179.9 -179.8 -179.8 ... 179.7 179.8 179.9
    lon_bnds  (lon, nv) float64 58kB dask.array<chunksize=(900, 2), meta=np.ndarray>
  * time      (time) datetime64[ns] 63kB 1979-01-02 1979-01-04 ... 2020-05-24
Dimensions without coordinates: nv
Data variables:
    swe       (time, lat, lon) float64 411GB dask.array<chunksize=(10, 900, 900), meta=np.ndarray>
    swe_std   (time, lat, lon) float64 411GB dask.array<chunksize=(10, 900, 900), meta=np.ndarray>
Attributes: (12/43)
    Conventions:                CF-1.9
    cdm_data_type:              grid
    comment:                    The following auxiliary datasets are used for...
    creator_email:              kari.luojus@fmi.fi (Scientific and Production...
    creator_name:               Finnish Meteorological Institute
    creator_url:                www.fmi.fi
    ...                         ...
    time_coverage_duration:     P1D
    time_coverage_end:          20200524T000000Z
    time_coverage_resolution:   P1D
    time_coverage_start:        19790102T000000Z
    title:                      ESA CCI snow SWE product level L3C daily, Dyn...
    tracking_id:                25063fb5-47ad-424a-8f26-29bdf35efb78

From the cci store, we pick an aerosol dataset. However, let’s just use a subset here, to see how it will look in the viewer.

[5]:
x1 = -23.40  # degree
y1 = -40.40  # degree
x2 = 57.40  # degree
y2 = 40.40  # degree
bbox = (x1, y1, x2, y2)

aerosol_ds = cci_store.open_data(
    'esacci.AEROSOL.mon.L3.AAI.multi-sensor.multi-platform.MSAAI.1-7.r1',
    variable_names=['absorbing_aerosol_index'],
    bbox=bbox,
    time_range=['2005-01-01', '2005-12-31']
)
aerosol_ds
[5]:
<xarray.Dataset> Size: 308kB
Dimensions:                  (time: 12, lat: 80, lon: 80, bnds: 2)
Coordinates:
  * lat                      (lat) float32 320B -39.5 -38.5 -37.5 ... 38.5 39.5
  * lon                      (lon) float32 320B -22.5 -21.5 -20.5 ... 55.5 56.5
  * time                     (time) datetime64[ns] 96B 2005-01-16T12:00:00 .....
    time_bnds                (time, bnds) datetime64[ns] 192B dask.array<chunksize=(12, 2), meta=np.ndarray>
Dimensions without coordinates: bnds
Data variables:
    absorbing_aerosol_index  (time, lat, lon) float32 307kB dask.array<chunksize=(1, 80, 80), meta=np.ndarray>
Attributes:
    Conventions:             CF-1.7
    title:                   esacci.AEROSOL.mon.L3.AAI.multi-sensor.multi-pla...
    date_created:            2025-12-04T11:52:18.378325
    processing_level:        L3
    time_coverage_start:     2005-01-01T00:00:00
    time_coverage_end:       2006-01-01T00:00:00
    time_coverage_duration:  P365DT0H0M0S
    history:                 [{'program': 'xcube_cci.chunkstore.CciChunkStore...

Now that we have the datasets assembled, we can start the viewer. We import it from xcube like this:

[6]:
from xcube.webapi.viewer import Viewer
[7]:
viewer = Viewer()
404 GET /viewer/config/config.json (127.0.0.1): xcube viewer has not been been configured
404 GET /viewer/config/config.json (127.0.0.1) 11.21ms
501 GET /viewer/state?key=sentinel (127.0.0.1) 0.27ms
404 GET /viewer/ext/contributions (127.0.0.1) 0.32ms

Next, we add the datasets.

[8]:
viewer.add_dataset(snow_ds)
[8]:
'63622925-cb47-4e27-9346-0d0acc930130'
[9]:
viewer.add_dataset(aerosol_ds)
[9]:
'5c042aa5-b2de-47db-b7af-2051191afb16'

Now that the viewer is set up, we can ask for information about it. With the following command, we get the links for the server and the viewer. The server is responsible for serving the datasets. You may take the link and use it with any running viewer. However, it is directly plugged into the viewer instance which you can open from its link.

[10]:
viewer.info()
Server: http://localhost:8000
Viewer: http://localhost:8000/viewer/?serverUrl=http://localhost:8000

Alternatively, you can open the viewer in a notebook cell:

[11]:
viewer.show()
[11]: