From 27422111952911cb3e9458368f0337213ea43d85 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 29 Sep 2022 17:23:17 +0200 Subject: [PATCH] Speed up operations that use the `Coord.cells` method for time coordinates (#4969) * Convert all time points at once before generating cells * Small simplification * Add a whatnew entry * Fix link Co-authored-by: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> Co-authored-by: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> --- docs/src/whatsnew/latest.rst | 4 ++++ lib/iris/coords.py | 33 ++++++++++++++++----------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index d579ddcce7..9c9640f4de 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -71,6 +71,10 @@ This document explains the changes made to Iris for this release :obj:`~iris.analysis.SUM`, :obj:`~iris.analysis.COUNT` and :obj:`~iris.analysis.PROPORTION` on real data. (:pull:`4905`) +#. `@bouweandela`_ made :meth:`iris.coords.Coord.cells` faster for time + coordinates. This also affects :meth:`iris.cube.Cube.extract`, + :meth:`iris.cube.Cube.subset`, and :meth:`iris.coords.Coord.intersect`. + (:pull:`4969`) 🔥 Deprecations =============== diff --git a/lib/iris/coords.py b/lib/iris/coords.py index d0d471a634..ba0ed8ee5d 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -1895,7 +1895,22 @@ def cells(self): ... """ - return _CellIterator(self) + if self.ndim != 1: + raise iris.exceptions.CoordinateMultiDimError(self) + + points = self.points + bounds = self.bounds + if self.units.is_time_reference(): + points = self.units.num2date(points) + if self.has_bounds(): + bounds = self.units.num2date(bounds) + + if self.has_bounds(): + for point, bound in zip(points, bounds): + yield Cell(point, bound) + else: + for point in points: + yield Cell(point) def _sanity_check_bounds(self): if self.ndim == 1: @@ -3137,22 +3152,6 @@ def xml_element(self, doc): return cellMethod_xml_element -# See Coord.cells() for the description/context. -class _CellIterator(Iterator): - def __init__(self, coord): - self._coord = coord - if coord.ndim != 1: - raise iris.exceptions.CoordinateMultiDimError(coord) - self._indices = iter(range(coord.shape[0])) - - def __next__(self): - # NB. When self._indices runs out it will raise StopIteration for us. - i = next(self._indices) - return self._coord.cell(i) - - next = __next__ - - # See ExplicitCoord._group() for the description/context. class _GroupIterator(Iterator): def __init__(self, points):