Skip to content

Archive layout: the contract

The Archive is the public Hugging Face dataset Rekin226/aquascope-gauges. People read it from DuckDB, R, QGIS and pandas without installing AquaScope, so its paths and columns are a public interface, the same as a Python function. This page lists every published prefix, its files and columns, units, cadence, licence and the workflow that writes it. Stability says what may change; The Archive explains how to use it.

Every file is at https://huggingface.co/datasets/Rekin226/aquascope-gauges/resolve/main/<path>, or hf://datasets/Rekin226/aquascope-gauges/<path> in DuckDB and pandas.

The promise

From 1.0, within a major version:

  • Paths stay. A published path is not renamed or removed. A new layout is added beside the old one, and the old one keeps being written for the deprecation period (see Stability).
  • Columns stay. A column is not renamed, removed, retyped or given a new unit. New columns may be added at the end, so read columns by name, not by position.
  • Keys stay. (source, station_id) identifies a gauge everywhere, river_id a GEOGLOWS v2 reach, hybas_id a BasinATLAS sub-basin. Dates are ISO 8601 (YYYY-MM-DD, months YYYY-MM), in UTC.
  • Units are fixed per column and given below. Discharge is m3/s, levels are metres, precipitation is mm.
  • Cadence is a target, not a guarantee. The schedules below are what CI runs. A run can fail; health.json, obs/refresh_status.json and each prefix's manifest.json say when a file was last made.
  • Values change. Rows are added and revised as agencies revise their records and as new days arrive. A method fix can change a derived number; the CHANGELOG says so.

What is not covered: the dataset card (README.md), the contents of the manifest.json and index.json files beyond the keys named here, row order, Parquet row-group sizes and compression, and anything under a prefix this page marks experimental.

Each scheduled job writes only under its own prefix (the harvest also writes the catalogue files at the root), plus its own record under health/jobs/. The forecast, warnings, climatology, skill and bulletin jobs build a smoke run without publishing it.

Status on 2026-10-12

Checked against the live dataset (file listing, Parquet schemas and JSON manifests). Every prefix below is published except health/, whose writer was merged on 2026-10-12 and publishes from each job's next run; scout/, waterbalance/ and the daily flowstatus/ files first appeared on 2026-10-11.

Prefix Status Stability
root catalogue (stations.parquet, ...) live stable
obs/ live stable
basins/ live stable
skill/ live experimental
bulletins/ live experimental
forecasts/ (issued/, status/, reaches.parquet) live experimental
forecasts/warnings/ live experimental
feeds/ live experimental
flowstatus/climatology/ live experimental
flowstatus/ (daily files) live experimental
scout/ live experimental
waterbalance/ live experimental
context/ live experimental
health/ from the next scheduled runs experimental
samples/ from the first mirror-samples.yml run (added 2026-10-12) experimental

The experimental prefixes were first published in October 2026 by the 0.26.0 and 0.27.0 jobs. They follow the same rules for adding columns, but a path or column there may change in a minor release, with a CHANGELOG entry, until it is declared stable.

Root: the station catalogue

Written by harvest.yml, weekly (Mondays 03:17 UTC), with aquascope harvest stations.

File What
stations.parquet GeoParquet 1.0, one row per station from every station-capable source
stations.geojson the same rows as GeoJSON points
health.json the last run, per source: source, ok, n_stations, seconds, error, license, redistributable, agency; plus run_at, aquascope_version, n_stations, n_ok, n_failed, files
signatures.parquet flow signatures of every mirrored discharge station
README.md the dataset card (not part of the contract)

stations.parquet columns:

Column Type Meaning
source string AquaScope source key (usgs, uk_ea, ...; see Data sources)
station_id string the station's id in the catalogue (join key)
site_id string the physical site within a source; defaults to station_id
name string station name as the agency gives it
latitude, longitude double WGS84 degrees
variables list of string what the station measures (discharge, water_level, groundwater_level, precipitation, ...)
period_start, period_end date the record's span where the agency says it, else empty
url string deep link to the agency's page
river, country, agency string where known
license string the source's licence identifier
redistributable bool true when the source's terms allow mirroring observations
extra string source-specific fields as JSON
geometry binary WKB point (GeoParquet geo metadata)

signatures.parquet columns: source, station_id, variable, latitude, longitude, unit, record_start, record_end (dates as strings), record_years, n_days, data_years, completeness, q_mean, q5, q50, q95 (m3/s; q5 is exceeded 5 % of days), bfi (Lyne-Hollick baseflow index), n_amax_years, amax_mk_p, amax_sen_slope (m3/s per year), amax_trend (rising, falling or none), q100 (m3/s, GEV by L-moments), amax_doy_mean, amax_doy_r, notes (why a value is empty).

