def test_radii_varying_with_lead_time(self): """ Test that a cube is returned when the radius varies with lead time. """ cube = set_up_cube(num_time_points=3) iris.util.promote_aux_coord_to_dim_coord(cube, "time") time_points = cube.coord("time").points fp_points = [2, 3, 4] cube = add_forecast_reference_time_and_forecast_period( cube, time_point=time_points, fp_point=fp_points) radii = [10000, 20000, 30000] lead_times = [2, 3, 4] neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, lead_times) result = plugin(cube) self.assertIsInstance(result, Cube) self.assertEqual(cube.coord("forecast_period").units, "hours")
def test_interpolation(self): """Test that interpolation is working as expected in _find_radii.""" fp_points = np.array([2, 3, 4]) neighbourhood_method = CircularNeighbourhood() ens_factor = 0.8 num_ens = 4.0 fp_points = np.array([2, 3, 4]) radii = [10000, 30000] lead_times = [2, 4] plugin = NBHood(neighbourhood_method, radii, lead_times=lead_times, ens_factor=ens_factor) result = plugin._find_radii(num_ens, cube_lead_times=fp_points) expected_result = np.array([4000., 8000., 12000.]) self.assertArrayAlmostEqual(result, expected_result)
def test_basic_array_cube_lead_times_an_array(self): """Test _find_radii returns an array with the correct values.""" neighbourhood_method = CircularNeighbourhood ens_factor = 0.9 num_ens = 2.0 fp_points = np.array([2, 3, 4]) radii = [10000, 20000, 30000] lead_times = [2, 3, 4] plugin = NBHood(neighbourhood_method(), radii, lead_times=lead_times, ens_factor=ens_factor) result = plugin._find_radii(num_ens, cube_lead_times=fp_points) expected_result = np.array([6363.961031, 12727.922061, 19091.883092]) self.assertIsInstance(result, np.ndarray) self.assertArrayAlmostEqual(result, expected_result)
def test_weighted_mode_is_true(self): """Test that the circular neighbourhood processing is successful, if the weighted mode is True.""" expected = np.array( [ [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.91666667, 0.875, 0.91666667, 1.0], [1.0, 0.875, 0.83333333, 0.875, 1.0], [1.0, 0.91666667, 0.875, 0.91666667, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], ] ) neighbourhood_method = "circular" radii = 4000 result = NBHood(neighbourhood_method, radii)(self.cube) self.assertIsInstance(result, Cube) self.assertArrayAlmostEqual(result.data, expected)
def test_weighted_mode_is_false(self): """Test that the circular neighbourhood processing is successful, if the weighted mode is False.""" expected = np.array( [ [1.0, 1.0, 0.92307692, 1.0, 1.0], [1.0, 0.92307692, 0.92307692, 0.92307692, 1.0], [0.92307692, 0.92307692, 0.92307692, 0.92307692, 0.92307692], [1.0, 0.92307692, 0.92307692, 0.92307692, 1.0], [1.0, 1.0, 0.92307692, 1.0, 1.0], ] ) neighbourhood_method = "circular" radii = 4000 result = NBHood(neighbourhood_method, radii, weighted_mode=False)(self.cube) self.assertIsInstance(result, Cube) self.assertArrayAlmostEqual(result.data, expected)
def test_radii_varying_with_lead_time_fp_seconds(self): """ Test that a cube fp coord is unchanged by the lead time calculation. """ cube = set_up_cube(num_time_points=3) iris.util.promote_aux_coord_to_dim_coord(cube, "time") time_points = cube.coord("time").points fp_points = [2, 3, 4] cube = add_forecast_reference_time_and_forecast_period( cube, time_point=time_points, fp_point=fp_points) cube.coord("forecast_period").convert_units("seconds") radii = [10000, 20000, 30000] lead_times = [2, 3, 4] neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, lead_times) result = plugin.process(cube) self.assertIsInstance(result, Cube) self.assertEqual(cube.coord("forecast_period").units, "seconds")
def test_radii_varying_with_lead_time_with_interpolation(self): """Test that a cube is returned for the following conditions: 1. The radius varies with lead time. 2. Linear interpolation is required to create values for the radii which are required but were not specified within the 'radii' argument.""" cube = set_up_cube(num_time_points=3) iris.util.promote_aux_coord_to_dim_coord(cube, "time") time_points = cube.coord("time").points fp_points = [2, 3, 4] cube = add_forecast_reference_time_and_forecast_period( cube, time_point=time_points, fp_point=fp_points) radii = [10000, 30000] lead_times = [2, 4] neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, lead_times) result = plugin.process(cube) self.assertIsInstance(result, Cube)
def test_source_realizations(self): """Test when the array has source_realization attribute.""" member_list = [0, 1, 2, 3] cube = ( set_up_cube_with_no_realizations(source_realizations=member_list)) radii = 14400 ens_factor = 0.8 neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, ens_factor=ens_factor) result = plugin.process(cube) self.assertIsInstance(result, Cube) expected = np.ones([1, 16, 16]) expected[0, 6:9, 6:9] = ( [0.91666667, 0.875, 0.91666667], [0.875, 0.83333333, 0.875], [0.91666667, 0.875, 0.91666667]) self.assertArrayAlmostEqual(result.data, expected)
def test_radii_varying_with_lead_time_check_data(self): """ Test that the expected data is produced when the radius varies with lead time. """ cube = set_up_cube( zero_point_indices=((0, 0, 7, 7), ( 0, 1, 7, 7, ), (0, 2, 7, 7)), num_time_points=3, ) expected = np.ones_like(cube.data) expected[0, 0, 6:9, 6:9] = ( [0.91666667, 0.875, 0.91666667], [0.875, 0.83333333, 0.875], [0.91666667, 0.875, 0.91666667], ) expected[0, 1, 5:10, 5:10] = SINGLE_POINT_RANGE_3_CENTROID expected[0, 2, 4:11, 4:11] = ( [1, 0.9925, 0.985, 0.9825, 0.985, 0.9925, 1], [0.9925, 0.98, 0.9725, 0.97, 0.9725, 0.98, 0.9925], [0.985, 0.9725, 0.965, 0.9625, 0.965, 0.9725, 0.985], [0.9825, 0.97, 0.9625, 0.96, 0.9625, 0.97, 0.9825], [0.985, 0.9725, 0.965, 0.9625, 0.965, 0.9725, 0.985], [0.9925, 0.98, 0.9725, 0.97, 0.9725, 0.98, 0.9925], [1, 0.9925, 0.985, 0.9825, 0.985, 0.9925, 1], ) iris.util.promote_aux_coord_to_dim_coord(cube, "time") time_points = cube.coord("time").points fp_points = [2, 3, 4] cube = add_forecast_reference_time_and_forecast_period( cube, time_point=time_points, fp_point=fp_points) radii = [5600, 7600, 9500] lead_times = [2, 3, 4] neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, lead_times) result = plugin(cube) self.assertArrayAlmostEqual(result.data, expected)
def test_use_mask_cube_occurrences_masked(self): """Test that the plugin returns an iris.cube.Cube with the correct data array if a mask cube is used and the mask cube does mask out the occurrences.""" expected = np.array([[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 0., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]]) cube = set_up_cube(zero_point_indices=((0, 0, 2, 2), ), num_grid_points=5, num_time_points=1) cube = iris.util.squeeze(cube) mask_cube = cube.copy() mask_cube.data = np.array([[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 0., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]]) radius = 2000 neighbourhood_method = SquareNeighbourhood() result = NBHood(neighbourhood_method, radius).process(cube, mask_cube) self.assertArrayAlmostEqual(result.data, expected)
def test_use_mask_cube_occurrences_masked(self): """Test that the plugin returns an iris.cube.Cube with the correct data array if a mask cube is used and the mask cube does mask out the occurrences.""" data = np.ones((5, 5), dtype=np.float32) data[2, 2] = 0 cube = set_up_variable_cube( data, spatial_grid="equalarea", ) expected_data = data mask_cube = cube.copy() radius = 2000 neighbourhood_method = SquareNeighbourhood() result = NBHood(neighbourhood_method, radius)(cube, mask_cube) self.assertArrayAlmostEqual(result.data, expected_data)
def test_square_neighbourhood(self): """Test that the square neighbourhood processing is successful.""" expected = np.array( [ [ [ [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.88888889, 0.88888889, 0.88888889, 1.0], [1.0, 0.88888889, 0.88888889, 0.88888889, 1.0], [1.0, 0.88888889, 0.88888889, 0.88888889, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], ] ] ] ) neighbourhood_method = "square" radii = 2000 result = NBHood(neighbourhood_method, radii)(self.cube) self.assertIsInstance(result, Cube) self.assertArrayAlmostEqual(result.data, expected)
def test_radii_varying_with_lead_time_with_interpolation_check_data(self): """Test that a cube with the correct data is returned for the following conditions: 1. The radius varies with lead time. 2. Linear interpolation is required to create values for the radii which are required but were not specified within the 'radii' argument.""" cube = set_up_cube(zero_point_indices=((0, 0, 7, 7), ( 0, 1, 7, 7, ), (0, 2, 7, 7)), num_time_points=3) expected = np.ones_like(cube.data) expected[0, 0, 6:9, 6:9] = ([0.91666667, 0.875, 0.91666667], [0.875, 0.83333333, 0.875], [0.91666667, 0.875, 0.91666667]) expected[0, 1, 5:10, 5:10] = SINGLE_POINT_RANGE_3_CENTROID expected[0, 2, 4:11, 4:11] = ([ 1, 0.9925, 0.985, 0.9825, 0.985, 0.9925, 1 ], [0.9925, 0.98, 0.9725, 0.97, 0.9725, 0.98, 0.9925], [0.985, 0.9725, 0.965, 0.9625, 0.965, 0.9725, 0.985], [ 0.9825, 0.97, 0.9625, 0.96, 0.9625, 0.97, 0.9825 ], [0.985, 0.9725, 0.965, 0.9625, 0.965, 0.9725, 0.985], [0.9925, 0.98, 0.9725, 0.97, 0.9725, 0.98, 0.9925], [1, 0.9925, 0.985, 0.9825, 0.985, 0.9925, 1]) iris.util.promote_aux_coord_to_dim_coord(cube, "time") time_points = cube.coord("time").points fp_points = [2, 3, 4] cube = add_forecast_reference_time_and_forecast_period( cube, time_point=time_points, fp_point=fp_points) radii = [5600, 9500] lead_times = [2, 4] neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, lead_times) result = plugin.process(cube) self.assertArrayAlmostEqual(result.data, expected)
def test_multiple_thresholds(self): """Test when the cube has a threshold dimension.""" data = np.ones((4, 16, 16), dtype=np.float32) data[0, 7, 7] = 0 cube = set_up_probability_cube( data, thresholds=np.array([278, 277, 276, 275], dtype=np.float32), spatial_grid="equalarea", ) radii = 5600 neighbourhood_method = CircularNeighbourhood() result = NBHood(neighbourhood_method, radii)(cube) self.assertIsInstance(result, Cube) expected = np.ones([4, 16, 16], dtype=np.float32) expected[0, 6:9, 6:9] = ( [0.9166666, 0.875, 0.9166666], [0.875, 0.8333333, 0.875], [0.9166666, 0.875, 0.9166666], ) self.assertArrayAlmostEqual(result.data, expected)
def test_multiple_realizations_and_times(self): """Test when the cube has a realization and time dimension.""" cube = set_up_cube(num_time_points=3, num_realization_points=4) iris.util.promote_aux_coord_to_dim_coord(cube, "time") time_points = cube.coord("time").points fp_points = [2, 3, 4] cube = add_forecast_reference_time_and_forecast_period( cube, time_point=time_points, fp_point=fp_points) radii = [14400, 14400, 14400] lead_times = [2, 3, 4] neighbourhood_method = CircularNeighbourhood() ens_factor = 0.8 result = NBHood(neighbourhood_method, radii, lead_times=lead_times, ens_factor=ens_factor).process(cube) self.assertIsInstance(result, Cube) expected = np.ones([4, 3, 16, 16]) expected[0, 0, 6:9, 6:9] = ([0.91666667, 0.875, 0.91666667], [0.875, 0.83333333, 0.875], [0.91666667, 0.875, 0.91666667]) self.assertArrayAlmostEqual(result.data, expected)
def test_use_mask_cube_occurrences_masked_irregular(self): """Test that the plugin returns an iris.cube.Cube with the correct data array if a mask cube is used and the mask cube does mask out the occurrences. In this case, an irregular mask is applied.""" expected = np.array( [[[[1.000000, 1.000000, 1.000000, 1.000000, 1.000000], [1.000000, 0.000000, 0.833333, 0.000000, 1.000000], [1.000000, 0.000000, 0.833333, 0.875000, 1.000000], [1.000000, 0.857143, 0.833333, 0.857143, 1.000000], [1.000000, 0.000000, 1.000000, 0.000000, 0.000000]]]]) cube = set_up_cube(zero_point_indices=((0, 0, 2, 2), ), num_grid_points=5, num_time_points=1) mask_cube = cube.copy() mask_cube.data = np.array([[[[1., 1., 1., 1., 1.], [1., 0., 1., 0., 1.], [1., 0., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 0., 1., 0., 0.]]]]) radius = 2000 neighbourhood_method = SquareNeighbourhood() result = NBHood(neighbourhood_method, radius).process(cube, mask_cube) self.assertArrayAlmostEqual(result.data, expected)
def test_radii_varying_with_lead_time_multiple_realizations(self): """Test that a cube is returned for the following conditions: 1. The radius varies wtih lead time. 2. The cube contains multiple realizations.""" cube = set_up_cube( zero_point_indices=((1, 0, 7, 7), (1, 1, 7, 7), (1, 2, 7, 7)), num_time_points=3, num_realization_points=2, ) time_points = cube.coord("time").points lead_times = [2, 3, 4] radii = [5600, 7600, 9500] cube = add_forecast_reference_time_and_forecast_period( cube, time_point=time_points, fp_point=lead_times) expected = np.ones_like(cube.data) expected[1, 0, 6:9, 6:9] = ( [0.91666667, 0.875, 0.91666667], [0.875, 0.83333333, 0.875], [0.91666667, 0.875, 0.91666667], ) expected[1, 1, 5:10, 5:10] = SINGLE_POINT_RANGE_3_CENTROID expected[1, 2, 4:11, 4:11] = ( [1, 0.9925, 0.985, 0.9825, 0.985, 0.9925, 1], [0.9925, 0.98, 0.9725, 0.97, 0.9725, 0.98, 0.9925], [0.985, 0.9725, 0.965, 0.9625, 0.965, 0.9725, 0.985], [0.9825, 0.97, 0.9625, 0.96, 0.9625, 0.97, 0.9825], [0.985, 0.9725, 0.965, 0.9625, 0.965, 0.9725, 0.985], [0.9925, 0.98, 0.9725, 0.97, 0.9725, 0.98, 0.9925], [1, 0.9925, 0.985, 0.9825, 0.985, 0.9925, 1], ) neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, lead_times) result = plugin(cube) self.assertIsInstance(result, Cube) self.assertArrayEqual(result[0].data, expected[0]) self.assertArrayAlmostEqual(result[1].data, expected[1])
def test_neighbourhood_method_exists(self): """Test that no exception is raised if the requested neighbourhood method exists.""" neighbourhood_method = "circular" radii = 10000 NBHood(neighbourhood_method, radii)
def test_basic(self): """Test that the plugin returns an iris.cube.Cube.""" neighbourhood_method = CircularNeighbourhood() result = NBHood(neighbourhood_method, self.RADIUS).process(self.cube) self.assertIsInstance(result, Cube)
def test_not_callable(self): """Test that the __repr__ returns the expected string.""" result = str(NBHood("circular", 10000)) msg = ('<BaseNeighbourhoodProcessing: neighbourhood_method: ' 'circular; radii: 10000.0; lead_times: None; ens_factor: 1.0>') self.assertEqual(result, msg)
def test_basic(self): """Test that the plugin returns an iris.cube.Cube.""" cube = set_up_cube() neighbourhood_method = "circular" result = NBHood(neighbourhood_method, self.RADIUS).process(cube) self.assertIsInstance(result, Cube)
def test_single_point_nan(self): """Test behaviour for a single NaN grid cell.""" self.cube.data[6][7] = np.NAN msg = "NaN detected in input cube data" with self.assertRaisesRegex(ValueError, msg): NBHood(self.RADIUS)(self.cube)