GloFAS historical — the intermediate stream¶
The Global Flood Awareness System (GloFAS) river reanalysis on the CEMS Early Warning Data Store ships as two streams of the same CDS dataset (cems-glofas-historical):
| Stream | Latency | What it is |
|---|---|---|
| consolidated | ~2-3 months behind | the final, quality-controlled reanalysis |
| intermediate | ~2-5 days behind | an ERA5T-driven stream filling the recent weeks the consolidated has not reached |
earthlens curates the intermediate as its own catalog id, cems-glofas-historical-intermediate, so you can ask for "the latest available" discharge without hand-editing product_type. This notebook downloads it live over the Danube basin, maps the river discharge, and walks through the four variables it exposes.
API: earthlens.core.EarthLens · dataset cems-glofas-historical-intermediate (EWDS endpoint).
Requires a Copernicus token in
~/.cdsapircand the GloFAS licence accepted once at https://ewds.climate.copernicus.eu/datasets/cems-glofas-historical.
Setup¶
We download to a notebook-relative out/ folder — each variable is only a few tens of KB for this small two-day Danube window, so nothing large lands on disk.
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
from matplotlib.colors import LogNorm
from earthlens.core import EarthLens
DATASET = "cems-glofas-historical-intermediate"
OUT = Path("out")
DANUBE = {"lat_lim": [44.0, 48.5], "lon_lim": [16.0, 22.0]} # a Danube-basin bbox
Quickstart — download river discharge¶
The shortest end-to-end call: two days of mean daily river discharge over the Danube. variables maps the dataset id to the variables you want; download() returns the written file paths.
lens = EarthLens(
data_source="ecmwf",
variables={DATASET: ["average-river-discharge-in-the-last-24-hours"]},
start="2026-06-15",
end="2026-06-16",
temporal_resolution="daily",
path=str(OUT),
**DANUBE,
)
discharge_files = lens.download()
discharge_files
Notice the file name ends in ..._cems-glofas-historical-intermediate.nc — earthlens names the output by the requested catalog id, not the underlying CDS dataset (cems-glofas-historical). That is why the intermediate and consolidated streams never overwrite each other on disk even though they retrieve from the same CDS dataset.
discharge_files[0].name
Map the discharge¶
Open the NetCDF and plot the mean daily discharge on a log colour scale (discharge spans several orders of magnitude, from headwater cells to the Danube main stem). Zero / land cells are masked.
ds = xr.open_dataset(discharge_files[0])
dis = ds["avg_dis"].squeeze()
if dis.ndim > 2: # keep the first time step
dis = dis.isel({dis.dims[0]: 0})
grid = np.ma.masked_less_equal(np.asarray(dis.values, dtype=float), 0)
fig, ax = plt.subplots(figsize=(7, 4.2))
im = ax.imshow(grid, cmap="Blues", norm=LogNorm(), origin="upper")
ax.set_title("GloFAS intermediate - mean river discharge, 2026-06-15 (Danube basin)")
ax.set_xlabel("longitude index")
ax.set_ylabel("latitude index")
fig.colorbar(im, ax=ax, label="discharge (m$^3$ s$^{-1}$)")
plt.tight_layout()
plt.show()
ds.close() # release the file handle before the next download
The bright network traces the Danube and its tributaries: discharge accumulates downstream, so the main stem carries the highest values while headwater cells stay faint.
The four variables — and the timespan twist¶
The intermediate stream exposes four variables. Two are fluxes / means served under timespan=time_mean, and two are instantaneous states the archive only serves under timespan=instantaneous. earthlens encodes that split per variable, so you never have to remember it:
| Variable | NetCDF name | units | timespan |
|---|---|---|---|
average-river-discharge-in-the-last-24-hours |
avg_dis |
m³ s⁻¹ | time_mean |
runoff-water-equivalent |
rowe |
kg m⁻² | time_mean |
snow-depth-water-equivalent |
sd |
kg m⁻² | instantaneous |
soil-wetness-index |
swir |
1 (index) | instantaneous |
You can read that straight off the catalog row:
from earthlens.ecmwf import Catalog
for name, var in Catalog().datasets[DATASET].variables.items():
print(
f"{name:44} nc={var.nc_variable:8} units={var.units:6} "
f"timespan={var.extras.get('timespan')}"
)
Download all four at once¶
Ask for every variable in one call. earthlens issues one retrieve per variable and applies the correct timespan to each — the two instantaneous state variables would 400 under time_mean, so getting this right automatically is the point of curating the row.
all_vars = EarthLens(
data_source="ecmwf",
variables={
DATASET: [
"average-river-discharge-in-the-last-24-hours",
"runoff-water-equivalent",
"snow-depth-water-equivalent",
"soil-wetness-index",
]
},
start="2026-06-15",
end="2026-06-16",
temporal_resolution="daily",
path=str(OUT),
**DANUBE,
).download()
sorted(p.name for p in all_vars)
All four land as separate NetCDFs (one per variable). Each carries its short GRIB variable name (avg_dis, rowe, sd, swir) — the values you would index with xarray or pyramids.
Takeaway¶
cems-glofas-historical-intermediategives you GloFAS discharge for the recent weeks the consolidated reanalysis has not caught up to, through the sameEarthLenscall.- It is a curated alias of
cems-glofas-historical, so earthlens routes the retrieve to the real CDS dataset but names the output by the requested id — the two streams coexist on disk. - The four variables carry their real NetCDF names and the correct per-variable
timespan, so discharge / runoff (time_mean) and snow-depth / soil-wetness (instantaneous) all download in one call.
See the EWDS reference for the full GloFAS / CEMS-fire / EFAS catalog.