Skip to content

[WIP] Add ERA5-Land dataset support to DataWrangling#400

Draft
xkykai wants to merge 2 commits into
mainfrom
xk/era5-land
Draft

[WIP] Add ERA5-Land dataset support to DataWrangling#400
xkykai wants to merge 2 commits into
mainfrom
xk/era5-land

Conversation

@xkykai

@xkykai xkykai commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the ERA5-Land reanalysis (reanalysis-era5-land) as a first-class dataset in DataWrangling, so land-surface state (soil temperature, soil moisture, skin temperature, snow) can be loaded as FieldTimeSeries / single-snapshot Fields on the native grid or regridded onto a target land grid.

The motivating use is observational ground truth for calibrating land models (e.g. SlabLand) online against reanalysis — the data layer that Phases 2–3 of the land-training effort depend on.

Approach

ERA5-Land is implemented as subtypes of the existing ERA5Dataset (ERA5HourlyLand, ERA5MonthlyLand), reusing the entire CDS download / NetCDF-split / retrieve_data / region-crop / regrid pipeline. Only what genuinely differs from ERA5 single-levels is overridden:

  • 0.1° gridBase.size(3600, 1801, 1) and specialized longitude/latitude interfaces (the inherited 0.25° values would be silently wrong).
  • Variable dicts — skin temperature, soil temperature (4 levels), volumetric soil water (4 layers), 2 m temperature/dewpoint, snow depth + snow-water-equivalent.
  • Instantaneous analysis fieldsconversion_units = nothing (no accumulation→flux conversion).
  • Land-only maskingdefault_inpainting = nothing so masked ocean cells stay NaN (to be masked in a loss, not smeared into coastal land).
  • CDS request — the reanalysis-era5-land product rejects product_type, so build_era5_request now sets it via a dispatched set_product_type! hook (ERA5 → ["reanalysis"]; ERA5-Land → omit). The land Union method is strictly more specific than the abstract ERA5Dataset, so it resolves unambiguously.

Files

  • src/DataWrangling/ERA5/ERA5_land.jl (new)
  • src/DataWrangling/ERA5/ERA5.jl, src/DataWrangling/DataWrangling.jl, src/NumericalEarth.jl — includes + exports
  • ext/NumericalEarthCDSAPIExt.jlcds_product/cds_varnames/nc_varnames/coord_vars dispatch + set_product_type! refactor

Testing

Verified against a live CDS download (Borneo bbox), not just static checks:

  • ✅ Package loads; both dataset types construct and appear in supported_datasets().
  • Metadata/Metadatum build; size(ERA5HourlyLand(), :skin_temperature) == (3600, 1801, 1); native grid is 0.1° (N→S).
  • Critical regression check: the ERA5-Land CDS request omits product_type; the single-level request still includes it.
  • NetCDF short names confirmed against real filesskt, stl1, swvl1, t2m, d2m, sde, sd all matched the dict exactly (no corrections needed).
  • Ocean masking end-to-end — a land/sea bbox loaded with finite land cells (289–304 K) and NaN ocean cells, no inpainting.

Notes / follow-ups

  • The monthly product (reanalysis-era5-land-monthly-means) shares the code path (only its cds_product string differs) and was not exercised with a live download.
  • Downloading requires the ERA5-Land licence accepted on the CDS account (separate from ERA5).
  • No new PrescribedLand-style coupling type is added: ERA5-Land targets are plain FieldTimeSeries consumed by a loss.

🤖 Generated with Claude Code

Introduce ERA5HourlyLand and ERA5MonthlyLand as subtypes of ERA5Dataset,
reusing the entire ERA5 download/split/read/regrid pipeline and overriding
only what differs for the land-surface reanalysis product:

- 0.1° native grid (3600, 1801, 1) with half-cell longitude offset
  (-0.05, 359.95), overriding the inherited 0.25° single-level size.
- Land-surface variables: skin/soil temperature (4 levels), volumetric
  soil water (4 layers), 2m temperature/dewpoint, snow depth and
  snow water equivalent, with verified netCDF short names.
- No unit conversion (instantaneous analysis fields) and no inpainting,
  so ocean cells stay masked as NaN via nan_convert_missing.

In the CDS extension, add cds_product / cds_varnames / nc_varnames /
coord_vars dispatch for the land datasets, mapping to the
reanalysis-era5-land and reanalysis-era5-land-monthly-means products.
Refactor build_era5_request to set product_type through a dispatched
set_product_type! hook: ERA5 (single/pressure) keeps ["reanalysis"],
while ERA5-Land omits the key entirely (the land products reject it).

Verified against live CDS downloads: all netCDF short names match, the
0.1° coordinate spacing is correct, and ocean cells load as NaN while
land cells carry physical values.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@xkykai xkykai changed the title Add ERA5-Land dataset support to DataWrangling [WIP] Add ERA5-Land dataset support to DataWrangling Jul 1, 2026
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 21 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/DataWrangling/ERA5/ERA5_land.jl 0.00% 13 Missing ⚠️
ext/NumericalEarthCDSAPIExt.jl 0.00% 8 Missing ⚠️

📢 Thoughts on this report? Let us know!

The ERA5-Land native size used Ny = 1801 (the file's latitude row count),
but `construct_native_grid` builds the LatitudeLongitudeGrid with
`size=(Nx,Ny)` over `latitude=(-90,90)`. With Ny=1801 the cells span
180/1801 ≈ 0.09994°, misregistered from the true 0.1° latitudes by up to
half a cell near the equator. Following the single-level convention where
the cell count is one less than the file row count, set Ny=1800: the 1800
cells then sit at exactly -89.95:0.1:89.95, and the extra file row folds in
through `AverageNorthSouth` mangling (data_lat_count 1801 == Ny + 1). This
touches neither the variable dicts nor the verified netCDF short names.

Add a network-free "ERA5-Land dataset, metadata, and dispatch" testset to
test/test_cds_downloading.jl covering: construction and supported_datasets
membership, the 0.1° size/interfaces with exact cell spacing and the
AverageNorthSouth mangling, the variable-name dicts, trait dispatch,
all_dates, the CDSAPIExt dispatch helpers, product_type omission via the
set_product_type! hook, and the padded BoundingBox area (which is only
clean because Δφ = 180/1800 = 0.1, pinning the Ny=1800 choice).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant