How are coastal sea-surface temperatures changing, and are marine heatwaves becoming more common?
Draw a rectangle, then check which collections cover it. Most NASA data is global, so a big box matches a lot.
-116, 22 → -107, 32 (Gulf of California)Sea-surface temperature (SST) is how warm the very top of the ocean is. A satellite reads the heat radiating off that thin top layer from orbit. Track it month after month for years and you can see whether a stretch of coast is slowly warming, and whether it now suffers more marine heatwaves: spells where the water stays unusually hot for days on end. Those can bleach reefs, kill fish, and upend local fisheries.
How are coastal sea-surface temperatures changing?
Sea-surface temperature (SST) is how warm the very top of the ocean is. A satellite reads the heat radiating off that thin top layer from orbit. Track it month after month for years and you can see whether a stretch of coast is slowly warming, and whether it now suffers more marine heatwaves: spells where the water stays unusually hot for days on end. Those can bleach reefs, kill fish, and upend local fisheries.
Which data to use, and how
Use this dataset: GHRSST L4 (MUR) (short name
MUR-JPL-L4-GLOB-v4.1), a daily, gap-filled ocean-temperature map at a fine ~1 km, going back to
2002. It’s the easiest to start with. Someone has already stitched together several satellites
and filled in the cloudy holes, so you get a clean value for every pixel every day and no
missing-data headaches.
Then do four steps. The runnable code further down does all of this; this is just the idea.
- Pick your coast. A small latitude/longitude box over the water you care about, plus the years you want.
- Build a “normal” year. For each calendar month, average all the years together to get the typical temperature for that month. This baseline pattern is the climatology (the long-run average seasonal cycle).
- Spot the hot spells. Flag any day hotter than the warmest 10% of days normally are for that time of year (the 90th percentile). A run of 5 or more such days in a row is one marine heatwave. Count heatwave-days per year.
- Fit a trend. Draw the long-term line through the yearly temperatures and the heatwave counts. Up means the coast is warming and/or heatwaves are getting more frequent.
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
- Whether this coast is warming, and by how much per decade (the SST trend for any pixel, 2002–present).
- What a “normal” year looks like here (the seasonal cycle) and how far the current year sits above or below it.
- Marine heatwaves: how often they strike (5+ days above the 90th percentile) and whether they’re getting more common.
- The temperature gap between the shoreline and the open ocean, meaning how warmth changes as you move offshore (the spatial gradient).
- How variable the water is, both along the coast and out to sea.
What it can’t tell you
- The temperature deeper down. Satellites only read the skin of the ocean. For temperatures metres below the surface you need a model that reconstructs the deep ocean (ECCO V4 reanalysis) or in-water robots (Argo floats).
- Tiny, fast features under ~4 km, like internal waves. Resolving those needs other instruments (high-resolution radar plus altimetry) combined together.
- Why the water warmed. A warming trend doesn’t say whether it’s a big climate cycle (like El Niño / ENSO, or the Atlantic Multidecadal Oscillation, AMO), local conditions, or long-term change. Pinning the cause is a separate study.
Gotchas to watch for
- The clean daily map is partly “filled in,” not all real. GHRSST L4 gives you a value for every pixel every day only because it interpolates across cloudy areas (gap-filling). In those spots you’re seeing a smart guess for consistency, not a direct measurement. Fine for trends; just know it.
- The satellite reads the skin, not the bulk. It measures the top millimetre of water; an oceanographer’s in-water sensor measures metres down (the skin-vs-bulk difference). Usually tiny, but it can matter for careful ecological work.
- Coasts are cloudy. Some coasts (e.g., California in summer) are foggy or cloudy for weeks, which blanks out raw satellite views. The gap-filled product papers over this, but the raw single-day high-resolution products (like MODIS Aqua SST) will have real holes. Averaging over a month helps.
- There’s no single “official” heatwave rule. Different studies draw the line differently. The most-cited convention is Hobday et al. 2016 (the 90th-percentile, 5-day rule used here). Pick one published definition and write down which, so your results are comparable.
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 GHRSST, open the daily SST cubes, build the climatology, detect marine heatwaves, fit the warming and heatwave trends, and plot it. It needs a free Earthdata Login.
import earthaccess, numpy as np, xarray as xr
import pymannkendall as mk
import matplotlib.pyplot as plt
earthaccess.login(strategy="netrc")
aoi = (-116, 22, -107, 32) # your coast as (W, S, E, N) — here, Gulf of California
window = ("2003-01-01", "2024-12-31") # whole calendar years
# 1. Search GHRSST L4 MUR (daily, gap-filled, 1 km) over the box and time window.
grans = earthaccess.search_data(short_name="MUR-JPL-L4-GLOB-v4.1",
bounding_box=aoi, temporal=window)
# 2. Open all granules as one cube, subset to the AOI, area-average each day to a
# single SST value. analysed_sst is in Kelvin -> convert to °C.
ds = xr.open_mfdataset(earthaccess.open(grans), combine="by_coords",
mask_and_scale=True, chunks={})
sst = (ds["analysed_sst"].sel(lon=slice(aoi[0], aoi[2]), lat=slice(aoi[1], aoi[3])) - 273.15)
w = np.cos(np.deg2rad(sst.lat)) # area-weight by latitude
daily = sst.weighted(w).mean(("lat", "lon")).load() # one SST per day
daily = daily.dropna("time")
# 3. Climatology = the "normal" year. For each day-of-year, the long-run mean and the
# 90th percentile across all years (Hobday et al. marine-heatwave threshold).
doy = daily["time"].dt.dayofyear
clim_mean = daily.groupby(doy).mean()
clim_p90 = daily.groupby(doy).quantile(0.90, dim="time")
thresh = clim_p90.sel(dayofyear=doy).values # per-day 90th-pct threshold
anom = daily.values - clim_mean.sel(dayofyear=doy).values
# 4. Marine heatwave = 5+ consecutive days above the 90th percentile. Count MHW-days/yr.
hot = daily.values > thresh
run, mhw = 0, np.zeros(len(hot), bool)
for i, h in enumerate(hot):
run = run + 1 if h else 0
if run >= 5:
mhw[i-run+1:i+1] = True # backfill the whole spell
years = daily["time"].dt.year.values
yr = np.unique(years)
mhw_days = np.array([mhw[years == y].sum() for y in yr])
yr_sst = np.array([daily.values[years == y].mean() for y in yr])
# 5. Robust trends (Theil–Sen slope + Mann–Kendall significance), both warming + heatwaves.
t_sst, t_mhw = mk.original_test(yr_sst), mk.original_test(mhw_days)
print(f"SST trend: {t_sst.slope*10:+.2f} °C/decade (p={t_sst.p:.3f}); "
f"marine-heatwave days {'rising' if t_mhw.slope>0 else 'falling'} "
f"{t_mhw.slope:+.1f} days/yr (p={t_mhw.p:.3f})")
# 6. SWOT sea-surface-height context: are recent warm spots tied to mesoscale eddies?
swot = earthaccess.search_data(short_name="SWOT_L2_LR_SSH_2.0", bounding_box=aoi,
temporal=("2024-03-01", "2024-12-31"))
print(f"{len(swot)} SWOT SSH granules available to overlay on warm anomalies")
# 7. Plot: yearly SST trend and the marine-heatwave-day count side by side.
fig, ax = plt.subplots(1, 2, figsize=(10, 4))
ax[0].plot(yr, yr_sst, "o-"); ax[0].set_title("Annual mean SST (°C)")
ax[1].bar(yr, mhw_days); ax[1].set_title("Marine-heatwave days / year")
plt.tight_layout(); plt.show()
# Before you trust it: cross-check the trend against an in-water Argo float or a tide-gauge
# SST record — GHRSST L4 is gap-filled (a smart guess under clouds), not all direct (see gotchas).
Where the data comes from
Everything comes from NASA through one free login (Earthdata Login), even though it’s stored in two different archives. The clean temperature maps (GHRSST), the sea-surface-height data (SWOT), and the deep-ocean model (ECCO) live in NASA’s physical- oceanography archive (PO.DAAC); the raw single-satellite temperatures (MODIS Aqua SST) and ocean- color data (PACE OCI) live in the ocean-biology archive (OB.DAAC). The same login opens both.
Sources
- GHRSST MUR: https://podaac.jpl.nasa.gov/dataset/MUR-JPL-L4-GLOB-v4.1
- Marine heatwave convention (Hobday et al.): https://www.marineheatwaves.org/definition.html
- OceanColor (MODIS SST): https://oceancolor.gsfc.nasa.gov/
Make it yours → Set the coastal box and date range and choose the climatology baseline and heatwave percentile/duration in the notebook.
A safe place to practise the method on MUR-JPL-L4-GLOB-v4.1. 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.
Computed · real data Worked examples, computed end-to-end on real satellite data — not yet scientist-verified · expand ▾
We ran the analysis on real data for Indian regions and report exactly what came back — including the honest nulls and refusals. Each card shows the slope, significance, and (for rainfall) a gauge cross-check.
Prior: Indian Ocean among the fastest-warming basins.
Prior: Indian Ocean rapid warming.