Licence: each row carries its source's licence in license; observations-derived values follow the source. Attribution per source is in aquascope.registry.SOURCES[key].attribution.

obs/: daily observations

Written by harvest.yml, weekly, incrementally (python -m aquascope.archive.refresh, then aquascope harvest bundles). Only sources whose registry entry has redistributable=True are mirrored.

Path Columns
obs/<variable>/<source>/<station_id>.csv.gz date,value: one row per day
obs/<variable>/<source>.parquet station_id (string), date (date32), value (double)
obs/manifest.json keys sources, bundles, bundle_status, updated_at, version; per "<source>/<variable>", each station's period, count and unit
obs/last_run.json the last harvest per source and variable: attempted, harvested, empty, failed, seconds, errors, budget_exhausted, stopped
obs/refresh_status.json per source and variable: status, station_budget, time_budget_seconds, exit_code, start and end times

<variable> is one of discharge (m3/s), water_level (m), groundwater_level (m) and precipitation (mm per day). <source> is the source key; <station_id> matches stations.parquet. Values are daily, in those units, as the agency publishes them after AquaScope's unit conversion; quality flags are not carried.

Licence: the source's own (the license column of stations.parquet, and the table in The Archive).

basins/: BasinATLAS catchments

The BasinATLAS files are written by basins.yml (manual; BasinATLAS v1.0 does not change). The three station tables are rebuilt weekly by harvest.yml.

File What Writer
basins/lev12_topology.parquet hybas_id, next_down, next_sink, main_bas (int64), sub_area, up_area (km2), pfaf_id, endo, coast, order, lat, lon (a representative point) basins.yml
basins/lev12_attributes.parquet every BasinATLAS attribute per level-12 sub-basin, keyed by hybas_id basins.yml
basins/lev12.fgb simplified level-12 polygons, FlatGeobuf with a spatial index basins.yml
basins/lev12.pmtiles, basins/lev06.pmtiles vector tiles for maps basins.yml
basins/build.json built_at, n_basins, files, attribution, license basins.yml
basins/station_catchments.parquet each station's sub-basin: source, station_id, hybas_id, up_area, sub_area, area_km2, area_source, attribute_scope, then catchment attributes with their unit in the name (elevation_m, slope_deg, precipitation_mm_yr, pet_mm_yr, aet_mm_yr, aridity_index, temperature_c, snow_cover_pct, runoff_mm_yr, discharge_m3s, land cover, soil, population and regulation fields) harvest.yml
basins/station_signatures.parquet donor signatures for regionalisation, in mm per day over the catchment: source, station_id, area_km2, area_source, hybas_id, n_days, n_years, start, end, q_mean_mm, q_median_mm, q95_mm, q05_mm, q_annual_max_mm, runoff_ratio, baseflow_index, fdc_slope, high_flow_frequency, low_flow_frequency, zero_flow_fraction, seasonality_index, flashiness_index harvest.yml
basins/regionalization_skill.json leave-one-out skill of the regionalisation methods: n_stations, n_signature_stations, k, run_at, methods harvest.yml

