Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Copying a cube would previously ignore any attached class:`iris.coords.CellMeasure`.
These are now copied over.
13 changes: 9 additions & 4 deletions lib/iris/analysis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Copy link
Member

@pp-mo pp-mo Nov 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a public function, so you really need to extend the docstring to cover the changes.
The new 'object_get' keyword is undocumented.
It might also be desirable to rename some things here, since e.g. "coords" is no longer always what it says.

Another way is to create an enhanced, private inner routine + leave the public one as a thin wrapper for coords alone.
Given the naming of the function itself, that might actually be preferable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened #3558 to address this.

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
Expand Down Expand Up @@ -334,15 +339,15 @@ 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)

# 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)
Expand Down
26 changes: 22 additions & 4 deletions lib/iris/cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand All @@ -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.
Expand Down
22 changes: 17 additions & 5 deletions lib/iris/tests/unit/cube/test_Cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down