Skip to content
ShubhwtfPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

75 Commits

Folders and files

Repository files navigation

ClimAite

AI-powered disaster management platform for India. Predicts hazards ahead of time and estimates who and what is actually affected — population, roads, hospitals inside a predicted zone — rather than drawing an undifferentiated colour on a map.

Five hazard models feed one API, a command dashboard, and a two-role mobile app.

What works today

Model Approach Held-out result Baseline it beats
Flood inundation ResNet-34 U-Net on Sentinel-1 SAR water IoU 0.590, acc 0.935 —
Drought forecast LSTM on 45 y IMD rainfall, SPI-3, 4-week lead RMSE 0.633, r 0.803 persistence 0.762 (+16.9% skill)
Landslide susceptibility XGBoost, 14 terrain + climate factors AUC 0.726 (0.701–0.759) slope alone 0.692 (+0.034)
Misinformation MuRIL classifier + tool-using debunk agent val F1 0.970, AUC 0.994 (n=5,592) majority class 0.673
Damage assessment Vision LLM, zero-shot on pre/post pairs in progress —

Every figure above is measured on data held out by space or time, never a random split. Where a model is close to a trivial baseline we say so in the table rather than in a footnote — the landslide model's +0.034 over "just use slope" is the honest headline for it.

Supporting layers, all verified end to end:

  • Assam 2026 situation view — the Upper Assam flood wave (Sivasagar, Charaideo, Jorhat) as a single screen, with every figure labelled by provenance. Reported figures (3.75 lakh+ affected in Sivasagar, "worst in over 60 years", the district ranking) carry a reported chip and an attribution line; model figures (water extent, population, roads, hospitals) carry a model chip. The gap between them is shown rather than hidden: a 512×512 SAR chip covers ~26 km² against Sivasagar's ~2,668 km², so the two numbers differ in kind. We do not rank districts ourselves, and the view says why.
  • Impact layer — PostGIS over 9.8 M OSM roads and 55.6 k hospitals plus the WorldPop raster. Central Guwahati: 1,364,145 people, 2,582.79 km road, 73 named hospitals, 332 km², in 0.73 s.
  • Incident reporting — field reports scored against real spatial context and against the platform's own predictions, with a derived priority that can raise but never lower the reporter's own severity.
  • Mobile app — Expo React Native, responder and citizen roles, offline-first, with hazard-avoiding routing over the real road graph (5.05 km across Guwahati, detouring to 6.57 km when a flood alert crosses the corridor).

146 backend tests pass.

Repository layout

models/
  flood/          Flood inundation segmentation (Sentinel-1 SAR, ResNet-34 U-Net)
  drought/        Drought forecasting (IMD rainfall, SPI-3 LSTM)
  landslide/      Landslide susceptibility (XGBoost)
  damage/         Damage assessment (vision LLM over pre/post pairs)
  misinformation/ Fake news detection (MuRIL + debunk agent)
backend/          FastAPI serving the models, impact layer and mobile API
db/               PostGIS schema, OSM/WorldPop ingestion, static data exports
frontend/         Command dashboard (React, Tailwind, MapLibre, Recharts)
mobile/           Field and citizen app (React Native / Expo, MapLibre)
datasets/         raw training data (not in git, ~3 GB)

Each model directory has its own README with data provenance, decisions, and limitations.

Running it

# Impact layer: PostGIS, then roads/hospitals and the population raster
docker compose up -d postgis            # or: bash db/setup_local.sh
python db/ingest_osm.py                 # 9.8M roads, 55k hospitals
python db/download_worldpop.py          # ~780 MB, stays a file on disk

# API
export CLIMAITE_DATABASE_URL="postgresql://climaite@127.0.0.1:55432/climaite"
uvicorn app.main:app --port 8000 --app-dir backend

Do not put .pgdb/bin on PATH in the shell that starts the API. The bundled Postgres ships its own PROJ database, and rasterio picks it up ahead of pyproj's: every prediction then fails with "The EPSG code is unknown … DATABASE.LAYOUT.VERSION.MINOR = 4 whereas a number >= 6 is expected". The API still starts and health still passes, so the failure only appears when someone runs a prediction — which on a demo means mid-demo. Use db/setup_local.sh or a subshell for the database tooling, and launch the API from a clean shell.

