def test_basic(self): """Test that the __repr__ returns the expected string.""" result = str(NBHood("circular", 10000)) msg = ('<BaseNeighbourhoodProcessing: neighbourhood_method: ' '<CircularNeighbourhood: weighted_mode: True>; ' 'radii: 10000.0; lead_times: None; ens_factor: 1.0>') self.assertEqual(result, msg)
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.""" expected = np.ones_like(self.multi_time_cube.data) expected[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, 5:10, 5:10] = SINGLE_POINT_RANGE_3_CENTROID expected[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], ) fp_points = [2, 3, 4] radii = [5600, 9500] lead_times = [2, 4] neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, lead_times) result = plugin(self.multi_time_cube) 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) cube = iris.util.squeeze(cube) mask_cube = cube.copy() mask_cube.data = np.array([ [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0, 1.0, 0.0, 1.0], [1.0, 0.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0, 1.0, 0.0, 0.0], ]) radius = 2000 neighbourhood_method = SquareNeighbourhood() result = NBHood(neighbourhood_method, radius)(cube, mask_cube) 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], ]) data = np.ones((5, 5), dtype=np.float32) data[2, 2] = 0 cube = set_up_variable_cube( data, spatial_grid="equalarea", ) mask_cube = cube.copy() mask_cube.data = np.array([ [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0, 1.0, 0.0, 1.0], [1.0, 0.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0, 1.0, 0.0, 0.0], ]) radius = 2000 neighbourhood_method = SquareNeighbourhood() result = NBHood(neighbourhood_method, radius)(cube, mask_cube) 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 and that a cube is returned. """ expected = np.ones_like(self.multi_time_cube.data) expected[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, 5:10, 5:10] = SINGLE_POINT_RANGE_3_CENTROID expected[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], ) radii = [5600, 7600, 9500] lead_times = [2, 3, 4] neighbourhood_method = CircularNeighbourhood() plugin = NBHood(neighbourhood_method, radii, lead_times) result = plugin(self.multi_time_cube) self.assertArrayAlmostEqual(result.data, expected) self.assertIsInstance(result, Cube)
def test_single_point_nan(self): """Test behaviour for a single NaN grid cell.""" self.cube.data[0][0][6][7] = np.NAN msg = "NaN detected in input cube data" with self.assertRaisesRegexp(ValueError, msg): neighbourhood_method = CircularNeighbourhood NBHood(neighbourhood_method, self.RADIUS).process(self.cube)
def test_use_mask_cube_occurrences_not_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 not mask out the occurrences.""" expected = np.array( [[1., 1., 1., 1., 1.], [1., 0.88888889, 0.88888889, 0.88888889, 1.], [1., 0.88888889, 0.88888889, 0.88888889, 1.], [1., 0.88888889, 0.88888889, 0.88888889, 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., 1., 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_default_percentiles(self): """Test that the circular neighbourhood processing is successful, if the default percentiles are used.""" neighbourhood_method = 'circular' radii = 4000 result = NBHood(neighbourhood_method, radii).process(self.cube) self.assertIsInstance(result, Cube)
def test_neighbourhood_method_exists(self): """Test that no exception is raised if the requested neighbourhood method exists.""" neighbourhood_method = 'circular' radii = 10000 result = NBHood(neighbourhood_method, radii) msg = '<CircularNeighbourhood: weighted_mode: True>' self.assertEqual(str(result.neighbourhood_method), msg)
def test_define_percentiles(self): """Test that the circular neighbourhood processing is successful, if the percentiles are passed in as a keyword argument.""" neighbourhood_method = "circular" radii = 4000 percentiles = (0, 25, 50, 75, 100) result = NBHood(neighbourhood_method, radii, percentiles=percentiles)(self.cube) self.assertIsInstance(result, Cube)
def test_callable(self): """Test that the __repr__ returns the expected string.""" result = str(NBHood(CircularNeighbourhood(), 10000)) msg = ("<BaseNeighbourhoodProcessing: neighbourhood_method: " "<CircularNeighbourhood: weighted_mode: True, " "sum_or_fraction: fraction>; " "radii: 10000.0; lead_times: None>") self.assertEqual(result, msg)
def test_realizations_and_source_realizations_fails(self): """Raises error if realizations and source realizations both set.""" self.cube.attributes.update({'source_realizations': [0, 1, 2, 3]}) msg = ('Realizations and attribute source_realizations should not' ' both be set') with self.assertRaisesRegexp(ValueError, msg): neighbourhood_method = CircularNeighbourhood() NBHood(neighbourhood_method, self.RADIUS).process(self.cube)
def test_neighbourhood_method_does_not_exist(self): """Test that desired error message is raised, if the neighbourhood method does not exist.""" neighbourhood_method = 'nonsense' radii = 10000 msg = 'The neighbourhood_method requested: ' with self.assertRaisesRegex(KeyError, msg): NBHood(neighbourhood_method, radii)
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_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>" ) self.assertEqual(result, msg)
def test_basic(self): """Test that the __repr__ returns the expected string.""" result = str(NBHood("circular", 10000)) msg = ('<BaseNeighbourhoodProcessing: neighbourhood_method: ' '<GeneratePercentilesFromACircularNeighbourhood: percentiles: ' '(0, 5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80, 90, 95, 100)>; ' 'radii: 10000.0; lead_times: None>') self.assertEqual(result, msg)
def test_interpolation(self): """Test that interpolation is working as expected in _find_radii.""" fp_points = np.array([2, 3, 4]) radii = [10000, 30000] lead_times = [2, 4] plugin = NBHood(radii=radii, lead_times=lead_times) result = plugin._find_radii(cube_lead_times=fp_points) expected_result = np.array([10000.0, 20000.0, 30000.0]) self.assertArrayAlmostEqual(result, expected_result)
def test_neighbourhood_method_exists(self): """Test that no exception is raised if the requested neighbourhood method exists.""" neighbourhood_method = "circular" radii = 10000 result = NBHood(neighbourhood_method, radii) msg = ("<CircularNeighbourhood: weighted_mode: True, " "sum_or_fraction: fraction>") self.assertEqual(str(result.neighbourhood_method), msg)
def test_radii_varying_with_lead_time_mismatch(self): """ Test that the desired error message is raised, if there is a mismatch between the number of radii and the number of lead times. """ radii = [10000, 20000, 30000] lead_times = [2, 3] msg = "There is a mismatch in the number of radii" with self.assertRaisesRegex(ValueError, msg): NBHood(radii, lead_times=lead_times)
def test_correct_radii_set(self): """Test that the correct neighbourhood radius is set when interpolation is required""" radii = [5600, 9500] lead_times = [3, 5] expected_radius = 7550 plugin = NBHood(radii, lead_times) plugin(self.cube) self.assertEqual(plugin.radius, expected_radius)
def test_basic_array_cube_lead_times_an_array(self): """Test _find_radii returns an array with the correct values.""" fp_points = np.array([2, 3, 4]) radii = [10000, 20000, 30000] lead_times = [1, 3, 5] plugin = NBHood(radii, lead_times=lead_times) result = plugin._find_radii(cube_lead_times=fp_points) expected_result = np.array([15000.0, 20000.0, 25000.0]) self.assertIsInstance(result, np.ndarray) self.assertArrayAlmostEqual(result, expected_result)
def test_neighbourhood_method_does_not_exist(self): """ Test that desired error message is raised, if the neighbourhood method does not exist. """ neighbourhood_method = 'nonsense' radii = 10000 msg = "is not valid as a neighbourhood_method" with self.assertRaisesRegexp(ValueError, msg): NBHood(neighbourhood_method, radii).process(self.cube)
def test_basic_float_cube_lead_times_is_none(self): """Test _find_radii returns an unaltered radius if the lead times are none, and this radius is a float.""" neighbourhood_method = CircularNeighbourhood() radius = 6300 plugin = NBHood(neighbourhood_method, radius) result = plugin._find_radii(cube_lead_times=None) expected_result = 6300.0 self.assertIsInstance(result, float) self.assertAlmostEqual(result, expected_result)
def test_basic_float_cube_lead_times_is_none(self): """Test _find_radii returns a float with the correct value.""" neighbourhood_method = CircularNeighbourhood() ens_factor = 0.8 num_ens = 2.0 radius = 6300 plugin = NBHood(neighbourhood_method, radius, ens_factor=ens_factor) result = plugin._find_radii(num_ens) expected_result = 3563.8181771801998 self.assertIsInstance(result, float) self.assertAlmostEquals(result, expected_result)
def test_basic_returns_float(self): """Test returns float.""" neighbourhood_method = CircularNeighbourhood() radii = 20.0 ens_factor = 1.0 num_ens = 3.0 width = 20.0 result = NBHood(neighbourhood_method, radii, ens_factor=ens_factor).adjust_nsize_for_ens( num_ens, width) self.assertIsInstance(result, float)
def test_neighbourhood_method_exists(self): """ Test that no exception is raised if the requested neighbourhood method exists. """ neighbourhood_method = 'circular' radii = 10000 result = NBHood(neighbourhood_method, radii) msg = ('<GeneratePercentilesFromACircularNeighbourhood: percentiles: ' '(0, 5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80, 90, 95, 100)>') self.assertEqual(str(result.neighbourhood_method), msg)
def test_no_realizations(self): """Test when the array has no realization coord.""" cube = set_up_cube_with_no_realizations() radii = 5600 neighbourhood_method = CircularNeighbourhood() result = NBHood(neighbourhood_method, radii).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_returns_adjusted_values(self): """Test returns the correct values.""" expected = 9.2376043070399998 neighbourhood_method = CircularNeighbourhood() radii = 20.0 ens_factor = 0.8 num_ens = 3.0 width = 20.0 result = NBHood(neighbourhood_method, radii, ens_factor=ens_factor).adjust_nsize_for_ens( num_ens, width) self.assertAlmostEqual(result, expected)
def test_returns_unchanged_for_ens1(self): """Test returns unchanged value when num_ens = 1.0.""" expected = 20.0 neighbourhood_method = CircularNeighbourhood() radii = 20.0 ens_factor = 0.8 num_ens = 1.0 width = 20.0 result = NBHood(neighbourhood_method, radii, ens_factor=ens_factor).adjust_nsize_for_ens( num_ens, width) self.assertAlmostEqual(result, expected)
def test_multiple_realizations(self): """Test when the cube has a realization dimension.""" cube = set_up_cube(num_realization_points=4) radii = 5600 neighbourhood_method = CircularNeighbourhood() result = NBHood(neighbourhood_method, radii).process(cube) self.assertIsInstance(result, Cube) expected = np.ones([4, 1, 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)