From 040ce9a2f415009f7fd2640eceb15da0498e80e4 Mon Sep 17 00:00:00 2001 From: Ali Akherati Date: Wed, 19 Aug 2026 16:46:41 -0700 Subject: [PATCH 1/3] feat(studio): ERA5 in the product, the schema, and the wizard (task 1.1) Raised in use: "I do not see ERA5 data being utilized" -- correct. SCIENCE-1 and BLOCKING-5 decided ERA5 zonal-mean monthly; nothing implemented it. Now: The committed product. data/pipelines/era5_zonal_monthly.py fetches ERA5 monthly means (1991-2020 WMO normal, 15 levels 300-5 hPa, 2.5 deg -- ASSUMPTION-9) and reduces 343 MB of raw fields to a 0.1 MB (month x level x lat) npz, committed with a sha256 manifest. Raw ERA5 is never redistributed; the derived product is, with attribution. The loader verifies the checksum once per process and refuses to extrapolate outside 300-5 hPa. Schema 0.4.0. site.dataset (USER | ERA5) with the emission-system structure: entered given_temperature_k / given_h2o_ppmv kept-but-inert, temperature_k / h2o_ppmv DERIVED. Pressure stays entered -- it places the box, so it is the lookup's coordinate rather than its result. Default USER: every existing config resolves byte-identically. Provenance records the dataset id + checksum automatically for ERA5 runs (ProvenanceRecord.datasets, carried empty since Phase 0, now used); the seam refuses an unresolved temperature. The wizard: stage 1 gains the ERA5 temperature-profile panel, box marked on it. The physics tests paid for themselves before the first commit. The acceptance suite asserts the stratosphere looks like the stratosphere (tropical cold point 185-205 K, summer pole warmer than winter, H2O single-digit ppmv). The first cut shipped CDS's DESCENDING pressure levels into an interpolation that assumed ascending: every lookup silently read the 300 hPa row, and T(55 hPa) came back 240 K with 414 ppmv of water -- plausible at a glance, impossible as a stratosphere. Fixed in the pipeline (both axes sorted ascending) and REFUSED in the loader (a non-monotonic axis raises rather than being reordered, because the checksum pins what was read). The headline: ERA5 says 209.42 K at the ensemble's site (30N, June, 55 hPa) where the ensemble typed 210 K -- the paper's number confirmed to half a kelvin by 30 years of reanalysis. H2O is 4.15 ppmv against the typed 6.91 (RH = 3% assumption), consistent with the known reanalysis dry bias (MLS: issue #94). Tropical cold point 191.4 K. 357 Python Tier-A (+11 -- and the climatology tests run in CI, since the product is committed rather than gitignored or a submodule), 55 vitest. Hash 0.3.0 -> 0.4.0 (...7813ae -> ...d35ba6): same default run, three more fields describing it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EaDHnPdiacsybr8Tp5WnqR --- data/pipelines/era5_zonal_monthly.py | 153 ++++++++++++ docs/studio/ASSUMPTIONS.md | 22 ++ docs/studio/PROGRESS.md | 38 +++ docs/studio/plan/PHASE_1.md | 2 +- studio/modelio/preview.py | 38 ++- studio/modelio/provenance.py | 14 +- studio/modelio/scenario.py | 14 +- studio/resolve/registry.py | 55 ++++- studio/schema/config.py | 89 +++++-- studio/schema/enums.py | 19 ++ studio/schema/layout.py | 20 +- studio/science/climatology.py | 221 ++++++++++++++++++ .../science/data/era5_zonal_monthly_v1.json | 31 +++ studio/science/data/era5_zonal_monthly_v1.npz | Bin 0 -> 135872 bytes studio/tests/unit/test_api.py | 2 +- studio/tests/unit/test_cli.py | 2 +- studio/tests/unit/test_climatology.py | 163 +++++++++++++ studio/tests/unit/test_config_hash.py | 7 +- studio/tests/unit/test_modelio_equivalence.py | 4 +- studio/tests/unit/test_resolve_graph.py | 4 + studio/tests/unit/test_resolve_registry.py | 2 +- studio/tests/unit/test_resolve_resolver.py | 28 ++- studio/tests/unit/test_runner.py | 2 +- studio/tests/unit/test_schema_export.py | 2 +- studio/tests/unit/test_schema_metadata.py | 6 +- studio/tests/unit/test_web_contract.py | 6 +- studio/web/src/panels.tsx | 48 +++- studio/web/src/schema.test.ts | 12 +- 28 files changed, 942 insertions(+), 62 deletions(-) create mode 100644 data/pipelines/era5_zonal_monthly.py create mode 100644 studio/science/climatology.py create mode 100644 studio/science/data/era5_zonal_monthly_v1.json create mode 100644 studio/science/data/era5_zonal_monthly_v1.npz create mode 100644 studio/tests/unit/test_climatology.py diff --git a/data/pipelines/era5_zonal_monthly.py b/data/pipelines/era5_zonal_monthly.py new file mode 100644 index 0000000..97d55d7 --- /dev/null +++ b/data/pipelines/era5_zonal_monthly.py @@ -0,0 +1,153 @@ +# Copyright (C) 2026 University Corporation for Atmospheric Research +# SPDX-License-Identifier: Apache-2.0 +"""ERA5 -> the committed zonal-mean monthly climatology (task 1.1, SCIENCE-1, BLOCKING-5). + +Produces ``studio/science/data/era5_zonal_monthly_v1.npz`` and its manifest. The product is +(month x level x latitude) for temperature, specific humidity and geopotential height -- a few MB, +committed to the repository with a checksum, so no run ever fetches anything (ADR-006: the raw ERA5 +fields are NOT redistributed; the Copernicus licence permits derived products with attribution). + +Conventions, each a decision recorded in ASSUMPTIONS.md (ASSUMPTION-9): + +* **Years 1991-2020** -- the WMO standard climate normal, so "the June climatology" cites a + standard rather than a habit. +* **Zonal mean, monthly mean** -- SCIENCE-1's answer (issue #53), decided 2026-08-18. +* **2.5-degree grid** at retrieval. The zonal mean over 144 longitudes is insensitive to this, and + it keeps the download ~10^2 MB instead of gigabytes. Latitude resolution of the product is 2.5 + degrees; the lookup interpolates. +* **15 pressure levels, 300-5 hPa** -- the lower-to-middle stratosphere the box lives in. The + lookup refuses to extrapolate outside this range. + +Usage (this script does NOT run in Studio's locked venv -- it needs ``cdsapi``; make a scratch env): + + python -m venv /tmp/cds && /tmp/cds/bin/pip install cdsapi netCDF4 numpy + /tmp/cds/bin/python data/pipelines/era5_zonal_monthly.py fetch /path/to/raw/ + /tmp/cds/bin/python data/pipelines/era5_zonal_monthly.py reduce /path/to/raw/ + +``fetch`` needs ``~/.cdsapirc``. ``reduce`` writes the product and prints the sha256 that goes into +the manifest; commit both files together. +""" + +from __future__ import annotations + +import argparse +import datetime +import hashlib +import json +from pathlib import Path + +#: Pressure levels [hPa], descending altitude. The box's native coordinate is pressure (ADR-003). +LEVELS_HPA = [5, 7, 10, 20, 30, 50, 70, 100, 125, 150, 175, 200, 225, 250, 300] + +#: WMO standard climate normal. +YEARS = list(range(1991, 2021)) + +VARIABLES = {"temperature": "t", "specific_humidity": "q", "geopotential": "z"} + +#: Identifier recorded in every run's provenance when the ERA5 dataset is selected. +DATASET_ID = "era5_zonal_monthly_v1" + +#: Standard gravity [m s^-2], to turn geopotential into geopotential height (WMO value). +STANDARD_GRAVITY = 9.80665 + +PRODUCT = Path(__file__).resolve().parents[2] / "studio" / "science" / "data" + + +def fetch(raw_dir: Path) -> None: + """One CDS request per variable: each queues independently, and one failure loses one file.""" + import cdsapi + + client = cdsapi.Client(quiet=True) + for variable in VARIABLES: + target = raw_dir / f"era5_{variable}.nc" + print(f"requesting {variable} -> {target}") + client.retrieve( + "reanalysis-era5-pressure-levels-monthly-means", + { + "product_type": ["monthly_averaged_reanalysis"], + "variable": [variable], + "pressure_level": [str(level) for level in LEVELS_HPA], + "year": [str(year) for year in YEARS], + "month": [f"{month:02d}" for month in range(1, 13)], + "time": ["00:00"], + "data_format": "netcdf", + "grid": [2.5, 2.5], + }, + str(target), + ) + + +def reduce(raw_dir: Path) -> None: + """Raw monthly fields -> (month x level x lat) climatology, zonal mean then multi-year mean.""" + import netCDF4 + import numpy as np + + arrays: dict[str, "np.ndarray"] = {} + latitude = level = None + for variable, short in VARIABLES.items(): + with netCDF4.Dataset(raw_dir / f"era5_{variable}.nc") as ds: + data = np.asarray(ds[short][:], dtype=np.float64) # (time, level, lat, lon) + times = netCDF4.num2date(ds["valid_time"][:], ds["valid_time"].units) + months = np.asarray([t.month for t in times]) + years = np.asarray([t.year for t in times]) + latitude = np.asarray(ds["latitude"][:], dtype=np.float64) + level = np.asarray(ds["pressure_level"][:], dtype=np.float64) + expected = len(YEARS) * 12 + if data.shape[0] != expected: + raise SystemExit(f"{variable}: {data.shape[0]} months, expected {expected} -- refetch") + if sorted(set(years)) != YEARS: + raise SystemExit(f"{variable}: years {min(years)}-{max(years)} != {YEARS[0]}-{YEARS[-1]}") + zonal = data.mean(axis=3) # over longitude + monthly = np.stack([zonal[months == m].mean(axis=0) for m in range(1, 13)]) + arrays[short] = monthly.astype(np.float32) # (12, level, lat) + + assert latitude is not None and level is not None + # BOTH axes ascending, so the lookup's searchsorted works without a flip at read time. CDS + # delivers latitude 90..-90 and pressure levels 300..5; trusting either order as-is is how the + # first cut of this pipeline put the 300 hPa row under every lookup -- caught by the + # stratosphere-shaped physics tests (T(55 hPa) came back 240 K, a tropospheric number). + lat_order = np.argsort(latitude) + latitude = latitude[lat_order] + level_order = np.argsort(level) + level = level[level_order] + for short in arrays: + arrays[short] = arrays[short][:, level_order][:, :, lat_order] + + PRODUCT.mkdir(parents=True, exist_ok=True) + out = PRODUCT / f"{DATASET_ID}.npz" + np.savez_compressed( + out, + latitude_deg=latitude.astype(np.float32), + level_hpa=level.astype(np.float32), + month=np.arange(1, 13, dtype=np.int16), + temperature_k=arrays["t"], + specific_humidity_kg_kg=arrays["q"], + geopotential_height_m=(arrays["z"] / STANDARD_GRAVITY).astype(np.float32), + ) + digest = hashlib.sha256(out.read_bytes()).hexdigest() + manifest = { + "dataset_id": DATASET_ID, + "source": "ERA5 monthly averaged reanalysis on pressure levels (Copernicus CDS)", + "doi": "10.24381/cds.6860a573", + "licence": ( + "Contains modified Copernicus Climate Change Service information (1991-2020). " + "Derived product; raw ERA5 fields are not redistributed." + ), + "convention": "zonal mean, then 1991-2020 mean, per calendar month (SCIENCE-1, issue #53)", + "years": [YEARS[0], YEARS[-1]], + "grid_deg": 2.5, + "levels_hpa": LEVELS_HPA, + "created": datetime.date.today().isoformat(), + "sha256": digest, + } + (PRODUCT / f"{DATASET_ID}.json").write_text(json.dumps(manifest, indent=2) + "\n") + size_mb = out.stat().st_size / 1e6 + print(f"wrote {out} ({size_mb:.1f} MB), sha256={digest}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("command", choices=["fetch", "reduce"]) + parser.add_argument("raw_dir", type=Path) + args = parser.parse_args() + (fetch if args.command == "fetch" else reduce)(args.raw_dir) diff --git a/docs/studio/ASSUMPTIONS.md b/docs/studio/ASSUMPTIONS.md index 0824bc8..b249520 100644 --- a/docs/studio/ASSUMPTIONS.md +++ b/docs/studio/ASSUMPTIONS.md @@ -191,3 +191,25 @@ observations in ways this repository does not quantify. Per-dataset caveat that each background's diameters are **dry or ambient** is implicit in the dataset (`AMBIENT_BACKGROUNDS` in `coupled/backgrounds.py`) rather than a declared field. +## ASSUMPTION-9 — Climatology product conventions: 1991–2020, 2.5°, 15 levels, no extrapolation + +**Made:** 2026-08-19 · **Affects:** `era5_zonal_monthly_v1` (the committed product), and every run +with `site.dataset = ERA5` · **Tracks:** SCIENCE-1 (answered), #94 (other platforms) + +Four choices inside SCIENCE-1's answer that the answer itself did not fix: + +- **Years 1991–2020** — the WMO standard climate normal, so "the June climatology" cites a standard + rather than a habit. +- **2.5° retrieval grid.** The zonal mean over 144 longitudes is insensitive to this; it keeps the + raw download ~10² MB instead of gigabytes. The product's latitude resolution is therefore 2.5°, + interpolated linearly at lookup. +- **15 pressure levels, 300–5 hPa** — the lower-to-middle stratosphere the box lives in. Linear + interpolation in **log-pressure** between levels. +- **No extrapolation, ever.** Outside 300–5 hPa the derivation raises (ADR-005). A plausible + temperature for 400 hPa from a stratospheric product is exactly the fabricated number this + project forbids. + +**How to revisit.** Regenerate with `data/pipelines/era5_zonal_monthly.py` after editing its +constants; the product version in the filename and the manifest's sha256 change together, and +provenance pins which product each run used, so old runs stay attributable. + diff --git a/docs/studio/PROGRESS.md b/docs/studio/PROGRESS.md index c0a309d..028a8ad 100644 --- a/docs/studio/PROGRESS.md +++ b/docs/studio/PROGRESS.md @@ -29,6 +29,44 @@ derivations to resolve rather than fixtures. --- +### 2026-08-19 — Task 1.1: ERA5 is in the product, the schema, and the wizard + +Raised in use: *"I do not see ERA5 data being utilized"* — correct; the decisions existed and the +pipeline did not. Now: + +**The committed product.** `data/pipelines/era5_zonal_monthly.py` fetches ERA5 monthly means +(1991–2020, the WMO normal; 15 levels, 300–5 hPa; 2.5° grid — ASSUMPTION-9) and reduces 343 MB of +raw fields to a **0.1 MB** `(month × level × lat)` npz, committed at +`studio/science/data/era5_zonal_monthly_v1.npz` with a sha256 manifest. Raw ERA5 is not +redistributed; the derived product is, with attribution (BLOCKING-5). + +**The schema (0.4.0).** `site.dataset` (USER | ERA5) with the emission-system structure: entered +`given_temperature_k` / `given_h2o_ppmv` kept-but-inert, `temperature_k` / `h2o_ppmv` derived. +Pressure stays entered — it places the box, so it is the lookup's coordinate. Default USER, so every +existing config resolves byte-identically. Provenance records the dataset id + checksum +automatically for ERA5 runs (`ProvenanceRecord.datasets`, empty since Phase 0, now used). + +**The wizard.** Stage 1 gains the ERA5 temperature-profile panel with the box marked on it; under +USER it is context, under ERA5 the marker is the run's value. + +**The physics check that paid for itself twice.** The acceptance tests assert the stratosphere looks +like the stratosphere (tropical cold point 185–205 K, summer pole warmer than winter, H₂O single-digit +ppmv). The first cut of the pipeline shipped CDS's *descending* pressure levels into an interpolation +that assumed ascending — every lookup silently read the 300 hPa row, and T(55 hPa) came back 240 K +with 414 ppmv of water. Plausible numbers at a glance; impossible as a stratosphere. Fixed in the +pipeline (both axes sorted ascending) and refused in the loader (a non-monotonic axis raises rather +than being reordered, since the checksum pins what was read). + +**The headline.** ERA5 says **209.42 K** at the ensemble's site (30°N, June, 55 hPa) where the +ensemble typed **210 K** — the paper's number confirmed to half a kelvin by 30 years of reanalysis. +H₂O comes out 4.15 ppmv against the typed 6.91 (RH = 3% assumption), consistent with the known dry +bias (MLS is issue #94). Tropical cold point: 191.4 K. + +357 Python Tier-A (+11, all running in CI — the product is committed, so the climatology is the +first substantive science whose tests CI executes), 55 vitest. + +--- + ### 2026-08-18 — SCIENCE-2 and SCIENCE-3 answered; ERA5 confirmed Three decisions in one message, closing every science question that gated Phases 1–4 (only diff --git a/docs/studio/plan/PHASE_1.md b/docs/studio/plan/PHASE_1.md index 69c99aa..f8e6c61 100644 --- a/docs/studio/plan/PHASE_1.md +++ b/docs/studio/plan/PHASE_1.md @@ -29,7 +29,7 @@ All 42 schema fields are placed and rendered; `test_layout.py` fails if a new on - **1.0 Wizard shell** — *done (2026-08-17)*. Layout manifest, generated form, override/stale actions, review with diff, submit. React + Vite + TS per ADR-007. -- **1.1 Climatology product** — *unblocked (2026-08-18).* SCIENCE-1 is answered: **zonal-mean, +- **1.1 Climatology product** — *done (2026-08-19).* SCIENCE-1 is answered: **zonal-mean, monthly**, so the reduced product is `(lat × month × level)` — of order 86k values per field, a few MB, small enough to **commit with a checksum** rather than fetch at run time. Longitude stays an input for the solar zenith angle but does not select the meteorology, and the convention goes into diff --git a/studio/modelio/preview.py b/studio/modelio/preview.py index 7c99bfb..3e6dc02 100644 --- a/studio/modelio/preview.py +++ b/studio/modelio/preview.py @@ -226,9 +226,12 @@ def concentration_sensitivity(config: RunConfig) -> dict[str, Any]: resolved = resolve(config).config volume = resolved.injection.plume_volume_cm3 - if volume is None or volume <= 0.0: - raise ValueError("plume_volume_cm3 is unresolved; resolve the config before previewing") - air = air_number_density(resolved.site.pressure_mbar, resolved.site.temperature_k) + temperature = resolved.site.temperature_k + if volume is None or volume <= 0.0 or temperature is None: + raise ValueError( + "plume_volume_cm3 / temperature_k are unresolved; resolve the config before previewing" + ) + air = air_number_density(resolved.site.pressure_mbar, temperature) decades = 3.0 volumes = np.logspace( math.log10(volume) - decades, math.log10(volume) + decades, _CURVE_POINTS // 3 @@ -239,7 +242,7 @@ def concentration_sensitivity(config: RunConfig) -> dict[str, Any]: molar_mass_g_per_mol=SO2_MOLAR_MASS_G_PER_MOL, volume_cm3=float(v), pressure_mbar=resolved.site.pressure_mbar, - temperature_k=resolved.site.temperature_k, + temperature_k=temperature, ) for v in volumes ] @@ -253,10 +256,37 @@ def concentration_sensitivity(config: RunConfig) -> dict[str, Any]: } +def climatology_profile(config: RunConfig) -> dict[str, Any]: + """The ERA5 zonal-mean monthly profile at this latitude and month (stage 1). + + Drawn whatever the dataset selection: under USER it is context ("here is what ERA5 thinks this + place looks like") with the typed values marked against it; under ERA5 the marker IS the derived + value. Pure product read -- no model, no JAX. + """ + from studio.science.climatology import DATASET_ID, load, profile + + resolved = resolve(config).config + month = resolved.schedule.month + latitude = resolved.site.latitude_deg + data = profile(month=month, latitude_deg=latitude) + return { + **data, + "dataset_id": DATASET_ID, + "sha256_12": load().sha256[:12], + "month": month, + "latitude_deg": latitude, + "selected_dataset": resolved.site.dataset.value, + "box_pressure_mbar": resolved.site.pressure_mbar, + "box_temperature_k": resolved.site.temperature_k, + "box_h2o_ppmv": resolved.site.h2o_ppmv, + } + + #: Panel name -> builder. The API exposes exactly these, so a typo in a panel name is a 404 naming #: the ones that exist rather than an empty chart. PANELS = { "sza": sza_diurnal, + "climatology": climatology_profile, "dilution": dilution_curve, "size-distribution": size_distribution, "bins": bin_grid, diff --git a/studio/modelio/provenance.py b/studio/modelio/provenance.py index 2959e95..147f842 100644 --- a/studio/modelio/provenance.py +++ b/studio/modelio/provenance.py @@ -185,6 +185,18 @@ def record_for( """ config.require_consistent() root = repo_root or repository_root() + + # Datasets are recorded automatically from the config, not trusted to the caller: a run whose + # temperature came from the ERA5 climatology but whose provenance does not say so would defeat + # the point of ADR-006. The import is lazy and the load cached; under USER nothing is touched. + recorded_datasets = dict(datasets or {}) + from studio.schema.enums import ClimatologyDataset + + if config.config.site.dataset is ClimatologyDataset.ERA5: + from studio.science.climatology import load + + product = load() + recorded_datasets[product.dataset_id] = product.sha256 submodules = {} for name in MODEL_SUBMODULES: path = root / name @@ -201,7 +213,7 @@ def record_for( studio_version=studio.__version__, sandbox=describe_checkout(root), submodules=submodules, - datasets=dict(datasets or {}), + datasets=recorded_datasets, resolved_config=config.config.model_dump(mode="json"), overrides={path: record.value for path, record in sorted(config.overrides.items())}, ) diff --git a/studio/modelio/scenario.py b/studio/modelio/scenario.py index 5cf3846..a021473 100644 --- a/studio/modelio/scenario.py +++ b/studio/modelio/scenario.py @@ -74,6 +74,16 @@ def to_scenario(config: RunConfig | ResolvedConfig) -> CoupledScenario: "start with no SO2." ) + temperature = run.site.temperature_k + h2o = run.site.h2o_ppmv + if temperature is None or h2o is None: + raise ValueError( + "site.temperature_k / site.h2o_ppmv are unresolved. They are DERIVED fields since the " + "ambient state gained a dataset selector (SCIENCE-1): run the config through " + "studio.resolve.resolve() before converting it, rather than letting the model run at " + "a temperature nobody chose." + ) + day_of_year = run.schedule.day_of_year if day_of_year is None: raise ValueError( @@ -89,9 +99,9 @@ def to_scenario(config: RunConfig | ResolvedConfig) -> CoupledScenario: } return CoupledScenario( - T=run.site.temperature_k, + T=temperature, P=run.site.pressure_mbar, - WTR=run.site.h2o_ppmv, + WTR=h2o, latitude=run.site.latitude_deg, longitude=run.site.longitude_deg, day_of_year=day_of_year, diff --git a/studio/resolve/registry.py b/studio/resolve/registry.py index 6f72d97..80a1ade 100644 --- a/studio/resolve/registry.py +++ b/studio/resolve/registry.py @@ -22,7 +22,7 @@ from dataclasses import dataclass from typing import Any, Final -from studio.schema.enums import EmissionInput +from studio.schema.enums import ClimatologyDataset, EmissionInput from studio.science import ( SO2_MOLAR_MASS_G_PER_MOL, initial_mixing_ratio_pptv, @@ -64,6 +64,36 @@ def compute(self, values: Mapping[str, Any]) -> Any: return self.fn({path: values[path] for path in self.inputs}) +def _site_temperature(values: Mapping[str, Any]) -> float: + """The temperature the run uses: entered, or the ERA5 climatology at (lat, month, p). + + The import is inside the branch on purpose: under USER (the default) the climatology product is + never touched, so a checkout without it still resolves every existing config. + """ + if values["site.dataset"] != ClimatologyDataset.ERA5: + return float(values["site.given_temperature_k"]) + from studio.science.climatology import temperature_k + + return temperature_k( + month=values["schedule.month"], + latitude_deg=values["site.latitude_deg"], + pressure_mbar=values["site.pressure_mbar"], + ) + + +def _site_h2o(values: Mapping[str, Any]) -> float: + """The water vapour the run uses: entered, or ERA5 specific humidity as ppmv.""" + if values["site.dataset"] != ClimatologyDataset.ERA5: + return float(values["site.given_h2o_ppmv"]) + from studio.science.climatology import h2o_ppmv + + return h2o_ppmv( + month=values["schedule.month"], + latitude_deg=values["site.latitude_deg"], + pressure_mbar=values["site.pressure_mbar"], + ) + + def _day_of_year(values: Mapping[str, Any]) -> int: """(month, day) -> day of year on the fixed non-leap calendar (SCIENCE-1).""" return calendar_day_of_year( @@ -164,6 +194,29 @@ def _so2_initial_pptv(values: Mapping[str, Any]) -> float: #: Derived field path -> how to compute it. Completeness against the schema is enforced by test. DERIVATIONS: Final[dict[str, Derivation]] = { + "site.temperature_k": Derivation( + inputs=( + "site.dataset", + "site.given_temperature_k", + "site.latitude_deg", + "site.pressure_mbar", + "schedule.month", + ), + fn=_site_temperature, + summary="the entered temperature, or the ERA5 zonal-mean monthly climatology at " + "(latitude, month, pressure)", + ), + "site.h2o_ppmv": Derivation( + inputs=( + "site.dataset", + "site.given_h2o_ppmv", + "site.latitude_deg", + "site.pressure_mbar", + "schedule.month", + ), + fn=_site_h2o, + summary="the entered water vapour, or ERA5 specific humidity converted to ppmv", + ), "schedule.day_of_year": Derivation( inputs=("schedule.month", "schedule.day_of_month"), fn=_day_of_year, diff --git a/studio/schema/config.py b/studio/schema/config.py index 9e0b955..513aaf1 100644 --- a/studio/schema/config.py +++ b/studio/schema/config.py @@ -38,6 +38,7 @@ from studio.schema.enums import ( BackgroundAerosol, + ClimatologyDataset, DilutionRegime, EmissionInput, PhotolysisMode, @@ -48,7 +49,7 @@ #: The schema's own version. Bumped on any change to field names, semantics or defaults, because #: those change the config hash and therefore run identity (ADR-006). Old configs are never silently #: reinterpreted under new semantics. -SCHEMA_VERSION = "0.3.0" +SCHEMA_VERSION = "0.4.0" #: Stratospheric background gas composition [pptv] used by the 810-run ensemble #: (``run_ensemble.py:56-57``). Module-level so the default is one object with one source, and so a @@ -80,9 +81,12 @@ class SchemaModel(BaseModel): class Site(SchemaModel): """Where the box is, and the thermodynamic state it sits in. - Phase 0 takes T and p as user input. Phase 1 derives them from climatology at a chosen - (lat, lon, altitude-or-tropopause-relative) point -- which is why they are primary fields now - and become ``derived_from`` targets later, not the other way round. + The ambient state has a selectable source (Phase 1): under ``dataset = USER`` the given values + are used as typed; under ``ERA5`` temperature and water vapour are derived from the committed + zonal-mean monthly climatology (SCIENCE-1) at this latitude, month and pressure. Pressure is + always entered -- it is what places the box, so it is the coordinate of the lookup rather than + a result of it. Same structure as the emission system: entered ``given_*`` values that are kept + but inert when unselected, and derived used-values the model reads. """ latitude_deg: float = SciField( @@ -110,15 +114,28 @@ class Site(SchemaModel): provenance=Provenance.PAPER_ENSEMBLE, source="coupled/paper_ensemble/run_ensemble.py:98", ) - temperature_k: float = SciField( + dataset: ClimatologyDataset = SciField( + default=ClimatologyDataset.USER, + unit=Unit.DIMENSIONLESS, + label="Ambient state from", + description=( + "Source of temperature and water vapour. USER takes the given values as typed; ERA5 " + "derives both from the committed zonal-mean monthly climatology (1991-2020) at this " + "latitude, month and pressure. Pressure is always entered: it places the box, so it " + "is the lookup's coordinate, not its result." + ), + provenance=Provenance.CONVENTION, + source="SCIENCE-1 (issue #53), answered 2026-08-18: zonal-mean monthly, ERA5", + ) + given_temperature_k: float = SciField( default=210.0, unit=Unit.KELVIN, gt=0.0, - label="Temperature", + label="Temperature (entered)", description=( - "Box temperature. The box is isobaric and ISOTHERMAL: the temperature feedback is " - "refused while the radiative calculation has no longwave component, so this value " - "holds for the whole run. See switches.heating_to_t and SCIENCE-4 (issue #56)." + "Box temperature as typed. Used when dataset is USER; under ERA5 the temperature is " + "derived and this value is inert. The box is isobaric and ISOTHERMAL either way " + "(SCIENCE-4): whatever the source, the value holds for the whole run." ), provenance=Provenance.PAPER_ENSEMBLE, source="coupled/paper_ensemble/TABLE_microphysics_parameters.md (Site: 210 K, 55 hPa)", @@ -131,27 +148,63 @@ class Site(SchemaModel): label="Pressure", description=( "Box pressure, the model's native pressure unit (mbar == hPa). Also sets the box " - "altitude used to place the aerosol in the TUV-x radiation column." + "altitude used to place the aerosol in the TUV-x radiation column, and is the " + "vertical coordinate of the climatology lookup when dataset is ERA5." ), provenance=Provenance.PAPER_ENSEMBLE, source="coupled/paper_ensemble/TABLE_microphysics_parameters.md (Site: 210 K, 55 hPa)", examples=[55.0, 120.0], ) - h2o_ppmv: float = SciField( + given_h2o_ppmv: float = SciField( default=6.9104, unit=Unit.PPMV, ge=0.0, - label="Water vapour", + label="Water vapour (entered)", description=( - "Water vapour mixing ratio. The ensemble value is RH = 3% precomputed at 210 K / " - "55 hPa; it is a decimal in native units on purpose (ADR-003) -- do not round-trip it " - "through SI." + "Water vapour mixing ratio as typed. Used when dataset is USER; under ERA5 it is " + "derived and this value is inert. The ensemble value is RH = 3% precomputed at " + "210 K / 55 hPa, a decimal in native units on purpose (ADR-003)." ), provenance=Provenance.PAPER_ENSEMBLE, source="coupled/paper_ensemble/run_ensemble.py:62 (LAT_ALT WTR column, RH = 3%)", + ) + temperature_k: float | None = SciField( + default=None, + unit=Unit.KELVIN, + label="Temperature (used)", + description=( + "The temperature the run uses: the entered value, or the ERA5 zonal-mean monthly " + "climatology interpolated to this latitude, month and pressure. Isothermal for the " + "whole run (SCIENCE-4)." + ), + provenance=Provenance.DERIVED, + derived_from=[ + "site.dataset", + "site.given_temperature_k", + "site.latitude_deg", + "site.pressure_mbar", + "schedule.month", + ], + ) + h2o_ppmv: float | None = SciField( + default=None, + unit=Unit.PPMV, + label="Water vapour (used)", + description=( + "The water vapour the run uses: the entered value, or ERA5 specific humidity " + "converted to a volume mixing ratio at this latitude, month and pressure." + ), + provenance=Provenance.DERIVED, + derived_from=[ + "site.dataset", + "site.given_h2o_ppmv", + "site.latitude_deg", + "site.pressure_mbar", + "schedule.month", + ], caveat=( - "Reanalysis stratospheric water vapour is biased dry, so ERA5 is not the recommended " - "source for this field when Phase 1 lands (BLOCKING-5)." + "Reanalysis stratospheric water vapour is biased dry (BLOCKING-5), so the ERA5 value " + "is a floor more than an estimate; MLS as a dedicated H2O source is issue #94." ), ) @@ -853,7 +906,7 @@ class RunConfig(SchemaModel): physics, and two runs whose only difference is a name are the same computation. """ - schema_version: Literal["0.3.0"] = SciField( + schema_version: Literal["0.4.0"] = SciField( default=SCHEMA_VERSION, unit=Unit.DIMENSIONLESS, label="Schema version", diff --git a/studio/schema/enums.py b/studio/schema/enums.py index 0450194..ad10ed7 100644 --- a/studio/schema/enums.py +++ b/studio/schema/enums.py @@ -123,6 +123,24 @@ class EmissionInput(StrEnum): EMISSION_DURATION = "emission_duration" +class ClimatologyDataset(StrEnum): + """Where stage 1's ambient state comes from. + + USER keeps the values typed -- the paper ensemble's parameterisation, and the default, so + existing configs keep their meaning. ERA5 derives temperature and water vapour from the + committed zonal-mean monthly climatology (SCIENCE-1) at this config's latitude, month and + pressure; pressure itself stays entered, because it is what places the box. + + One member per product that EXISTS. MERRA-2 and MLS are issue #94, and adding an enum member + before its product would let a config claim a derivation that cannot run (ADR-005). + """ + + #: Ambient state typed directly (default; the ensemble's own values). + USER = "user" + #: ERA5 zonal-mean monthly climatology, 1991-2020 (era5_zonal_monthly_v1, SCIENCE-1). + ERA5 = "era5" + + class AxisKind(StrEnum): """How a ``RunSet`` axis combines with the others. See ``studio/schema/runset.py``.""" @@ -139,6 +157,7 @@ class AxisKind(StrEnum): __all__ = [ "AxisKind", "BackgroundAerosol", + "ClimatologyDataset", "DilutionRegime", "EmissionInput", "PhotolysisMode", diff --git a/studio/schema/layout.py b/studio/schema/layout.py index ee2bc23..623b421 100644 --- a/studio/schema/layout.py +++ b/studio/schema/layout.py @@ -91,10 +91,22 @@ class Stage: ), Section( title="Ambient state", - fields=("site.temperature_k", "site.pressure_mbar", "site.h2o_ppmv"), - note="Entered directly today. SCIENCE-1 is answered (zonal-mean monthly, ERA5), so " - "the climatology-derived p/T arrives with the reduced product (task 1.1); until " - "then these are typed.", + fields=( + "site.dataset", + "site.pressure_mbar", + "site.given_temperature_k", + "site.given_h2o_ppmv", + ), + note="Pressure is always entered -- it places the box, so it is the climatology " + "lookup's coordinate rather than its result. The entered T and H2O are used under " + "USER and kept but inert under ERA5.", + ), + Section( + title="And the run uses", + fields=("site.temperature_k", "site.h2o_ppmv"), + note="Entered values, or the ERA5 zonal-mean monthly climatology (1991-2020, " + "SCIENCE-1) interpolated to this latitude, month and pressure. ERA5 water vapour " + "is biased dry (BLOCKING-5); MLS as a dedicated H2O source is issue #94.", ), Section( title="Date and time", diff --git a/studio/science/climatology.py b/studio/science/climatology.py new file mode 100644 index 0000000..d70cf0f --- /dev/null +++ b/studio/science/climatology.py @@ -0,0 +1,221 @@ +# Copyright (C) 2026 University Corporation for Atmospheric Research +# SPDX-License-Identifier: Apache-2.0 +"""Reading the committed ERA5 zonal-mean monthly climatology (SCIENCE-1). + +The product is built by ``data/pipelines/era5_zonal_monthly.py`` and committed at +``studio/science/data/era5_zonal_monthly_v1.npz`` with a manifest carrying its sha256. This module +is the ONLY reader: it verifies the checksum once per process, interpolates, and refuses to +extrapolate. No fetching happens here or anywhere at run time (ADR-006). + +Interpolation choices, stated because they are conventions: + +* **Linear in latitude** between the product's 2.5-degree rows. Zonal-mean fields are smooth at + this scale; the residual against the 0.25-degree native grid is far below interannual spread. +* **Linear in log-pressure** between levels, because temperature is closer to linear in log-p than + in p through the stratosphere (pressure falls exponentially with height). +* **No extrapolation.** Outside 300-5 hPa the derivation raises rather than guessing (ADR-005): a + plausible temperature for 400 hPa from a stratospheric product is exactly the fabricated number + this project forbids. +""" + +from __future__ import annotations + +import hashlib +import json +from functools import lru_cache +from pathlib import Path +from typing import Final, NamedTuple + +import numpy as np +import numpy.typing as npt + +#: Molar masses [g mol^-1]: dry air (US Standard Atmosphere 1976), water (CODATA). +MOLAR_MASS_DRY_AIR_G_PER_MOL: Final = 28.9644 +MOLAR_MASS_WATER_G_PER_MOL: Final = 18.0153 + +#: The committed product this module reads. +DATASET_ID: Final = "era5_zonal_monthly_v1" + +_DATA_DIR = Path(__file__).resolve().parent / "data" + + +class Climatology(NamedTuple): + """The product in memory. Arrays are (month, level, latitude); axes ascend except level.""" + + latitude_deg: npt.NDArray[np.floating] + level_hpa: npt.NDArray[np.floating] + temperature_k: npt.NDArray[np.floating] + specific_humidity_kg_kg: npt.NDArray[np.floating] + geopotential_height_m: npt.NDArray[np.floating] + dataset_id: str + sha256: str + + +class ClimatologyUnavailableError(FileNotFoundError): + """The committed product is missing -- regenerate it, never substitute for it.""" + + +@lru_cache(maxsize=1) +def load() -> Climatology: + """Load and checksum-verify the product, once per process. + + Raises: + ClimatologyUnavailableError: If the product or its manifest is absent. The message carries + the regeneration commands, because the reader who hits this is holding a fresh clone. + ValueError: If the file does not match the manifest's sha256 -- an edited or corrupted + product must not silently feed runs (ADR-006). + """ + npz_path = _DATA_DIR / f"{DATASET_ID}.npz" + manifest_path = _DATA_DIR / f"{DATASET_ID}.json" + if not npz_path.is_file() or not manifest_path.is_file(): + raise ClimatologyUnavailableError( + f"the ERA5 climatology product is not present at {npz_path}. It is committed to the " + f"repository, so this means an incomplete checkout or a build that stripped data " + f"files. To regenerate: data/pipelines/era5_zonal_monthly.py (fetch, then reduce; " + f"needs ~/.cdsapirc). Never substitute a fabricated profile." + ) + manifest = json.loads(manifest_path.read_text()) + digest = hashlib.sha256(npz_path.read_bytes()).hexdigest() + if digest != manifest["sha256"]: + raise ValueError( + f"{npz_path.name} does not match its manifest: sha256 {digest} != " + f"{manifest['sha256']}. The product or the manifest was modified; regenerate both " + f"together with data/pipelines/era5_zonal_monthly.py." + ) + with np.load(npz_path) as data: + # Refuse, not fix: the interpolation's searchsorted requires ascending axes, and the first + # cut of the pipeline shipped descending levels. A product violating this is regenerated, + # never silently reordered here -- the checksum pins WHAT was read, so the reader must not + # change what it means. + for axis in ("latitude_deg", "level_hpa"): + values = data[axis] + if not np.all(np.diff(values) > 0): + raise ValueError( + f"{npz_path.name}: {axis} is not strictly ascending; the product predates the " + f"axis-order fix -- regenerate it with data/pipelines/era5_zonal_monthly.py" + ) + return Climatology( + latitude_deg=data["latitude_deg"].astype(np.float64), + level_hpa=data["level_hpa"].astype(np.float64), + temperature_k=data["temperature_k"].astype(np.float64), + specific_humidity_kg_kg=data["specific_humidity_kg_kg"].astype(np.float64), + geopotential_height_m=data["geopotential_height_m"].astype(np.float64), + dataset_id=str(manifest["dataset_id"]), + sha256=digest, + ) + + +def _interpolate( + field: npt.NDArray[np.floating], + *, + month: int, + latitude_deg: float, + pressure_mbar: float, + climatology: Climatology, +) -> float: + """Bilinear in (latitude, log-pressure) at an exact month. Refuses to extrapolate.""" + if not 1 <= month <= 12: + raise ValueError(f"month must be 1-12, got {month}") + lats = climatology.latitude_deg + if not lats[0] <= latitude_deg <= lats[-1]: + raise ValueError(f"latitude {latitude_deg} outside the product's {lats[0]}..{lats[-1]}") + levels = climatology.level_hpa # strictly ascending; enforced at load + p_lo, p_hi = float(levels.min()), float(levels.max()) + if not p_lo <= pressure_mbar <= p_hi: + raise ValueError( + f"pressure {pressure_mbar} mbar is outside the climatology's {p_lo:g}-{p_hi:g} hPa. " + f"The product covers the lower-to-middle stratosphere; extrapolating a stratospheric " + f"profile would fabricate a value (ADR-005)." + ) + plane = field[month - 1] # (level, lat) + + # latitude bracket + j = int(np.searchsorted(lats, latitude_deg)) + j0, j1 = max(j - 1, 0), min(j, len(lats) - 1) + w_lat = 0.0 if j0 == j1 else (latitude_deg - lats[j0]) / (lats[j1] - lats[j0]) + + # log-pressure bracket (ascending, enforced at load) + logp = np.log(levels) + target = float(np.log(pressure_mbar)) + i = int(np.searchsorted(logp, target)) + i0, i1 = max(i - 1, 0), min(i, len(levels) - 1) + w_p = 0.0 if i0 == i1 else (target - logp[i0]) / (logp[i1] - logp[i0]) + + v00, v01 = plane[i0, j0], plane[i0, j1] + v10, v11 = plane[i1, j0], plane[i1, j1] + return float( + (1 - w_p) * ((1 - w_lat) * v00 + w_lat * v01) + w_p * ((1 - w_lat) * v10 + w_lat * v11) + ) + + +def temperature_k(*, month: int, latitude_deg: float, pressure_mbar: float) -> float: + """Climatological temperature at (month, latitude, pressure).""" + c = load() + return _interpolate( + c.temperature_k, + month=month, + latitude_deg=latitude_deg, + pressure_mbar=pressure_mbar, + climatology=c, + ) + + +def specific_humidity_to_ppmv(q_kg_kg: float) -> float: + """Specific humidity (kg water / kg moist air) -> volume mixing ratio [ppmv]. + + Exact mole-fraction form, not the dilute approximation: x = (q/Mw) / (q/Mw + (1-q)/Md). + At stratospheric q ~ 3e-6 the two differ negligibly, but the exact form costs nothing and + removes an approximation nobody needs to remember. + """ + if q_kg_kg < 0.0: + raise ValueError(f"specific humidity cannot be negative, got {q_kg_kg}") + moles_water = q_kg_kg / MOLAR_MASS_WATER_G_PER_MOL + moles_dry = (1.0 - q_kg_kg) / MOLAR_MASS_DRY_AIR_G_PER_MOL + return moles_water / (moles_water + moles_dry) * 1e6 + + +def h2o_ppmv(*, month: int, latitude_deg: float, pressure_mbar: float) -> float: + """Climatological water vapour at (month, latitude, pressure), in the model's ppmv. + + Carries the same caveat as the schema field: reanalysis stratospheric water vapour is biased + dry (BLOCKING-5); MLS as a dedicated H2O source is issue #94. + """ + c = load() + q = _interpolate( + c.specific_humidity_kg_kg, + month=month, + latitude_deg=latitude_deg, + pressure_mbar=pressure_mbar, + climatology=c, + ) + return specific_humidity_to_ppmv(q) + + +def profile(*, month: int, latitude_deg: float) -> dict[str, list[float]]: + """T and H2O against pressure at (month, latitude) -- the stage-1 preview panel's data.""" + c = load() + out_t, out_q = [], [] + for level in c.level_hpa: + out_t.append( + temperature_k(month=month, latitude_deg=latitude_deg, pressure_mbar=float(level)) + ) + out_q.append(h2o_ppmv(month=month, latitude_deg=latitude_deg, pressure_mbar=float(level))) + return { + "level_hpa": [float(level) for level in c.level_hpa], + "temperature_k": out_t, + "h2o_ppmv": out_q, + } + + +__all__ = [ + "DATASET_ID", + "MOLAR_MASS_DRY_AIR_G_PER_MOL", + "MOLAR_MASS_WATER_G_PER_MOL", + "Climatology", + "ClimatologyUnavailableError", + "h2o_ppmv", + "load", + "profile", + "specific_humidity_to_ppmv", + "temperature_k", +] diff --git a/studio/science/data/era5_zonal_monthly_v1.json b/studio/science/data/era5_zonal_monthly_v1.json new file mode 100644 index 0000000..8db98c4 --- /dev/null +++ b/studio/science/data/era5_zonal_monthly_v1.json @@ -0,0 +1,31 @@ +{ + "dataset_id": "era5_zonal_monthly_v1", + "source": "ERA5 monthly averaged reanalysis on pressure levels (Copernicus CDS)", + "doi": "10.24381/cds.6860a573", + "licence": "Contains modified Copernicus Climate Change Service information (1991-2020). Derived product; raw ERA5 fields are not redistributed.", + "convention": "zonal mean, then 1991-2020 mean, per calendar month (SCIENCE-1, issue #53)", + "years": [ + 1991, + 2020 + ], + "grid_deg": 2.5, + "levels_hpa": [ + 5, + 7, + 10, + 20, + 30, + 50, + 70, + 100, + 125, + 150, + 175, + 200, + 225, + 250, + 300 + ], + "created": "2026-08-19", + "sha256": "617617884a1a7bab5700e0561b90bf35eebdf0fb12703049ebcae66d143fc078" +} diff --git a/studio/science/data/era5_zonal_monthly_v1.npz b/studio/science/data/era5_zonal_monthly_v1.npz new file mode 100644 index 0000000000000000000000000000000000000000..e9acf01ca9c29ebfe1f0ab3aca3ca4fd6f3a2846 GIT binary patch literal 135872 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 literal 0 HcmV?d00001 diff --git a/studio/tests/unit/test_api.py b/studio/tests/unit/test_api.py index 0d8f309..43de7c5 100644 --- a/studio/tests/unit/test_api.py +++ b/studio/tests/unit/test_api.py @@ -71,7 +71,7 @@ def test_resolve_returns_the_derived_values_and_the_identity(api: Any) -> None: @pytest.mark.parametrize( "config", [ - {"site": {"temperature_k": -5}}, + {"site": {"given_temperature_k": -5}}, {"microphysics": {"n_bins": 100}}, {"switches": {"heating_to_t": True}}, {"site": {"temprature_k": 210}}, diff --git a/studio/tests/unit/test_cli.py b/studio/tests/unit/test_cli.py index 5d71281..0c0d447 100644 --- a/studio/tests/unit/test_cli.py +++ b/studio/tests/unit/test_cli.py @@ -117,7 +117,7 @@ def test_planned_runs_have_distinct_identities(sweep_file: Path) -> None: [ ("not: [valid", "not valid"), ("- a\n- b\n", "must contain a mapping"), - ("site:\n temperature_k: -5\n", "not a valid configuration"), + ("site:\n given_temperature_k: -5\n", "not a valid configuration"), ], ) def test_a_bad_config_file_exits_two_with_a_message( diff --git a/studio/tests/unit/test_climatology.py b/studio/tests/unit/test_climatology.py new file mode 100644 index 0000000..2c89d8e --- /dev/null +++ b/studio/tests/unit/test_climatology.py @@ -0,0 +1,163 @@ +# Copyright (C) 2026 University Corporation for Atmospheric Research +# SPDX-License-Identifier: Apache-2.0 +"""The ERA5 zonal-mean monthly climatology: the product, its reader, and the derivations over it. + +Unlike the model-facing tests, these run in CI: the product is COMMITTED (a few MB of npz), not a +gitignored artefact or a submodule. That is deliberate -- it means the climatology path is the first +scientifically substantive code whose tests CI can actually execute. + +The physics assertions use wide, cited bounds. They are not testing ERA5 (ERA5 is the reference); +they are testing that the reduction and interpolation did not scramble axes -- a transposed +(month, level, lat) array still produces plausible-looking numbers at any single point, but it +cannot produce a colder tropical tropopause than midlatitude one AND a summer-warm polar +stratosphere at once. +""" + +from __future__ import annotations + +import pytest + +from studio.resolve import apply_change, resolve +from studio.schema import RunConfig +from studio.science import climatology + + +def _era5(**site: object) -> RunConfig: + return RunConfig.model_validate({"site": {"dataset": "era5", **site}}) + + +@pytest.mark.tier_a +def test_the_product_is_committed_and_matches_its_manifest() -> None: + """Presence and integrity: the sha256 in the manifest is the one the loader verifies.""" + product = climatology.load() + assert product.dataset_id == climatology.DATASET_ID + assert product.temperature_k.shape == (12, len(product.level_hpa), len(product.latitude_deg)) + assert len(product.sha256) == 64 + + +@pytest.mark.tier_a +def test_the_interpolation_is_exact_at_grid_points() -> None: + """At a node of the product, interpolation must return the stored value bit-for-bit.""" + product = climatology.load() + month, level_index, lat_index = 6, 5, 48 # arbitrary interior node + expected = float(product.temperature_k[month - 1, level_index, lat_index]) + got = climatology.temperature_k( + month=month, + latitude_deg=float(product.latitude_deg[lat_index]), + pressure_mbar=float(product.level_hpa[level_index]), + ) + assert got == expected + + +@pytest.mark.tier_a +def test_no_extrapolation_ever() -> None: + """Outside 300-5 hPa the lookup raises rather than guessing (ADR-005).""" + for pressure in (400.0, 1000.0, 2.0): + with pytest.raises(ValueError, match="outside the climatology"): + climatology.temperature_k(month=6, latitude_deg=30.0, pressure_mbar=pressure) + + +@pytest.mark.tier_a +def test_the_stratosphere_looks_like_the_stratosphere() -> None: + """Axis-scrambling detectors, with generous bounds. + + * The tropical tropopause region (~100 hPa) is the coldest place in the product's domain: + ~190-205 K climatologically (Seidel et al. 2001 put the tropical cold point near 190 K). + * 30N at ~50 hPa in June sits near 210-220 K -- the paper ensemble's 210 K at 55 hPa is + exactly this number, which is the strongest single check available. + * The summer polar stratosphere is WARMER than the winter one at 30 hPa by tens of kelvin + (no polar night jet in summer). + """ + tropical_tropopause = climatology.temperature_k(month=2, latitude_deg=0.0, pressure_mbar=100.0) + assert 185.0 < tropical_tropopause < 205.0 + + ensemble_site = climatology.temperature_k(month=6, latitude_deg=30.0, pressure_mbar=55.0) + assert 205.0 < ensemble_site < 222.0 + + july_arctic = climatology.temperature_k(month=7, latitude_deg=80.0, pressure_mbar=30.0) + january_arctic = climatology.temperature_k(month=1, latitude_deg=80.0, pressure_mbar=30.0) + assert july_arctic > january_arctic + 10.0, "summer pole must be warmer than winter pole" + + +@pytest.mark.tier_a +def test_stratospheric_water_vapour_is_a_few_ppmv() -> None: + """The wet stratosphere is single-digit ppmv (3-8 typical); 100x off means a unit slipped. + + The q -> ppmv conversion is where a silent factor would live, so the bound is deliberately + tight enough to catch Mw/Md swapped (x1.6) as well as kg/g confusions (x1000). + """ + value = climatology.h2o_ppmv(month=6, latitude_deg=30.0, pressure_mbar=55.0) + assert 2.0 < value < 10.0, f"{value} ppmv is not a stratospheric water vapour value" + + +@pytest.mark.tier_a +def test_the_conversion_is_the_exact_mole_fraction_form() -> None: + assert climatology.specific_humidity_to_ppmv(0.0) == 0.0 + # Dilute limit: q * Md/Mw * 1e6, to first order. + approx = 3e-6 * (28.9644 / 18.0153) * 1e6 + assert climatology.specific_humidity_to_ppmv(3e-6) == pytest.approx(approx, rel=1e-5) + with pytest.raises(ValueError, match="negative"): + climatology.specific_humidity_to_ppmv(-1e-6) + + +@pytest.mark.tier_a +def test_era5_dataset_derives_the_ambient_state() -> None: + """The schema path end to end: dataset=ERA5 fills T and H2O from the product.""" + resolved = resolve(_era5()).config + assert resolved.site.temperature_k == pytest.approx( + climatology.temperature_k(month=6, latitude_deg=30.0, pressure_mbar=55.0) + ) + assert resolved.site.h2o_ppmv == pytest.approx( + climatology.h2o_ppmv(month=6, latitude_deg=30.0, pressure_mbar=55.0) + ) + # The given values are kept but inert, exactly as in the emission system. + assert resolved.site.given_temperature_k == 210.0 + + +@pytest.mark.tier_a +def test_user_dataset_is_byte_identical_to_the_old_behaviour() -> None: + """The default path must not so much as touch the product.""" + resolved = resolve(RunConfig()).config + assert resolved.site.temperature_k == 210.0 + assert resolved.site.h2o_ppmv == 6.9104 + assert resolved.injection.so2_initial_pptv == pytest.approx(3309115922.996412, rel=1e-15) + + +@pytest.mark.tier_a +def test_changing_the_month_moves_the_era5_temperature() -> None: + """The wizard's claim, on real data: edit the month, the ambient state follows.""" + june = resolve(_era5()) + december = apply_change(june, "schedule.month", 12) + t_june = june.config.site.temperature_k + t_december = december.config.site.temperature_k + assert t_june is not None and t_december is not None + assert t_june != t_december, "30N at 55 hPa has a real seasonal cycle" + assert december.is_consistent + + +@pytest.mark.tier_a +def test_the_concentration_follows_the_era5_temperature() -> None: + """The chain reaches the model's input: T from ERA5 changes the air density, so the pptv.""" + user = resolve(RunConfig()).config + era5 = resolve(_era5()).config + assert era5.site.temperature_k is not None and user.site.temperature_k is not None + if era5.site.temperature_k != user.site.temperature_k: + assert era5.injection.so2_initial_pptv != user.injection.so2_initial_pptv + # Same number density either way; pptv scales with T at fixed p (ideal gas). + ratio = era5.injection.so2_initial_pptv / user.injection.so2_initial_pptv + assert ratio == pytest.approx(era5.site.temperature_k / user.site.temperature_k, rel=1e-12) + + +@pytest.mark.tier_a +def test_era5_runs_record_the_dataset_in_provenance(repo_root: object) -> None: + """ADR-006: a run whose temperature came from ERA5 must say so, with the checksum.""" + from pathlib import Path + + from studio.modelio.provenance import record_for + + root = repo_root if isinstance(repo_root, Path) else None + if root is None or not (root / "stratchem-jax" / ".git").exists(): + pytest.skip("model submodules not checked out") + record = record_for(resolve(_era5()), repo_root=root) + assert record.datasets == {climatology.DATASET_ID: climatology.load().sha256} + assert record_for(resolve(RunConfig()), repo_root=root).datasets == {} diff --git a/studio/tests/unit/test_config_hash.py b/studio/tests/unit/test_config_hash.py index bd13377..8e8fd56 100644 --- a/studio/tests/unit/test_config_hash.py +++ b/studio/tests/unit/test_config_hash.py @@ -34,7 +34,10 @@ #: * ...46cbe3 -> ...373ab4 (0.2.0) when the temperature feedback was refused. The VALUE of #: heating_to_t did not change -- False either way -- but schema_version is part of the hashed #: payload, which is what makes "old configs are never silently reinterpreted" true. -#: * ...6d3a73 -> the value below, still 0.3.0 and unmerged, when the release date became a month +#: * 0.3.0 -> 0.4.0 when the ambient state gained its dataset selector (SCIENCE-1 implemented): +#: given_temperature_k / given_h2o_ppmv entered, temperature_k / h2o_ppmv derived. The default RUN +#: is unchanged -- USER dataset, the same 210 K -- but the config has three more fields. +#: * ...6d3a73 -> ...7813ae, still 0.3.0 and unmerged, when the release date became a month #: and a day with day_of_year derived (SCIENCE-1: the climatology is a monthly average, so there #: is no year, and the month must not be enterable twice). #: * ...373ab4 -> ...6d3a73 (0.3.0) when the emission system arrived: a selector for which @@ -44,7 +47,7 @@ #: the last bit -- but the config that describes it now has four more fields, so it is a different #: configuration and must hash differently. A schema that grew a field without moving the hash #: would be one where two different configs could share an identity. -GOLDEN_DEFAULT_HASH = "a201086e2dc9039fe95b0d11bd184a7fccad39b5c9cbca83ee83c766957813ae" +GOLDEN_DEFAULT_HASH = "b8ca6becb22b49668e22d1f2dce8451b79bd3159c82fb0966cce182ccdd35ba6" @pytest.mark.tier_a diff --git a/studio/tests/unit/test_modelio_equivalence.py b/studio/tests/unit/test_modelio_equivalence.py index da7f432..34d8d28 100644 --- a/studio/tests/unit/test_modelio_equivalence.py +++ b/studio/tests/unit/test_modelio_equivalence.py @@ -63,7 +63,9 @@ def studio_scenario() -> Any: def test_the_golden_case_is_the_schemas_default(build_scenario: Any) -> None: """``RunConfig()`` with no arguments IS the golden case; nothing has to be set up to get it.""" reference = build_scenario(GOLDEN_AXES) - config = RunConfig() + # temperature_k is DERIVED since 0.4.0 (dataset selector), so the default config resolves it; + # under the default USER dataset it must equal the entered value, which is the golden case's. + config = resolve(RunConfig()).config assert config.site.temperature_k == reference.T assert config.site.pressure_mbar == reference.P assert config.background.aerosol is BackgroundAerosol.SABR_220 diff --git a/studio/tests/unit/test_resolve_graph.py b/studio/tests/unit/test_resolve_graph.py index b3080a5..3f94639 100644 --- a/studio/tests/unit/test_resolve_graph.py +++ b/studio/tests/unit/test_resolve_graph.py @@ -119,6 +119,8 @@ def test_the_schemas_derived_chain() -> None: assert schema_derived_fields() == ( "injection.emission_duration_s", "schedule.day_of_year", + "site.h2o_ppmv", + "site.temperature_k", "injection.emission_rate_kg_s", "injection.plume_length_m", "injection.plume_volume_cm3", @@ -126,6 +128,8 @@ def test_the_schemas_derived_chain() -> None: ) order = schema_derived_fields() for earlier, later in ( + # The mixing ratio reads the DERIVED temperature (0.4.0), so the site must resolve first. + ("site.temperature_k", "injection.so2_initial_pptv"), ("injection.emission_duration_s", "injection.emission_rate_kg_s"), ("injection.emission_duration_s", "injection.plume_length_m"), ("injection.plume_length_m", "injection.plume_volume_cm3"), diff --git a/studio/tests/unit/test_resolve_registry.py b/studio/tests/unit/test_resolve_registry.py index b3c4919..1ff8c23 100644 --- a/studio/tests/unit/test_resolve_registry.py +++ b/studio/tests/unit/test_resolve_registry.py @@ -53,7 +53,7 @@ def test_declared_inputs_match_derived_from_exactly() -> None: @pytest.mark.tier_a def test_an_unregistered_field_raises_rather_than_returning_none() -> None: with pytest.raises(NotImplementedError, match="no derivation registered"): - derivation_for("site.temperature_k") + derivation_for("site.pressure_mbar") @pytest.mark.tier_a diff --git a/studio/tests/unit/test_resolve_resolver.py b/studio/tests/unit/test_resolve_resolver.py index a81d8a9..83de735 100644 --- a/studio/tests/unit/test_resolve_resolver.py +++ b/studio/tests/unit/test_resolve_resolver.py @@ -71,7 +71,8 @@ def test_chained_derivations_resolve_in_order() -> None: [ ("injection.plume_length_m", 30000.0, {VOLUME, SO2_PPTV}), ("injection.plume_width_m", 20.0, {VOLUME, SO2_PPTV}), - ("site.temperature_k", 213.0, {SO2_PPTV}), + # Editing the ENTERED temperature recomputes the derived one, then the mixing ratio. + ("site.given_temperature_k", 213.0, {"site.temperature_k", SO2_PPTV}), ("site.pressure_mbar", 120.0, {SO2_PPTV}), # Mass reaches the REPORTED emission rate as well since 0.3.0: R = M / t, so twice the mass # over the same track is twice the rate. It does NOT reach the length or the volume, which @@ -105,7 +106,7 @@ def test_an_override_is_never_overwritten_by_a_recomputation() -> None: assert overridden.config.injection.so2_initial_pptv == 5.0e9 assert overridden.is_consistent, "an override anchored to the current inputs is not stale" - after_edit = apply_change(overridden, "site.temperature_k", 213.0) + after_edit = apply_change(overridden, "site.given_temperature_k", 213.0) assert after_edit.config.injection.so2_initial_pptv == 5.0e9 @@ -113,7 +114,7 @@ def test_an_override_is_never_overwritten_by_a_recomputation() -> None: def test_a_moved_input_marks_the_override_stale_with_both_values() -> None: """ "Stale" without "here is what it would be" leaves the user to recompute by hand.""" overridden = set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9) - after_edit = apply_change(overridden, "site.temperature_k", 213.0) + after_edit = apply_change(overridden, "site.given_temperature_k", 213.0) assert after_edit.stale_fields == (SO2_PPTV,) (entry,) = after_edit.stale @@ -130,7 +131,7 @@ def test_an_unrelated_edit_does_not_make_an_override_stale() -> None: """Only a change to one of ITS inputs counts. Flagging on every edit would train users to dismiss the flag.""" overridden = set_override(resolve(RunConfig()), VOLUME, 3.0e12) - after = apply_change(overridden, "site.temperature_k", 213.0) + after = apply_change(overridden, "site.given_temperature_k", 213.0) assert after.is_consistent assert after.config.injection.plume_volume_cm3 == 3.0e12 @@ -147,7 +148,7 @@ def test_a_downstream_auto_field_uses_the_overridden_value() -> None: @pytest.mark.tier_a def test_accept_derived_drops_the_override_and_recomputes() -> None: stale = apply_change( - set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9), "site.temperature_k", 213.0 + set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9), "site.given_temperature_k", 213.0 ) accepted = accept_derived(stale, SO2_PPTV) assert accepted.is_consistent @@ -162,7 +163,7 @@ def test_keep_override_re_anchors_and_clears_staleness() -> None: """The user has said, knowingly, that their value still applies -- that is the difference between this and never having flagged it.""" stale = apply_change( - set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9), "site.temperature_k", 213.0 + set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9), "site.given_temperature_k", 213.0 ) kept = keep_override(stale, SO2_PPTV) assert kept.is_consistent @@ -170,7 +171,7 @@ def test_keep_override_re_anchors_and_clears_staleness() -> None: assert kept.overrides[SO2_PPTV].inputs["site.temperature_k"] == 213.0 # ...and it goes stale again on the NEXT change, rather than being permanently silenced - assert apply_change(kept, "site.temperature_k", 220.0).stale_fields == (SO2_PPTV,) + assert apply_change(kept, "site.given_temperature_k", 220.0).stale_fields == (SO2_PPTV,) @pytest.mark.tier_a @@ -178,7 +179,7 @@ def test_a_stale_config_refuses_to_pass_as_consistent() -> None: """A stale config still has a hash, and that is the trap: a stable identity for numbers that do not follow from each other.""" stale = apply_change( - set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9), "site.temperature_k", 213.0 + set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9), "site.given_temperature_k", 213.0 ) with pytest.raises(InconsistentConfigError, match="stale override"): stale.require_consistent() @@ -190,7 +191,7 @@ def test_the_stale_list_travels_with_the_config() -> None: """Serialising must carry the stale list, or a persisted config loses the fact that it is inconsistent -- exactly what the plan forbids.""" stale = apply_change( - set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9), "site.temperature_k", 213.0 + set_override(resolve(RunConfig()), SO2_PPTV, 5.0e9), "site.given_temperature_k", 213.0 ) restored = type(stale).model_validate_json(stale.model_dump_json()) assert restored.stale_fields == (SO2_PPTV,) @@ -209,9 +210,14 @@ def test_editing_a_derived_field_directly_is_an_override() -> None: @pytest.mark.tier_a def test_overriding_a_primary_field_is_refused() -> None: - """Primary fields have no derivation to be stale against; the concept does not apply.""" + """Primary fields have no derivation to be stale against; the concept does not apply. + + Pressure, deliberately: it is one of the few fields that stayed primary through 0.3.0 (the + emission system) and 0.4.0 (the dataset selector), precisely because everything else is + derived FROM it. + """ with pytest.raises(ValueError, match="not a derived field"): - set_override(resolve(RunConfig()), "site.temperature_k", 999.0) + set_override(resolve(RunConfig()), "site.pressure_mbar", 999.0) @pytest.mark.tier_a diff --git a/studio/tests/unit/test_runner.py b/studio/tests/unit/test_runner.py index b46ad9d..9b691d3 100644 --- a/studio/tests/unit/test_runner.py +++ b/studio/tests/unit/test_runner.py @@ -285,7 +285,7 @@ def test_a_bad_input_file_exits_distinctly_from_a_model_failure( import subprocess bad = tmp_path / "bad.json" - bad.write_text('{"config": {"site": {"temperature_k": -5}}}', encoding="utf-8") + bad.write_text('{"config": {"site": {"given_temperature_k": -5}}}', encoding="utf-8") proc = subprocess.run( [sys.executable, "-m", "studio.cli.run", str(bad), str(tmp_path / "out")], capture_output=True, diff --git a/studio/tests/unit/test_schema_export.py b/studio/tests/unit/test_schema_export.py index a79f20d..8d3788c 100644 --- a/studio/tests/unit/test_schema_export.py +++ b/studio/tests/unit/test_schema_export.py @@ -42,7 +42,7 @@ def test_metadata_survives_the_export() -> None: """Unit, provenance and source must reach the client, or the form cannot explain a field.""" schema = run_config_json_schema() site = schema["$defs"]["Site"]["properties"] - temperature = site["temperature_k"][EXTENSION_KEY] + temperature = site["given_temperature_k"][EXTENSION_KEY] assert temperature["unit"] == "K" assert temperature["provenance"] == "paper_ensemble" assert "TABLE_microphysics_parameters.md" in temperature["source"] diff --git a/studio/tests/unit/test_schema_metadata.py b/studio/tests/unit/test_schema_metadata.py index 8a8c482..adbd586 100644 --- a/studio/tests/unit/test_schema_metadata.py +++ b/studio/tests/unit/test_schema_metadata.py @@ -142,9 +142,9 @@ def test_bounded_quantities_declare_their_range() -> None: must_be_bounded = { "site.latitude_deg", "site.longitude_deg", - "site.temperature_k", + "site.given_temperature_k", "site.pressure_mbar", - "site.h2o_ppmv", + "site.given_h2o_ppmv", "schedule.month", "schedule.day_of_month", "schedule.start_utc_hour", @@ -167,7 +167,7 @@ def test_bounded_quantities_declare_their_range() -> None: ("path", "value"), [ ("site.latitude_deg", 91.0), - ("site.temperature_k", 0.0), + ("site.given_temperature_k", 0.0), ("site.pressure_mbar", -1.0), ("schedule.month", 13), ("schedule.day_of_month", 32), diff --git a/studio/tests/unit/test_web_contract.py b/studio/tests/unit/test_web_contract.py index dc97639..67b89d0 100644 --- a/studio/tests/unit/test_web_contract.py +++ b/studio/tests/unit/test_web_contract.py @@ -42,7 +42,7 @@ def _node(schema: dict[str, Any], path: str) -> dict[str, Any]: ("switches.heating_to_t", "const", "single accepted value -> read-only"), ("switches.sulfur", "type", "boolean -> checkbox"), ("dilution.regime", "$ref", "string enum by reference ->