Files
Northern-Thailand-Ping-Rive…/rust/forecast/flood_config.json
T
grabowski 5c4f464383
CI / Test suite (push) Successful in 1m2s
CI / Format & lint (push) Successful in 22s
Rust / fmt, clippy, test, build (push) Successful in 9m53s
Security / Dependency vulnerabilities (push) Successful in 1m52s
Security / Static analysis (push) Successful in 20s
Security / License report (push) Successful in 1m41s
feat(forecast): Rust forecast crate, bit-for-bit with the Python serving path
Phase 2a of docs/RUST_REWRITE.md. rust/forecast (ping-forecast) ports the
serving half of src/ml: the HII mirror gap fill, the hourly grid, every
feature (pandas' Kahan rolling sums included), the Mae Ngat dam frame,
HistGradientBoosting tree inference, the heuristic fallback, stale-threshold
handling and the P.1 flood-stage probabilities.

Hand-over from Python (src/ml/export.py):
- models/flood_<station>.json.gz next to each joblib bundle; train_all() writes
  it, retrain.sh promotes it, `python -m src.ml.export` exports existing ones.
- rust/forecast/flood_config.json: thresholds, stages, leads and notify
  constants, compiled in. tests/test_model_export.py fails while it differs
  from the Python source.

Parity (rust/forecast/tests/parity.rs, fixtures from
testdata/gen_forecast_fixtures.py on the production code path): four
scenarios incl. the 2024 flood with RID lagging behind HII. Merged readings,
all features and all levels identical; with all 15 local models 377/384
probabilities bit-identical, the rest within 2 ulp (exp).

Python refactor without behaviour change: predict.forecasts_from_long, and
get_latest_forecasts/load_latest/serving_frame take now/rain for
reproducible comparisons; the HII query orders its rows.
2026-10-18 14:21:56 +07:00

349 lines
3.7 KiB
JSON

{
"thresholds": {
"*": [
3.0,
4.5
],
"P.1": [
3.7,
4.2
],
"P.103": [
5.95,
6.75
],
"P.20": [
2.35,
2.8
],
"P.21": [
3.2,
3.6
],
"P.4A": [
3.4,
3.9
],
"P.5": [
4.55,
4.95
],
"P.67": [
2.45,
2.9
],
"P.75": [
3.2,
3.65
],
"P.76": [
5.35,
5.45
],
"P.77": [
4.3,
4.9
],
"P.81": [
5.15,
6.3
],
"P.82": [
3.4,
3.75
],
"P.84": [
3.45,
3.9
],
"P.85": [
2.9,
3.35
],
"P.87": [
3.75,
4.05
],
"P.92": [
2.95,
3.6
]
},
"flood_stages": {
"P.1": [
{
"stage": 1,
"level": 3.7,
"discharge_cms": 405.0
},
{
"stage": 2,
"level": 3.9,
"discharge_cms": 438.0
},
{
"stage": 3,
"level": 4.0,
"discharge_cms": 458.0
},
{
"stage": 4,
"level": 4.1,
"discharge_cms": 478.0
},
{
"stage": 5,
"level": 4.2,
"discharge_cms": 493.0
},
{
"stage": 6,
"level": 4.3,
"discharge_cms": 508.0
},
{
"stage": 7,
"level": 4.6,
"discharge_cms": 558.0
}
]
},
"upstream_leads": {
"P.1": [
[
"P.103",
1
],
[
"P.67",
7
],
[
"P.21",
9
],
[
"P.75",
12
],
[
"P.4A",
12
],
[
"P.92",
15
],
[
"P.20",
17
]
],
"P.103": [
[
"P.67",
6
],
[
"P.21",
8
],
[
"P.75",
11
],
[
"P.4A",
11
],
[
"P.92",
14
],
[
"P.20",
16
]
],
"P.21": [
[
"P.67",
1
],
[
"P.75",
3
],
[
"P.4A",
3
],
[
"P.92",
6
],
[
"P.20",
8
]
],
"P.67": [
[
"P.75",
5
],
[
"P.4A",
5
],
[
"P.92",
8
],
[
"P.20",
10
]
],
"P.75": [
[
"P.92",
3
],
[
"P.20",
5
]
],
"P.4A": [
[
"P.92",
3
],
[
"P.20",
5
]
],
"P.92": [
[
"P.20",
2
]
],
"P.20": [],
"P.5": [
[
"P.1",
12
],
[
"P.103",
13
]
],
"P.81": [
[
"P.1",
4
],
[
"P.103",
5
]
],
"P.82": [],
"P.84": [],
"P.87": [],
"P.77": [],
"P.85": [],
"P.76": []
},
"dam_stations": [
"P.1",
"P.103",
"P.21",
"P.5",
"P.67",
"P.81"
],
"monsoon_months": [
6,
7,
8,
9,
10
],
"ffill_limit_h": 3,
"basin_anchor": "P.1",
"forward_rain_h": 24,
"horizons": [
6,
12,
24
],
"stale_after_h": 6.0,
"heuristic_sigma": 0.3,
"heuristic_version": "heuristic-v1",
"latest_window_h": 336,
"hii_fill_stations": [
"P.1",
"P.103",
"P.20",
"P.4A",
"P.67",
"P.75",
"P.82",
"P.84",
"P.92",
"P.81"
],
"hii_exact_mirrors": [
"P.1",
"P.103",
"P.20",
"P.4A",
"P.67",
"P.75",
"P.82",
"P.84",
"P.92"
],
"hii_min_overlap_hours": 168,
"dam": {
"dam_id": "200103",
"report_hour": 7,
"ffill_limit_h": 48,
"serving_days": 21
},
"notify": {
"clear_margin_m": 0.1,
"capacity_guard_min_pct": 60.0,
"capacity_guard_exempt": [
"P.1"
],
"outlook_on": 0.5,
"outlook_off": 0.25,
"outlook_horizon": 24,
"feed_stale_after_h": 3.0,
"station_names": {
"P.1": "Nawarat Bridge, Chiang Mai city",
"P.103": "Ring Road Bridge 3, Chiang Mai",
"P.67": "Ban Tae (Mae Taeng)",
"P.21": "Ban Rim Tai (Mae Rim)",
"P.75": "Ban Chai Lat",
"P.92": "Ban Muang Aut",
"P.20": "Ban Chiang Dao",
"P.4A": "Ban Mae Taeng",
"P.5": "Tha Nang Bridge (downstream)",
"P.81": "Ban Pong (downstream)",
"P.82": "Ban Sob Win",
"P.84": "Ban Panton",
"P.87": "Ban Pa Sang",
"P.77": "Ban Sop Mae Sapuat",
"P.85": "Ban Lai Kaew",
"P.76": "Ban Mae I Hai"
}
}
}