[Scipy-svn] r2556 - trunk/Lib/sandbox/maskedarray

scipy-svn at scipy.org scipy-svn at scipy.org
Mon Jan 15 01:44:51 CST 2007


Author: pierregm
Date: 2007-01-15 01:44:41 -0600 (Mon, 15 Jan 2007)
New Revision: 2556

Modified:
   trunk/Lib/sandbox/maskedarray/CHANGELOG
   trunk/Lib/sandbox/maskedarray/core.py
   trunk/Lib/sandbox/maskedarray/mrecords.py
Log:
cf changelog

Modified: trunk/Lib/sandbox/maskedarray/CHANGELOG
===================================================================
--- trunk/Lib/sandbox/maskedarray/CHANGELOG	2007-01-15 00:23:52 UTC (rev 2555)
+++ trunk/Lib/sandbox/maskedarray/CHANGELOG	2007-01-15 07:44:41 UTC (rev 2556)
@@ -1,3 +1,6 @@
+#2007-01-14 : Mrecords
+#           : - Slices are now properly supported
+#           : - `filled` is now properly supported
 #2007-01-12 : Mrecords
 #			: - Complete reorganization...
 #2007-01-10 : Mrecords

Modified: trunk/Lib/sandbox/maskedarray/core.py
===================================================================
--- trunk/Lib/sandbox/maskedarray/core.py	2007-01-15 00:23:52 UTC (rev 2555)
+++ trunk/Lib/sandbox/maskedarray/core.py	2007-01-15 07:44:41 UTC (rev 2556)
@@ -140,6 +140,7 @@
                   'i' : 999999,
                   'O' : '?',
                   'S' : 'N/A',
