Skip to content

Conversation

@schlunma
Copy link
Contributor

@schlunma schlunma commented Oct 12, 2023

Description

This PR refactors our regridding. The main purpose is to simplify the code so that new schemes can be added more easily, which will be necessary for #2178.

Features

  1. At the moment, the schemes linear, area_weighted and nearest work for regular and irregular grids. However, for unstructured grids, we have to use unstructured_nearest. This PR unifies this behavior so that nearest can also be used for unstructured grids (just like for irregular grids, I added a check for unstructured grids here that automatically selects the correct regridding scheme for unstructured grids).

  2. In addition, this PR unifies all regridding schemes so they can be used the (iris-intended) way within Cube.regrid, just like the regridding schemes provided by iris. These are now located in the new esmvalcore.preprocessor.regridding_schemes module. With this, regridding is as easy as

loaded_scheme = _load_scheme(cube, scheme)
cube = cube.regrid(target_grid_cube, loaded_scheme)
  1. Finally, this PR adds a check of the validity of the specified regridding schemes early in an ESMValTool run, so that the tool won't fail because of a bad scheme halfway through the recipe (potentially after hours of running).

Deprecations

This PR deprecated two regridding schemes, which will be removed with ESMValCore v2.13.0:

  • unstructured_nearest: Please use the scheme nearest instead. This is an exact replacement for data on unstructured grids. ESMValCore is now able to determine the most suitable regridding scheme based on the input data.
  • linear_extrapolate: Please use a generic scheme with reference: iris.analysis:Linear and extrapolation_mode: extrapolate instead. This is an exact replacement, e.g.:
preprocessors:
      regrid_preprocessor:
        regrid:
          target_grid: 2.5x2.5
          scheme:
            reference: iris.analysis:Linear
            extrapolation_mode: extrapolate

Related to #2178

Link to documentation:


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:

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.

hey Manu, no actual changes needed, just a couple questions for now - the review block is more for me since I'm not done going through the code yet (just got to _regrid_esmpy

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 unification PR, Manu, many thanks! I am very happy to see this happening, but I have a few concerns related to the way how things are structured ie private/public access to various classes and methods, and a bit of extra complexity that IMHO we can do without. Nothing major tho 🍺

tgt_cube,
method=self._METHOD,
mask_threshold=self.mask_threshold,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

OK call me old fashioned but to me this is a bit wrong: public method in a private class is something I don't agree with, especially since the ESMPYScheme name doesn't reflect the fact that an actual regridder instance is built within its bellows. What's wrong with the old generic and public regrid wrapper that the user is exposed to?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree with you that this looks too complicated, but this is how iris expects regridding schemes to look like! The scheme class needs a public method regridder(self, src_cube, target_grid) that returns an object of a regridder class. This regridder class needs to have a method def __call__(self, cube) that actually performs the regridding. Here is an example for a regridder in iris.

The advantage of this new syntax is that it's much more generic. All of our regridding schemes are used the same way (within iris.cube.Cube.regrid(). In the old version, some schemes used the iris syntax, some use this regrid function that you mentiond, etc.

Copy link
Contributor

Choose a reason for hiding this comment

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

indeed - I caught that, and liked it - but here's the thing - aligning ourselves to iris is not something we should aim for. If we find a nice, generic, and robust way of writing code and functionality we should go that way, regardless iris do other things; in this case, it's prob useful since we are in essence wrapping our regridding around iris regridding, so I'll grab the bait 🐟

Regridder instance.
"""
return _GenericRegridder(src_cube, tgt_cube, self.func, **self.kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

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

ah I see why the one above is private! OK - I'd argue you can coalesce that class into this one, and get rid of _GenericRegridder, and this is already public and does all the bits one needs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See comment above about how iris implements regridders. This needs to stay like this.

Copy link
Contributor

Choose a reason for hiding this comment

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

mhmm, 🐟

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.

approving this with very many thanks to Manu for the (rather heavy lifting) work, but I'd like a second pair of reviewing eyes, specifically @bouweandela or @zklaus please - Manu could you hold fire (merge, that is) until one of those two fellas have looked at it too, if you please, bud 🍺

Copy link
Member

@bouweandela bouweandela left a comment

Choose a reason for hiding this comment

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

Looks very nice improvement @schlunma!

A few comments:

  • It would be nice to avoid leaking private things into the public API (check the API docs page)
  • Could you please indicate in the API docs for each scheme if it supports lazy data?

@schlunma
Copy link
Contributor Author

Thanks for the review @bouweandela, I think I addressed all your comments 👍

tgt_cube:
Cube defining the target grid.
method:
Regridding algorithm.
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice to mention the valid method names here

Copy link
Member

@bouweandela bouweandela left a comment

Choose a reason for hiding this comment

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

Thanks for these improvements @schlunma!

@schlunma
Copy link
Contributor Author

schlunma commented Feb 1, 2024

Thanks for the reviews @bouweandela and @valeriupredoi ! Merging this now since two people approved.

@schlunma schlunma merged commit b0d30f6 into main Feb 1, 2024
@schlunma schlunma deleted the refactor_regridding branch February 1, 2024 15:13
@valeriupredoi
Copy link
Contributor

yay 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deprecated feature preprocessor Related to the preprocessor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants