Skip to content
ayush00gitPublic

About

Aahat (आहट): satellite early warning for glacial lake outburst floods in Himachal Pradesh, using Sentinel-2 and Copernicus DEM on AWS, with Hindi alerts for villages downstream.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

72 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Aahat (आहट)

A satellite watch on Himalayan glacial lakes and the valleys below them, starting with Himachal Pradesh. Built for Environmental Hacks (WeMakeDevs x AWS), Heat and Water track.

When a glacial lake bursts (a glacial lake outburst flood, GLOF), the water goes down a valley where people live beside the river. Aahat measures 22 such lakes in and upstream of Himachal Pradesh from Sentinel-2 imagery, ranks them with a score whose every factor is shown with its source, estimates where a flood from each would go and how soon it would reach each village, and gives a villager a plain answer in Hindi: is my village in a flood path, from which lake, how many minutes, and what to do. District officials get the same data on a dashboard, with the evidence behind each number and an alert tool that warns the nearest villages first.

Live link
Villager app (Hindi first, installable) https://aahat.ayyush.dev/
Officials' dashboard https://aahat.ayyush.dev/officials/
API https://aahat.ayyush.dev/api/lakes (all routes in API.md)

Every flood figure in Aahat is a screening estimate from a 30 m elevation model, not a hydraulic model. Aahat does not detect a burst as it happens and does not predict when a lake will burst. The full list is under Limits.

What it does

  • Measures each lake every season. Lake outlines and areas for 2017 to 2026 come from Sentinel-2 L2A scenes read in place from AWS Open Data. Each yearly record names the scenes it was mapped from.
  • Scores each lake, and shows why. score = 100 × size × likelihood, from five measured factors, each with its value, rule and published source. Today the two highest are Samudra Tapu (62.0) and Gepang Gath (61.6), both "very high"; 5 lakes are "moderate" and 15 "low" (live API, 10 Oct 2026).
  • Estimates the flood below each lake. A flow path up to 150 km long over the Copernicus DEM, an expected and a severe scenario, the flood depth every 250 m, a flood corridor, and an arrival time at every settlement, bridge, road, hydro project, school and clinic that OpenStreetMap maps near the path.
  • Warns the nearest villages first. An alert goes to subscribers in arrival order, each with their own minutes to arrival, as a Hindi voice message (Amazon Polly), a text message (Amazon SNS) and a browser notification (web push). Officials can run it as a dry run that plans and voices the alert and sends nothing.
  • Watches heat and rain. For each lake the API reads a three-day forecast from Open-Meteo and raises a weather level when heavy rain is forecast, or when the forecast maximum temperature is 5 C or more above the mean of the past three days (fast melt). Heat and rain are the two inputs this trigger watches, which is where the project meets the Heat and Water track.
  • Looks for a lake that has emptied, and for a newly blocked river. At each refresh the newest clear scene is compared with the season outline (a drop of more than 30% raises a dry-run alert for officials), and the first 60 km of river below each lake is scanned for new standing water.
  • Answers questions in Hindi or English. The assistant is Claude reading this project's own API through tools. Every number in an answer is checked against what the tools returned; an answer that fails the check twice is replaced by a fixed template built from the data.
  • Runs a new lake on request. An official gives a name or coordinates; the server maps that lake's yearly areas, scores it and stores the files.

Search covers 19,803 named settlements in and around Himachal Pradesh, in English or Devanagari.

