summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpierregm <pierregm@localhost>2009-07-18 20:03:02 +0000
committerpierregm <pierregm@localhost>2009-07-18 20:03:02 +0000
commita44e1438cc156d24bfdaa80f5007bc16f6e88418 (patch)
tree60b6661d8202b9538376bec69f2df03edd14104f
parent4beb657e521ceeb7645dfb84f531c55b8032fa39 (diff)
downloadnumpy-a44e1438cc156d24bfdaa80f5007bc16f6e88418.tar.gz
core : fixed MaskedArray.__array_finalize__ when the mask is full of False (bugfix #1166)
extras : introduced clump_masked and clump_unmasked
-rw-r--r--numpy/ma/core.py5
-rw-r--r--numpy/ma/extras.py76
-rw-r--r--numpy/ma/tests/test_core.py8
-rw-r--r--numpy/ma/tests/test_extras.py31
4 files changed, 110 insertions, 10 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index 105dd30ec..4b4fdc2b9 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -2513,7 +2513,10 @@ class MaskedArray(ndarray):
self._mask = _mask
# Finalize the mask ...........
if self._mask is not nomask:
- self._mask.shape = self.shape
+ try:
+ self._mask.shape = self.shape
+ except ValueError:
+ self._mask = nomask
return
#..................................
def __array_wrap__(self, obj, context=None):
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index 6041b7e2c..85cc834c1 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -13,8 +13,9 @@ __date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $'
__all__ = ['apply_along_axis', 'atleast_1d', 'atleast_2d', 'atleast_3d',
'average',
- 'column_stack','compress_cols','compress_rowcols', 'compress_rows',
- 'count_masked', 'corrcoef', 'cov',
+ 'clump_masked', 'clump_unmasked', 'column_stack', 'compress_cols',
+ 'compress_rowcols', 'compress_rows', 'count_masked', 'corrcoef',
+ 'cov',
'diagflat', 'dot','dstack',
'ediff1d',
'flatnotmasked_contiguous', 'flatnotmasked_edges',
@@ -30,7 +31,7 @@ __all__ = ['apply_along_axis', 'atleast_1d', 'atleast_2d', 'atleast_3d',
'vander', 'vstack',
]
-from itertools import groupby
+import itertools
import warnings
import core as ma
@@ -1366,7 +1367,7 @@ def flatnotmasked_contiguous(a):
if len(unmasked) == 0:
return None
result = []
- for k, group in groupby(enumerate(unmasked), lambda (i,x):i-x):
+ for (k, group) in itertools.groupby(enumerate(unmasked), lambda (i,x):i-x):
tmp = np.array([g[1] for g in group], int)
# result.append((tmp.size, tuple(tmp[[0,-1]])))
result.append( slice(tmp[0], tmp[-1]) )
@@ -1411,6 +1412,73 @@ def notmasked_contiguous(a, axis=None):
return result
+def _ezclump(mask):
+ """
+ Finds the clumps (groups of data with the same values) for a 1D bool array.
+
+ Returns a series of slices.
+ """
+ #def clump_masked(a):
+ if mask.ndim > 1:
+ mask = mask.ravel()
+ idx = (mask[1:] - mask[:-1]).nonzero()
+ idx = idx[0] + 1
+ slices = [slice(left, right)
+ for (left, right) in zip(itertools.chain([0], idx),
+ itertools.chain(idx, [len(mask)]),)]
+ return slices
+
+
+def clump_unmasked(a):
+ """
+ Returns a list of slices corresponding to the unmasked clumps of a 1D array.
+
+ Examples
+ --------
+ >>> a = ma.masked_array(np.arange(10))
+ >>> a[[0, 1, 2, 6, 8, 9]] = ma.masked
+ >>> clump_unmasked(a)
+ [slice(3, 6, None), slice(7, 8, None)]
+
+ .. versionadded:: 1.4.0
+ """
+ mask = getattr(a, '_mask', nomask)
+ if mask is nomask:
+ return [slice(0, a.size)]
+ slices = _ezclump(mask)
+ if a[0] is masked:
+ result = slices[1::2]
+ else:
+ result = slices[::2]
+ return result
+
+
+def clump_masked(a):
+ """
+ Returns a list of slices corresponding to the masked clumps of a 1D array.
+
+ Examples
+ --------
+ >>> a = ma.masked_array(np.arange(10))
+ >>> a[[0, 1, 2, 6, 8, 9]] = ma.masked
+ >>> clump_masked(a)
+ [slice(0, 3, None), slice(6, 7, None), slice(8, None, None)]
+
+ .. versionadded:: 1.4.0
+ """
+ mask = ma.getmask(a)
+ if mask is nomask:
+ return []
+ slices = _ezclump(mask)
+ if len(slices):
+ if a[0] is masked:
+ slices = slices[::2]
+ else:
+ slices = slices[1::2]
+ return slices
+
+
+
#####--------------------------------------------------------------------------
#---- Polynomial fit ---
#####--------------------------------------------------------------------------
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index 549f864b7..b6222a8cb 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -783,6 +783,12 @@ class TestMaskedArrayArithmetic(TestCase):
assert_equal(amaximum, np.maximum.outer(a,a))
+ def test_minmax_reduce(self):
+ "Test np.min/maximum.reduce on array w/ full False mask"
+ a = array([1, 2, 3], mask=[False, False, False])
+ b = np.maximum.reduce(a)
+ assert_equal(b, 3)
+
def test_minmax_funcs_with_output(self):
"Tests the min/max functions with explicit outputs"
mask = np.random.rand(12).round()
@@ -1359,7 +1365,7 @@ class TestFillingValues(TestCase):
assert_equal(test[1][0], maximum_fill_value(a['B']['BA']))
assert_equal(test[1][1], maximum_fill_value(a['B']['BB']))
assert_equal(test[1], maximum_fill_value(a['B']))
-
+
#------------------------------------------------------------------------------
diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py
index 089a4e58a..687fc9b81 100644
--- a/numpy/ma/tests/test_extras.py
+++ b/numpy/ma/tests/test_extras.py
@@ -70,7 +70,24 @@ class TestGeneric(TestCase):
mask=[(1, (1, 1)), (1, (1, 1))], dtype=dt)
test = masked_all_like(control)
assert_equal(test, control)
+
+ def test_clump_masked(self):
+ "Test clump_masked"
+ a = masked_array(np.arange(10))
+ a[[0, 1, 2, 6, 8, 9]] = masked
#
+ test = clump_masked(a)
+ control = [slice(0, 3), slice(6, 7), slice(8, 10)]
+ assert_equal(test, control)
+
+ def test_clump_unmasked(self):
+ "Test clump_unmasked"
+ a = masked_array(np.arange(10))
+ a[[0, 1, 2, 6, 8, 9]] = masked
+ test = clump_unmasked(a)
+ control = [slice(3, 6), slice(7, 8),]
+ assert_equal(test, control)
+
class TestAverage(TestCase):
@@ -151,8 +168,13 @@ class TestAverage(TestCase):
a2dma = average(a2dm, axis=1)
assert_equal(a2dma, [1.5, 4.0])
+
+
class TestConcatenator(TestCase):
- "Tests for mr_, the equivalent of r_ for masked arrays."
+ """
+ Tests for mr_, the equivalent of r_ for masked arrays.
+ """
+
def test_1d(self):
"Tests mr_ on 1D arrays."
assert_array_equal(mr_[1,2,3,4,5,6],array([1,2,3,4,5,6]))
@@ -186,7 +208,10 @@ class TestConcatenator(TestCase):
class TestNotMasked(TestCase):
- "Tests notmasked_edges and notmasked_contiguous."
+ """
+ Tests notmasked_edges and notmasked_contiguous.
+ """
+
def test_edges(self):
"Tests unmasked_edges"
data = masked_array(np.arange(25).reshape(5, 5),
@@ -222,7 +247,6 @@ class TestNotMasked(TestCase):
assert_equal(test[1], [(0, 1, 2, 4), (4, 2, 4, 4)])
-
def test_contiguous(self):
"Tests notmasked_contiguous"
a = masked_array(np.arange(24).reshape(3,8),
@@ -248,7 +272,6 @@ class TestNotMasked(TestCase):
-
class Test2DFunctions(TestCase):
"Tests 2D functions"
def test_compress2d(self):