diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index 1fc786c68f..5a4c0cd942 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -41,6 +41,11 @@ This document explains the changes made to Iris for this release 🐛 Bugs Fixed ============= +#. :user:`gaoflow` fixed :meth:`iris.coords.Coord.cell` so that a masked bound + is preserved as masked, instead of revealing the value stored underneath the + mask. This also corrects the cube/coordinate printout for such bounds. + (:issue:`5158`) + #. :user:`gaoflow` fixed :func:`iris.analysis.cartography.wrap_lons` so that it preserves the floating-point dtype of its input (e.g. ``float32``) instead of always promoting the result to ``float64``. Integer inputs are still returned diff --git a/lib/iris/coords.py b/lib/iris/coords.py index c804267145..da712d6e2a 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -2302,7 +2302,10 @@ def cell(self, index: int, /, *, pydate: bool | None = False) -> Cell: bound = None if self.has_bounds(): - bound = tuple(np.array(self.core_bounds()[index], ndmin=1).flatten()) + # Use `np.asanyarray` to preserve any masked values (see #5158): + bound = tuple( + np.atleast_1d(np.asanyarray(self.core_bounds()[index])).flatten() + ) if self.units.is_time_reference(): convert = self.units.num2pydate if pydate else self.units.num2date diff --git a/lib/iris/tests/unit/coords/test_Coord.py b/lib/iris/tests/unit/coords/test_Coord.py index 6ac28fa235..697a6f86d4 100644 --- a/lib/iris/tests/unit/coords/test_Coord.py +++ b/lib/iris/tests/unit/coords/test_Coord.py @@ -445,6 +445,22 @@ def test_time_as_object(self, mocker): mocker.call((mocker.sentinel.lower, mocker.sentinel.upper)), ] + def test_masked_point(self): + # A masked point should be preserved as masked in the cell (#5158). + coord = AuxCoord(ma.masked_array([3.0], mask=[True])) + cell = coord.cell(0) + assert cell.point is ma.masked + + def test_masked_bound(self): + # A masked bound should be preserved as masked in the cell, rather + # than revealing the value underneath the mask (#5158). + coord = AuxCoord( + [5.0], bounds=ma.masked_array([[3.0, 7.0]], mask=[[True, False]]) + ) + cell = coord.cell(0) + assert cell.bound[0] is ma.masked + assert cell.bound[1] == 7.0 + class Test_collapsed(CoordTestMixin): def test_serialize(self):