Skip to content

Commit

Permalink
Made set_up_variable_cube test helper support non-square grid cells (#…
Browse files Browse the repository at this point in the history
…1988)

* Changed helper methods and updated tests using it to match. Also signed contributors list and mailmap

Co-authored-by: Stephen Moseley <stephen.moseley@metoffice.gov.uk>

Co-authored-by: Stephen Moseley <stephen.moseley@metoffice.gov.uk>

* Changed one of the generate metadata tests to match new set-up-test-cube logic

* Fixed generate_metadata tests

* Tidying up

* small review acton

* Added tests for test cubes with equal x and y dimensions

* Bugfix

---------

Co-authored-by: Stephen Moseley <stephen.moseley@metoffice.gov.uk>
  • Loading branch information
MO-PeterJordan and MoseleyS committed Apr 22, 2024
1 parent 96cdbef commit 84a8944
Show file tree
Hide file tree
Showing 25 changed files with 203 additions and 93 deletions.
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Mark Worsfold <mark.worsfold@metoffice.gov.uk> <35810969+MarkWorsfold@users.nore
Meabh NicGuidhir <meabh.nicguidhir@metoffice.gov.uk> <meabh.nicguidhir@metoffice.gov.uk>
Neil Crosswaite <neil.crosswaite@metoffice.gov.uk> <43375279+neilCrosswaite@users.noreply.github.com>
Paul Abernethy <paul.abernethy@metoffice.gov.uk> <paul.abernethy@metoffice.gov.uk>
Peter Jordan <peter.jordan@metoffice.gov.uk> <52462411+mo-peterjordan@users.noreply.github.com>
Shafiat Dewan <87321907+ShafiatDewan@users.noreply.github.com> <87321907+ShafiatDewan@users.noreply.github.com>
Shubhendra Singh Chauhan <withshubh@gmail.com> <withshubh@gmail.com>
Simon Jackson <simon.jackson@metoffice.gov.uk> <simon.jackson@metoffice.gov.uk>
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ below:
- Katharine Hurst (Met Office, UK)
- Simon Jackson (Met Office, UK)
- Caroline Jones (Met Office, UK)
- Peter Jordan (Met Office, UK)
- Bruno P. Kinoshita (NIWA, NZ)
- Lucy Liu (Bureau of Meteorology, Australia)
- Daniel Mentiplay (Bureau of Meteorology, Australia)
Expand Down
9 changes: 6 additions & 3 deletions improver/cli/generate_metadata_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def process(
time_period: int = None,
json_input: cli.inputjson = None,
ensemble_members: int = 8,
grid_spacing: float = None,
x_grid_spacing: float = None,
y_grid_spacing: float = None,
domain_corner: cli.comma_separated_list_of_float = None,
npoints: int = 71,
):
Expand Down Expand Up @@ -78,8 +79,10 @@ def process(
ensemble_members (Optional[int]):
Number of ensemble members. Default 8. Will not be used if "realizations",
"percentiles" or "thresholds" provided in json_input.
grid_spacing (Optional[float]):
Resolution of grid (metres or degrees).
x_grid_spacing (Optional[float]):
Resolution of grid along the x-axis (metres or degrees).
y_grid_spacing (Optional[float]):
Resolution of grid along the y-axis (metres or degrees).
domain_corner (Optional[Tuple[float, float]]):
Bottom left corner of grid domain (y,x) (degrees for latlon or metres for
equalarea).
Expand Down
9 changes: 5 additions & 4 deletions improver/synthetic_data/generate_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,12 @@ def generate_metadata(
kwargs["time_bounds"] = time_bounds

# If grid_spacing not specified, use default for requested spatial grid
if "grid_spacing" not in kwargs or kwargs["grid_spacing"] is None:
if "spatial_grid" not in kwargs:
kwargs["spatial_grid"] = DEFAULT_SPATIAL_GRID
for spacing_axis in ["x_grid_spacing", "y_grid_spacing"]:
if spacing_axis not in kwargs or kwargs[spacing_axis] is None:
if "spatial_grid" not in kwargs:
kwargs["spatial_grid"] = DEFAULT_SPATIAL_GRID

kwargs["grid_spacing"] = DEFAULT_GRID_SPACING[kwargs["spatial_grid"]]
kwargs[spacing_axis] = DEFAULT_GRID_SPACING[kwargs["spatial_grid"]]

# Create ndimensional array of zeros
if "height_levels" not in kwargs:
Expand Down
62 changes: 42 additions & 20 deletions improver/synthetic_data/set_up_test_cubes.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def construct_yx_coords(
ypoints: int,
xpoints: int,
spatial_grid: str,
grid_spacing: Optional[float] = None,
x_grid_spacing: Optional[float] = None,
y_grid_spacing: Optional[float] = None,
domain_corner: Optional[Tuple[float, float]] = None,
) -> Tuple[DimCoord, DimCoord]:
"""
Expand All @@ -76,9 +77,14 @@ def construct_yx_coords(
Number of grid points required along the x-axis
spatial_grid:
Specifier to produce either a "latlon" or "equalarea" grid
grid_spacing:
Grid resolution (degrees for latlon or metres for equalarea). If not provided,
defaults to 10 degrees for "latlon" grid or 2000 metres for "equalarea" grid
x_grid_spacing:
Grid resolution along the x axis. Degrees for latlon or metres for equalarea.
If not provided, defaults to 10 degrees for "latlon" grid or 2000 metres for
"equalarea" grid
y_grid_spacing:
Grid resolution along the y axis. Degrees for latlon or metres for equalarea.
If not provided, defaults to 10 degrees for "latlon" grid or 2000 metres for
"equalarea" grid
domain_corner:
Bottom left corner of grid domain (y,x) (degrees for latlon or metres for equalarea).
If not provided, a grid is created centred around (0,0).
Expand All @@ -89,12 +95,18 @@ def construct_yx_coords(
if spatial_grid not in GRID_COORD_ATTRIBUTES.keys():
raise ValueError("Grid type {} not recognised".format(spatial_grid))

if grid_spacing is None:
grid_spacing = GRID_COORD_ATTRIBUTES[spatial_grid]["default_grid_spacing"]
if x_grid_spacing is None:
x_grid_spacing = GRID_COORD_ATTRIBUTES[spatial_grid]["default_grid_spacing"]
if y_grid_spacing is None:
y_grid_spacing = GRID_COORD_ATTRIBUTES[spatial_grid]["default_grid_spacing"]

if domain_corner is None:
domain_corner = _set_domain_corner(ypoints, xpoints, grid_spacing)
y_array, x_array = _create_yx_arrays(ypoints, xpoints, domain_corner, grid_spacing)
domain_corner = _set_domain_corner(
ypoints, xpoints, x_grid_spacing, y_grid_spacing
)
y_array, x_array = _create_yx_arrays(
ypoints, xpoints, domain_corner, x_grid_spacing, y_grid_spacing
)

y_coord = DimCoord(
y_array,
Expand All @@ -119,7 +131,11 @@ def construct_yx_coords(


def _create_yx_arrays(
ypoints: int, xpoints: int, domain_corner: Tuple[float, float], grid_spacing: float,
ypoints: int,
xpoints: int,
domain_corner: Tuple[float, float],
x_grid_spacing: float,
y_grid_spacing: float,
) -> Tuple[ndarray, ndarray]:
"""
Creates arrays for constructing y and x DimCoords.
Expand All @@ -128,13 +144,14 @@ def _create_yx_arrays(
ypoints
xpoints
domain_corner
grid_spacing
x_grid_spacing
y_grid_spacing
Returns:
Tuple containing arrays of y and x coordinate values
"""
y_stop = domain_corner[0] + (grid_spacing * (ypoints - 1))
x_stop = domain_corner[1] + (grid_spacing * (xpoints - 1))
y_stop = domain_corner[0] + (y_grid_spacing * (ypoints - 1))
x_stop = domain_corner[1] + (x_grid_spacing * (xpoints - 1))

y_array = np.linspace(domain_corner[0], y_stop, ypoints, dtype=np.float32)
x_array = np.linspace(domain_corner[1], x_stop, xpoints, dtype=np.float32)
Expand All @@ -143,21 +160,22 @@ def _create_yx_arrays(


def _set_domain_corner(
ypoints: int, xpoints: int, grid_spacing: float
ypoints: int, xpoints: int, x_grid_spacing: float, y_grid_spacing: float
) -> Tuple[float, float]:
"""
Set domain corner to create a grid around 0,0.
Args:
ypoints
xpoints
grid_spacing
x_grid_spacing
y_grid_spacing
Returns:
(y,x) values of the bottom left corner of the domain
"""
y_start = 0 - ((ypoints - 1) * grid_spacing) / 2
x_start = 0 - ((xpoints - 1) * grid_spacing) / 2
y_start = 0 - ((ypoints - 1) * y_grid_spacing) / 2
x_start = 0 - ((xpoints - 1) * x_grid_spacing) / 2

return y_start, x_start

Expand Down Expand Up @@ -387,7 +405,8 @@ def set_up_variable_cube(
include_scalar_coords: Optional[List[Coord]] = None,
attributes: Optional[Dict[str, str]] = None,
standard_grid_metadata: Optional[str] = None,
grid_spacing: Optional[float] = None,
x_grid_spacing: Optional[float] = None,
y_grid_spacing: Optional[float] = None,
domain_corner: Optional[Tuple[float, float]] = None,
height_levels: Optional[Union[List[float], ndarray]] = None,
pressure: bool = False,
Expand Down Expand Up @@ -431,8 +450,10 @@ def set_up_variable_cube(
Recognised mosg__model_configuration for which to set up Met
Office standard grid attributes. Should be 'uk_det', 'uk_ens',
'gl_det' or 'gl_ens'.
grid_spacing:
Grid resolution (degrees for latlon or metres for equalarea).
x_grid_spacing:
Grid resolution along the x axis (degrees for latlon or metres for equalarea).
y_grid_spacing:
Grid resolution along the y axis (degrees for latlon or metres for equalarea).
domain_corner:
Bottom left corner of grid domain (y,x) (degrees for latlon or metres for equalarea).
height_levels:
Expand All @@ -453,7 +474,8 @@ def set_up_variable_cube(
ypoints,
xpoints,
spatial_grid,
grid_spacing=grid_spacing,
x_grid_spacing=x_grid_spacing,
y_grid_spacing=y_grid_spacing,
domain_corner=domain_corner,
)

Expand Down
4 changes: 3 additions & 1 deletion improver_tests/acceptance/test_generate_metadata_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ def test_ensemble_members(tmp_path):
"120",
"--ensemble-members",
"4",
"--grid-spacing",
"--x-grid-spacing",
"1000",
"--y-grid-spacing",
"1000",
"--domain-corner",
"0,0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ def set_up_masked_cubes():
frt=cycletime,
spatial_grid="equalarea",
standard_grid_metadata="uk_det",
grid_spacing=grid_spacing,
x_grid_spacing=grid_spacing,
y_grid_spacing=grid_spacing,
)

# set up a masked nowcast cube with more rain
Expand All @@ -108,7 +109,8 @@ def set_up_masked_cubes():
frt=cycletime,
spatial_grid="equalarea",
attributes={"mosg__model_configuration": "nc_det"},
grid_spacing=grid_spacing,
x_grid_spacing=grid_spacing,
y_grid_spacing=grid_spacing,
)

return iris.cube.CubeList([ukv_cube, nowcast_cube]), cycletime_string
Expand Down
7 changes: 6 additions & 1 deletion improver_tests/categorical/decision_tree/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ def set_up_wxcube(

if lat_lon:
kwargs.update(
{"spatial_grid": "latlon", "domain_corner": (49, -8), "grid_spacing": 1}
{
"spatial_grid": "latlon",
"domain_corner": (49, -8),
"x_grid_spacing": 1,
"y_grid_spacing": 1,
}
)
cube = set_up_variable_cube(data, **kwargs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ def orography_fixture() -> Cube:
name="surface_altitude",
units="m",
spatial_grid="equalarea",
grid_spacing=1000,
x_grid_spacing=1000,
y_grid_spacing=1000,
domain_corner=(-1000, -1000),
)
return cube
Expand Down Expand Up @@ -102,7 +103,8 @@ def mask_fixture() -> Cube:
name="land_binary_mask",
units="1",
spatial_grid="equalarea",
grid_spacing=1000,
x_grid_spacing=1000,
y_grid_spacing=1000,
domain_corner=(-2000, -2000),
)
return mask
Expand Down
9 changes: 6 additions & 3 deletions improver_tests/lightning/test_LightningFromCapePrecip.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def cape_cube_fixture() -> Cube:
attributes=None,
standard_grid_metadata="gl_ens",
domain_corner=(-60, 0),
grid_spacing=20,
x_grid_spacing=20,
y_grid_spacing=20,
)
return cube

Expand All @@ -85,7 +86,8 @@ def precip_cube_fixture() -> Cube:
attributes=None,
standard_grid_metadata="gl_ens",
domain_corner=(-60, 0),
grid_spacing=20,
x_grid_spacing=20,
y_grid_spacing=20,
)
return cube

Expand All @@ -107,7 +109,8 @@ def expected_cube_fixture() -> Cube:
time_bounds=(datetime(2017, 11, 10, 4, 0), datetime(2017, 11, 10, 5, 0)),
attributes=MANDATORY_ATTRIBUTE_DEFAULTS,
domain_corner=(-60, 0),
grid_spacing=20,
x_grid_spacing=20,
y_grid_spacing=20,
)
cube = add_coordinate(
cube,
Expand Down
3 changes: 2 additions & 1 deletion improver_tests/nowcasting/optical_flow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def set_up_test_cube(data, name, units, time):
spatial_grid="equalarea",
time=time,
frt=time,
grid_spacing=2000,
x_grid_spacing=2000,
y_grid_spacing=2000,
domain_corner=(0, 0),
)
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def input_cubes():
data.copy(),
name="lwe_convective_precipitation_rate",
units="m s-1",
grid_spacing=10,
x_grid_spacing=10,
y_grid_spacing=10,
domain_corner=(-90, -180),
attributes=GLOBAL_ATTRIBUTES,
)
Expand All @@ -72,7 +73,8 @@ def input_cubes():
data.copy(),
name="lwe_stratiform_precipitation_rate",
units="m s-1",
grid_spacing=10,
x_grid_spacing=10,
y_grid_spacing=10,
domain_corner=(-90, -180),
attributes=GLOBAL_ATTRIBUTES,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ def setUp(self):
name="orographic_height",
units="m",
spatial_grid="equalarea",
grid_spacing=2000.0,
x_grid_spacing=2000.0,
y_grid_spacing=2000.0,
)
self.expected_data = [
[50, 50, 50, 20, 5],
Expand All @@ -424,7 +425,8 @@ def setUp(self):
name="orographic_height",
units="m",
spatial_grid="latlon",
grid_spacing=0.01,
x_grid_spacing=0.01,
y_grid_spacing=0.01,
)

def test_basic(self):
Expand Down
3 changes: 2 additions & 1 deletion improver_tests/regrid/test_AdjustLandSeaPoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ def setUp(self):
"precipitation_amount",
"kg m^-2",
"equalarea",
grid_spacing=2000,
x_grid_spacing=2000,
y_grid_spacing=2000,
domain_corner=(0, -50000),
)

Expand Down
3 changes: 2 additions & 1 deletion improver_tests/regrid/test_RegridLandSea.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ def setUp(self):
spatial_grid="latlon",
standard_grid_metadata="gl_det",
domain_corner=domain_corner,
grid_spacing=2,
x_grid_spacing=2,
y_grid_spacing=2,
)

# set up dummy landmask on source grid
Expand Down
3 changes: 2 additions & 1 deletion improver_tests/spotdata/test_SpotExtraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def setUp(self):
units="K",
attributes=attributes,
domain_corner=(0, 0),
grid_spacing=10,
x_grid_spacing=10,
y_grid_spacing=10,
time=time,
frt=frt,
)
Expand Down
8 changes: 6 additions & 2 deletions improver_tests/synthetic_data/test_generate_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def test_name_unknown_with_units():
def test_set_spatial_grid(spatial_grid):
""" Tests different spatial grids generates cubes with default values for that
spatial grid """
cube = generate_metadata(MANDATORY_ATTRIBUTE_DEFAULTS, spatial_grid=spatial_grid,)
cube = generate_metadata(MANDATORY_ATTRIBUTE_DEFAULTS, spatial_grid=spatial_grid)

expected_spatial_grid_attributes = SPATIAL_GRID_ATTRIBUTE_DEFAULTS[spatial_grid]

Expand Down Expand Up @@ -449,7 +449,11 @@ def test_set_grid_spacing():
""" Tests cube generated with specified grid_spacing and the rest of the values set
as default values """
grid_spacing = 5
cube = generate_metadata(MANDATORY_ATTRIBUTE_DEFAULTS, grid_spacing=grid_spacing)
cube = generate_metadata(
MANDATORY_ATTRIBUTE_DEFAULTS,
x_grid_spacing=grid_spacing,
y_grid_spacing=grid_spacing,
)

assert np.diff(cube.coord(axis="y").points)[0] == grid_spacing
assert np.diff(cube.coord(axis="x").points)[0] == grid_spacing
Expand Down
Loading

0 comments on commit 84a8944

Please sign in to comment.