# Dashboard
cd frontend && npm install && npm run dev

# Mobile app. The phone cannot reach 127.0.0.1 on this machine, so serve the API on
# 0.0.0.0 and point the app at this machine's LAN address.
python db/seed_mobile.py                # safety stations + NGO allowlist
cd mobile && npm install
EXPO_PUBLIC_API_BASE_URL=http://<your-lan-ip>:8000 npx expo start

See db/README.md for the impact layer, incidents and routing, frontend/README.md for the dashboard, and mobile/README.md for the phone app.

Why these sensors and datasets

No single sensor answers every question, and the pairing is deliberate:

  • SAR (Sentinel-1) sees through monsoon cloud and works at night, which is exactly when floods happen — but cannot resolve individual buildings.
  • Optical gives the resolution to assess a building, and is useless under cloud.
  • Elevation and rainfall climatology are slow-changing, good for susceptibility, and say nothing about right now.
  • Social text is the only channel that carries misinformation.

Verified sources: Sen1Floods11 hand-labelled subset (446 chips) for flood; IMD Pune 0.25° daily gridded rainfall, 1901–2024, for drought and landslide (Pai et al. 2014, MAUSAM 65(1)); GSI Bhukosh plus the NASA Global Landslide Catalog (25,401 merged mapped landslides) for susceptibility; xBD via xView2.org for damage; IFND for misinformation.

Two provenance rules that matter. Sensor type must match between training and inference — training on SAR and inferring on optical fails at the pixel level. And Bhoonidhi is an inference-time source for real Indian imagery only, never a training set.

Architecture

Target deployment on AWS: CloudFront in front of static assets and map tiles; an ALB onto an EC2 auto-scaling group for the API; RDS PostgreSQL with PostGIS holding flood polygons, susceptibility scores and damage polygons as real geometry; ElastiCache Redis for hot tiles and rate limiting; SQS with dead-letter queues for preprocessing and inference jobs; three S3 buckets (raw data, versioned weights, processed outputs); all inference on SageMaker — async GPU endpoints for the CNNs, serverless for XGBoost, real-time for the classifier; SNS fanning out to Twilio SMS and Firebase push.

PostGIS is the piece that turns a model output into an operational number: a spatial join against population, roads and infrastructure is what makes "332 km² flooded" into "1.36 million people and 73 hospitals affected". It is built and running locally; the rest of the architecture is specified, not deployed.

What we got wrong, and how we know

The measurement discipline below is the part of this project we would defend hardest. Every item is a claim we made, tested, and had to withdraw.

A metric that improves when you remove a known defect was measuring the defect. The landslide model reported AUC 0.788 and scored central Mumbai — 0.9° of slope, 2 m above sea level — as the single most landslide-prone location tested. Every training negative came from ground steeper than 8°, so it had never seen flat ground labelled stable. Fixing that dropped AUC to 0.701 and raised the slope-only baseline from 0.594 to 0.677, cutting the apparent margin from +0.194 to +0.024. Both moves are the fix working: the old margin was inflated by a negative set that excluded flat ground. An independent check moved the opposite way — real GSI events above the surface median went 75.4% → 85.4% — so the model that scores 0.087 worse on AUC is the better one.

