Skip to content

Commit e34aa07

Browse files
authored
Add option to ignore horizontal coordinates if there are multiple when regridding (#2672)
1 parent fc1ac9f commit e34aa07

File tree

5 files changed

+84
-14
lines changed

5 files changed

+84
-14
lines changed

doc/recipe/preprocessor.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,24 @@ The arguments are defined below:
887887
Otherwise, it cuts off at the previous value.
888888
* ``step_longitude``: Longitude distance between the centers of two neighbouring cells.
889889

890+
Regridding input data with multiple horizontal coordinates
891+
----------------------------------------------------------
892+
893+
When there are multiple horizontal coordinates available in the input data, the
894+
standard names of the coordinates to use need to be specified. By default, these
895+
are ``[latitude, longitude]``. To use the coordinates from a
896+
`rotated pole grid <https://cfconventions.org/Data/cf-conventions/cf-conventions-1.12/cf-conventions.html#grid-mappings-and-projections>`__,
897+
one would specify:
898+
899+
.. code-block:: yaml
900+
901+
preprocessors:
902+
regrid_preprocessor:
903+
regrid:
904+
target_grid: 1x1
905+
scheme: linear
906+
use_src_coords: [grid_latitude, grid_longitude]
907+
890908
Regridding (interpolation, extrapolation) schemes
891909
-------------------------------------------------
892910

esmvalcore/preprocessor/_regrid.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import re
1111
import ssl
1212
import warnings
13+
from collections.abc import Iterable
1314
from copy import deepcopy
1415
from decimal import Decimal
1516
from pathlib import Path
@@ -745,6 +746,7 @@ def regrid(
745746
lat_offset: bool = True,
746747
lon_offset: bool = True,
747748
cache_weights: bool = False,
749+
use_src_coords: Iterable[str] = ("latitude", "longitude"),
748750
) -> Cube:
749751
"""Perform horizontal regridding.
750752
@@ -800,6 +802,9 @@ def regrid(
800802
support weights caching. More details on this are given in the section
801803
on :ref:`caching_regridding_weights`. To clear the cache, use
802804
:func:`esmvalcore.preprocessor.regrid.cache_clear`.
805+
use_src_coords:
806+
If there are multiple horizontal coordinates available in the source
807+
cube, only use horizontal coordinates with these standard names.
803808
804809
Returns
805810
-------
@@ -848,6 +853,16 @@ def regrid(
848853
scheme:
849854
reference: esmf_regrid.schemes:ESMFAreaWeighted
850855
"""
856+
# Remove unwanted coordinates from the source cube.
857+
cube = cube.copy()
858+
use_src_coords = set(use_src_coords)
859+
for axis in ("X", "Y"):
860+
coords = cube.coords(axis=axis)
861+
if len(coords) > 1:
862+
for coord in coords:
863+
if coord.standard_name not in use_src_coords:
864+
cube.remove_coord(coord)
865+
851866
# Load target grid and select appropriate scheme
852867
target_grid_cube = _get_target_grid_cube(
853868
cube,
@@ -858,15 +873,16 @@ def regrid(
858873

859874
# Horizontal grids from source and target (almost) match
860875
# -> Return source cube with target coordinates
861-
if _horizontal_grid_is_close(cube, target_grid_cube):
862-
for coord in ["latitude", "longitude"]:
863-
cube.coord(coord).points = target_grid_cube.coord(
864-
coord
865-
).core_points()
866-
cube.coord(coord).bounds = target_grid_cube.coord(
867-
coord
868-
).core_bounds()
869-
return cube
876+
if cube.coords("latitude") and cube.coords("longitude"):
877+
if _horizontal_grid_is_close(cube, target_grid_cube):
878+
for coord in ["latitude", "longitude"]:
879+
cube.coord(coord).points = target_grid_cube.coord(
880+
coord
881+
).core_points()
882+
cube.coord(coord).bounds = target_grid_cube.coord(
883+
coord
884+
).core_bounds()
885+
return cube
870886

871887
# Load scheme and reuse existing regridder if possible
872888
if isinstance(scheme, str):

tests/integration/preprocessor/_regrid/test_regrid.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,31 @@ def setUp(self):
4242
dim_coords_and_dims=coords_spec,
4343
)
4444

45+
# Setup cube with multiple horizontal dimensions
46+
self.multidim_cube = _make_cube(data, grid="rotated", aux_coord=False)
47+
lats, lons = np.meshgrid(
48+
np.arange(1, data.shape[-2] + 1),
49+
np.arange(1, data.shape[-1] + 1),
50+
)
51+
self.multidim_cube.add_aux_coord(
52+
iris.coords.AuxCoord(
53+
lats,
54+
var_name="lat",
55+
standard_name="latitude",
56+
units="degrees",
57+
),
58+
(1, 2),
59+
)
60+
self.multidim_cube.add_aux_coord(
61+
iris.coords.AuxCoord(
62+
lons,
63+
var_name="lon",
64+
standard_name="longitude",
65+
units="degrees",
66+
),
67+
(1, 2),
68+
)
69+
4570
# Setup mesh cube
4671
self.mesh_cube = _make_cube(data, grid="mesh")
4772

@@ -125,6 +150,17 @@ def test_regrid__linear(self, cache_weights):
125150
expected = np.array([[[1.5]], [[5.5]], [[9.5]]])
126151
assert_array_equal(result.data, expected)
127152

153+
def test_regrid__linear_multidim(self):
154+
"""Test that latitude/longitude are used by default."""
155+
result = regrid(
156+
self.multidim_cube,
157+
self.grid_for_linear,
158+
"linear",
159+
)
160+
expected = np.ma.masked_array([[[1.5]], [[5.5]], [[9.5]]], mask=False)
161+
result.data = np.round(result.data, 1)
162+
assert_array_equal(result.data, expected)
163+
128164
@pytest.mark.parametrize("cache_weights", [True, False])
129165
def test_regrid__linear_file(self, tmp_path, cache_weights):
130166
file = tmp_path / "file.nc"

tests/unit/preprocessor/_regrid/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ def _make_vcoord(data, dtype=None):
3737

3838

3939
def _make_cube(
40-
data,
41-
aux_coord=True,
42-
dim_coord=True,
40+
data: np.ndarray,
41+
aux_coord: bool = True,
42+
dim_coord: bool = True,
4343
dtype=None,
4444
grid: Literal["regular", "rotated", "mesh"] = "regular",
45-
):
45+
) -> iris.cube.Cube:
4646
"""Create a 3d synthetic test cube."""
4747
if dtype is None:
4848
dtype = np.int32

tests/unit/preprocessor/_regrid/test_regrid.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def test_regrid_is_skipped_if_grids_are_the_same():
233233

234234
# regridding to the same spec returns the same cube
235235
expected_same_cube = regrid(cube, target_grid="10x10", scheme=scheme)
236-
assert expected_same_cube is cube
236+
assert expected_same_cube == cube
237237

238238
# regridding to a different spec returns a different cube
239239
expected_different_cube = regrid(cube, target_grid="5x5", scheme=scheme)

0 commit comments

Comments
 (0)