Skip to content

Bug-fix extraction from generation-cleanout-v2 - #87

Merged
maritsandstad merged 11 commits into
basefrom
bugfixes-from-cleanout-v2
Jul 2, 2026
Merged

Bug-fix extraction from generation-cleanout-v2#87
maritsandstad merged 11 commits into
basefrom
bugfixes-from-cleanout-v2

Conversation

@benmsanderson

Copy link
Copy Markdown
Owner

Summary

Extracts the bug fixes that had accumulated on generation-cleanout-v2 into a focused PR against base, leaving the FastMIP operational scripts and notebooks behind.

The 10 commits here are cherry-picks of:

  • PR Fastmip scaling error fixes #69 (fastmip-scaling-error-explore) — 9e76742, b90204c
    • ensure_path for netcdf dump, plus various scaling-timeseries / diverse-input fixes
  • PR pulling ben's exog fix into fastmip branch #78 (noise-temporal-persistence) — 5fb128e
    • Preserve low-frequency global variability: default use_exog to 'none'
  • PR Fixing scaling #77 (fix-extended-timescaling) — 585614a, 16ad717
    • Variable-length temperature scaling timeseries no longer collapses to all-1s
  • PR Fit precipitation quantile map per month-of-year, full window #84 (fix-precip-seasonal-transform) — 9250e37
    • Fit gamma transform per month-of-year over the full window, instead of conflating seasonal cycle with internal variability
  • Standalone fixesb3e1b75, a5c5656, 8007a21, 7c8e83a
    • interface field generation fix on base (introduces GenerationInputs)
    • Linting, changelog, docstring

The cherry-picks preserved Marit's and Ben's authorship on each commit.

What was deliberately left out

  • scripts/FastMIP_* (4 scripts)
  • notebooks/FASTMIP_*.ipynb, notebooks/FastMIP_*.ipynb, notebooks/aggregate_to_regions.py, notebooks/FAIR_GSAT/
  • data/FASTMIP_phase1/FAIR_GSAT/...
  • FastMIP_README.md, FastMIP_env_setup.sh, conda_env_fastmip.yml
  • notebooks/GCAM_predict.ipynb re-execution bundled into the linting commit

Diff

10 files, +1460 / −260 — all under src/, tests/, and CHANGELOG.rst. No notebooks, no operational scripts.

Test plan

  • Full pytest suite passes (281 tests)
  • Touched test files pass directly (59 tests across test_meteor_interface.py, test_geo_data_utils.py, test_noise_generator.py)
  • black --check, ruff check, isort --check-only all clean
  • CI green

maritsandstad and others added 10 commits June 30, 2026 19:33
…xog='none')

The EOF-weighting fix (PR #74) corrected the *monthly* global tas variance,
but the *annual/decadal* global variability was still ~2.5x too small: the
generated noise was temporally white/anti-persistent (lag-1 autocorr ~-0.1)
whereas real global-mean tas is strongly red (lag-1 ~+0.57).

Root cause is the VAR-X exogenous regressor, not the EOF basis or the seasonal
t_glob removal. Stage-by-stage (CanESM5 tas, validated against piControl):

  target (piControl)                 annual std 0.089 K   lag-1 +0.57
  training anomaly global mean       0.081 K              +0.56   (red)
  in-sample retained PCs -> global   0.074 K              +0.51   (red)
  VAR-X generated, use_exog='all'    0.038 K              +0.18   (white)
  VAR-X generated, use_exog='none'   0.076 K              +0.53   (red)

Using the smoothed global temperature (t_glob) as a VAR-X exogenous regressor
absorbs the persistent low-frequency global variability into the deterministic
forced term. At generation t_glob is the prescribed (smooth, internally
invariant) trajectory, so that power is never regenerated -> white noise. With
use_exog='none' the persistence stays in the AR dynamics and is reproduced
(CanESM5 86% of target annual std, ACCESS-ESM1-5 79%; monthly variance
unchanged). The temperature-dependent mean/seasonal response is already
captured by the seasonal model, so the exog regressor is redundant.

Changes:
  - MeteorNoiseGenerator and train_*_from_cmip6 default use_exog 'temp_only'->'none'
  - interface _get_default_config: tas 'all'->'none' (pr was already 'none')
  - 'temp_only'/'all' retained for backward compatibility (documented as
    suppressing low-frequency global variability; 'temp_only' is also unstable
    at high lag_order)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit 75759b3)
(cherry picked from commit 4f5df80)
(cherry picked from commit 25f0686)
(cherry picked from commit 402e20b)
The Gamma transform was conflating the seasonal cycle and the climate-change
trend with internal variability:

  - Time-series path: the Gaussian was fit on the whole flattened
    (n_real, n_time) ensemble, so sigma was dominated by the wet/dry-season
    swing and the inter-realization noise band got squashed in the CDF→PPF
    roundtrip.
  - Gridded path: the transform was applied per year-slice, so the per-
    gridpoint Gaussian mean was the local 1-year climatology, which
    normalized every year to its own local distribution and wiped the
    climate-change trend at each gridpoint.

Fit and apply per month-of-year (12 fits) so the seasonal cycle lives in
the per-month means instead of sigma, and on the gridded side build a
single full-window transformed ensemble up front so the annual / monthly /
climatology slicers just read from it. Old pooled fit/apply functions are
kept for backwards compatibility; the seasonal variants are wired through
VariableTransformConfig and only used when present.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit 706a94a)
(cherry picked from commit 2ad4f85, dropping the GCAM_predict.ipynb
re-execution that was bundled with the lint fix.)
(cherry picked from commit a11f269)

@maritsandstad maritsandstad left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with this, minor comments which could be discussed and no big deal if we defer them to later

Comment thread src/meteor/geo_data_utils.py
Comment thread src/meteor/noise_generator.py Outdated
Comment thread src/meteor/precipitation_transform.py
- Remove the leftover `print(n_lat, n_lon, n_time)` debug call in
  noise_generator._generate_realizations_unified_implementation.
- Expand the one-line geo_data_utils module docstring into a grouped
  inventory of the helpers it exposes.
@benmsanderson

Copy link
Copy Markdown
Owner Author

Thanks @maritsandstad — pushed 4f22d61 addressing the two quick ones:

  • noise_generator.py:575 — debug print(n_lat, n_lon, n_time) removed.
  • geo_data_utils.py — expanded the one-line module docstring into a grouped inventory of what the file exposes (coordinate discovery, area weighting, spatial aggregation, time-axis helpers).

For the third comment (folding most of precipitation_transform.py into shared libraries like geo_data_utils.py) — agreed, but feels like more than a bug-fix-extraction PR should swallow. Filed as #88 so it doesn't get lost.

@benmsanderson
benmsanderson marked this pull request as ready for review June 30, 2026 19:17
@maritsandstad
maritsandstad merged commit 8ae867e into base Jul 2, 2026
16 checks passed
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.

2 participants