Skip to content

Make domain_stats use spatial_average and handle 0-360 longitudes - #495

Merged
brianpm-ucar merged 2 commits into
NCAR:mainfrom
brianpm-ucar:domain-stats-spatial-average
Oct 3, 2026
Merged

brianpm-ucar merged 2 commits into
NCAR:mainfrom
brianpm-ucar:domain-stats-spatial-average

Conversation

@brianpm-ucar

Copy link
Copy Markdown
Collaborator

Closes #262.

domain_stats now takes its mean with spatial_average instead of its own copy of the cos(lat) weights, as the issue asked.

While doing that I found a bug in the same function. make_polar_plot calls it with [-180, 180, 45, 90], but the regridded data has longitude 0 to 360, and the old sel(lon=slice(-180, 180)) kept only longitudes 0 to 180. The Mean, Max and Min in the polar-map header therefore described half of the cap. The old code also returned an empty selection for latitude that runs north to south.

Change

  • The region is picked with masks on lon % 360 and on latitude, so the longitude convention of the data and of the domain no longer has to match. If west is greater than east the box wraps through 0/360, and a span of 360 degrees or more is the whole circle.
  • The mean is spatial_average(region). Min and max are as before.
  • New tests in lib/test/unit_tests/test_domain_stats.py: same answer for 0-360 and -180-180 data, descending latitude, a box across 0/360, box edges on 0, 180 and 360, NaN points left out, and the global box equal to spatial_average. Each expected value is a separate numpy calculation. Against the old function, 5 of the 6 tests fail.

Effect on real output (PS climatology from the t1 model-vs-model run, longitude 0 to 358.75; mean, max, min in hPa):

Region Old New
North cap (45N-90N) 985.71, 1031.65, 756.02 984.57, 1031.65, 661.54
South cap (90S-45S) 928.81, 1011.12, 580.60 952.89, 1011.12, 580.60

For data already on -180 to 180 with ascending latitude, old and new give identical values.

Checking

  • pytest lib/test/unit_tests: 269 passed. black --check lib/ is clean.
  • A separate read-only Claude agent reviewed the change with no blocking findings. I tightened the docstring (2-D input; the old code silently averaged over any extra dimension, the new one raises for a time dimension longer than 1) and two tests after its review.

Not checked

  • A full ADF run with the polar-plot headers. The only caller, make_polar_plot, passes 2-D seasonal fields.
  • The black version pinned for CI (I used the p12 environment's).

Not changed here: make_polar_plot still fills the percent-difference panel with 0 before its statistics, and still selects latitude with sel(slice) for the plot itself.

Claude-assisted: written with Claude Code.

🤖 Generated with Claude Code

brianpm-ucar and others added 2 commits September 29, 2026 16:36
domain_stats picked its region with sel(lon=slice(west, east)), so the polar
plots' [-180, 180, 45, 90] kept only longitudes 0 to 180 of the usual 0 to 360
data, and the header mean, max and min described half the cap. It also
failed on latitude that runs north to south.

Pick the region with masks on longitude modulo 360 and on latitude, and take
the mean with spatial_average instead of a second copy of the cos(lat) weights.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The class-level numpy call ran at import time, and CI installs only PyYAML
and pytest, so collection failed instead of skipping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brianpm-ucar
brianpm-ucar merged commit 696d2fc into NCAR:main Oct 3, 2026
7 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.

Change domain_stats to use spatial_average

1 participant