On Sunday 20 January 2008 16:32:40 you wrote: > Pierre, > > The attached script shows how one can make a masked array with different > dimensions for the mask than for the data. I presume this is a bug. It > is triggered by the present code in the matplotlib quiver function.
Yep, bug indeed. Thanks for pointing that out ! The following patch should take care of the problem. (In short, a getmask function was used instead of getmaskarray). Note that the patch takes also into account elements I had sent to Stefan 2 weeks ago, that were not ported yet to the SVN: I still can't commit to the numpy/branches/maskedarray. Let me know how it works, and thanks again for your time. P.
Index: /home/backtopop/workspace/numpy_maskedarray/numpy/ma/core.py =================================================================== --- /home/backtopop/workspace/numpy_maskedarray/numpy/ma/core.py (revision 4737) +++ /home/backtopop/workspace/numpy_maskedarray/numpy/ma/core.py (working copy) @@ -14,42 +14,47 @@ :author: Pierre Gerard-Marchant :contact: pierregm_at_uga_dot_edu +:version: $Id: core.py 341 2007-12-25 16:23:05Z backtopop $ """ -__author__ = "Pierre GF Gerard-Marchant" +__author__ = "Pierre GF Gerard-Marchant ($Author: backtopop $)" +__version__ = '1.0' +__revision__ = "$Revision: 341 $" +__date__ = '$Date: 2007-12-25 11:23:05 -0500 (Tue, 25 Dec 2007) $' + __docformat__ = "restructuredtext en" __all__ = ['MAError', 'MaskType', 'MaskedArray', 'bool_', 'complex_', 'float_', 'int_', 'object_', 'abs', 'absolute', 'add', 'all', 'allclose', 'allequal', 'alltrue', - 'amax', 'amin', 'anom', 'anomalies', 'any', 'arange', - 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', - 'arctanh', 'argmax', 'argmin', 'argsort', 'around', - 'array', 'asarray','asanyarray', + 'amax', 'amin', 'anom', 'anomalies', 'any', 'arange', + 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', + 'arctanh', 'argmax', 'argmin', 'argsort', 'around', + 'array', 'asarray','asanyarray', 'bitwise_and', 'bitwise_or', 'bitwise_xor', 'ceil', 'choose', 'compressed', 'concatenate', 'conjugate', - 'cos', 'cosh', 'count', + 'cos', 'cosh', 'count', 'default_fill_value', 'diagonal', 'divide', 'dump', 'dumps', 'empty', 'empty_like', 'equal', 'exp', 'fabs', 'fmod', 'filled', 'floor', 'floor_divide','fix_invalid', 'getmask', 'getmaskarray', 'greater', 'greater_equal', 'hypot', 'ids', 'inner', 'innerproduct', - 'isMA', 'isMaskedArray', 'is_mask', 'is_masked', 'isarray', + 'isMA', 'isMaskedArray', 'is_mask', 'is_masked', 'isarray', 'left_shift', 'less', 'less_equal', 'load', 'loads', 'log', 'log10', - 'logical_and', 'logical_not', 'logical_or', 'logical_xor', + 'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'make_mask', 'make_mask_none', 'mask_or', 'masked', - 'masked_array', 'masked_equal', 'masked_greater', - 'masked_greater_equal', 'masked_inside', 'masked_less', - 'masked_less_equal', 'masked_not_equal', 'masked_object', - 'masked_outside', 'masked_print_option', 'masked_singleton', - 'masked_values', 'masked_where', 'max', 'maximum', 'mean', 'min', - 'minimum', 'multiply', + 'masked_array', 'masked_equal', 'masked_greater', + 'masked_greater_equal', 'masked_inside', 'masked_less', + 'masked_less_equal', 'masked_not_equal', 'masked_object', + 'masked_outside', 'masked_print_option', 'masked_singleton', + 'masked_values', 'masked_where', 'max', 'maximum', 'mean', 'min', + 'minimum', 'multiply', 'negative', 'nomask', 'nonzero', 'not_equal', 'ones', 'outer', 'outerproduct', 'power', 'product', 'ptp', 'put', 'putmask', 'rank', 'ravel', 'remainder', 'repeat', 'reshape', 'resize', - 'right_shift', 'round_', + 'right_shift', 'round_', 'shape', 'sin', 'sinh', 'size', 'sometrue', 'sort', 'sqrt', 'std', - 'subtract', 'sum', 'swapaxes', + 'subtract', 'sum', 'swapaxes', 'take', 'tan', 'tanh', 'transpose', 'true_divide', 'var', 'where', 'zeros'] @@ -178,6 +183,26 @@ else: raise TypeError, 'Unsuitable type for calculating minimum.' + +def _check_fill_value(fill_value, dtype): + descr = numpy.dtype(dtype).descr + if fill_value is None: + if len(descr) > 1: + fill_value = [default_fill_value(numeric.dtype(d[1])) + for d in descr] + else: + fill_value = default_fill_value(dtype) + else: + fval = numpy.resize(narray(fill_value,copy=False,dtype=object_), + len(descr)) + if len(descr) > 1: + fill_value = [numpy.asarray(f).astype(d[1]).item() + for (f,d) in zip(fval, descr)] + else: + fill_value = narray(fval, copy=False, dtype=dtype).item() + return fill_value + + def set_fill_value(a, fill_value): """Set the filling value of a, if a is a masked array. Otherwise, do nothing. @@ -187,7 +212,7 @@ """ if isinstance(a, MaskedArray): - a.set_fill_value(fill_value) + a._fill_value = _check_fill_value(fill_value, a.dtype) return def get_fill_value(a): @@ -212,6 +237,7 @@ return t1 return None + #####-------------------------------------------------------------------------- def filled(a, value = None): """Return a as an array with masked data replaced by value. If @@ -1058,7 +1084,7 @@ Construction: x = MaskedArray(data, mask=nomask, dtype=None, copy=True, - fill_value=None, keep_mask=True, hard_mask=False, shrink=True) + fill_value=None, keep_mask = True, hard_mask=False, shrink=True) *Parameters*: data : {var} @@ -1162,11 +1188,7 @@ _data._sharedmask = False # Update fill_value....... - if fill_value is None: - _data._fill_value = getattr(data, '_fill_value', - default_fill_value(_data)) - else: - _data._fill_value = fill_value + _data._fill_value = _check_fill_value(fill_value, _data.dtype) # Process extra options .. _data._hardmask = hard_mask _data._baseclass = _baseclass @@ -1210,7 +1232,7 @@ if context is not None: result._mask = result._mask.copy() (func, args, _) = context - m = reduce(mask_or, [getmask(arg) for arg in args]) + m = reduce(mask_or, [getmaskarray(arg) for arg in args]) # Get the domain mask................ domain = ufunc_domain.get(func, None) if domain is not None: @@ -1266,6 +1288,10 @@ dout = dout.view(type(self)) # Inherit attributes from self 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] # Update the mask if needed if m is not nomask: if isinstance(indx, basestring): @@ -1459,9 +1485,7 @@ If value is None, use a default based on the data type. """ - if value is None: - value = default_fill_value(self) - self._fill_value = value + self._fill_value = _check_fill_value(value,self.dtype) fill_value = property(fget=get_fill_value, fset=set_fill_value, doc="Filling value.") @@ -2769,7 +2793,6 @@ for x in arrays: if getmask(x) is not nomask: break - else: return data # OK, so we have to concatenate the masks dm = numpy.concatenate([getmaskarray(a) for a in arrays], axis) @@ -3207,4 +3230,5 @@ def loads(strg): "Load a pickle from the current string.""" return cPickle.loads(strg) - + + \ No newline at end of file Index: /home/backtopop/workspace/numpy_maskedarray/numpy/ma/tests/test_core.py =================================================================== --- /home/backtopop/workspace/numpy_maskedarray/numpy/ma/tests/test_core.py (revision 4737) +++ /home/backtopop/workspace/numpy_maskedarray/numpy/ma/tests/test_core.py (working copy) @@ -3,12 +3,12 @@ :author: Pierre Gerard-Marchant :contact: pierregm_at_uga_dot_edu -:version: $Id: test_core.py 3473 2007-10-29 15:18:13Z jarrod.millman $ +:version: $Id: test_core.py 344 2008-01-06 21:35:14Z backtopop $ """ -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" +__author__ = "Pierre GF Gerard-Marchant ($Author: backtopop $)" __version__ = '1.0' -__revision__ = "$Revision: 3473 $" -__date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' +__revision__ = "$Revision: 344 $" +__date__ = '$Date: 2008-01-06 16:35:14 -0500 (Sun, 06 Jan 2008) $' import types import warnings @@ -32,18 +32,6 @@ from test_old_ma import * restore_path() -class TestNoMask(NumpyTestCase): - def test_no_inplace(self): - x = nomask - y = x - x += 1 - assert x != y - - def test_no_copy(self): - x = nomask - y = x.copy() - assert x is y - #.............................................................................. class TestMA(NumpyTestCase): "Base test class for MaskedArrays." @@ -352,6 +340,11 @@ assert(xm[0].ptp() is masked) assert(xm[0].ptp(0) is masked) assert(xm[0].ptp(-1) is masked) + # + x = array([1,2,3], mask=True) + assert(x.min() is masked) + assert(x.max() is masked) + assert(x.ptp() is masked) #........................ def test_addsumprod (self): "Tests add, sum, product." @@ -390,6 +383,16 @@ xmym = concatenate((xm,ym),1) assert_equal(numpy.concatenate((x,y),1), xmym) assert_equal(numpy.concatenate((xm.mask,ym.mask),1), xmym._mask) + # + x=zeros(2) + y=array(ones(2),mask=[False,True]) + z = concatenate((x,y)) + assert_array_equal(z,[0,0,1,1]) + assert_array_equal(z.mask,[False,False,False,True]) + z = concatenate((y,x)) + assert_array_equal(z,[1,1,0,0]) + assert_array_equal(z.mask,[False,True,False,False]) + #........................ def test_indexing(self): "Tests conversions and indexing" @@ -756,6 +759,19 @@ dma_3 = MaskedArray(dma_1, mask=[1,0,0,0]*6) fail_if_equal(dma_3.mask, dma_1.mask) + def test_backwards(self): + "Tests backward compatibility with numpy.core.ma" + import numpy.core.ma as nma + x = nma.arange(5) + x[2] = nma.masked + X = masked_array(x, mask=x._mask) + assert_equal(X._mask, x.mask) + assert_equal(X._data, x._data) + X = masked_array(x) + assert_equal(X._data, x._data) + assert_equal(X._mask, x.mask) + assert_equal(getmask(x), [0,0,1,0,0]) + def test_pickling(self): "Tests pickling" import cPickle @@ -774,10 +790,27 @@ assert(isinstance(a_pickled._data,numpy.matrix)) # def test_fillvalue(self): - "Check that we don't lose the fill_value" + "Having fun with the fill_value" data = masked_array([1,2,3],fill_value=-999) series = data[[0,2,1]] assert_equal(series._fill_value, data._fill_value) + # + 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['f'].fill_value, 999) + assert_equal(x['s'].fill_value, '999') + # + x.fill_value=(9,'???') + assert_equal(x.fill_value, (9,'???')) + assert_equal(x['f'].fill_value, 9) + assert_equal(x['s'].fill_value, '???') + # + x = array([1,2,3.1]) + x.fill_value = 999 + assert_equal(numpy.asarray(x.fill_value).dtype, float_) + assert_equal(x.fill_value, 999.) # def test_asarray(self): (x, y, a10, m1, m2, xm, ym, z, zm, xf) = self.d @@ -793,6 +826,7 @@ assert_equal(data_fixed._mask, [1., 0., 1.]) # def test_imag_real(self): + "Check complex" xx = array([1+10j,20+2j], mask=[1,0]) assert_equal(xx.imag,[10,2]) assert_equal(xx.imag.filled(), [1e+20,2]) @@ -800,6 +834,29 @@ assert_equal(xx.real,[1,20]) assert_equal(xx.real.filled(), [1e+20,20]) assert_equal(xx.real.dtype, xx._data.real.dtype) + # + def test_ndmin(self): + "Check the use of ndmin" + x = array([1,2,3],mask=[1,0,0], ndmin=2) + assert_equal(x.shape,(1,3)) + assert_equal(x._data,[[1,2,3]]) + assert_equal(x._mask,[[1,0,0]]) + # + def test_record(self): + "Check record access" + mtype = [('f',float_),('s','|S3')] + x = array([(1,'a'),(2,'b'),(numpy.pi,'pi')], dtype=mtype) + x[1] = masked + # + (xf, xs) = (x['f'], x['s']) + assert_equal(xf.data, [1,2,numpy.pi]) + assert_equal(xf.mask, [0,1,0]) + assert_equal(xf.dtype, float_) + assert_equal(xs.data, ['a', 'b', 'pi']) + assert_equal(xs.mask, [0,1,0]) + assert_equal(xs.dtype, '|S3') + # + #............................................................................... @@ -1348,37 +1405,7 @@ putmask(mxx, mask, values) assert_equal(mxx, [1,2,30,4,5,60]) - def test_ndmin(self): - x = array([1,2,3],mask=[1,0,0], ndmin=2) - assert_equal(x.shape,(1,3)) - assert_equal(x._data,[[1,2,3]]) - assert_equal(x._mask,[[1,0,0]]) - def test_sumprod_masked(self): - x = masked_array([1,2,3], mask=True) - z = x.min() - assert(x.sum() is masked) - assert(x.prod() is masked) - - def test_fancy_dtype(self): - mtype = [('f',float_),('s','|S3')] - x = array([(1,'a'),(2,'b'),(numpy.pi,'pi')], dtype=mtype) - x[1] = masked - x['f'] = 17 - - def test_concat(self): - x=zeros(2) - y=array(ones(2),mask=[False,True]) - - z = concatenate((x,y)) - assert_array_equal(z,[0,0,1,1]) - assert_array_equal(z.mask,[False,False,False,True]) - - z = concatenate((y,x)) - assert_array_equal(z,[1,1,0,0]) - assert_array_equal(z.mask,[False,True,False,False]) - - #.............................................................................. ############################################################################### Index: /home/backtopop/workspace/numpy_maskedarray/numpy/ma/mrecords.py =================================================================== --- /home/backtopop/workspace/numpy_maskedarray/numpy/ma/mrecords.py (revision 4737) +++ /home/backtopop/workspace/numpy_maskedarray/numpy/ma/mrecords.py (working copy) @@ -3,12 +3,12 @@ :author: Pierre Gerard-Marchant :contact: pierregm_at_uga_dot_edu -:version: $Id: mrecords.py 3473 2007-10-29 15:18:13Z jarrod.millman $ +:version: $Id: mrecords.py 344 2008-01-06 21:35:14Z backtopop $ """ -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" +__author__ = "Pierre GF Gerard-Marchant ($Author: backtopop $)" __version__ = '1.0' -__revision__ = "$Revision: 3473 $" -__date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' +__revision__ = "$Revision: 344 $" +__date__ = '$Date: 2008-01-06 16:35:14 -0500 (Sun, 06 Jan 2008) $' import sys import types @@ -34,6 +34,8 @@ from numpy.ma.core import default_fill_value, masked_print_option import warnings +import logging +logging.basicConfig(level=logging.DEBUG, format='%(name)-15s %(levelname)s %(message)s',) reserved_fields = ['_data','_mask','_fieldmask', 'dtype'] @@ -249,7 +251,7 @@ _localdict = self.__dict__ _data = self._data # We want a field ........ - if isinstance(indx, str): + if isinstance(indx, basestring): obj = _data[indx].view(MaskedArray) obj._set_mask(_localdict['_fieldmask'][indx]) # Force to nomask if the mask is empty @@ -693,10 +695,10 @@ ################################################################################ if __name__ == '__main__': import numpy as N - from numpy.ma.testutils import assert_equal + from maskedarray.testutils import assert_equal if 1: d = N.arange(5) - m = numpy.ma.make_mask([1,0,0,1,1]) + m = maskedarray.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 = masked_array(base_d, mask=base_m).T
_______________________________________________ Numpy-discussion mailing list Numpy-discussion@scipy.org http://projects.scipy.org/mailman/listinfo/numpy-discussion