q21·intermediate

After days of monsoon rain, is the hillside above my village about to slide?

landdisaster-responsehydrologypublic-health Datasets: 5 30–60 min

A landslide nowcast is NASA's best same-day guess at how dangerous the hillsides in an area are right now, given how much rain has soaked in. It doesn't watch the ground move. It takes the recent rainfall plus how steep and slide-prone the land is and turns that into a risk score for each ~1 km patch. Think of it as a daily "how primed is this slope to fail?" reading, not a prediction of the exact moment or spot.

After days of monsoon rain, is the hillside above my village about to slide?

A landslide nowcast is NASA’s best same-day guess at how dangerous the hillsides in an area are right now, given how much rain has soaked in. It doesn’t watch the ground move. It takes the recent rainfall plus how steep and slide-prone the land is and turns that into a risk score for each ~1 km patch. Think of it as a daily “how primed is this slope to fail?” reading, not a prediction of the exact moment or spot.

Which data to use, and how

Use this dataset: GPM IMERG (half-hourly Late) (short name GPM_3IMERGHHL). It’s NASA’s satellite rainfall product. It tells you how much rain has fallen over your slope in the hours and days before a decision, which is what triggers rain-driven landslides. It’s the easiest single layer to start with, and rainfall accumulation is the heart of the story.

When you’re ready for the actual hazard score, add the Global Landslide Nowcast (Global_Landslide_Nowcast). This is NASA’s LHASA model, which already combines rain with terrain into a 0–1 risk number for each grid cell.

Then do four steps (the runnable code further down does all of this; this is just the idea):

  1. Pick your area. A small latitude/longitude box around the village and slope, plus the dates you care about. The LHASA archive covers 2015 → Feb 2021, good for studying past monsoon seasons.
  2. Add up the rain. Sum the IMERG rainfall over your box across the storm window to get multi-day accumulation in millimetres. The more soaked the ground, the more primed the slope.
  3. Read the hazard score. Pull the LHASA nowcast value (p_landslide, a 0–1 probability) for your box on the day in question. Higher means more dangerous.
  4. Find the danger pixels. Flag the spots that are high-hazard, steep, and heavily rained-on. Optionally count how many people live beneath them.

That’s the whole method. Below, “How a scientist answers this” names the exact tools, and the Run it cell does it live on synthetic data so you can see each step work.

What you can find out

  • A daily landslide-hazard score for your area from the LHASA nowcast (p_landslide, 0–1) for any day in the 2015–2021 archive.
  • How much rain has piled up over the slope from IMERG, the trigger that primes the soil.
  • How steep the terrain is above the village (slope, computed from SRTM elevation). Steepness is one of LHASA’s own core ingredients.
  • Whether the rain is still climbing or easing in the hours before a decision, using the half-hourly Late rainfall run.
  • Which corners of a district are most exposed by overlaying the hazard score on steep, populated valleys.
  • Roughly how many people live in the high-hazard area. Overlay free WorldPop population, count people inside the high-probability pixels, and name the district with geoBoundaries (verified: ~1.67M people in the default Kaski box, district Kaski).

What it can’t tell you

  • The exact hour or exact spot a slope will fail. LHASA is a regional, ~1 km signal. It says “this neighbourhood is dangerous today,” not “this particular hillside will go at 3pm.” The grid cell is far bigger than one village’s slope.
  • Deep or earthquake-triggered slides. LHASA is built only for shallow, rain-triggered landslides. A slide set off by an earthquake, or one buried deep underground, is outside what it models.
  • Slides with no rain trigger. Failures caused by a river cutting into a bank, construction, irrigation, or melting snow won’t show up. The model only reacts to rainfall.
  • Casualties or property damage. You can estimate people exposed (the WorldPop overlay below), but actual deaths, injuries, and losses depend on building strength, timing, and warnings. These data layers don’t see any of that.

