Skip to content

Add CORDEX domain target grids for regridding#3096

Open
ghossh wants to merge 6 commits into
mainfrom
target-grid-cordex-domain
Open

Add CORDEX domain target grids for regridding#3096
ghossh wants to merge 6 commits into
mainfrom
target-grid-cordex-domain

Conversation

@ghossh

@ghossh ghossh commented Jun 1, 2026

Copy link
Copy Markdown

Description

Adds support for using standard CORDEX domain names, such as EUR-11, as target_grid values in the regrid preprocessor.

Previously, target_grid: EUR-11 was treated as an MxN grid specification and failed with:

ValueError: Invalid MxN cell specification for grid, got 'EUR-11'.

Closes #3088

Link to documentation:

https://esmvaltool--3096.org.readthedocs.build/projects/ESMValCore/en/3096/recipe/preprocessor.html#regridding-on-a-cordex-domain-grid

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.

@ghossh ghossh requested a review from bouweandela June 1, 2026 14:58
@CLAassistant

CLAassistant commented Jun 1, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@codecov

codecov Bot commented Jun 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 46.15385% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.01%. Comparing base (4127673) to head (a96e132).
⚠️ Report is 40 commits behind head on main.

Files with missing lines Patch % Lines
esmvalcore/preprocessor/_regrid.py 44.73% 21 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3096      +/-   ##
==========================================
- Coverage   96.14%   96.01%   -0.13%     
==========================================
  Files         267      267              
  Lines       15771    15803      +32     
==========================================
+ Hits        15163    15174      +11     
- Misses        608      629      +21     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bouweandela bouweandela left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks like a great start! Could you take a look at the checklist? A few things to do would be

  • sign the CLA
  • add a unit test
  • add documentation

Usually you can find advice on how to go about that in the pull request template, but in case you missed it you can find it here: https://github.com/ESMValGroup/ESMValCore/blob/main/.github/pull_request_template.md

Dummy cube with rotated-pole dimension coordinates and geographical
auxiliary coordinates matching the official domain specification.
"""
domain = cx.cordex_domain(domain_name, bounds=True)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe you could simplify this code by using ncdata.iris_xarray.cubes_to_xarray to convert the xarray.Dataset to an iris.cube.Cube directly?

@bouweandela bouweandela Jun 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit simpler, but not much. What I meant was something like

domain = cordex.domain(domain_name, bounds=True).reset_coords()
# Add a mock variable.
domain["data"] = xr.zeros_like(domain.lon)
# Associate the grid mapping and coordinates with the data.
domain.data.attrs = {
    "coordinates": "lat lon",
    "grid_mapping": "rotated_latitude_longitude",
}
# Associate the bounds with the coordinates.
domain.lat.attrs["bounds"] = "lat_vertices"
domain.lon.attrs["bounds"] = "lon_vertices"

cube, = ncdata.iris_xarray.cubes_from_xarray(domain)
cube.coord("grid_latitude").guess_bounds()
cube.coord("grid_longitude").guess_bounds()

@ghossh ghossh self-assigned this Jun 8, 2026
ghossh added 2 commits June 8, 2026 15:31
This update introduces a new section in the preprocessor documentation detailing how to regrid to standard CORDEX domains using the `target_grid` parameter. An example configuration for the `EUR-11` domain is provided, clarifying the use of domain names recognized by the `cordex` package.
@ghossh ghossh requested a review from bouweandela June 8, 2026 13:56
@ghossh

ghossh commented Jun 8, 2026

Copy link
Copy Markdown
Author

Hi @bouweandela , Please provide another review. Not sure why the workflow commit is failing!

@ghossh

ghossh commented Jun 9, 2026

Copy link
Copy Markdown
Author

Hi @bouweandela , I found that in case of :

  - project: CORDEX
    domain: EUR-11
    dataset: RACMO22E
    driver: CNRM-CERFACS-CNRM-CM5
    ensemble: r1i1p1
    institute: KNMI
    rcm_version: v2

in this line, it's failing due to no having bounds

if not np.allclose(coord1.bounds, coord2.bounds):

A possible solution could be like adding this:

        if not coord1.has_bounds() or not coord2.has_bounds():
            return False

what do you think?

@bouweandela

Copy link
Copy Markdown
Member

Not sure why the workflow commit is failing!

Should be fixed by #3104

@bouweandela

Copy link
Copy Markdown
Member

Regarding the no-bounds issue: this seems unrelated to the changes in this pull request, so it would be great if you could open a new issue for this. We can then make a plan for how to solve it there and tackle it in a new pull request.

-------
bool
Whether ``spec`` is recognised by :mod:`cordex`.
"""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
"""
"""
if not isinstance(spec, str):
return False

Adding this here would avoid the extra nesting in the places where you're calling this function, making that code a bit easier to read.

Alternatively, a :class:`~esmvalcore.dataset.Dataset` can be provided.
Alternatively, a string cell specification may be provided,
of the form ``MxN``, which specifies the extent of the cell, longitude
by latitude (degrees) for a global, regular target grid.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please also mention that this can be a CORDEX domain here

target_grid: EUR-11
scheme: linear

Any domain name recognized by the ``cordex`` package can be used, for example

Copy link
Copy Markdown
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 add a link to this page so users can find the available domains easily.

Comment on lines +823 to +824
domain definition instead of interpreting the value as an ``MxN`` grid
specification.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
domain definition instead of interpreting the value as an ``MxN`` grid
specification.
domain definition.

would suggest leaving that out as it doesn't add much

assert target.coord(var_name="rlon") is not None


def test_update_target_grid_accepts_cordex_domain():

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice that you're adding tests for this! I think this would be a better place for them:

def test_update_regrid_time():

def test_get_target_grid_cube_cordex_domain(global_cube):
"""Test target grid cube construction for a CORDEX domain."""
target = _get_target_grid_cube(global_cube, "EUR-11")
assert target.coord(var_name="rlat") is not None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
assert target.coord(var_name="rlat") is not None
assert target.coords(var_name="rlat")

would test that there is at least one coordinate with the name "rlat". The iris.cube.Cube.coord method raises an exception if no coordinate is found, so it will never return None.

@bouweandela bouweandela left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice progress @ghossh! I've pasted the checklist back in the pull request description to make it easier for myself to remember what to look for. A few more things to do would be to add a label to the pull request (e.g. preprocessor) and add yourself to the list of authors. Could you please also update the branch so coverage is uploaded again and I can see which lines of code have coverage.

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

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Make it possible to regrid to the standard CORDEX domains

3 participants