API and Streaming Capabilities

API and Streaming Capabilities#

If necessary, install the DTCG API with:

!pip install 'dtcg[jupyter] @ git+https://github.com/DTC-Glaciers/dtcg'

In a cell below.

from dtcg.api.external import call
import dtcg.integration.oggm_bindings as dtcg_oggm
import dtcg.interface.plotting as dtcg_plotting
import holoviews as hv
import xarray as xr
from dtcg import DEFAULT_L2_DATACUBE_URL

Here we showcase some of DTCG’s more experimental infrastructural capabilities, which address more long-term considerations for integration with DESP.

Streaming Datacubes#

DTCG simplifies user interactions and saves on bandwidth costs by streaming data. Streaming a datacube just requires the RGI-ID of the glacier:

streamer = call.StreamDatacube(server=DEFAULT_L2_DATACUBE_URL)
datacube = streamer.stream_datacube(glacier="RGI60-06.00372")
datacube
<xarray.DataTree>
Group: /
├── Group: /L1
│       Dimensions:                               (y: 194, x: 208, t: 177, t_wgms: 0)
│       Coordinates:
│         * y                                     (y) float32 776B 7.118e+06 ... 7.11...
│         * x                                     (x) float32 832B 4.443e+05 ... 4.48...
│         * t                                     (t) datetime64[ns] 1kB 2011-01-15 ....
│         * t_wgms                                (t_wgms) int64 0B 
│       Data variables: (12/19)
│           consensus_ice_thickness               (y, x) float32 161kB dask.array<chunksize=(194, 208), meta=np.ndarray>
│           eolis_gridded_elevation_change        (t, y, x) float64 57MB dask.array<chunksize=(177, 60, 60), meta=np.ndarray>
│           eolis_gridded_elevation_change_sigma  (t, y, x) float64 57MB dask.array<chunksize=(177, 60, 60), meta=np.ndarray>
│           glacier_ext                           (y, x) int8 40kB dask.array<chunksize=(194, 208), meta=np.ndarray>
│           glacier_mask                          (y, x) int8 40kB dask.array<chunksize=(194, 208), meta=np.ndarray>
│           hugonnet_dhdt                         (y, x) float32 161kB dask.array<chunksize=(194, 208), meta=np.ndarray>
│           ...                                    ...
│           spatial_ref                           int64 8B ...
│           topo                                  (y, x) float32 161kB dask.array<chunksize=(194, 208), meta=np.ndarray>
│           topo_smoothed                         (y, x) float32 161kB dask.array<chunksize=(194, 208), meta=np.ndarray>
│           topo_valid_mask                       (y, x) int8 40kB dask.array<chunksize=(194, 208), meta=np.ndarray>
│           wgms_mb                               (t_wgms) float64 0B dask.array<chunksize=(0,), meta=np.ndarray>
│           wgms_mb_unc                           (t_wgms) float64 0B dask.array<chunksize=(0,), meta=np.ndarray>
│       Attributes:
│           Conventions:         CF-1.12
│           comment:             The DTC Glaciers project is developed under the Euro...
│           date_created:        2026-01-11T14:01:19.084593
│           RGI-ID:              RGI60-06.00372
│           glacier_attributes:  {'rgi_id': 'RGI60-06.00372', 'glims_id': 'G343896E64...
│           title:               Datacube of glacier-domain variables.
│           summary:             Resampled glacier-domain variables from multiple sou...
├── Group: /L2_Daily_Hugonnet_2000_2020
│   ├── Group: /L2_Daily_Hugonnet_2000_2020/annual_hydro
│   │       Dimensions:                       (member: 8, time: 27, rgi_id: 1, month_2d: 12)
│   │       Coordinates:
│   │         * member                        (member) <U7 224B 'Control' '0.05' ... '0.95'
│   │         * time                          (time) int64 216B 2000 2001 2002 ... 2025 2026
│   │           calendar_month                (time) int64 216B dask.array<chunksize=(27,), meta=np.ndarray>
│   │           calendar_year                 (time) int64 216B dask.array<chunksize=(27,), meta=np.ndarray>
│   │           hydro_month                   (time) int64 216B dask.array<chunksize=(27,), meta=np.ndarray>
│   │           hydro_year                    (time) int64 216B dask.array<chunksize=(27,), meta=np.ndarray>
│   │         * rgi_id                        (rgi_id) <U14 56B 'RGI60-06.00372'
│   │         * month_2d                      (month_2d) int64 96B 1 2 3 4 5 ... 9 10 11 12
│   │           calendar_month_2d             (month_2d) int64 96B dask.array<chunksize=(12,), meta=np.ndarray>
│   │       Data variables: (12/21)
│   │           area                          (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
│   │           length                        (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
│   │           liq_prcp_off_glacier          (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
│   │           liq_prcp_off_glacier_monthly  (member, time, month_2d, rgi_id) float64 21kB dask.array<chunksize=(1, 27, 12, 1), meta=np.ndarray>
│   │           liq_prcp_on_glacier           (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
│   │           liq_prcp_on_glacier_monthly   (member, time, month_2d, rgi_id) float64 21kB dask.array<chunksize=(1, 27, 12, 1), meta=np.ndarray>
│   │           ...                            ...
│   │           snowfall_off_glacier          (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
│   │           snowfall_off_glacier_monthly  (member, time, month_2d, rgi_id) float64 21kB dask.array<chunksize=(1, 27, 12, 1), meta=np.ndarray>
│   │           snowfall_on_glacier           (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
│   │           snowfall_on_glacier_monthly   (member, time, month_2d, rgi_id) float64 21kB dask.array<chunksize=(1, 27, 12, 1), meta=np.ndarray>
│   │           specific_mb                   (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
│   │           volume                        (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
│   │       Attributes:
│   │           Conventions:           CF-1.12
│   │           comment:               The DTC Glaciers project is developed under the Eu...
│   │           date_created:          2026-01-11T14:01:19.088667
│   │           RGI-ID:                RGI60-06.00372
│   │           glacier_attributes:    {}
│   │           title:                 Datacube of observation-informed modelled variables.
│   │           summary:               Observation-informed modelled variables for RGI6-I...
│   │           calibration_strategy:  OGGM mass-balance model 'DailyTIModel' calibrated ...
│   ├── Group: /L2_Daily_Hugonnet_2000_2020/daily_smb
│   │       Dimensions:                   (member: 8, time: 9436)
│   │       Coordinates:
│   │         * member                    (member) <U7 224B 'Control' '0.05' ... '0.95'
│   │         * time                      (time) float64 75kB 2e+03 2e+03 ... 2.026e+03
│   │           calendar_year             (time) int64 75kB dask.array<chunksize=(9436,), meta=np.ndarray>
│   │       Data variables:
│   │           specific_mb               (member, time) float64 604kB dask.array<chunksize=(1, 9436), meta=np.ndarray>
│   │           specific_mb_calendar_cum  (member, time) float64 604kB dask.array<chunksize=(1, 9436), meta=np.ndarray>
│   │       Attributes:
│   │           Conventions:           CF-1.12
│   │           comment:               The DTC Glaciers project is developed under the Eu...
│   │           date_created:          2026-01-11T14:01:19.094434
│   │           RGI-ID:                RGI60-06.00372
│   │           glacier_attributes:    {}
│   │           title:                 Datacube of observation-informed modelled variables.
│   │           summary:               Observation-informed modelled variables for RGI6-I...
│   │           calibration_strategy:  OGGM mass-balance model 'DailyTIModel' calibrated ...
│   └── Group: /L2_Daily_Hugonnet_2000_2020/monthly
│           Dimensions:                   (member: 8, time: 310, rgi_id: 1)
│           Coordinates:
│             * member                    (member) <U7 224B 'Control' '0.05' ... '0.95'
│             * time                      (time) float64 2kB 2e+03 2e+03 ... 2.026e+03
│               calendar_month            (time) int64 2kB dask.array<chunksize=(310,), meta=np.ndarray>
│               calendar_year             (time) int64 2kB dask.array<chunksize=(310,), meta=np.ndarray>
│               hydro_month               (time) int64 2kB dask.array<chunksize=(310,), meta=np.ndarray>
│               hydro_year                (time) int64 2kB dask.array<chunksize=(310,), meta=np.ndarray>
│             * rgi_id                    (rgi_id) <U14 56B 'RGI60-06.00372'
│           Data variables:
│               area                      (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
│               length                    (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
│               specific_mb               (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
│               specific_mb_calendar_cum  (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
│               volume                    (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
│           Attributes:
│               Conventions:           CF-1.12
│               comment:               The DTC Glaciers project is developed under the Eu...
│               date_created:          2026-01-11T14:01:19.095507
│               RGI-ID:                RGI60-06.00372
│               glacier_attributes:    {}
│               title:                 Datacube of observation-informed modelled variables.
│               summary:               Observation-informed modelled variables for RGI6-I...
│               calibration_strategy:  OGGM mass-balance model 'DailyTIModel' calibrated ...
└── Group: /L2_Daily_Hugonnet_2010_2020
    ├── Group: /L2_Daily_Hugonnet_2010_2020/annual_hydro
    │       Dimensions:                       (member: 8, time: 27, rgi_id: 1, month_2d: 12)
    │       Coordinates:
    │         * member                        (member) <U7 224B 'Control' '0.05' ... '0.95'
    │         * time                          (time) int64 216B 2000 2001 2002 ... 2025 2026
    │           calendar_month                (time) int64 216B dask.array<chunksize=(27,), meta=np.ndarray>
    │           calendar_year                 (time) int64 216B dask.array<chunksize=(27,), meta=np.ndarray>
    │           hydro_month                   (time) int64 216B dask.array<chunksize=(27,), meta=np.ndarray>
    │           hydro_year                    (time) int64 216B dask.array<chunksize=(27,), meta=np.ndarray>
    │         * rgi_id                        (rgi_id) <U14 56B 'RGI60-06.00372'
    │         * month_2d                      (month_2d) int64 96B 1 2 3 4 5 ... 9 10 11 12
    │           calendar_month_2d             (month_2d) int64 96B dask.array<chunksize=(12,), meta=np.ndarray>
    │       Data variables: (12/21)
    │           area                          (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
    │           length                        (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
    │           liq_prcp_off_glacier          (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
    │           liq_prcp_off_glacier_monthly  (member, time, month_2d, rgi_id) float64 21kB dask.array<chunksize=(1, 27, 12, 1), meta=np.ndarray>
    │           liq_prcp_on_glacier           (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
    │           liq_prcp_on_glacier_monthly   (member, time, month_2d, rgi_id) float64 21kB dask.array<chunksize=(1, 27, 12, 1), meta=np.ndarray>
    │           ...                            ...
    │           snowfall_off_glacier          (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
    │           snowfall_off_glacier_monthly  (member, time, month_2d, rgi_id) float64 21kB dask.array<chunksize=(1, 27, 12, 1), meta=np.ndarray>
    │           snowfall_on_glacier           (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
    │           snowfall_on_glacier_monthly   (member, time, month_2d, rgi_id) float64 21kB dask.array<chunksize=(1, 27, 12, 1), meta=np.ndarray>
    │           specific_mb                   (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
    │           volume                        (member, time, rgi_id) float64 2kB dask.array<chunksize=(1, 27, 1), meta=np.ndarray>
    │       Attributes:
    │           Conventions:           CF-1.12
    │           comment:               The DTC Glaciers project is developed under the Eu...
    │           date_created:          2026-01-11T14:01:19.102278
    │           RGI-ID:                RGI60-06.00372
    │           glacier_attributes:    {}
    │           title:                 Datacube of observation-informed modelled variables.
    │           summary:               Observation-informed modelled variables for RGI6-I...
    │           calibration_strategy:  OGGM mass-balance model 'DailyTIModel' calibrated ...
    ├── Group: /L2_Daily_Hugonnet_2010_2020/daily_smb
    │       Dimensions:                   (member: 8, time: 9436)
    │       Coordinates:
    │         * member                    (member) <U7 224B 'Control' '0.05' ... '0.95'
    │         * time                      (time) float64 75kB 2e+03 2e+03 ... 2.026e+03
    │           calendar_year             (time) int64 75kB dask.array<chunksize=(9436,), meta=np.ndarray>
    │       Data variables:
    │           specific_mb               (member, time) float64 604kB dask.array<chunksize=(1, 9436), meta=np.ndarray>
    │           specific_mb_calendar_cum  (member, time) float64 604kB dask.array<chunksize=(1, 9436), meta=np.ndarray>
    │       Attributes:
    │           Conventions:           CF-1.12
    │           comment:               The DTC Glaciers project is developed under the Eu...
    │           date_created:          2026-01-11T14:01:19.107996
    │           RGI-ID:                RGI60-06.00372
    │           glacier_attributes:    {}
    │           title:                 Datacube of observation-informed modelled variables.
    │           summary:               Observation-informed modelled variables for RGI6-I...
    │           calibration_strategy:  OGGM mass-balance model 'DailyTIModel' calibrated ...
    └── Group: /L2_Daily_Hugonnet_2010_2020/monthly
            Dimensions:                   (member: 8, time: 310, rgi_id: 1)
            Coordinates:
              * member                    (member) <U7 224B 'Control' '0.05' ... '0.95'
              * time                      (time) float64 2kB 2e+03 2e+03 ... 2.026e+03
                calendar_month            (time) int64 2kB dask.array<chunksize=(310,), meta=np.ndarray>
                calendar_year             (time) int64 2kB dask.array<chunksize=(310,), meta=np.ndarray>
                hydro_month               (time) int64 2kB dask.array<chunksize=(310,), meta=np.ndarray>
                hydro_year                (time) int64 2kB dask.array<chunksize=(310,), meta=np.ndarray>
              * rgi_id                    (rgi_id) <U14 56B 'RGI60-06.00372'
            Data variables:
                area                      (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
                length                    (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
                specific_mb               (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
                specific_mb_calendar_cum  (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
                volume                    (member, time, rgi_id) float64 20kB dask.array<chunksize=(1, 310, 1), meta=np.ndarray>
            Attributes:
                Conventions:           CF-1.12
                comment:               The DTC Glaciers project is developed under the Eu...
                date_created:          2026-01-11T14:01:19.109065
                RGI-ID:                RGI60-06.00372
                glacier_attributes:    {}
                title:                 Datacube of observation-informed modelled variables.
                summary:               Observation-informed modelled variables for RGI6-I...
                calibration_strategy:  OGGM mass-balance model 'DailyTIModel' calibrated ...

We can also specify the datacube layer we want to access by using the layer argument:

datacube_l1 = streamer.stream_datacube(glacier="RGI60-06.00372", layer="L1")
datacube_l1
<xarray.DataTree>
Group: /
    Dimensions:                               (y: 194, x: 208, t: 177, t_wgms: 0)
    Coordinates:
      * y                                     (y) float32 776B 7.118e+06 ... 7.11...
      * x                                     (x) float32 832B 4.443e+05 ... 4.48...
      * t                                     (t) datetime64[ns] 1kB 2011-01-15 ....
      * t_wgms                                (t_wgms) int64 0B 
    Data variables: (12/19)
        consensus_ice_thickness               (y, x) float32 161kB dask.array<chunksize=(194, 208), meta=np.ndarray>
        eolis_gridded_elevation_change        (t, y, x) float64 57MB dask.array<chunksize=(177, 60, 60), meta=np.ndarray>
        eolis_gridded_elevation_change_sigma  (t, y, x) float64 57MB dask.array<chunksize=(177, 60, 60), meta=np.ndarray>
        glacier_ext                           (y, x) int8 40kB dask.array<chunksize=(194, 208), meta=np.ndarray>
        glacier_mask                          (y, x) int8 40kB dask.array<chunksize=(194, 208), meta=np.ndarray>
        hugonnet_dhdt                         (y, x) float32 161kB dask.array<chunksize=(194, 208), meta=np.ndarray>
        ...                                    ...
        spatial_ref                           int64 8B ...
        topo                                  (y, x) float32 161kB dask.array<chunksize=(194, 208), meta=np.ndarray>
        topo_smoothed                         (y, x) float32 161kB dask.array<chunksize=(194, 208), meta=np.ndarray>
        topo_valid_mask                       (y, x) int8 40kB dask.array<chunksize=(194, 208), meta=np.ndarray>
        wgms_mb                               (t_wgms) float64 0B dask.array<chunksize=(0,), meta=np.ndarray>
        wgms_mb_unc                           (t_wgms) float64 0B dask.array<chunksize=(0,), meta=np.ndarray>
    Attributes:
        Conventions:         CF-1.12
        comment:             The DTC Glaciers project is developed under the Euro...
        date_created:        2026-01-11T14:01:19.084593
        RGI-ID:              RGI60-06.00372
        glacier_attributes:  {'rgi_id': 'RGI60-06.00372', 'glims_id': 'G343896E64...
        title:               Datacube of glacier-domain variables.
        summary:             Resampled glacier-domain variables from multiple sou...

Technical Implementation#

Datacubes are streamed directly from a URL, and opened as data trees. This is equivalent to accessing a GeoZarrHandler’s data_tree attribute:

xr.open_datatree(
    stream_url="https://cluster.klima.uni-bremen.de/~dtcg/test_zarr/",
    group=None,
    chunks={},
    engine="zarr",
    consolidated=True,
    decode_cf=True,
)

A user will not download data unless they perform a processing step or call compute().

datacube.L1.eolis_gridded_elevation_change
<xarray.DataArray 'eolis_gridded_elevation_change' (t: 177, y: 194, x: 208)> Size: 57MB
dask.array<open_dataset-eolis_gridded_elevation_change, shape=(177, 194, 208), dtype=float64, chunksize=(177, 60, 60), chunktype=numpy.ndarray>
Coordinates:
  * t        (t) datetime64[ns] 1kB 2011-01-15 2011-02-15 ... 2025-09-15
  * y        (y) float32 776B 7.118e+06 7.118e+06 ... 7.115e+06 7.115e+06
  * x        (x) float32 832B 4.443e+05 4.443e+05 ... 4.482e+05 4.483e+05
Attributes:
    units:                m
    ancillary_variables:  elevation_change_sigma, interpolation_binary_mask
    comment:              Elevation change since January 2011.
    institution:          Earthwave/The University of Edinburgh/ESA
    long_name:            change in land-ice surface altitude since January 2011
    references:           EOLIS elevation data generated using swath processi...
    source:               CryoTEMPO-EOLIS gridded product; gaps filled with G...
    standard_name:        change_over_time_in_land_ice_surface_altitude
    grid_mapping:         spatial_ref

DTC Glaciers API#

import dtcg
import dtcg.interface.gateway
import dtcg.interface.plotting

A user interacts with DTCG only through API requests. This means a single centralised framework can handle requests from Jupyter notebooks, websites, and cli wrappers. Flows are simplified for non-technical users, and can be customised for more advanced use cases. It also prevents significant changes to the DTCG API interfering with existing flows, as little to no backend code is exposed to the user.

# User selects these via dropdown menus
subregion_name = "vent_rofenache"
glacier_name = "RGI60-06.00372"

API queries are extensible, as long as they conform to the OpenAPI standard. For selecting a subregion, this is what an API query could look like:

# A query might look like this
user_query_params = {
    "action": "select_subregion",
    "region_name": "Central Europe",
    "subregion_name": subregion_name,
    "glacier_name": glacier_name,
    "shapefile_path": "nested_catchments_oetztal/nested_catchments_oetztal.shx",
    "oggm_params": {
        "use_multiprocessing": True,
        "rgi_version": "62",
        "store_model_geometry": True,
    },
}

A user can also select specific glaciers:

# A query might look like this
user_query_params = {
    "action": "select_glacier",
    "region_name": "Central Europe",
    "subregion_name": subregion_name,
    "glacier_name": glacier_name,
    "shapefile_path": "nested_catchments_oetztal/nested_catchments_oetztal.shx",
    "oggm_params": {
        "use_multiprocessing": True,
        "rgi_version": "62",
        "store_model_geometry": True,
    },
}

The API is very flexible: it can pass OGGM parameters directly to OGGM, and to preserve bandwidth a response can be customised to contain as little data as needed.