Gotchas to watch for

  • It’s a hazard nowcast, not a prediction. “High” means elevated risk, be careful. It’s not a guarantee a slope will move. Treat it like a fire-danger rating, not a verdict.
  • Satellite rain undercounts in the mountains. IMERG Late arrives with about a 12-hour delay and tends to underestimate rainfall in steep terrain (the Himalaya, the Andes) compared with ground gauges. The effect is called orographic under-bias: rain wrung out by mountains that the satellite misses. Real totals may be higher than it reports, so don’t treat a low number as “safe.”
  • The map is coarser than your hillside. The ~1 km hazard grid can’t resolve the single slope above one village, while the SRTM terrain is ~30 m. Use the fine-scale slope and aspect (which way the hill faces) to localize the danger within a hazard cell.
  • The archive stops in Feb 2021. This dataset is for studying past monsoon seasons. For today’s live hazard, use the LHASA portal (link in Sources), not this archive.
  • Two datasets share one name. LHASA ships two collections with the same short name, so the code passes version="2.0.0" to grab the current model and its p_landslide (a 0–1 probability, not a 0/1/2 category). Skip this and you may load the wrong one.
  • Local ground signs still win. Fresh cracks, tilting trees, suddenly muddy springs, and rumbling are faster and more reliable than any satellite product. And none of this replaces official evacuation orders.

The real-data code

The Run it cell above runs this method on synthetic data with no login. Below is the whole recipe against the real archive: search, open the nowcast / rain / terrain, sum the rain, read the hazard score, compute slope, flag the danger pixels, count who’s beneath them, and plot it. It needs a free Earthdata Login.

import earthaccess, numpy as np, xarray as xr
import requests, rasterio
from rasterio.windows import from_bounds
import geopandas as gpd
from shapely.geometry import Point
import matplotlib.pyplot as plt

earthaccess.login(strategy="netrc")

aoi = (83.5, 27.8, 84.5, 28.6)               # Kaski/Myagdi mid-hills, Nepal as (W, S, E, N)
rain_window    = ("2020-07-10", "2020-07-15")  # a deadly 2020 monsoon window in the LHASA archive
nowcast_window = ("2020-07-14", "2020-07-15")

# 1. LHASA daily landslide nowcast — 0–1 probability of a rain-triggered slide.
#    version="2.0.0" disambiguates the two collections sharing this short_name.
nowcast = earthaccess.search_data(short_name="Global_Landslide_Nowcast", version="2.0.0",
                                  bounding_box=aoi, temporal=nowcast_window)
nc = xr.open_dataset(earthaccess.open(nowcast[:1])[0])
p = nc["p_landslide"].sel(lat=slice(aoi[1], aoi[3]), lon=slice(aoi[0], aoi[2]))

# 2. IMERG half-hourly Late — sum the rain over the storm window (the trigger).
imerg = earthaccess.search_data(short_name="GPM_3IMERGHHL", bounding_box=aoi, temporal=rain_window)
rain = xr.open_mfdataset([earthaccess.open([g])[0] for g in imerg],
                         group="Grid")["precipitation"]        # mm/hr, lives in /Grid
rain_mm = (rain * 0.5).sum("time").sel(lat=slice(aoi[1], aoi[3]), lon=slice(aoi[0], aoi[2]))
rain_mm = rain_mm.transpose("lat", "lon")                      # IMERG stores lon-major
print(f"Peak {rain_window[0]}{rain_window[1]} rainfall in box: {float(rain_mm.max()):.0f} mm")

# 3. SRTM 30m DEM → slope. Mosaic the 1° tiles, then slope = arctan(|gradient|) in degrees.
dem_grans = earthaccess.search_data(short_name="SRTMGL1", bounding_box=aoi)
files = earthaccess.open(dem_grans)
import rioxarray
tiles = [rioxarray.open_rasterio(f).squeeze() for f in files]
dem = rioxarray.merge.merge_arrays(tiles).rio.clip_box(*aoi)
px = abs(float(dem.x[1] - dem.x[0])) * 111320 * np.cos(np.radians(float(dem.y.mean())))
dy, dx = np.gradient(dem.values.astype("float64"), abs(float(dem.y[1]-dem.y[0]))*111320, px)
slope_deg = np.degrees(np.arctan(np.hypot(dx, dy)))
print(f"Steepest slope in box: {np.nanmax(slope_deg):.0f}°")

# 4. Flag danger on the ~1 km hazard grid: high probability AND heavy multi-day rain.
#    (Slope is finer than the grid; carry it for the within-cell localisation below.)
p_aligned = p.isel(time=0).reindex_like(rain_mm, method="nearest")
danger = (p_aligned.values > 0.5) & (rain_mm.values > 100)
print(f"High-hazard cells (p>0.5 & rain>100mm): {int(np.nansum(danger))} of {danger.size}")

