Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use smarter (units-aware) weights #2139

Merged
merged 14 commits into from
Aug 29, 2023
Merged

Use smarter (units-aware) weights #2139

merged 14 commits into from
Aug 29, 2023

Conversation

schlunma
Copy link
Contributor

@schlunma schlunma commented Jul 14, 2023

Description

Since version 3.5.0, iris allows the usage of cell measures (and a lot of other objects) as weights. This has the great benefit that units in statistical calculations are handled properly, e.g., for an area-weighted sum, resulting units are multiplied by m2.

In addition, this PR adds type hints for all functions of the affected modules.

Closes #1613
Closes #708

Link to documentation:

Backwards-compatibility

The changes of these PR are NOT backwards-compatible. Since this PR fixes calculations that have been scientifically wrong in previous versions, no deprecation cycle is used. The following preprocessors are affected:

Preprocessor Affected option Old behavior New behavior Affected recipe(s)
area_statistics operator='sum' Cube units remained, e.g., kg m-2 s-1 Cube units are multiplied by m2, e.g., kg s-1 recipe_wenzel16nat, recipe_wenzel14jgr
climate_statistics period='full' and operator='sum' Cube units remained, e.g., kg m-2 s-1 Cube units are multiplied by time units, e.g., kg m-2 -
axis_statistics operator='sum' Cube units remained, e.g., kg m-2 s-1 Cube units are multiplied by coordinate units, e.g., kg m-1 s-1 -
depth_integration all Cube units remained, e.g., kg m-2 s-1 Cube units are multiplied by coordinate units, e.g., kg m-1 s-1 recipe_ocean_example

In addition, there has been a bug in climate_statistics, which lead to a wrong calculation of weighted sums if the weights are equal for all time points. These are the relevant lines of code:

if time_weights.min() == time_weights.max():
# No weighting needed.
clim_cube = cube.collapsed('time', operator_method)
else:
clim_cube = cube.collapsed('time',
operator_method,
weights=time_weights)

While this simplification is correct for calculating means and RMSE, the weighted sum actually differs in both cases. Thus, we need to always consider the weights here, regardless if they are equal or not. This PR fixes that.

I will test all affected recipes and open corresponding PR in ESMValTool if any changes are necessary.

EDIT: I tested all affected recipes; they run fine with minimal changes (ESMValGroup/ESMValTool#3300).


Before you get started

Checklist

It is the responsibility of the author to make sure the pull request is ready to review. The icons indicate whether the item will be subject to the 🛠 Technical or 🧪 Scientific review.


To help with the number pull requests:

@schlunma schlunma added enhancement New feature or request preprocessor Related to the preprocessor labels Jul 14, 2023
@schlunma schlunma added this to the v2.10.0 milestone Jul 14, 2023
@schlunma schlunma self-assigned this Jul 14, 2023
@codecov
Copy link

codecov bot commented Jul 14, 2023

Codecov Report

Merging #2139 (9dbc2e5) into main (579bb61) will increase coverage by 0.03%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main    #2139      +/-   ##
==========================================
+ Coverage   93.10%   93.14%   +0.03%     
==========================================
  Files         237      237              
  Lines       12826    12828       +2     
==========================================
+ Hits        11942    11948       +6     
+ Misses        884      880       -4     
Files Changed Coverage Δ
esmvalcore/preprocessor/_area.py 94.54% <100.00%> (+0.88%) ⬆️
esmvalcore/preprocessor/_shared.py 100.00% <100.00%> (ø)
esmvalcore/preprocessor/_time.py 97.72% <100.00%> (-0.01%) ⬇️
esmvalcore/preprocessor/_volume.py 91.59% <100.00%> (+1.16%) ⬆️

@schlunma schlunma marked this pull request as ready for review July 17, 2023 13:58
Copy link
Contributor

@valeriupredoi valeriupredoi left a comment

Choose a reason for hiding this comment

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

this is a very nice PR and introduced functionality, very cool, @schlunma 🍺 Proper testing too 🎖️ (I don't see any reason) but do we expect any changes in results for recipes that use this set of preprocessors? Also, were there any distinct changes in performance you might have noticed? Cheers!

@valeriupredoi valeriupredoi added the iris Related to the Iris package label Jul 19, 2023
@valeriupredoi
Copy link
Contributor

PS: I meant actual result changes, not if the recipes just run. I guess we could find that out at v2.10 release time - which reminds me, maybe we should curate a list of PRs that may lead to changes in results and have that at hand when testing for a release

@schlunma
Copy link
Contributor Author

Good point!

Old version:

grafik

New version:

diag_CMIP5_HadGEM2-CC_Omon_historical_r1i1p1__prep_depth_integration_1_diag_depthInt_1_2001_2004_map_0

@valeriupredoi
Copy link
Contributor

awesome you doing testing, Manu! About those K -> m.K units change - it's a bit fishy (excuse the pun) at first glance since the numbers are the same, only units changed? You wanna do more testing before we merge this? 🍺

@schlunma
Copy link
Contributor Author

schlunma commented Jul 19, 2023

No, nothing fishy at all, that's exactly what was to be expected: In this preprocessor (depth_integration), a weighted sum of potential temperature along the depth coordinate is taken; i.e., potential temperature (units K) is multiplied by the depth layer thickness (units m) and then summed up, which results in the units K m. 🐟 This PR just fixes the units handling; the actual calculation was correct before (hence the numbers didn't change).

This has also been expected by the author of depth_integration; see the following comment I removed now:

# result.units = Unit('m') * result.units # This doesn't work:
# TODO: Change units on cube to reflect 2D concentration (not 3D)
# Waiting for news from iris community.

@valeriupredoi
Copy link
Contributor

excellent! I'll take my 🐟 back then 😁

@bouweandela bouweandela merged commit 4baa8aa into main Aug 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backwards incompatible change enhancement New feature or request iris Related to the Iris package preprocessor Related to the preprocessor
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Smarter area weighted sum Global total air sea flux of CO2 removed
3 participants