class Test_process(IrisTest): """Test the process method.""" def setUp(self): """Set up data for testing.""" self.plugin = GenerateTopographicZoneWeights() orography_data = np.array([[10.0, 25.0], [75.0, 100.0]]) self.orography = set_up_orography_cube(orography_data) landmask_data = np.array([[0, 1], [1, 1]], dtype=np.float32) landmask = self.orography.copy(data=landmask_data) landmask.rename("land_binary_mask") landmask.units = Unit("1") self.landmask = landmask self.thresholds_dict = {"bounds": [[0, 50], [50, 200]], "units": "m"} def test_basic(self): """Test that the output is a cube with the expected format.""" result = self.plugin.process(self.orography, self.thresholds_dict, self.landmask) self.assertIsInstance(result, iris.cube.Cube) self.assertEqual(result.name(), "topographic_zone_weights") self.assertEqual(result.units, Unit("1")) self.assertTrue(result.coord("topographic_zone")) self.assertEqual(result.coord("topographic_zone").units, Unit("m")) def test_invalid_orography(self): """Test that the appropriate exception is raised if the orography has more than two dimensions.""" orography_data = np.array([[[0.0, 25.0], [75.0, 100.0]]]) orography = set_up_orography_cube(orography_data) msg = "The input orography cube should be two-dimensional" with self.assertRaisesRegex(InvalidCubeError, msg): self.plugin.process(orography, self.thresholds_dict, self.landmask) def test_data(self): """Test that the result data and mask is as expected.""" expected_weights_data = np.array( [[[1e20, 1.0], [0.33, 0.17]], [[1e20, 0.0], [0.67, 0.83]]], dtype=np.float32) expected_weights_mask = np.array([[[True, False], [False, False]], [[True, False], [False, False]]]) result = self.plugin.process(self.orography, self.thresholds_dict, self.landmask) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data.data, expected_weights_data, decimal=2) self.assertArrayAlmostEqual(result.data.mask, expected_weights_mask) def test_data_no_mask(self): """Test that the result data is as expected, when none of the points are masked.""" expected_weights_data = np.array( [[[1.0, 1.0], [0.33, 0.17]], [[0.0, 0.0], [0.67, 0.83]]], dtype=np.float32) landmask_data = np.array([[1, 1], [1, 1]]) landmask = self.landmask.copy(landmask_data) result = self.plugin.process(self.orography, self.thresholds_dict, landmask) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data, expected_weights_data, decimal=2) def test_data_no_mask_input(self): """Test that the result data is as expected, when no landsea mask is input.""" expected_weights_data = np.array( [[[1.0, 1.0], [0.33, 0.17]], [[0.0, 0.0], [0.67, 0.83]]], dtype=np.float32) result = self.plugin.process(self.orography, self.thresholds_dict) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data, expected_weights_data, decimal=2) def test_data_no_mask_input_metatdata(self): """Test that the result metadata is as expected, when no landsea mask is input.""" result = self.plugin.process(self.orography, self.thresholds_dict) self.assertIsInstance(result, iris.cube.Cube) self.assertEqual( result.attributes["topographic_zones_include_seapoints"], "True") def test_data_no_mask_three_bands(self): """Test that the result data is as expected, when none of the points are masked and there are three bands defined.""" orography_data = np.array([[10.0, 40.0, 45.0], [70.0, 80.0, 95.0], [115.0, 135.0, 145.0]]) orography = set_up_orography_cube(orography_data) landmask_data = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]) landmask = orography.copy(data=landmask_data) landmask.rename("land_binary_mask") landmask.units = Unit("1") thresholds_dict = { "bounds": [[0, 50], [50, 100], [100, 150]], "units": "m" } expected_weights_data = np.array([ [[1.0, 0.7, 0.6], [0.1, 0.0, 0.0], [0.0, 0.0, 0.0]], [[0.0, 0.3, 0.4], [0.9, 0.9, 0.6], [0.2, 0.0, 0.0]], [[0.0, 0.0, 0.0], [0.0, 0.1, 0.4], [0.8, 1.0, 1.0]], ]) result = self.plugin.process(orography, thresholds_dict, landmask) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data, expected_weights_data, decimal=2) def test_different_band_units(self): """Test for if the thresholds are specified in a different unit to the orography. The thresholds are converted to match the units of the orography.""" expected_weights_data = np.array( [[[1e20, 1.0], [0.333, 0.167]], [[1e20, 0.0], [0.67, 0.83]]], dtype=np.float32, ) expected_weights_mask = np.array([[[True, False], [False, False]], [[True, False], [False, False]]]) thresholds_dict = {"bounds": [[0, 0.05], [0.05, 0.2]], "units": "km"} result = self.plugin.process(self.orography, thresholds_dict, self.landmask) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data.data, expected_weights_data, decimal=2) self.assertArrayAlmostEqual(result.data.mask, expected_weights_mask) def test_one_band_with_orography_in_band(self): """Test that if only one band is specified, the results are as expected.""" expected_weights_data = np.array([[1e20, 1.0], [1.0, 1.0]], dtype=np.float32) expected_weights_mask = np.array([[True, False], [False, False]]) orography_data = np.array([[10.0, 20.0], [30.0, 40.0]], dtype=np.float32) orography = self.orography.copy(data=orography_data) thresholds_dict = {"bounds": [[0, 50]], "units": "m"} result = self.plugin.process(orography, thresholds_dict, self.landmask) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data.data, expected_weights_data, decimal=2) self.assertArrayAlmostEqual(result.data.mask, expected_weights_mask) @ManageWarnings(record=True) def test_warning_if_orography_above_bands(self, warning_list=None): """Test that a warning is raised if the orography is greater than the maximum band.""" orography_data = np.array([[60.0, 70.0], [80.0, 90.0]]) orography = self.orography.copy(data=orography_data) thresholds_dict = {"bounds": [[0, 50]], "units": "m"} msg = "The maximum orography is greater than the uppermost band" self.plugin.process(orography, thresholds_dict, self.landmask) self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue(any(msg in str(item) for item in warning_list)) @ManageWarnings(record=True) def test_warning_if_orography_below_bands(self, warning_list=None): """Test that a warning is raised if the orography is lower than the minimum band.""" orography_data = np.array([[60.0, 70.0], [80.0, 90.0]]) orography = self.orography.copy(data=orography_data) thresholds_dict = {"bounds": [[100, 150]], "units": "m"} msg = "The minimum orography is lower than the lowest band" self.plugin.process(orography, thresholds_dict, self.landmask) self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue(any(msg in str(item) for item in warning_list))
class Test_process(IrisTest): """Test the process method.""" def setUp(self): """Set up data for testing.""" self.plugin = GenerateTopographicZoneWeights() orography_data = np.array([[[[10., 25.], [75., 100.]]]]) orography = set_up_cube(orography_data, "altitude", "m", realizations=np.array([0]), y_dimension_length=2, x_dimension_length=2) orography = orography[0, 0, ...] orography.remove_coord("realization") orography.remove_coord("time") self.orography = orography landmask_data = np.array([[0, 1], [1, 1]]) landmask = orography.copy(data=landmask_data) landmask.rename("land_binary_mask") landmask.units = Unit("1") self.landmask = landmask self.thresholds_dict = { 'land': { 'bounds': [[0, 50], [50, 200]], 'units': 'm' } } def test_basic(self): """Test that the output is a cube with the expected format.""" result = self.plugin.process(self.orography, self.landmask, self.thresholds_dict) self.assertIsInstance(result, iris.cube.Cube) self.assertEqual(result.name(), "topographic_zone_weights") self.assertEqual(result.units, Unit("1")) self.assertTrue(result.coord("topographic_zone")) self.assertEqual(result.coord("topographic_zone").units, Unit("m")) def test_invalid_orography(self): """Test that the appropriate exception is raised if the orography has more than two dimensions.""" orography_data = np.array([[[[0., 25.], [75., 100.]]]]) orography = set_up_cube(orography_data, "altitude", "m", realizations=np.array([0]), y_dimension_length=2, x_dimension_length=2) msg = "The input orography cube should be two-dimensional" with self.assertRaisesRegexp(InvalidCubeError, msg): self.plugin.process(orography, self.landmask, self.thresholds_dict) def test_invalid_bands(self): """Test for if the thresholds_dict has an invalid key.""" thresholds_dict = { 'invalid': { 'bounds': [[0, 50], [50, 200]], 'units': 'm' } } msg = "'land'" with self.assertRaisesRegexp(KeyError, msg): self.plugin.process(self.orography, self.landmask, thresholds_dict) def test_data(self): """Test that the result data and mask is as expected.""" expected_weights_data = np.array([[[1e20, 1.0], [0.33, 0.17]], [[1e20, 0.0], [0.67, 0.83]]]) expected_weights_mask = np.array([[[True, False], [False, False]], [[True, False], [False, False]]]) result = self.plugin.process(self.orography, self.landmask, self.thresholds_dict) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data.data, expected_weights_data, decimal=2) self.assertArrayAlmostEqual(result.data.mask, expected_weights_mask) def test_data_no_mask(self): """Test that the result data is as expected, when none of the points are masked.""" expected_weights_data = np.array([[[1.0, 1.0], [0.33, 0.17]], [[0.0, 0.0], [0.67, 0.83]]]) landmask_data = np.array([[1, 1], [1, 1]]) landmask = self.landmask.copy(landmask_data) result = self.plugin.process(self.orography, landmask, self.thresholds_dict) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data, expected_weights_data, decimal=2) def test_data_no_mask_three_bands(self): """Test that the result data is as expected, when none of the points are masked and there are three bands defined.""" orography_data = np.array([[[[10., 40., 45.], [70., 80., 95.], [115., 135., 145.]]]]) orography = set_up_cube(orography_data, "altitude", "m", realizations=np.array([0]), y_dimension_length=3, x_dimension_length=3) orography = orography[0, 0, ...] orography.remove_coord("realization") orography.remove_coord("time") landmask_data = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]) landmask = orography.copy(data=landmask_data) landmask.rename("land_binary_mask") landmask.units = Unit("1") thresholds_dict = { 'land': { 'bounds': [[0, 50], [50, 100], [100, 150]], 'units': 'm' } } expected_weights_data = np.array([[[1.0, 0.7, 0.6], [0.1, 0.0, 0.0], [0.0, 0.0, 0.0]], [[0.0, 0.3, 0.4], [0.9, 0.9, 0.6], [0.2, 0.0, 0.0]], [[0.0, 0.0, 0.0], [0.0, 0.1, 0.4], [0.8, 1.0, 1.0]]]) result = self.plugin.process(orography, landmask, thresholds_dict) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data, expected_weights_data, decimal=2) def test_different_band_units(self): """Test for if the thresholds are specified in a different unit to the orography. The thresholds are converted to match the units of the orography.""" expected_weights_data = np.array([[[1e20, 1.0], [0.33, 0.17]], [[1e20, 0.0], [0.67, 0.83]]]) expected_weights_mask = np.array([[[True, False], [False, False]], [[True, False], [False, False]]]) thresholds_dict = { 'land': { 'bounds': [[0, 0.05], [0.05, 0.2]], 'units': 'km' } } result = self.plugin.process(self.orography, self.landmask, thresholds_dict) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data.data, expected_weights_data, decimal=2) self.assertArrayAlmostEqual(result.data.mask, expected_weights_mask) def test_one_band_with_orography_in_band(self): """Test that if only one band is specified, the results are as expected.""" expected_weights_data = np.array([[1e20, 1.0], [1.0, 1.0]]) expected_weights_mask = np.array([[True, False], [False, False]]) orography_data = np.array([[10., 20.], [30., 40.]]) orography = self.orography.copy(data=orography_data) thresholds_dict = {'land': {'bounds': [[0, 50]], 'units': 'm'}} result = self.plugin.process(orography, self.landmask, thresholds_dict) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data.data, expected_weights_data, decimal=2) self.assertArrayAlmostEqual(result.data.mask, expected_weights_mask) def test_warning_if_orography_above_bands(self): """Test that a warning is raised if the orography is greater than the maximum band.""" orography_data = np.array([[60., 70.], [80., 90.]]) orography = self.orography.copy(data=orography_data) thresholds_dict = {'land': {'bounds': [[0, 50]], 'units': 'm'}} msg = "The maximum orography is greater than the uppermost band" with warnings.catch_warnings(record=True) as warning_list: self.plugin.process(orography, self.landmask, thresholds_dict) self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue(any(msg in str(item) for item in warning_list)) def test_warning_if_orography_below_bands(self): """Test that a warning is raised if the orography is lower than the minimum band.""" orography_data = np.array([[60., 70.], [80., 90.]]) orography = self.orography.copy(data=orography_data) thresholds_dict = {'land': {'bounds': [[100, 150]], 'units': 'm'}} msg = "The minimum orography is lower than the lowest band" with warnings.catch_warnings(record=True) as warning_list: self.plugin.process(orography, self.landmask, thresholds_dict) self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue(any(msg in str(item) for item in warning_list))