[Numpy-svn] r5248 - in trunk/numpy/ma: . tests

numpy-svn at scipy.org numpy-svn at scipy.org
Tue Jun 3 17:23:21 EDT 2008


Author: pierregm
Date: 2008-06-03 16:23:15 -0500 (Tue, 03 Jun 2008)
New Revision: 5248

Modified:
   trunk/numpy/ma/core.py
   trunk/numpy/ma/mrecords.py
   trunk/numpy/ma/tests/test_core.py
   trunk/numpy/ma/testutils.py
Log:
core:
* use the "import numpy as np" convention
* use np.function instead of (from)numeric.function
* CHANGE : when using named fields, the fill_value is now a void-ndarray (and no longer a tuple)
* _check_fill_value now checks that an existing fill_value is compatible with a new dtype (bug #806)
* fix_invalid now accepts the mask keyword
* MaskedArray.__new__ doesn't run _check_fill_value when the fill_value is None
* add the astype method, to support the conversion of fill_value when needed.
* arange/empty/empty_like/ones/zeros are now available through _convert2ma

test_core:
* modified test_filled_value to reflect that fill_value is a void-ndrecord when using named fields
* added test_check_fill_value/test_check_fill_value_with_records

testutils: 
* use the "import numpy as np" convention
* assert_equal_records now uses getitem instead of getattr
* assert_array_compare now calls numpy.testing.utils.assert_array_compare on filled data
* the assert_xxx functions now accept the verbose keyword

mrecords:
* MaskedRecords inherit get_fill_value and set_fill_value from MaskedArray
* In filled, force the filling value to be a void-ndarray

Modified: trunk/numpy/ma/core.py
===================================================================
--- trunk/numpy/ma/core.py	2008-06-03 08:50:08 UTC (rev 5247)
+++ trunk/numpy/ma/core.py	2008-06-03 21:23:15 UTC (rev 5248)
@@ -61,24 +61,23 @@
 import cPickle
 import operator
 
-import numpy
-from numpy.core import bool_, complex_, float_, int_, object_, str_
+import numpy as np
+from numpy import ndarray, dtype, typecodes, amax, amin, iscomplexobj,\
+    bool_, complex_, float_, int_, object_, str_
+from numpy import array as narray
 
+
 import numpy.core.umath as umath
-import numpy.core.fromnumeric  as fromnumeric
-import numpy.core.numeric as numeric
 import numpy.core.numerictypes as ntypes
-from numpy import bool_, dtype, typecodes, amax, amin, ndarray, iscomplexobj
 from numpy import expand_dims as n_expand_dims
-from numpy import array as narray
 import warnings
 
 
-MaskType = bool_
+MaskType = np.bool_
 nomask = MaskType(0)
 
 divide_tolerance = 1.e-35
-numpy.seterr(all='ignore')
+np.seterr(all='ignore')
 
 def doc_note(note):
     return "\nNotes\n-----\n%s" % note
@@ -90,7 +89,7 @@
     "Class for MA related errors."
     def __init__ (self, args=None):
         "Creates an exception."
-        Exception.__init__(self,args)
+        Exception.__init__(self, args)
         self.args = args
     def __str__(self):
         "Calculates the string representation."
@@ -111,12 +110,12 @@
                   'V' : '???',
                   }
 max_filler = ntypes._minvals
-max_filler.update([(k,-numpy.inf) for k in [numpy.float32, numpy.float64]])
+max_filler.update([(k, -np.inf) for k in [np.float32, np.float64]])
 min_filler = ntypes._maxvals
-min_filler.update([(k,numpy.inf) for k in [numpy.float32, numpy.float64]])
+min_filler.update([(k, +np.inf) for k in [np.float32, np.float64]])
 if 'float128' in ntypes.typeDict:
-    max_filler.update([(numpy.float128,-numpy.inf)])
-    min_filler.update([(numpy.float128, numpy.inf)])
+    max_filler.update([(np.float128, -np.inf)])
+    min_filler.update([(np.float128, +np.inf)])
 
 def default_fill_value(obj):
     """Calculate the default fill value for the argument object.
@@ -124,7 +123,7 @@
     """
     if hasattr(obj,'dtype'):
         defval = default_filler[obj.dtype.kind]
-    elif isinstance(obj, numeric.dtype):
+    elif isinstance(obj, np.dtype):
         defval = default_filler[obj.kind]
     elif isinstance(obj, float):
         defval = default_filler['f']
@@ -155,7 +154,7 @@
         return min_filler[ntypes.typeDict['int_']]
     elif isinstance(obj, long):
         return min_filler[ntypes.typeDict['uint']]
-    elif isinstance(obj, numeric.dtype):
+    elif isinstance(obj, np.dtype):
         return min_filler[obj]
     else:
         raise TypeError, 'Unsuitable type for calculating minimum.'
@@ -177,28 +176,43 @@
         return max_filler[ntypes.typeDict['int_']]
     elif isinstance(obj, long):
         return max_filler[ntypes.typeDict['uint']]
-    elif isinstance(obj, numeric.dtype):
+    elif isinstance(obj, np.dtype):
         return max_filler[obj]
     else:
         raise TypeError, 'Unsuitable type for calculating minimum.'
 
 
-def _check_fill_value(fill_value, dtype):
-    descr = numpy.dtype(dtype).descr
+def _check_fill_value(fill_value, ndtype):
+    ndtype = np.dtype(ndtype)
+    nbfields = len(ndtype)
     if fill_value is None:
-        if len(descr) > 1:
-            fill_value = [default_fill_value(numeric.dtype(d[1]))
-                          for d in descr]
+        if nbfields >= 1:
+            fill_value = np.array(tuple([default_fill_value(np.dtype(d))
+                                         for (_, d) in ndtype.descr]),
+                                  dtype=ndtype)
         else:
-            fill_value = default_fill_value(dtype)
+            fill_value = default_fill_value(ndtype)
+    elif nbfields >= 1:
+        if isinstance(fill_value, ndarray):
+            try:
+                fill_value = np.array(fill_value, copy=False, dtype=ndtype)
+            except ValueError:
+                err_msg = "Unable to transform %s to dtype %s"
+                raise ValueError(err_msg % (fill_value,ndtype))
+        else:
+            fval = np.resize(fill_value, nbfields)
+            fill_value = tuple([np.asarray(f).astype(d).item()
+                                for (f, (_, d)) in zip(fval, ndtype.descr)])
+            fill_value = np.array(fill_value, copy=False, dtype=ndtype)
     else:
-        fill_value = narray(fill_value).tolist()
-        fval = numpy.resize(fill_value, len(descr))
-        if len(descr) > 1:
-            fill_value = [numpy.asarray(f).astype(d[1]).item()
-                          for (f,d) in zip(fval, descr)]
+        if isinstance(fill_value, basestring) and (ndtype.char not in 'SV'):
+            fill_value = default_fill_value(ndtype)
         else:
-            fill_value = narray(fval, copy=False, dtype=dtype).item()
+            # In case we want to convert 1e+20 to int...
+            try:
+                fill_value = np.array(fill_value, copy=False, dtype=ndtype).item()
+            except OverflowError:
+                fill_value = default_fill_value(ndtype)
     return fill_value
 
 
@@ -302,13 +316,13 @@
         return a subclass of ndarray if approriate (True).
 
     """
-    data = getattr(a, '_data', numpy.array(a, subok=subok))
+    data = getattr(a, '_data', np.array(a, subok=subok))
     if not subok:
         return data.view(ndarray)
     return data
 getdata = get_data
 
-def fix_invalid(a, copy=True, fill_value=None):
+def fix_invalid(a, mask=nomask, copy=True, fill_value=None):
     """Return (a copy of) a where invalid data (nan/inf) are masked
     and replaced by fill_value.
 
