diff options
author | pierregm <pierregm@localhost> | 2008-11-21 17:12:47 +0000 |
---|---|---|
committer | pierregm <pierregm@localhost> | 2008-11-21 17:12:47 +0000 |
commit | 3a1ffccbafc70bd5d45568fb4dd17de2accf92a4 (patch) | |
tree | da439a87acc8904b4c17a64b00c4d67e0a980e87 | |
parent | e39cb02e227e168f8b3b55c455820c47e2d6c4c1 (diff) | |
download | numpy-3a1ffccbafc70bd5d45568fb4dd17de2accf92a4.tar.gz |
* Prevent the shape of a 1d-singleton to be lost when interacting with masked (bug fix #948)
-rw-r--r-- | numpy/ma/core.py | 25 | ||||
-rw-r--r-- | numpy/ma/tests/test_core.py | 85 |
2 files changed, 92 insertions, 18 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 66958f553..78c6fde81 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -565,7 +565,7 @@ class _MaskedBinaryOperation: m = mask_or(getmask(a), getmask(b)) (d1, d2) = (get_data(a), get_data(b)) result = self.f(d1, d2, *args, **kwargs).view(get_masked_subclass(a, b)) - if result.size > 1: + if len(result.shape): if m is not nomask: result._mask = make_mask_none(result.shape) result._mask.flat = m @@ -874,7 +874,7 @@ def make_mask(m, copy=False, shrink=True, flag=None, dtype=MaskType): else: result = np.array(filled(m, True), dtype=MaskType) # Bas les masques ! - if shrink and not result.any(): + if shrink and (not result.dtype.names) and (not result.any()): return nomask else: return result @@ -1590,17 +1590,17 @@ class MaskedArray(ndarray): # if getmask(indx) is not nomask: # msg = "Masked arrays must be filled before they can be used as indices!" # raise IndexError, msg - dout = ndarray.__getitem__(ndarray.view(self,ndarray), indx) + dout = ndarray.__getitem__(ndarray.view(self, ndarray), indx) # We could directly use ndarray.__getitem__ on self... # But then we would have to modify __array_finalize__ to prevent the # mask of being reshaped if it hasn't been set up properly yet... # So it's easier to stick to the current version _mask = self._mask - if not getattr(dout,'ndim', False): + if not getattr(dout, 'ndim', False): # A record ................ if isinstance(dout, np.void): mask = _mask[indx] - if mask.view((bool,len(mask.dtype))).any(): + if mask.view((bool, len(mask.dtype))).any(): dout = masked_array(dout, mask=mask) else: return dout @@ -1656,7 +1656,7 @@ class MaskedArray(ndarray): _mask = self._mask = make_mask_none(self.shape, _dtype) # Now, set the mask to its value. if nbfields: - _mask[indx] = tuple([True,] * nbfields) + _mask[indx] = tuple([True] * nbfields) else: _mask[indx] = True if not self._isfield: @@ -1795,7 +1795,7 @@ class MaskedArray(ndarray): if _mask.size > 1: axis = 1 else: - axis=None + axis = None # try: return _mask.view((bool_, len(self.dtype))).all(axis) @@ -2197,7 +2197,7 @@ masked_%(name)s(data = %(data)s, new_mask = mask_or(other_mask, invalid) self._mask = mask_or(self._mask, new_mask) # The following line is potentially problematic, as we change _data... - np.putmask(self._data,invalid,self.fill_value) + np.putmask(self._data, invalid, self.fill_value) return self #............................................ def __float__(self): @@ -2857,7 +2857,7 @@ masked_%(name)s(data = %(data)s, if not axis: return (self - m) else: - return (self - expand_dims(m,axis)) + return (self - expand_dims(m, axis)) def var(self, axis=None, dtype=None, out=None, ddof=0): "" @@ -3124,7 +3124,8 @@ masked_%(name)s(data = %(data)s, else: filler = fill_value idx = np.indices(self.shape) - idx[axis] = self.filled(filler).argsort(axis=axis,kind=kind,order=order) + idx[axis] = self.filled(filler).argsort(axis=axis, kind=kind, + order=order) idx_l = idx.tolist() tmp_mask = self._mask[idx_l].flat tmp_data = self._data[idx_l].flat @@ -3315,11 +3316,11 @@ masked_%(name)s(data = %(data)s, nbdims = self.ndim dtypesize = len(self.dtype) if nbdims == 0: - return tuple([None]*dtypesize) + return tuple([None] * dtypesize) elif nbdims == 1: maskedidx = _mask.nonzero()[0].tolist() if dtypesize: - nodata = tuple([None]*dtypesize) + nodata = tuple([None] * dtypesize) else: nodata = None [operator.setitem(result,i,nodata) for i in maskedidx] diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index 82d7f49e4..606b3c285 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -12,7 +12,6 @@ import warnings import numpy as np import numpy.core.fromnumeric as fromnumeric from numpy import ndarray -from numpy import int_ from numpy.ma.testutils import * import numpy.ma.core @@ -70,7 +69,7 @@ class TestMaskedArray(TestCase): self.failUnless(not isMaskedArray(x)) self.failUnless(isMaskedArray(xm)) self.failUnless((xm-ym).filled(0).any()) - fail_if_equal(xm.mask.astype(int_), ym.mask.astype(int_)) + fail_if_equal(xm.mask.astype(int), ym.mask.astype(int)) s = x.shape assert_equal(np.shape(xm), s) assert_equal(xm.shape, s) @@ -594,7 +593,12 @@ class TestMaskedArrayArithmetic(TestCase): assert_equal(y.shape, x.shape) assert_equal(y._mask, [True, True]) - + def test_arithmetic_with_masked_singleton_on_1d_singleton(self): + "Check that we're not losing the shape of a singleton" + x = masked_array([1, ]) + y = x + masked + assert_equal(y.shape, x.shape) + assert_equal(y.mask, [True, ]) def test_scalar_arithmetic(self): x = array(0, mask=0) @@ -1728,7 +1732,7 @@ class TestMaskedArrayMethods(TestCase): x = array(zip([1,2,3], [1.1,2.2,3.3], ['one','two','thr']), - dtype=[('a',int_),('b',float),('c','|S8')]) + dtype=[('a',int),('b',float),('c','|S8')]) x[-1] = masked assert_equal(x.tolist(), [(1,1.1,'one'),(2,2.2,'two'),(None,None,None)]) @@ -1953,7 +1957,7 @@ class TestMaskedArrayMathMethodsComplex(TestCase): m2XX = array(data=XX,mask=m2.reshape(XX.shape)) self.d = (x,X,XX,m,mx,mX,mXX,m2x,m2X,m2XX) - #------------------------------------------------------ + def test_varstd(self): "Tests var & std on MaskedArrays." (x,X,XX,m,mx,mX,mXX,m2x,m2X,m2XX) = self.d @@ -2017,6 +2021,7 @@ class TestMaskedArrayFunctions(TestCase): assert_equal(masked_where(not_equal(x,2), x), masked_not_equal(x,2)) assert_equal(masked_where([1,1,0,0,0], [1,2,3,4,5]), [99,99,3,4,5]) + def test_masked_where_oddities(self): """Tests some generic features.""" atest = ones((10,10,10), dtype=float) @@ -2024,6 +2029,7 @@ class TestMaskedArrayFunctions(TestCase): ctest = masked_where(btest,atest) assert_equal(atest,ctest) + def test_masked_where_shape_constraint(self): a = arange(10) try: @@ -2141,11 +2147,12 @@ class TestMaskedArrayFunctions(TestCase): tmp[(xm<=2).filled(True)] = True assert_equal(d._mask, tmp) # - ixm = xm.astype(int_) + ixm = xm.astype(int) d = where(ixm>2, ixm, masked) assert_equal(d, [-9,-9,-9,-9, -9, 4, -9, -9, 10, -9, -9, 3]) assert_equal(d.dtype, ixm.dtype) + def test_where_with_masked_choice(self): x = arange(10) x[3] = masked @@ -2286,6 +2293,70 @@ class TestMaskedArrayFunctions(TestCase): test = make_mask_descr(ntype) assert_equal(test, np.dtype(np.bool)) + + def test_make_mask(self): + "Test make_mask" + # w/ a list as an input + mask = [0,1] + test = make_mask(mask) + assert_equal(test.dtype, MaskType) + assert_equal(test, [0,1]) + # w/ a ndarray as an input + mask = np.array([0,1], dtype=np.bool) + test = make_mask(mask) + assert_equal(test.dtype, MaskType) + assert_equal(test, [0,1]) + # w/ a flexible-type ndarray as an input - use default + mdtype = [('a', np.bool), ('b', np.bool)] + mask = np.array([(0, 0), (0, 1)], dtype=mdtype) + test = make_mask(mask) + assert_equal(test.dtype, MaskType) + assert_equal(test, [1,1]) + # w/ a flexible-type ndarray as an input - use input dtype + mdtype = [('a', np.bool), ('b', np.bool)] + mask = np.array([(0, 0), (0, 1)], dtype=mdtype) + test = make_mask(mask, dtype=mask.dtype) + assert_equal(test.dtype, mdtype) + assert_equal(test, mask) + # w/ a flexible-type ndarray as an input - use input dtype + mdtype = [('a', np.float), ('b', np.float)] + bdtype = [('a', np.bool), ('b', np.bool)] + mask = np.array([(0, 0), (0, 1)], dtype=mdtype) + test = make_mask(mask, dtype=mask.dtype) + assert_equal(test.dtype, bdtype) + assert_equal(test, np.array([(0, 0), (0, 1)], dtype=bdtype)) + + + def test_mask_or(self): + # Initialize + mtype = [('a', np.bool), ('b', np.bool)] + mask = np.array([(0, 0), (0, 1), (1, 0), (0, 0)], dtype=mtype) + # Test using nomask as input + test = mask_or(mask, nomask) + assert_equal(test, mask) + test = mask_or(nomask, mask) + assert_equal(test, mask) + # Using False as input + test = mask_or(mask, False) + assert_equal(test, mask) + # Using True as input. Won't work, but keep it for the kicks + #test = ma.mask_or(mask, True) + #control = np.array([(1, 1), (1, 1), (1, 1), (1, 1)], dtype=mtype) + #assert_equal(test, control) + # Using another array w/ the same dtype + other = np.array([(0, 1), (0, 1), (0, 1), (0, 1)], dtype=mtype) + test = mask_or(mask, other) + control = np.array([(0, 1), (0, 1), (1, 1), (0, 1)], dtype=mtype) + assert_equal(test, control) + # Using another array w/ a different dtype + othertype = [('A', np.bool), ('B', np.bool)] + other = np.array([(0, 1), (0, 1), (0, 1), (0, 1)], dtype=othertype) + try: + test = mask_or(mask, other) + except ValueError: + pass + + #------------------------------------------------------------------------------ class TestMaskedFields(TestCase): @@ -2408,6 +2479,8 @@ class TestMaskedFields(TestCase): assert_equal_records(a[-2]._mask, a._mask[-2]) +#------------------------------------------------------------------------------ + class TestMaskedView(TestCase): # def setUp(self): |