NWM catalog explorer¶
This notebook needs no credentials and no network. It reads the
bundled earthlens.nwm catalog to answer the first questions every
National Water Model user has: which products exist, what output kind
each is, which configurations produce them, and what the exact S3 keys
look like.
Setup¶
Pull in the two entry points this notebook uses: Catalog (the bundled
earthlens.nwm metadata) and the unified EarthLens facade (for the
no-network key enumeration later on).
from earthlens import EarthLens
from earthlens.nwm import Catalog
Products and configurations¶
Instantiate the catalog and list its two top-level axes: the products (the file families the model writes) and the configurations (the operational runs that produce them).
cat = Catalog()
print('products: ', cat.products())
print('configurations:', sorted(cat.configurations))
Products and their output kind¶
chrtout is per-reach streamflow indexed by feature_id (so it is
tabular); ldasout is a gridded 1 km land-surface product (so it is
raster). The output kind is what the facade uses to decide whether
aggregate= is meaningful.
for key in cat.products():
p = cat.get_product(key)
print(f'{key:9s} kind={p.output_kind:8s} token={p.s3_token:11s} dims={p.dims}')
for name, var in p.variables.items():
print(f' - {name:14s} [{var.units}] {var.long_name}')
Configurations¶
A configuration is the operational run that produced a file: its run
hours, its forecast (fNNN) or analysis (tmNN) step scheme, its
horizon, and — for ensembles — its member count.
for key in sorted(cat.configurations):
c = cat.get_config(key)
kind = 'ensemble (%d members)' % c.members if c.members else 'deterministic'
print(
f'{key:16s} {len(c.cycles_utc):2d} cycles/day {c.step_kind:8s} '
f'first={c.first_step} horizon={c.horizon_h}h {kind}'
)
What S3 keys would a request enumerate?¶
_search() is the cheap, no-network half of the backend: it expands a
request into the exact noaa-nwm-pds keys it would download. We build
a deterministic short_range request first, using a whole-Earth bbox
(the 'no subset' signal) so it stays a plain whole-file download.
nwm = EarthLens(
data_source="nwm",
start='2026-05-26',
end='2026-05-26',
dataset='chrtout',
variables=['streamflow'],
aoi=[-180, -90, 180, 90],
configuration='short_range',
cycles=[0, 6],
steps=[1, 3],
)
With the request built, expand it into the S3 keys it would fetch and
print each href:
for rp in nwm._search():
print(rp.href)
Ensemble configurations¶
The ensemble configurations ride the member on both the directory and
the product token (channel_rt_1). Build a medium_range request that
pins member=3:
ens = EarthLens(
data_source="nwm",
start='2026-05-26',
end='2026-05-26',
dataset='chrtout',
variables=['streamflow'],
aoi=[-180, -90, 180, 90],
configuration='medium_range',
member=3,
cycles=[0],
steps=[240],
)
Enumerate the keys for that ensemble request — note the member token appearing in the path and product name:
print(ens._search()[0].href)