Skip to content

Commit 3e1e80e

Browse files
Lazy iris.cube.Cube.rolling_window (#5795)
* Lazy iris.cube.Cube.rolling_window * Fix test * Add whatsnew * Move test to tests.unit --------- Co-authored-by: Martin Yeo <[email protected]>
1 parent 22c98e8 commit 3e1e80e

File tree

3 files changed

+26
-14
lines changed

3 files changed

+26
-14
lines changed

docs/src/whatsnew/latest.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ This document explains the changes made to Iris for this release
5555
🚀 Performance Enhancements
5656
===========================
5757

58-
#. N/A
59-
6058
#. `@bouweandela`_ added the option to specify the Dask chunks of the target
6159
array in :func:`iris.util.broadcast_to_shape`. (:pull:`5620`)
6260

6361
#. `@schlunma`_ allowed :func:`iris.analysis.cartography.area_weights` to
6462
return dask arrays with arbitrary chunks. (:pull:`5658`)
6563

64+
#. `@bouweandela`_ made :meth:`iris.cube.Cube.rolling_window` work with lazy
65+
data. (:pull:`5795`)
6666

6767
🔥 Deprecations
6868
===============

lib/iris/cube.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4552,12 +4552,6 @@ def rolling_window(self, coord, aggregator, window, **kwargs):
45524552
-------
45534553
:class:`iris.cube.Cube`.
45544554
4555-
Notes
4556-
-----
4557-
.. note::
4558-
4559-
This operation does not yet have support for lazy evaluation.
4560-
45614555
Examples
45624556
--------
45634557
>>> import iris, iris.analysis
@@ -4661,7 +4655,7 @@ def rolling_window(self, coord, aggregator, window, **kwargs):
46614655
# this will add an extra dimension to the data at dimension + 1 which
46624656
# represents the rolled window (i.e. will have a length of window)
46634657
rolling_window_data = iris.util.rolling_window(
4664-
self.data, window=window, axis=dimension
4658+
self.core_data(), window=window, axis=dimension
46654659
)
46664660

46674661
# now update all of the coordinates to reflect the aggregation
@@ -4680,7 +4674,7 @@ def rolling_window(self, coord, aggregator, window, **kwargs):
46804674
"coordinate." % coord_.name()
46814675
)
46824676

4683-
new_bounds = iris.util.rolling_window(coord_.points, window)
4677+
new_bounds = iris.util.rolling_window(coord_.core_points(), window)
46844678

46854679
if np.issubdtype(new_bounds.dtype, np.str_):
46864680
# Handle case where the AuxCoord contains string. The points
@@ -4726,9 +4720,12 @@ def rolling_window(self, coord, aggregator, window, **kwargs):
47264720
kwargs["weights"] = iris.util.broadcast_to_shape(
47274721
weights, rolling_window_data.shape, (dimension + 1,)
47284722
)
4729-
data_result = aggregator.aggregate(
4730-
rolling_window_data, axis=dimension + 1, **kwargs
4731-
)
4723+
4724+
if aggregator.lazy_func is not None and self.has_lazy_data():
4725+
agg_method = aggregator.lazy_aggregate
4726+
else:
4727+
agg_method = aggregator.aggregate
4728+
data_result = agg_method(rolling_window_data, axis=dimension + 1, **kwargs)
47324729
result = aggregator.post_process(new_cube, data_result, [coord], **kwargs)
47334730
return result
47344731

lib/iris/tests/unit/cube/test_Cube.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ def setUp(self):
877877
self.cell_measure = CellMeasure([0, 1, 2, 0, 1, 2], long_name="bar")
878878
self.multi_dim_cube.add_cell_measure(self.cell_measure, 1)
879879

880-
self.mock_agg = mock.Mock(spec=Aggregator)
880+
self.mock_agg = mock.Mock(spec=Aggregator, lazy_func=None)
881881
self.mock_agg.aggregate = mock.Mock(return_value=np.empty([4]))
882882
self.mock_agg.post_process = mock.Mock(side_effect=lambda x, y, z: x)
883883

@@ -919,6 +919,21 @@ def test_kwargs(self):
919919
)
920920
self.assertMaskedArrayEqual(expected_result, res_cube.data)
921921

922+
def test_lazy(self):
923+
window = 2
924+
self.cube.data = da.ma.masked_array(
925+
self.cube.data, mask=([True, False, False, False, True, False])
926+
)
927+
res_cube = self.cube.rolling_window("val", iris.analysis.MEAN, window, mdtol=0)
928+
self.assertTrue(self.cube.has_lazy_data())
929+
self.assertTrue(res_cube.has_lazy_data())
930+
expected_result = ma.array(
931+
[-99.0, 1.5, 2.5, -99.0, -99.0],
932+
mask=[True, False, False, True, True],
933+
dtype=np.float64,
934+
)
935+
self.assertMaskedArrayEqual(expected_result, res_cube.data)
936+
922937
def test_ancillary_variables_and_cell_measures_kept(self):
923938
res_cube = self.multi_dim_cube.rolling_window("val", self.mock_agg, 3)
924939
self.assertEqual(res_cube.ancillary_variables(), [self.ancillary_variable])

0 commit comments

Comments
 (0)