diff --git a/cf/data/data.py b/cf/data/data.py index f9c2d3bb50..cc349175ee 100644 --- a/cf/data/data.py +++ b/cf/data/data.py @@ -8361,24 +8361,25 @@ def binary_mask(self): m.override_units(_units_1, inplace=True) return m + @daskified(_DASKIFIED_VERBOSE) @_deprecated_kwarg_check("i") @_inplace_enabled(default=False) def clip(self, a_min, a_max, units=None, inplace=False, i=False): """Clip (limit) the values in the data array in place. - Given an interval, values outside the interval are clipped to the - interval edges. For example, if an interval of [0, 1] is specified - then values smaller than 0 become 0 and values larger than 1 - become 1. + Given an interval, values outside the interval are clipped to + the interval edges. For example, if an interval of [0, 1] is + specified then values smaller than 0 become 0 and values + larger than 1 become 1. :Parameters: - a_min: + a_min: number Minimum value. If `None`, clipping is not performed on lower interval edge. Not more than one of `a_min` and `a_max` may be `None`. - a_max: + a_max: number Maximum value. If `None`, clipping is not performed on upper interval edge. Not more than one of `a_min` and `a_max` may be `None`. @@ -8398,31 +8399,35 @@ def clip(self, a_min, a_max, units=None, inplace=False, i=False): `None` is returned. - **Examples:** + **Examples** - >>> g = f.clip(-90, 90) - >>> g = f.clip(-90, 90, 'degrees_north') + >>> d = cf.Data(np.arange(12).reshape(3, 4), 'm') + >>> print(d.array) + [[ 0 1 2 3] + [ 4 5 6 7] + [ 8 9 10 11]] + >>> print(d.clip(2, 10).array) + [[ 2 2 2 3] + [ 4 5 6 7] + [ 8 9 10 10]] + >>> print(d.clip(0.003, 0.009, 'km').array) + [[3. 3. 3. 3.] + [4. 5. 6. 7.] + [8. 9. 9. 9.]] """ - d = _inplace_enabled_define_and_cleanup(self) - if units is not None: # Convert the limits to the same units as the data array units = Units(units) - self_units = d.Units + self_units = self.Units if self_units != units: - a_min = Units.conform(a_min, units, self_units) - a_max = Units.conform(a_max, units, self_units) - # --- End: if - - config = d.partition_configuration(readonly=False) - - for partition in d.partitions.matrix.flat: - partition.open(config) - array = partition.array - array.clip(a_min, a_max, out=array) - partition.close() + a_min = Units.conform(np.asanyarray(a_min), units, self_units) + a_max = Units.conform(np.asanyarray(a_max), units, self_units) + d = _inplace_enabled_define_and_cleanup(self) + dx = self._get_dask() + dx = da.clip(dx, a_min, a_max) + d._set_dask(dx, reset_mask_hardness=False) return d @classmethod diff --git a/cf/functions.py b/cf/functions.py index ebb12c20fa..4c8355a38f 100644 --- a/cf/functions.py +++ b/cf/functions.py @@ -13,7 +13,6 @@ from collections.abc import Iterable from itertools import product from marshal import dumps -from math import ceil as math_ceil from numbers import Integral from os import getpid, listdir, mkdir from os.path import abspath as _os_path_abspath @@ -25,9 +24,9 @@ import cfdm import netCDF4 +import numpy as np from dask import config from dask.utils import parse_bytes -import numpy as np from numpy import __file__ as _numpy__file__ from numpy import __version__ as _numpy__version__ from numpy import all as _numpy_all diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py index 9e6a610ab8..c9fd4c788d 100644 --- a/cf/test/test_Data.py +++ b/cf/test/test_Data.py @@ -1506,30 +1506,19 @@ def test_Data_binary_mask(self): m = d.binary_mask self.assertTrue((d.binary_mask.array == [[0, 1, 0, 0]]).all()) - @unittest.skipIf(TEST_DASKIFIED_ONLY, "no attr. 'partition_configuration'") def test_Data_clip(self): - if self.test_only and inspect.stack()[0][3] not in self.test_only: - return - - c0 = -53.234 - c1 = 34.345456567 - - a = self.a + 0.34567 - ac = np.clip(a, c0, c1) + a = np.arange(12).reshape(3, 4) + d = cf.Data(a, "m", chunks=2) - d = cf.Data(a, "km") - self.assertIsNotNone(d.clip(c0, c1)) - self.assertIsNone(d.clip(c0, c1, inplace=True)) - - d = cf.Data(a, "km") - e = d.clip(c0, c1) - self.assertTrue((e.array == ac).all()) + self.assertIsNone(d.clip(-1, 12, inplace=True)) - e = d.clip(c0 * 1000, c1 * 1000, units="m") - self.assertTrue((e.array == ac).all()) + b = np.clip(a, 2, 10) + e = d.clip(2, 10) + self.assertTrue((e.array == b).all()) - d.clip(c0 * 100, c1 * 100, units="10m", inplace=True) - self.assertTrue(d.allclose(ac, rtol=1e-05, atol=1e-08)) + b = np.clip(a, 3, 9) + e = d.clip(0.003, 0.009, "km") + self.assertTrue((e.array == b).all()) @unittest.skipIf(TEST_DASKIFIED_ONLY, "no attr. 'partition_configuration'") def test_Data_months_years(self):