Files
Northern-Thailand-Ping-Rive…/docs/DATA_SOURCES.md
T
grabowski d72496f404
CI/CD Pipeline - Northern Thailand Ping River Monitor / Test Suite (3.11) (push) Failing after 31s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Build Docker Image (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Integration Test with Services (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Deploy to Staging (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Deploy to Production (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Performance Test (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Cleanup (push) Successful in 0s
Documentation / Documentation Summary (push) Successful in 2s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Code Quality (push) Successful in 13s
Documentation / Validate Documentation (push) Failing after 9s
Documentation / Generate API Documentation (push) Successful in 9s
Documentation / Build Sphinx Documentation (push) Successful in 15s
feat: backfill hii_waterlevel from the HII waterlevel_graph archive
scripts/backfill_hii_waterlevel.py walks the api-v3 waterlevel_graph
endpoint (hourly wl_msl + discharge, archive back to ~2019) in full-year
windows per station and upserts into hii_waterlevel. Defaults to the
RID-mirror and key stations; --stations/--all/--start/--end/--chunk-days
override. History upserts touch only wl_msl and discharge so colliding
live-snapshot rows keep storage_percent/situation_level. Idempotent and
safe to re-run.
2026-08-11 15:11:08 +07:00

257 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Data Sources & External API Catalog
Catalog of every data source available to the Ping River Monitor — what we ingest
today, what the ThaiWater/HII ecosystem exposes, and vetted external feeds for
future model inputs (rainfall, dam releases, forecasts).
All "verified" claims below were empirically probed on **2026-08-11**. Endpoints
marked *(catalog)* were recovered from the thaiwater.net frontend JS bundle but
not exercised (auth required).
---
## 1. Currently ingested — RID hydrology telemetry
The only source persisted to the database and used by the ML pipeline.
| | |
|---|---|
| Endpoint | `POST https://hyd-app-db.rid.go.th/webservice/getGroupHourlyWaterLevelReportAllHL.ashx` |
| Agency | Royal Irrigation Department (RID) |
| Auth | None |
| Cadence | Hourly (`hourlytime` 1.0024.00; hour 24 = midnight next day) |
| Params | `DW[UtokID]=1`, `DW[BasinID]=6` (Ping), `DW[TimeCurrent]=<Buddhist-calendar date>`, `rows=100` |
| Variables | Water level (m, gauge datum), discharge (m³/s, `'***'` = malformed), discharge % of channel capacity |
| Stations | 16 P-series gauges (P.1 anchor at Nawarat Bridge; see `src/data/stations.json`) |
| Client | `src/water_scraper_v3.py` |
Human-facing page: <https://hyd-app-db.rid.go.th/hydro1h.html>
---
## 2. ThaiWater / HII ecosystem
ThaiWater (<https://twa.thaiwater.net>) is the National Hydroinformatics
Institute (HII) portal. It sits on **two distinct API layers** with very
different access rules.
### 2.1 `api-v3.thaiwater.net` — open, no authentication ✅
Base: `https://api-v3.thaiwater.net/api/v1/thaiwater30/public/`
Undocumented backend of the portal. No key, no session. No published rate
limits or terms of use — be a good citizen (hourly polls, cache, filter to
Ping basin `basin_code == 6`).
#### `waterlevel_load` — national water-level snapshot (verified)
```
GET https://api-v3.thaiwater.net/api/v1/thaiwater30/public/waterlevel_load
```
- ~2.4 MB, 1,426 stations nationwide; **125 in Ping Basin, 61 in Chiang Mai
province, 34 with discharge**.
- Per station: `waterlevel_m`, `waterlevel_msl`, `waterlevel_msl_previous`,
`flow_rate`, `discharge`, `storage_percent`, `situation_level` (14 flood
severity), `diff_wl_bank`, bank/critical levels (`min_bank`,
`critical_level_msl`, `warning_level_m`, `critical_level_m`, `qmax`),
`river_name`, basin, geocode, agency, lat/long, `is_key_station`.
- Ping key stations present: P.1, P.67, P.75, P.81, P.92, P.17, P.87, P.4A,
P.7A, P.77, P.2A — plus RID mirrors (`ridhydro_P.1`, …), Tak-reach `TP.`/
`TUP.` codes, and HII sensor clusters (`PIN001-011`, `CHM001-005`).
- **P.1 = internal station id `3226`** (lat 18.786961, long 99.005089).
#### `waterlevel_graph` — hourly historical time series (verified) ⭐
```
GET .../waterlevel_graph?station_type=tele_waterlevel&station_id=3226&start_date=2024-09-25&end_date=2024-10-08
```
- Returns `{data: {graph_data: [{datetime, value, value_out, discharge}]}}`,
hourly. `value` is **water level in m MSL** (not gauge datum).
- **Respects arbitrary date ranges. Archive verified back to at least
2019-08** (P.1 returned data for 2019-08-01). 14-day windows tested OK;
maximum window size not probed.
- Oct 2024 record flood fully present: peak 305.8 m MSL @ 2024-10-05 12:00,
discharge 656 m³/s.
- Datum conversion at P.1: 305.8 MSL peak = 5.30 m gauge ⇒
**gauge ≈ MSL 300.5 m** (verify per station before use; each station has
its own datum offset).
- Value: independent second historical source for cross-validating / gap-filling
the RID feed (RID grid is only ~56% filled).
#### `rain_24h` — national rainfall snapshot (verified)
```
GET https://api-v3.thaiwater.net/api/v1/thaiwater30/public/rain_24h
```
- ~4.5 MB, 4,445 stations; **321 in Chiang Mai province**; agencies include
HII, DWR, RID.
- Per station: `rain_1h`, `rain_24h` (mm), `rainfall_datetime`,
`station.id` (small int — the graph key), `station.tele_station_oldcode`
(e.g. `CHM005`, `STN0410`, `ridtele_TUP.14`), `sub_basin_id`, lat/long,
basin, geocode, agency.
- **This is the missing rainfall input** for the flood model — near-real-time
hourly gauge rain across the upper Ping catchment.
#### `rain_24h_graph` — trailing-window rainfall series (verified, limited) ⚠️
```
GET .../rain_24h_graph?station_type=tele_rainfall&station_id=418&start_date=...&end_date=...
```
- `station_id` is the **small `station.id`** from `rain_24h` (e.g. 418 =
CHM005 "Chiang Mai 5", Mae Taeng), *not* the top-level record id.
- Returns hourly `{rainfall_datetime, rainfall_value}` — **but the date range
is IGNORED**: every request returns the same trailing ~36-hour window
(39 rows). Requests for 2020/2024 return identical data to today.
- Consequence: **no rainfall history via this API**. To build training data,
persist `rain_24h` from now on and backfill history from satellite QPE or an
HII data request (§4).
#### Probed and NOT available on api-v3 (all HTTP 404)
`dam_daily`, `dam`, `dam_json`, `big_dam`, `mainstream_dam`, `weather`,
`rain_graph`, `rainfall_graph`, `rain24hr_graph`. Dam data is v2-only (§2.2).
### 2.2 `twa-api-public.thaiwater.net` — auth-gated (x-api-key / session) 🔒
The layer our existing `src/thaiwater.py` client uses
(`GET /v2/waterlevel` with `x-api-key: $THAIWATER_API_KEY`; wired to
`GET /sensors/thaiwater` in the web API, display-only, never persisted).
Without a key: HTTP 401/500. No public key-registration page was found —
obtain a sanctioned key from HII (<https://hii.or.th>).
Full endpoint catalog *(catalog — recovered from frontend JS, not exercised)*:
- **Water level / discharge**: `/v2/waterlevel`, `/v2/waterlevel/list`,
`/v2/waterlevel/{id}/detail`, `/v2/waterlevel/canal`,
`/v2/waterlevel/sea-waterlevel`, `/v2/waterlevel-discharge`,
`/v2/waterlevel-discharge/list`, `/v2/waterlevel-discharge/{id}/detail`,
`/v2/waterlevel-discharge/{id}/forecast-table`,
`/v2/waterlevel-discharge/forecast`, `/v2/waterlevel-discharge/forecast/list`,
`/v2/watergate`, `/v2/waterload-tide`
- **Dams** (incl. Bhumibol): `/v2/large-dam/daily-geo-json`,
`/v2/large-dam/daily/list`, `/v2/large-dam/hourly/list`,
`/v2/large-dam/daily/{id}/detail`, `/v2/large-dam/hourly/{id}/detail`,
`/v2/medium-dam/daily-geo-json`, `/v2/medium-dam/daily/list`,
`/v2/medium-dam/{id}/detail`, `/v2/summary/summary4dam`,
`/v2/summary/dam-summary`, `/v2/summary/dam-crisis`
- **Rainfall**: `/v2/rainfall/{type}`, `/v2/rainfall/{type}/list`,
`/v2/district-rain/actual-measure`, `/v2/district-rain/forecast`,
`/v2/district-rain/accumulate`, `/v2/summary/rainfall24h-ranking-province`,
`/v2/summary/rainfall-24hr-forecast`, `/v2/summary/rainfall-forecast`,
`/v2/summary/warning-rainfall-24h`, `/v2/summary/warning-rainfall-48h`
- **Weather / hazards**: `/v2/weather`, `/v2/storm`, `/v2/wave`, `/v2/pm25`,
`/v2/pm10`, `/v2/flood/flash-flood`, `/v2/flood/flash-flood-alert`,
`/v2/drought/alert`, `/v2/drought/risk-area/list`,
`/v2/summary/weather-summary`, `/v2/summary/temperature-forecast`,
`/v2/summary-area/rainfall`
- **Time-series / graph** (base `/data/platform/v1/public/`):
`tele_waterlevel/graph`, `flow/graph`, `latest_waterlevel/forecast/graph`,
`latest_watertide/forecast/graph`, `dam_pdaily_sum_by_date`,
`dam_pdaily_sum_by_region_graph`, `dam_rulecurve/graph`,
`medium_dam/graph_year`, `monthly_rainfall/stations`,
`monthly_rainfall/anomaly-stations`, `tele_watergate/graph`,
`salinity_forecast_cpy/graph`, `sea_waterlevel_forecast/graph`,
`latest_weather_area`, `latest_weather_area_daily`
### 2.3 Other HII hosts
| Host | What | Access |
|---|---|---|
| `https://standard.thaiwater.net` | **Official water-data standard** — canonical station/basin/province code registries, data-exchange formats, warning-level definitions (Thai) | Open, docs site |
| `https://api.hii.or.th/tiservice/v1/ws/{token}/isohyet/daily/latest/province/{code}` | Daily isohyet rainfall by province | Token in path |
| `https://live1.hii.or.th/product/latest/rain/one_map/data/*.tif` | Rainfall anomaly & 16-month forecast GeoTIFF rasters | Open |
| `https://data.hii.or.th` | HII open-data catalog — 36 datasets (rainfall telemetry, water level, weather, climate) | Open browsing |
| `https://tiwrm.hii.or.th` | Legacy reports | Open |
Historical bulk telemetry: HII documents a request channel at
**nhcsoc@hii.or.th**.
---
## 3. Dams & reservoirs
> **Geography matters: Bhumibol Dam (Tak) is ~240 km DOWNSTREAM of P.1** and
> cannot influence Chiang Mai water levels. Do not use it as a P.1 feature.
The predictive upstream reservoir is **Mae Ngat Somboon Chon** (Mae Ngat
tributary, joins the Ping above Chiang Mai; spilled 110 m³/s during the
Oct 2024 flood). Mae Kuang Udom Thara is the second upstream reservoir.
| Source | What | Access |
|---|---|---|
| `https://lsim.rid.go.th/ForeCast?reservoirid=22` | Mae Ngat daily status/forecast (RID) | Open, scrape |
| `https://app.rid.go.th/reservoir/` | RID reservoir DB, per-reservoir daily detail with date-range URLs | Open, scrape (confirm URL pattern before hard-coding) |
| `https://water.egat.co.th` | EGAT dams (Bhumibol/Sirikit) hourly+daily inflow/outflow/level | Endpoint catalog not public; contact EGAT (0-2436-8186). Only relevant downstream of Bhumibol |
| ThaiWater `/v2/large-dam/*`, `dam_rulecurve/graph` | All large/medium dams incl. hourly | Requires HII API key (§2.2) |
---
## 4. Rainfall & weather (external)
### Near-real-time (usable in the live inference path)
| Source | Cadence / latency | Access | Notes |
|---|---|---|---|
| HII `rain_24h` (§2.1) | Hourly, near-real-time | Open JSON | Primary rain-gauge feed; persist from now on |
| GSMaP NRT (JAXA) | Hourly, ~4 h latency, 0.1° | Free JAXA registration (FTP); or Google Earth Engine `JAXA/GPM_L3/GSMaP/v8/operational` (no registration) | Gauge-corrected `hourlyPrecipRateGC`; catchment-average rain where gauges are sparse |
| NASA IMERG **Early Run** | Half-hourly, ~4 h latency, 0.1° | Free Earthdata login | NASA-stack alternative to GSMaP |
### Forecasts (the only way past the ~17 h physical lead-time cap)
| Source | What | Access |
|---|---|---|
| **Open-Meteo** (<https://open-meteo.com>) | Hourly precip forecast ≤16 days, any lat/lon; **Historical Forecast API archive from 2021** (train on forecast-as-seen, leakage-free); Previous Runs API (fixed 17-day leads from Jan 2024); ERA5 back to 1940 | Free, no key, 10k calls/day, non-commercial w/ attribution |
| TMD NWP API (`https://data.tmd.go.th/nwpapi/v1/forecast/location/...`) | WRF 4.2 daily/hourly forecasts by place, processed ~06:00 daily | Free Bearer-token registration (`/nwpapi/doc/main/`) |
| GFS / ECMWF IFS open data | 0.25° global, 4×/day | Free (NOMADS / AWS / data.ecmwf.int); Open-Meteo already wraps both |
### Training-only (too slow for live)
| Source | Cadence | Latency |
|---|---|---|
| CHIRPS (`data.chc.ucsb.edu/products/CHIRPS-2.0/`) | Daily, 0.05° | ~2 days prelim / 3+ weeks final |
| IMERG Late / Final | Half-hourly | ~14 h / ~3.5 months |
| TMD observation API (`data.tmd.go.th/api/index1.php`) | 3-hourly / daily station obs, XML | Free uid+key registration |
---
## 5. Historical / open-data portals
| Portal | Content |
|---|---|
| `https://data.hii.or.th` | 36 HII datasets (rainfall telemetry the most viewed) |
| `https://data.go.th/dataset?organization=rid` | 4 RID datasets (API + ZIP) |
| `https://gdcatalog.go.th` | Nationwide daily rainfall-station catalogs |
| `https://hydro-1.net` | RID Upper-Northern Hydrology Center — hourly/daily tables, hydrology yearbooks (rating curves) for P-series stations; scrape/download |
| `https://water.rid.go.th/flood/flood/daily.pdf` | RID daily flood bulletin (PDF only) |
---
## 6. Integration status & recommended order
| Source | Status | Action |
|---|---|---|
| RID hourly gauges | ✅ Ingested (hourly → PostgreSQL) | — |
| ThaiWater `/v2/waterlevel` | 🟡 Display-only (`src/thaiwater.py`, needs `THAIWATER_API_KEY`, never persisted) | Optionally persist |
| HII `rain_24h` | ✅ Ingested hourly via `src/hii_collector.py``hii_rain_stations` + `hii_rainfall` (Ping-filtered; ~300 stations) | — |
| HII `waterlevel_load` | ✅ Ingested hourly via `src/hii_collector.py``hii_wl_stations` + `hii_waterlevel` (125 Ping stations, m MSL; `rid_code` column maps mirrors like `ridhydro_P.1``P.1`, `offset_msl` converts MSL → gauge datum) | — |
| HII `waterlevel_graph` | ✅ Backfill via `scripts/backfill_hii_waterlevel.py``hii_waterlevel` (hourly MSL + discharge, archive ≥2019; full-year windows per request; upserts never overwrite live-snapshot columns) | Run once on the box: `python scripts/backfill_hii_waterlevel.py` (defaults: 2019-01-01 → today, RID-mirror + key stations; `--stations P.1,P.67`, `--all` for every Ping station) |
| Mae Ngat reservoir (lsim.rid.go.th) | ❌ Not ingested | Add daily storage/release scrape |
| Satellite QPE (GSMaP/IMERG) | ❌ | Backfill training rainfall (GEE) |
| Open-Meteo forecasts | ❌ | Add forecast features (live + 2021 archive for training) |
| HII API key (dams, forecasts) | ❌ | Contact HII for sanctioned access |
**Collector configuration** (`src/hii_collector.py`): runs automatically every
scraping cycle (hourly cadence, even while the RID scraper is in 1-minute retry
mode) from both `--web-api` and continuous-monitoring modes; one-shot via
`python -m src.main --collect-hii`. Env vars: `ENABLE_HII_COLLECTION`
(default `true`), `HII_BASIN_CODE` (default `6` = Ping). Requires a SQL
`DB_TYPE` (sqlite/postgresql/mysql); tables are created automatically.
**Caveats**: `api-v3` is an undocumented backend — no SLA, no ToS, may change
without notice. Poll hourly at most, cache aggressively, and pursue official
HII access for anything production-critical.