Ruling out extrapolation is not the same as ruling out error. Guwahati (2.06°) still scores 0.703 "high". We explained that twice and were wrong twice: not a sampling gap (42.6% of flat negatives exceed Guwahati's own 1,700 mm rainfall) and not a stale threshold (that class scores a median 0.024, only 0.6% above 0.6). All 14 of Guwahati's features sit within 1.3 SD of the flat-negative mean. It is a genuine isolated error, 1 in 19 flat Indian cities, that nothing in the inputs can flag — so the API marks the combination of flat ground and a high score as suspect, rather than warning on all flat ground and being wrong 18 times out of 19.

A correlation matching the truth's own correlation is not evidence of a shortcut. The flood model's output correlates −0.82 with scene brightness, which looked like proof it was reading brightness instead of finding water. But brightness correlates −0.82 with the truth, so a perfect model shows the same number. An intervention settled it: uniformly brighten a chip, leaving the truth untouched. The baseline shifts −0.416 per unit, yet its error correlates only −0.098 with brightness. Per-chip normalisation removed the capability exactly as designed (+0.018, invariant) and made the model worse on every axis. It was real signal, not a shortcut.

Check what a sample covers before concluding a model missed something. The flood model was recorded as reading 0.7% water at Jorhat and blamed for missing a worst-hit district. A 512² Sentinel-1 chip covers 26 km²; Jorhat is ~2,850 km². Tiling a 7×7 grid on the same scene finds 81% water. Charaideo made the point twice — 3×3 found nine dry chips and looked like a real miss until 7×7 found 84.2%. Three earlier hypotheses for that "miss" (orbit geometry, weak labels, the brightness shortcut) were all investigated and all wrong, because the measurement was at fault rather than the model.

Segmentation metrics on sparse masked labels must be accumulated dataset-wide. 16 of 67 flood validation chips are entirely no-data or contain no water, so intersection and union are both zero and a per-chip IoU scores them a vacuous 1.0.

A zero and an unknown are different operational facts and look identical as numbers. A flood zone with no hospitals and one whose hospital layer failed to load both report 0, and an officer reading the second as the first does not dispatch. Every impact figure carries an availability flag and a plain-language reason.

Degrees are not a unit of distance. ST_Area on EPSG:4326 returns square degrees — 0.004 for a 44 km² zone, plausible enough to ship. India spans UTM 42N–47N so no single projected CRS is right everywhere; geography matched the correct UTM zone within 0.1% where India-specific EPSG:7755 was 3.7% low and Web Mercator 25% high. Likewise, clip before you measure: ST_Length over roads that merely intersect a zone counted 704 m where the intersection was 234 m.

Colour-blindness must be checked across the whole palette at once, not pairwise. A "likely false" swatch passed against damage in isolation and collapsed into the landslide colour at dE 0.6 under tritanopia. db/check_palette.py now gates every pair.

Known limitations

  • No authentication anywhere. Acceptable for a local demo, not for deployment. The NGO donation allowlist stops a casual claim, not a determined one, and the app says so.
  • Landslide gain over a slope map is +0.034. Real but thin; the missing causative factors (lithology, soil, distance to drainage and roads, LULC) are the likely reason.
  • Flood over-predicts water on sparse scenes — 1.5× on bright chips, 2.2× on dark-but-dry — and a district readout needs a tile-grid aggregate plus a dry-season baseline to difference against. Neither is built.
  • Drought is meteorological, not agricultural. Soil moisture remains unresolved: SMAP starts in 2015 and truncates a joint record with IMD; ERA5-Land reaches further back but is model output rather than observation.
  • Damage assessment is zero-shot LLM inference, not a trained model. No Indian equivalent of xBD exists, so it is benchmarked on xBD and demonstrated separately on manually sourced Indian imagery.
  • Probabilities are not calibrated to real prevalence. Landslide training is balanced 1:1 while real prevalence is far lower, so a 0.7 ranks a location rather than stating a 70% chance.
  • The misinformation model's 138-sample disaster subset scores 1.000 on every metric, and we audited it rather than quoting it. The cause is not a train/test overlap — no row or duplicate crosses the split. IFND's fake entries are fact-checker headlines about misinformation, so the label is written into the text: "fact check:" appears in 23 of 43 fake test rows and 0 real ones. A keyword regex with no model scores 0.935 accuracy and 1.000 precision on the same rows, which is the baseline that 1.000 has to be read against. The general validation figure (F1 0.970, n=5,592) is the one in the table above. Two standing tests now assert the leak is present so it cannot be re-described as clean. The deeper consequence: a real social-media claim carries none of those markers, so six fabricated wire-style claims were all labelled credible at ≥0.979 confidence and none escalated — see models/misinformation/README.md.
  • Regional-language performance is unmeasured. hindi_validation_measured is false, so the MuRIL choice is not yet justified by a number despite regional coverage being part of the pitch.

Data and weights are not in git

datasets/ is ~3 GB of imagery and gridded climate data; weights are ~90 MB binaries. Both are excluded by .gitignore — weights belong in versioned S3 per the architecture. Each model README documents how to obtain its data and reproduce training.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages