MSWEP precipitation — download and map a real event¶
This showcase pulls real MSWEP daily precipitation from an approved GloH2O Drive share, reads it with pyramids, and maps it — end to end, on real data.
MSWEP (Multi-Source Weighted-Ensemble Precipitation) is a machine-learning merge of gauge, satellite and reanalysis precipitation at 0.1° global, 1979→near-real-time. We look at 25 April 2020, during the pre-monsoon build-up over South and Southeast Asia.
Access. MSWEP is CC-BY-NC and not public — you need an approved GloH2O share. Set
MSWEP_DRIVE_FOLDERto your v3.16 folder id and authenticate (a service account, anrcloneremote, orgcloud auth application-default login). See the authentication guide. This notebook keeps its rendered outputs because the docs build has no credentials to regenerate them.
Setup¶
Imports, and a scratch directory for the downloaded granules (a temp dir — the raw NetCDF is ~5 MB/day and is regenerable, so we do not keep it in the repo). The share id comes from the environment, never hard-coded.
%matplotlib inline
import os
import tempfile
import warnings
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from cleopatra.glyphs.gridded.array_glyph import ArrayGlyph
from cleopatra.styling.colorbar import ColorBar
from cleopatra.styling.params import DataStyle
from pyramids.netcdf import NetCDF
from earthlens.biodiversity import LicenseWarning
from earthlens.core import EarthLens
warnings.simplefilter('ignore', LicenseWarning) # CC-BY-NC notice
DATA_DIR = Path(tempfile.mkdtemp(prefix='mswep_'))
FOLDER_ID = os.environ['MSWEP_DRIVE_FOLDER'] # your approved v3.16 share
MMDAY = 'precipitation (mm/day)' # shared colour-bar / axis label
Download five days of precipitation¶
One EarthLens(...).download() call fetches the daily granules for the window. The backend returns the
raw NetCDF paths — decoding is pyramids' job, not the fetch library's. We grab 24–28 April 2020.
paths = EarthLens(
'mswep',
start='2020-04-24',
end='2020-04-28',
variables=['precipitation'],
temporal_resolution='daily',
version='3.16',
folder_id=FOLDER_ID,
path=DATA_DIR,
).download()
[p.name for p in paths]
Five YYYYDOY.nc granules, mirrored under <root>/Past/Daily/. 2020116.nc is day-of-year 116 —
25 April 2020, our focus day.
Read one granule with pyramids¶
earthlens never decodes NetCDF itself; pyramids does. NetCDF.read_file returns a Container, and
get_variable gives the precipitation field as a georeferenced (EPSG:4326) Variable — a 0.1°
global grid, 1800 × 3600 cells.
focus = next(p for p in paths if p.name == '2020116.nc')
precip = NetCDF.read_file(str(focus)).get_variable('precipitation')
precip.shape, precip.epsg, precip.cell_size
To map it we read the array and mask the fill value — MSWEP flags ocean and no-data cells with large negatives, so anything below zero is not a real rain rate.
field = precip.read_array().astype('float32')
field[field < 0] = np.nan # fill / ocean-mask -> NaN
print(
f'max {np.nanmax(field):.0f} mm/day, wet cells (>1 mm) {np.nanmean(field > 1) * 100:.0f}%'
)
Map it — global¶
The array is row-major from the top-left (90°N, 180°W), so imshow with origin='upper' and a
full-globe extent places it correctly. We cap the colour scale at 40 mm/day so ordinary rain stays
visible next to the tropical extremes.
glyph = ArrayGlyph(
field,
extent=[-180, 180, -90, 90],
vmin=0,
vmax=40,
figsize=(11, 5.2),
title="MSWEP daily precipitation \u2014 25 April 2020",
)
fig, ax = glyph.plot(
data_style=DataStyle(style="precipitation"), colorbar=ColorBar(label=MMDAY)
)
ax.set_xlabel("longitude")
ax.set_ylabel("latitude")
plt.show()
The wet belt sits where late April expects it: the ITCZ across the tropics, convection over the Maritime Continent, and the first pre-monsoon rains brushing South Asia. Now zoom in.
Zoom — South and Southeast Asia¶
We crop by slicing the array with the grid's affine transform (geotransform), rather than pulling a
second file — the whole globe is already in memory. Window: 60–120°E, 0–35°N.
x0, dx, _, y0, _, dy = precip.geotransform
col = lambda lon: int(round((lon - x0) / dx))
row = lambda lat: int(round((lat - y0) / dy))
west, east, south, north = 60, 120, 0, 35
region = field[row(north) : row(south), col(west) : col(east)]
region.shape
glyph = ArrayGlyph(
region,
extent=[west, east, south, north],
vmin=0,
vmax=60,
figsize=(7.5, 4.6),
title="Pre-monsoon rainfall over South & SE Asia \u2014 25 Apr 2020",
)
fig, ax = glyph.plot(
data_style=DataStyle(style="precipitation"), colorbar=ColorBar(label=MMDAY)
)
ax.set_xlabel("longitude")
ax.set_ylabel("latitude")
plt.show()
The heavy cores over the Bay of Bengal, the Western Ghats coast, and the Maritime Continent are the convective systems MSWEP is built to capture — gauge-corrected where gauges exist, satellite-driven elsewhere.
A five-day time series¶
Finally, area-averaged rainfall over the same window for each day — a small helper reads each granule, masks it, and takes the regional mean. This is where the multi-day download pays off.
def regional_mean(path):
a = (
NetCDF.read_file(str(path))
.get_variable('precipitation')
.read_array()
.astype('float32')
)
a[a < 0] = np.nan
return np.nanmean(a[row(north) : row(south), col(west) : col(east)])
days = [
pd.to_datetime('2020-01-01') + pd.Timedelta(days=int(p.stem[4:]) - 1) for p in paths
]
series = pd.Series(
[regional_mean(p) for p in paths], index=days, name='mm/day'
).sort_index()
series
fig, ax = plt.subplots(figsize=(7.5, 3.6))
series.plot(ax=ax, marker='o')
ax.set(title='Area-mean rainfall, 60-120 E / 0-35 N', ylabel=MMDAY, xlabel='')
ax.grid(alpha=0.3)
plt.show()
The regional mean rises across the window — the pre-monsoon convection organising day by day, exactly the signal you would reach MSWEP for.
Takeaway¶
EarthLens('mswep', …).download()returns raw NetCDF paths; pyramids decodes them.- A MSWEP granule is a 0.1° global EPSG:4326 grid; mask values
< 0(ocean / no-data) before mapping. - The same pattern serves MSWX variables (
product='mswx', variables=['Temp', …]) and theMid/Longforecast ensembles (variant='Mid', init=…, members=…).
Next: usage for the full request surface, and the catalog explorer for a no-network tour of the products.