Try it in two minutes

  1. Open https://aahat.ayyush.dev/ and search for Thirot (or type थिरोट), a village in Lahaul and Spiti district. One lake threatens it: Gepang Gath, about 64 km up the river. The village is "at risk" (amber), not "in flood path" (red): it is not flooded in the expected scenario, only in the severe one or within 10 m above the flood level. The fast arrival estimate is about 106 minutes. Below that the app lists four more lakes whose floods would pass nearby without reaching the village. The map shows the lakes and the flood path.
  2. On the same page, ask a question, for example "सबसे खतरनाक झील कौन सी है?" (which lake is the most dangerous?). Answers typically take 7 to 20 seconds. Compare the numbers with step 4.
  3. Search for Hamirpur (two places share the name; the district tells them apart). Neither is in a mapped flood path, and the app says so as "not covered", which is not the same as safe.
  4. Open https://aahat.ayyush.dev/officials/ and pick Gepang Gath in the list.
    • Risk: the score written out, each factor with its value, rule and source link, and the replay of the score season by season.
    • Downstream exposure: the two peak discharges with their formulas, and every exposed place nearest first.
    • Data & evidence: per season, the area, coverage and the Sentinel-2 scenes used, with a link to view that imagery in Copernicus Browser.
  5. Check any number against the API: curl https://aahat.ayyush.dev/api/lakes/gepang-gath.
  6. The Alerts tab runs a simulated burst. It needs the officials' token, which is not published here; it is available to judges on request. Dry run is ticked by default: the server plans, logs and voices the alert and sends nothing.

Architecture

flowchart TD
  subgraph SRC["Open data sources"]
    S2["Sentinel-2 L2A COGs<br/>Earth Search STAC, AWS Open Data"]
    DEM["Copernicus DEM GLO-30<br/>AWS Open Data"]
    RGI["RGI 7.0 glacier outlines<br/>GLIMS"]
    OSM["OpenStreetMap<br/>Geofabrik extract"]
    OM["Open-Meteo forecast"]
  end

  subgraph EC2["One EC2 instance, ap-south-1"]
    PIPE["Python pipeline<br/>systemd timer, every 2 days"]
    DISK["JSON and GeoJSON files<br/>written to the server disk"]
    API["Go API"]
    CADDY["Caddy, HTTPS"]
    WORK["Research worker<br/>one job at a time"]
  end

  subgraph USERS["Users"]
    VILL["Villager PWA<br/>Hindi first"]
    DASH["Officials dashboard"]
  end

  S3["Amazon S3<br/>published data, public to read"]
  POLLY["Amazon Polly<br/>Hindi voice"]
  SNS["Amazon SNS<br/>SMS and ops email"]
  PUSH["Web push, VAPID"]
  CLAUDE["Claude<br/>Anthropic API"]

  S2 --> PIPE
  DEM --> PIPE
  RGI --> PIPE
  OSM --> PIPE
  PIPE --> DISK
  DISK -- "sync after each refresh" --> S3
  S3 --> API
  DISK -. "fallback" .-> API
  OM --> API
  API --> CADDY
  CADDY --> VILL
  CADDY --> DASH
  API -. "spoken warnings" .-> POLLY
  API -. "SMS" .-> SNS
  API -. "notifications" .-> PUSH
  API -. "ask and job summaries" .-> CLAUDE
  API -- "job file" --> WORK
  S2 --> WORK
  WORK -. "results" .-> S3
  PIPE -. "failure email" .-> SNS
Loading

The pipeline, the API, both web apps and the research worker run on one t4g.small instance in ap-south-1 (Mumbai), created and updated with the AWS CLI scripts in infra/ec2/.

  • A systemd timer runs the pipeline every 2 days (refresh.sh): new scenes for the current season, then risk, downstream, the index, the place list, the barrier scans and the drain checks.
  • When a refresh finishes, the files are synced to an S3 bucket (and once a day besides). So new Sentinel-2 scenes, which arrive on AWS Open Data about every 5 days per lake, flow as: Open Data → pipeline on EC2 → S3.
  • The Go API serves the data from S3 (prefix data/, cached in memory for 10 minutes) and falls back to the copy on the server's disk if S3 cannot be reached. It listens on localhost; Caddy terminates HTTPS and serves the two static web apps.
  • The data/ prefix is public to read, as open data: start at data/lakes/index.json and data/README.txt (layout, sources, terms). The subscriptions and alert log (state/) and researcher results (research/) are in the same bucket and stay private. The bucket is versioned.
  • The API writes a researcher job as a file; a systemd path unit starts the worker, which runs the pipeline for that lake and copies the results to S3 under research/<job_id>/.
  • A failed unit (API, refresh or backup) emails its last 30 journal lines through an SNS topic.
