After the cyclone made landfall, which villages and farms near me got flooded?
Draw a rectangle, then check which collections cover it. Most NASA data is global, so a big box matches a lot.
89, 21.5 → 91, 23 (Bangladesh coast — Khulna/Barisal delta (Bay of Bengal cyclone zone))A flood map is just a picture of where there's standing water that shouldn't be there. The problem after a cyclone is that thick storm clouds hide the ground from ordinary cameras in space. Radar gets around this. A radar satellite bounces its own radio pulses off the surface and listens for the echo, so it sees water through cloud, day or night. Calm water bounces the pulse away from the satellite and shows up dark, which is how the flood gives itself away.
After the cyclone made landfall, which villages and farms near me got flooded?
A flood map is just a picture of where there’s standing water that shouldn’t be there. The problem after a cyclone is that thick storm clouds hide the ground from ordinary cameras in space. Radar gets around this. A radar satellite bounces its own radio pulses off the surface and listens for the echo, so it sees water through cloud, day or night. Calm water bounces the pulse away from the satellite and shows up dark, which is how the flood gives itself away.
Which data to use, and how
Use this dataset: OPERA DSWx-S1 (short name
OPERA_L3_DSWX-S1_V1). It’s a ready-made surface-water map built from Sentinel-1 radar. NASA
has already done the hard part of turning raw radar echoes into a simple “this pixel is water /
not water” grid, so you don’t have to. It sees through the cyclone’s cloud shield, and it covers
the Bay of Bengal from 2024 onward, so pick a recent storm.
Then do four steps (the runnable code further down does all of this; this is just the idea):
- Pick your area. A small latitude/longitude box around the coast you care about, and the days right after the cyclone made landfall.
- Grab the water layer. Each DSWx-S1 file is a tile. Keep only the water-classification
layer (the file ending
_B01_WTR.tif) and stitch the tiles together to cover your box. - Keep the wet pixels. The layer labels every pixel (open water, partial water, flooded vegetation, “unknown”, and so on). Keep the ones that mean water and count them. That’s your flooded area in km².
- Put names and people on it. Overlay free WorldPop population to estimate how many people are in the flooded box, and use free geoBoundaries district outlines to name the places. (Verified: ~16.3M people in the default delta box; the test point lands in district Pirojpur.)
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
- Where the flood is, through thick cloud. Radar sees the ground even under the storm, when ordinary optical sensors are blind.
- Different kinds of flooding. DSWx-S1 separately flags open water, partial water, and inundated vegetation, so flooded rice paddies and mangrove fringe show up, not just open ponds.
- Which named villages and farms are hit. Clip the flood map to a settlement and intersect it with map polygons (e.g. OpenStreetMap buildings and land use) to list affected places.
- Roughly how many people are in the flooded area. Overlay WorldPop population (1 km) on the flood map and count, then name the flooded districts with geoBoundaries.
- The rain that caused it. GPM IMERG Half-Hourly Early run gives near-real-time (~4 h delay) rainfall totals over the landfall window, showing where water pooled.
- An early “is it flooding right now” cue. CYGNSS (GPS signals reflected off the surface) brightens over standing water and punches through the storm, filling the gaps between radar passes.
- The storm making landfall, every 10 minutes. Himawari-9 sits over one spot of the globe and snaps the whole disk every 10 minutes, covering the Bay of Bengal at the western edge of its view, so you can pin the eye and the exact landfall hour. Free, no login.
What it can’t tell you
- How deep the water is, or whether your ground floor is underwater. DSWx-S1 maps water presence, not depth. Depth needs a ground-elevation map (a DEM, e.g. Copernicus GLO-30) plus a water-flow model (HEC-RAS).
- Building-by-building or crop-by-crop damage. The pixels are ~30 m (and CYGNSS footprints are ~25 km), far too coarse to see individual houses or fields. Detailed damage needs commercial high-resolution imagery (Maxar, Planet, ICEYE).
- The exact hour the flood peaked. Sentinel-1 only passes over a given spot every ~6–12 days, so DSWx-S1 gives you snapshots, not the rising-and-falling curve. CYGNSS only fills the gaps coarsely.
- Flooding inside cities and drainage flooding. Radar struggles in built-up areas (hard edges of buildings stay bright even over water), so DSWx flags dense-urban pixels as unreliable.
- Salt water vs. fresh water. These sensors see water, not saltiness, which matters a lot for whether farmland recovers.
Gotchas to watch for
- A wet pixel says “wet,” not “how deep.” DSWx-S1 marks water presence only. Don’t read a flood map as a depth map; for depth you need elevation plus a flow model.
- Snapshots, not a movie. The radar satellite revisits the same place only every ~6–12 days, so you might catch the flood on the way up or down and miss the worst moment. Use CYGNSS or the rainfall map to sanity-check timing.
- Some water is always there. Rivers, ponds, and tidal flats show up as “water” even on a dry day. The fix: grab a calm dry-season DSWx-S1 scene of the same area and subtract it, so you’re left with only the new flooding.
- Cities and dense forest are unreliable. DSWx flags two kinds of trouble pixels: high
backscatter (built-up areas that stay bright) and layover/shadow (where the radar geometry hides
the ground). The data marks these (class
253= high backscatter,254= no data); treat them as “unknown,” not “dry.” - CYGNSS is coarse (~25 km). It’s a regional “is it flooding somewhere around here” cue, not a parcel-level map. Use it for timing, not for drawing boundaries.
- The cloud read can hiccup. PO.DAAC occasionally returns a transient
502error on a cloud read. Just retry; it’s not your code.
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 the radar water maps, mosaic the tiles, classify the wet pixels into flooded km², overlay free population to count who’s in it, and plot the flood map. It needs a free Earthdata Login. DSWx-S1 coverage over the Bay of Bengal begins in 2024, so the window below is Cyclone Dana (landfall 25 Oct 2024).
import earthaccess, glob, requests
import rioxarray
from rioxarray.merge import merge_arrays
import numpy as np
import rasterio
from rasterio.warp import reproject, Resampling
import matplotlib.pyplot as plt
earthaccess.login(strategy="netrc")
# Bay of Bengal landfall corridor — Khulna/Barisal delta, Bangladesh (W, S, E, N).
# Replace the window with the days right after YOUR cyclone's landfall.
aoi = (89.0, 21.5, 91.0, 23.0)
post_window = ("2024-10-25", "2024-10-27") # first Sentinel-1 passes after Cyclone Dana
# 1. OPERA DSWx-S1 — radar surface water, delivered as Cloud-Optimized GeoTIFFs.
results = earthaccess.search_data(
short_name="OPERA_L3_DSWX-S1_V1", bounding_box=aoi, temporal=post_window)
print(f"Found {len(results)} DSWx-S1 granules")
# 2. Download and keep only the water-classification layer (B01_WTR) for each tile.
earthaccess.download(results, local_path="./dswx")
wtr_tiles = sorted(glob.glob("./dswx/*_B01_WTR.tif"))
# 3. Mosaic the UTM tiles, then reproject + clip to the AOI.
tiles = [rioxarray.open_rasterio(t, masked=False).squeeze() for t in wtr_tiles]
da = merge_arrays(tiles).rio.reproject("EPSG:4326").rio.clip_box(*aoi)
# DSWx-S1 WTR classes: 0 not-water, 1 open water, 2 partial water,
# 252 inundated vegetation, 253 high backscatter, 254 no-data, 255 fill.
flood_mask = da.isin([1, 2, 252]) # open + partial + inundated vegetation = "wet"
flooded_px = int(flood_mask.sum())
flooded_km2 = flooded_px * (0.030 ** 2) # DSWx-S1 native pixel is ~30 m
print(f"Flooded area: {flooded_px:,} px ≈ {flooded_km2:.1f} km^2")
# 4. People in the flood — free WorldPop 1 km population (no NASA login), resampled onto
# the flood grid so we sum population only where DSWx says it's wet.
meta = requests.get("https://www.worldpop.org/rest/data/pop/wpic1km?iso3=BGD").json()
pop_url = next(f for f in meta["data"][-1]["files"] if f.endswith(".tif"))
open("bgd_pop_1km.tif", "wb").write(requests.get(pop_url).content)
pop_on_flood = np.zeros(flood_mask.shape, dtype="float64")
with rasterio.open("bgd_pop_1km.tif") as src:
src_pop = src.read(1).astype("float64")
src_pop[src_pop == src.nodata] = 0.0
reproject(src_pop, pop_on_flood,
src_transform=src.transform, src_crs=src.crs,
dst_transform=da.rio.transform(), dst_crs=da.rio.crs,
resampling=Resampling.bilinear)
people_in_flood = float(np.where(flood_mask.values, pop_on_flood, 0).sum())
print(f"People in the flooded pixels: {people_in_flood:,.0f}")
# 5. Verdict + map.
print(f"VERDICT: ~{flooded_km2:.0f} km^2 flooded, ~{people_in_flood:,.0f} people in the water.")
flood_mask.astype("int8").plot(cmap="Blues", add_colorbar=False)
plt.title(f"DSWx-S1 flood, {post_window[0]}..{post_window[1]} ({flooded_km2:.0f} km²)")
plt.xlabel("lon"); plt.ylabel("lat"); plt.tight_layout(); plt.show()
# Cross-check: rivers/ponds/tidal flats read "water" even on a dry day. Subtract a calm
# dry-season DSWx-S1 scene of the same box (search a low-rain month, same flood_mask) so
# you keep only the *new* flooding — and ignore class 253/254 pixels as "unknown," not dry.
Where the data comes from
Everything NASA here comes through one free login (Earthdata Login), even though the pieces live in different archives: the radar flood map (OPERA DSWx-S1) at ASF / PO.DAAC, the storm rainfall (GPM IMERG Early) at GES DISC, and the during-storm flood cue (CYGNSS) at PO.DAAC. The people-and-places layers (WorldPop population, geoBoundaries district outlines) and the landfall movie (Himawari-9 on NOAA’s open S3 bucket) are free and need no login at all. For the western Indian Ocean / Mozambique use EUMETSAT Meteosat instead of Himawari; for the Americas, NOAA GOES.
Sources
- OPERA DSWx-S1 product: https://www.jpl.nasa.gov/go/opera/products/dswx-product/
- OPERA DSWx-S1 in Earthdata Search: https://search.earthdata.nasa.gov/search?q=OPERA_L3_DSWX-S1_V1
- GPM IMERG (GES DISC): https://gpm.nasa.gov/data/imerg
- CYGNSS mission & data (PO.DAAC): https://podaac.jpl.nasa.gov/CYGNSS
- NASA Disasters cyclone/flood response: https://disasters.nasa.gov/
- WorldPop population (free, no login): https://www.worldpop.org/
- geoBoundaries (free CC-BY admin boundaries): https://www.geoboundaries.org/
- Himawari on AWS (NOAA open data, no login): https://registry.opendata.aws/noaa-himawari/
- EUMETSAT Meteosat (western Indian Ocean / Africa geostationary): https://www.eumetsat.int/
Make it yours → Set the AOI around your town, the post-landfall date for the Sentinel-1 pass and the pre-storm baseline scene, and the population-count thresholds in the notebook.
A safe place to practise the method on OPERA_L3_DSWX-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.