Quick Start

This page walks through a minimal end-to-end forecast in five steps: download data, prepare predictors and predictand, cross-validate a model, verify the hindcast, and produce an operational forecast map.

For more detailed explanations of each step see the User guide.

Prerequisites

Install wass2s and activate your environment (see Installation) then open a Jupyter notebook or Python script and import the package:

from wass2s import *
import numpy as np

Step 1 — Download data

downloader = WAS_Download()

# ERA5 global SST — predictor window (JFM)
downloader.WAS_Download_Reanalysis(
    dir_to_save="./data/era5/",
    center_variable=["ERA5.SST"],
    year_start=1991, year_end=2025,
    area=[45, -180, -45, 180],   # [N, W, S, E]
    seas=["01", "02", "03"],
    force_download=False
)

# AgERA5 precipitation — predictand (JJAS)
downloader.WAS_Download_AgroIndicators(
    dir_to_save="./data/obs/",
    variables=["AGRO.PRCP"],
    year_start=1991, year_end=2024,
    area=[30, -25, 0, 30],
    seas=["06", "07", "08", "09"],
    force_download=False
)

Step 2 — Prepare predictors and predictand

clim_year_start, clim_year_end = 1991, 2020
year_start, year_end = 1991, 2024

# Observed predictand (T, Y, X)
predictand = prepare_predictand(
    "./data/obs/", ["AGRO.PRCP"],
    year_start, year_end,
    seas=["06", "07", "08", "09"],
    ds=False
)

# SST indices as predictors
sst_index_names = ["NINO34", "TNA", "TSA", "DMI"]
predictors = compute_sst_indices(
    "./data/era5/", sst_index_names,
    "ERA5.SST", year_start, year_end,
    seas=["01", "02", "03"],
    clim_year_start=clim_year_start,
    clim_year_end=clim_year_end
)
predictors = (
    predictors
    .to_array()
    .rename({"variable": "features"})
    .transpose("T", "features")
)

Step 3 — Cross-validate a Ridge regression model

# Optimise the regularisation parameter
ridge = WAS_Ridge_Model(
    n_clusters=6,
    alpha_range=np.logspace(-4, 0.1, 20),
    nb_cores=4
)
alpha, clusters = ridge.compute_hyperparameters(
    predictand, predictors.isel(T=slice(None, -1)),
    clim_year_start, clim_year_end
)

# Leave-one-out cross-validation
cv = WAS_Cross_Validator(
    n_splits=len(predictand.get_index("T")),
    nb_omit=2
)
hindcast_det, hindcast_prob = cv.cross_validate(
    ridge, predictand,
    predictors.isel(T=slice(None, -1)),
    clim_year_start, clim_year_end,
    alpha=alpha
)

Step 4 — Verify the hindcast

verifier = WAS_Verification()

pearson = verifier.compute_deterministic_score(
    verifier.pearson_corr, predictand, hindcast_det
)
groc = verifier.compute_probabilistic_score(
    verifier.calculate_groc, predictand, hindcast_prob,
    clim_year_start=clim_year_start,
    clim_year_end=clim_year_end
)

verifier.plot_model_score(pearson, "Pearson",
    dir_save_score="./scores/", figure_name="pearson_ridge")
verifier.plot_model_score(groc, "GROC",
    dir_save_score="./scores/", figure_name="groc_ridge")

Step 5 — Operational forecast for the target year

# The last time step of predictors is the real-time predictor
forecast_det, forecast_prob = ridge.forecast(
    predictand, clim_year_start, clim_year_end,
    predictors.isel(T=slice(None, -1)),   # hindcast predictors
    hindcast_det,
    predictors.isel(T=[-1]),              # real-time predictor
    alpha=alpha
)

# Save and plot
plot_prob_forecasts(
    dir_to_save="./forecasts/",
    forecast_prob=forecast_prob,
    model_name="Ridge",
    title="JJAS 2025 Sahel Rainfall Forecast — Ridge Regression"
)

Tip

Replace WAS_Ridge_Model with any other model class — WAS_PCR, WAS_CCA, WAS_SVR, WAS_MLP, WAS_Analog, or an MME class — without changing the cross-validation or forecasting calls.