From f2dee4278c4ff70b0e7742e2d27aa94ce89c3649 Mon Sep 17 00:00:00 2001 From: David Hassell Date: Wed, 27 Apr 2022 09:26:11 +0100 Subject: [PATCH 1/3] Data.isscalar --- cf/data/data.py | 13 +++++++------ cf/test/test_Data.py | 5 +++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/cf/data/data.py b/cf/data/data.py index c3d0cd1449..b73e476e6e 100644 --- a/cf/data/data.py +++ b/cf/data/data.py @@ -4894,18 +4894,19 @@ def is_masked(a): return bool(dx.any()) @property + @daskified(_DASKIFIED_VERBOSE) def isscalar(self): - """True if the data array is a 0-d scalar array. + """True if the data is a 0-d scalar array. **Examples** - >>> d.ndim - 0 + >>> d = cf.Data(9, 'm') >>> d.isscalar True - - >>> d.ndim >= 1 - True + >>> d = cf.Data([9], 'm') + >>> d.isscalar + False + >>> d = cf.Data([9, 10], 'm') >>> d.isscalar False diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py index 0f22111145..fab8102415 100644 --- a/cf/test/test_Data.py +++ b/cf/test/test_Data.py @@ -3845,6 +3845,11 @@ def test_Data_override_calendar(self): self.assertIsNone(d.override_calendar("all_leap", inplace=True)) + def test_Data_isscalar(self): + self.assertTrue(cf.Data(9, "m").isscalar) + self.assertFalse(cf.Data([9], "m").isscalar) + self.assertFalse(cf.Data([9, 10], "m").isscalar) + if __name__ == "__main__": print("Run date:", datetime.datetime.now()) From dc22fb64789b13550084fb9e019818b295c306b0 Mon Sep 17 00:00:00 2001 From: David Hassell Date: Wed, 27 Apr 2022 10:16:20 +0100 Subject: [PATCH 2/3] Data.masked_all --- cf/data/data.py | 60 +++++++++++++++++++++++++++++++------------- cf/test/test_Data.py | 17 ++++++++++--- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/cf/data/data.py b/cf/data/data.py index b73e476e6e..d485656321 100644 --- a/cf/data/data.py +++ b/cf/data/data.py @@ -53,7 +53,6 @@ cf_soften_mask, cf_where, ) -from .filledarray import FilledArray from .mixin import DataClassDeprecationsMixin from .utils import ( # is_small,; is_very_small, YMDhms, @@ -9396,43 +9395,68 @@ def del_units(self, default=ValueError()): ) @classmethod - def masked_all(cls, shape, dtype=None, units=None, chunk=True): - """Return a new data array of given shape and type with all - elements masked. + def masked_all( + cls, + shape, + dtype=None, + units=None, + calendar=None, + chunks=_DEFAULT_CHUNKS, + ): + """Return an empty masked array with all elements masked. - .. seealso:: `empty`, `ones`, `zeros` + .. seealso:: `empty`, `ones`, `zeros`, `masked_invalid` :Parameters: shape: `int` or `tuple` of `int` - The shape of the new array. + The shape of the new array. e.g. ``(2, 3)`` or ``2``. dtype: data-type - The data-type of the new array. By default the data-type - is ``float``. + The desired output data-type for the array, e.g. + `numpy.int8`. The default is `numpy.float64`. units: `str` or `Units` The units for the new data array. + calendar: `str`, optional + The calendar for reference time units. + + {{chunks: `int`, `tuple`, `dict` or `str`, optional}} + + .. versionadded:: 4.0.0 + :Returns: `Data` - The new data array having all elements masked. + A masked array with all data masked. **Examples** - >>> d = cf.Data.masked_all((96, 73)) + >>> d = cf.Data.masked_all((2, 2)) + >>> print(d.array) + [[-- --] + [-- --]] + + >>> d = cf.Data.masked_all((), dtype=bool) + >>> print(d.array) + masked_array(data=--, + mask=True, + fill_value=True, + dtype=bool) """ - array = FilledArray( - shape=tuple(shape), - size=reduce(mul, shape, 1), - ndim=len(shape), - dtype=np.dtype(dtype), - fill_value=cf_masked, + d = cls.empty( + shape=shape, + dtype=dtype, + units=units, + calendar=calendar, + chunks=chunks, ) - - return cls(array, units=units, chunk=chunk) + dx = d.to_dask_array() + dx = dx.map_blocks(partial(np.ma.array, mask=True, copy=False)) + d._set_dask(dx, reset_mask_hardness=False) + return d @daskified(_DASKIFIED_VERBOSE) @_inplace_enabled(default=False) diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py index fab8102415..916af722be 100644 --- a/cf/test/test_Data.py +++ b/cf/test/test_Data.py @@ -3845,10 +3845,19 @@ def test_Data_override_calendar(self): self.assertIsNone(d.override_calendar("all_leap", inplace=True)) - def test_Data_isscalar(self): - self.assertTrue(cf.Data(9, "m").isscalar) - self.assertFalse(cf.Data([9], "m").isscalar) - self.assertFalse(cf.Data([9, 10], "m").isscalar) + def test_Data_masked_all(self): + # shape + for shape in ((), (2,), (2, 3)): + a = np.ma.masked_all(shape) + d = cf.Data.masked_all(shape) + self.assertEqual(d.shape, a.shape) + self.assertTrue((d.array.mask == a.mask).all()) + + # dtype + for dtype in "fibUS": + a = np.ma.masked_all((), dtype=dtype) + d = cf.Data.masked_all((), dtype=dtype) + self.assertEqual(d.dtype, a.dtype) if __name__ == "__main__": From d34f4d710ab0faf96327535b49693bfa55c3b73f Mon Sep 17 00:00:00 2001 From: David Hassell Date: Mon, 9 May 2022 08:26:31 +0100 Subject: [PATCH 3/3] Typo Co-authored-by: Sadie L. Bartholomew --- cf/data/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cf/data/data.py b/cf/data/data.py index b22c1ceb9d..5ead348dcc 100644 --- a/cf/data/data.py +++ b/cf/data/data.py @@ -9419,7 +9419,7 @@ def masked_all( [-- --]] >>> d = cf.Data.masked_all((), dtype=bool) - >>> print(d.array) + >>> d.array masked_array(data=--, mask=True, fill_value=True,