AWS service What Aahat uses it for
Registry of Open Data on AWS Sentinel-2 L2A COGs (found through Earth Search STAC, read with HTTP range requests) and the Copernicus DEM GLO-30
Amazon EC2 One t4g.small (2 vCPU ARM, 2 GB) running the pipeline, API, web apps and research worker, with an Elastic IP
Amazon S3 Versioned bucket: the published data the API serves (data/, public to read), and privately the API state backup (state/) and researcher job results (research/)
Amazon Polly Hindi and Indian-English speech (voice Kajal, neural) for alerts and assistant answers, played in the app
Amazon SNS SMS alerts (sandbox: verified numbers only) and the ops topic that emails unit failures
AWS IAM An instance role, so the server calls Polly, SNS and S3 with no stored keys
Amazon Bedrock Fallback for the assistant and researcher jobs (Converse API) when the Anthropic API key is missing

How the numbers are made

This is the short version. The full method, with every threshold and the reasons for it, is in docs/methods.md.

How lake mapping works

For each lake and each post-monsoon season (15 Aug to 31 Oct), the pipeline picks the Sentinel-2 scenes that are clearest over the lake, masks cloud, snow, ice and terrain shadow, and calls a clear pixel water when NDWI > 0.3. A pixel is water if it was water in at least half of its clear observations. The lake is the connected water body at the lake's seed point. Each yearly area carries a shoreline uncertainty (perimeter × 5 m) and a coverage figure; below 90% coverage, or with fewer than two clear scenes, the year is marked partial. Details: docs/methods.md.

How the hazard score works

score = 100 × size × likelihood, both 0–1, so a small pond in steep terrain can't outrank a large lake, and size alone can't put a quiet lake first. Every factor is a raw number with units, turned into 0–1 by a stated linear rule; the UI shows value, rule, score, weight, note and source for each.

Factor Group Measured as 0 → 1 Source of threshold
Water volume size Huggel et al. 2002, V = 0.104·A^1.42, from the latest full-coverage area 10⁵ → 10⁸ m³ (log) Kougkoulos et al. 2018 classes at 0.33 / 0.67
Lake growth likelihood (¼) Theil–Sen trend over full-coverage seasons, ×5; zero unless the change beats 2× measurement uncertainty 0 → 25% per 5 yr CWC 2024 top class
Steepness below outlet likelihood (¼) mean gradient of the first 1 km of flow path below the spill point (DEM) 0 → 10° Fujita et al. 2013 steep-lakefront 10°
Ice/rock fall sources likelihood (¼) area of > 30° slopes in the lake's catchment whose line to the lake is > 14° 0 → 0.5 km² Allen et al. 2016 (Himachal) definition, Rinzin et al. 2021 high class
Distance to glacier ice likelihood (¼) nearest Randolph Glacier Inventory 7.0 outline (c. 2000; includes debris-covered tongues) 500 m → 0 m Rinzin et al. 2021, CWC 2024

Levels: low < 20 ≤ moderate < 40 ≤ high < 60 ≤ very high.

No hindsight: the replay scores season Y using only seasons ≤ Y and the 2011–2015 DEM; a unit test checks that a later jump can't change an earlier score.

It is a screening score for deciding where to look, not a probability that a lake will burst.

How the downstream estimate works

  1. Path: steepest descent over the Copernicus DEM from the spill point, up to 150 km.
  2. Breach peak, two scenarios: expected = Evans 1986 (0.72·V^0.53), which lands closest to NRSC's HEC-RAS dam-breach peak for Gepang Gath; severe = the larger of that and Huggel et al. 2002 (0.00077·V^1.017). For lakes under roughly 0.1 km² the two scenarios are the same flood.
  3. Downstream decay: peak × exp(−km / 42.4 km), fitted to the peaks NRSC report along the valley for both lakes and to South Lhonak 2023 (Sattar et al. 2025).
  4. Flood level: Manning normal depth (n = 0.06, as NRSC use below Sissu) on a DEM cross-section every 250 m.
  5. Corridor: DEM cells below the flood level, connected to the river and no wider than the water reached on the nearest cross-section.
  6. Arrival: distance ÷ flood-front speed, 10 m/s (fast) to 8 m/s (expected); South Lhonak 2023 averaged about 8 m/s over 67.5 km.
  7. Exposure: OpenStreetMap. An asset is in flood path if it is flooded in the expected scenario, at risk if only in the severe one or within 10 m above the flood level near the corridor (300 m). Flooded means in the corridor with ground below the flood level there, so a flooded place always has a negative height above the flood, and no other place does.

