1  GEOGloWS Overview

1.1 What is GEOGloWS?

GEOGloWS (Group on Earth Observations Global Water Sustainability) is a GEO initiative that provides a global streamflow forecasting and historical simulation service. The flagship product is the GEOGloWS ECMWF Streamflow Service, a partnership between GEO, ECMWF, and Brigham Young University (BYU).

The service aims to give every country access to hydrological forecasts, particularly countries that lack national forecasting infrastructure. Version 2 was released in 2024 with significant improvements to the river network and data access infrastructure.

1.2 Model Architecture

The system has two components:

1.2.1 Forecasts

  • Meteorological forcing: ECMWF IFS (Integrated Forecasting System) ensemble weather forecasts provide runoff inputs
  • Routing model: RAPID (Routing Application for Parallel computation of Discharge) routes runoff through the global river network
  • River network: TDX-Hydro — derived from TanDEM-X 90m DEM, approximately 6.8 million river reaches globally
  • Ensemble members: 52 (51 perturbed + 1 high-resolution control)
  • Forecast lead time: 15 days
  • Temporal resolution: Hourly (3-hourly for ensemble members, hourly for high-res)
  • Update frequency: Daily

1.2.2 Retrospective Simulation

  • Meteorological forcing: ERA5 reanalysis (ECMWF’s global atmospheric reanalysis)
  • Period: 1940 to present — this is substantially longer than GloFAS (1979–present)
  • Temporal resolution: Hourly (also available as daily, monthly, yearly aggregates)
  • Return periods: Pre-computed for 2, 5, 10, 25, 50, 100-year levels using Log-Pearson III distribution

1.2.3 Critical Conceptual Note: Retrospective vs Reforecast

This distinction is fundamental to understanding what GEOGloWS can and cannot do for trigger calibration:

Retrospective (what GEOGloWS has): A single deterministic time series of “what the model thinks happened” from 1940–present. It uses ERA5 reanalysis — essentially observed weather run through the routing model after the fact. There is no forecast uncertainty because the meteorological input is already known. You get one discharge value per timestep.

Reforecast (what GloFAS has, GEOGloWS does not): For each historical date, the forecast system is re-run as if standing on that date not knowing the future. For example, for July 15 2015, you get an N-member ensemble forecast with multiple leadtime steps — and you can compare what it predicted at 3-day and 7-day lead against what actually happened.

The retrospective is the answer key. The reforecast is the student’s exam papers. You need both to grade forecast skill. For AA trigger calibration — where the question is “if X% of ensemble members exceed the threshold at 3-day lead, should we trigger?” — you need reforecasts to calibrate X%. The retrospective alone cannot answer this.

GEOGloWS’s forecast archive currently retains roughly 22 months (gd.dates() returns ~670 daily forecast dates as of writing). That is enough to compare a forecast’s day-0 analysis against the retrospective for the same date, but far too short to support the multi-year reforecast comparison required for trigger calibration.

1.3 Comparison with Existing Data Sources

Feature GloFAS Google GRRR GEOGloWS v2
Provider ECMWF/Copernicus Google GEO/BYU/ECMWF
Hydro model LISFLOOD Proprietary RAPID (routing only)
Met forcing ECMWF IFS + ERA5 Proprietary ECMWF IFS + ERA5
Ensemble members 51 (reforecast: 11) Ensemble 52
Forecast lead 30 days Variable 15 days
Retrospective 1979–present 1980–2023 1940–present
Reforecasts Yes (2003–2023) Yes (2016–2023) No
Return periods Copernicus dashboard Computed Built-in API
RP distribution Gumbel Empirical Log-Pearson III
API auth CDS registration GCS token None (free)
River network ~0.05° grid HydroBASINS TDX-Hydro (~6.8M reaches)
Bias correction Manual Manual Built-in (SFDC, FDC)

1.4 Python Package: geoglows v2.2.0

The geoglows Python package provides access to all data products. Data is stored on AWS S3 as Zarr arrays (retrospective) and on a REST API (forecasts).

1.4.1 Key Functions

Code
import geoglows.data as gd
import pandas as pd
from pathlib import Path

# Available data functions
data_funcs = [
    ("gd.forecast_ensembles(river_id)", "52-member ensemble forecast"),
    ("gd.forecast_stats(river_id)", "Ensemble summary statistics"),
    ("gd.retrospective(river_id)", "Full retrospective (hourly default)"),
    ("gd.retro_daily(river_id)", "Daily retrospective"),
    ("gd.return_periods(river_id)", "RP thresholds (2-100yr)"),
    ("gd.fdc(river_id)", "Flow duration curve"),
    ("gd.dates()", "Available forecast dates"),
    ("gd.latlon_to_river(lat, lon)", "Find river ID from coordinates"),
]

import pandas as pd
pd.DataFrame(data_funcs, columns=["Function", "Description"])
Function Description
0 gd.forecast_ensembles(river_id) 52-member ensemble forecast
1 gd.forecast_stats(river_id) Ensemble summary statistics
2 gd.retrospective(river_id) Full retrospective (hourly default)
3 gd.retro_daily(river_id) Daily retrospective
4 gd.return_periods(river_id) RP thresholds (2-100yr)
5 gd.fdc(river_id) Flow duration curve
6 gd.dates() Available forecast dates
7 gd.latlon_to_river(lat, lon) Find river ID from coordinates

1.4.2 Quick Demo: Return Periods

Code
import ocha_stratus as stratus
from src.constants import BLOB_PREFIX, BLOB_STAGE

rp = stratus.load_parquet_from_blob(
    f"{BLOB_PREFIX}/geoglows_return_periods_441135650.parquet",
    stage=BLOB_STAGE,
)
print("Chatara (Koshi) — GEOGloWS Return Periods (m³/s):")
rp
Chatara (Koshi) — GEOGloWS Return Periods (m³/s):
441135650
return_period
2 14458.948
5 18433.434
10 21056.356
25 24379.680
50 26870.105
100 29378.284

1.4.3 Quick Demo: Forecast Ensemble Structure

# Example: fetch today's forecast (not run at render time — requires S3 search)
stats = gd.forecast_stats(river_id=441135650)
# Returns DataFrame with columns:
#   flow_min, flow_25p, flow_avg, flow_med, flow_75p, flow_max, high_res
# Index: hourly timestamps over 15-day forecast window
# Shape: ~280 rows x 7 columns

The forecast data has 52 ensemble members (51 perturbed + 1 high-resolution control). The forecast_stats() function returns summary statistics across the 51 perturbed members; forecast_ensembles() returns all 52 individual traces.

1.5 Data Storage

  • Retrospective: S3 Zarr at s3://geoglows-v2/ (anonymous access)
  • Forecasts: S3 Zarr, organized by date (YYYYMMDDHH.zarr)
  • REST API: https://geoglows.ecmwf.int/api/v2/ (backup access method)
  • Metadata table: Parquet file with all ~6.8M river reach properties

1.5.1 Known Issues

  • The pytz package is missing from the declared dependencies (must be installed manually)
  • latlon_to_river() requires downloading the full metadata table (~100MB+), which is slow on first call
  • The metadata table in v2.2.0 does not contain lat/lon columns despite the function trying to use them — the REST getriverid endpoint is more reliable