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

PI-2472: Tweak area weighting regrid move xdim and ydim axes #3594

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
41 changes: 39 additions & 2 deletions lib/iris/experimental/regrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,31 @@ def _regrid_area_weighted_array(
cached_x_bounds.append(x_bounds)
cached_x_indices.append(x_indices)

# Move y_dim and x_dim to last dimensions
x_dim_orig = copy.copy(x_dim)
y_dim_orig = copy.copy(y_dim)
Copy link
Contributor

Choose a reason for hiding this comment

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

Stephen queried the use of copy.copy and I agree it isn't required here. I'll add this comment to #3596.

if x_dim is None and y_dim is None:
# e.g. a scalar point such as a vertical profile
pass
elif x_dim is not None and y_dim is None:
# test cross_section along line latitude
src_data = np.moveaxis(src_data, x_dim, -1)
x_dim = src_data.ndim - 1
elif y_dim is not None and x_dim is None:
# test cross_section along line longitude
src_data = np.moveaxis(src_data, y_dim, -1)
y_dim = src_data.ndim - 1
elif x_dim < y_dim:
src_data = np.moveaxis(src_data, x_dim, -1)
src_data = np.moveaxis(src_data, y_dim - 1, -2)
x_dim = src_data.ndim - 1
y_dim = src_data.ndim - 2
else:
src_data = np.moveaxis(src_data, x_dim, -1)
src_data = np.moveaxis(src_data, y_dim, -2)
x_dim = src_data.ndim - 1
y_dim = src_data.ndim - 2

# Create empty data array to match the new grid.
# Note that dtype is not preserved and that the array is
# masked to allow for regions that do not overlap.
Expand Down Expand Up @@ -577,8 +602,6 @@ def _regrid_area_weighted_array(
# Transpose weights to match dim ordering in data.
weights_shape_y = weights.shape[0]
weights_shape_x = weights.shape[1]
if x_dim is not None and y_dim is not None and x_dim < y_dim:
weights = weights.T
# Broadcast the weights array to allow numpy's ma.average
# to be called.
weights_padded_shape = [1] * data.ndim
Expand Down Expand Up @@ -608,6 +631,20 @@ def _regrid_area_weighted_array(
if not src_masked and not new_data.mask.any():
new_data = new_data.data

# Restore axis to original order
if x_dim_orig is None and y_dim_orig is None:
pass
elif x_dim_orig is not None and y_dim_orig is None:
new_data = np.moveaxis(new_data, -1, x_dim_orig)
elif y_dim_orig is not None and x_dim_orig is None:
new_data = np.moveaxis(new_data, -1, y_dim_orig)
elif x_dim_orig < y_dim_orig:
new_data = np.moveaxis(new_data, -1, x_dim_orig)
new_data = np.moveaxis(new_data, -1, y_dim_orig)
else:
new_data = np.moveaxis(new_data, -2, y_dim_orig)
new_data = np.moveaxis(new_data, -1, x_dim_orig)

Copy link
Contributor

Choose a reason for hiding this comment

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

These last two loops can be consolidated, since new_data will end in [..., y, x] in either case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok. We'll revisit in PR #3596 after everything has been rejigged anyway

return new_data


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,19 +322,36 @@ def test_regrid_latlon_reduced_res(self):
res = regrid_area_weighted(src, dest)
self.assertCMLApproxData(res, RESULT_DIR + ("latlonreduced.cml",))

def test_regrid_transposed(self):
src = self.simple_cube.copy()
dest = _subsampled_grid(src, 2, 3)
# Transpose src so that the coords are not y, x ordered.
src.transpose()
def test_regrid_reorder_axis(self):
src = self.realistic_cube[0, :4, :3, :2]
z = src.coord("model_level_number")
lat = src.coord("grid_latitude")
lon = src.coord("grid_longitude")
dest = _resampled_grid(self.realistic_cube[0, 0, :3, :2], 3, 3)
res = regrid_area_weighted(src, dest)
self.assertCMLApproxData(res, RESULT_DIR + ("trasposed.cml",))
# Using original and transposing the result should give the
# same answer.
src = self.simple_cube.copy()
self.assertArrayShapeStats(src, (4, 3, 2), 288.08868, 0.008262919)
self.assertArrayShapeStats(res, (4, 9, 6), 288.08865, 0.00826281)
# Reshape src so that the coords are ordered [x, z, y],
# the mean and std statistics should be the same
data = np.moveaxis(src.data.copy(), 2, 0)
src = iris.cube.Cube(data)
src.add_dim_coord(lat, 2)
src.add_dim_coord(z, 1)
src.add_dim_coord(lon, 0)
res = regrid_area_weighted(src, dest)
res.transpose()
self.assertCMLApproxData(res, RESULT_DIR + ("trasposed.cml",))
self.assertArrayShapeStats(src, (2, 4, 3), 288.08868, 0.008262919)
self.assertArrayShapeStats(res, (6, 4, 9), 288.08865, 0.00826281)
# Reshape src so that the coords are ordered [y, x, z],
# the mean and std statistics should be the same
data = np.moveaxis(src.data.copy(), 2, 0)
src = iris.cube.Cube(data)
src.add_dim_coord(z, 2)
src.add_dim_coord(lon, 1)
src.add_dim_coord(lat, 0)
dest = _resampled_grid(self.realistic_cube[0, 0, :3, :2], 3, 3)
res = regrid_area_weighted(src, dest)
self.assertArrayShapeStats(src, (3, 2, 4), 288.08868, 0.008262919)
self.assertArrayShapeStats(res, (9, 6, 4), 288.08865, 0.00826281)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should these different tests be in separate test functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Usually yes, but in this case they align with the transpose function that this supersedes and also share the same results info.


def test_regrid_lon_to_half_res(self):
src = self.simple_cube
Expand Down Expand Up @@ -446,6 +463,16 @@ def test_cross_section(self):
self.assertCMLApproxData(
res, RESULT_DIR + ("const_lat_cross_section.cml",)
)
# Constant latitude, data order [x, z]
# Using original and transposing the result should give the
# same answer.
src.transpose()
dest.transpose()
res = regrid_area_weighted(src, dest)
res.transpose()
self.assertCMLApproxData(
res, RESULT_DIR + ("const_lat_cross_section.cml",)
)

# Constant longitude
src = self.realistic_cube[0, :, :, 10]
Expand All @@ -460,6 +487,16 @@ def test_cross_section(self):
self.assertCMLApproxData(
res, RESULT_DIR + ("const_lon_cross_section.cml",)
)
# Constant longitude, data order [y, z]
# Using original and transposing the result should give the
# same answer.
src.transpose()
dest.transpose()
res = regrid_area_weighted(src, dest)
res.transpose()
self.assertCMLApproxData(
res, RESULT_DIR + ("const_lon_cross_section.cml",)
)

def test_scalar_source_cube(self):
src = self.simple_cube[1, 2]
Expand Down

This file was deleted.

This file was deleted.