Showcase — the Hunga Tonga eruption (January 2022)¶
The 15 January 2022 eruption of Hunga Tonga–Hunga Haʻapai was one of the most violent explosions ever recorded and all but erased the young volcanic island. This notebook pulls Sentinel-2 before/after composites and renders them with pyramids' Dataset.plot().
What this notebook does¶
- Fetch a pre- and post-eruption Sentinel-2 composite.
- Render both with
Dataset.plot(rgb_options=...)— the central island is there in early January and gone afterwards.
Hunga Tonga sits under near-permanent tropical cloud, so this stays qualitative; each scene is a month-long median composite (median drops most cloud).
Needs
GEE_SERVICE_ACCOUNT/GEE_SERVICE_KEYandpyramids-gis[viz].
Setup¶
First the imports and a bit of noise-suppression. pyramids provides Dataset (reading + plotting); earthlens provides the unified EarthLens entry point.
import os
import warnings
import matplotlib.pyplot as plt
import numpy as np
from dotenv import find_dotenv, load_dotenv
from loguru import logger
from pyramids.dataset import Dataset # pyramids' own reading + plotting
from earthlens import EarthLens
warnings.filterwarnings("ignore")
logger.remove()
2026-06-13 18:18:36 | INFO | pyramids.base.config | Logging is configured.
Credentials¶
This notebook reads its credentials from a .env file at the repository root (loaded with python-dotenv; your PATH is left untouched). Create that .env with at least:
GEE_SERVICE_ACCOUNT="your-sa@your-project.iam.gserviceaccount.com"
GEE_SERVICE_KEY="/path/to/your/service-account-key.json"
load_dotenv(find_dotenv(usecwd=True))
SERVICE_ACCOUNT = os.environ["GEE_SERVICE_ACCOUNT"]
SERVICE_KEY = os.environ["GEE_SERVICE_KEY"]
if any(x is None for x in (SERVICE_ACCOUNT, SERVICE_KEY)):
raise ValueError("Missing credentials in .env")
1 · Sentinel-2 before/after composites¶
Both scenes share the same area of interest, dataset, and true-colour bands (B4, B3, B2); only the date window changes. Each is a month-long median composite, which drops most of the tropical cloud.
AOI = [-175.45, -20.62, -175.35, -20.52]
C = "COPERNICUS/S2_SR_HARMONIZED"
Before — December 2021 to mid-January 2022¶
Build the GEE request for the pre-eruption window, keeping construct → authenticate → load on separate lines. load() returns a list of rasters; we take the single composite with [0].
before_scene = EarthLens(
data_source="gee",
cadence="raw",
dataset=C,
variables=["B4", "B3", "B2"],
aoi=AOI,
start="2021-12-15",
end="2022-01-13",
scale=10,
reducer="median",
)
before_scene.authenticate(service_account=SERVICE_ACCOUNT, service_key=SERVICE_KEY)
before_rasters = before_scene.load()
before = before_rasters[0]
COPERNICUS/S2_SR_HARMONIZED [B4,B3,B2]: 0%| | 0/1 [00:00<?, ?img/s]
COPERNICUS/S2_SR_HARMONIZED [B4,B3,B2]: 100%|██████████| 1/1 [00:40<00:00, 40.59s/img]
COPERNICUS/S2_SR_HARMONIZED [B4,B3,B2]: 100%|██████████| 1/1 [00:40<00:00, 40.59s/img]
After — late January to February 2022¶
Same request, shifted to the post-eruption window. The island that anchors the pre-eruption scene is gone here.
after_scene = EarthLens(
data_source="gee",
cadence="raw",
dataset=C,
variables=["B4", "B3", "B2"],
aoi=AOI,
start="2022-01-20",
end="2022-02-28",
scale=10,
reducer="median",
)
after_scene.authenticate(service_account=SERVICE_ACCOUNT, service_key=SERVICE_KEY)
after_rasters = after_scene.load()
after = after_rasters[0]
print("composites:", bool(before), bool(after))
COPERNICUS/S2_SR_HARMONIZED [B4,B3,B2]: 0%| | 0/1 [00:00<?, ?img/s]
COPERNICUS/S2_SR_HARMONIZED [B4,B3,B2]: 100%|██████████| 1/1 [00:31<00:00, 32.00s/img]
COPERNICUS/S2_SR_HARMONIZED [B4,B3,B2]: 100%|██████████| 1/1 [00:32<00:00, 32.00s/img]
composites: True True
2 · Before and after — Dataset.plot()¶
Render both composites side by side as true-colour images. The percentile stretch keeps the cloud-bright scenes readable; the island's destruction is plain even through the cloud.
if before and after:
fig, ax = plt.subplots(1, 2, figsize=(12, 6))
before.plot(
rgb_options={"rgb": [0, 1, 2], "percentile": 2},
ax=ax[0],
title="Hunga Tonga - before (Dec 2021-Jan 2022)",
)
after.plot(
rgb_options={"rgb": [0, 1, 2], "percentile": 2},
ax=ax[1],
title="Hunga Tonga - after (late Jan-Feb 2022)",
)
for a in (ax[0], ax[1]):
a.set_xticks([])
a.set_yticks([])
plt.tight_layout()
plt.show()
else:
print("no scenes - set GEE credentials and rerun")
Recap¶
The before/after pair, rendered with Dataset.plot(), makes the island's destruction plain even through tropical cloud.
Try it yourself¶
- Add the SWIR band
B12to highlight fresh ash. - See the GEE backend reference.