True-colour approach 5 — a daily MODIS time-lapse of the middle-Danube corridor¶
Sentinel-2/Landsat resolve a single reach; to watch a whole corridor dry out day by day you need a
daily sensor. MODIS (MOD09GA, ~500 m, daily) is too coarse for channel width but perfect for a
smooth basin-scale true-colour movie — the land browning and the big rivers/reservoirs standing out
across the drought. We animate the middle-Danube corridor through summer 2026.
Needs
GEE_SERVICE_ACCOUNT/GEE_SERVICE_KEYandpyramids-gis[viz].
Setup¶
pyramids reads and plots the GeoTIFFs (Dataset / DatasetCollection); earthlens provides the
EarthLens entry point. Earth Engine credentials come from a repo-root .env.
import os
import warnings
from pathlib import Path
import matplotlib.pyplot as plt
from IPython.display import Image, display
from loguru import logger
from pyramids.dataset import DatasetCollection
from earthlens.core import EarthLens
warnings.filterwarnings("ignore")
logger.remove()
plt.rcParams["figure.dpi"] = 80
from dotenv import find_dotenv, load_dotenv
load_dotenv(find_dotenv(usecwd=True))
SERVICE_ACCOUNT = os.environ["GEE_SERVICE_ACCOUNT"]
SERVICE_KEY = os.environ["GEE_SERVICE_KEY"]
The corridor and the window¶
A wide box over the middle Danube (Hungary–Serbia) and a daily MODIS true-colour frame across the
drought. MODIS bands sur_refl_b01/b04/b03 are red/green/blue.
CORRIDOR = {"lat_lim": [44.0, 48.5], "lon_lim": [16.0, 22.0]}
MODIS = "MODIS/061/MOD09GA"
OUT = Path("out") / "tc5_modis_corridor"
raw = OUT / "daily"
raw.mkdir(parents=True, exist_ok=True)
Pull one daily true-colour frame per day (cached)¶
One daily MODIS true-colour GeoTIFF per day over the corridor, mid-June to mid-July 2026 (the peak of the drought). Cached, so re-runs skip the pulls.
cached = sorted(raw.glob("*.tif"))
if cached:
frames = cached
else:
job = EarthLens(
data_source="gee",
dataset=MODIS,
variables=["sur_refl_b01", "sur_refl_b04", "sur_refl_b03"],
start="2026-06-15",
end="2026-07-15",
temporal_resolution="daily",
scale=2000.0,
path=raw,
export_via="url",
**CORRIDOR,
)
job.authenticate(service_account=SERVICE_ACCOUNT, service_key=SERVICE_KEY)
frames = job.download(progress_bar=False)
len(frames)
Animate the corridor day by day¶
Read the daily frames into one collection and animate the true colour. MODIS surface reflectance needs a
brightness stretch, which pyramids applies via surface_reflectance.
dc = DatasetCollection.read_multiple_files(str(raw), date=False)
gif = OUT / "modis_corridor.gif"
dc.plot(
rgb_options={"rgb": [0, 1, 2], "surface_reflectance": 3200},
figsize=(6, 5),
title="Middle Danube corridor - MODIS true colour, Jun-Jul 2026",
).save_animation(str(gif), fps=3)
plt.close("all")
display(Image(filename=str(gif)))
Notes¶
- MODIS is basin-scale, not channel-scale: watch the land brown and the reservoirs/large reaches, not individual sandbars. Cloudy days are part of a daily time-lapse (the weather moving through).
- Swap
MOD09GA(Terra, morning) forMYD09GA(Aqua, afternoon), or widen the box to the whole basin.