AFNOCast β Seasonal Precipitation Post-Processing (Blue Nile)
Seasonal AFNOCast (Wiegels et al., 2026)is a deep-learning post-processing model that corrects bias and downscales daily ensemble precipitation forecasts from ECMWF SEAS5 (~0.28Β°) to a high-resolution 0.1Β° grid over the Blue Nile Basin (7.1Β°Nβ17.6Β°N, 32.0Β°Eβ39.7Β°E).
A separate model state dict is provided for each of the 12 calendar months of valid time, enabling month-specific bias correction across the full 215-day SEAS5 forecast horizon.
Model Architecture
Seasonal AFNOCast is a 3-D convolutional encoderβdecoder augmented with an Adaptive Fourier Neural Operator (AFNO) block that operates on the spectral representation of the spatial field.
Input (25/51 ens Γ 11 time-steps Γ 38 lat Γ 28 lon)
β
βββ Encoder (2Γ ReflectionPad3d + Conv3d + ReLU)
βββ Encoder2 (2Γ ReflectionPad3d + Conv3d + ReLU)
β βββ + ensemble std conditioning (same encoder path)
βββ Bicubic upsampling Γ2.79 β (~106 lat Γ 78 lon)
βββ Positional embedding (learnable)
βββ AFNO block (Adaptive Fourier, 2 blocks, sparsity threshold 0.001)
βββ Dropout3d (p=0.1, applied after AFNO β dropout_state=1)
βββ Encoder2 (second pass)
βββ Decoder (2Γ stride Conv3d + ReLU β n_ens output members)
Output (n_ens Γ 106 lat Γ 78 lon)
The forward pass uses torch.vmap over the ensemble dimension so each member is processed independently through process_chain, with the per-pixel ensemble standard deviation injected as an additive conditioning signal.
| Hyperparameter | Value |
|---|---|
n_feature |
10 |
dropout_state |
1 (late dropout, after AFNO) |
n_ens (output members) |
1 per forward pass |
| AFNO blocks | 2 |
| Upsampling factor | Γ2.79 (bicubic, antialias) |
Input / Output Specification
| Input | Output | |
|---|---|---|
| Variable | Total precipitation | Total precipitation |
| Source | ECMWF SEAS5 | post-processed forecast towards ERA5-Land |
| Resolution | 0.1Β° (106 Γ 78 grid points) | |
| Ensemble | 25 members (hindcast), 51 members (forecast) | 1 member per model call, after concatenation 25/51 members |
| Temporal context | 11 days (target day Β± 5 days) | 1 day (target day) |
| Domain | lat 7.1β17.6Β°N, lon 32.0β39.7Β°E | same |
Per-Month Checkpoints
One model is trained independently for each calendar month of valid time (i.e. the month in which the forecast day falls, not the initialisation month).
| Month | File |
|---|---|
| January | afnocast_best_01.safetensors |
| February | afnocast_best_02.safetensors |
| March | afnocast_best_03.safetensors |
| April | afnocast_best_04.safetensors |
| May | afnocast_best_05.safetensors |
| June | afnocast_best_06.safetensors |
| July | afnocast_best_07.safetensors |
| August | afnocast_best_08.safetensors |
| September | afnocast_best_09.safetensors |
| October | afnocast_best_10.safetensors |
| November | afnocast_best_11.safetensors |
| December | afnocast_best_12.safetensors |
Training Details
| Setting | Value |
|---|---|
| Optimizer | Adam |
| Learning rate | 3 Γ 10β»β΄ |
| Epochs | 100 (early stopping patience = 10) |
| Batch size | 4 |
Data splits:
| Split | Period |
|---|---|
| Training | 1981β2010 |
| Validation (during training) | 2011β2016 |
| Hold-out test | 2017β2023 |
Loss function:
| Component | Weight | Description |
|---|---|---|
| CRPS | 1.0 | Continuous Ranked Probability Score across ensemble |
Usage
Installation
This project is managed with uv. Clone the repository and run:
uv sync
This creates a .venv/ virtual environment and installs all dependencies. Activate it before running anything:
source .venv/bin/activate # Linux / macOS
# on Windows: .venv\Scripts\activate
Quick inference (Python API)
from seasonal_afnocast.inference.inference import InferenceOrchestrator
orchestrator = InferenceOrchestrator(
init_date="202505", # SEAS5 initialisation date (yyyymm)
trained_model_dir="weights/", # directory with afnocast_best_MM.safetensors
seas_forecast_dir="/path/to/SEAS5_tp_yyyymm.nc/directory",
output_dir="./output",
device="cuda", # or "cpu"
batch_size=4,
)
ds = orchestrator.run()
# ds is an xarray.Dataset with dims (timestep, ens_out, latitude, longitude)
# Saved automatically to output_dir/inference_202505.nc
Command-line interface
python src/seasonal_afnocast/inference/inference.py \
--init_date yyyymm \
--seas-forecast-dir /path/to/SEAS5/dir \
--output-dir ./results/inference \
The --trained-model-dir and --config arguments default to the weights/ and configs/ folders at the project root and can be omitted when running from the cloned repository.
What happens internally
compute_target_months("2025", "05")derives the 7β8 calendar months covered by the 215-day forecast.- For each target month the orchestrator loads
afnocast_best_<MM>.safetensors. InferenceDatasetreads the raw SEAS5 NetCDF, clips to the Blue Nile domain, filters to that calendar month, and builds 11-step Β±5-day context windows (with boundary padding) β mirroring the training sample construction.- Outputs are stitched into a single
xarray.Datasetwith proper latitude/longitude coordinates and saved as NetCDF.
Expected SEAS5 input file
/your/seas5/dir/SEAS5_tp_<yyyymm>.nc
Dimensions: (ens, time, lat, lon)
Variable: tp (total precipitation, float32).
Repository Structure
βββ configs/
β βββ config_afnocast.yaml # Model and data configuration
βββ weights/
β βββ afnocast_best_01.safetensors # State dicts, one per calendar month
β βββ ...
βββ src/seasonal_afnocast/
β βββ models/AFNOCast.py # Model architecture
β βββ inference/inference.py # InferenceOrchestrator
β βββ dataloader/
β β βββ dataloader_inference.py # InferenceDataset + compute_target_months
β βββ utils/config.py # Config loading (YAML β OmegaConf)
βββ pyproject.toml
βββ README.md
Intended Use & Limitations
- Intended use: Post-processing and downscaling of ECMWF SEAS5 ensemble precipitation forecasts over the Blue Nile Basin for seasonal hydro-meteorological applications.
- Geographic scope: Blue Nile Basin only (7.1Β°Nβ17.6Β°N, 32.0Β°Eβ39.7Β°E). The model has not been evaluated outside this domain.
- Variable: Precipitation only. The architecture would need retraining for other variables.
- Forecast system: Trained on SEAS5 reforecasts. Performance for other forecast systems is untested.
Citation
If you use AFNOCast in your work, please cite this repository:
@misc{afnocast2025,
author = {Wiegels, R., Chwala, C., Polz, J., Glawion, L., Lorenz, C., Schober, T.C., Kunstmann, H. },
title = {AFNOCast: Seasonal Precipitation AI Post-Processing for the Blue Nile Basin},
year = {2025},
howpublished = {\url{https://huggingface.co/rwiegels/seasonal_afnocast}},
}
Acknowledgements
The AFNO block implementation is based on the AFNO-transformer by NVIDIA Research. SEAS5 data: Β© ECMWF. ERA5-Land data: Copernicus Climate Change Service.