Visualise data with xcube viewer
How to visualise data with xcube viewer in your workspace¶
A DeepESDL example notebook¶
This notebook demonstrates how to use the features of the xcube JupyterLab integration.
The notebook demonstrates three scenarios how xcube Viewer is utilized in JupyterLab.
In particular, we open xcube Viewer for any xarray.Dataset
instances
- persisted in deepesdl public s3 storage (saved datasets)
- opened or otherwise created in this Notebook (in-memory datasets)
- using a configuration file for customising stlyes.
To explore the xcube viewer functionalities, please checkout the documentation: https://xcube.readthedocs.io/en/latest/viewer.html#functionality
Please, also refer to the DeepESDL documentation and visit the platform's website for further information!
Brockmann Consult, 2025
This notebook runs with the python environment users-deepesdl-xcube-1.9.1
, please checkout the documentation for help on changing the environment.
For example reasons we will access a deepesdl public data cube and visualize it in the jupyter lab using xcube viewer
from xcube.core.store import new_data_store
store = new_data_store("s3", root="deep-esdl-public", storage_options=dict(anon=True))
store.list_data_ids()
['LC-1x2025x2025-2.0.0.levels', 'LC-1x2160x2160-1.0.0.levels', 'SMOS-L2C-OS-20230101-20231231-1W-res0-1x1000x1000.levels', 'SMOS-L2C-OS-20230101-20231231-1W-res0-53x120x120.zarr', 'SMOS-L2C-OS-20230101-20231231-1W-res0.zarr', 'SMOS-L2C-SM-20230101-20231231-1W-res0-1x1000x1000.levels', 'SMOS-L2C-SM-20230101-20231231-1W-res0-53x120x120.zarr', 'SMOS-L2C-SM-20230101-20231231-1W-res0.zarr', 'SMOS-freezethaw-1x720x720-1.0.1.zarr', 'SMOS-freezethaw-4267x10x10-1.0.1.zarr', 'SeasFireCube-8D-0.25deg-1x720x1440-3.0.0.zarr', 'SeasFireCube-8D-0.25deg-966x180x360-3.0.0.zarr', 'SeasFireCube_v3.zarr', 'black-sea-1x1024x1024.levels', 'black-sea-256x128x128.zarr', 'esa-cci-permafrost-1x1151x1641-0.0.2.levels', 'esa-cci-permafrost-1x1151x1641-1.0.0.zarr', 'esdc-8d-0.25deg-1x720x1440-3.0.1.zarr', 'esdc-8d-0.25deg-256x128x128-3.0.1.zarr', 'extrAIM-merged-cube-1x86x179.zarr', 'hydrology-1D-0.009deg-100x60x60-3.0.2.zarr', 'hydrology-1D-0.009deg-1418x70x76-2.0.0.zarr', 'hydrology-1D-0.009deg-1x1102x2415-2.0.0.levels', 'hydrology-1D-0.009deg-1x1102x966-3.0.2.levels', 'ocean-1M-9km-1x1080x1080-1.4.0.levels', 'ocean-1M-9km-64x256x256-1.4.0.zarr', 'polar-100m-1x2048x2048-1.0.1.zarr']
We use the xcube datastore framework here to open the dataset, but it could also be opened by other means, e.g., xr.open_dataset()
, provided it has variables with dimensions ["time", "y", "x"] or ["y", "x"].
Let's visualize the Earth System Data Cube:
dataset = store.open_data("esdc-8d-0.25deg-1x720x1440-3.0.1.zarr")
dataset
<xarray.Dataset> Size: 353GB Dimensions: (time: 1978, lat: 720, lon: 1440) Coordinates: * lat (lat) float64 6kB -89.88 -89.62 ... 89.88 * lon (lon) float64 12kB -179.9 ... 179.9 * time (time) datetime64[ns] 16kB 1979-01-05 ... Data variables: (12/42) aerosol_optical_thickness_550 (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> air_temperature_2m (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> bare_soil_evaporation (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> burnt_area (time, lat, lon) float64 16GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> cot (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> cth (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> ... ... sif_rtsif (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> sm (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> snow_sublimation (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> surface_moisture (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> terrestrial_ecosystem_respiration (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> transpiration (time, lat, lon) float32 8GB dask.array<chunksize=(1, 720, 1440), meta=np.ndarray> Attributes: (12/23) Conventions: CF-1.9 acknowledgment: All ESDC data providers are acknowledged insi... contributor_name: ['University of Leipzig', 'Max Planck Institu... contributor_url: ['https://www.uni-leipzig.de/', 'https://www.... creator_name: ['University of Leipzig', 'Brockmann Consult ... creator_url: ['https://www.uni-leipzig.de/', 'https://www.... ... ... publisher_url: https://www.earthsystemdatalab.net/ time_coverage_end: 2021-12-31T00:00:00.000000000 time_coverage_start: 1979-01-05T00:00:00.000000000 time_period: 8D time_period_reported_day: 5.0 title: Earth System Data Cube (ESDC) v3.0.1
from xcube.webapi.viewer import Viewer
Scenario 1: Open xcube Viewer for a dataset instances persisted from a certain source (saved datasets).
For the functionalities of xcube viewer please head over to the documentation: https://xcube.readthedocs.io/en/latest/viewer.html#functionality
viewer = Viewer()
viewer.add_dataset(dataset)
'65afdabd-d52b-4b06-921b-5182cd571d74'
You can click on the viewer link to open xcube Viewer in a new browser tab:
viewer.info()
Server: https://deep.earthsystemdatalab.net/user/alicebalfanz/proxy/8001 Viewer: https://deep.earthsystemdatalab.net/user/alicebalfanz/proxy/8001/viewer/?serverUrl=https://deep.earthsystemdatalab.net/user/alicebalfanz/proxy/8001
You can also open xcube Viewer inlined here:
viewer.show()
To stop the server and viewer:
viewer.stop_server()
INFO:xcube:Stopping service...
Scenario 2: Open xcube Viewer for a dataset instances opened or otherwise created in this Notebook (in-memory datasets).
Below, let's fetch a dataset from CDS on the fly, without persisting it - for more details about xcube CDS datastore and how to get CDS credentials please checkout the example notebook in xcube-datastores GENERATE C3S CDS CUBES. Be aware of performance loss, so in case you plan to use a dataset a lot for analysis or visualisation, please persist it into the team s3 storage. The public cubes provided within DeepESDL are already persisted in S3, so you should not duplicate them in your team storage.
import os
os.environ['CDSAPI_URL'] = 'https://cds.climate.copernicus.eu/api'
os.environ['CDSAPI_KEY'] = '[PERSONAL-ACCESS-TOKEN]'
cds_store = new_data_store('cds')
bbox=[-5, 45, 35, 65]
cds_dataset = cds_store.open_data('reanalysis-era5-single-levels-monthly-means:monthly_averaged_reanalysis',
variable_names=['2m_temperature'],
bbox=bbox,
spatial_res=0.25,
time_range=['2010-01-01', '2010-12-31'])
cds_dataset
xcube-cds version 0.9.3 2024-09-18 08:40:41,936 INFO Request ID is 6a55691a-15bb-4b7d-81dc-fedb6febd390 INFO:cads_api_client.processing:Request ID is 6a55691a-15bb-4b7d-81dc-fedb6febd390 2024-09-18 08:40:41,973 INFO status has been updated to accepted INFO:cads_api_client.processing:status has been updated to accepted 2024-09-18 08:40:43,517 INFO status has been updated to running INFO:cads_api_client.processing:status has been updated to running 2024-09-18 08:40:45,804 INFO status has been updated to successful INFO:cads_api_client.processing:status has been updated to successful
9830c36a333f3eab454e3817a76610df.nc: 0%| | 0.00/322k [00:00<?, ?B/s]
<xarray.Dataset> Size: 617kB Dimensions: (lat: 80, lon: 160, time: 12) Coordinates: number int64 8B ... * lat (lat) float64 640B 64.88 64.62 64.38 64.12 ... 45.62 45.38 45.12 * lon (lon) float64 1kB -4.875 -4.625 -4.375 -4.125 ... 34.38 34.62 34.88 expver (time) <U4 192B ... * time (time) datetime64[ns] 96B 2010-01-01 2010-02-01 ... 2010-12-01 Data variables: t2m (time, lat, lon) float32 614kB ... Attributes: GRIB_centre: ecmf GRIB_centreDescription: European Centre for Medium-Range Weather Forecasts GRIB_subCentre: 0 Conventions: CF-1.7 institution: European Centre for Medium-Range Weather Forecasts history: 2024-09-18T08:40 GRIB to CDM+CF via cfgrib-0.9.1...
cds_dataset.attrs["title"] = "ERA5 2m Temperature"
Let's set some attributes of the variable, so the colormapping does not fall back on the default
cds_dataset.t2m.attrs["color_value_min"] = 270
cds_dataset.t2m.attrs["color_value_max"] = 310
cds_dataset.t2m.attrs["color_bar_name"] = "plasma"
viewer = Viewer()
viewer.add_dataset(dataset)
viewer.add_dataset(cds_dataset)
'f6015205-89c6-49d5-a0c4-d7c90694d5b4'
You can click on the viewer link to open xcube Viewer in a new browser tab:
viewer.info()
Server: https://deep.earthsystemdatalab.net/user/alicebalfanz/proxy/8006 Viewer: https://deep.earthsystemdatalab.net/user/alicebalfanz/proxy/8006/viewer/?serverUrl=https://deep.earthsystemdatalab.net/user/alicebalfanz/proxy/8006
You can also open xcube Viewer inlined here:
viewer.show()
To stop the server and viewer:
viewer.stop_server()
Scenario 3: Use custom server configuration to start server and pass it to the viewer constructor. In this example, we have create a local file with the configuration and load it as a dictionary and pass it to the viewer.
The configuration file is pointing to your team storage as input source. If you don't have anything stored in your team S3 storage, the viewer will not be able to display any data. Please check other example notebooks and create some sample datasets in your team storage to visualize the content.
The custom configuration allows you to predefined your value ranges, the colormaps that should be used as well as which bands should be used to create an RGB image, then the RGB switch in the viewer will display the RGB image.
If you do not have a server-config.yaml file in your directory, please create one with the following content:
DataStores:
- Identifier: deep-esdl-team-storage
StoreId: s3
StoreParams:
root: $S3_USER_STORAGE_BUCKET
storage_options:
anon: false
key: $S3_USER_STORAGE_KEY
secret: $S3_USER_STORAGE_SECRET
Datasets:
- Path: "*.zarr"
Style: default
# ChunkCacheSize: 1G
Styles:
- Identifier: default
ColorMappings:
analysed_sst:
ColorBar: plasma
ValueRange: [270, 310]
## if you have bands that can create an RGB image, you can specify them as below.
# rgb:
# Red:
# Variable: B04
# ValueRange: [0., 0.25]
# Green:
# Variable: B03
# ValueRange: [0., 0.25]
# Blue:
# Variable: B02
# ValueRange: [0., 0.25]
For all possible settings within the server configuration file, please checkout the documentation: https://xcube.readthedocs.io/en/latest/cli/xcube_serve.html#configuration-file
from xcube.util.config import load_configs
viewer = Viewer(server_config=load_configs("server-config.yaml"))
viewer.show()
To stop the server and viewer:
viewer.stop_server()