+                  'V' : '???',        
                   }
 max_filler = {'b': False,
               'f' : -numeric.inf,
@@ -574,7 +575,7 @@
     except AttributeError:
         return False
 #
-def make_mask(m, copy=False, small_mask=False):
+def make_mask(m, copy=False, small_mask=True, flag=None):
     """make_mask(m, copy=0, small_mask=0)
 Returns `m` as a mask, creating a copy if necessary or requested.
 The function can accept any sequence of integers or `nomask`. 
@@ -586,6 +587,10 @@
     - `copy` (boolean, *[False]*) : Returns a copy of `m` if true.
     - `small_mask` (boolean, *[False]*): Flattens mask to `nomask` if `m` is all false.
     """
+    if flag is not None:
+        warnings.warn("The flag 'flag' is now called 'small_mask'!",
+                      DeprecationWarning)
+        small_mask = flag
     if m is nomask:
         return nomask
     elif isinstance(m, ndarray):
@@ -807,14 +812,20 @@
 The fill_value is not used for computation within this module.
     """
     __array_priority__ = 10.1
+    _defaultmask = nomask
+    _defaulthardmask = False
     #TODO: There some reorganization to do round here
     def __new__(cls, data=None, mask=nomask, dtype=None, copy=False, fill_value=None,
-                keep_mask=True, small_mask=True, hard_mask=False):
+                keep_mask=True, small_mask=True, hard_mask=False, flag=None):
         """array(data, dtype=None, copy=True, mask=nomask, fill_value=None)
         
 If `data` is already a ndarray, its dtype becomes the default value of dtype.
         """  
 #        logging.debug("__new__ received %s" % type(data))
+        if flag is not None:
+            warnings.warn("The flag 'flag' is now called 'small_mask'!",
+                          DeprecationWarning)
+            small_mask = flag
         # 1. Argument is MA ...........
         if isinstance(data, MaskedArray) or\
            (hasattr(data,"_mask") and hasattr(data,"_data")) :
@@ -881,11 +892,8 @@
         cls._defaulthardmask = hard_mask
         cls._defaultmask = mask
 #        logging.debug("__new__ returned %s as %s" % (type(_data), cls))
-#        data = numeric.ndarray.__new__(cls, shape=_data.shape,dtype=_data.dtype, 
-#                                       buffer=_data.data, offset=0)
-#        print type(data), data.shape
-#        return data
         return numeric.asanyarray(_data).view(cls)
+    
     #..................................
     def __array_wrap__(self, obj, context=None):
         """Special hook for ufuncs.
@@ -926,16 +934,29 @@
         #
 #        logging.debug("__finalize__ received %s" % type(obj))
         if isinstance(obj, MaskedArray):
-#        if isMaskedArray(obj):
+            # We came here from a MaskedArray
             self._data = obj._data
             self._mask = obj._mask
             self._hardmask = obj._hardmask
             self._fill_value = obj._fill_value
         else:
-            self._data = obj
-            self._mask = self._defaultmask
+            # We came here from a .view()
+            if hasattr(obj,'_data') and hasattr(obj, '_mask'):
+                # obj is an old masked array or a smart record
+                self._data = obj._data
+                self._mask = obj._mask
+            else:
+                # obj is anything but...
+                self._data = obj
+                self._mask = self._defaultmask
+            # Set the instance default
             self._hardmask = self._defaulthardmask
             self.fill_value = self._fill_value
+            # Reset the class default
+            MaskedArray._defaultmask = nomask
+            MaskedArray._defaulthardmask = False
+            MaskedArray._fill_value = None
+#            logging.debug("__finalize__: obj has _mask %s" % hasattr(obj,'_data'))
 #        #
 #        logging.debug("__finalize__ returned %s" % type(self))       
         return    
@@ -1146,13 +1167,13 @@
             return with_mask1 % {
                 'name': name,
                 'data': str(self),
-                'mask': str(self.mask),
+                'mask': str(self._mask),
                 'fill': str(self.fill_value),
                 }
         return with_mask % {
             'name': name,
             'data': str(self),
-            'mask': str(self.mask),
+            'mask': str(self._mask),
             'fill': str(self.fill_value),
             }
     #............................................
@@ -1265,8 +1286,9 @@
         try:
             return self.__class__(self, mask=self._mask, dtype=tc, copy=True)
         except:
-            d = self._data.astype(tc) 
-            return self.__class__(d, mask=self._mask, dtype=tc)
+#            d = self._data.astype(tc) 
+            return self.__class__(self._data.astype(tc), mask=self._mask, 
+                                  dtype=tc)
 #        
 #        
     #............................................

Modified: trunk/Lib/sandbox/maskedarray/mrecords.py
===================================================================
--- trunk/Lib/sandbox/maskedarray/mrecords.py	2007-01-15 00:23:52 UTC (rev 2555)
+++ trunk/Lib/sandbox/maskedarray/mrecords.py	2007-01-15 07:44:41 UTC (rev 2556)
@@ -13,7 +13,7 @@
 import sys
 import types
 
-import numpy as N
+import numpy
 from numpy import bool_, complex_, float_, int_, str_, object_
 import numpy.core.numeric as numeric
 import numpy.core.numerictypes as ntypes
@@ -24,7 +24,7 @@
 from numpy.core.records import fromarrays as recfromarrays
 
 ndarray = numeric.ndarray
-_byteorderconv = N.core.records._byteorderconv
+_byteorderconv = numpy.core.records._byteorderconv
 _typestr = ntypes._typestr
 
 import maskedarray as MA
@@ -39,8 +39,8 @@
 logging.basicConfig(level=logging.DEBUG,
                     format='%(name)-15s %(levelname)s %(message)s',)
 
+reserved_fields = ['_data','_mask','_fieldmask', 'dtype']
 
-
 def _getformats(data):
     """Returns the formats of each array of arraylist as a comma-separated 
     string."""
@@ -66,7 +66,6 @@
     """    
     ndescr = len(descr)
     default_names = ['f%i' % i for i in range(ndescr)]
-    reserved = ['_data','_mask','_fieldmask', 'dtype']
     if names is None:
         new_names = default_names
     else:
@@ -81,8 +80,8 @@
             new_names += default_names[nnames:]
     ndescr = []
     for (n, d, t) in zip(new_names, default_names, descr.descr):
-        if n in reserved:
-            if t[0] in reserved: 
+        if n in reserved_fields:
+            if t[0] in reserved_fields: 
                 ndescr.append((d,t[1]))
             else:
                 ndescr.append(t)
@@ -246,7 +245,6 @@
             return
         elif attr == '_mask':
             if self._hardmask:
-#                logging.debug("setattr: object has hardmask")
                 if val is not nomask:
                     mval = getmaskarray(val)
                     for k in _names:
@@ -272,6 +270,45 @@
         return MaskedRecords(_localdict['_data'][indx], 
                              mask=_localdict['_fieldmask'][indx],
                              dtype=self.dtype)
+        
+    def __getslice__(self, i, j):
+        """Returns the slice described by [i,j]."""
+        _localdict = self.__dict__
+        return MaskedRecords(_localdict['_data'][i:j], 
+                        mask=_localdict['_fieldmask'][i:j],
+                       dtype=self.dtype)      
+        
+    def __setslice__(self, i, j, value):
+        """Sets the slice described by [i,j] to `value`."""
+        _localdict = self.__dict__
+        d = _localdict['_data']
+        m = _localdict['_fieldmask']
+        names = self.dtype.names
+        if value is masked:
+            for n in names:
+                m[i:j][n] = masked
+        elif not self._hardmask:
+            fval = filled(value)
+            mval = getmaskarray(value)
+            for n in names:
+                d[n][i:j] = fval
+                m[n][i:j] = mval
+        else:
+            mindx = getmaskarray(self)[i:j]
+            val = masked_array(value, mask=mindx, keep_mask=True)
+            valmask = getmask(value)
+            if valmask is nomask:
+                for n in names:
+                    mval = mask_or(m[n][i:j], valmask)
+                    d[n][i:j][~mval] = filled(value)
+            elif valmask.size > 1:
+                for n in names:
+                    mval = mask_or(m[n][i:j], valmask)
+                    d[n][i:j][~mval] = fval[~mval]
+                    m[n][i:j] = mask_or(m[n][i:j], mval) 
+            
+        return MaskedRecords(d, mask=m, dtype=self.dtype)      
+        
     #......................................................
     def __str__(self):
         """x.__str__() <==> str(x)
@@ -312,6 +349,35 @@
         if dtype.fields is None:
             return self.__array__().view(dtype)
         return ndarray.view(self, obj)            
+    #......................................................
+    def filled(self, fill_value=None):
+        """Returns an array of the same class as `_data`,
+ with masked values filled with `fill_value`.
+Subclassing is preserved.
+        
+If `fill_value` is None, uses self.fill_value.
+        """
+        _localdict = self.__dict__
+        d = _localdict['_data']
+        fm = _localdict['_fieldmask']
+        if not numeric.asarray(fm, dtype=bool_).any():
+            return d
+        #
+        if fill_value is None:
+            value = _localdict['fill_value']
+        else:
+            value = fill_value
+            if numeric.size(value) == 1:
+                value = [value,] * len(self.dtype)
+        #
+        if self is masked:
+            result = numeric.asanyarray(value)
+        else:
+            result = d.copy()
+            for (n, v) in zip(d.dtype.names, value):
+                numpy.putmask(numeric.asarray(result[n]), 
+                              numeric.asarray(fm[n]), v)
+        return result
     #............................................
     def harden_mask(self):
         "Forces the mask to hard"
@@ -559,6 +625,43 @@
                      for (a,m,t) in zip(_variables.T, _mask, vartypes)]
     return MaskedRecords(_datalist, dtype=mdescr)
     