@@ -329,9 +343,9 @@
     b : MaskedArray
 
     """
-    a = masked_array(a, copy=copy, subok=True)
+    a = masked_array(a, copy=copy, mask=mask, subok=True)
     #invalid = (numpy.isnan(a._data) | numpy.isinf(a._data))
-    invalid = numpy.logical_not(numpy.isfinite(a._data))
+    invalid = np.logical_not(np.isfinite(a._data))
     if not invalid.any():
         return a
     a._mask |= invalid
@@ -439,16 +453,16 @@
         "Execute the call behavior."
         #
         m = getmask(a)
-        d1 = get_data(a)
+        d1 = getdata(a)
         #
         if self.domain is not None:
-            dm = narray(self.domain(d1), copy=False)
-            m = numpy.logical_or(m, dm)
+            dm = np.array(self.domain(d1), copy=False)
+            m = np.logical_or(m, dm)
             # The following two lines control the domain filling methods.
             d1 = d1.copy()
             # We could use smart indexing : d1[dm] = self.fill ...
-            # ... but numpy.putmask looks more efficient, despite the copy.
-            numpy.putmask(d1, dm, self.fill)
+            # ... but np.putmask looks more efficient, despite the copy.
+            np.putmask(d1, dm, self.fill)
         # Take care of the masked singletong first ...
         if not m.ndim and m:
             return masked
@@ -500,14 +514,14 @@
         "Execute the call behavior."
         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))
+        result = self.f(d1, d2, *args, **kwargs).view(get_masked_subclass(a, b))
         if result.size > 1:
             if m is not nomask:
                 result._mask = make_mask_none(result.shape)
                 result._mask.flat = m
-            if isinstance(a,MaskedArray):
+            if isinstance(a, MaskedArray):
                 result._update_from(a)
-            if isinstance(b,MaskedArray):
+            if isinstance(b, MaskedArray):
                 result._update_from(b)
         elif m:
             return masked
@@ -554,7 +568,7 @@
             m = umath.logical_or.outer(ma, mb)
         if (not m.ndim) and m:
             return masked
-        rcls = get_masked_subclass(a,b)
+        rcls = get_masked_subclass(a, b)
         # We could fill the arguments first, butis it useful ?
         # d = self.f.outer(filled(a, self.fillx), filled(b, self.filly)).view(rcls)
         d = self.f.outer(getdata(a), getdata(b)).view(rcls)
@@ -614,16 +628,16 @@
         if t.any(None):
             mb = mask_or(mb, t)
             # The following line controls the domain filling
-            d2 = numpy.where(t,self.filly,d2)
+            d2 = np.where(t,self.filly,d2)
         m = mask_or(ma, mb)
         if (not m.ndim) and m:
             return masked
-        result =  self.f(d1, d2).view(get_masked_subclass(a,b))
+        result =  self.f(d1, d2).view(get_masked_subclass(a, b))
         if result.ndim > 0:
             result._mask = m
-            if isinstance(a,MaskedArray):
+            if isinstance(a, MaskedArray):
                 result._update_from(a)
-            if isinstance(b,MaskedArray):
+            if isinstance(b, MaskedArray):
                 result._update_from(b)
         return result
 
@@ -647,7 +661,7 @@
 negative = _MaskedUnaryOperation(umath.negative)
 floor = _MaskedUnaryOperation(umath.floor)
 ceil = _MaskedUnaryOperation(umath.ceil)
-around = _MaskedUnaryOperation(fromnumeric.round_)
+around = _MaskedUnaryOperation(np.round_)
 logical_not = _MaskedUnaryOperation(umath.logical_not)
 # Domained unary ufuncs .......................................................
 sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0,
@@ -723,7 +737,7 @@
     """
     m = getmask(a)
     if m is nomask:
-        m = make_mask_none(fromnumeric.shape(a))
+        m = make_mask_none(np.shape(a))
     return m
 
 def is_mask(m):
@@ -776,16 +790,18 @@
     else:
         return result
 
-def make_mask_none(s):
+def make_mask_none(newshape):
     """Return a mask of shape s, filled with False.
 
     Parameters
     ----------
-    s : tuple
+    news : tuple
         A tuple indicating the shape of the final mask.
+    fieldnames: {None, string sequence}, optional
+        A list of field names, if needed.
 
     """
-    result = numeric.zeros(s, dtype=MaskType)
+    result = np.zeros(newshape, dtype=MaskType)
     return result
 
 def mask_or (m1, m2, copy=False, shrink=True):
@@ -834,7 +850,7 @@
 
     """
     cond = make_mask(condition)
-    a = narray(a, copy=copy, subok=True)
+    a = np.array(a, copy=copy, subok=True)
     if hasattr(a, '_mask'):
         cond = mask_or(cond, a._mask)
         cls = type(a)
@@ -925,7 +941,7 @@
         condition = umath.equal(x._data, value)
         mask = x._mask
     else:
-        condition = umath.equal(fromnumeric.asarray(x), value)
+        condition = umath.equal(np.asarray(x), value)
         mask = nomask
     mask = mask_or(mask, make_mask(condition, shrink=True))
     return masked_array(x, mask=mask, copy=copy, fill_value=value)
@@ -955,7 +971,7 @@
     """
     abs = umath.absolute
     xnew = filled(x, value)
-    if issubclass(xnew.dtype.type, numeric.floating):
+    if issubclass(xnew.dtype.type, np.floating):
         condition = umath.less_equal(abs(xnew-value), atol+rtol*abs(value))
         mask = getattr(x, '_mask', nomask)
     else:
@@ -969,8 +985,8 @@
     preexisting mask is conserved.
 
     """
-    a = narray(a, copy=copy, subok=True)
-    condition = ~(numpy.isfinite(a))
+    a = np.array(a, copy=copy, subok=True)
+    condition = ~(np.isfinite(a))
     if hasattr(a, '_mask'):
         condition = mask_or(condition, a._mask)
         cls = type(a)
@@ -1054,7 +1070,7 @@
     def getdoc(self):
         "Return the doc of the function (from the doc of the method)."
         methdoc = getattr(ndarray, self._name, None)
-        methdoc = getattr(numpy, self._name, methdoc)
+        methdoc = getattr(np, self._name, methdoc)
         if methdoc is not None:
             return methdoc.__doc__
     #
@@ -1084,7 +1100,7 @@
     "Define an interator."
     def __init__(self, ma):
         self.ma = ma
-        self.ma_iter = numpy.asarray(ma).flat
+        self.ma_iter = np.asarray(ma).flat
 
         if ma._mask is nomask:
             self.maskiter = None
@@ -1106,7 +1122,7 @@
         return d
 
 
-class MaskedArray(numeric.ndarray):
+class MaskedArray(ndarray):
     """Arrays with possibly masked values.  Masked values of True
     exclude the corresponding element from any computation.
 
@@ -1151,11 +1167,11 @@
     __array_priority__ = 15
     _defaultmask = nomask
     _defaulthardmask = False
