Skip to content

Commit

Permalink
refactor grid.py and unit test code
Browse files Browse the repository at this point in the history
  • Loading branch information
zfan001 committed May 14, 2021
1 parent 76f0339 commit 97a76ff
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 74 deletions.
36 changes: 18 additions & 18 deletions improver/regrid/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ def calculate_input_grid_spacing(cube_in):
raise ValueError("Input grid is not on a latitude/longitude system")

# calculate grid spacing
lon_spacing = calculate_grid_spacing(cube_in, "degree", axis="x")
lat_spacing = calculate_grid_spacing(cube_in, "degree", axis="y")
lon_spacing = calculate_grid_spacing(cube_in, "degree", axis="x", rtol=1.0e-5)
lat_spacing = calculate_grid_spacing(cube_in, "degree", axis="y", rtol=1.0e-5)

if lon_spacing < 0 or lat_spacing < 0:
raise ValueError("Input grid coordinates are not ascending.")
Expand Down Expand Up @@ -169,8 +169,8 @@ def flatten_spatial_dimensions(cube):
in_values = cube.data
coord_names = get_cube_coord_names(cube)
lats_name, lons_name = latlon_names(cube)
lats_index = coord_names.index(lats_name)
lons_index = coord_names.index(lons_name)
lats_index = cube.coord_dims(lats_name)[0]
lons_index = cube.coord_dims(lons_name)[0]

