Rossby wave breaking prediction check

Rossby wave breaking prediction check

Runs once a day on GitHub Actions (.github/workflows/rwb_prediction.yml) and publishes to the public Hugging Face dataset yanxingjianken/rwb-prediction, which the page /blocking-plots/rwb-prediction/ reads.

Question. Can new Rossby wave breaking be predicted a day ahead from the analysed flow alone, without running a weather forecast? At every 00 and 12 UTC issue time three methods mark alarm regions on the map, on three upper-level surfaces (PV on 330 K, PV on 350 K, θ on 2 PVU):

  • U − c matching: on contours at fixed equivalent latitudes, every 15° of longitude, the phase speed c of the contour’s undulation over the past 24 h against the wind U along it; the region lies within 500 km of the pieces where |U − c| ≤ 2 m s⁻¹.
  • Opus model: a predictor variable computed from the analysed winds and θ on 2 PVU of the past 60 h in local cells; the region covers the cells where it has fallen to 0.1 of its value 1.5–2.5 days earlier. One set of alarm regions per issue time, scored against the breakings of all three surfaces.
  • GFS 24-h forecast: the NOAA GFS run from the issue time; the region lies within 500 km of the new breakings it forecasts at 6–24 h.

Truth. ERA5T (about five days behind real time). Breaking objects every 6 h from overturning circumpolar contours at fixed values (PV every 0.5 PVU, θ every 5 K; after the method of pvtend.rwb; field smoothed with a 3° Gaussian, bays of at least 300 deg², anticyclonic or cyclonic by the path-order rule, merged within 1000 km); an onset is an object with no object of the same type within 1500 km 6 h and 12 h earlier.

Scores. A new breaking within 24 h of the issue time is a hit when an alarm region lies within 1000 km of it; an alarm region with no breaking within 1000 km is a false alarm; on about 210 equal-area boxes (≈1000 km) north of 10° N, the false positive rate is the share of the boxes without a breaking that an alarm region touched.

All settings are in config.py and were fixed before any score was computed.

graph TD
    A[(ERA5T hourly u, v, T, 70-500 hPa, CDS)] --> S[surfaces.py: PV on 330/350 K, θ on 2 PVU]
    G[(GFS 1° runs, steps 0-24 h, AWS)] --> S
    S --> E[events.py: breaking objects and onsets]
    S --> P[predictors.py: U − c matching, Opus model, GFS]
    E --> C[core.py: onsets vs alarm regions: hits, false alarms, box scores]
    P --> C
    C --> R[render.py: maps]
    C --> M[run_pipeline.py: issue records, summary.json, index.json]
    R --> H[(Hugging Face dataset)]
    M --> H
    H --> W[page /blocking-plots/rwb-prediction/]
FileContent
config.pyevery setting
era5.py, gfs.pyERA5T from the Climate Data Store; GFS 1° by byte ranges from the NOAA Open Data bucket
surfaces.pyErtel PV from pressure levels; PV on isentropes, θ on 2 PVU (same code for both sources)
events.pybreaking objects, types, flanks, onsets
predictors.pythe three methods’ alarm regions
core.pyone issue time: onsets of the next 24 h, alarm regions, hits, false alarms, box scores
render.pythe maps
run_pipeline.pydaily mode (Actions) and a one-off backfill mode
tests/breaking types on an idealized jet; contour crossings

Local backfill (run once by hand; nothing recurring):

python run_pipeline.py --backfill 2026093012 2026102612 --era5-dir era5 --out out --workers 8

The daily job needs the repository secrets HF_TOKEN and a personal access token of the ECMWF data stores (CDSAPI_KEY or ECDS_API; the token itself or the text of an API configuration file, any data-store URL — ERA5 is always requested from the Climate Data Store).