summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Wieser <wieser.eric@gmail.com>2018-02-17 06:39:29 (GMT)
committerEric Wieser <wieser.eric@gmail.com>2018-03-25 19:19:33 (GMT)
commit093c308fcc4249d8a0f1336827d8eb9ad1e7d274 (patch)
treeba3612fbbd3ea2890d2c8c231e244bf8928ba434
parente2c71688e765a2c0eba4958891b0637754575f18 (diff)
downloadpython-numpy-093c308fcc4249d8a0f1336827d8eb9ad1e7d274.zip
python-numpy-093c308fcc4249d8a0f1336827d8eb9ad1e7d274.tar.gz
python-numpy-093c308fcc4249d8a0f1336827d8eb9ad1e7d274.tar.bz2
BUG: Always return a list from np.ma.flatnotmasked_contiguous
Depending on the input, this would return: * A single slice, if mask=nomask * A list of slices, if mask is an array * None, if mask is fully masked The documented return value is a list, and all downstream callers of this function end up having to correct for it not being one. This affects the result of np.ma.notmasked_contiguous, which also did not document these unusual return values.
-rw-r--r--doc/release/1.15.0-notes.rst9
-rw-r--r--numpy/ma/extras.py50
-rw-r--r--numpy/ma/tests/test_extras.py11
3 files changed, 53 insertions, 17 deletions
diff --git a/doc/release/1.15.0-notes.rst b/doc/release/1.15.0-notes.rst
index fadce76..6e4ef7e 100644
--- a/doc/release/1.15.0-notes.rst
+++ b/doc/release/1.15.0-notes.rst
@@ -46,6 +46,15 @@ Future Changes
Compatibility notes
===================
+``np.ma.notmasked_contiguous`` and ``np.ma.flatnotmasked_contiguous`` always return lists
+-----------------------------------------------------------------------------------------
+This was always the documented behavior, but in reality the result used to be
+any of slice, None, or list.
+
+All downstream users seem to use detect the `None` result from
+``flatnotmasked_contiguous`` and replace it with ``[]``.
+These callers will continue to work as before.
+
C API changes
=============
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index e247fe1..8272dce 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -1620,7 +1620,10 @@ def flatnotmasked_contiguous(a):
Returns
-------
slice_list : list
- A sorted sequence of slices (start index, end index).
+ A sorted sequence of `slice` objects (start index, end index).
+
+ ..versionchanged:: 1.15.0
+ Now returns an empty list instead of None for a fully masked array
See Also
--------
@@ -1635,7 +1638,7 @@ def flatnotmasked_contiguous(a):
--------
>>> a = np.ma.arange(10)
>>> np.ma.flatnotmasked_contiguous(a)
- slice(0, 10, None)
+ [slice(0, 10, None)]
>>> mask = (a < 3) | (a > 8) | (a == 5)
>>> a[mask] = np.ma.masked
@@ -1645,13 +1648,13 @@ def flatnotmasked_contiguous(a):
>>> np.ma.flatnotmasked_contiguous(a)
[slice(3, 5, None), slice(6, 9, None)]
>>> a[:] = np.ma.masked
- >>> print(np.ma.flatnotmasked_edges(a))
- None
+ >>> np.ma.flatnotmasked_contiguous(a)
+ []
"""
m = getmask(a)
if m is nomask:
- return slice(0, a.size, None)
+ return [slice(0, a.size)]
i = 0
result = []
for (k, g) in itertools.groupby(m.ravel()):
@@ -1659,7 +1662,7 @@ def flatnotmasked_contiguous(a):
if not k:
result.append(slice(i, i + n))
i += n
- return result or None
+ return result
def notmasked_contiguous(a, axis=None):
"""
@@ -1671,7 +1674,8 @@ def notmasked_contiguous(a, axis=None):
The input array.
axis : int, optional
Axis along which to perform the operation.
- If None (default), applies to a flattened version of the array.
+ If None (default), applies to a flattened version of the array, and this
+ is the same as `flatnotmasked_contiguous`.
Returns
-------
@@ -1679,6 +1683,8 @@ def notmasked_contiguous(a, axis=None):
A list of slices (start and end indexes) of unmasked indexes
in the array.
+ If the input is 2d and axis is specified, the result is a list of lists.
+
See Also
--------
flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges,
@@ -1690,17 +1696,35 @@ def notmasked_contiguous(a, axis=None):
Examples
--------
- >>> a = np.arange(9).reshape((3, 3))
+ >>> a = np.arange(12).reshape((3, 4))
>>> mask = np.zeros_like(a)
- >>> mask[1:, 1:] = 1
-
+ >>> mask[1:, :-1] = 1; mask[0, 1] = 1; mask[-1, 0] = 0
>>> ma = np.ma.array(a, mask=mask)
+ >>> ma
+ masked_array(
+ data=[[0, --, 2, 3],
+ [--, --, --, 7],
+ [8, --, --, 11]],
+ mask=[[False, True, False, False],
+ [ True, True, True, False],
+ [False, True, True, False]],
+ fill_value=999999)
>>> np.array(ma[~ma.mask])
- array([0, 1, 2, 3, 6])
+ array([ 0, 2, 3, 7, 8, 11])
>>> np.ma.notmasked_contiguous(ma)
- [slice(0, 4, None), slice(6, 7, None)]
+ [slice(0, 1, None), slice(2, 4, None), slice(7, 9, None), slice(11, 12, None)]
+
+ >>> np.ma.notmasked_contiguous(ma, axis=0)
+ [[slice(0, 1, None), slice(2, 3, None)], # column broken into two segments
+ [], # fully masked column
+ [slice(0, 1, None)],
+ [slice(0, 3, None)]]
+ >>> np.ma.notmasked_contiguous(ma, axis=1)
+ [[slice(0, 1, None), slice(2, 4, None)], # row broken into two segments
+ [slice(3, 4, None)],
+ [slice(0, 1, None), slice(3, 4, None)]]
"""
a = asarray(a)
nd = a.ndim
@@ -1717,7 +1741,7 @@ def notmasked_contiguous(a, axis=None):
#
for i in range(a.shape[other]):
idx[other] = i
- result.append(flatnotmasked_contiguous(a[tuple(idx)]) or None)
+ result.append(flatnotmasked_contiguous(a[tuple(idx)]))
return result
diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py
index 9bebd61..95319eb 100644
--- a/numpy/ma/tests/test_extras.py
+++ b/numpy/ma/tests/test_extras.py
@@ -128,7 +128,10 @@ class TestGeneric(object):
a = arange(10)
# No mask
test = flatnotmasked_contiguous(a)
- assert_equal(test, slice(0, a.size))
+ assert_equal(test, [slice(0, a.size)])
+ # mask of all false
+ a.mask = np.zeros(10, dtype=bool)
+ assert_equal(test, [slice(0, a.size)])
# Some mask
a[(a < 3) | (a > 8) | (a == 5)] = masked
test = flatnotmasked_contiguous(a)
@@ -136,7 +139,7 @@ class TestGeneric(object):
#
a[:] = masked
test = flatnotmasked_contiguous(a)
- assert_equal(test, None)
+ assert_equal(test, [])
class TestAverage(object):
@@ -384,14 +387,14 @@ class TestNotMasked(object):
[slice(0, 1, None), slice(2, 3, None)],
[slice(2, 3, None)],
[slice(2, 3, None)],
- None,
+ [],
[slice(2, 3, None)]
])
#
tmp = notmasked_contiguous(a, 1)
assert_equal(tmp, [
[slice(0, 4, None)],
- None,
+ [],
[slice(0, 6, None), slice(7, 8, None)]
])