Check against NRSC's HEC-RAS modelling (Gepang Gath, Samudra Tapu reports on Bhuvan): NRSC's peak discharge falls between our two scenarios at every benchmark site. Its flood depth does so at three of the five: at Sissu below Gepang Gath NRSC's 21.5 m exceeds our 17.5 m severe depth, and at Tandi below Gepang Gath NRSC's 10.4 m is under our 11.8 m expected depth. Our depths are the median of the stations within 1 km of the site, because normal depth on a 30 m DEM varies by several metres from one cross-section to the next.

Site NRSC peak, depth Ours expected → severe
Gepang Gath → Sissu, 11 km 9,378 m³/s, 21.5 m 5,837, 7.4 m → 30,947, 17.5 m
Gepang Gath → Tandi, 31 km 4,123 m³/s, 10.4 m 3,642, 11.8 m → 19,309, 25.5 m
Samudra Tapu → Batal, 17.8 km 15,692 m³/s, 17.1 m 6,811, 14.2 m → 48,170, 32.8 m
Samudra Tapu → Khoksar, 67 km 6,665 m³/s, 12.9 m 2,132, 5.6 m → 15,077, 14.8 m
Samudra Tapu → Tandi, 110 km 3,275 m³/s, 9.4 m 773, 3.5 m → 5,469, 10.6 m

NRSC reports: Gepang Gath, Samudra Tapu. NRSC give "Sissu in just 21 minutes" for Gepang Gath; our fast–expected arrival there is 18–23 min.

All of it is a screening estimate: normal depth on a 30 m DEM with no river bathymetry, empirical peaks with large scatter, and only what OpenStreetMap maps.

Barrier lakes, sudden drainage and weather

  • New barrier lakes: new water on the river line (at least 0.02 km² and 60 m wide) in the last 20 days that was not water the year before. Replayed on Sedongpu (Yarlung Tsangpo), 31 Oct 2018, it finds three candidates on the lake behind the debris dam that formed on 29 Oct (SANDRP). A reservoir refilling looks the same, so a candidate within 12 km of a mapped dam is tagged reservoir_level_change; the one candidate in today's scans, below Lam Dal, is of that kind.
  • Sudden drainage: drained only if the area on the newest clear scene is more than 30% and 3× the combined shoreline uncertainty below the season outline, with at least 90% of the outline observed. Cloud and shadow are unknown, never dry. Lakes under 50,000 m² are not checked, and a lake freezing over is not flagged.
  • Weather trigger: high at 50 mm of precipitation on a forecast day or 100 mm over the forecast days; elevated at 20 mm, 40 mm, or a forecast maximum temperature 5 C or more above the mean of the past 3 days. These thresholds are our own screening choice, not a published standard, and the level does not change the risk score.

Details for all three: docs/methods.md.

Repository layout

Path What Language
pipeline/ Sentinel-2 water mapping, lake area time series, terrain, risk, downstream routing, barrier and drain checks Python
api/ HTTP API, weather trigger, assistant, alert dispatcher, researcher jobs Go
web/villager/ Villager app, Hindi first, installable PWA TypeScript, Preact, MapLibre
web/dashboard/ Officials' dashboard TypeScript, Preact, MapLibre
infra/ec2/ Provisioning and deploy scripts, systemd units, Caddy config Bash, AWS CLI
docs/ Methods in full
API.md The HTTP API with examples

The lake catalogue is pipeline/src/aahat/data/lakes.json: 22 lakes, each with its seed point, district, basin and the source it was taken from.

Run it locally

Pipeline quick start

cd pipeline
uv sync
uv run aahat series --lake samudra-tapu --years 2017-2026 --quicklook -v   # or --lake all
uv run aahat summary                                                        # table of every lake x year
uv run aahat discover --lat 32.50 --lon 77.20 --radius 5000 --year 2025    # find water bodies around a point
uv run pytest -q

