Session: 2026-05-27

← Index


Summary

Consistency fixes across notebooks 08, 14, and 15 to align wet-season definitions and Floodscan event classification. Investigated the 2025 trigger threshold methodology. Created two new notebooks: 17_threshold_selection.ipynb for the Benue grid search and 18_trigger_summary_performance.ipynb for end-to-end trigger performance evaluation.


Fixes and refinements

Google GRRR 2023 coverage (08_trigger_events.ipynb)

The Google GRRR reforecast zarr is static and covers 1980–2023, but the reforecast data for 2023 ends in July — before the Aug–Oct flood season peak. Treating 2023 as a complete year would misclassify it as a non-event.

Fix: added a dynamic filter (_grrr_rf_complete_years) that excludes any year where the maximum valid_time month is below October. This makes 2023 a NaN in the trigger matrix’s google column rather than a spurious 0.

_grrr_rf_complete_years = (
    df_grrr_rf
    .assign(year=..., month=...)
    .groupby("year")["month"]
    .max()
    .pipe(lambda s: s[s >= 10].index)
)

Floodscan event years from trigger matrix (15_trigger_performance.ipynb)

Notebook 15 was independently recomputing Floodscan annual max and RP thresholds using a seasonal filter (Aug–Nov), diverging from notebook 08’s all-months computation. This caused different event year classifications between notebooks.

Fix: replaced the local Floodscan computation with a direct load of the trigger matrix parquet produced by notebook 08 ({state}_trigger_matrix.parquet). The fs_3yr, fs_4yr, fs_5yr columns are now the single source of truth across all performance notebooks.

trigger_matrix_blob = f"ds-aa-nga-flooding/processed/trigger_matrix/{STATE.lower()}_trigger_matrix.parquet"
df_trig = stratus.load_parquet_from_blob(trigger_matrix_blob)
all_fs_years = set(df_trig["year"])
fs_event_years = {rp: set(df_trig[df_trig[f"fs_{rp}yr"] == 1]["year"]) for rp in RP_LEVELS}

FAR plot vs Floodscan RP events (14_forecast_performance.ipynb)

The final “Activation probability & FAR” plot was computing FAR against GloFAS reanalysis events, mixing reforecast performance with reanalysis ground truth.

Fix: replaced the single FAR line with three lines showing FAR vs Floodscan 3/4/5-year RP event years (loaded from the trigger matrix). Removed the light blue action window shading from this panel, which was added by shade_action_windows(ax).


2025 threshold methodology

Investigated how the current Adamawa thresholds (GloFAS: 3,132 m³/s; Google: 1,195 m³/s) were derived, for reference when setting up the Benue trigger. Key findings from exploration/2025/combined_gf_grrr_reanalysis.ipynb:

The 2025 metrics code (grrr_comparison.ipynb) used tpr (detection rate), ppv (precision), and f1 — accuracy and FAR were not computed in 2025.


New notebooks

Grid search notebook for selecting GloFAS and Google GRRR thresholds for the Benue (Makurdi) trigger. Currently glofas_thresh and google_thresh are None in STATE_CONFIG["Benue"].

Approach: - Loads GloFAS reanalysis (Makurdi), Google GRRR reanalysis (Makurdi HYBAS), Floodscan pixels for Benue state - Floodscan flood years computed from all-months annual max (consistent with notebook 08) - Wet-season (Aug–Nov) annual max for both models, inner-joined on common years - Grid search over all (GloFAS rank, Google rank) pairs; rank 0 = never trigger; OR trigger logic - Outputs: performance heatmaps (POD / Precision / F1) per Floodscan RP level, implied combined RP heatmap, threshold selection cells, year-by-year table, performance summary

Usage: run heatmaps, set SELECTED_GF_RANK and SELECTED_GOOGLE_RANK, then update STATE_CONFIG["Benue"] in src/constants.py.

18_trigger_summary_performance.ipynb — End-to-end trigger evaluation

Evaluates GloFAS trigger performance (accuracy, detection rate, FAR, precision, F1) for both the action and readiness triggers as configured in STATE_CONFIG, against all Floodscan RP levels.

Key design: - Reanalysis as leadtime=0: GloFAS reanalysis daily discharge is prepended to the reforecast as leadtime=0. A year activates if any signal at leadtime ≤ cutoff exceeds the threshold — covering both real-time observations and short-range forecasts in a single cumulative-max framework. - Consistent denominator: evaluation restricted to reforecast years (2003–2022) so all years have both reanalysis and forecast signal. - Readiness trigger is skipped if glofas_leadtime_readiness is None; the notebook asserts action leadtime and threshold are set. - Outputs: per-trigger summary table, year-by-year activation table with TP/FP/FN/TN classification, metric-vs-leadtime plot for all leadtimes 0–16.


Notebook index

Notebook Purpose
08_trigger_events.ipynb Trigger matrix — Floodscan flood year flags and model trigger columns (canonical source of truth)
13_model_performance.ipynb Annual peak correlation and precision/recall for GloFAS and Google reanalysis vs Floodscan
14_forecast_performance.ipynb Skill metrics and exceedance detection for GloFAS and Google reforecasts
15_trigger_performance.ipynb GloFAS reforecast trigger performance (accuracy/POD/FAR/precision/F1) vs leadtime, evaluated against trigger matrix event years
17_threshold_selection.ipynb Benue threshold grid search — OR trigger performance heatmaps over (GloFAS rank, Google rank) pairs
18_trigger_summary_performance.ipynb Summary trigger performance at configured action/readiness leadtimes, with reanalysis as leadtime=0

Open questions

Benue trigger thresholds

glofas_thresh and google_thresh for Benue are None in STATE_CONFIG. Run 17_threshold_selection.ipynb and update src/constants.py to unblock notebooks 16 and 18 for Benue.

Benue readiness leadtime

glofas_leadtime_readiness and google_leadtime_readiness are None for both Adamawa and Benue. These need to be defined based on the operational AA framework timeline before notebook 18 can evaluate readiness trigger performance.

Wet season definition inconsistency

Different notebooks use different wet-season month filters:

Notebook Wet months Purpose
08_trigger_events.ipynb All months (no filter before annual max) Floodscan event classification
13_model_performance.ipynb Aug–Dec [8,9,10,11,12] Daily correlation and annual max
14_forecast_performance.ipynb Aug–Dec [8,9,10,11,12] Reforecast exceedance detection
15_trigger_performance.ipynb Aug–Nov [8,9,10,11] Reforecast cumulative max
17_threshold_selection.ipynb Aug–Nov [8,9,10,11] Reanalysis annual max for threshold grid
18_trigger_summary_performance.ipynb Aug–Nov [8,9,10,11] Combined reanalysis+reforecast annual max

This is intentional (Floodscan uses all months to catch tail events; model evaluation filters to the core flood season) but worth documenting explicitly in a shared constants cell if the notebooks are later consolidated.