From 227264c8ff83e667f0ffcf08bd7df5e266eb4e4e Mon Sep 17 00:00:00 2001 From: "stephen.worsley" Date: Wed, 13 Nov 2019 16:20:02 +0000 Subject: [PATCH 1/7] have cube.__eq__ check ancillary variables --- lib/iris/cube.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index a1a07caab2..a97efbd498 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -3583,6 +3583,15 @@ def __eq__(self, other): or coord_comparison["non_equal_data_dimension"] ) + if result: + anc_diff = set(self._ancillary_variables_and_dims) == set( + other._ancillary_variables_and_dims + ) + cm_diff = set(self._cell_measures_and_dims) == set( + other._cell_measures_and_dims + ) + result = anc_diff and cm_diff + # Having checked everything else, check approximate data equality. if result: result = da.allclose( From 4e68261f78a56e5144be9261ded1ee515d7c2c28 Mon Sep 17 00:00:00 2001 From: "stephen.worsley" Date: Thu, 14 Nov 2019 10:39:47 +0000 Subject: [PATCH 2/7] Add tests --- lib/iris/tests/unit/cube/test_Cube.py | 70 ++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index cd2484370b..16d8ee6876 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -25,7 +25,13 @@ from iris.analysis import MEAN from iris.aux_factory import HybridHeightFactory from iris.cube import Cube -from iris.coords import AuxCoord, DimCoord, CellMeasure, AncillaryVariable +from iris.coords import ( + AuxCoord, + DimCoord, + CellMeasure, + AncillaryVariable, + CellMethod, +) from iris.exceptions import ( CoordinateNotFoundError, CellMeasureNotFoundError, @@ -2206,5 +2212,67 @@ def test_data_bool_not_eq(self): self.assertFalse(cube1 == cube2) +class Test__eq__meta(tests.IrisTest): + def test_ancillary_fail(self): + cube1 = Cube([0, 1]) + cube2 = Cube([0, 1]) + avr = AncillaryVariable([2, 3], long_name="foo") + cube2.add_ancillary_variable(avr, 0) + self.assertFalse(cube1 == cube2) + + def test_ancillary_reorder(self): + cube1 = Cube([0, 1]) + cube2 = Cube([0, 1]) + avr1 = AncillaryVariable([2, 3], long_name="foo") + avr2 = AncillaryVariable([4, 5], long_name="bar") + # Add the same ancillary variables to cube1 and cube2 in + # opposite orders. + cube1.add_ancillary_variable(avr1, 0) + cube1.add_ancillary_variable(avr2, 0) + cube2.add_ancillary_variable(avr2, 0) + cube2.add_ancillary_variable(avr1, 0) + self.assertTrue(cube1 == cube2) + + def test_cell_measure_fail(self): + cube1 = Cube([0, 1]) + cube2 = Cube([0, 1]) + cms = CellMeasure([2, 3], measure="area", 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") + # Add the same cell measure to cube1 and cube2 in + # opposite orders. + cube1.add_cell_measure(cms1, 0) + cube1.add_cell_measure(cms2, 0) + cube2.add_cell_measure(cms2, 0) + cube2.add_cell_measure(cms1, 0) + self.assertTrue(cube1 == cube2) + + def test_cell_method_fail(self): + cube1 = Cube([0, 1]) + cube2 = Cube([0, 1]) + cmth = CellMethod("mean", "time", "6hr") + cube2.add_cell_meathod(cmth) + self.assertFalse(cube1 == cube2) + + def test_cell_method_reorder(self): + cube1 = Cube([0, 1]) + cube2 = Cube([0, 1]) + cmth1 = CellMethod("mean", "time", "6hr") + cmth2 = CellMethod("mean", "time", "12hr") + # Add the same cell method to cube1 and cube2 in + # opposite orders. + cube1.add_cell_method(cmth1) + cube1.add_cell_method(cmth2) + cube2.add_cell_method(cmth2) + cube2.add_cell_method(cmth1) + self.assertTrue(cube1 == cube2) + + if __name__ == "__main__": tests.main() From dd6ae54657428b59ff614e73c8f23fa163050043 Mon Sep 17 00:00:00 2001 From: "stephen.worsley" Date: Thu, 14 Nov 2019 11:15:14 +0000 Subject: [PATCH 3/7] Remove cell method reordering test --- lib/iris/tests/unit/cube/test_Cube.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index 16d8ee6876..bba4b6ed65 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -2260,19 +2260,6 @@ def test_cell_method_fail(self): cube2.add_cell_meathod(cmth) self.assertFalse(cube1 == cube2) - def test_cell_method_reorder(self): - cube1 = Cube([0, 1]) - cube2 = Cube([0, 1]) - cmth1 = CellMethod("mean", "time", "6hr") - cmth2 = CellMethod("mean", "time", "12hr") - # Add the same cell method to cube1 and cube2 in - # opposite orders. - cube1.add_cell_method(cmth1) - cube1.add_cell_method(cmth2) - cube2.add_cell_method(cmth2) - cube2.add_cell_method(cmth1) - self.assertTrue(cube1 == cube2) - if __name__ == "__main__": tests.main() From 7533d821b5b868cb189618a95ac17a7d4be54b0f Mon Sep 17 00:00:00 2001 From: "stephen.worsley" Date: Mon, 18 Nov 2019 11:03:41 +0000 Subject: [PATCH 4/7] add test and make *_and_dims more hashable --- lib/iris/cube.py | 12 ++++++------ lib/iris/tests/unit/cube/test_Cube.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index a97efbd498..d8b7f36607 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -1044,7 +1044,7 @@ def _check_multi_dim_metadata(self, metadata, data_dims): def _add_unique_aux_coord(self, coord, data_dims): data_dims = self._check_multi_dim_metadata(coord, data_dims) - self._aux_coords_and_dims.append([coord, data_dims]) + self._aux_coords_and_dims.append((coord, data_dims)) def add_aux_factory(self, aux_factory): """ @@ -1095,7 +1095,7 @@ def add_cell_measure(self, cell_measure, data_dims=None): if self.cell_measures(cell_measure): raise ValueError("Duplicate cell_measures are not permitted.") data_dims = self._check_multi_dim_metadata(cell_measure, data_dims) - self._cell_measures_and_dims.append([cell_measure, data_dims]) + self._cell_measures_and_dims.append((cell_measure, data_dims)) self._cell_measures_and_dims.sort( key=lambda cm_dims: (cm_dims[0]._as_defn(), cm_dims[1]) ) @@ -1125,7 +1125,7 @@ def add_ancillary_variable(self, ancillary_variable, data_dims=None): ancillary_variable, data_dims ) self._ancillary_variables_and_dims.append( - [ancillary_variable, data_dims] + (ancillary_variable, data_dims) ) self._ancillary_variables_and_dims.sort( key=lambda av_dims: (av_dims[0]._as_defn(), av_dims[1]) @@ -1195,7 +1195,7 @@ def _add_unique_dim_coord(self, dim_coord, data_dim): ) ) - self._dim_coords_and_dims.append([dim_coord, int(data_dim)]) + self._dim_coords_and_dims.append((dim_coord, int(data_dim))) def remove_aux_factory(self, aux_factory): """Removes the given auxiliary coordinate factory from the cube.""" @@ -1263,7 +1263,7 @@ def remove_cell_measure(self, cell_measure): cell_measure = self.cell_measure(cell_measure) self._cell_measures_and_dims = [ - [cell_measure_, dim] + (cell_measure_, dim) for cell_measure_, dim in self._cell_measures_and_dims if cell_measure_ is not cell_measure ] @@ -1280,7 +1280,7 @@ def remove_ancillary_variable(self, ancillary_variable): """ self._ancillary_variables_and_dims = [ - [ancillary_variable_, dim] + (ancillary_variable_, dim) for ancillary_variable_, dim in self._ancillary_variables_and_dims if ancillary_variable_ is not ancillary_variable ] diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index bba4b6ed65..fd289ff5db 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -2260,6 +2260,20 @@ def test_cell_method_fail(self): cube2.add_cell_meathod(cmth) self.assertFalse(cube1 == cube2) + # Unlike cell measures, cell methods are order sensitive. + def test_cell_method_reorder_fail(self): + cube1 = Cube([0, 1]) + cube2 = Cube([0, 1]) + cmth1 = CellMethod("mean", "time", "6hr") + cmth2 = CellMethod("mean", "time", "12hr") + # Add the same cell method to cube1 and cube2 in + # opposite orders. + cube1.add_cell_method(cmth1) + cube1.add_cell_method(cmth2) + cube2.add_cell_method(cmth2) + cube2.add_cell_method(cmth1) + self.assertFalse(cube1 == cube2) + if __name__ == "__main__": tests.main() From ea49cc5282739b96deca1e48d1d08ea7bc71a4c3 Mon Sep 17 00:00:00 2001 From: "stephen.worsley" Date: Mon, 18 Nov 2019 11:16:26 +0000 Subject: [PATCH 5/7] fix tests --- lib/iris/tests/unit/cube/test_Cube.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index fd289ff5db..c6a9cf0f36 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -1919,13 +1919,13 @@ def test_remove_aux_coord(self): def test_remove_cell_measure(self): self.cube.remove_cell_measure(self.cube.cell_measure("area")) self.assertEqual( - self.cube._cell_measures_and_dims, [[self.b_cell_measure, (0, 1)]] + self.cube._cell_measures_and_dims, [(self.b_cell_measure, (0, 1))] ) def test_remove_cell_measure_by_name(self): self.cube.remove_cell_measure("area") self.assertEqual( - self.cube._cell_measures_and_dims, [[self.b_cell_measure, (0, 1)]] + self.cube._cell_measures_and_dims, [(self.b_cell_measure, (0, 1))] ) def test_fail_remove_cell_measure_by_name(self): @@ -2257,7 +2257,7 @@ def test_cell_method_fail(self): cube1 = Cube([0, 1]) cube2 = Cube([0, 1]) cmth = CellMethod("mean", "time", "6hr") - cube2.add_cell_meathod(cmth) + cube2.add_cell_method(cmth) self.assertFalse(cube1 == cube2) # Unlike cell measures, cell methods are order sensitive. From 1fa729017611a1edc4bcbc4662eb9050b5fe3e6e Mon Sep 17 00:00:00 2001 From: "stephen.worsley" Date: Tue, 19 Nov 2019 10:27:47 +0000 Subject: [PATCH 6/7] address review comments --- lib/iris/cube.py | 11 ++++++----- lib/iris/tests/unit/cube/test_Cube.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index d8b7f36607..2c3f26971f 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -3584,13 +3584,14 @@ def __eq__(self, other): ) if result: - anc_diff = set(self._ancillary_variables_and_dims) == set( - other._ancillary_variables_and_dims - ) - cm_diff = set(self._cell_measures_and_dims) == set( + result = set(self._cell_measures_and_dims) == set( other._cell_measures_and_dims ) - result = anc_diff and cm_diff + + if result: + result = set(self._ancillary_variables_and_dims) == set( + other._ancillary_variables_and_dims + ) # Having checked everything else, check approximate data equality. if result: diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index c6a9cf0f36..e3f67a8e1e 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -2233,6 +2233,15 @@ def test_ancillary_reorder(self): cube2.add_ancillary_variable(avr1, 0) self.assertTrue(cube1 == cube2) + def test_ancillary_diff_data(self): + cube1 = Cube([0, 1]) + cube2 = Cube([0, 1]) + avr1 = AncillaryVariable([2, 3], long_name="foo") + avr2 = AncillaryVariable([4, 5], long_name="foo") + cube1.add_ancillary_variable(avr1, 0) + cube2.add_ancillary_variable(avr2, 0) + self.assertFalse(cube1 == cube2) + def test_cell_measure_fail(self): cube1 = Cube([0, 1]) cube2 = Cube([0, 1]) @@ -2253,6 +2262,15 @@ def test_cell_measure_reorder(self): cube2.add_cell_measure(cms1, 0) self.assertTrue(cube1 == cube2) + 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") + cube1.add_cell_measure(cms1, 0) + cube2.add_cell_measure(cms2, 0) + self.assertFalse(cube1 == cube2) + def test_cell_method_fail(self): cube1 = Cube([0, 1]) cube2 = Cube([0, 1]) From 7af627cc31825ac8e5eb47bbcc8be39b45ad5b48 Mon Sep 17 00:00:00 2001 From: "stephen.worsley" Date: Tue, 19 Nov 2019 11:10:07 +0000 Subject: [PATCH 7/7] address review comments --- lib/iris/tests/unit/cube/test_Cube.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index e3f67a8e1e..2407238b40 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -2292,6 +2292,19 @@ def test_cell_method_reorder_fail(self): cube2.add_cell_method(cmth1) self.assertFalse(cube1 == cube2) + def test_cell_method_correct_order(self): + cube1 = Cube([0, 1]) + cube2 = Cube([0, 1]) + cmth1 = CellMethod("mean", "time", "6hr") + cmth2 = CellMethod("mean", "time", "12hr") + # Add the same cell method to cube1 and cube2 in + # the same order. + cube1.add_cell_method(cmth1) + cube1.add_cell_method(cmth2) + cube2.add_cell_method(cmth1) + cube2.add_cell_method(cmth2) + self.assertTrue(cube1 == cube2) + if __name__ == "__main__": tests.main()