GEDI L4A aboveground-biomass footprints (NASA Earthdata)¶
GEDI L4A footprint granules from the ORNL DAAC are a vector product
(per-shot aboveground biomass), so the backend reports OUTPUT_KIND='vector'
and the facade rejects aggregate=. This notebook downloads a granule, reads
one beam of per-shot footprints from the HDF5 file, and scatters them coloured
by biomass.
The backend fetches whole HDF5 orbit granules (no server-side subsetting in the MVP), so a wide window pulls several hundred MB — keep the window small. This is a live query: it needs the
[earthdata]extra and EDL credentials, and every step is wrapped so the notebook stays safe to run offline.
Setup¶
The only import needed up front is the unified EarthLens entry point plus
Path for the output directory; h5py and matplotlib are imported later,
right where the granule is read and plotted. We also create the directory the
granule will be written to.
from pathlib import Path
from earthlens import EarthLens
OUT_DIR = Path('earthdata_output')
OUT_DIR.mkdir(exist_ok=True)
Download a GEDI L4A granule¶
Build the request first — the GEDI L4A dataset id, the agbd variable, a
narrow two-day window, and a small bounding box over the Congo Basin — then
call download() to fetch the matching HDF5 granule(s) into OUT_DIR. The
construct and download steps are kept on separate lines, and the whole block
is wrapped so a missing credential or extra simply prints a skip message
offline.
paths = None
try:
gedi = EarthLens(
data_source='earthdata',
dataset='GEDI_L4A_AGB_Density_V2_1_2056',
variables=['agbd'],
start='2020-05-01',
end='2020-05-02',
aoi=[12.0, -3.0, 18.0, 3.0],
path=str(OUT_DIR),
)
paths = gedi.download(progress_bar=False)
print(len(paths), 'granule(s):', [Path(p).name for p in paths])
except Exception as exc:
print(f'skipped live query: {type(exc).__name__}: {exc}')
Read one beam of footprints¶
Each granule is an HDF5 file of per-beam footprints. We open the first beam
and pull a sample of its lowest-mode latitude/longitude and agbd values. The
read is wrapped so an h5py or structure surprise does not mask the download
above.
lat = lon = agbd = beam = None
if paths:
try:
import h5py
with h5py.File(paths[0], 'r') as h5:
beam = next(k for k in h5 if k.startswith('BEAM'))
lat = h5[f'{beam}/lat_lowestmode'][:5000]
lon = h5[f'{beam}/lon_lowestmode'][:5000]
agbd = h5[f'{beam}/agbd'][:5000]
except Exception as exc:
print(f'read step skipped: {type(exc).__name__}: {exc}')
Plot the footprints¶
Scatter the sampled footprints coloured by aboveground biomass density
(agbd, Mg/ha) to see how biomass varies along the beam track.
if beam is not None:
try:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(8, 6))
sc = ax.scatter(lon, lat, c=agbd, cmap='YlGn', s=6, vmin=0)
fig.colorbar(sc, ax=ax, label='AGBD (Mg/ha)')
ax.set_title(f'GEDI L4A footprints ({beam}) — aboveground biomass')
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
plt.tight_layout()
plt.show()
except Exception as exc:
print(f'plot step skipped: {type(exc).__name__}: {exc}')