Read-only mirror of https://github.com/MeteoSwiss/ai-models-ensembles — MeteoSwiss. Issues & pull requests at the source.
  • Python 71.8%
  • Shell 22.9%
  • TeX 4%
  • Dockerfile 1.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
sadamov 5d5ae654f9 diag: 10 m wind speed in the single-ensemble Gaussianity figures
Wind speed is derived from the 10 m components in every source (forecasts,
IFS-ENS, ERA5) after the time and lead selection, so the extractors read one
slab per component. Added as a fourth variable to member_shapiro_rate and to
the single-point Q-Q.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 12:42:06 +02:00
ai_models_ensembles refresh: GraphCast all-weights refresh-every-N (GRAPHCAST_FRESH) 2026-10-07 19:34:20 +02:00
config reviewer-response tooling + figure/table polish (AMS AIES review pass) 2026-07-06 13:30:20 +02:00
containers chore(repo): slim + make the analysis scripts machine-portable 2026-09-01 21:59:12 +02:00
figures diag: 10 m wind speed in the single-ensemble Gaussianity figures 2026-10-15 12:42:06 +02:00
scripts talk: unperturbed AIFS (sigma=0) on the headline CRPSS figure 2026-10-13 21:36:23 +02:00
tests phase5: per-member IFS-ENS IC source (--ic-zarr) + MARS->SwissClim rename 2026-06-08 21:36:11 +02:00
tools diag: 10 m wind speed in the single-ensemble Gaussianity figures 2026-10-15 12:42:06 +02:00
.gitignore chore(figures): track previously-ignored figure PNGs/PDFs 2026-07-12 19:35:25 +02:00
.pre-commit-config.yaml added remaining figures from the swissclim-eval repo. then some baseic tests and pre-commits 2025-11-08 23:04:08 +01:00
LICENSE Initial commit 2023-11-23 06:34:09 -05:00
pyproject.toml chore(repo): scope pytest to tests/ 2026-09-01 22:21:46 +02:00
README.md docs: cut README to a slim operational guide 2026-09-02 01:51:11 +02:00
uv.lock chore(uv): track uv.lock for reproducible venv installs 2026-06-06 18:49:45 +02:00

AI Model Ensembles for Weather Forecasting

Turns deterministic AI weather models into calibrated ensembles by perturbing their frozen weights post-hoc, and benchmarks them against trained-probabilistic models and IFS-ENS with SwissClim Evaluations. The method, experiments, and results are in the paper: paper link TBD.

The repo is a thin orchestration layer: earth2studio does model loading, IC fetch, and rollout; swissclim-evaluations does verification; this code wires them together (model registry, IC + weight perturbation, Slurm scripts, per-model GH200 containers).

Layout

Path What
ai_models_ensembles/ the package: Typer CLI, perturbation, the earth2studio to SwissClim bridge
scripts/ Slurm submitters for inference and verification - scripts/README.md
tools/ one analysis script per paper figure/table, plus the Milton case study - tools/README.md
figures/ schematic sources (draw_*.py) and the generated figure/table files (all PDF)
containers/ one Dockerfile per model + submit_build.sh
config/ SwissClim YAML templates
tests/ schema-bridge and CLI-loadability unit tests

ai-ens models prints the model registry; ai-ens --help the CLI. Adding a model is one ModelSpec in ai_models_ensembles/e2s_models.py.

Quickstart

# 1. per-model container(s) -> $STORE/<model>.sqsh
bash containers/submit_build.sh <model|all>

# 2. host venv (orchestration + analysis only; no torch / earth2studio / jax)
uv venv --python 3.11 .venv && source .venv/bin/activate
uv pip install -e . --no-deps
uv pip install -e ./SwissClim_Evaluations --no-deps      # ai-ens verify, plot_bivariate.py
uv pip install "typer>=0.12" "zarr>=3.0" "xarray>=2024.10" "numpy>=2.0" \
  pandas matplotlib dask numcodecs pyyaml netCDF4 cfgrib rich pytest ruff pre-commit

# 3. run (each job submits to Slurm; parameters are constants at the top of each script)
bash scripts/submit_all_inference.sh [baseline]
bash scripts/submit_ablation.sh {phase1|phase2|phase2b|phase3|phase3b} [model]
bash scripts/evaluate_baselines.sh all [model]
bash scripts/evaluate_ablation.sh {<phase>|intercompare <phase>|allphases_intercompare} [model]

Anything that imports earth2studio runs inside a container: srun --container-image=$STORE/<model>.sqsh python -m ai_models_ensembles.cli .... ai-ens infer flags (--data-source, --ic-magnitude, --ic-zarr, --weight-magnitude, --layer) are documented in ai-ens infer --help; the --layer groups per model live in _MODEL_LAYER_GROUPS (e2s_perturbation.py).

Reproducing the figures and tables

tools/*.py regenerate one paper figure or table each. They read the cached intermediates committed under tools/data/ plus the eval outputs under $STORE, and resolve every machine path through tools/_env.py / ${AIENS_*:-default} shell variables, so they run on any machine once these point at your data:

Variable Meaning
AIENS_STORE forecasts / baselines / intercomparison root
AIENS_SCRATCH scratch for large CSV/JSON intermediates
AIENS_WB2_22 / AIENS_WB2_24 WeatherBench2 ERA5 truth zarrs
AIENS_IFS_ENS IFS-ENS reference zarr
AIENS_PY / AIENS_REPO interpreter / repo root for the Slurm scripts

Defaults are the CSCS paths (see tools/_env.py). The table scripts that read only tools/data/ need no $STORE. Full script-to-output map in tools/README.md.

Output format

Inference and verification speak the SwissClim schema: dims (init_time, lead_time, ensemble, latitude, longitude[, level]), datetime64 / timedelta64 coordinates, integer-hPa level, ECMWF long variable names. Bridge and tests: swissclim_format.py, tests/test_swissclim_format.py. The on-disk $STORE tree is documented in scripts/README.md.

Development

pre-commit install && pre-commit run --all-files
pytest -q          # schema bridge + CLI loadability only

Requirements: Linux, Slurm + pyxis/enroot for the GH200 containers, CUDA 12.x, outbound HTTPS for the arco / wb2 data sources, ~/.cdsapirc for cds, envsubst (gettext-base). HPC operational gotchas (SIGSEGV retries, poisoned fsspec cache, degraded capstor mount) are in scripts/README.md.