in_values = np.swapaxes(in_values, 0, lats_index)
in_values = np.swapaxes(in_values, 1, lons_index)
Expand Down Expand Up @@ -343,32 +343,32 @@ def create_regrid_cube(cube_array, cube_in, cube_out):
Returns:
iris.cube.Cube: regridded result cube
"""

# generate a cube based on new data and cube_in
cube_v = Cube(
cube_array,
standard_name=cube_in.standard_name,
var_name=cube_in.var_name,
units=cube_in.units,
attributes=cube_in.attributes,
)

# use dim_coord from cube_in except lat/lon
cube_coord_names = get_cube_coord_names(cube_in)
lats_name, lons_name = latlon_names(cube_in)
cube_coord_names.remove(lats_name)
cube_coord_names.remove(lons_name)

cube_v = Cube(cube_array)
cube_v.attributes = cube_in.attributes

cube_v.var_name = cube_in.var_name
cube_v.standard_name = cube_in.standard_name
cube_v.units = cube_in.units

ndim = len(cube_coord_names)
for i, val in enumerate(cube_coord_names):
cube_v.add_dim_coord(cube_in.coord(val), i)

cube_coord_names = get_cube_coord_names(cube_out)
if "projection_y_coordinate" in cube_coord_names:
cord_1 = "projection_y_coordinate"
cord_2 = "projection_x_coordinate"
else:
cord_1, cord_2 = latlon_names(cube_out)

# Put in suitable spatial coord from cube_out into cube_in
cord_1, cord_2 = latlon_names(cube_out)
cube_v.add_dim_coord(cube_out.coord(cord_1), ndim)
cube_v.add_dim_coord(cube_out.coord(cord_2), ndim + 1)

# add all aus_coords from cube_in
for coord in cube_in.aux_coords:
dims = np.array(cube_in.coord_dims(coord)) + 1
cube_v.add_aux_coord(coord.copy(), dims)
Expand Down
4 changes: 2 additions & 2 deletions improver/utilities/spatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def check_if_grid_is_equal_area(


def calculate_grid_spacing(
cube: Cube, units: Union[Unit, str], axis: str = "x", rtol: float = 1.0e-5
cube: Cube, units: Union[Unit, str], axis: str = "x", rtol: float = 0.0
) -> float:
"""
Returns the grid spacing of a given spatial axis
Expand Down Expand Up @@ -106,7 +106,7 @@ def calculate_grid_spacing(
diffs_diff = np.diff(diffs)
diffs_mean = np.mean(diffs)

if np.any(abs(diffs_diff) > rtol * abs(diffs_mean)):
if not np.allclose(diffs, diffs_mean, rtol=rtol, atol=0.0):
raise ValueError(
"Coordinate {} points are not equally spaced".format(coord.name())
)
Expand Down
79 changes: 28 additions & 51 deletions improver_tests/regrid/test_RegridWithLandSeaMask.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,58 +35,23 @@
# the regridding reference results are manually checked for different methods
# not using "set_up_variable_cube" because of different spacing at lat/lon

import iris
import numpy as np
from iris.coords import DimCoord
from iris.cube import Cube

from improver.regrid.bilinear import basic_indexes
from improver.regrid.grid import calculate_input_grid_spacing, latlon_from_cube
from improver.regrid.landsea import RegridLandSea
from improver.synthetic_data.set_up_test_cubes import set_up_variable_cube


# function for creating cube from data, lats, lons
def create_cube(cube_array, lats, lons, name, unit):
"""
create a simple cube from data and lat/lon coords
args:
cube_array (numpy.ndarray):
data value (two dimensional)
lats ( numpy.ndarray):
latitude array
lons ( numpy.ndarray):
longitude array
name (str):
variable name
unit (str):
variable unit
return:
cube_v(iris.cube.Cube):
new-created cube
"""
cube_v = Cube(cube_array)
# assume name
cube_v.var_name = name
# cube_v.standard_name= name
cube_v.units = unit

coord_lat = DimCoord(
lats,
standard_name="latitude",
units="degrees",
coord_system=iris.coord_systems.GeogCS(6371229),
)
coord_lon = DimCoord(
lons,
standard_name="longitude",
units="degrees",
coord_system=iris.coord_systems.GeogCS(6371229),
)

cube_v.add_dim_coord(coord_lat, 0)
cube_v.add_dim_coord(coord_lon, 1)

return cube_v
def modify_cube_coordinate_value(cube, coord_x, coord_y):
"""modify x(longitude) & y(latitude) andcoordinates for a cube"""
cube.coord(axis="x").points = coord_x
cube.coord(axis="x").bounds = None
cube.coord(axis="x").guess_bounds()
cube.coord(axis="y").points = coord_y
cube.coord(axis="y").bounds = None
cube.coord(axis="y").guess_bounds()
return cube


def define_source_target_grid_data():
Expand Down Expand Up @@ -120,9 +85,15 @@ def define_source_target_grid_data():
out_mask[7, 6] = 1
out_mask[1, 0] = 0

cube_in = create_cube(data, in_lats, in_lons, "air_temperature", "Celsius")
cube_in_mask = create_cube(in_mask, in_lats, in_lons, "Land_Binary_Mask", "1")
cube_out_mask = create_cube(out_mask, out_lats, out_lons, "Land_Binary_Mask", "1")
# create cube with default spacing
cube_in = set_up_variable_cube(data, "air_temperature", "Celsius")
cube_in_mask = set_up_variable_cube(in_mask, "Land_Binary_Mask", "1")
cube_out_mask = set_up_variable_cube(out_mask, "Land_Binary_Mask", "1")

# modify cube coordinates to the designed value
cube_in = modify_cube_coordinate_value(cube_in, in_lons, in_lats)
cube_in_mask = modify_cube_coordinate_value(cube_in_mask, in_lons, in_lats)
cube_out_mask = modify_cube_coordinate_value(cube_out_mask, out_lons, out_lats)

return cube_in, cube_out_mask, cube_in_mask

Expand Down Expand Up @@ -156,9 +127,15 @@ def define_source_target_grid_data_same_domain():
out_mask[6, 6] = 1
out_mask[1, 0] = 0

cube_in = create_cube(data, in_lats, in_lons, "air_temperature", "Celsius")
cube_in_mask = create_cube(in_mask, in_lats, in_lons, "Land_Binary_Mask", "1")
cube_out_mask = create_cube(out_mask, out_lats, out_lons, "Land_Binary_Mask", "1")
# create cube with default spacing
cube_in = set_up_variable_cube(data, "air_temperature", "Celsius")
cube_in_mask = set_up_variable_cube(in_mask, "Land_Binary_Mask", "1")
cube_out_mask = set_up_variable_cube(out_mask, "Land_Binary_Mask", "1")

# modify cube coordinates to the designed value
cube_in = modify_cube_coordinate_value(cube_in, in_lons, in_lats)
cube_in_mask = modify_cube_coordinate_value(cube_in_mask, in_lons, in_lats)
cube_out_mask = modify_cube_coordinate_value(cube_out_mask, out_lons, out_lats)

return cube_in, cube_out_mask, cube_in_mask

Expand Down
6 changes: 3 additions & 3 deletions improver_tests/utilities/test_spatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def test_lat_lon_equal_spacing_with_tolerance(self):
10.0,
20.00001,
]
result = calculate_grid_spacing(self.lat_lon_cube, "degrees")
result = calculate_grid_spacing(self.lat_lon_cube, "degrees", rtol=1.0e-5)
self.assertAlmostEqual(result, 10.0)

def test_lat_lon_negative_spacing(self):
Expand All @@ -224,7 +224,7 @@ def test_lat_lon_negative_spacing(self):
-10.0,
-19.99999,
]
result = calculate_grid_spacing(self.lat_lon_cube, "degrees")
result = calculate_grid_spacing(self.lat_lon_cube, "degrees", rtol=1.0e-5)
self.assertAlmostEqual(result, -10.0)

def test_lat_lon_unequal_spacing(self):
Expand All @@ -238,7 +238,7 @@ def test_lat_lon_unequal_spacing(self):
]
msg = "Coordinate longitude points are not equally spaced"
with self.assertRaisesRegex(ValueError, msg):
calculate_grid_spacing(self.lat_lon_cube, "degrees")
calculate_grid_spacing(self.lat_lon_cube, "degrees", rtol=1.0e-5)

def test_incorrect_units(self):
"""Test ValueError for incorrect units"""
Expand Down

0 comments on commit 97a76ff

Please sign in to comment.