Showcase — Hurricane Ian from geostationary orbit (GOES, AWS Open Data)¶
Geostationary weather satellites watch the same hemisphere continuously, so they are how forecasters track hurricanes minute to minute. NOAA's GOES-16 ABI imager publishes its imagery openly on AWS. This notebook uses the earthlens amazon-s3 backend (unsigned, no credentials) to pull the clean-infrared window (band 13) over Hurricane Ian (September 2022) — the band that shows deep convective cloud tops day or night — and pyramids reprojects the geostationary grid to lat/lon on the fly.
Public AWS Open Data — no credentials needed. The backend selects the first frame of the requested day.
What this notebook does¶
- Fetch the GOES-16 ABI band-13 (10.3 µm IR) scene over the Gulf/Florida.
- Convert the scaled radiance to brightness temperature (K).
- Map the cold cloud tops — Ian's deep convection stands out against the warm, clear background.
Colder (lower) brightness temperatures mark taller, more intense storm clouds.
Setup¶
The imports and a bit of noise-suppression. pyramids provides Dataset (reading + plotting); earthlens provides the unified EarthLens entry point. This backend is unsigned public AWS Open Data, so there are no credentials to load.
import os
import tempfile
import matplotlib.pyplot as plt
import numpy as np
from cleopatra.array_glyph import ArrayGlyph
from loguru import logger
from pyramids.dataset import Dataset
from earthlens import EarthLens
logger.disable("earthlens")
logger.disable("pyramids")
1 · Fetch the GOES-16 scene¶
We build the request first: the GOES-16 ABI L2 Cloud & Moisture Imagery dataset, band C13 (the clean IR window), a single day around Ian's Florida landfall, and a bounding box over the Gulf/Florida. The amazon-s3 backend reads the granule unsigned and pyramids reprojects the geostationary grid to WGS84.
scene = EarthLens(
data_source="amazon-s3",
dataset="goes",
variables=["C13"],
start="2022-09-29",
end="2022-09-29",
aoi=[-85.0, 24.0, -79.0, 31.0], # Ian over Florida (W, S, E, N)
path=tempfile.mkdtemp(),
)
The download is kept as its own step. download() returns the list of written granule paths; we take the first and print its filename so it is clear which frame the backend selected.
path = None
try:
paths = scene.download(progress_bar=False)
path = str(paths[0]) if paths else None
print("granule:", os.path.basename(path) if path else None)
except Exception as exc: # noqa: BLE001
print("GOES download skipped:", exc)
2 · Brightness temperature¶
Read the reprojected raster and convert the scaled stored value to brightness temperature in kelvin (the GOES scale factor is 0.1; values below 1 are treated as no-data).
if path:
ds = Dataset.read_file(path)
arr = np.asarray(ds.read_array(), dtype="float32")
bt = arr[0] if arr.ndim == 3 else arr
bt = np.where(bt < 1, np.nan, bt) * 0.1 # scaled -> kelvin
else:
bt = None
Map the cold cloud tops¶
A reversed turbo colormap puts the coldest (highest, most intense) cloud tops at the bright end, so Ian's deep convection stands out against the warm, clear background.
if bt is not None:
ArrayGlyph(
bt,
figsize=(7, 8),
title="GOES-16 ABI band 13 (clean IR) — Hurricane Ian over Florida, 29 Sep 2022",
).plot(cmap="turbo_r", vmin=200, vmax=300, cbar_label="brightness temperature (K)")
plt.show()
print(
f"coldest cloud-top brightness temperature in scene: {np.nanmin(bt):.0f} K "
f"({np.nanmin(bt)-273.15:.0f} °C) — the deepest convection"
)
else:
print("no scene — rerun with network access")
Recap¶
The earthlens amazon-s3 backend pulls GOES ABI imagery from public AWS Open Data with no credentials, and pyramids reprojects the geostationary grid to lat/lon — turning a raw satellite granule into an analysis-ready brightness-temperature map of the hurricane's clouds.
Try it yourself¶
- Switch
bucket="noaa-goes18"for the Pacific, or bandC02(visible) for a daytime view. - Re-point the date/AOI at another storm or a wildfire-smoke pall.
- See the Amazon S3 backend reference.