diff --git a/docs/iris/src/whatsnew/contributions_3.0.0/bugfix_2019-Nov-19_cell_measure_copy_loss.txt b/docs/iris/src/whatsnew/contributions_3.0.0/bugfix_2019-Nov-19_cell_measure_copy_loss.txt new file mode 100644 index 0000000000..3a0bbfaf56 --- /dev/null +++ b/docs/iris/src/whatsnew/contributions_3.0.0/bugfix_2019-Nov-19_cell_measure_copy_loss.txt @@ -0,0 +1,2 @@ +* Copying a cube would previously ignore any attached class:`iris.coords.CellMeasure`. + These are now copied over. \ No newline at end of file diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py index 1932a4dc9d..0544cd8cb4 100644 --- a/lib/iris/analysis/__init__.py +++ b/lib/iris/analysis/__init__.py @@ -186,7 +186,7 @@ def matches_any(self, predicate): return any(self.matches(predicate)) -def coord_comparison(*cubes): +def coord_comparison(*cubes, object_get=None): """ Convenience function to help compare coordinates on one or more cubes by their metadata. @@ -240,7 +240,12 @@ def coord_comparison(*cubes): print('All equal coordinates: ', result['equal']) """ - all_coords = [cube.coords() for cube in cubes] + if object_get is None: + from iris.cube import Cube + + object_get = Cube.coords + + all_coords = [object_get(cube) for cube in cubes] grouped_coords = [] # set of coordinates id()s of coordinates which have been processed @@ -334,7 +339,7 @@ def diff_shape_fn(cube, coord): # dimension on their respective cubes # (None -> group describes a different dimension) def diff_data_dim_fn(cube, coord): - return cube.coord_dims(coord) != first_cube.coord_dims(first_coord) + return coord.cube_dims(cube) != first_coord.cube_dims(first_cube) if coord_group.matches_any(diff_data_dim_fn): different_data_dimension.add(coord_group) @@ -342,7 +347,7 @@ def diff_data_dim_fn(cube, coord): # get all coordinate groups which don't describe a dimension # (None -> doesn't describe a dimension) def no_data_dim_fn(cube, coord): - return cube.coord_dims(coord) == () + return coord.cube_dims(cube) == () if coord_group.matches_all(no_data_dim_fn): no_data_dimension.add(coord_group) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 55ed96441b..3ff77fa1ad 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -3522,6 +3522,12 @@ def _deepcopy(self, memo, data=None): new_dim_coords_and_dims = deepcopy(self._dim_coords_and_dims, memo) new_aux_coords_and_dims = deepcopy(self._aux_coords_and_dims, memo) + new_cell_measures_and_dims = deepcopy( + self._cell_measures_and_dims, memo + ) + new_ancillary_variables_and_dims = deepcopy( + self._ancillary_variables_and_dims, memo + ) # Record a mapping from old coordinate IDs to new coordinates, # for subsequent use in creating updated aux_factories. @@ -3541,6 +3547,8 @@ def _deepcopy(self, memo, data=None): dm.core_data(), dim_coords_and_dims=new_dim_coords_and_dims, aux_coords_and_dims=new_aux_coords_and_dims, + cell_measures_and_dims=new_cell_measures_and_dims, + ancillary_variables_and_dims=new_ancillary_variables_and_dims, ) new_cube.metadata = deepcopy(self.metadata, memo) @@ -3567,13 +3575,23 @@ def __eq__(self, other): ) if result: - result = set(self._cell_measures_and_dims) == set( - other._cell_measures_and_dims + coord_comparison = iris.analysis.coord_comparison( + self, other, object_get=Cube.cell_measures, + ) + # if there are any cell measures which are not equal + result = not ( + coord_comparison["not_equal"] + or coord_comparison["non_equal_data_dimension"] ) if result: - result = set(self._ancillary_variables_and_dims) == set( - other._ancillary_variables_and_dims + coord_comparison = iris.analysis.coord_comparison( + self, other, object_get=Cube.ancillary_variables, + ) + # if there are any ancillary variables which are not equal + result = not ( + coord_comparison["not_equal"] + or coord_comparison["non_equal_data_dimension"] ) # Having checked everything else, check approximate data equality. diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index df9d193cad..c25b330491 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -1710,6 +1710,18 @@ def test(self): cube = stock.simple_3d() self._check_copy(cube, cube.copy()) + def test_copy_ancillary_variables(self): + cube = stock.simple_3d() + avr = AncillaryVariable([2, 3], long_name="foo") + cube.add_ancillary_variable(avr, 0) + self._check_copy(cube, cube.copy()) + + def test_copy_cell_measures(self): + cube = stock.simple_3d() + cms = CellMeasure([2, 3], long_name="foo") + cube.add_cell_measure(cms, 0) + self._check_copy(cube, cube.copy()) + def test__masked_emptymask(self): cube = Cube(ma.array([0, 1])) self._check_copy(cube, cube.copy()) @@ -2268,15 +2280,15 @@ def test_ancillary_diff_data(self): def test_cell_measure_fail(self): cube1 = Cube([0, 1]) cube2 = Cube([0, 1]) - cms = CellMeasure([2, 3], measure="area", long_name="foo") + cms = CellMeasure([2, 3], long_name="foo") cube2.add_cell_measure(cms, 0) self.assertFalse(cube1 == cube2) def test_cell_measure_reorder(self): cube1 = Cube([0, 1]) cube2 = Cube([0, 1]) - cms1 = CellMeasure([2, 3], measure="area", long_name="foo") - cms2 = CellMeasure([4, 5], measure="area", long_name="bar") + cms1 = CellMeasure([2, 3], long_name="foo") + cms2 = CellMeasure([4, 5], long_name="bar") # Add the same cell measure to cube1 and cube2 in # opposite orders. cube1.add_cell_measure(cms1, 0) @@ -2288,8 +2300,8 @@ def test_cell_measure_reorder(self): def test_cell_measure_diff_data(self): cube1 = Cube([0, 1]) cube2 = Cube([0, 1]) - cms1 = CellMeasure([2, 3], measure="area", long_name="foo") - cms2 = CellMeasure([4, 5], measure="area", long_name="foo") + cms1 = CellMeasure([2, 3], long_name="foo") + cms2 = CellMeasure([4, 5], long_name="foo") cube1.add_cell_measure(cms1, 0) cube2.add_cell_measure(cms2, 0) self.assertFalse(cube1 == cube2)