# 5. Who's exposed — free WorldPop population + geoBoundaries place name (no NASA login).
meta = requests.get("https://www.worldpop.org/rest/data/pop/wpic1km?iso3=NPL").json()
pop_url = next(f for f in meta["data"][-1]["files"] if f.endswith(".tif"))
open("npl_pop_1km.tif", "wb").write(requests.get(pop_url).content)   # ~1 MB
with rasterio.open("npl_pop_1km.tif") as src:
    win = from_bounds(*aoi, transform=src.transform)
    pop = src.read(1, window=win).astype("float64")
    pop[pop == src.nodata] = np.nan
adm = gpd.read_file(requests.get(
    "https://www.geoboundaries.org/api/current/gbOpen/NPL/ADM2/").json()["gjDownloadURL"])
district = adm[adm.contains(Point(83.98, 28.21))].iloc[0]["shapeName"]
print(f"VERDICT: {int(np.nansum(danger))} high-hazard cells over {district}; "
      f"~{np.nansum(pop):,.0f} people live in this box.")    # verified ~1.67M for this Kaski box

# Plot: rainfall accumulation with the high-hazard cells outlined.
fig, ax = plt.subplots()
rain_mm.plot(ax=ax, cmap="Blues", cbar_kwargs={"label": "rain (mm)"})
ax.contour(rain_mm.lon, rain_mm.lat, danger, levels=[0.5], colors="red")
ax.set_title(f"Rain + landslide hazard — {district}"); plt.tight_layout(); plt.show()

# Before you trust it: IMERG under-bias in steep terrain (gotchas) — compare with a ground gauge,
# and remember the ~1 km nowcast can't pin the one slope above the village.

Where the data comes from

Everything NASA here comes through one free login (Earthdata Login). The LHASA landslide nowcast and IMERG rainfall both live at the GES DISC archive. The SRTM elevation (SRTMGL1) comes from a different NASA archive (LP DAAC), but the same single login works for both. The optional exposure layers are free and need no login at all: WorldPop gridded population and geoBoundaries administrative boundaries (to name the district).

Sources

How a scientist answers this
Parameters
Daily rain-triggered landslide hazard probability p_landslide (0–1) from the NASA LHASA Global Landslide Nowcast (~1 km, 2015–2021 archive), driven by multi-day antecedent rainfall accumulation from GPM IMERG Half-Hourly Late (mm over 1–7 day windows). Terrain steepness is slope (degrees) computed from the SRTM 30 m DEM (a core LHASA susceptibility input); exposure is people inside high-hazard pixels via WorldPop (1 km), with the area named from geoBoundaries ADM2.
Method
Read the LHASA nowcast probability over the AOI, accumulate IMERG rainfall over rolling antecedent windows to gauge how primed the soil is, derive slope from the DEM, and intersect high-probability pixels with steep, populated terrain; sum WorldPop counts inside high-hazard pixels for exposure. LHASA combines a static susceptibility map (slope, geology, forest loss, road/fault distance) with a rainfall trigger.
Validation
Compare nowcast hazard days against any cataloged local landslide events and confirm the rainfall driver against an independent gauge or product; state that LHASA is a regional ~1 km hazard signal (shallow rain-triggered slides only), not a slope-specific or hour-specific failure forecast, and that IMERG underestimates orographic extremes.
In plain EnglishAdd up the recent rain over the steep slope above the village and read NASA's daily landslide-hazard map, then count how many people live in the most dangerous pixels — it flags elevated risk for the region, not the exact spot or hour a slope will give way.

Make it yours → Change the AOI box, the date in the 2015–2021 archive, the rainfall accumulation window, and the slope/probability thresholds used to flag high-hazard exposed pixels.

🧪 Virtual Mock Lab stand-in data · runs in your browser · no login

A safe place to practise the method on GPM_3IMERGHHL. The code is the real earthaccess workflow, but we feed it stand-in data shaped like the real product — so you can run it, change the numbers, and break it without an account. When you want the real data, use the recipe under “The real-data code” above, or download the notebook below.

editable · runs in your browser

Datasets used

Recipe ready · not yet run The recipe and the Virtual Mock Lab above are ready to use. We haven't yet run this question end-to-end on real data, so it has no verified answer yet — only the questions we've actually computed carry one. That's the honest line between a method and a result.