Licence: CC BY 4.0, BasinATLAS v1.0 (Linke et al. 2019, https://doi.org/10.1038/s41597-019-0300-6). The station tables also carry each source's terms for the gauge data they are computed from.

skill/: the evidence ladder (experimental)

Written by model-skill.yml, monthly (the 3rd, 05:41 UTC).

File What
skill/model_skill.parquet one row per gauge and model: source, station_id, lat, lon, area_km2, model, label, grade (A to D), why, is_best, kge, r, alpha, beta, nse, pbias, mean_gauge, mean_model (m3/s), n_days, start, end, flood_years, q2_*, q10_*, q100_* (gauge and model, m3/s, and _error_pct), site_id, match, distance_m, model_area_km2, area_ratio, sentence, licence, computed_at
skill/manifest.json the run: built_at, n_rows, n_gauges, rows_by_model, dropped, failures, models, grading

Licence: model output under each model's terms (GEOGLOWS v2 and Google GRRR CC BY 4.0, NWM public domain), scored against gauge data under each source's terms.

forecasts/: issued forecasts and today's status (experimental)

Written by forecast-archive.yml, daily (06:41 UTC), with python -m aquascope.archive.forecasts.

File What
forecasts/status/latest.parquet each live gauge's flow today against normal: source, station_id, value_date, value (m3/s), percentile, class (much_below, below, normal, above, much_above), n_years
forecasts/status/<YYYY-MM-DD>.parquet the same snapshot, kept by date
forecasts/status/latest.json made, date, sources, n, counts, classes, method
forecasts/issued/<YYYY-MM-DD>.parquet one row per gauge, model and valid day: issue_date, source, station_id, river_id, model, init_date, valid_date, lead_day, mean, median, p25, p75, min, max, high_res (m3/s, raw) and the same with _c (corrected to the gauge), kge_raw, kge_corrected, reach_mean_ratio, gauge_q2 to gauge_q100 (m3/s), by, generated
forecasts/reaches.parquet each gauge's reach: source, station_id, river_id, distance_m, lat, lon, glofas_lat, glofas_lon, snapped_at
forecasts/manifest.json issues (date, file, counts, what was dropped and why), columns, status, licence

Licence: GEOGLOWS v2 output CC BY 4.0; GloFAS through Open-Meteo CC BY 4.0. Model output, labelled so.

forecasts/warnings/: floods ahead (experimental)

Written by flood-warnings.yml, daily (14:23 UTC), with python -m aquascope.archive.warnings. Model output, not an official warning.

File What
forecasts/warnings/latest.parquet one row per reach expected to reach its 2-year flow in 15 days: river_id, lat, lon, strahler_order, area_km2, peak_cms, peak_date, rp (years), share (of 51 members), q2 to q100 (m3/s), daily (one character per day, 0 to 6), gauges
forecasts/warnings/<YYYY-MM-DD>.parquet the same table, kept by the forecast's start date (the last 60 days, then the first of each month; see retention)
forecasts/warnings/latest.geojson the same reaches as slim points for maps
forecasts/warnings/manifest.json issue_date, valid_from, valid_to, counts, thresholds, method, smoke

Licence: CC BY-NC-SA 4.0, because the return-period thresholds come from GEOGLOWS's retrospective return periods, which their metadata licenses that way. The forecast itself is CC BY 4.0.

feeds/: per-gauge Atom feeds (experimental)

Written by forecast-archive.yml, daily, after forecasts/ (python -m aquascope.archive.feeds).

File What
feeds/<source>/<station_id>.xml an Atom 1.0 feed per live gauge (the id with anything but A-Z a-z 0-9 . _ - as _)
feeds/index.json updated, date, base, n, rights, feeds (gauge to path)
feeds/state.parquet the entries kept per gauge: source, station_id, kind, cls, level, entry_id, updated, link, title, summary

Licence: the gauge's agency for observations; GEOGLOWS v2 CC BY 4.0 for forecast entries.

flowstatus/: flow against normal (experimental)

Path What Writer, cadence
flowstatus/climatology/month-01.parquet to month-12.parquet river_id (int64), p10, p25, p75, p90 (float32, m3/s): the percentiles of daily flow in that calendar month, 1950 to 2019 flow-climatology.yml, manual, once
flowstatus/climatology/reaches.parquet river_id, lat, lon, strahler_order flow-climatology.yml
flowstatus/climatology/manifest.json source, base_period, percentiles, min_strahler_order, n, files, licence flow-climatology.yml
flowstatus/latest.parquet river_id (int64), flow_cms (float32, m3/s), class (uint8, 1 much below to 5 much above) flood-warnings.yml, daily
flowstatus/latest.bin.gz, flowstatus/<YYYY-MM-DD>.bin.gz the compact class file the Explorer draws from (format in aquascope.flowstatus); dated files (the last 60 days, then the first of each month; see retention) flood-warnings.yml, daily
flowstatus/manifest.json the day's run: issue_date, n, counts, classes, percentiles, base_period, files, licence flood-warnings.yml, daily

Licence: CC BY 4.0 (GEOGLOWS v2 forecast and flow duration curves).

scout/: what stands out today (experimental)

Written by flood-warnings.yml, daily, after the Floods ahead issue (python -m aquascope.map_scout).

File What
scout/latest.json made, date, method, inputs, findings, picks, counts, sources: the world's findings, each of one kind (status, floods_ahead, floods_past, gauges_today, models_disagree), with its place, numbers, reason and source
scout/<YYYY-MM-DD>.json the same, kept by date (the last 60 days, then the first of each month; see retention)

Licence: each finding names its layer, under that layer's licence.

waterbalance/: subbasins by monthly water balance (experimental)

Written by water-balance.yml, monthly (the 9th, 05:41 UTC), with python -m aquascope.waterbalance. Modelled, not measured.

File What
waterbalance/monthly.parquet one row per HydroBASINS level-4 subbasin and month since 1990: hybas_id (int64), month (YYYY-MM), p_mm, et_mm, q_mm, closure_mm (mm in the month), q_out_cms, q_in_cms (m3/s), era5t (bool), p_anom, et_anom, q_anom, closure_anom (mm against 1991-2020)
waterbalance/normals.parquet hybas_id, month_of_year, p_mm, et_mm, q_mm, closure_mm: 1991-2020 means
waterbalance/basins.parquet hybas_id, k, area_km2, lat, lon, outlets, down_id, up_ids, linked, runoff_ok, runoff_check, era5_cells
waterbalance/basins.geojson simplified outlines
waterbalance/normals.json, waterbalance/years/<YYYY>.json the Explorer's files
waterbalance/manifest.json months covered, method, licences, cost

Licence: CC BY 4.0 (ERA5 from Copernicus Climate Change Service / ECMWF, GEOGLOWS v2, BasinATLAS).

bulletins/: the monthly state of the rivers (experimental)

Written by bulletin.yml, monthly (the 3rd, 08:17 UTC), with python -m aquascope.bulletin.

File What
bulletins/<YYYY-MM>/status.parquet one row per gauge: source, station_id, month, value (monthly mean flow, m3/s), n_days, percentile, class, n_years, median (m3/s), ratio, record, country, basin_id
bulletins/<YYYY-MM>/bulletin.json the bulletin's numbers, per country and basin
bulletins/<YYYY-MM>/bulletin.html, bulletin.md, map.png the bulletin for reading and printing
bulletins/index.json latest, months (newest first: month, label, made, classed, considered, counts, headline, sources)

Licence: computed from the mirrored observations, under each source's terms.

health/: scheduled job health (experimental)

Written by every scheduled workflow's last step, whether the job passed or not (aquascope.archive.health_jobs,

593). A smoke run's record is never published.