Outputs land in pipeline/out/lakes/<lake-id>/: series.json (yearly areas with uncertainty and data quality), <year>.geojson (lake outline), and <year>.png quicklooks with --quicklook. summary writes out/lakes/index.json for the API and maps. Then, in order: uv run aahat risk --lake all, uv run aahat downstream --lake all, and uv run aahat places. The other commands (barrier, drain, sweep) and every output file are described in docs/methods.md.

API

cd api
go run ./cmd/server -data ../pipeline/out     # local, listens on :8080
go vet ./... && go test ./...                 # tests use fixtures and fakes, never the network

Environment variables for voice, SMS, push and the assistant are in api/README.md. Anything not configured logs instead of sending.

Web apps

cd web/villager        # or web/dashboard
npm install
npm run dev            # http://localhost:5173, /api proxied to the local API
npm run build          # type-check + vite build -> dist/

The villager app proxies to 127.0.0.1:8080 and the dashboard to 127.0.0.1:8081 by default; set AAHAT_API_TARGET to change either. See each app's README.

Server

cd infra/ec2
./provision.sh                 # key pair, security group, IAM role (Polly + SNS), t4g.small, Elastic IP
./deploy.sh                    # build + ship API, web apps and pipeline results; restart services
./deploy-pipeline.sh           # ship the pipeline + refresh timer (runs on the server every 2 days)

The rest (SMS, ops alerts, the data bucket, restore, teardown) is in infra/ec2/README.md.

Data sources and attribution

Data Used for Source
Sentinel-2 L2A (Copernicus, ESA / EU) Lake outlines, barrier and drain checks COGs via Earth Search (AWS Open Data, us-west-2), read in place with HTTP range requests
Copernicus DEM GLO-30 Terrain shadow, spill point, flow path, flood levels AWS Open Data
Randolph Glacier Inventory 7.0 Distance to glacier ice GLIMS WFS
OpenStreetMap (© OpenStreetMap contributors, ODbL) Settlements, roads, bridges, hydro projects, schools, clinics, dams, district boundaries, lake seed points where named Geofabrik northern-India extract, Overpass elsewhere
Open-Meteo Weather outlook and trigger open-meteo.com
NRSC (ISRO) GLOF reports Benchmarks for peak discharge, depth and arrival; not an input Gepang Gath, Samudra Tapu

The dashboard's map also offers Esri World Imagery as a base layer.

Limits

  • Screening, not hydraulics. Flood depth is Manning normal depth on 30 m DEM cross-sections with no river bathymetry and no hydrodynamic routing. Peak discharge comes from empirical relations with large scatter.
  • Depth agrees with NRSC at three of five sites, not five. See the table above: NRSC's depth is above our severe depth at Sissu and below our expected depth at Tandi, both below Gepang Gath.
  • No real-time burst detection. Sentinel-2 revisits every ~5 days and cloud hides lakes, most of all in the monsoon. The pipeline runs every 2 days. The drain check can show that a lake has emptied; it cannot say so while the flood is still in the valley.
  • Arrival times assume fixed flood speeds (10 m/s and 8 m/s). A real flood front speeds up and slows down.
  • The risk score is not a probability that a lake will burst, and the weather level does not change it.
  • The weather thresholds are our own screening choice, not a published standard.
  • The drain check skips lakes under 50,000 m² (8 of the 22 today) and lakes that are freezing over.
  • The barrier scan misses narrow lakes (under about 60 m wide) and cannot tell a refilling reservoir from a new lake except by distance to a mapped dam.

What comes next

  • A statewide lake inventory. aahat sweep already finds large high-altitude lakes in fixed windows; nine of the catalogue's lakes came from it.
  • SMS sender registration (DLT) for India, and voice calls.
  • In-situ sensors. The signed webhook POST /webhook/sensor already exists; no sensor is connected to it.

Team

Ayush (@ayush00git), with Claude as coding partner.

About

Aahat (आहट): satellite early warning for glacial lake outburst floods in Himachal Pradesh, using Sentinel-2 and Copernicus DEM on AWS, with Hindi alerts for villages downstream.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages