class Test_apply_ice(IrisTest): """Test the apply_ice method.""" def setUp(self): """Create test cubes and plugin instance. The cube coordinates look like this: Dimension coordinates: projection_y_coordinate: 3; projection_x_coordinate: 3; Scalar coordinates: time: 2015-11-23 07:00:00 forecast_reference_time: 2015-11-23 07:00:00 forecast_period: 0 seconds self.vii_cube: Has extra coordinate of length(3) "threshold" containing points [0.5, 1., 2.] kg m-2. """ (_, self.fg_cube, _, _, self.ice_cube) = set_up_lightning_test_cubes( validity_time=dt(2015, 11, 23, 7), fg_frt=dt(2015, 11, 23, 7)) self.plugin = Plugin() self.ice_threshold_coord = find_threshold_coordinate(self.ice_cube) def test_basic(self): """Test that the method returns the expected cube type""" result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertIsInstance(result, Cube) def test_input(self): """Test that the method does not modify the input cubes.""" cube_a = self.fg_cube.copy() cube_b = self.ice_cube.copy() self.plugin.apply_ice(cube_a, cube_b) self.assertArrayAlmostEqual(cube_a.data, self.fg_cube.data) self.assertArrayAlmostEqual(cube_b.data, self.ice_cube.data) def test_missing_threshold_low(self): """Test that the method raises an error if the ice_cube doesn't have a threshold coordinate for 0.5.""" self.ice_threshold_coord.points = [0.4, 1.0, 2.0] msg = r"No matching prob\(Ice\) cube for threshold 0.5" with self.assertRaisesRegex(ConstraintMismatchError, msg): self.plugin.apply_ice(self.fg_cube, self.ice_cube) def test_missing_threshold_mid(self): """Test that the method raises an error if the ice_cube doesn't have a threshold coordinate for 1.0.""" self.ice_threshold_coord.points = [0.5, 0.9, 2.0] msg = r"No matching prob\(Ice\) cube for threshold 1." with self.assertRaisesRegex(ConstraintMismatchError, msg): self.plugin.apply_ice(self.fg_cube, self.ice_cube) def test_missing_threshold_high(self): """Test that the method raises an error if the ice_cube doesn't have a threshold coordinate for 2.0.""" self.ice_threshold_coord.points = [0.5, 1.0, 4.0] msg = r"No matching prob\(Ice\) cube for threshold 2." with self.assertRaisesRegex(ConstraintMismatchError, msg): self.plugin.apply_ice(self.fg_cube, self.ice_cube) def test_ice_null(self): """Test that small VII probs do not increase moderate lightning risk""" self.ice_cube.data[:, 1, 1] = 0.0 self.ice_cube.data[0, 1, 1] = 0.5 self.fg_cube.data[1, 1] = 0.25 expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[1, 1] = 0.25 result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data) def test_ice_zero(self): """Test that zero VII probs do not increase zero lightning risk""" self.ice_cube.data[:, 1, 1] = 0.0 self.fg_cube.data[1, 1] = 0.0 expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[1, 1] = 0.0 result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data) def test_ice_small(self): """Test that small VII probs do increase zero lightning risk""" self.ice_cube.data[:, 1, 1] = 0.0 self.ice_cube.data[0, 1, 1] = 0.5 self.fg_cube.data[1, 1] = 0.0 expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[1, 1] = 0.05 result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data) def test_ice_large(self): """Test that large VII probs do increase zero lightning risk""" self.ice_cube.data[:, 1, 1] = 1.0 self.fg_cube.data[1, 1] = 0.0 expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[1, 1] = 0.9 result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data) def test_ice_large_with_fc(self): """Test that large VII probs do increase zero lightning risk when forecast lead time is non-zero (three forecast_period points)""" self.ice_cube.data[:, 1, 1] = 1.0 self.fg_cube.data[1, 1] = 0.0 frt_point = self.fg_cube.coord("forecast_reference_time").points[0] fg_cube_input = CubeList([]) for fc_time in np.array([1, 2.5, 3]) * 3600: # seconds fg_cube_next = self.fg_cube.copy() fg_cube_next.coord("time").points = [frt_point + fc_time] fg_cube_next.coord("forecast_period").points = [fc_time] fg_cube_input.append(squeeze(fg_cube_next)) fg_cube_input = fg_cube_input.merge_cube() expected = fg_cube_input.copy() # expected.data contains all ones except: expected.data[0, 1, 1] = 0.54 expected.data[1, 1, 1] = 0.0 expected.data[2, 1, 1] = 0.0 result = self.plugin.apply_ice(fg_cube_input, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data)
class Test_apply_ice(IrisTest): """Test the apply_ice method.""" def setUp(self): """Create cubes with a single zero prob(precip) point. The cubes look like this: precipitation_amount / (kg m^-2) Dimension coordinates: time: 1; projection_y_coordinate: 3; projection_x_coordinate: 3; Auxiliary coordinates: forecast_period (on time coord): 0.0 hours (simulates nowcast data) Scalar coordinates: forecast_reference_time: 2015-11-23 03:00:00 Data: self.fg_cube: All points contain float(1.) Cube name is "probability_of_lightning". self.ice_cube: With extra coordinate of length(3) "threshold" containing points [0.5, 1., 2.] kg m^-2. Time and forecast_period dimensions "sqeezed" to be Scalar coords. All points contain float(0.) Cube name is "probability_of_vertical_integral_of_ice". """ self.fg_cube = add_forecast_reference_time_and_forecast_period( set_up_cube_with_no_realizations(zero_point_indices=[], num_grid_points=3), fp_point=0.0) self.fg_cube.rename("probability_of_lightning") self.ice_cube = squeeze( add_forecast_reference_time_and_forecast_period(set_up_cube( num_realization_points=3, zero_point_indices=[], num_grid_points=3), fp_point=0.0)) threshold_coord = self.ice_cube.coord('realization') threshold_coord.points = [0.5, 1.0, 2.0] threshold_coord.rename('threshold') threshold_coord.units = cf_units.Unit('kg m^-2') self.ice_cube.data = np.zeros_like(self.ice_cube.data) self.ice_cube.rename("probability_of_vertical_integral_of_ice") self.plugin = Plugin() def test_basic(self): """Test that the method returns the expected cube type""" result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertIsInstance(result, Cube) def test_input(self): """Test that the method does not modify the input cubes.""" cube_a = self.fg_cube.copy() cube_b = self.ice_cube.copy() self.plugin.apply_ice(cube_a, cube_b) self.assertArrayAlmostEqual(cube_a.data, self.fg_cube.data) self.assertArrayAlmostEqual(cube_b.data, self.ice_cube.data) def test_missing_threshold_low(self): """Test that the method raises an error if the ice_cube doesn't have a threshold coordinate for 0.5.""" self.ice_cube.coord('threshold').points = [0.4, 1., 2.] msg = (r"No matching prob\(Ice\) cube for threshold 0.5") with self.assertRaisesRegex(ConstraintMismatchError, msg): self.plugin.apply_ice(self.fg_cube, self.ice_cube) def test_missing_threshold_mid(self): """Test that the method raises an error if the ice_cube doesn't have a threshold coordinate for 1.0.""" self.ice_cube.coord('threshold').points = [0.5, 0.9, 2.] msg = (r"No matching prob\(Ice\) cube for threshold 1.") with self.assertRaisesRegex(ConstraintMismatchError, msg): self.plugin.apply_ice(self.fg_cube, self.ice_cube) def test_missing_threshold_high(self): """Test that the method raises an error if the ice_cube doesn't have a threshold coordinate for 2.0.""" self.ice_cube.coord('threshold').points = [0.5, 1., 4.] msg = (r"No matching prob\(Ice\) cube for threshold 2.") with self.assertRaisesRegex(ConstraintMismatchError, msg): self.plugin.apply_ice(self.fg_cube, self.ice_cube) def test_ice_null(self): """Test that small VII probs do not increase moderate lightning risk""" self.ice_cube.data[:, 1, 1] = 0. self.ice_cube.data[0, 1, 1] = 0.5 self.fg_cube.data[0, 1, 1] = 0.25 expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[0, 1, 1] = 0.25 result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data) def test_ice_zero(self): """Test that zero VII probs do not increase zero lightning risk""" self.ice_cube.data[:, 1, 1] = 0. self.fg_cube.data[0, 1, 1] = 0. expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[0, 1, 1] = 0. result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data) def test_ice_small(self): """Test that small VII probs do increase zero lightning risk""" self.ice_cube.data[:, 1, 1] = 0. self.ice_cube.data[0, 1, 1] = 0.5 self.fg_cube.data[0, 1, 1] = 0. expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[0, 1, 1] = 0.05 result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data) def test_ice_large(self): """Test that large VII probs do increase zero lightning risk""" self.ice_cube.data[:, 1, 1] = 1. self.fg_cube.data[0, 1, 1] = 0. expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[0, 1, 1] = 0.9 result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data) def test_ice_large_with_fc(self): """Test that large VII probs do increase zero lightning risk when forecast lead time is non-zero (two forecast_period points)""" self.ice_cube.data[:, 1, 1] = 1. self.fg_cube.data[0, 1, 1] = 0. self.fg_cube.coord('forecast_period').points = [1.] # hours fg_cube_next = self.fg_cube.copy() time_pt, = self.fg_cube.coord('time').points fg_cube_next.coord('time').points = [time_pt + 2.] # hours fg_cube_next.coord('forecast_period').points = [3.] # hours self.fg_cube = CubeList([squeeze(self.fg_cube), squeeze(fg_cube_next)]).merge_cube() expected = self.fg_cube.copy() # expected.data contains all ones except: expected.data[0, 1, 1] = 0.54 expected.data[1, 1, 1] = 0.0 result = self.plugin.apply_ice(self.fg_cube, self.ice_cube) self.assertArrayAlmostEqual(result.data, expected.data)