-    _baseclass =  numeric.ndarray
+    _baseclass = ndarray
 
     def __new__(cls, data=None, mask=nomask, dtype=None, copy=False,
                 subok=True, ndmin=0, fill_value=None,
-                keep_mask=True, hard_mask=False, flag=None,shrink=True,
+                keep_mask=True, hard_mask=False, flag=None, shrink=True,
                 **options):
         """Create a new masked array from scratch.
 
@@ -1181,29 +1197,34 @@
             _sharedmask = True
         # Process mask ...........
         if mask is nomask:
+             # Erase the current mask ?
             if not keep_mask:
+                # With a reduced version
                 if shrink:
                     _data._mask = nomask
+                # With full version
                 else:
-                    _data._mask = make_mask_none(_data)
+                    _data._mask = np.zeros(_data.shape, dtype=MaskType)
             if copy:
                 _data._mask = _data._mask.copy()
                 _data._sharedmask = False
             else:
                 _data._sharedmask = True
+        # Case 2. : With a mask in input ........
         else:
-            mask = narray(mask, dtype=MaskType, copy=copy)
+            mask = np.array(mask, dtype=MaskType, copy=copy)
             if mask.shape != _data.shape:
                 (nd, nm) = (_data.size, mask.size)
                 if nm == 1:
-                    mask = numeric.resize(mask, _data.shape)
+                    mask = np.resize(mask, _data.shape)
                 elif nm == nd:
-                    mask = fromnumeric.reshape(mask, _data.shape)
+                    mask = np.reshape(mask, _data.shape)
                 else:
                     msg = "Mask and data not compatible: data size is %i, "+\
                           "mask size is %i."
                     raise MAError, msg % (nd, nm)
                 copy = True
+            # Set the mask to the new value
             if _data._mask is nomask:
                 _data._mask = mask
                 _data._sharedmask = not copy
@@ -1216,8 +1237,10 @@
                     _data._sharedmask = False
         # Update fill_value.......
         if fill_value is None:
-            fill_value = getattr(data,'_fill_value', None)
-        _data._fill_value = _check_fill_value(fill_value, _data.dtype)
+            fill_value = getattr(data, '_fill_value', None)
+        # But don't run the check unless we have something to check....
+        if fill_value is not None:
+            _data._fill_value = _check_fill_value(fill_value, _data.dtype)
         # Process extra options ..
         _data._hardmask = hard_mask
         _data._baseclass = _baseclass
@@ -1227,15 +1250,15 @@
     def _update_from(self, obj):
         """Copies some attributes of obj to self.
         """
-        if obj is not None and isinstance(obj,ndarray):
+        if obj is not None and isinstance(obj, ndarray):
             _baseclass = type(obj)
         else:
             _baseclass = ndarray
-        _basedict = getattr(obj,'_basedict',getattr(obj,'__dict__',{}))
+        _basedict = getattr(obj, '_basedict', getattr(obj, '__dict__',{}))
         _dict = dict(_fill_value=getattr(obj, '_fill_value', None),
                      _hardmask=getattr(obj, '_hardmask', False),
                      _sharedmask=getattr(obj, '_sharedmask', False),
-                     _baseclass=getattr(obj,'_baseclass',_baseclass),
+                     _baseclass=getattr(obj,'_baseclass', _baseclass),
                      _basedict=_basedict,)
         self.__dict__.update(_dict)
         self.__dict__.update(_basedict)
@@ -1281,7 +1304,7 @@
                     # Domain not recognized, use fill_value instead
                     fill_value = self.fill_value
                 result = result.copy()
-                numpy.putmask(result, d, fill_value)
+                np.putmask(result, d, fill_value)
                 # Update the mask
                 if m is nomask:
                     if d is not nomask:
@@ -1297,6 +1320,24 @@
         #....
         return result
     #.............................................
+    def astype(self, newtype):
+        """Returns a copy of the array cast to newtype."""
+        newtype = np.dtype(newtype)
+        output = self._data.astype(newtype).view(type(self))
+        output._update_from(self)
+        names = output.dtype.names
+        if names is None:
+            output._mask = self._mask.astype(bool)
+        else:
+            if self._mask is nomask:
+                output._mask = nomask
+            else:
+                output._mask = self._mask.astype([(n,bool) for n in names])
+        # Don't check _fill_value if it's None, that'll speed things up
+        if self._fill_value is not None:
+            output._fill_value = _check_fill_value(self._fill_value, newtype)
+        return output
+    #.............................................
     def __getitem__(self, indx):
         """x.__getitem__(y) <==> x[y]
 
@@ -1312,10 +1353,10 @@
         # 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
-        m = self._mask
+        _mask = self._mask
         if not getattr(dout,'ndim', False):
             # Just a scalar............
-            if m is not nomask and m[indx]:
+            if _mask is not nomask and _mask[indx]:
                 return masked
         else:
             # Force dout to MA ........
@@ -1324,20 +1365,15 @@
             dout._update_from(self)
             # Check the fill_value ....
             if isinstance(indx, basestring):
-                fvindx = list(self.dtype.names).index(indx)
-                dout._fill_value = self.fill_value[fvindx]
+                if self._fill_value is not None:
+                    dout._fill_value = self._fill_value[indx]
             # Update the mask if needed
-            if m is not nomask:
+            if _mask is not nomask:
                 if isinstance(indx, basestring):
-                    dout._mask = m.reshape(dout.shape)
+                    dout._mask = _mask.reshape(dout.shape)
                 else:
-                    dout._mask = ndarray.__getitem__(m, indx).reshape(dout.shape)
+                    dout._mask = ndarray.__getitem__(_mask, indx).reshape(dout.shape)
 #               Note: Don't try to check for m.any(), that'll take too long...
-#                mask = ndarray.__getitem__(m, indx).reshape(dout.shape)
-#                if self._shrinkmask and not m.any():
-#                    dout._mask = nomask
-#                else:
-#                    dout._mask = mask
         return dout
     #........................
     def __setitem__(self, indx, value):
@@ -1354,7 +1390,7 @@
 #            msg = "Masked arrays must be filled before they can be used as indices!"
 #            raise IndexError, msg
         if isinstance(indx, basestring):
-            ndarray.__setitem__(self._data,indx, getdata(value))
+            ndarray.__setitem__(self._data, indx, getdata(value))
             warnings.warn("MaskedArray.__setitem__ on fields: "\
                           "The mask is NOT affected!")
             return
@@ -1362,19 +1398,19 @@
         if value is masked:
             m = self._mask
             if m is nomask:
-                m = numpy.zeros(self.shape, dtype=MaskType)
+                m = np.zeros(self.shape, dtype=MaskType)
             m[indx] = True
             self._mask = m
             self._sharedmask = False
             return
         #....
-        dval = narray(value, copy=False, dtype=self.dtype)
+        dval = np.array(value, copy=False, dtype=self.dtype)
         valmask = getmask(value)
         if self._mask is nomask:
             # Set the data, then the mask
             ndarray.__setitem__(self._data,indx,dval)
             if valmask is not nomask:
-                self._mask = numpy.zeros(self.shape, dtype=MaskType)
+                self._mask = np.zeros(self.shape, dtype=MaskType)
                 self._mask[indx] = valmask
         elif not self._hardmask:
             # Unshare the mask if necessary to avoid propagation
@@ -1392,7 +1428,7 @@
                 dindx[~mindx] = dval
             elif mindx is nomask:
                 dindx = dval
-            ndarray.__setitem__(self._data,indx,dindx)
+            ndarray.__setitem__(self._data, indx, dindx)
             self._mask[indx] = mindx
     #............................................
     def __getslice__(self, i, j):
@@ -1438,7 +1474,7 @@
                 self.unshare_mask()
                 self._mask.flat = mask
         if self._mask.shape:
-            self._mask = numeric.reshape(self._mask, self.shape)
+            self._mask = np.reshape(self._mask, self.shape)
     _set_mask = __setmask__
     #....
     def _get_mask(self):