File What
health/jobs/<job>.json one job: job, label, workflow, cadence, cadence_hours, stale_after_hours, layers, writes, updated_at, last_run, last_success, last_failure (each with status, started_at, finished_at, duration_s, event, run_url, counts, data_date, reasons, notes), consecutive_failures, history
health/jobs/index.json about, updated_at, jobs: every job in JOBS with its expected cadence and newest state, which the Explorer reads

Licence: none of its own; the files hold run metadata only, no observations.

context/: place-context mirrors (experimental)

Written by mirror-context.yml, manual (run again when a source releases a new version). Each dataset is a cell-sorted Parquet plus one small gzipped CSV per 2-degree cell (n00_e000 names the cell by its south-west corner).

Path What Licence
context/dams/gdw_barriers.parquet, context/dams/cells/<cell>.csv.gz Global Dam Watch v1.0 barriers: gdw_id, name, reservoir, river, country, year, height_m, capacity_mcm, area_km2, main_use, dor_pc, catchment_km2, lat, lon, grand_id (cell in the Parquet) CC BY 4.0
context/ghcn/prcp_stations.csv.gz NOAA GHCN-Daily stations that record precipitation: id, lat, lon, elev_m, name, first_year, last_year CC0
context/floods/groundsource.parquet, context/floods/groundsource/cells/<cell>.csv.gz Groundsource flood events from news: uuid, start_date, end_date, lat, lon, west, south, east, north, area_km2 CC BY 4.0
context/floods/microsoft.parquet, context/floods/microsoft/cells/<cell>.csv.gz Microsoft AI for Good Sentinel-1 flood detections per 0.05 degree cell and month: lat, lon, year, month, n MIT
context/floods/monthly/grid.parquet both flood sources per half-degree cell and month: month, row, col, lat, lon, news, radar CC BY 4.0 (news), MIT (radar)
context/floods/monthly/index.json, context/floods/monthly/months/<YYYY-MM>.json.gz the months covered, and one compact file per month for the Explorer as above
context/manifest.json per dataset: rows, cells, folder, licence, attribution, source, built

samples/: sample model results (experimental)

Written by mirror-samples.yml, manual and one-off (python -m aquascope.archive.samples). An additive path (#591): the files the Explorer's "Try a sample model" opens when their own host does not let a browser page fetch them. Each is a byte-for-byte copy, checked against the SHA-256 recorded in aquascope.archive.samples.

File What
samples/hec-ras/Flood_model.p01_BC12_S6_R6.hdf a HEC-RAS 6.5 2D plan result (29.9 MB): compound flooding in Portsmouth, Virginia, 109 steps every 15 minutes
samples/hec-ras/manifest.json id, title, about, files (each path, name, bytes, sha256), source (url, resource, title, creator, publisher, licence, licence_url), attribution, mirrored_at, made_by

Licence: CC BY 4.0. Zandsalimi, Zanko, GNN4CF: Dataset for Boundary-Aware Graph Neural Networks for Compound Flood Forecasting, HydroShare, resource 32aac3af553c4e1fbb997ec58d9de9b6. FloPy's Freyberg example, the MODFLOW sample, is not mirrored: the Explorer reads it from GitHub (public domain).

Changing this page

A pull request that adds a prefix, file or column updates this page in the same change; tests/test_public_api.py checks that every prefix the code publishes is listed here. A pull request that would rename or remove a path or column follows the deprecation rules in Stability.