def test_landsea_mask_in_weights(self): """Test that the final result from collapsing the nbhood retains the mask from weights input.""" self.nbhooded_cube.data[0, 0:2, 0] = np.nan self.nbhooded_cube.data[2, 3:, 4] = np.nan mask = np.array([[[1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1]], [[1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1]], [[1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1]]]) self.weights_cube.data = np.ma.masked_array(self.weights_cube.data, mask=mask) plugin = CollapseMaskedNeighbourhoodCoordinate( "topographic_zone", weights=self.weights_cube) result = plugin.process(self.nbhooded_cube) expected_result = np.array([[0.0, 0.0, 0.0, 0.2, 0.2], [0.0, 0.0, 0.2, 0.2, 0.2], [0.0, 0.19, 0.2, 0.2, 0.2], [0.0, 0.2, 0.2, 0.19, 0.2], [0.0, 0.0, 0.0, 0.0, 0.0]]) expected_mask = np.array([[True, True, True, False, False], [True, True, False, False, False], [True, False, False, False, False], [True, False, False, False, False], [True, True, True, True, True]]) self.assertArrayAlmostEqual(expected_result, result.data.data) self.assertArrayAlmostEqual(expected_mask, result.data.mask) self.assertEqual(expected_mask.dtype, bool) self.assertIsInstance(expected_result, np.ndarray)
class Test_process(IrisTest): """Test the process method of CollapseMaskedNeighbourhoodCoordinate""" def setUp(self): """Set up a weights cube and default plugin to use in unittests.""" weights_data = np.array([[[0.8, 0.7, 0.0, 0.0, 0.0], [0.7, 0.3, 0.0, 0.0, 0.0], [0.3, 0.1, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0]], [[0.2, 0.3, 1.0, 1.0, 1.0], [0.3, 0.7, 1.0, 1.0, 1.0], [0.7, 0.9, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 0.9, 0.5], [1.0, 1.0, 1.0, 0.6, 0.2]], [[0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.1, 0.5], [0.0, 0.0, 0.0, 0.4, 0.8]]]) topographic_zone_points = [50, 150, 250] topographic_zone_bounds = [[0, 100], [100, 200], [200, 300]] weights_cubes = iris.cube.CubeList([]) for data, point, bounds in zip(weights_data, topographic_zone_points, topographic_zone_bounds): weights_cubes.append( set_up_topographic_zone_cube(data, point, bounds, num_grid_points=5)) self.weights_cube = weights_cubes.merge_cube() nbhood_data = np.ones((3, 5, 5)) nbhood_data[0] = nbhood_data[0] * 0.1 nbhood_data[1] = nbhood_data[1] * 0.2 nbhood_data[2] = nbhood_data[2] * 0.1 self.nbhooded_cube = self.weights_cube.copy(nbhood_data) self.plugin = CollapseMaskedNeighbourhoodCoordinate( "topographic_zone", self.weights_cube) def test_basic(self): """Test that a cube is returned from the process method""" result = self.plugin.process(self.nbhooded_cube) self.assertIsInstance(result, iris.cube.Cube) def test_no_NaNs_in_nbhooded_cube(self): """No NaNs in the neighbourhood cube, so no renormalization is needed. The neighbourhood data has all values of 0.1 for the top and bottom bands and 0.2 for points in the middle band. The weights are used to calculate the weighted average amongst the bands.""" expected_result = np.array([[0.12, 0.13, 0.2, 0.2, 0.2], [0.13, 0.17, 0.2, 0.2, 0.2], [0.17, 0.19, 0.2, 0.2, 0.2], [0.2, 0.2, 0.2, 0.19, 0.15], [0.2, 0.2, 0.2, 0.16, 0.12]]) result = self.plugin.process(self.nbhooded_cube) self.assertArrayAlmostEqual(expected_result, result.data) def test_some_NaNs_in_nbhooded_cube(self): """Some NaNs in the neighbourhood cube, so renormalizing is needed. The neighbourhood data has all values of 0.1 for the top and bottom bands and 0.2 for points in the middle band. The weights are used to calculate the weighted average amongst the bands. This is the same test as above, but a few of the weights are modified where there are NaNs in the neighbourhood data, giving slightly different results.""" self.nbhooded_cube.data[0, 0:2, 0] = np.nan self.nbhooded_cube.data[2, 3:, 4] = np.nan expected_result = np.array([[0.2, 0.13, 0.2, 0.2, 0.2], [0.2, 0.17, 0.2, 0.2, 0.2], [0.17, 0.19, 0.2, 0.2, 0.2], [0.2, 0.2, 0.2, 0.19, 0.2], [0.2, 0.2, 0.2, 0.16, 0.2]]) result = self.plugin.process(self.nbhooded_cube) self.assertArrayAlmostEqual(expected_result, result.data) def test_landsea_mask_in_weights(self): """Test that the final result from collapsing the nbhood retains the mask from weights input.""" self.nbhooded_cube.data[0, 0:2, 0] = np.nan self.nbhooded_cube.data[2, 3:, 4] = np.nan mask = np.array([[[1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1]], [[1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1]], [[1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1]]]) self.weights_cube.data = np.ma.masked_array(self.weights_cube.data, mask=mask) plugin = CollapseMaskedNeighbourhoodCoordinate( "topographic_zone", weights=self.weights_cube) result = plugin.process(self.nbhooded_cube) expected_result = np.array([[0.0, 0.0, 0.0, 0.2, 0.2], [0.0, 0.0, 0.2, 0.2, 0.2], [0.0, 0.19, 0.2, 0.2, 0.2], [0.0, 0.2, 0.2, 0.19, 0.2], [0.0, 0.0, 0.0, 0.0, 0.0]]) expected_mask = np.array([[True, True, True, False, False], [True, True, False, False, False], [True, False, False, False, False], [True, False, False, False, False], [True, True, True, True, True]]) self.assertArrayAlmostEqual(expected_result, result.data.data) self.assertArrayAlmostEqual(expected_mask, result.data.mask) self.assertEqual(expected_mask.dtype, bool) self.assertIsInstance(expected_result, np.ndarray) def test_multidimensional_neighbourhood_input(self): """Test that we can collapse the right dimension when there are additional leading dimensions like threshold.""" nbhooded_cube = add_dimensions_to_cube(self.nbhooded_cube, {"threshold": 3}) expected_result = np.array([[[0.12, 0.13, 0.2, 0.2, 0.2], [0.13, 0.17, 0.2, 0.2, 0.2], [0.17, 0.19, 0.2, 0.2, 0.2], [0.2, 0.2, 0.2, 0.19, 0.15], [0.2, 0.2, 0.2, 0.16, 0.12]], [[0.12, 0.13, 0.2, 0.2, 0.2], [0.13, 0.17, 0.2, 0.2, 0.2], [0.17, 0.19, 0.2, 0.2, 0.2], [0.2, 0.2, 0.2, 0.19, 0.15], [0.2, 0.2, 0.2, 0.16, 0.12]], [[0.12, 0.13, 0.2, 0.2, 0.2], [0.13, 0.17, 0.2, 0.2, 0.2], [0.17, 0.19, 0.2, 0.2, 0.2], [0.2, 0.2, 0.2, 0.19, 0.15], [0.2, 0.2, 0.2, 0.16, 0.12]]]) result = self.plugin.process(nbhooded_cube) self.assertArrayAlmostEqual(expected_result, result.data) def test_preserve_dimensions_input(self): """Test that the dimensions on the output cube are the same as the input cube, apart from the collapsed dimension. Add threshold and realization coordinates and check they are in the right place after collapsing the topographic_zone coordinate.""" nbhood_cube = self.weights_cube.copy() nbhood_cube.remove_coord("realization") nbhood_cube = add_dimensions_to_cube(nbhood_cube, { "threshold": 3, "realization": 4 }) result = self.plugin.process(nbhood_cube) expected_dims = [ coord for coord in nbhood_cube.dim_coords if coord.long_name is not "topographic_zone" ] self.assertEqual(result.dim_coords, tuple(expected_dims)) self.assertEqual(result.coord_dims("realization"), (0, )) self.assertEqual(result.coord_dims("threshold"), (1, )) self.assertEqual(result.coord_dims("projection_y_coordinate"), (2, )) self.assertEqual(result.coord_dims("projection_x_coordinate"), (3, )) def test_preserve_dimensions_with_single_point(self): """Test that the dimensions on the output cube are the same as the input cube, appart from the collapsed dimension. Add threshold and realization coordinates and check they are in the right place after collapsing the topographic_zone coordinate. Check that a dimension coordinate with a single point is preserved and not demoted to a scalar coordinate.""" nbhood_cube = self.weights_cube.copy() nbhood_cube.remove_coord("realization") nbhood_cube = add_dimensions_to_cube(nbhood_cube, { "threshold": 3, "realization": 1 }) result = self.plugin.process(nbhood_cube) expected_dims = [ coord for coord in nbhood_cube.dim_coords if coord.long_name is not "topographic_zone" ] self.assertEqual(result.dim_coords, tuple(expected_dims)) self.assertEqual(result.coord_dims("realization"), (0, )) self.assertEqual(result.coord_dims("threshold"), (1, )) self.assertEqual(result.coord_dims("projection_y_coordinate"), (2, )) self.assertEqual(result.coord_dims("projection_x_coordinate"), (3, ))