[Numpy-svn] r5946 - in trunk/numpy/ma: . tests
numpy-svn at scipy.org
numpy-svn at scipy.org
Fri Oct 17 22:15:19 EDT 2008
Author: pierregm
Date: 2008-10-17 21:14:51 -0500 (Fri, 17 Oct 2008)
New Revision: 5946
Modified:
trunk/numpy/ma/core.py
trunk/numpy/ma/mrecords.py
trunk/numpy/ma/tests/test_core.py
trunk/numpy/ma/tests/test_mrecords.py
trunk/numpy/ma/tests/test_subclassing.py
Log:
core : * fixed make_mask_descr to recognize subdtypes
: * fixed some corner cases of view
mrecords : * fixed view
: * got rid of _fieldmask for _mask
: * WARNING: setting ._mask no longer calls __setmask__ : BE CAREFUL.
: * prevent setting ._mask directly, as it screws up things: use .mask instead
test_subclassing : * clean up
Modified: trunk/numpy/ma/core.py
===================================================================
--- trunk/numpy/ma/core.py 2008-10-09 21:53:12 UTC (rev 5945)
+++ trunk/numpy/ma/core.py 2008-10-18 02:14:51 UTC (rev 5946)
@@ -749,11 +749,20 @@
Each field is set to a bool.
"""
+ # Make sure we do have a dtype
+ if not isinstance(ndtype, np.dtype):
+ ndtype = np.dtype(ndtype)
+ # Do we have some name fields ?
if ndtype.names:
mdescr = [list(_) for _ in ndtype.descr]
for m in mdescr:
m[1] = '|b1'
- return [tuple(_) for _ in mdescr]
+ return np.dtype([tuple(_) for _ in mdescr])
+ # Is this some kind of composite a la (np.float,2)
+ elif ndtype.subdtype:
+ mdescr = list(ndtype.subdtype)
+ mdescr[0] = np.dtype(bool)
+ return np.dtype(tuple(mdescr))
else:
return MaskType
@@ -1434,20 +1443,33 @@
return result
#.............................................
def view(self, dtype=None, type=None):
- if dtype is not None:
+ if dtype is None:
if type is None:
- args = (dtype,)
+ output = ndarray.view(self)
else:
- args = (dtype, type)
+ output = ndarray.view(self, type)
elif type is None:
- args = ()
+ try:
+ if issubclass(dtype, ndarray):
+ output = ndarray.view(self, dtype)
+ dtype = None
+ else:
+ output = ndarray.view(self, dtype)
+ except TypeError:
+ output = ndarray.view(self, dtype)
else:
- args = (type,)
- output = ndarray.view(self, *args)
+ output = ndarray.view(self, dtype, type)
+ # Should we update the mask ?
if (getattr(output,'_mask', nomask) is not nomask):
- mdtype = make_mask_descr(output.dtype)
+ if dtype is None:
+ dtype = output.dtype
+ mdtype = make_mask_descr(dtype)
+
output._mask = self._mask.view(mdtype, ndarray)
output._mask.shape = output.shape
+ # Make sure to reset the _fill_value if needed
+ if getattr(output, '_fill_value', None):
+ output._fill_value = None
return output
view.__doc__ = ndarray.view.__doc__
#.............................................
@@ -1996,7 +2018,7 @@
#
def __rmul__(self, other):
"Multiply other by self, and return a new masked array."
- return multiply(self, other)
+ return multiply(other, self)
#
def __div__(self, other):
"Divide other into self, and return a new masked array."
Modified: trunk/numpy/ma/mrecords.py
===================================================================
--- trunk/numpy/ma/mrecords.py 2008-10-09 21:53:12 UTC (rev 5945)
+++ trunk/numpy/ma/mrecords.py 2008-10-18 02:14:51 UTC (rev 5946)
@@ -106,8 +106,6 @@
_fill_value : {record}
Filling values for each field.
"""
- _defaultfieldmask = nomask
- _defaulthardmask = False
#............................................
def __new__(cls, shape, dtype=None, buf=None, offset=0, strides=None,
formats=None, names=None, titles=None,
@@ -164,7 +162,7 @@
dtype=mdescr).view(recarray)
# Update some of the attributes
_dict = self.__dict__
- _dict.update(_mask=_mask, _fieldmask=_mask)
+ _dict.update(_mask=_mask)
self._update_from(obj)
if _dict['_baseclass'] == ndarray:
_dict['_baseclass'] = recarray
@@ -226,7 +224,7 @@
def __setattr__(self, attr, val):
"Sets the attribute attr to the value val."
# Should we call __setmask__ first ?
- if attr in ['_mask','mask','_fieldmask','fieldmask']:
+ if attr in ['mask', 'fieldmask']:
self.__setmask__(val)
return
# Create a shortcut (so that we don't have to call getattr all the time)
@@ -331,18 +329,44 @@
reprstr.extend([fmt % (' fill_value', self.fill_value),
' )'])
return str("\n".join(reprstr))
- #......................................................
- def view(self, obj):
+# #......................................................
+ def view(self, dtype=None, type=None):
"""Returns a view of the mrecarray."""
- try:
- if issubclass(obj, ndarray):
- return ndarray.view(self, obj)
- except TypeError:
- pass
- dtype_ = np.dtype(obj)
- if dtype_.fields is None:
- return self.__array__().view(dtype_)
- return ndarray.view(self, obj)
+ # OK, basic copy-paste from MaskedArray.view...
+ if dtype is None:
+ if type is None:
+ output = ndarray.view(self)
+ else:
+ output = ndarray.view(self, type)
+ # Here again...
+ elif type is None:
+ try:
+ if issubclass(dtype, ndarray):
+ output = ndarray.view(self, dtype)
+ dtype = None
+ else:
+ output = ndarray.view(self, dtype)
+ # OK, there's the change
+ except TypeError:
+ dtype = np.dtype(dtype)
+ # we need to revert to MaskedArray, but keeping the possibility
+ # ...of subclasses (eg, TimeSeriesRecords), so we'll force a type
+ # ...set to the first parent
+ if dtype.fields is None:
+ basetype = self.__class__.__bases__[0]
+ output = self.__array__().view(dtype, basetype)
+ output._update_from(self)
+ else:
+ output = ndarray.view(self, dtype)
+ output._fill_value = None
+ else:
+ output = ndarray.view(self, dtype, type)
+ # Update the mask, just like in MaskedArray.view
+ if (getattr(output,'_mask', nomask) is not nomask):
+ mdtype = ma.make_mask_descr(output.dtype)
+ output._mask = self._mask.view(mdtype, ndarray)
+ output._mask.shape = output.shape
+ return output
def harden_mask(self):
"Forces the mask to hard"
@@ -355,7 +379,7 @@
"""Returns a copy of the masked record."""
_localdict = self.__dict__
copied = self._data.copy().view(type(self))
- copied._fieldmask = self._fieldmask.copy()
+ copied._mask = self._mask.copy()
return copied
def tolist(self, fill_value=None):
@@ -371,7 +395,7 @@
if fill_value is not None:
return self.filled(fill_value).tolist()
result = narray(self.filled().tolist(), dtype=object)
- mask = narray(self._fieldmask.tolist())
+ mask = narray(self._mask.tolist())
result[mask] = None
return result.tolist()
#--------------------------------------------
@@ -385,7 +409,7 @@
self.dtype,
self.flags.fnc,
self._data.tostring(),
- self._fieldmask.tostring(),
+ self._mask.tostring(),
self._fill_value,
)
return state
@@ -405,7 +429,7 @@
(ver, shp, typ, isf, raw, msk, flv) = state
ndarray.__setstate__(self, (shp, typ, isf, raw))
mdtype = dtype([(k,bool_) for (k,_) in self.dtype.descr])
- self.__dict__['_fieldmask'].__setstate__((shp, mdtype, isf, msk))
+ self.__dict__['_mask'].__setstate__((shp, mdtype, isf, msk))
self.fill_value = flv
#
def __reduce__(self):
@@ -508,7 +532,7 @@
Lists of tuples should be preferred over lists of lists for faster processing.
"""
# Grab the initial _fieldmask, if needed:
- _fieldmask = getattr(reclist, '_fieldmask', None)
+ _mask = getattr(reclist, '_mask', None)
# Get the list of records.....
try:
nfields = len(reclist[0])
@@ -533,13 +557,13 @@
mask = np.array(mask, copy=False)
maskrecordlength = len(mask.dtype)
if maskrecordlength:
- mrec._fieldmask.flat = mask
+ mrec._mask.flat = mask
elif len(mask.shape) == 2:
- mrec._fieldmask.flat = [tuple(m) for m in mask]
+ mrec._mask.flat = [tuple(m) for m in mask]
else:
- mrec._mask = mask
- if _fieldmask is not None:
- mrec._fieldmask[:] = _fieldmask
+ mrec.__setmask__(mask)
+ if _mask is not None:
+ mrec._mask[:] = _mask
return mrec
def _guessvartypes(arr):
@@ -680,5 +704,5 @@
# Add the mask of the new field
newmask.setfield(getmaskarray(newfield),
*newmask.dtype.fields[newfieldname])
- newdata._fieldmask = newmask
+ newdata._mask = newmask
return newdata
Modified: trunk/numpy/ma/tests/test_core.py
===================================================================
--- trunk/numpy/ma/tests/test_core.py 2008-10-09 21:53:12 UTC (rev 5945)
+++ trunk/numpy/ma/tests/test_core.py 2008-10-18 02:14:51 UTC (rev 5946)
@@ -2270,6 +2270,21 @@
self.failUnless(c[0,0] is masked)
self.failUnless(c.flags['C'])
+
+ def test_make_mask_descr(self):
+ "Test make_mask_descr"
+ ntype = [('a',np.float), ('b',np.float)]
+ test = make_mask_descr(ntype)
+ assert_equal(test, [('a',np.bool),('b',np.bool)])
+ #
+ ntype = (np.float, 2)
+ test = make_mask_descr(ntype)
+ assert_equal(test, (np.bool,2))
+ #
+ ntype = np.float
+ test = make_mask_descr(ntype)
+ assert_equal(test, np.dtype(np.bool))
+
#------------------------------------------------------------------------------
class TestMaskedFields(TestCase):
@@ -2361,23 +2376,15 @@
a = array(iterator, dtype=[('a',float),('b',float)])
a.mask[0] = (1,0)
controlmask = np.array([1]+19*[0], dtype=bool)
- #
+ # Transform globally to simple dtype
test = a.view(float)
assert_equal(test, data.ravel())
assert_equal(test.mask, controlmask)
- #
+ # Transform globally to dty
test = a.view((float,2))
assert_equal(test, data)
assert_equal(test.mask, controlmask.reshape(-1,2))
#
- test = a.view([('A',float),('B',float)])
- assert_equal(test.mask.dtype.names, ('A', 'B'))
- assert_equal(test['A'], a['a'])
- assert_equal(test['B'], a['b'])
- #
- test = a.view(np.ndarray)
- assert_equal(test, a._data)
- #
test = a.view((float,2), np.matrix)
assert_equal(test, data)
self.failUnless(isinstance(test, np.matrix))
@@ -2399,6 +2406,86 @@
assert_equal_records(a[-2]._data, a._data[-2])
assert_equal_records(a[-2]._mask, a._mask[-2])
+
+class TestMaskedView(TestCase):
+ #
+ def setUp(self):
+ iterator = zip(np.arange(10), np.random.rand(10))
+ data = np.array(iterator)
+ a = array(iterator, dtype=[('a',float),('b',float)])
+ a.mask[0] = (1,0)
+ controlmask = np.array([1]+19*[0], dtype=bool)
+ self.data = (data, a, controlmask)
+ #
+ def test_view_to_nothing(self):
+ (data, a, controlmask) = self.data
+ test = a.view()
+ self.failUnless(isinstance(test, MaskedArray))
+ assert_equal(test._data, a._data)
+ assert_equal(test._mask, a._mask)
+
+ #
+ def test_view_to_type(self):
+ (data, a, controlmask) = self.data
+ test = a.view(np.ndarray)
+ self.failUnless(not isinstance(test, MaskedArray))
+ assert_equal(test, a._data)
+ assert_equal_records(test, data.view(a.dtype).squeeze())
+ #
+ def test_view_to_simple_dtype(self):
+ (data, a, controlmask) = self.data
+ # View globally
+ test = a.view(float)
+ self.failUnless(isinstance(test, MaskedArray))
+ assert_equal(test, data.ravel())
+ assert_equal(test.mask, controlmask)
+ #
+ def test_view_to_flexible_dtype(self):
+ (data, a, controlmask) = self.data
+ #
+ test = a.view([('A',float),('B',float)])
+ assert_equal(test.mask.dtype.names, ('A', 'B'))
+ assert_equal(test['A'], a['a'])
+ assert_equal(test['B'], a['b'])
+ #
+ test = a[0].view([('A',float),('B',float)])
+ self.failUnless(isinstance(test, MaskedArray))
+ assert_equal(test.mask.dtype.names, ('A', 'B'))
+ assert_equal(test['A'], a['a'][0])
+ assert_equal(test['B'], a['b'][0])
+ #
+ test = a[-1].view([('A',float),('B',float)])
+ self.failUnless(not isinstance(test, MaskedArray))
+ assert_equal(test.dtype.names, ('A', 'B'))
+ assert_equal(test['A'], a['a'][-1])
+ assert_equal(test['B'], a['b'][-1])
+
+ #
+ def test_view_to_subdtype(self):
+ (data, a, controlmask) = self.data
+ # View globally
+ test = a.view((float,2))
+ self.failUnless(isinstance(test, MaskedArray))
+ assert_equal(test, data)
+ assert_equal(test.mask, controlmask.reshape(-1,2))
+ # View on 1 masked element
+ test = a[0].view((float,2))
+ self.failUnless(isinstance(test, MaskedArray))
+ assert_equal(test, data[0])
+ assert_equal(test.mask, (1,0))
+ # View on 1 unmasked element
+ test = a[-1].view((float,2))
+ self.failUnless(not isinstance(test, MaskedArray))
+ assert_equal(test, data[-1])
+ #
+ def test_view_to_dtype_and_type(self):
+ (data, a, controlmask) = self.data
+ #
+ test = a.view((float,2), np.matrix)
+ assert_equal(test, data)
+ self.failUnless(isinstance(test, np.matrix))
+ self.failUnless(not isinstance(test, MaskedArray))
+
###############################################################################
#------------------------------------------------------------------------------
if __name__ == "__main__":
Modified: trunk/numpy/ma/tests/test_mrecords.py
===================================================================
--- trunk/numpy/ma/tests/test_mrecords.py 2008-10-09 21:53:12 UTC (rev 5945)
+++ trunk/numpy/ma/tests/test_mrecords.py 2008-10-18 02:14:51 UTC (rev 5946)
@@ -65,8 +65,6 @@
assert_equal(mbase_first.tolist(), (1,1.1,'one'))
# Used to be mask, now it's recordmask
assert_equal(mbase_first.recordmask, nomask)
- # _fieldmask and _mask should be the same thing
- assert_equal(mbase_first._fieldmask.item(), (False, False, False))
assert_equal(mbase_first._mask.item(), (False, False, False))
assert_equal(mbase_first['a'], mbase['a'][0])
mbase_last = mbase[-1]
@@ -75,7 +73,7 @@
assert_equal(mbase_last.tolist(), (None,None,None))
# Used to be mask, now it's recordmask
assert_equal(mbase_last.recordmask, True)
- assert_equal(mbase_last._fieldmask.item(), (True, True, True))
+ assert_equal(mbase_last._mask.item(), (True, True, True))
assert_equal(mbase_last['a'], mbase['a'][-1])
assert (mbase_last['a'] is masked)
# as slice ..........
@@ -107,7 +105,7 @@
assert_equal(ma.getmaskarray(mbase['a']), [0]*5)
# Use to be _mask, now it's recordmask
assert_equal(mbase.recordmask, [False]*5)
- assert_equal(mbase._fieldmask.tolist(),
+ assert_equal(mbase._mask.tolist(),
np.array([(0,0,0),(0,1,1),(0,0,0),(0,0,0),(0,1,1)],
dtype=bool))
# Set a field to mask ........................
@@ -117,7 +115,7 @@
assert_equal(mbase.c.recordmask, [1]*5)
assert_equal(ma.getmaskarray(mbase['c']), [1]*5)
assert_equal(ma.getdata(mbase['c']), ['N/A']*5)
- assert_equal(mbase._fieldmask.tolist(),
+ assert_equal(mbase._mask.tolist(),
np.array([(0,0,1),(0,1,1),(0,0,1),(0,0,1),(0,1,1)],
dtype=bool))
# Set fields by slices .......................
@@ -159,23 +157,23 @@
base = self.base.copy()
mbase = base.view(mrecarray)
# Set the mask to True .......................
- mbase._mask = masked
+ mbase.mask = masked
assert_equal(ma.getmaskarray(mbase['b']), [1]*5)
assert_equal(mbase['a']._mask, mbase['b']._mask)
assert_equal(mbase['a']._mask, mbase['c']._mask)
- assert_equal(mbase._fieldmask.tolist(),
+ assert_equal(mbase._mask.tolist(),
np.array([(1,1,1)]*5, dtype=bool))
# Delete the mask ............................
- mbase._mask = nomask
+ mbase.mask = nomask
assert_equal(ma.getmaskarray(mbase['c']), [0]*5)
- assert_equal(mbase._fieldmask.tolist(),
+ assert_equal(mbase._mask.tolist(),
np.array([(0,0,0)]*5, dtype=bool))
#
def test_set_mask_fromarray(self):
base = self.base.copy()
mbase = base.view(mrecarray)
# Sets the mask w/ an array
- mbase._mask = [1,0,0,0,1]
+ mbase.mask = [1,0,0,0,1]
assert_equal(mbase.a.mask, [1,0,0,0,1])
assert_equal(mbase.b.mask, [1,0,0,0,1])
assert_equal(mbase.c.mask, [1,0,0,0,1])
@@ -206,7 +204,7 @@
# Set an element to mask .....................
mbase = base.view(mrecarray).copy()
mbase[-2] = masked
- assert_equal(mbase._fieldmask.tolist(),
+ assert_equal(mbase._mask.tolist(),
np.array([(0,0,0),(1,1,1),(0,0,0),(1,1,1),(1,1,1)],
dtype=bool))
# Used to be mask, now it's recordmask!
@@ -265,11 +263,11 @@
mbase = base.view(mrecarray)
mbase.harden_mask()
self.failUnless(mbase._hardmask)
- mbase._mask = nomask
+ mbase.mask = nomask
assert_equal_records(mbase._mask, base._mask)
mbase.soften_mask()
self.failUnless(not mbase._hardmask)
- mbase._mask = nomask
+ mbase.mask = nomask
# So, the mask of a field is no longer set to nomask...
assert_equal_records(mbase._mask,
ma.make_mask_none(base.shape,base.dtype))
@@ -286,7 +284,7 @@
assert_equal(mrec_.dtype, mrec.dtype)
assert_equal_records(mrec_._data, mrec._data)
assert_equal(mrec_._mask, mrec._mask)
- assert_equal_records(mrec_._fieldmask, mrec._fieldmask)
+ assert_equal_records(mrec_._mask, mrec._mask)
#
def test_filled(self):
"Test filling the array"
@@ -340,6 +338,45 @@
np.array([(0,0,0),(1,1,1)], dtype=mult.dtype))
+class TestView(TestCase):
+ #
+ def setUp(self):
+ (a, b) = (np.arange(10), np.random.rand(10))
+ ndtype = [('a',np.float), ('b',np.float)]
+ arr = np.array(zip(a,b), dtype=ndtype)
+ rec = arr.view(np.recarray)
+ #
+ marr = ma.array(zip(a,b), dtype=ndtype, fill_value=(-9., -99.))
+ mrec = fromarrays([a,b], dtype=ndtype, fill_value=(-9., -99.))
+ mrec.mask[3] = (False, True)
+ self.data = (mrec, a, b, arr)
+ #
+ def test_view_by_itself(self):
+ (mrec, a, b, arr) = self.data
+ test = mrec.view()
+ self.failUnless(isinstance(test, MaskedRecords))
+ assert_equal_records(test, mrec)
+ assert_equal_records(test._mask, mrec._mask)
+ #
+ def test_view_simple_dtype(self):
+ (mrec, a, b, arr) = self.data
+ ntype = (np.float, 2)
+ test = mrec.view(ntype)
+ assert(isinstance(test, ma.MaskedArray))
+ assert_equal(test, np.array(zip(a,b), dtype=np.float))
+ assert(test[3,1] is ma.masked)
+ #
+ def test_view_flexible_type(self):
+ (mrec, a, b, arr) = self.data
+ alttype = [('A',np.float), ('B',np.float)]
+ test = mrec.view(alttype)
+ assert(isinstance(test, MaskedRecords))
+ assert_equal_records(test, arr.view(alttype))
+ assert(test['B'][3] is masked)
+ assert_equal(test.dtype, np.dtype(alttype))
+ assert(test._fill_value is None)
+
+
################################################################################
class TestMRecordsImport(TestCase):
"Base test class for MaskedArrays."
@@ -395,7 +432,7 @@
_mrec = fromrecords(mrec)
assert_equal(_mrec.dtype, mrec.dtype)
assert_equal_records(_mrec._data, mrec.filled())
- assert_equal_records(_mrec._fieldmask, mrec._fieldmask)
+ assert_equal_records(_mrec._mask, mrec._mask)
def test_fromrecords_wmask(self):
"Tests construction from records w/ mask."
@@ -403,20 +440,20 @@
#
_mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=[0,1,0,])
assert_equal_records(_mrec._data, mrec._data)
- assert_equal(_mrec._fieldmask.tolist(), [(0,0,0),(1,1,1),(0,0,0)])
+ assert_equal(_mrec._mask.tolist(), [(0,0,0),(1,1,1),(0,0,0)])
#
_mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=True)
assert_equal_records(_mrec._data, mrec._data)
- assert_equal(_mrec._fieldmask.tolist(), [(1,1,1),(1,1,1),(1,1,1)])
+ assert_equal(_mrec._mask.tolist(), [(1,1,1),(1,1,1),(1,1,1)])
#
- _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=mrec._fieldmask)
+ _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=mrec._mask)
assert_equal_records(_mrec._data, mrec._data)
- assert_equal(_mrec._fieldmask.tolist(), mrec._fieldmask.tolist())
+ assert_equal(_mrec._mask.tolist(), mrec._mask.tolist())
#
_mrec = fromrecords(nrec.tolist(), dtype=ddtype,
- mask=mrec._fieldmask.tolist())
+ mask=mrec._mask.tolist())
assert_equal_records(_mrec._data, mrec._data)
- assert_equal(_mrec._fieldmask.tolist(), mrec._fieldmask.tolist())
+ assert_equal(_mrec._mask.tolist(), mrec._mask.tolist())
def test_fromtextfile(self):
"Tests reading from a text file."
Modified: trunk/numpy/ma/tests/test_subclassing.py
===================================================================
--- trunk/numpy/ma/tests/test_subclassing.py 2008-10-09 21:53:12 UTC (rev 5945)
+++ trunk/numpy/ma/tests/test_subclassing.py 2008-10-18 02:14:51 UTC (rev 5946)
@@ -154,24 +154,4 @@
if __name__ == '__main__':
run_module_suite()
- if 0:
- x = array(arange(5), mask=[0]+[1]*4)
- my = masked_array(subarray(x))
- ym = msubarray(x)
- #
- z = (my+1)
- self.failUnless(isinstance(z,MaskedArray))
- self.failUnless(not isinstance(z, MSubArray))
- self.failUnless(isinstance(z._data, SubArray))
- assert_equal(z._data.info, {})
- #
- z = (ym+1)
- self.failUnless(isinstance(z, MaskedArray))
- self.failUnless(isinstance(z, MSubArray))
- self.failUnless(isinstance(z._data, SubArray))
- self.failUnless(z._data.info['added'] > 0)
- #
- ym._set_mask([1,0,0,0,1])
- assert_equal(ym._mask, [1,0,0,0,1])
- ym._series._set_mask([0,0,0,0,1])
- assert_equal(ym._mask, [0,0,0,0,1])
+
More information about the Numpy-svn
mailing list