@@ -1527,7 +1563,7 @@
         If value is None, use a default based on the data type.
 
         """
-        self._fill_value = _check_fill_value(value,self.dtype)
+        self._fill_value = _check_fill_value(value, self.dtype)
 
     fill_value = property(fget=get_fill_value, fset=set_fill_value,
                           doc="Filling value.")
@@ -1560,21 +1596,21 @@
             fill_value = self.fill_value
         #
         if self is masked_singleton:
-            result = numeric.asanyarray(fill_value)
+            result = np.asanyarray(fill_value)
         else:
             result = self._data.copy()
             try:
-                numpy.putmask(result, m, fill_value)
+                np.putmask(result, m, fill_value)
             except (TypeError, AttributeError):
                 fill_value = narray(fill_value, dtype=object)
                 d = result.astype(object)
-                result = fromnumeric.choose(m, (d, fill_value))
+                result = np.choose(m, (d, fill_value))
             except IndexError:
                 #ok, if scalar
                 if self._data.shape:
                     raise
                 elif m:
-                    result = narray(fill_value, dtype=self.dtype)
+                    result = np.array(fill_value, dtype=self.dtype)
                 else:
                     result = self._data
         return result
@@ -1585,7 +1621,7 @@
         """
         data = ndarray.ravel(self._data)
         if self._mask is not nomask:
-            data = data.compress(numpy.logical_not(ndarray.ravel(self._mask)))
+            data = data.compress(np.logical_not(ndarray.ravel(self._mask)))
         return data
 
 
@@ -1606,7 +1642,7 @@
         # Get the basic components
         (_data, _mask) = (self._data, self._mask)
         # Force the condition to a regular ndarray (forget the missing values...)
-        condition = narray(condition, copy=False, subok=False)
+        condition = np.array(condition, copy=False, subok=False)
         #
         _new = _data.compress(condition, axis=axis, out=out).view(type(self))
         _new._update_from(self)
@@ -1741,7 +1777,7 @@
         # The following 3 lines control the domain filling
         if dom_mask.any():
             other_data = other_data.copy()
-            numpy.putmask(other_data, dom_mask, 1)
+            np.putmask(other_data, dom_mask, 1)
         ndarray.__idiv__(self._data, other_data)
         self._mask = mask_or(self._mask, new_mask)
         return self
@@ -1752,28 +1788,28 @@
         other_data = getdata(other)
         other_mask = getmask(other)
         ndarray.__ipow__(_data, other_data)
-        invalid = numpy.logical_not(numpy.isfinite(_data))
-        new_mask = mask_or(other_mask,invalid)
+        invalid = np.logical_not(np.isfinite(_data))
+        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...
-        numpy.putmask(self._data,invalid,self.fill_value)
+        np.putmask(self._data,invalid,self.fill_value)
         return self
     #............................................
     def __float__(self):
         "Convert to float."
         if self.size > 1:
-            raise TypeError,\
-                   "Only length-1 arrays can be converted to Python scalars"
+            raise TypeError("Only length-1 arrays can be converted "\
+                            "to Python scalars")
         elif self._mask:
             warnings.warn("Warning: converting a masked element to nan.")
-            return numpy.nan
+            return np.nan
         return float(self.item())
 
     def __int__(self):
         "Convert to int."
         if self.size > 1:
-            raise TypeError,\
-                   "Only length-1 arrays can be converted to Python scalars"
+            raise TypeError("Only length-1 arrays can be converted "\
+                            "to Python scalars")
         elif self._mask:
             raise MAError, 'Cannot convert masked element to a Python int.'
         return int(self.item())
@@ -1823,9 +1859,9 @@
                 n = s[axis]
                 t = list(s)
                 del t[axis]
-                return numeric.ones(t) * n
-        n1 = numpy.size(m, axis)
-        n2 = m.astype(int_).sum(axis)
+                return np.ones(t) * n
+        n1 = np.size(m, axis)
+        n2 = m.astype(int).sum(axis)
         if axis is None:
             return (n1-n2)
         else:
@@ -2419,7 +2455,7 @@
                     filler = maximum_fill_value(self)
             else:
                 filler = fill_value
-            idx = numpy.indices(self.shape)
+            idx = np.indices(self.shape)
             idx[axis] = self.filled(filler).argsort(axis=axis,kind=kind,order=order)
             idx_l = idx.tolist()
             tmp_mask = self._mask[idx_l].flat
@@ -2659,7 +2695,7 @@
 isMA = isMaskedArray  #backward compatibility
 # We define the masked singleton as a float for higher precedence...
 # Note that it can be tricky sometimes w/ type comparison
-masked_singleton = MaskedArray(0, dtype=float_, mask=True)
+masked_singleton = MaskedArray(0, dtype=np.float_, mask=True)
 masked = masked_singleton
 
 masked_array = MaskedArray
@@ -2817,7 +2853,7 @@
         try:
             return getattr(MaskedArray, self._methodname).__doc__
         except:
-            return getattr(numpy, self._methodname).__doc__
+            return getattr(np, self._methodname).__doc__
     def __call__(self, a, *args, **params):
         if isinstance(a, MaskedArray):
             return getattr(a, self._methodname).__call__(*args, **params)
@@ -2831,7 +2867,7 @@
         try:
             return method(*args, **params)
         except SystemError:
-            return getattr(numpy,self._methodname).__call__(a, *args, **params)
+            return getattr(np,self._methodname).__call__(a, *args, **params)
 
 all = _frommethod('all')
 anomalies = anom = _frommethod('anom')
@@ -2878,13 +2914,13 @@
     # Get the result and view it as a (subclass of) MaskedArray
     result = umath.power(fa,fb).view(basetype)
     # Find where we're in trouble w/ NaNs and Infs
-    invalid = numpy.logical_not(numpy.isfinite(result.view(ndarray)))
+    invalid = np.logical_not(np.isfinite(result.view(ndarray)))
     # Retrieve some extra attributes if needed
     if isinstance(result,MaskedArray):
         result._update_from(a)
     # Add the initial mask
     if m is not nomask:
-        if numpy.isscalar(result):
+        if np.isscalar(result):
             return masked
         result._mask = m
     # Fix the invalid parts
@@ -2905,7 +2941,7 @@
 #        if m.all():
 #            fa.flat = 1
 #        else:
-#            numpy.putmask(fa,m,1)
+#            np.putmask(fa,m,1)
 #        return masked_array(umath.power(fa, fb), m)
 
 #..............................................................................
@@ -2953,7 +2989,7 @@
     else:
         filler = fill_value
 #    return
-    indx = numpy.indices(a.shape).tolist()
+    indx = np.indices(a.shape).tolist()
     indx[axis] = filled(a,filler).argsort(axis=axis,kind=kind,order=order)
     return a[indx]
 sort.__doc__ = MaskedArray.sort.__doc__
@@ -2962,13 +2998,13 @@
 def compressed(x):
     """Return a 1-D array of all the non-masked data."""
     if getmask(x) is nomask:
-        return numpy.asanyarray(x)
+        return np.asanyarray(x)
     else:
         return x.compressed()
 
 def concatenate(arrays, axis=0):
     "Concatenate the arrays along the given axis."
-    d = numpy.concatenate([getdata(a) for a in arrays], axis)
+    d = np.concatenate([getdata(a) for a in arrays], axis)
     rcls = get_masked_subclass(*arrays)
     data = d.view(rcls)
     # Check whether one of the arrays has a non-empty mask...
@@ -2978,7 +3014,7 @@
     else:
         return data
     # OK, so we have to concatenate the masks
