From a5d3793c6a08ec737cd7eb512049561a046b2d6d Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 2 Mar 2021 17:20:02 +0000 Subject: [PATCH 1/3] fix intersection out of bounds point --- lib/iris/cube.py | 21 +++++++++++---------- lib/iris/tests/unit/cube/test_Cube.py | 8 ++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index f280891fde..00bf11d2fe 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -3185,18 +3185,19 @@ def _intersect_modulus( pre_wrap_delta != post_wrap_delta ) - # Recalculate the extended minimum. indices = inside_indices[split_cell_indices] cells = bounds[indices] - cells_delta = np.diff(coord.bounds[indices]) - - # Watch out for ascending/descending bounds - if cells_delta[0, 0] > 0: - cells[:, 0] = cells[:, 1] - cells_delta[:, 0] - minimum = np.min(cells[:, 0]) - else: - cells[:, 1] = cells[:, 0] + cells_delta[:, 0] - minimum = np.min(cells[:, 1]) + if maximum % modulus not in cells: + # Recalculate the extended minimum. + cells_delta = np.diff(coord.bounds[indices]) + + # Watch out for ascending/descending bounds. + if cells_delta[0, 0] > 0: + cells[:, 0] = cells[:, 1] - cells_delta[:, 0] + minimum = np.min(cells[:, 0]) + else: + cells[:, 1] = cells[:, 0] + cells_delta[:, 0] + minimum = np.min(cells[:, 1]) points = wrap_lons(coord.points, minimum, modulus) diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index 9fe90f5a4e..fbf76b4260 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -1731,6 +1731,14 @@ def test_aligned_exclusive(self): self.assertEqual(result.data[0, 0, 0], 171) self.assertEqual(result.data[0, 0, -1], 189) + def test_aligned_bounds_at_modulus(self): + cube = create_cube(-179.5, 180.5, bounds=True) + result = cube.intersection(longitude=(0, 360)) + self.assertArrayEqual(result.coord("longitude").bounds[0], [0, 1]) + self.assertArrayEqual(result.coord("longitude").bounds[-1], [359, 360]) + self.assertEqual(result.data[0, 0, 0], 180) + self.assertEqual(result.data[0, 0, -1], 179) + def test_negative_misaligned_points_inside(self): cube = create_cube(0, 360, bounds=True) result = cube.intersection(longitude=(-10.25, 10.25)) From cf62f66878a5951c375654c1b3db7a19f474c22f Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 10 Mar 2021 15:00:47 +0000 Subject: [PATCH 2/3] fix intersection out of bounds point take 2 --- docs/iris/src/whatsnew/3.0.2.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/iris/src/whatsnew/3.0.2.rst b/docs/iris/src/whatsnew/3.0.2.rst index 90ce970326..769b673a4c 100644 --- a/docs/iris/src/whatsnew/3.0.2.rst +++ b/docs/iris/src/whatsnew/3.0.2.rst @@ -21,6 +21,10 @@ This document explains the changes made to Iris for this release #. `@jonseddon`_ handled a malformed ``um_stash_source`` CF variable attribute in a netCDF file rather than raising a ``ValueError``. (:pull:`4035`) + #. `@rcomer`_ fixed :meth:`~iris.cube.Cube.intersection` for special cases + where one cell's bounds align with the requested maximum and minimum, as + reported in :issue:`3391`. (:pull:`4059`) + 📚 **Documentation** #. `@bjlittle`_ updated the ``intersphinx_mapping`` and fixed documentation From 71abfbded884873ae4f618168a4f7d4c6c8da620 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Thu, 6 May 2021 10:37:45 +0100 Subject: [PATCH 3/3] add referencing comment --- lib/iris/cube.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 00bf11d2fe..129542fb21 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -3188,7 +3188,10 @@ def _intersect_modulus( indices = inside_indices[split_cell_indices] cells = bounds[indices] if maximum % modulus not in cells: - # Recalculate the extended minimum. + # Recalculate the extended minimum only if the output bounds + # do not span the requested (minumum, maximum) range. If + # they do span that range, this adjustment would give unexpected + # results (see #3391). cells_delta = np.diff(coord.bounds[indices]) # Watch out for ascending/descending bounds.