Fix monthly tasmax/tasmin being a copy of tas (#644) - #648
Merged
Conversation
CMIP7 monthly tas_tmaxavg/tminavg (CMIP6 Amon.tasmax/tasmin) were written
bit-identical to tas: the mapping pointed all three variables at the
monthly-mean fld_s03i236, and calculate_monthly_maximum/minimum over
already-monthly bins is an identity. The daily variants renamed the daily
*mean* field, so they were wrong too.
- Point tasmax/tasmin (ESM1-5, ESM1-6) at the model's within-day extrema
fld_s03i236_max/_min from the daily pe stream (per-variable file_pattern
override), and reduce them to monthly with a new calculate_monthly_mean
operation, matching the CF cell_methods
"time: maximum within days time: mean over days". Daily targets keep the
direct-rename bypass, which now renames the true extrema field.
- Skip the generic auto-resampling when the variable's formula performs the
temporal reduction itself, so the formula receives the raw daily input.
- Guard the monthly reductions against monthly-or-coarser input: every bin
would hold one sample, silently returning the input unchanged.
- determine_resampling_method: parse the last "time:" clause of cell_methods
instead of substring priority, so chained reductions ("maximum within days
... mean over days") continue the outer reduction (mean) when coarsening.
- Integration test harness honours per-variable file_pattern overrides.
Verified against the ESM1.6 test archive: monthly tmaxavg/tminavg now equal
the monthly mean of the daily max/min (279.57/275.82 K vs tas 277.70 K),
daily tmax/tmin match the raw extrema exactly, and tasmax > tas > tasmin.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #648 +/- ##
=====================================
Coverage 77.3% 77.3%
=====================================
Files 40 40
Lines 8524 8519 -5
Branches 1593 1587 -6
=====================================
- Hits 6590 6589 -1
+ Misses 1604 1602 -2
+ Partials 330 328 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
rhaegar325
approved these changes
Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #644
The problem
Monthly
tasmaxandtasmin(CMIP7tmaxavg/tminavg) were written with exactly the same values astas. The daily variants were also wrong: they contained the daily mean temperature, not the daily max/min.Why it happened
The mapping pointed all these variables at
fld_s03i236, which is the mean temperature field. The real daily max/min live in separate fields (fld_s03i236_max/fld_s03i236_min) that only exist in the daily output stream — the monthly stream doesn't have them at all.So for monthly targets, MOPPy read the monthly-mean field and asked for the "monthly maximum" of it. With one value per month, that operation returns the input unchanged — a silent copy of
tas. For daily targets, it simply renamed the daily-mean field.The fix
tasmax/tasminnow readfld_s03i236_max/_minfrom the daily files (ESM1-5 and ESM1-6 mappings), even for monthly output.calculate_monthly_meanoperation), matching the CF definition "time: maximum within days time: mean over days". Daily output just renames the true extrema field.tmaxavg/tminavgoutput is a copy oftavg, not a daily max/min aggregate #644, which also affects e.g.sfcWindmax).Verification
Against the ESM1.6 test archive (1951):
tmaxavg(mon)tminavg(mon)tmax(day)tmin(day)tasmax > tas > tasminnow holds everywhere. Full unit suite passes (1849 tests, 36 new/updated), and the CMIP7 integration tests for all four variants pass WCRP compliance.Note for reviewers: the ESM1-5 mapping got the same change. Its stream layout and naming convention are identical (it already uses
fld_s03i230_maxforsfcWindmax), but I could only verify values against ESM1.6 data — worth confirming ESM1-5 archives carryfld_s03i236_max/_minin theirpedaily files.🤖 Generated with Claude Code