-    dm = numpy.concatenate([getmaskarray(a) for a in arrays], axis)
+    dm = np.concatenate([getmaskarray(a) for a in arrays], axis)
     # If we decide to keep a '_shrinkmask' option, we want to check that ...
     # ... all of them are True, and then check for dm.any()
 #    shrink = numpy.logical_or.reduce([getattr(a,'_shrinkmask',True) for a in arrays])
@@ -3060,21 +3096,21 @@
     if getmask(a) is nomask:
         if valmask is not nomask:
             a._sharedmask = True
-            a.mask = numpy.zeros(a.shape, dtype=bool_)
-            numpy.putmask(a._mask, mask, valmask)
+            a.mask = np.zeros(a.shape, dtype=bool_)
+            np.putmask(a._mask, mask, valmask)
     elif a._hardmask:
         if valmask is not nomask:
             m = a._mask.copy()
-            numpy.putmask(m, mask, valmask)
+            np.putmask(m, mask, valmask)
             a.mask |= m
     else:
         if valmask is nomask:
             valmask = getmaskarray(values)
-        numpy.putmask(a._mask, mask, valmask)
-    numpy.putmask(a._data, mask, valdata)
+        np.putmask(a._mask, mask, valmask)
+    np.putmask(a._data, mask, valdata)
     return
 
-def transpose(a,axes=None):
+def transpose(a, axes=None):
     """Return a view of the array with dimensions permuted according to axes,
     as a masked array.
 
@@ -3108,8 +3144,8 @@
     # We can't use _frommethods here, as N.resize is notoriously whiny.
     m = getmask(x)
     if m is not nomask:
-        m = numpy.resize(m, new_shape)
-    result = numpy.resize(x, new_shape).view(get_masked_subclass(x))
+        m = np.resize(m, new_shape)
+    result = np.resize(x, new_shape).view(get_masked_subclass(x))
     if result.ndim:
         result._mask = m
     return result
@@ -3118,18 +3154,18 @@
 #................................................
 def rank(obj):
     "maskedarray version of the numpy function."
-    return fromnumeric.rank(getdata(obj))
-rank.__doc__ = numpy.rank.__doc__
+    return np.rank(getdata(obj))
+rank.__doc__ = np.rank.__doc__
 #
 def shape(obj):
     "maskedarray version of the numpy function."
-    return fromnumeric.shape(getdata(obj))
-shape.__doc__ = numpy.shape.__doc__
+    return np.shape(getdata(obj))
+shape.__doc__ = np.shape.__doc__
 #
 def size(obj, axis=None):
     "maskedarray version of the numpy function."
-    return fromnumeric.size(getdata(obj), axis)
-size.__doc__ = numpy.size.__doc__
+    return np.size(getdata(obj), axis)
+size.__doc__ = np.size.__doc__
 #................................................
 
 #####--------------------------------------------------------------------------
@@ -3159,26 +3195,26 @@
     elif x is None or y is None:
         raise ValueError, "Either both or neither x and y should be given."
     # Get the condition ...............
-    fc = filled(condition, 0).astype(bool_)
-    notfc = numpy.logical_not(fc)
+    fc = filled(condition, 0).astype(MaskType)
+    notfc = np.logical_not(fc)
     # Get the data ......................................
     xv = getdata(x)
     yv = getdata(y)
     if x is masked:
         ndtype = yv.dtype
-        xm = numpy.ones(fc.shape, dtype=MaskType)
+        xm = np.ones(fc.shape, dtype=MaskType)
     elif y is masked:
         ndtype = xv.dtype
-        ym = numpy.ones(fc.shape, dtype=MaskType)
+        ym = np.ones(fc.shape, dtype=MaskType)
     else:
-        ndtype = numpy.max([xv.dtype, yv.dtype])
+        ndtype = np.max([xv.dtype, yv.dtype])
         xm = getmask(x)
-    d = numpy.empty(fc.shape, dtype=ndtype).view(MaskedArray)
-    numpy.putmask(d._data, fc, xv.astype(ndtype))
-    numpy.putmask(d._data, notfc, yv.astype(ndtype))
-    d._mask = numpy.zeros(fc.shape, dtype=MaskType)
-    numpy.putmask(d._mask, fc, getmask(x))
-    numpy.putmask(d._mask, notfc, getmask(y))
+    d = np.empty(fc.shape, dtype=ndtype).view(MaskedArray)
+    np.putmask(d._data, fc, xv.astype(ndtype))
+    np.putmask(d._data, notfc, yv.astype(ndtype))
+    d._mask = np.zeros(fc.shape, dtype=MaskType)
+    np.putmask(d._mask, fc, getmask(x))
+    np.putmask(d._mask, notfc, getmask(y))
     d._mask |= getmaskarray(condition)
     if not d._mask.any():
         d._mask = nomask
@@ -3203,8 +3239,8 @@
     c = filled(indices, 0)
     masks = [nmask(x) for x in t]
     a = [fmask(x) for x in t]
-    d = numpy.choose(c, a)
-    m = numpy.choose(c, masks)
+    d = np.choose(c, a)
+    m = np.choose(c, masks)
     m = make_mask(mask_or(m, getmask(indices)), copy=0, shrink=True)
     return masked_array(d, mask=m)
 
@@ -3232,17 +3268,13 @@
 
     """
     if out is None:
-        return numpy.round_(a, decimals, out)
+        return np.round_(a, decimals, out)
     else:
-        numpy.round_(getdata(a), decimals, out)
+        np.round_(getdata(a), decimals, out)
         if hasattr(out, '_mask'):
             out._mask = getmask(a)
         return out
 
-def arange(stop, start=None, step=1, dtype=None):
-    "maskedarray version of the numpy function."
-    return numpy.arange(stop, start, step, dtype).view(MaskedArray)
-arange.__doc__ = numpy.arange.__doc__
 
 def inner(a, b):
     "maskedarray version of the numpy function."
@@ -3252,8 +3284,8 @@
         fa.shape = (1,)
     if len(fb.shape) == 0:
         fb.shape = (1,)
-    return numpy.inner(fa, fb).view(MaskedArray)
-inner.__doc__ = numpy.inner.__doc__
+    return np.inner(fa, fb).view(MaskedArray)
+inner.__doc__ = np.inner.__doc__
 inner.__doc__ += doc_note("Masked values are replaced by 0.")
 innerproduct = inner
 
@@ -3261,16 +3293,16 @@
     "maskedarray version of the numpy function."
     fa = filled(a, 0).ravel()
     fb = filled(b, 0).ravel()
-    d = numeric.outer(fa, fb)
+    d = np.outer(fa, fb)
     ma = getmask(a)
     mb = getmask(b)
     if ma is nomask and mb is nomask:
         return masked_array(d)
     ma = getmaskarray(a)
     mb = getmaskarray(b)
-    m = make_mask(1-numeric.outer(1-ma, 1-mb), copy=0)
+    m = make_mask(1-np.outer(1-ma, 1-mb), copy=0)
     return masked_array(d, mask=m)
-outer.__doc__ = numpy.outer.__doc__
+outer.__doc__ = np.outer.__doc__
 outer.__doc__ += doc_note("Masked values are replaced by 0.")
 outerproduct = outer
 
@@ -3311,7 +3343,7 @@
     x = filled(array(d1, copy=0, mask=m), fill_value).astype(float)
     y = filled(array(d2, copy=0, mask=m), 1).astype(float)
     d = umath.less_equal(umath.absolute(x-y), atol + rtol * umath.absolute(y))
-    return fromnumeric.alltrue(fromnumeric.ravel(d))
+    return np.alltrue(np.ravel(d))
 
 #..............................................................................
 def asarray(a, dtype=None):
