Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions esmvalcore/preprocessor/_regrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
_LON_RANGE = _LON_MAX - _LON_MIN

# A cached stock of standard horizontal target grids.
_CACHE: Dict[str, iris.cube.Cube] = dict()
_CACHE: Dict[str, iris.cube.Cube] = {}

# Supported point interpolation schemes.
POINT_INTERPOLATION_SCHEMES = {
Expand Down Expand Up @@ -598,7 +598,7 @@ def regrid(cube, target_grid, scheme, lat_offset=True, lon_offset=True):
target_grid = _regional_stock_cube(target_grid)

if not isinstance(target_grid, iris.cube.Cube):
raise ValueError('Expecting a cube, got {}.'.format(target_grid))
raise ValueError(f'Expecting a cube, got {target_grid}.')

# Unstructured regridding requires x2 2d spatial coordinates,
# so ensure to purge any 1d native spatial dimension coordinates
Expand Down Expand Up @@ -1008,12 +1008,13 @@ def get_cmor_levels(cmor_table, coordinate):
"""
if cmor_table not in CMOR_TABLES:
raise ValueError(
"Level definition cmor_table '{}' not available".format(
cmor_table))
f"Level definition cmor_table '{cmor_table}' not available"
)

if coordinate not in CMOR_TABLES[cmor_table].coords:
raise ValueError('Coordinate {} not available for {}'.format(
coordinate, cmor_table))
raise ValueError(
f'Coordinate {coordinate} not available for {cmor_table}'
)

cmor = CMOR_TABLES[cmor_table].coords[coordinate]

Expand All @@ -1023,8 +1024,9 @@ def get_cmor_levels(cmor_table, coordinate):
return [float(cmor.value)]

raise ValueError(
'Coordinate {} in {} does not have requested values'.format(
coordinate, cmor_table))
f'Coordinate {coordinate} in {cmor_table} does not have requested '
f'values'
)


def get_reference_levels(filename, project, dataset, short_name, mip,
Expand Down Expand Up @@ -1096,7 +1098,7 @@ def extract_coordinate_points(cube, definition, scheme):
----------
cube : cube
The source cube to extract a point from.
defintion : dict(str, float or array of float)
definition : dict(str, float or array of float)
The coordinate - values pairs to extract
scheme : str
The interpolation scheme. 'linear' or 'nearest'. No default.
Expand All @@ -1114,7 +1116,6 @@ def extract_coordinate_points(cube, definition, scheme):
ValueError:
If the interpolation scheme is not provided or is not recognised.
"""

msg = f"Unknown interpolation scheme, got {scheme!r}."
scheme = POINT_INTERPOLATION_SCHEMES.get(scheme.lower())
if not scheme:
Expand Down
18 changes: 11 additions & 7 deletions esmvalcore/preprocessor/_regrid_esmpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from ._mapping import get_empty_data, map_slices, ref_to_dims_index


ESMF_MANAGER = ESMF.Manager(debug=False)

ESMF_LON, ESMF_LAT = 0, 1
Expand Down Expand Up @@ -73,8 +72,9 @@ def coords_iris_to_esmpy(lat, lon, circular):
esmpy_lat_corners = cf_2d_bounds_to_esmpy_corners(lat.bounds, circular)
esmpy_lon_corners = cf_2d_bounds_to_esmpy_corners(lon.bounds, circular)
else:
raise NotImplementedError('Coord dimension is {}. Expected 1 or 2.'
''.format(dim))
raise NotImplementedError(
f'Coord dimension is {dim}. Expected 1 or 2.'
)
return esmpy_lat, esmpy_lon, esmpy_lat_corners, esmpy_lon_corners


Expand Down Expand Up @@ -202,7 +202,6 @@ def regridder(src):


def build_regridder_3d(src_rep, dst_rep, regrid_method, mask_threshold):
# pylint: disable=too-many-locals
# The necessary refactoring will be done for the full 3d regridding.
"""Build regridder for 2.5d regridding."""
esmf_regridders = []
Expand Down Expand Up @@ -295,6 +294,11 @@ def get_grid_representants(src, dst):
if src_rep.ndim == 3:
dims = [dim + 1 for dim in dims]
aux_coords_and_dims.append((coord, dims))

# Add scalar dimensions of source cube to target
for scalar_coord in src_rep.coords(dimensions=()):
aux_coords_and_dims.append((scalar_coord, ()))

dst_rep = iris.cube.Cube(
data=get_empty_data(dst_shape, src.dtype),
standard_name=src.standard_name,
Expand All @@ -317,12 +321,12 @@ def regrid(src, dst, method='linear'):

Parameters
----------
src_cube: :class:`iris.cube.Cube`
src: :class:`iris.cube.Cube`
Source data. Must have latitude and longitude coords.
These can be 1d or 2d and should have bounds.
dst_cube: :class:`iris.cube.Cube`
dst: :class:`iris.cube.Cube`
Defines the target grid.
regrid_method:
method:
Selects the regridding method.
Can be 'linear', 'area_weighted',
or 'nearest'. See ESMPy_.
Expand Down
21 changes: 18 additions & 3 deletions tests/unit/preprocessor/_regrid_esmpy/test_regrid_esmpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ def setUp(self):
points=depth_points,
bounds=depth_bounds,
has_bounds=mock.Mock(return_value=True))
self.scalar_coord = mock.Mock(iris.coords.AuxCoord,
long_name='scalar_coord',
ndim=1,
shape=(1,))
data_shape = lon_2d_points.shape
raw_data = np.arange(np.prod(data_shape)).reshape(data_shape)
mask = np.zeros(data_shape)
Expand Down Expand Up @@ -225,13 +229,15 @@ def setUp(self):
self.coords = {
'latitude': self.lat_2d,
'longitude': self.lon_2d,
'depth': self.depth
'depth': self.depth,
'scalar_coord': self.scalar_coord,
}
self.coord_dims = {
'latitude': (0, 1),
'longitude': (0, 1),
self.lat_2d: (0, 1),
self.lon_2d: (0, 1),
'scalar_coord': (),
}

def coord(name=None, axis=None):
Expand All @@ -240,10 +246,12 @@ def coord(name=None, axis=None):
raise CoordinateNotFoundError()
return self.coords[name]

def coords(dim_coords=None):
def coords(dim_coords=None, dimensions=None):
"""Return coordinates for mock cube."""
if dim_coords:
return []
if dimensions == ():
return [self.scalar_coord]
return list(self.coords.values())

self.cube = mock.Mock(
Expand Down Expand Up @@ -280,6 +288,12 @@ def coord_3d(name=None, dimensions=None, dim_coords=None, axis=None):
return self.coords['depth']
return self.coords[name]

def coords_3d(dimensions=None):
"""Return coordinates for mock cube."""
if dimensions == ():
return []
return [self.lat_2d, self.lon_2d, self.depth]

self.cube_3d = mock.Mock(
spec=iris.cube.Cube,
dtype=np.float32,
Expand All @@ -294,6 +308,7 @@ def coord_3d(name=None, dimensions=None, dim_coords=None, axis=None):
data=self.data_3d,
coord=coord_3d,
coord_dims=lambda name: self.coord_dims_3d[name],
coords=coords_3d,
)
self.cube.__getitem__ = mock.Mock(return_value=self.cube)

Expand Down Expand Up @@ -636,7 +651,7 @@ def test_get_grid_representants_2d_src(self, mock_cube,
attributes=src.attributes,
cell_methods=src.cell_methods,
dim_coords_and_dims=[],
aux_coords_and_dims=[],
aux_coords_and_dims=[(self.scalar_coord, ())],
)

@mock.patch('esmvalcore.preprocessor._regrid_esmpy.map_slices')
Expand Down