Was this region flooded after a recent storm?
Draw a rectangle, then check which collections cover it. Most NASA data is global, so a big box matches a lot.
-83, 35 → -82, 36 (Asheville NC (Hurricane Helene zone))Radar lets you see the ground from space even through thick storm clouds. The satellite sends down a microwave pulse and listens for the echo. Smooth, flat water sends almost nothing back, so it shows up dark. Rough land (trees, buildings, dry soil) bounces a lot back and shows up bright. A flood, then, is a new dark patch that wasn't there before the storm.
Was this region flooded after a recent storm?
Radar lets you see the ground from space even through thick storm clouds. The satellite sends down a microwave pulse and listens for the echo. Smooth, flat water sends almost nothing back, so it shows up dark. Rough land (trees, buildings, dry soil) bounces a lot back and shows up bright. A flood, then, is a new dark patch that wasn’t there before the storm.
Which data to use, and how
Use this dataset: OPERA RTC-S1 (short name
OPERA_L2_RTC-S1_V1). It’s pre-processed, “analysis-ready” radar from the Sentinel-1 satellite.
Someone has already done the hard cleanup steps, so you can open it and use it. The raw version
(Sentinel-1 GRD) needs real radar expertise to handle, so skip it as a
beginner. The reason to use radar at all is that it sees through clouds, and a storm
covers everything in cloud exactly when you need to look.
Then do four steps (the runnable code further down does all of this; this is just the idea):
- Pick your region, a latitude/longitude box around the storm-hit area, and two time windows: a few days before the storm, and the first days after it.
- Grab a “before” and an “after” radar image of that box from those two windows.
- Find the dark (water) pixels in each. Radar brightness is measured in decibels (dB), a log scale where more-negative means darker. Rule of thumb: anything darker than about −20 dB is smooth water.
- Subtract before from after. A pixel that is water now (after < −20 dB) but was dry before (pre > −15 dB) is new water. That’s your flood. Add up those pixels to get flooded area, and optionally overlay GPM IMERG rainfall to show how much rain fell.
That’s the 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
- How far the flood water spread, the flooded extent within 24–48 hours of the storm, because the radar sees straight through the cloud cover.
- What’s new water vs normal water. Comparing before and after separates the flood from the rivers and lakes that are always there.
- How much rain fell during the storm, by adding in IMERG rainfall data.
- Whether the ground was already soaked before the storm (its “antecedent saturation”), which primes a region to flood, from the LIS soil-moisture model (or SMAP).
- Which roads and buildings got hit, by laying the flood map over OpenStreetMap (OSM) road and building outlines.
What it can’t tell you
- How deep the water is. Radar tells you water is there, not how many feet of it. For depth you’d combine the flood map with an elevation model (a DEM, a map of ground height) and a hydraulic model (software like HEC-RAS or DELWAQ that simulates how water flows).
- Damage to individual buildings. The radar pixels are too coarse to judge house-by-house harm. That needs sharp commercial photos (companies like Planet or Maxar).
- Flooding you can’t see from above. Basements, tunnels, anything underground is simply invisible to a satellite.
Gotchas to watch for
- Radar sees roughness, not depth. It flags smooth surfaces as water (dB below −20). That’s usually right, but a smooth dry surface can fool it, and a rough surface won’t darken even when it’s underwater. So treat the map as “likely water,” not gospel.
- Cities are the hard case. Buildings act like mirrored corners that bounce radar straight back (a “corner reflection”), so a flooded street between tall buildings can still look bright. Radar alone under-counts urban flooding, so pair it with other data there.
- The satellite only passes every 12 days. With one Sentinel-1 satellite, your “after” image might land days off the flood’s peak, so you can miss the worst moment. Either accept the timing, or add faster commercial radar (ICEYE, Capella) if you need it.
- Always compare to a “before” image. Rivers and lakes are smooth too, so without a baseline they’ll show up as “flood.” The before/after subtraction is what removes those permanent water bodies.
- Start with the ready-made product. OPERA RTC-S1 is the recommended entry point precisely because the raw radar (GRD) requires SAR expertise to correct.
The real-data code
The Run it cell above runs the method on synthetic data (no login). Below is the whole recipe against the real archive: search, open the before/after radar, threshold the dark water, subtract to find new water, add up the IMERG rain, and plot it. It needs a free Earthdata Login.
import earthaccess, numpy as np, rasterio, xarray as xr
import matplotlib.pyplot as plt
earthaccess.login(strategy="netrc")
# Hurricane Helene impact in Asheville, NC, late September 2024
storm_aoi = (-83, 35, -82, 36)
pre_window = ("2024-09-15", "2024-09-25") # before the storm
post_window = ("2024-09-27", "2024-10-05") # right after
# 1. OPERA RTC-S1 — analysis-ready Sentinel-1 (avoids raw GRD complexity).
# Each granule ships one GeoTIFF per polarization; grab the VV file.
def vv_db(window):
grans = earthaccess.search_data(short_name="OPERA_L2_RTC-S1_V1",
bounding_box=storm_aoi, temporal=window)
urls = [u for g in grans for u in g.data_links() if u.endswith("_VV.tif")]
files = earthaccess.open(urls[:1]) # one overlapping scene is enough
with rasterio.open(files[0]) as src:
g0 = src.read(1).astype("float32") # linear backscatter (gamma-0)
g0[g0 <= 0] = np.nan # mask no-data before the log
return 10.0 * np.log10(g0) # convert to decibels (dB)
pre, post = vv_db(pre_window), vv_db(post_window)
h = min(pre.shape[0], post.shape[0]); w = min(pre.shape[1], post.shape[1])
pre, post = pre[:h, :w], post[:h, :w] # align overlapping footprints
# 2. Threshold + before/after subtraction: smooth water is radar-dark.
# New water (the flood) = dark now AND not-dark before -> removes rivers/lakes.
new_water = (post < -20.0) & (pre > -15.0)
px_km2 = (10.0 * 10.0) / 1e6 # RTC-S1 pixels are ~10 m
flood_km2 = float(np.nansum(new_water) * px_km2)
# 3. IMERG rainfall — how much rain actually fell over the storm window.
imerg = earthaccess.search_data(short_name="GPM_3IMERGHHL", bounding_box=storm_aoi,
temporal=("2024-09-25", "2024-09-28"))
ds = xr.open_mfdataset(earthaccess.open(imerg), group="Grid", combine="nested",
concat_dim="time")
rain = ds["precipitation"].sel(lon=slice(storm_aoi[0], storm_aoi[2]),
lat=slice(storm_aoi[1], storm_aoi[3]))
rain_mm = rain.sum("time") * 0.5 # half-hourly mm/hr -> mm total
max_mm = float(rain_mm.max())
# 4. Verdict + plot: flood extent next to the rain that drove it.
print(f"Flooded (new water): {flood_km2:,.0f} km2; peak rainfall {max_mm:.0f} mm")
fig, (a1, a2) = plt.subplots(1, 2, figsize=(11, 5))
a1.imshow(post, cmap="gray", vmin=-25, vmax=0)
a1.imshow(np.where(new_water, 1, np.nan), cmap="cool", alpha=0.7)
a1.set_title(f"New water (flood): {flood_km2:,.0f} km2")
rain_mm.plot(ax=a2, cmap="Blues"); a2.set_title(f"IMERG rain, peak {max_mm:.0f} mm")
plt.tight_layout(); plt.show()
# Before you trust it: confirm against a "before" baseline (done here) so permanent
# rivers/lakes aren't counted, and remember cities under-count (corner reflection — see gotchas).
Where the data comes from
Everything comes from NASA through one free login (Earthdata Login), even though the pieces live in different NASA archives: the Sentinel-1 / OPERA radar is held at ASF, the IMERG rainfall at GES DISC, the LIS soil-moisture model at GHRC, and the optional HLS optical imagery at LP DAAC. You sign in once and reach all four.
Sources
- OPERA RTC-S1: https://www.jpl.nasa.gov/go/opera/products/rtc-product
- ASF Vertex flood-mapping tutorials: https://asf.alaska.edu/how-to/
- Hurricane Helene rapid response: https://disasters.nasa.gov/
Make it yours → Set the storm bounding box and the before/after date windows, and adjust the VV backscatter (dB) water threshold for your terrain.
A safe place to practise the method on OPERA_L2_RTC-S1_V1. 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.