@@ -3337,26 +3369,6 @@
     return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True)
 
 
-def empty(new_shape, dtype=float):
-    "maskedarray version of the numpy function."
-    return numpy.empty(new_shape, dtype).view(MaskedArray)
-empty.__doc__ = numpy.empty.__doc__
-
-def empty_like(a):
-    "maskedarray version of the numpy function."
-    return numpy.empty_like(a).view(MaskedArray)
-empty_like.__doc__ = numpy.empty_like.__doc__
-
-def ones(new_shape, dtype=float):
-    "maskedarray version of the numpy function."
-    return numpy.ones(new_shape, dtype).view(MaskedArray)
-ones.__doc__ = numpy.ones.__doc__
-
-def zeros(new_shape, dtype=float):
-    "maskedarray version of the numpy function."
-    return numpy.zeros(new_shape, dtype).view(MaskedArray)
-zeros.__doc__ = numpy.zeros.__doc__
-
 #####--------------------------------------------------------------------------
 #---- --- Pickling ---
 #####--------------------------------------------------------------------------
@@ -3406,7 +3418,7 @@
     """
     __doc__ = None
     def __init__(self, funcname):
-        self._func = getattr(numpy, funcname)
+        self._func = getattr(np, funcname)
         self.__doc__ = self.getdoc()
     def getdoc(self):
         "Return the doc of the function (from the doc of the method)."
@@ -3414,10 +3426,15 @@
     def __call__(self, a, *args, **params):
         return self._func.__call__(a, *args, **params).view(MaskedArray)
 
+arange = _convert2ma('arange')
+clip = np.clip
+empty = _convert2ma('empty')
+empty_like = _convert2ma('empty_like')
 frombuffer = _convert2ma('frombuffer')
 fromfunction = _convert2ma('fromfunction')
 identity = _convert2ma('identity')
-indices = numpy.indices
-clip = numpy.clip
+indices = np.indices
+ones = _convert2ma('ones')
+zeros = _convert2ma('zeros')
 
 ###############################################################################

Modified: trunk/numpy/ma/mrecords.py
===================================================================
--- trunk/numpy/ma/mrecords.py	2008-06-03 08:50:08 UTC (rev 5247)
+++ trunk/numpy/ma/mrecords.py	2008-06-03 21:23:15 UTC (rev 5248)
@@ -217,29 +217,6 @@
             return self._fieldmask.view((bool_, len(self.dtype))).all()
     mask = _mask = property(fget=_getmask, fset=_setmask)
     #......................................................
-    def get_fill_value(self):
-        """Return the filling value.
-
-        """
-        if self._fill_value is None:
-            ddtype = self.dtype
-            fillval = _check_fill_value(None, ddtype)
-            self._fill_value = np.array(tuple(fillval), dtype=ddtype)
-        return self._fill_value
-
-    def set_fill_value(self, value=None):
-        """Set the filling value to value.
-
-        If value is None, use a default based on the data type.
-
-        """
-        ddtype = self.dtype
-        fillval = _check_fill_value(value, ddtype)
-        self._fill_value = np.array(tuple(fillval), dtype=ddtype)
-
-    fill_value = property(fget=get_fill_value, fset=set_fill_value,
-                          doc="Filling value.")
-    #......................................................
     def __len__(self):
         "Returns the length"
         # We have more than one record
@@ -306,9 +283,14 @@
         # Case #1.: Basic field ............
         base_fmask = self._fieldmask
         _names = self.dtype.names or []
+        _localdict = self.__dict__
         if attr in _names:
             if val is masked:
-                fval = self.fill_value[attr]
+                _fill_value = _localdict['_fill_value']
+                if _fill_value is not None:
+                    fval = _fill_value[attr]
+                else:
+                    fval = None
                 mval = True
             else:
                 fval = filled(val)
@@ -327,13 +309,16 @@
         _data = self._data
         # We want a field ........
         if isinstance(indx, basestring):
-            #NB: Make sure _sharedmask is True to propagate back to _fieldmask
-            #NB: Don't use _set_mask, there are some copies being made that break propagation
-            #NB: Don't force the mask to nomask, that wrecks easy masking
+            #!!!: Make sure _sharedmask is True to propagate back to _fieldmask
+            #!!!: Don't use _set_mask, there are some copies being made...
+            #!!!: ...that break propagation
+            #!!!: Don't force the mask to nomask, that wrecks easy masking
             obj = _data[indx].view(MaskedArray)
-#            obj._set_mask(_fieldmask[indx])
             obj._mask = _fieldmask[indx]
             obj._sharedmask = True
+            fval = _localdict['_fill_value']
+            if fval is not None:
+                obj._fill_value = fval[indx]
             # Force to masked if the mask is True
             if not obj.ndim and obj._mask:
                 return masked
@@ -429,18 +414,19 @@
             return d
         #
         if fill_value is None:
-            value = _check_fill_value(_localdict['_fill_value'],self.dtype)
+            value = _check_fill_value(_localdict['_fill_value'], d.dtype)
         else:
             value = fill_value
             if np.size(value) == 1:
-                value = [value,] * len(self.dtype)
+                value = np.array(tuple([value,] * len(d.dtype)),
+                                 dtype=d.dtype)
         #
         if self is masked:
             result = np.asanyarray(value)
         else:
             result = d.copy()
-            for (n, v) in zip(d.dtype.names, value):
-                np.putmask(np.asarray(result[n]), np.asarray(fm[n]), v)
+            for n in d.dtype.names:
+                np.putmask(np.asarray(result[n]), np.asarray(fm[n]), value[n])
         return result
     #......................................................
     def harden_mask(self):

Modified: trunk/numpy/ma/tests/test_core.py
===================================================================
--- trunk/numpy/ma/tests/test_core.py	2008-06-03 08:50:08 UTC (rev 5247)
+++ trunk/numpy/ma/tests/test_core.py	2008-06-03 21:23:15 UTC (rev 5248)
@@ -795,12 +795,12 @@
         mtype = [('f',float_),('s','|S3')]
         x = array([(1,'a'),(2,'b'),(numpy.pi,'pi')], dtype=mtype)
         x.fill_value=999
-        assert_equal(x.fill_value,[999.,'999'])
+        assert_equal(x.fill_value.item(),[999.,'999'])
         assert_equal(x['f'].fill_value, 999)
         assert_equal(x['s'].fill_value, '999')
         #
         x.fill_value=(9,'???')
-        assert_equal(x.fill_value, (9,'???'))
+        assert_equal(x.fill_value.item(), (9,'???'))
         assert_equal(x['f'].fill_value, 9)
         assert_equal(x['s'].fill_value, '???')
         #
@@ -865,9 +865,90 @@
         assert_equal(xf.dtype, float_)
         assert_equal(xs.data, ['A', 'b', 'pi'])
         assert_equal(xs.dtype, '|S3')
+    #
+    def test_check_fill_value(self):
+        "Test _check_fill_value"
+        _check_fill_value = numpy.ma.core._check_fill_value
+        #
+        fval = _check_fill_value(0,int)
+        assert_equal(fval, 0)
+        fval = _check_fill_value(None,int)
+        assert_equal(fval, default_fill_value(0))
+        #
+        fval = _check_fill_value(0,"|S3")
+        assert_equal(fval, "0")
+        fval = _check_fill_value(None,"|S3")
+        assert_equal(fval, default_fill_value("|S3"))
+        #
+        fval = _check_fill_value(1e+20,int)
+        assert_equal(fval, default_fill_value(0))
+        
+    def test_check_fill_value_with_fields(self):
+        "Tests _check_fill_value with records"
+        _check_fill_value = numpy.ma.core._check_fill_value
+        #
+        ndtype = [('a',int),('b',float),('c',"|S3")]
+        fval = _check_fill_value([-999,-999.9,"???"], ndtype)
+        assert(isinstance(fval,ndarray))
+        assert_equal(fval.item(), [-999,-999.9,"???"])
+        #
+        fval = _check_fill_value(None, ndtype)
+        assert(isinstance(fval,ndarray))
+        assert_equal(fval.item(), [default_fill_value(0),
+                                   default_fill_value(0.),
+                                   default_fill_value("0")])
+        #
+        fill_val = np.array((-999,-999.9,"???"),dtype=ndtype)
+        fval = _check_fill_value(fill_val, ndtype)
+        assert(isinstance(fval,ndarray))
+        assert_equal(fval.item(), [-999,-999.9,"???"])
+        #
+        fill_val = np.array((-999,-999.9,"???"),
+                            dtype=[("A",int),("B",float),("C","|S3")])
+        fval = _check_fill_value(fill_val, ndtype)
+        assert(isinstance(fval,ndarray))
+        assert_equal(fval.item(), [-999,-999.9,"???"])
+        #
+        fill_value =  np.array((-999,-999.9,"???"), dtype=object)
+        fval = _check_fill_value(fill_val, ndtype)
+        assert(isinstance(fval,ndarray))
+        assert_equal(fval.item(), [-999,-999.9,"???"])
+        #
+        fill_value =  np.array((-999,-999.9,"???"))
+        fval = _check_fill_value(fill_val, ndtype)
+        assert(isinstance(fval,ndarray))
+        assert_equal(fval.item(), [-999,-999.9,"???"])
+        #
+        ndtype = [("a",int)]
+        fval = _check_fill_value(-999, ndtype)
+        assert(isinstance(fval,ndarray))
+        assert_equal(fval.item(), (-999,))
+    #
+    def test_fillvalue_conversion(self):
+        "Tests the behavior of fill_value during conversion"
+        # We had a tailored comment to make sure special attributes are properly
+        # dealt with
+        a = array(['3', '4', '5'])
+        a._basedict.update(comment="updated!")
+        #
+        b = array(a, dtype=int)
+        assert_equal(b._data, [3,4,5])
+        assert_equal(b.fill_value, default_fill_value(0))
+        #
+        b = array(a, dtype=float)
+        assert_equal(b._data, [3,4,5])
+        assert_equal(b.fill_value, default_fill_value(0.))
+        #
+        b = a.astype(int)
+        assert_equal(b._data, [3,4,5])
+        assert_equal(b.fill_value, default_fill_value(0))
+        assert_equal(b._basedict['comment'], "updated!")
+        #
+        b = a.astype([('a','|S3')])
+        assert_equal(b['a']._data, a._data)
+        assert_equal(b['a'].fill_value, a.fill_value)
 
 
-
 #...............................................................................
 
 class TestUfuncs(NumpyTestCase):
@@ -1478,7 +1559,7 @@
         datatype = [('a',int_),('b',float_),('c','|S8')]
         a = masked_array([(1,1.1,'1.1'),(2,2.2,'2.2'),(3,3.3,'3.3')],
                          dtype=datatype)
-        assert_equal(len(a.fill_value), len(datatype))
+        assert_equal(len(a.fill_value.item()), len(datatype))
         #
         b = empty_like(a)
         assert_equal(b.shape, a.shape)
@@ -1590,4 +1671,4 @@
 ###############################################################################
 #------------------------------------------------------------------------------
 if __name__ == "__main__":
-    NumpyTest('numpy.ma.core').run()
+    NumpyTest().run()

Modified: trunk/numpy/ma/testutils.py
===================================================================
--- trunk/numpy/ma/testutils.py	2008-06-03 08:50:08 UTC (rev 5247)
+++ trunk/numpy/ma/testutils.py	2008-06-03 21:23:15 UTC (rev 5248)
@@ -10,16 +10,18 @@
 __date__ = "$Date: 2007-11-13 10:01:14 +0200 (Tue, 13 Nov 2007) $"
 
 
-import numpy as N
-from numpy.core import ndarray
-from numpy.core.numerictypes import float_
+import operator
+
+import numpy as np
+from numpy import ndarray, float_
 import numpy.core.umath as umath
 from numpy.testing import NumpyTest, NumpyTestCase
+import numpy.testing.utils as utils
 from numpy.testing.utils import build_err_msg, rand
 
 import core
 from core import mask_or, getmask, getmaskarray, masked_array, nomask, masked
-from core import filled, equal, less
+from core import fix_invalid, filled, equal, less
 
 #------------------------------------------------------------------------------
 def approx (a, b, fill_value=True, rtol=1.e-5, atol=1.e-8):
@@ -35,12 +37,13 @@
     d1 = filled(a)
     d2 = filled(b)
     if d1.dtype.char == "O" or d2.dtype.char == "O":
-        return N.equal(d1,d2).ravel()
+        return np.equal(d1,d2).ravel()
     x = filled(masked_array(d1, copy=False, mask=m), fill_value).astype(float_)
     y = filled(masked_array(d2, copy=False, mask=m), 1).astype(float_)
-    d = N.less_equal(umath.absolute(x-y), atol + rtol * umath.absolute(y))
+    d = np.less_equal(umath.absolute(x-y), atol + rtol * umath.absolute(y))
     return d.ravel()
 
+
 def almost(a, b, decimal=6, fill_value=True):
     """Returns True if a and b are equal up to decimal places.
 If fill_value is True, masked values considered equal. Otherwise, masked values
