diff --git a/cf/data/data.py b/cf/data/data.py index 974a033921..ec5f719ef3 100644 --- a/cf/data/data.py +++ b/cf/data/data.py @@ -8739,20 +8739,67 @@ def count_masked(self): """ return self._size - self.count() + @daskified(_DASKIFIED_VERBOSE) def cyclic(self, axes=None, iscyclic=True): - """Returns or sets the axes of the data array which are cyclic. + """Get or set the cyclic axes. + + Some methods treat the first and last elements of a cyclic + axis as adjacent and physically connected, such as + `convolution_filter`, `__getitem__` and `__setitem__`. Some + methods may make a cyclic axis non-cyclic, such as `halo`. :Parameters: axes: (sequence of) `int`, optional + Select the axes to have their cyclicity set. By + default, or if *axes* is `None` or an empty sequence, + no axes are modified. iscyclic: `bool` + Specify whether to make the axes cyclic or + non-cyclic. By default (True), the axes are set as + cyclic. :Returns: `set` + The cyclic axes prior to the change, or the current + cylcic axes if no axes are specified. - **Examples:** + **Examples** + + >>> d = cf.Data(np.arange(12).reshape(3, 4)) + >>> d.cyclic() + set() + >>> d.cyclic(0) + set() + >>> d.cyclic() + {0} + >>> d.cyclic(0, iscyclic=False) + {0} + >>> d.cyclic() + set() + >>> d.cyclic([0, 1]) + set() + >>> d.cyclic() + {0, 1} + >>> d.cyclic([0, 1], iscyclic=False) + {0, 1} + >>> d.cyclic() + set() + + >>> print(d.array) + [[ 0 1 2 3] + [ 4 5 6 7] + [ 8 9 10 11]] + >>> d[0, -1:2] + Traceback (most recent call last): + ... + IndexError: Can't take a cyclic slice of a non-cyclic axis + >>> d.cyclic(1) + set() + >>> d[0, -1:2] + """ cyclic_axes = self._cyclic diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py index 1d9cf3f372..175a8c3a7e 100644 --- a/cf/test/test_Data.py +++ b/cf/test/test_Data.py @@ -3831,6 +3831,34 @@ def test_Data__bool__(self): with self.assertRaises(ValueError): bool(cf.Data([1, 2])) + def test_Data_cyclic(self): + d = cf.Data(np.arange(12).reshape(3, 4)) + self.assertEqual(d.cyclic(), set()) + self.assertEqual(d.cyclic(0), set()) + self.assertEqual(d.cyclic(), {0}) + self.assertEqual(d.cyclic(1), {0}) + self.assertEqual(d.cyclic(), {0, 1}) + self.assertEqual(d.cyclic(0, iscyclic=False), {0, 1}) + self.assertEqual(d.cyclic(), {1}) + self.assertEqual(d.cyclic(1, iscyclic=False), {1}) + self.assertEqual(d.cyclic(), set()) + self.assertEqual(d.cyclic([0, 1]), set()) + self.assertEqual(d.cyclic(), {0, 1}) + self.assertEqual(d.cyclic([0, 1], iscyclic=False), {0, 1}) + self.assertEqual(d.cyclic(), set()) + + # Invalid axis + with self.assertRaises(ValueError): + d.cyclic(2) + + # Scalar data + d = cf.Data(9) + self.assertEqual(d.cyclic(), set()) + + # Scalar data invalid axis + with self.assertRaises(ValueError): + d.cyclic(0) + def test_Data_change_calendar(self): d = cf.Data( [0, 1, 2, 3, 4], "days since 2004-02-27", calendar="standard"