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

Modifies LightningFromCapePrecip plugin to accept 3h precipitation-rate-max data #1568

Merged
merged 3 commits into from
Sep 28, 2021
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
13 changes: 7 additions & 6 deletions improver/lightning.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ def _get_inputs(cubes: CubeList) -> Tuple[Cube, Cube]:
"""
Separates CAPE and precipitation rate cubes and checks that the following
match: forecast_reference_time, spatial coords, time-bound interval and
that CAPE time is exactly one hour older than precipitation rate time.
that CAPE time is at the lower bound of precipitation rate time.
Copy link
Contributor

Choose a reason for hiding this comment

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

As a note, and unrelated to this PR, the acceptance tests for the lightning_from_cape_and_precip.py CLI are currently failing due a mismatch in the units for the number_of_lightning_flashes_per_unit_area coordinate i.e. m-2 vs s-1.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Final tweak from #1550 hadn't been committed and merged - it has now.

The precipitation rate data must represent a period of 1 or 3 hours.
"""
cape = cubes.extract(
iris.Constraint(
Expand All @@ -100,14 +101,14 @@ def _get_inputs(cubes: CubeList) -> Tuple[Cube, Cube]:
raise ValueError(f"No cube named precipitation_rate_max found in {cubes}")
(cape_time,) = list(cape.coord("time").cells())
(precip_time,) = list(precip.coord("time").cells())
if cape_time.point + timedelta(hours=1) != precip_time.point:
if cape_time.point != precip_time.bound[0]:
raise ValueError(
f"CAPE cube time ({cape_time.point}) should be valid one hour earlier "
f"than precipitation_rate_max cube time ({precip_time.point})."
f"CAPE cube time ({cape_time.point}) should be valid at the "
f"precipitation_rate_max cube lower bound ({precip_time.bound[0]})."
)
if np.diff(precip_time.bound) != timedelta(hours=1):
if np.diff(precip_time.bound) not in [timedelta(hours=1), timedelta(hours=3)]:
raise ValueError(
f"Precipitation_rate_max cube time window must be one hour, "
f"Precipitation_rate_max cube time window must be one or three hours, "
f"not {np.diff(precip_time.bound)}."
)
if cape.coord("forecast_reference_time") != precip.coord(
Expand Down
29 changes: 20 additions & 9 deletions improver_tests/lightning/test_LightningFromCapePrecip.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ def test_basic(cape_cube, precip_cube, expected_cube):
assert np.allclose(result.data, expected_cube.data)


def test_3h_cubes(cape_cube, precip_cube, expected_cube):
"""Run the plugin again with 3h cubes"""
cape_cube.coord("time").points = cape_cube.coord("time").points - 2 * 3600
bounds = precip_cube.coord("time").bounds
gavinevans marked this conversation as resolved.
Show resolved Hide resolved
precip_cube.coord("time").bounds = (bounds[0][0] - 2 * 3600, bounds[0][1])
precip_cube.rename("precipitation_rate_max-PT03H")
expected_cube.coord("time").bounds = (bounds[0][0] - 2 * 3600, bounds[0][1])
result = LightningFromCapePrecip()(CubeList([cape_cube, precip_cube]))
assert result.xml().splitlines(keepends=True) == expected_cube.xml().splitlines(
keepends=True
)
assert np.allclose(result.data, expected_cube.data)


def test_with_model_attribute(cape_cube, precip_cube, expected_cube):
"""Run the plugin with model_id_attr and check the result cube matches the expected_cube"""
expected_cube.attributes["mosg__model_configuration"] = "gl_ens"
Expand All @@ -142,21 +156,18 @@ def test_with_model_attribute(cape_cube, precip_cube, expected_cube):


def break_time_point(cape_cube, precip_cube):
"""Modifies precip_cube time points to be incremented by 1 second and
"""Modifies cape_cube time points to be incremented by 1 second and
returns the error message this will trigger"""
precip_cube.coord("time").points = precip_cube.coord("time").points + 1
return (
r"CAPE cube time .* should be valid one hour earlier than "
r"precipitation_rate_max cube time .*"
)
cape_cube.coord("time").points = cape_cube.coord("time").points + 1
return r"CAPE cube time .* should be valid at the precipitation_rate_max cube lower bound .*"


def break_time_bound(cape_cube, precip_cube):
"""Modifies lower bound on precip_cube time coord to be incremented by 1 second and
"""Modifies upper bound on precip_cube time coord to be incremented by 1 second and
returns the error message this will trigger"""
bounds = precip_cube.coord("time").bounds
precip_cube.coord("time").bounds = (bounds[0][0] + 1, bounds[0][1])
return r"Precipitation_rate_max cube time window must be one hour, not .*"
precip_cube.coord("time").bounds = (bounds[0][0], bounds[0][1] + 1)
bayliffe marked this conversation as resolved.
Show resolved Hide resolved
return r"Precipitation_rate_max cube time window must be one or three hours, not .*"


def break_reference_time(cape_cube, precip_cube):
Expand Down