@@ -50,10 +53,10 @@
     d1 = filled(a)
     d2 = filled(b)
     if d1.dtype.char == "O" or d2.dtype.char == "O":
-        return N.equal(d1,d2).ravel()
+        return np.equal(d1,d2).ravel()
     x = filled(masked_array(d1, copy=False, mask=m), fill_value).astype(float_)
     y = filled(masked_array(d2, copy=False, mask=m), 1).astype(float_)
-    d = N.around(N.abs(x-y),decimal) <= 10.0**(-decimal)
+    d = np.around(np.abs(x-y),decimal) <= 10.0**(-decimal)
     return d.ravel()
 
 
@@ -69,11 +72,12 @@
     """Asserts that two records are equal. Pretty crude for now."""
     assert_equal(a.dtype, b.dtype)
     for f in a.dtype.names:
-        (af, bf) = (getattr(a,f), getattr(b,f))
+        (af, bf) = (operator.getitem(a,f), operator.getitem(b,f))
         if not (af is masked) and not (bf is masked):
-            assert_equal(getattr(a,f), getattr(b,f))
+            assert_equal(operator.getitem(a,f), operator.getitem(b,f))
     return
 
+
 def assert_equal(actual,desired,err_msg=''):
     """Asserts that two items are equal.
     """
@@ -95,16 +99,18 @@
     # Case #4. arrays or equivalent
     if ((actual is masked) and not (desired is masked)) or \
         ((desired is masked) and not (actual is masked)):
-        msg = build_err_msg([actual, desired], err_msg, header='', names=('x', 'y'))
+        msg = build_err_msg([actual, desired], 
+                            err_msg, header='', names=('x', 'y'))
         raise ValueError(msg)
