Methodology

The numbers in this app are simulated. This page documents the method the app implements and the pipeline it is designed to run on β€” see Data Provenance below for exactly which values are measured and which are generated.

1. Lake detection

Glacial lakes are delineated from Landsat Surface Reflectance imagery using the Modified Normalized Difference Water Index (MNDWI). A 2000–2024 record spans three sensors: Landsat 5 TM and 7 ETM+ for 2000–2012, Landsat 8 OLI from 2013, and Landsat 9 from late 2021. Sentinel-2 MSI (10 m) is used from 2016 onward on the Change Detection page.

NDWI = Green βˆ’ NIRGreen + NIR
MNDWI = Green βˆ’ SWIRGreen + SWIR

Threshold: pixels with MNDWI > 0.2 are classified as water.

2. Hazard scoring

FactorMax scoreNotes
Dam type40Moraine=40, Ice=30, Bedrock=10
Area growth rate25Capped at 0.05 kmΒ²/yr = 25 pts
Downstream slope20Capped at 35Β° = 20 pts
Distance to settlement15Inverse linear; 0 km = 15 pts, β‰₯80 km = 0 pts

Every non-dam component floors at 0: a shrinking lake or a negative slope contributes no hazard points, it never subtracts from the dam-type baseline.

3. Data sources

DatasetProviderResolutionUseIn shipped data?
Landsat 5/7/8/9 SRUSGS / NASA30 mLake delineation (MNDWI)No β€” pipeline only
Sentinel-2 MSIESA10 mRecent area measurementsNo β€” needs fetch_sentinel.py
Copernicus DEM GLO-30ESA / Copernicus30 mDownstream slopeNo β€” slopes are simulated
ICIMOD GLOF DatabaseICIMODβ€”Event catalogue for ML trainingEvents yes, attributes unverified
WorldPop Nepal 2020WorldPop / Univ. of Southampton100 mPopulation exposureYes
OpenStreetMapOSM contributorsβ€”Building footprintsYes

4. Data provenance

Which numbers on this site are measured, and which are generated for demonstration:

ValueSource
Lake names, coordinates, basin, district, elevationReal β€” published lake inventories
Lake area 2000–2024Simulated β€” data/generate_data.py
Area growth rateSimulated β€” data/generate_data.py
Dam typeSimulated β€” random draw, weighted toward moraine
Downstream slope, distance to settlementSimulated β€” random draw
Hazard score and risk classComputed from the simulated inputs above
Sentinel-2 change detection cacheDerived from the simulated series (data/create_demo_cache.py)
GLOF event catalogueReal events, unverified attribute values; HKH-wide, not Nepal-only
ML probabilities and climate projectionsComputed from the simulated inputs above
Population and building countsReal β€” WorldPop 2020 (100 m) and OpenStreetMap
Flood corridors8 digitised from valley topography; 17 synthetic centroid paths

Because the hazard inputs are simulated, this site carries no validation against observed GLOF events β€” a scoring method built on generated slopes and dam types cannot be tested against real outcomes. Validation becomes meaningful once a real inventory is loaded via data/fetch_icimod.py.

5. Google Earth Engine script

/**
 * Google Earth Engine Script β€” Nepal Glacial Lake Detection
 * Detects water bodies in the Nepal Himalaya using Landsat 8 SR + SRTM elevation.
 *
 * Instructions:
 *   1. Open https://code.earthengine.google.com/
 *   2. Paste this script and click Run.
 *   3. The export task will appear in the Tasks panel β€” click Run to export to Drive.
 */

// ── 1. Define Nepal bounding box ──────────────────────────────────────────
var nepal = ee.Geometry.Rectangle([80.0, 26.3, 88.2, 30.5]);

// ── 2. Load Landsat 8 Surface Reflectance Collection 2 ───────────────────
var l8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
  .filterBounds(nepal)
  .filterDate('2013-01-01', '2024-12-31')
  .filter(ee.Filter.lt('CLOUD_COVER', 20))
  .select(['SR_B3', 'SR_B6'], ['Green', 'SWIR1']);  // bands for MNDWI

// ── 3. Scale reflectance values ───────────────────────────────────────────
function applyScaleFactors(image) {
  var opticalBands = image.select(['Green', 'SWIR1']).multiply(0.0000275).add(-0.2);
  return image.addBands(opticalBands, null, true);
}
l8 = l8.map(applyScaleFactors);

// ── 4. Compute MNDWI per image ────────────────────────────────────────────
// MNDWI = (Green - SWIR) / (Green + SWIR)
function computeMNDWI(image) {
  var mndwi = image.normalizedDifference(['Green', 'SWIR1']).rename('MNDWI');
  return image.addBands(mndwi);
}
l8 = l8.map(computeMNDWI);

// ── 5. Build annual median composites ─────────────────────────────────────
var years = ee.List.sequence(2013, 2024);

var annualComposites = ee.ImageCollection(years.map(function(year) {
  var yearlyMed = l8
    .filter(ee.Filter.calendarRange(year, year, 'year'))
    .select('MNDWI')
    .median()
    .set('year', year);
  return yearlyMed;
}));

// ── 6. Create overall median MNDWI composite ──────────────────────────────
var mndwiComposite = annualComposites.median().rename('MNDWI');
print('MNDWI composite band info:', mndwiComposite.bandNames());

// ── 7. Threshold to produce water mask (MNDWI > 0.2) ─────────────────────
var waterMask = mndwiComposite.gt(0.2).rename('water');

// ── 8. Apply elevation filter (> 3500m using SRTM) ───────────────────────
var srtm = ee.Image('USGS/SRTMGL1_003').select('elevation');
var highElevMask = srtm.gt(3500);
var glacialWater = waterMask.updateMask(highElevMask);

// ── 9. Convert water pixels to vectors ────────────────────────────────────
var waterVectors = glacialWater.reduceToVectors({
  geometry: nepal,
  crs: glacialWater.projection(),
  scale: 30,
  geometryType: 'polygon',
  eightConnected: false,
  labelProperty: 'water',
  reducer: ee.Reducer.countEvery(),
  maxPixels: 1e10,
});

// ── 10. Filter by minimum area (> 0.01 kmΒ² = 10,000 mΒ²) ─────────────────
var filteredLakes = waterVectors.filter(
  ee.Filter.gt('count', 11)  // 11 pixels Γ— 900 mΒ²/pixel β‰ˆ 10,000 mΒ²
);

print('Detected lake count:', filteredLakes.size());

// ── 11. Add area property ─────────────────────────────────────────────────
var lakesWithArea = filteredLakes.map(function(feat) {
  var areaSqKm = feat.geometry().area().divide(1e6);
  return feat.set('area_km2', areaSqKm);
});

// ── 12. Visualise on map ──────────────────────────────────────────────────
Map.centerObject(nepal, 7);
Map.addLayer(mndwiComposite, {min: -0.5, max: 0.8, palette: ['brown', 'white', 'blue']}, 'MNDWI Composite');
Map.addLayer(glacialWater.selfMask(), {palette: ['00AAFF']}, 'Glacial Water Mask');
Map.addLayer(lakesWithArea, {color: 'red'}, 'Detected Lakes (> 0.01 kmΒ², > 3500m)');

// ── 13. Export to Google Drive as GeoJSON ─────────────────────────────────
Export.table.toDrive({
  collection: lakesWithArea,
  description: 'Nepal_Glacial_Lakes_2013_2024',
  fileFormat: 'GeoJSON',
  folder: 'GEE_Exports',
  fileNamePrefix: 'nepal_glacial_lakes',
});