def test_probabilities_not_monotonically_increasing( self, warning_list=None): """ Test that the plugin raises a Warning when the probabilities of the Cumulative Distribution Function are not monotonically increasing. """ data = np.array([0.05, 0.7, 0.95]) data = data[:, np.newaxis, np.newaxis, np.newaxis] self.current_temperature_forecast_cube = add_forecast_reference_time_and_forecast_period( set_up_probability_threshold_cube( data, "air_temperature", "degreesC", forecast_thresholds=[8, 10, 12], y_dimension_length=1, x_dimension_length=1, spp__relative_to_threshold="above", )) cube = self.current_temperature_forecast_cube percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() warning_msg = "The probability values used to construct the" plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertTrue(any(warning_msg in str(item) for item in warning_list))
def test_transpose_cube_dimensions(self): """ Test that the plugin returns an the expected data, when comparing input cubes which have dimensions in a different order. """ # Calculate result for nontransposed cube. cube = self.current_temperature_forecast_cube percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() nontransposed_result = plugin._probabilities_to_percentiles( cube, percentiles, bounds_pairing) # Calculate result for transposed cube. # Original cube dimensions are [P, T, Y, X]. # Transposed cube dimensions are [X, Y, T, P]. cube.transpose([3, 2, 1, 0]) transposed_result = plugin._probabilities_to_percentiles( cube, percentiles, bounds_pairing) # Result cube will be [P, X, Y, T] # Transpose cube to be [P, T, Y, X] transposed_result.transpose([0, 3, 2, 1]) self.assertArrayAlmostEqual(nontransposed_result.data, transposed_result.data)
def test_unknown_thresholding(self): """Test that the plugin returns an Iris.cube.Cube.""" cube = self.current_temperature_forecast_cube cube.coord(var_name="threshold" ).attributes["spp__relative_to_threshold"] = "between" percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() msg = "Probabilities to percentiles only implemented for" with self.assertRaisesRegex(NotImplementedError, msg): plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing)
def test_simple_check_data_below(self): """ Test that the plugin returns an Iris.cube.Cube with the expected data values for the percentiles when input probabilities are given for being below a threshold. The input cube contains probabilities that values are below a given threshold. """ expected = np.array([8.4, 10.61538462, 11.84615385]) expected = expected[:, np.newaxis, np.newaxis, np.newaxis] data = np.array([0.95, 0.3, 0.05])[::-1] data = data[:, np.newaxis, np.newaxis, np.newaxis] self.current_temperature_forecast_cube = add_forecast_reference_time_and_forecast_period( set_up_probability_threshold_cube( data, "air_temperature", "degreesC", forecast_thresholds=[8, 10, 12], y_dimension_length=1, x_dimension_length=1, spp__relative_to_threshold="above", )) cube = self.current_temperature_forecast_cube cube.coord(var_name="threshold" ).attributes["spp__relative_to_threshold"] = "below" percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertArrayAlmostEqual(result.data, expected)
def test_lots_of_percentiles(self): """ Test that the plugin returns an Iris.cube.Cube with the expected data values for the percentiles, if lots of percentile values are requested. """ data = np.array( [[[[13.9, -16., 10.2], [-28., -16., -35.2], [-35.2, -37., -37.6]]], [[[17.7, 8.25, 10.6], [-4., 8.25, -25.6], [-25.6, -31., -32.8]]], [[[21.5, 8.75, 11.], [8.33333333, 8.75, -16.], [-16., -25., -28.]] ], [[[25.3, 9.25, 11.4], [9., 9.25, -6.4], [-6.4, -19., -23.2]]], [[[29.1, 9.75, 11.8], [9.66666667, 9.75, 3.2], [3.2, -13., -18.4]] ], [[[32.9, 10.33333333, 15.8], [10.33333333, 10.2, 8.5], [8.33333333, -7., -13.6]]], [[[36.7, 11., 23.4], [11., 10.6, 9.5], [9., -1., -8.8]]], [[[40.5, 11.66666667, 31.], [11.66666667, 11., 10.5], [9.66666667, 5., -4.]]], [[[44.3, 21.5, 38.6], [21.5, 11.4, 11.5], [10.5, 8.5, 0.8]]], [[[48.1, 40.5, 46.2], [40.5, 11.8, 31.], [11.5, 9.5, 5.6]]]], dtype=np.float32) cube = self.current_temperature_forecast_cube percentiles = np.arange(5, 100, 10) bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertArrayAlmostEqual(result.data, data, decimal=5)
def test_lots_of_probability_thresholds(self): """ Test that the plugin returns an Iris.cube.Cube with the expected data values for the percentiles, if there are lots of thresholds. """ input_probs_1d = np.linspace(1, 0, 30) input_probs = np.tile(input_probs_1d, (3, 3, 1, 1)).T data = np.array( [[[[2.9, 2.9, 2.9], [2.9, 2.9, 2.9], [2.9, 2.9, 2.9]]], [[[14.5, 14.5, 14.5], [14.5, 14.5, 14.5], [14.5, 14.5, 14.5]]], [[[26.099998, 26.099998, 26.099998], [26.099998, 26.099998, 26.099998], [26.099998, 26.099998, 26.099998]]]], dtype=np.float32) temperature_values = np.arange(0, 30) cube = (add_forecast_reference_time_and_forecast_period( set_up_probability_threshold_cube( input_probs, "air_temperature", "degreesC", forecast_thresholds=temperature_values, spp__relative_to_threshold='above'))) percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertArrayAlmostEqual(result.data, data)
def test_check_single_threshold(self): """ Test that the plugin returns an Iris.cube.Cube with the expected data values for the percentiles, if a single threshold is used for constructing the percentiles. """ data = np.array( [[[[12.2, 8., 12.2], [-16., 8., -30.4], [-30.4, -34., -35.2]]], [[[29., 26.66666667, 29.], [23.75, 26.66666667, 8.], [8., -10., -16.]]], [[[45.8, 45.33333333, 45.8], [44.75, 45.33333333, 41.6], [41.6, 29., 3.2]]]], dtype=np.float32) threshold_coord = find_threshold_coordinate( self.current_temperature_forecast_cube) for acube in self.current_temperature_forecast_cube.slices_over( threshold_coord): cube = acube break percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertArrayAlmostEqual(result.data, data, decimal=5)
def test_basic(self): """Test that the plugin returns an Iris.cube.Cube.""" cube = self.current_temperature_forecast_cube percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertIsInstance(result, Cube)
def test_return_name(self): """Test that the plugin returns an Iris.cube.Cube with an appropriate name. """ cube = self.current_temperature_forecast_cube percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertEqual(result.name(), "air_temperature")
def test_result_cube_has_no_air_temperature_threshold_coordinate(self): """ Test that the plugin returns a cube with coordinates that do not include the air_temperature_threshold coordinate. """ cube = self.current_temperature_forecast_cube percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) for coord in result.coords(): self.assertNotEqual(coord.name(), "threshold")
def test_return_coord_units(self): """Test that the plugin returns an Iris.cube.Cube with an appropriate percentile coordinate with suitable units. """ cube = self.current_temperature_forecast_cube percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertIsInstance(result.coord("percentile"), DimCoord) self.assertArrayEqual(result.coord("percentile").points, percentiles) self.assertEqual(result.coord("percentile").units, unit.Unit("%"))
def test_check_data_multiple_timesteps(self): """ Test that the plugin returns an Iris.cube.Cube with the expected data values for the percentiles. """ expected = np.array( [ [[[8.0, 8.0], [-8.0, 8.66666667]], [[8.0, -16.0], [8.0, -16.0]] ], [[[12.0, 12.0], [12.0, 12.0]], [[10.5, 10.0], [10.5, 10.0]]], [[[31.0, 31.0], [31.0, 31.0]], [[11.5, 11.33333333], [11.5, 12.0]]], ], dtype=np.float32, ) data = np.array( [ [[[0.8, 0.8], [0.7, 0.9]], [[0.8, 0.6], [0.8, 0.6]]], [[[0.6, 0.6], [0.6, 0.6]], [[0.5, 0.4], [0.5, 0.4]]], [[[0.4, 0.4], [0.4, 0.4]], [[0.1, 0.1], [0.1, 0.2]]], ], dtype=np.float32, ) cube = set_up_probability_threshold_cube( data, "air_temperature", "degreesC", timesteps=2, x_dimension_length=2, y_dimension_length=2, spp__relative_to_threshold="above", ) self.probability_cube = add_forecast_reference_time_and_forecast_period( cube, time_point=np.array([402295.0, 402296.0]), fp_point=[2.0, 3.0]) cube = self.probability_cube percentiles = [20, 60, 80] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertArrayAlmostEqual(result.data, expected, decimal=5)
def test_check_data_spot_forecasts(self): """ Test that the plugin returns an Iris.cube.Cube with the expected data values for the percentiles for spot forecasts. """ data = np.array( [[[15.8, 8., 10.4, -16., 8., -30.4, -30.4, -34., -35.2]], [[31., 10., 12., 10., 10., 8., 8., -10., -16.]], [[46.2, 31., 42.4, 31., 11.6, 12., 11., 9., 3.2]]], dtype=np.float32) cube = self.current_temperature_spot_forecast_cube percentiles = [10, 50, 90] bounds_pairing = (-40, 50) plugin = Plugin() result = plugin._probabilities_to_percentiles(cube, percentiles, bounds_pairing) self.assertArrayAlmostEqual(result.data, data, decimal=5)