diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 3c2e143bec3..8ae1e1c570a 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -59,6 +59,8 @@ Bug fixes By `Deepak Cherian `_. - ``plot.line()`` learned new kwargs: ``xincrease``, ``yincrease`` that change the direction of the respective axes. By `Deepak Cherian `_. +- Fixed ``to_iris`` to maintain lazy dask array after conversion (:issue:`2046`). + By `Alex Hilson `_ and `Stephan Hoyer `_. .. _whats-new.0.10.3: diff --git a/xarray/convert.py b/xarray/convert.py index a6defd083bf..a3c99119306 100644 --- a/xarray/convert.py +++ b/xarray/convert.py @@ -6,6 +6,7 @@ from .coding.times import CFDatetimeCoder, CFTimedeltaCoder from .conventions import decode_cf +from .core import duck_array_ops from .core.dataarray import DataArray from .core.dtypes import get_fill_value from .core.pycompat import OrderedDict, range @@ -94,7 +95,6 @@ def to_iris(dataarray): # Iris not a hard dependency import iris from iris.fileformats.netcdf import parse_cell_methods - from xarray.core.pycompat import dask_array_type dim_coords = [] aux_coords = [] @@ -121,13 +121,7 @@ def to_iris(dataarray): args['cell_methods'] = \ parse_cell_methods(dataarray.attrs['cell_methods']) - # Create the right type of masked array (should be easier after #1769) - if isinstance(dataarray.data, dask_array_type): - from dask.array import ma as dask_ma - masked_data = dask_ma.masked_invalid(dataarray) - else: - masked_data = np.ma.masked_invalid(dataarray) - + masked_data = duck_array_ops.masked_invalid(dataarray.data) cube = iris.cube.Cube(masked_data, **args) return cube diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py index 3a2c123f87e..ef52b4890ef 100644 --- a/xarray/core/duck_array_ops.py +++ b/xarray/core/duck_array_ops.py @@ -101,6 +101,10 @@ def isnull(data): einsum = _dask_or_eager_func('einsum', array_args=slice(1, None), requires_dask='0.17.3') +masked_invalid = _dask_or_eager_func( + 'masked_invalid', eager_module=np.ma, + dask_module=getattr(dask_array, 'ma', None)) + def asarray(data): return data if isinstance(data, dask_array_type) else np.asarray(data) diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 32ab3a634cb..9805966c04e 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -3025,12 +3025,11 @@ def test_to_and_from_iris_dask(self): roundtripped = DataArray.from_iris(actual) assert_identical(original, roundtripped) - # If the Iris version supports it then we should get a dask array back + # If the Iris version supports it then we should have a dask array + # at each stage of the conversion if hasattr(actual, 'core_data'): - pass - # TODO This currently fails due to the decoding loading - # the data (#1372) - # self.assertEqual(type(original.data), type(roundtripped.data)) + self.assertEqual(type(original.data), type(actual.core_data())) + self.assertEqual(type(original.data), type(roundtripped.data)) actual.remove_coord('time') auto_time_dimension = DataArray.from_iris(actual)