-    actual = N.array(actual, copy=False, subok=True)
-    desired = N.array(desired, copy=False, subok=True)
-    if actual.dtype.char in "OS" and desired.dtype.char in "OS":
+    actual = np.array(actual, copy=False, subok=True)
+    desired = np.array(desired, copy=False, subok=True)
+    if actual.dtype.char in "OSV" and desired.dtype.char in "OSV":
         return _assert_equal_on_sequences(actual.tolist(),
                                           desired.tolist(),
                                           err_msg='')
     return assert_array_equal(actual, desired, err_msg)
-#.............................
+
+
 def fail_if_equal(actual,desired,err_msg='',):
     """Raises an assertion error if two items are equal.
     """
@@ -120,119 +126,91 @@
         for k in range(len(desired)):
             fail_if_equal(actual[k], desired[k], 'item=%r\n%s' % (k,err_msg))
         return
-    if isinstance(actual, N.ndarray) or isinstance(desired, N.ndarray):
+    if isinstance(actual, np.ndarray) or isinstance(desired, np.ndarray):
         return fail_if_array_equal(actual, desired, err_msg)
     msg = build_err_msg([actual, desired], err_msg)
     assert desired != actual, msg
 assert_not_equal = fail_if_equal
-#............................
-def assert_almost_equal(actual,desired,decimal=7,err_msg=''):
+
+
+def assert_almost_equal(actual, desired, decimal=7, err_msg='', verbose=True):
     """Asserts that two items are almost equal.
     The test is equivalent to abs(desired-actual) < 0.5 * 10**(-decimal)
     """
-    if isinstance(actual, N.ndarray) or isinstance(desired, N.ndarray):
-        return assert_array_almost_equal(actual, desired, decimal, err_msg)
-    msg = build_err_msg([actual, desired], err_msg)
+    if isinstance(actual, np.ndarray) or isinstance(desired, np.ndarray):
+        return assert_array_almost_equal(actual, desired, decimal=decimal, 
+                                         err_msg=err_msg, verbose=verbose)
+    msg = build_err_msg([actual, desired], 
+                        err_msg=err_msg, verbose=verbose)
     assert round(abs(desired - actual),decimal) == 0, msg
-#............................
-def assert_array_compare(comparison, x, y, err_msg='', header='',
+
+
+assert_close = assert_almost_equal
+
+
+def assert_array_compare(comparison, x, y, err_msg='', verbose=True, header='',
                          fill_value=True):
     """Asserts that a comparison relation between two masked arrays is satisfied
     elementwise."""
+    # Fill the data first
     xf = filled(x)
     yf = filled(y)
+    # Allocate a common mask and refill
     m = mask_or(getmask(x), getmask(y))
-
-    x = masked_array(xf, copy=False, subok=False, mask=m).filled(fill_value)
-    y = masked_array(yf, copy=False, subok=False, mask=m).filled(fill_value)
-
+    x = masked_array(xf, copy=False, mask=m)
+    y = masked_array(yf, copy=False, mask=m)
     if ((x is masked) and not (y is masked)) or \
         ((y is masked) and not (x is masked)):
-        msg = build_err_msg([x, y], err_msg, header=header, names=('x', 'y'))
+        msg = build_err_msg([x, y], err_msg=err_msg, verbose=verbose, 
+                            header=header, names=('x', 'y'))
         raise ValueError(msg)
+    # OK, now run the basic tests on filled versions
+    return utils.assert_array_compare(comparison, 
+                                      x.filled(fill_value), y.filled(fill_value), 
+                                      err_msg=err_msg, 
+                                      verbose=verbose, header=header)
 
-    if (x.dtype.char != "O") and (x.dtype.char != "S"):
-        x = x.astype(float_)
-        if isinstance(x, N.ndarray) and x.size > 1:
-            x[N.isnan(x)] = 0
-        elif N.isnan(x):
-            x = 0
-    if (y.dtype.char != "O") and (y.dtype.char != "S"):
-        y = y.astype(float_)
-        if isinstance(y, N.ndarray) and y.size > 1:
-            y[N.isnan(y)] = 0
-        elif N.isnan(y):
-            y = 0
-    try:
-        cond = (x.shape==() or y.shape==()) or x.shape == y.shape
-        if not cond:
-            msg = build_err_msg([x, y],
-                                err_msg
-                                + '\n(shapes %s, %s mismatch)' % (x.shape,
-                                                                  y.shape),
-                                header=header,
-                                names=('x', 'y'))
-            assert cond, msg
-        val = comparison(x,y)
-        if m is not nomask and fill_value:
-            val = masked_array(val, mask=m, copy=False)
-        if isinstance(val, bool):
-            cond = val
-            reduced = [0]
-        else:
-            reduced = val.ravel()
-            cond = reduced.all()
-            reduced = reduced.tolist()
-        if not cond:
-            match = 100-100.0*reduced.count(1)/len(reduced)
-            msg = build_err_msg([x, y],
-                                err_msg
-                                + '\n(mismatch %s%%)' % (match,),
-                                header=header,
-                                names=('x', 'y'))
-            assert cond, msg
-    except ValueError:
-        msg = build_err_msg([x, y], err_msg, header=header, names=('x', 'y'))
-        raise ValueError(msg)
-#............................
-def assert_array_equal(x, y, err_msg=''):
+
+def assert_array_equal(x, y, err_msg='', verbose=True):
     """Checks the elementwise equality of two masked arrays."""
-    assert_array_compare(equal, x, y, err_msg=err_msg,
+    assert_array_compare(equal, x, y, err_msg=err_msg, verbose=verbose,
                          header='Arrays are not equal')
-##............................
-def fail_if_array_equal(x, y, err_msg=''):
+
+
+def fail_if_array_equal(x, y, err_msg='', verbose=True):
     "Raises an assertion error if two masked arrays are not equal (elementwise)."
     def compare(x,y):
-
-        return (not N.alltrue(approx(x, y)))
-    assert_array_compare(compare, x, y, err_msg=err_msg,
+        return (not np.alltrue(approx(x, y)))
+    assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose,
                          header='Arrays are not equal')
-#............................
-def assert_array_approx_equal(x, y, decimal=6, err_msg=''):
+
+
+def assert_array_approx_equal(x, y, decimal=6, err_msg='', verbose=True):
     """Checks the elementwise equality of two masked arrays, up to a given
     number of decimals."""
     def compare(x, y):
         "Returns the result of the loose comparison between x and y)."
         return approx(x,y, rtol=10.**-decimal)
-    assert_array_compare(compare, x, y, err_msg=err_msg,
+    assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose,
                          header='Arrays are not almost equal')
-#............................
-def assert_array_almost_equal(x, y, decimal=6, err_msg=''):
+
+
+def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True):
     """Checks the elementwise equality of two masked arrays, up to a given
     number of decimals."""
     def compare(x, y):
         "Returns the result of the loose comparison between x and y)."
         return almost(x,y,decimal)
-    assert_array_compare(compare, x, y, err_msg=err_msg,
+    assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose,
                          header='Arrays are not almost equal')
-#............................
-def assert_array_less(x, y, err_msg=''):
+
+
+def assert_array_less(x, y, err_msg='', verbose=True):
     "Checks that x is smaller than y elementwise."
-    assert_array_compare(less, x, y, err_msg=err_msg,
+    assert_array_compare(less, x, y, err_msg=err_msg, verbose=verbose,
                          header='Arrays are not less-ordered')
-#............................
-assert_close = assert_almost_equal
-#............................
+
+
 def assert_mask_equal(m1, m2):
     """Asserts the equality of two masks."""
     if m1 is nomask:
@@ -240,6 +218,3 @@
     if m2 is nomask:
         assert(m1 is nomask)
     assert_array_equal(m1, m2)
-
-if __name__ == '__main__':
-    pass




More information about the Numpy-svn mailing list