-
-
 ################################################################################
+if 1:
+    from maskedarray.testutils import assert_equal
+    import numpy as N
+    if 1:
+#        def setup(self):       
+#        "Generic setup" 
+        d = N.arange(5)
+        m = MA.make_mask([1,0,0,1,1])
+        base_d = N.r_[d,d[::-1]].reshape(2,-1).T
+        base_m = N.r_[[m, m[::-1]]].T
+        base = MA.array(base_d, mask=base_m)    
+        mrecord = fromarrays(base.T,)
+        self_data = [d, m, mrecord]
+        
+#    def test_get(self):
+#        "Tests fields retrieval"
+        [d, m, mrec] = self_data
+        mrec = mrec.copy()
+        assert_equal(mrec.f0, MA.array(d,mask=m))
+        assert_equal(mrec.f1, MA.array(d[::-1],mask=m[::-1]))
+        assert((mrec._fieldmask == N.core.records.fromarrays([m, m[::-1]])).all())
+        assert_equal(mrec._mask, N.r_[[m,m[::-1]]].all(0))
+        assert_equal(mrec.f0[1], mrec[1].f0)
+        #
+        assert(isinstance(mrec[:2], MaskedRecords))
+        assert_equal(mrec[:2]['f0'], d[:2])
+        #
+        mrec[:2] = 5
+        assert_equal(mrec.f0._data, [5,5,2,3,4])
+        assert_equal(mrec.f1._data, [5,5,2,1,0])
+        assert_equal(mrec.f0._mask, [0,0,0,1,1])
+        assert_equal(mrec.f1._mask, [0,0,0,0,1])
+        mrec.harden_mask()
+        mrec[-2:] = 5
+        assert_equal(mrec.f0._data, [5,5,2,3,4])
+        assert_equal(mrec.f1._data, [5,5,2,5,0])
+        assert_equal(mrec.f0._mask, [0,0,0,1,1])
+        assert_equal(mrec.f1._mask, [0,0,0,0,1])
+        
\ No newline at end of file



More information about the Scipy-svn mailing list