From numpy-svn at scipy.org Fri Feb 1 06:18:01 2008 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 1 Feb 2008 05:18:01 -0600 (CST) Subject: [Numpy-svn] r4766 - trunk/numpy/core/tests Message-ID: <20080201111801.2E04839C442@new.scipy.org> Author: stefan Date: 2008-02-01 05:17:39 -0600 (Fri, 01 Feb 2008) New Revision: 4766 Modified: trunk/numpy/core/tests/test_regression.py Log: Add regression test for searchsorted on variable-length arrays. Modified: trunk/numpy/core/tests/test_regression.py =================================================================== --- trunk/numpy/core/tests/test_regression.py 2008-01-31 19:19:26 UTC (rev 4765) +++ trunk/numpy/core/tests/test_regression.py 2008-02-01 11:17:39 UTC (rev 4766) @@ -775,5 +775,10 @@ assert_equal(np.fromstring("12:09:09", dtype=int, sep=":"), [12,9,9]) + def check_searchsorted_variable_length(self, level=rlevel): + x = np.array(['a','aa','b']) + y = np.array(['d','e']) + assert_equal(x.searchsorted(y), [3,3]) + if __name__ == "__main__": NumpyTest().run() From numpy-svn at scipy.org Fri Feb 1 18:40:40 2008 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 1 Feb 2008 17:40:40 -0600 (CST) Subject: [Numpy-svn] r4767 - in branches/maskedarray/numpy/ma: . tests Message-ID: <20080201234040.70CB239C013@new.scipy.org> Author: pierregm Date: 2008-02-01 17:40:35 -0600 (Fri, 01 Feb 2008) New Revision: 4767 Modified: branches/maskedarray/numpy/ma/core.py branches/maskedarray/numpy/ma/mrecords.py branches/maskedarray/numpy/ma/tests/test_core.py branches/maskedarray/numpy/ma/tests/test_mrecords.py Log: maskedarray.core: tolist : make sure that a masked record is output as a tuple of None maskedarray.mrecords: * introduced mrecarray as the equivalent of recarray w/ fieldmask * simplified fromarrays/fromrecords Modified: branches/maskedarray/numpy/ma/core.py =================================================================== --- branches/maskedarray/numpy/ma/core.py 2008-02-01 11:17:39 UTC (rev 4766) +++ branches/maskedarray/numpy/ma/core.py 2008-02-01 23:40:35 UTC (rev 4767) @@ -191,8 +191,8 @@ else: fill_value = default_fill_value(dtype) else: - fval = numpy.resize(narray(fill_value,copy=False,dtype=object_), - len(descr)) + 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)] @@ -2491,15 +2491,23 @@ if fill_value is not None: return self.filled(fill_value).tolist() result = self.filled().tolist() - if self._mask is nomask: + # Set temps to save time when dealing w/ mrecarrays... + _mask = self._mask + if _mask is nomask: return result - if self.ndim == 0: - return [None] - elif self.ndim == 1: - maskedidx = self._mask.nonzero()[0].tolist() - [operator.setitem(result,i,None) for i in maskedidx] + nbdims = self.ndim + dtypesize = len(self.dtype) + if nbdims == 0: + return tuple([None]*dtypesize) + elif nbdims == 1: + maskedidx = _mask.nonzero()[0].tolist() + if dtypesize: + nodata = tuple([None]*dtypesize) + else: + nodata = None + [operator.setitem(result,i,nodata) for i in maskedidx] else: - for idx in zip(*[i.tolist() for i in self._mask.nonzero()]): + for idx in zip(*[i.tolist() for i in _mask.nonzero()]): tmp = result for i in idx[:-1]: tmp = tmp[i] Modified: branches/maskedarray/numpy/ma/mrecords.py =================================================================== --- branches/maskedarray/numpy/ma/mrecords.py 2008-02-01 11:17:39 UTC (rev 4766) +++ branches/maskedarray/numpy/ma/mrecords.py 2008-02-01 23:40:35 UTC (rev 4767) @@ -1,35 +1,49 @@ """mrecords -Defines a class of record arrays supporting masked arrays. +Defines the equivalent of recarrays for maskedarray. +Masked arrays already support named fields, but masking works only by records. +By comparison, mrecarrays support masking individual fields. + :author: Pierre Gerard-Marchant """ +#TODO: We should make sure that no field is called '_mask','mask','_fieldmask', +#TODO: ...or whatever restricted keywords. +#TODO: An idea would be to no bother in the first place, and then rename the +#TODO: invalid fields with a trailing underscore... +#TODO: Maybe we could just overload the parser function ? + + __author__ = "Pierre GF Gerard-Marchant" import sys import types import numpy -from numpy import bool_, complex_, float_, int_, str_, object_ +from numpy import bool_, complex_, float_, int_, str_, object_, dtype from numpy import array as narray import numpy.core.numeric as numeric import numpy.core.numerictypes as ntypes from numpy.core.defchararray import chararray -from numpy.core.records import find_duplicate - -from numpy.core.records import format_parser, record, recarray +from numpy.core.records import find_duplicate, format_parser, record, recarray from numpy.core.records import fromarrays as recfromarrays +from numpy.core.records import fromrecords as recfromrecords ndarray = numeric.ndarray _byteorderconv = numpy.core.records._byteorderconv _typestr = ntypes._typestr import numpy.ma -from numpy.ma import MaskedArray, masked, nomask, masked_array,\ - make_mask, mask_or, getmask, getmaskarray, filled +from numpy.ma import MAError, MaskedArray, masked, nomask, masked_array,\ + make_mask, mask_or, getdata, getmask, getmaskarray, filled from numpy.ma.core import default_fill_value, masked_print_option +_check_fill_value = numpy.ma.core._check_fill_value import warnings +__all__ = ['MaskedRecords','mrecarray', + 'fromarrays','fromrecords','fromtextfile','addfield', + ] + reserved_fields = ['_data','_mask','_fieldmask', 'dtype'] def _getformats(data): @@ -80,7 +94,13 @@ return numeric.dtype(ndescr) +def _get_fieldmask(self): + mdescr = [(n,'|b1') for n in self.dtype.names] + fdmask = numpy.empty(self.shape, dtype=mdescr) + fdmask.flat = tuple([False]*len(mdescr)) + return fdmask + class MaskedRecords(MaskedArray, object): """ @@ -96,89 +116,131 @@ """ _defaultfieldmask = nomask _defaulthardmask = False - def __new__(cls, data, mask=nomask, dtype=None, - hard_mask=False, fill_value=None, -# offset=0, strides=None, + #............................................ + def __new__(cls, shape, dtype=None, buf=None, offset=0, strides=None, formats=None, names=None, titles=None, - byteorder=None, aligned=False): - # Get the new descriptor ................ - if dtype is not None: - descr = numeric.dtype(dtype) + byteorder=None, aligned=False, + mask=nomask, hard_mask=False, fill_value=None, keep_mask=True, + copy=False, + **options): + # + self = recarray.__new__(cls, shape, dtype=dtype, buf=buf, offset=offset, + strides=strides, formats=formats, + byteorder=byteorder, aligned=aligned,) +# self = self.view(cls) + # + mdtype = [(k,'|b1') for (k,_) in self.dtype.descr] + if mask is nomask or not numpy.size(mask): + if not keep_mask: + self._fieldmask = tuple([False]*len(mdtype)) else: - if formats is None: - formats = _getformats(data) - parsed = format_parser(formats, names, titles, aligned, byteorder) - descr = parsed._descr - if names is not None: - descr = _checknames(descr,names) - _names = descr.names - mdescr = [(n,'|b1') for n in _names] - # get the shape ......................... - try: - shape = numeric.asarray(data[0]).shape - except IndexError: - shape = len(data.dtype) - if isinstance(shape, int): - shape = (shape,) - # Construct the _data recarray .......... - if isinstance(data, record): - _data = numeric.asarray(data).view(recarray) - _fieldmask = mask - elif isinstance(data, MaskedRecords): - _data = data._data - _fieldmask = data._fieldmask - elif isinstance(data, recarray): - _data = data - if mask is nomask: - _fieldmask = data.astype(mdescr) - _fieldmask.flat = tuple([False]*len(mdescr)) + mask = narray(mask, copy=copy) + if mask.shape != self.shape: + (nd, nm) = (self.size, mask.size) + if nm == 1: + mask = numpy.resize(mask, self.shape) + elif nm == nd: + mask = numpy.reshape(mask, self.shape) + else: + msg = "Mask and data not compatible: data size is %i, "+\ + "mask size is %i." + raise MAError(msg % (nd, nm)) + copy = True + if not keep_mask: + self.__setmask__(mask) + self._sharedmask = True else: - _fieldmask = mask - elif (isinstance(data, (tuple, numpy.void)) or\ - hasattr(data,'__len__') and isinstance(data[0], (tuple, numpy.void))): - data = numeric.array(data, dtype=descr).view(recarray) - _data = data - if mask is nomask: - _fieldmask = data.astype(mdescr) - _fieldmask.flat = tuple([False]*len(mdescr)) - else: - _fieldmask = mask - else: - _data = recarray(shape, dtype=descr) - _fieldmask = recarray(shape, dtype=mdescr) - for (n,v) in zip(_names, data): - _data[n] = numeric.asarray(v).view(ndarray) - _fieldmask[n] = getmaskarray(v) - #........................................ - _data = _data.view(cls) - _data._fieldmask = _fieldmask - _data._hardmask = hard_mask - if fill_value is None: - _data._fill_value = [default_fill_value(numeric.dtype(d[1])) - for d in descr.descr] - else: - _data._fill_value = fill_value - return _data - + if mask.dtype == mdtype: + _fieldmask = mask + else: + _fieldmask = narray([tuple([m]*len(mdtype)) for m in mask], + dtype=mdtype) + self._fieldmask = _fieldmask + return self + #...................................................... def __array_finalize__(self,obj): - if isinstance(obj, MaskedRecords): - self.__dict__.update(_fieldmask=obj._fieldmask, - _hardmask=obj._hardmask, - _fill_value=obj._fill_value - ) - else: - self.__dict__.update(_fieldmask = nomask, - _hardmask = False, - fill_value = None - ) + # Make sure we have a _fieldmask by default .. + _fieldmask = getattr(obj, '_fieldmask', None) + if _fieldmask is None: + mdescr = [(n,'|b1') for (n,_) in self.dtype.descr] + _fieldmask = numpy.empty(self.shape, dtype=mdescr).view(recarray) + _fieldmask.flat = tuple([False]*len(mdescr)) + # Update some of the attributes + attrdict = dict(_fieldmask=_fieldmask, + _hardmask=getattr(obj,'_hardmask',False), + _fill_value=getattr(obj,'_fill_value',None)) + self.__dict__.update(attrdict) + # Finalize as a regular maskedarray ..... + # Note: we can't call MaskedArray.__array_finalize__, it chokes pickling + self._update_from(obj) + # Update special attributes ... + self._basedict = getattr(obj, '_basedict', getattr(obj, '__dict__', None)) + if self._basedict is not None: + self.__dict__.update(self._basedict) return - + #...................................................... def _getdata(self): "Returns the data as a recarray." return self.view(recarray) _data = property(fget=_getdata) + #...................................................... + def __setmask__(self, mask): + "Sets the mask and update the fieldmask." + names = self.dtype.names + fmask = self.__dict__['_fieldmask'] + newmask = make_mask(mask, copy=False) + if names is not None: + if self._hardmask: + for n in names: + fmask[n].__ior__(newmask) + else: + for n in names: + fmask[n].flat = newmask + return + _setmask = __setmask__ + # + def _getmask(self): + """Return the mask of the mrecord. + A record is masked when all the fields are masked. + + """ + if self.size > 1: + return self._fieldmask.view((bool_, len(self.dtype))).all(1) + else: + return self._fieldmask.view((bool_, len(self.dtype))).all() + _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 = narray(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 = narray(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 + if self.ndim: + return len(self._data) + # We have only one record: return the nb of fields + return len(self.dtype) + #...................................................... def __getattribute__(self, attr): "Returns the given attribute." try: @@ -215,7 +277,15 @@ exctype, value = sys.exc_info()[:2] raise exctype, value else: - if attr not in list(self.dtype.names) + ['_mask','mask']: + # Get the list of names ...... + _names = self.dtype.names + if _names is None: + _names = [] + else: + _names = list(_names) + _names += ['_mask','mask'] + # Check the attribute + if attr not in _names: return ret if newattr: # We just added this one try: # or this setattr worked on an internal @@ -227,14 +297,26 @@ base_fmask = self._fieldmask _names = self.dtype.names if attr in _names: - fval = filled(val) - mval = getmaskarray(val) + if val is masked: + fval = self.fill_value[attr] + mval = True + else: + fval = filled(val) + mval = getmaskarray(val) if self._hardmask: mval = mask_or(mval, base_fmask.__getattr__(attr)) self._data.__setattr__(attr, fval) base_fmask.__setattr__(attr, mval) return elif attr == '_mask': + #FIXME: We should check for self._harmask over there. +# if self._hardmask: +# val = make_mask(val) +# if val is not nomask: +## mval = getmaskarray(val) +# for k in _names: +# m = mask_or(val, base_fmask.__getattr__(k)) +# base_fmask.__setattr__(k, m) self.__setmask__(val) return #............................................ @@ -242,30 +324,29 @@ """Returns all the fields sharing the same fieldname base. The fieldname base is either `_data` or `_mask`.""" _localdict = self.__dict__ + _fieldmask = _localdict['_fieldmask'] _data = self._data # We want a field ........ if isinstance(indx, basestring): obj = _data[indx].view(MaskedArray) - obj._set_mask(_localdict['_fieldmask'][indx]) + obj._set_mask(_fieldmask[indx]) # Force to nomask if the mask is empty if not obj._mask.any(): obj._mask = nomask + # Force to masked if the mask is True + if not obj.ndim and obj._mask: + return masked return obj # We want some elements .. # First, the data ........ - obj = ndarray.__getitem__(self, indx) - if isinstance(obj, numpy.void): - obj = self.__class__(obj, dtype=self.dtype) - else: - obj = obj.view(type(self)) - obj._fieldmask = numpy.asarray(_localdict['_fieldmask'][indx]).view(recarray) + obj = narray(_data[indx], copy=False).view(mrecarray) + obj._fieldmask = narray(_fieldmask[indx], copy=False).view(recarray) return obj - #............................................ + #.... def __setitem__(self, indx, value): "Sets the given record to value." MaskedArray.__setitem__(self, indx, value) - - + #............................................ def __setslice__(self, i, j, value): "Sets the slice described by [i,j] to `value`." _localdict = self.__dict__ @@ -295,31 +376,6 @@ d[n][i:j][~mval] = dval[~mval] m[n][i:j] = mask_or(m[n][i:j], mval) self._fieldmask = m - - #..................................................... - def __setmask__(self, mask): - "Sets the mask." - names = self.dtype.names - fmask = self.__dict__['_fieldmask'] - newmask = make_mask(mask, copy=False) -# self.unshare_mask() - if self._hardmask: - for n in names: - fmask[n].__ior__(newmask) - else: - for n in names: - fmask[n].flat = newmask - return - - def _getmask(self): - """Returns the mask of the mrecord: a record is masked when all the fields -are masked.""" - if self.size > 1: - return self._fieldmask.view((bool_, len(self.dtype))).all(1) - - _setmask = __setmask__ - _mask = property(fget=_getmask, fset=_setmask) - #...................................................... def __str__(self): "Calculates the string representation." @@ -331,14 +387,14 @@ mstr = ["%s" % ",".join([str(i) for i in s]) for s in zip([getattr(self,f) for f in self.dtype.names])] return "(%s)" % ", ".join(mstr) - + # def __repr__(self): "Calculates the repr representation." _names = self.dtype.names fmt = "%%%is : %%s" % (max([len(n) for n in _names])+4,) reprstr = [fmt % (f,getattr(self,f)) for f in self.dtype.names] reprstr.insert(0,'masked_records(') - reprstr.extend([fmt % (' fill_value', self._fill_value), + reprstr.extend([fmt % (' fill_value', self.fill_value), ' )']) return str("\n".join(reprstr)) #...................................................... @@ -355,11 +411,11 @@ 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``. If ``fill_value`` is None, ``self.fill_value`` is -used instead. + """Returns an array of the same class as the _data part, where masked + values are filled with fill_value. + If fill_value is None, self.fill_value is used instead. -Subclassing is preserved. + Subclassing is preserved. """ _localdict = self.__dict__ @@ -369,7 +425,7 @@ return d # if fill_value is None: - value = _localdict['_fill_value'] + value = _check_fill_value(_localdict['_fill_value'],self.dtype) else: value = fill_value if numeric.size(value) == 1: @@ -383,168 +439,213 @@ numpy.putmask(numeric.asarray(result[n]), numeric.asarray(fm[n]), v) return result - #............................................ + #...................................................... def harden_mask(self): "Forces the mask to hard" self._hardmask = True def soften_mask(self): "Forces the mask to soft" self._hardmask = False - #............................................. + #...................................................... def copy(self): """Returns a copy of the masked record.""" _localdict = self.__dict__ - return MaskedRecords(self._data.copy(), - mask=_localdict['_fieldmask'].copy(), - dtype=self.dtype) - #............................................. + copied = self._data.copy().view(type(self)) + copied._fieldmask = self._fieldmask.copy() + return copied + #...................................................... + def tolist(self, fill_value=None): + """Copy the data portion of the array to a hierarchical python + list and returns that list. + Data items are converted to the nearest compatible Python + type. Masked values are converted to fill_value. If + fill_value is None, the corresponding entries in the output + list will be ``None``. + """ + if fill_value is not None: + return self.filled(fill_value).tolist() + result = narray(self.filled().tolist(), dtype=object) + mask = narray(self._fieldmask.tolist()) + result[mask] = None + return [tuple(r) for r in result] + #-------------------------------------------- + # Pickling + def __getstate__(self): + """Return the internal state of the masked array, for pickling purposes. + + """ + state = (1, + self.shape, + self.dtype, + self.flags.fnc, + self._data.tostring(), + self._fieldmask.tostring(), + self._fill_value, + ) + return state + # + def __setstate__(self, state): + """Restore the internal state of the masked array, for pickling purposes. + ``state`` is typically the output of the ``__getstate__`` output, and is a + 5-tuple: + + - class name + - a tuple giving the shape of the data + - a typecode for the data + - a binary string for the data + - a binary string for the mask. + + """ + (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._fieldmask.__setstate__((shp, mdtype, isf, msk)) + self.fill_value = flv + # + def __reduce__(self): + """Return a 3-tuple for pickling a MaskedArray. + + """ + return (_mrreconstruct, + (self.__class__, self._baseclass, (0,), 'b', ), + self.__getstate__()) + +def _mrreconstruct(subtype, baseclass, baseshape, basetype,): + """Internal function that builds a new MaskedArray from the + information stored in a pickle. + + """ + _data = ndarray.__new__(baseclass, baseshape, basetype).view(subtype) +# _data._mask = ndarray.__new__(ndarray, baseshape, 'b1') +# return _data + _mask = ndarray.__new__(ndarray, baseshape, 'b1') + return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) + + +mrecarray = MaskedRecords + #####--------------------------------------------------------------------------- #---- --- Constructors --- #####--------------------------------------------------------------------------- def fromarrays(arraylist, dtype=None, shape=None, formats=None, - names=None, titles=None, aligned=False, byteorder=None): + names=None, titles=None, aligned=False, byteorder=None, + fill_value=None): """Creates a mrecarray from a (flat) list of masked arrays. -*Parameters*: - arraylist : {sequence} + Parameters + ---------- + arraylist : sequence A list of (masked) arrays. Each element of the sequence is first converted to a masked array if needed. If a 2D array is passed as argument, it is processed line by line - dtype : {numeric.dtype} + dtype : numeric.dtype Data type descriptor. - {shape} : {integer} - Number of records. If None, ``shape`` is defined from the shape of the + shape : integer + Number of records. If None, shape is defined from the shape of the first array in the list. - formats : {sequence} + formats : sequence Sequence of formats for each individual field. If None, the formats will be autodetected by inspecting the fields and selecting the highest dtype possible. - names : {sequence} + names : sequence Sequence of the names of each field. - -titles : {sequence} + titles : sequence (Description to write) - aligned : {boolean} + aligned : boolean (Description to write, not used anyway) - byteorder: {boolean} + byteorder: boolean (Description to write, not used anyway) + fill_value : sequence + Sequence of data to be used as filling values. -*Notes*: + Notes + ----- Lists of tuples should be preferred over lists of lists for faster processing. """ - arraylist = [masked_array(x) for x in arraylist] - # Define/check the shape..................... - if shape is None or shape == 0: - shape = arraylist[0].shape - if isinstance(shape, int): - shape = (shape,) - # Define formats from scratch ............... - if formats is None and dtype is None: - formats = _getformats(arraylist) - # Define the dtype .......................... - if dtype is not None: - descr = numeric.dtype(dtype) - _names = descr.names - else: - parsed = format_parser(formats, names, titles, aligned, byteorder) - _names = parsed._names - descr = parsed._descr - # Determine shape from data-type............. - if len(descr) != len(arraylist): - msg = "Mismatch between the number of fields (%i) and the number of "\ - "arrays (%i)" - raise ValueError, msg % (len(descr), len(arraylist)) - d0 = descr[0].shape - nn = len(d0) - if nn > 0: - shape = shape[:-nn] - # Make sure the shape is the correct one .... - for k, obj in enumerate(arraylist): - nn = len(descr[k].shape) - testshape = obj.shape[:len(obj.shape)-nn] - if testshape != shape: - raise ValueError, "Array-shape mismatch in array %d" % k - # Reconstruct the descriptor, by creating a _data and _mask version - return MaskedRecords(arraylist, dtype=descr) + datalist = [getdata(x) for x in arraylist] + masklist = [getmaskarray(x) for x in arraylist] + _array = recfromarrays(datalist, + dtype=dtype, shape=shape, formats=formats, + names=names, titles=titles, aligned=aligned, + byteorder=byteorder).view(mrecarray) + _array._fieldmask[:] = zip(*masklist) + if fill_value is not None: + _array.fill_value = fill_value + return _array + + #.............................................................................. def fromrecords(reclist, dtype=None, shape=None, formats=None, names=None, - titles=None, aligned=False, byteorder=None): + titles=None, aligned=False, byteorder=None, + fill_value=None, mask=nomask): """Creates a MaskedRecords from a list of records. -*Parameters*: - arraylist : {sequence} + Parameters + ---------- + arraylist : sequence A list of (masked) arrays. Each element of the sequence is first converted to a masked array if needed. If a 2D array is passed as argument, it is processed line by line - dtype : {numeric.dtype} + dtype : numeric.dtype Data type descriptor. - {shape} : {integer} + shape : integer Number of records. If None, ``shape`` is defined from the shape of the first array in the list. - formats : {sequence} + formats : sequence Sequence of formats for each individual field. If None, the formats will be autodetected by inspecting the fields and selecting the highest dtype possible. - names : {sequence} + names : sequence Sequence of the names of each field. - -titles : {sequence} + titles : sequence (Description to write) - aligned : {boolean} + aligned : boolean (Description to write, not used anyway) - byteorder: {boolean} + byteorder: boolean (Description to write, not used anyway) + fill_value : sequence + Sequence of data to be used as filling values. + mask : sequence or boolean. + External mask to apply on the data. *Notes*: Lists of tuples should be preferred over lists of lists for faster processing. """ - # reclist is in fact a mrecarray ................. - if isinstance(reclist, MaskedRecords): - mdescr = reclist.dtype - shape = reclist.shape - return MaskedRecords(reclist, dtype=mdescr) - # No format, no dtype: create from to arrays ..... + # Grab the initial _fieldmask, if needed: + _fieldmask = getattr(reclist, '_fieldmask', None) + # Get the list of records..... nfields = len(reclist[0]) - if formats is None and dtype is None: # slower - if isinstance(reclist, recarray): - arrlist = [reclist.field(i) for i in range(len(reclist.dtype))] - if names is None: - names = reclist.dtype.names + if isinstance(reclist, ndarray): + # Make sure we don't have some hidden mask + if isinstance(reclist,MaskedArray): + reclist = reclist.filled().view(ndarray) + # Grab the initial dtype, just in case + if dtype is None: + dtype = reclist.dtype + reclist = reclist.tolist() + mrec = recfromrecords(reclist, dtype=dtype, shape=shape, formats=formats, + names=names, titles=titles, + aligned=aligned, byteorder=byteorder).view(mrecarray) + # Set the fill_value if needed + if fill_value is not None: + mrec.fill_value = fill_value + # Now, let's deal w/ the mask + if mask is not nomask: + mask = narray(mask, copy=False) + maskrecordlength = len(mask.dtype) + if maskrecordlength: + mrec._fieldmask.flat = mask + elif len(mask.shape) == 2: + mrec._fieldmask.flat = [tuple(m) for m in mask] else: - obj = numeric.array(reclist,dtype=object) - arrlist = [numeric.array(obj[...,i].tolist()) - for i in xrange(nfields)] - return MaskedRecords(arrlist, formats=formats, names=names, - titles=titles, aligned=aligned, byteorder=byteorder) - # Construct the descriptor ....................... - if dtype is not None: - descr = numeric.dtype(dtype) - _names = descr.names - else: - parsed = format_parser(formats, names, titles, aligned, byteorder) - _names = parsed._names - descr = parsed._descr + mrec._mask = mask + if _fieldmask is not None: + mrec._fieldmask[:] = _fieldmask + return mrec - try: - retval = numeric.array(reclist, dtype = descr).view(recarray) - except TypeError: # list of lists instead of list of tuples - if (shape is None or shape == 0): - shape = len(reclist)*2 - if isinstance(shape, (int, long)): - shape = (shape*2,) - if len(shape) > 1: - raise ValueError, "Can only deal with 1-d array." - retval = recarray(shape, mdescr) - for k in xrange(retval.size): - retval[k] = tuple(reclist[k]) - return MaskedRecords(retval, dtype=descr) - else: - if shape is not None and retval.shape != shape: - retval.shape = shape - # - return MaskedRecords(retval, dtype=descr) - def _guessvartypes(arr): """Tries to guess the dtypes of the str_ ndarray `arr`, by testing element-wise conversion. Returns a list of dtypes. @@ -648,7 +749,7 @@ _mask = (_variables.T == missingchar) _datalist = [masked_array(a,mask=m,dtype=t) for (a,m,t) in zip(_variables.T, _mask, vartypes)] - return MaskedRecords(_datalist, dtype=mdescr) + return fromarrays(_datalist, dtype=mdescr) #.................................................................... def addfield(mrecord, newfield, newfieldname=None): @@ -685,28 +786,6 @@ newdata._fieldmask = newmask return newdata -################################################################################ -if __name__ == '__main__': - import numpy as N - from numpy.ma.testutils import assert_equal - if 1: - d = N.arange(5) - m = numpy.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 = masked_array(base_d, mask=base_m).T - mrecord = fromarrays(base,dtype=[('a',N.float_),('b',N.float_)]) - mrec = MaskedRecords(mrecord.copy()) - # - if 1: - mrec = mrec.copy() - mrec.harden_mask() - assert(mrec._hardmask) - mrec._mask = nomask - assert_equal(mrec._mask, N.r_[[m,m[::-1]]].all(0)) - mrec.soften_mask() - assert(not mrec._hardmask) - mrec.mask = nomask - tmp = mrec['b']._mask - assert(mrec['b']._mask is nomask) - assert_equal(mrec['a']._mask,mrec['b']._mask) +############################################################################### + + Modified: branches/maskedarray/numpy/ma/tests/test_core.py =================================================================== --- branches/maskedarray/numpy/ma/tests/test_core.py 2008-02-01 11:17:39 UTC (rev 4766) +++ branches/maskedarray/numpy/ma/tests/test_core.py 2008-02-01 23:40:35 UTC (rev 4767) @@ -1347,7 +1347,16 @@ assert_equal(xlist[0],[0,None,2,3]) assert_equal(xlist[1],[4,5,6,7]) assert_equal(xlist[2],[8,9,None,11]) + # Make sure a masked record is output as a tuple of None + x = array(zip([1,2,3], + [1.1,2.2,3.3], + ['one','two','thr']), + dtype=[('a',int_),('b',float_),('c','|S8')]) + x[-1] = masked + assert_equal(x.tolist(), [(1,1.1,'one'),(2,2.2,'two'),(None,None,None)]) + + def test_squeeze(self): "Check squeeze" data = masked_array([[1,2,3]]) Modified: branches/maskedarray/numpy/ma/tests/test_mrecords.py =================================================================== --- branches/maskedarray/numpy/ma/tests/test_mrecords.py 2008-02-01 11:17:39 UTC (rev 4766) +++ branches/maskedarray/numpy/ma/tests/test_mrecords.py 2008-02-01 23:40:35 UTC (rev 4767) @@ -1,33 +1,35 @@ # pylint: disable-msg=W0611, W0612, W0511,R0201 -"""Tests suite for mrecarray. +"""Tests suite for mrecords. :author: Pierre Gerard-Marchant :contact: pierregm_at_uga_dot_edu -:version: $Id: test_mrecords.py 3473 2007-10-29 15:18:13Z jarrod.millman $ """ __author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" -__version__ = '1.0' __revision__ = "$Revision: 3473 $" __date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' import types import numpy as N -import numpy.core.fromnumeric as fromnumeric +from numpy import recarray, bool_, int_, float_ +from numpy import array as narray +from numpy.core.records import fromrecords as recfromrecords +from numpy.core.records import fromarrays as recfromarrays +import numpy.core.fromnumeric as fromnumeric_ from numpy.testing import NumpyTest, NumpyTestCase from numpy.testing.utils import build_err_msg import numpy.ma.testutils -from numpy.ma.testutils import * +from numpy.ma.testutils import assert_equal, assert_equal_records import numpy.ma -from numpy.ma import masked_array, masked, nomask +from numpy.ma import masked_array, masked, nomask, getdata, getmaskarray #import numpy.ma.mrecords #from numpy.ma.mrecords import mrecarray, fromarrays, fromtextfile, fromrecords import numpy.ma.mrecords -from numpy.ma.mrecords import MaskedRecords, \ +from numpy.ma.mrecords import MaskedRecords, mrecarray,\ fromarrays, fromtextfile, fromrecords, addfield #.............................................................................. @@ -39,111 +41,275 @@ def setup(self): "Generic setup" - d = N.arange(5) - m = numpy.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 = masked_array(base_d, mask=base_m) - mrecord = fromarrays(base.T, dtype=[('a',N.float_),('b',N.float_)]) - self.data = [d, m, mrecord] + ilist = [1,2,3,4,5] + flist = [1.1,2.2,3.3,4.4,5.5] + slist = ['one','two','three','four','five'] + ddtype = [('a',int_),('b',float_),('c','|S8')] + mask = [0,1,0,0,1] + self.base = masked_array(zip(ilist,flist,slist), mask=mask, dtype=ddtype) + + def test_byview(self): + "Test creation by view" + base = self.base + mbase = base.view(mrecarray) + assert_equal(mbase._mask, base._mask) + assert isinstance(mbase._data, recarray) + assert_equal_records(mbase._data, base._data.view(recarray)) + for field in ('a','b','c'): + assert_equal(base[field], mbase[field]) + assert_equal_records(mbase.view(mrecarray), mbase) def test_get(self): "Tests fields retrieval" - [d, m, mrec] = self.data - mrec = mrec.copy() - assert_equal(mrec.a, masked_array(d,mask=m)) - assert_equal(mrec.b, masked_array(d[::-1],mask=m[::-1])) - assert((mrec._fieldmask == N.core.records.fromarrays([m, m[::-1]], dtype=mrec._fieldmask.dtype)).all()) - assert_equal(mrec._mask, N.r_[[m,m[::-1]]].all(0)) - assert_equal(mrec.a[1], mrec[1].a) - # - assert(isinstance(mrec[:2], MaskedRecords)) - assert_equal(mrec[:2]['a'], d[:2]) + base = self.base.copy() + mbase = base.view(mrecarray) + # As fields.......... + for field in ('a','b','c'): + assert_equal(getattr(mbase,field), mbase[field]) + assert_equal(base[field], mbase[field]) + # as elements ....... + mbase_first = mbase[0] + assert isinstance(mbase_first, mrecarray) + assert_equal(mbase_first.dtype, mbase.dtype) + assert_equal(mbase_first.tolist(), (1,1.1,'one')) + assert_equal(mbase_first.mask, nomask) + assert_equal(mbase_first._fieldmask.item(), (False, False, False)) + assert_equal(mbase_first['a'], mbase['a'][0]) + mbase_last = mbase[-1] + assert isinstance(mbase_last, mrecarray) + assert_equal(mbase_last.dtype, mbase.dtype) + assert_equal(mbase_last.tolist(), (None,None,None)) + assert_equal(mbase_last.mask, True) + assert_equal(mbase_last._fieldmask.item(), (True, True, True)) + assert_equal(mbase_last['a'], mbase['a'][-1]) + assert (mbase_last['a'] is masked) + # as slice .......... + mbase_sl = mbase[:2] + assert isinstance(mbase_sl, mrecarray) + assert_equal(mbase_sl.dtype, mbase.dtype) + assert_equal(mbase_sl._mask, [0,1]) + assert_equal_records(mbase_sl, base[:2].view(mrecarray)) + for field in ('a','b','c'): + assert_equal(getattr(mbase_sl,field), base[:2][field]) - def test_set(self): - "Tests setting fields/attributes." - [d, m, mrecord] = self.data - mrecord.a._data[:] = 5 - assert_equal(mrecord['a']._data, [5,5,5,5,5]) - mrecord.a = 1 - assert_equal(mrecord['a']._data, [1]*5) - assert_equal(getmaskarray(mrecord['a']), [0]*5) - mrecord.b = masked - assert_equal(mrecord.b.mask, [1]*5) - assert_equal(getmaskarray(mrecord['b']), [1]*5) - mrecord._mask = masked - assert_equal(getmaskarray(mrecord['b']), [1]*5) - assert_equal(mrecord['a']._mask, mrecord['b']._mask) - mrecord._mask = nomask - assert_equal(getmaskarray(mrecord['b']), [0]*5) - assert_equal(mrecord['a']._mask, mrecord['b']._mask) + def test_set_fields(self): + "Tests setting fields." + base = self.base.copy() + mbase = base.view(mrecarray) + mbase = mbase.copy() + mbase.fill_value = (999999,1e20,'N/A') + # Change the data, the mask should be conserved + mbase.a._data[:] = 5 + assert_equal(mbase['a']._data, [5,5,5,5,5]) + assert_equal(mbase['a']._mask, [0,1,0,0,1]) + # Change the elements, and the mask will follow + mbase.a = 1 + assert_equal(mbase['a']._data, [1]*5) + assert_equal(getmaskarray(mbase['a']), [0]*5) + assert_equal(mbase._mask, [False]*5) + assert_equal(mbase._fieldmask.tolist(), + narray([(0,0,0),(0,1,1),(0,0,0),(0,0,0),(0,1,1)], + dtype=bool_)) + # Set a field to mask ........................ + mbase.c = masked + assert_equal(mbase.c.mask, [1]*5) + assert_equal(getmaskarray(mbase['c']), [1]*5) + assert_equal(getdata(mbase['c']), ['N/A']*5) + assert_equal(mbase._fieldmask.tolist(), + narray([(0,0,1),(0,1,1),(0,0,1),(0,0,1),(0,1,1)], + dtype=bool_)) + # Set fields by slices ....................... + mbase = base.view(mrecarray).copy() + mbase.a[3:] = 5 + assert_equal(mbase.a, [1,2,3,5,5]) + assert_equal(mbase.a._mask, [0,1,0,0,0]) + mbase.b[3:] = masked + assert_equal(mbase.b, base['b']) + assert_equal(mbase.b._mask, [0,1,0,1,1]) + # + def test_set_mask(self): + base = self.base.copy() + mbase = base.view(mrecarray) + # Set the mask to True ....................... + mbase._mask = masked + assert_equal(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(), + narray([(1,1,1)]*5, + dtype=bool_)) + # Delete the mask ............................ + mbase._mask = nomask + assert_equal(getmaskarray(mbase['c']), [0]*5) + assert_equal(mbase._fieldmask.tolist(), + narray([(0,0,0)]*5, + dtype=bool_)) + # + def test_set_elements(self): + base = self.base.copy() + mbase = base.view(mrecarray) + # Set an element to mask ..................... + mbase[-2] = masked + assert_equal(mbase._fieldmask.tolist(), + narray([(0,0,0),(1,1,1),(0,0,0),(1,1,1),(1,1,1)], + dtype=bool_)) + assert_equal(mbase._mask, [0,1,0,1,1]) + # Set slices ................................. + mbase = base.view(mrecarray).copy() + mbase[:2] = 5 + assert_equal(mbase.a._data, [5,5,3,4,5]) + assert_equal(mbase.a._mask, [0,0,0,0,1]) + assert_equal(mbase.b._data, [5.,5.,3.3,4.4,5.5]) + assert_equal(mbase.b._mask, [0,0,0,0,1]) + assert_equal(mbase.c._data, ['5','5','three','four','five']) + assert_equal(mbase.b._mask, [0,0,0,0,1]) # - def test_setfields(self): - "Tests setting fields." - [d, m, mrecord] = self.data - mrecord.a[3:] = 5 - assert_equal(mrecord.a, [0,1,2,5,5]) - assert_equal(mrecord.a._mask, [1,0,0,0,0]) - # - mrecord.b[3:] = masked - assert_equal(mrecord.b, [4,3,2,1,0]) - assert_equal(mrecord.b._mask, [1,1,0,1,1]) - - def test_setslices(self): - "Tests setting slices." - [d, m, mrec] = self.data - mrec[:2] = 5 - assert_equal(mrec.a._data, [5,5,2,3,4]) - assert_equal(mrec.b._data, [5,5,2,1,0]) - assert_equal(mrec.a._mask, [0,0,0,1,1]) - assert_equal(mrec.b._mask, [0,0,0,0,1]) - # - mrec[:2] = masked - assert_equal(mrec._mask, [1,1,0,0,1]) - mrec[-2] = masked - assert_equal(mrec._mask, [1,1,0,1,1]) - # + mbase = base.view(mrecarray).copy() + mbase[:2] = masked + assert_equal(mbase.a._data, [1,2,3,4,5]) + assert_equal(mbase.a._mask, [1,1,0,0,1]) + assert_equal(mbase.b._data, [1.1,2.2,3.3,4.4,5.5]) + assert_equal(mbase.b._mask, [1,1,0,0,1]) + assert_equal(mbase.c._data, ['one','two','three','four','five']) + assert_equal(mbase.b._mask, [1,1,0,0,1]) + # def test_setslices_hardmask(self): "Tests setting slices w/ hardmask." - [d, m, mrec] = self.data - mrec.harden_mask() - mrec[-2:] = 5 - assert_equal(mrec.a._data, [0,1,2,3,4]) - assert_equal(mrec.b._data, [4,3,2,5,0]) - assert_equal(mrec.a._mask, [1,0,0,1,1]) - assert_equal(mrec.b._mask, [1,1,0,0,1]) + base = self.base.copy() + mbase = base.view(mrecarray) + mbase.harden_mask() + mbase[-2:] = 5 + assert_equal(mbase.a._data, [1,2,3,5,5]) + assert_equal(mbase.b._data, [1.1,2.2,3.3,5,5.5]) + assert_equal(mbase.c._data, ['one','two','three','5','five']) + assert_equal(mbase.a._mask, [0,1,0,0,1]) + assert_equal(mbase.b._mask, mbase.a._mask) + assert_equal(mbase.b._mask, mbase.c._mask) def test_hardmask(self): "Test hardmask" - [d, m, mrec] = self.data - mrec = mrec.copy() - mrec.harden_mask() - assert(mrec._hardmask) - mrec._mask = nomask - assert_equal(mrec._mask, N.r_[[m,m[::-1]]].all(0)) - mrec.soften_mask() - assert(not mrec._hardmask) - mrec._mask = nomask - assert(mrec['b']._mask is nomask) - assert_equal(mrec['a']._mask,mrec['b']._mask) + base = self.base.copy() + mbase = base.view(mrecarray) + mbase.harden_mask() + assert(mbase._hardmask) + mbase._mask = nomask + assert_equal(mbase._mask, [0,1,0,0,1]) + mbase.soften_mask() + assert(not mbase._hardmask) + mbase._mask = nomask + assert(mbase['b']._mask is nomask) + assert_equal(mbase['a']._mask,mbase['b']._mask) + # + def test_pickling(self): + "Test pickling" + import cPickle + base = self.base.copy() + mrec = base.view(mrecarray) + _ = cPickle.dumps(mrec) + mrec_ = cPickle.loads(_) + 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) + # + def test_filled(self): + "Test filling the array" + _a = masked_array([1,2,3],mask=[0,0,1],dtype=int_) + _b = masked_array([1.1,2.2,3.3],mask=[0,0,1],dtype=float_) + _c = masked_array(['one','two','three'],mask=[0,0,1],dtype='|S8') + ddtype = [('a',int_),('b',float_),('c','|S8')] + mrec = fromarrays([_a,_b,_c], dtype=ddtype, + fill_value=(99999,99999.,'N/A')) + mrecfilled = mrec.filled() + assert_equal(mrecfilled['a'], narray((1,2,99999), dtype=int_)) + assert_equal(mrecfilled['b'], narray((1.1,2.2,99999.), dtype=float_)) + assert_equal(mrecfilled['c'], narray(('one','two','N/A'), dtype='|S8')) + # + def test_tolist(self): + "Test tolist." + _a = masked_array([1,2,3],mask=[0,0,1],dtype=int_) + _b = masked_array([1.1,2.2,3.3],mask=[0,0,1],dtype=float_) + _c = masked_array(['one','two','three'],mask=[1,0,0],dtype='|S8') + ddtype = [('a',int_),('b',float_),('c','|S8')] + mrec = fromarrays([_a,_b,_c], dtype=ddtype, + fill_value=(99999,99999.,'N/A')) + # + assert_equal(mrec.tolist(), + [(1,1.1,None),(2,2.2,'two'),(None,None,'three')]) +################################################################################ +class TestMRecordsImport(NumpyTestCase): + "Base test class for MaskedArrays." + def __init__(self, *args, **kwds): + NumpyTestCase.__init__(self, *args, **kwds) + self.setup() + + def setup(self): + "Generic setup" + _a = masked_array([1,2,3],mask=[0,0,1],dtype=int_) + _b = masked_array([1.1,2.2,3.3],mask=[0,0,1],dtype=float_) + _c = masked_array(['one','two','three'],mask=[0,0,1],dtype='|S8') + ddtype = [('a',int_),('b',float_),('c','|S8')] + mrec = fromarrays([_a,_b,_c], dtype=ddtype, + fill_value=(99999,99999.,'N/A')) + nrec = recfromarrays((_a.data,_b.data,_c.data), dtype=ddtype) + self.data = (mrec, nrec, ddtype) + + def test_fromarrays(self): + _a = masked_array([1,2,3],mask=[0,0,1],dtype=int_) + _b = masked_array([1.1,2.2,3.3],mask=[0,0,1],dtype=float_) + _c = masked_array(['one','two','three'],mask=[0,0,1],dtype='|S8') + (mrec, nrec, _) = self.data + for (f,l) in zip(('a','b','c'),(_a,_b,_c)): + assert_equal(getattr(mrec,f)._mask, l._mask) + + def test_fromrecords(self): - "Test from recarray." - [d, m, mrec] = self.data - nrec = N.core.records.fromarrays(N.r_[[d,d[::-1]]], - dtype=[('a',N.float_),('b',N.float_)]) - #.................... - mrecfr = fromrecords(nrec) - assert_equal(mrecfr.a, mrec.a) - assert_equal(mrecfr.dtype, mrec.dtype) - #.................... - tmp = mrec[::-1] #.tolist() - mrecfr = fromrecords(tmp) - assert_equal(mrecfr.a, mrec.a[::-1]) - #.................... - mrecfr = fromrecords(nrec.tolist(), names=nrec.dtype.names) - assert_equal(mrecfr.a, mrec.a) - assert_equal(mrecfr.dtype, mrec.dtype) + "Test construction from records." + (mrec, nrec, ddtype) = self.data + #...... + palist = [(1, 'abc', 3.7000002861022949, 0), + (2, 'xy', 6.6999998092651367, 1), + (0, ' ', 0.40000000596046448, 0)] + pa = recfromrecords(palist, names='c1, c2, c3, c4') + mpa = fromrecords(palist, names='c1, c2, c3, c4') + assert_equal_records(pa,mpa) + #..... + _mrec = fromrecords(nrec) + assert_equal(_mrec.dtype, mrec.dtype) + for field in _mrec.dtype.names: + assert_equal(getattr(_mrec, field), getattr(mrec._data, field)) + # + _mrec = fromrecords(nrec.tolist(), names='c1,c2,c3') + assert_equal(_mrec.dtype, [('c1',int_),('c2',float_),('c3','|S5')]) + for (f,n) in zip(('c1','c2','c3'), ('a','b','c')): + assert_equal(getattr(_mrec,f), getattr(mrec._data, n)) + # + _mrec = fromrecords(mrec) + assert_equal(_mrec.dtype, mrec.dtype) + assert_equal_records(_mrec._data, mrec.filled()) + assert_equal_records(_mrec._fieldmask, mrec._fieldmask) + + def test_fromrecords_wmask(self): + "Tests construction from records w/ mask." + (mrec, nrec, ddtype) = self.data + # + _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)]) + # + _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)]) + # + _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=mrec._fieldmask) + assert_equal_records(_mrec._data, mrec._data) + assert_equal(_mrec._fieldmask.tolist(), mrec._fieldmask.tolist()) + # + _mrec = fromrecords(nrec.tolist(), dtype=ddtype, + mask=mrec._fieldmask.tolist()) + assert_equal_records(_mrec._data, mrec._data) + assert_equal(_mrec._fieldmask.tolist(), mrec._fieldmask.tolist()) def test_fromtextfile(self): "Tests reading from a text file." @@ -170,10 +336,11 @@ def test_addfield(self): "Tests addfield" - [d, m, mrec] = self.data - mrec = addfield(mrec, masked_array(d+10, mask=m[::-1])) - assert_equal(mrec.f2, d+10) - assert_equal(mrec.f2._mask, m[::-1]) + (mrec, nrec, ddtype) = self.data + (d,m) = ([100,200,300], [1,0,0]) + mrec = addfield(mrec, masked_array(d, mask=m)) + assert_equal(mrec.f3, d) + assert_equal(mrec.f3._mask, m) ############################################################################### #------------------------------------------------------------------------------ From numpy-svn at scipy.org Wed Feb 6 18:11:42 2008 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Wed, 6 Feb 2008 17:11:42 -0600 (CST) Subject: [Numpy-svn] r4768 - branches/maskedarray/numpy/ma/tests Message-ID: <20080206231142.5EE0F39C0CD@new.scipy.org> Author: stefan Date: 2008-02-06 17:11:09 -0600 (Wed, 06 Feb 2008) New Revision: 4768 Modified: branches/maskedarray/numpy/ma/tests/test_core.py Log: Remove print statement from test. Modified: branches/maskedarray/numpy/ma/tests/test_core.py =================================================================== --- branches/maskedarray/numpy/ma/tests/test_core.py 2008-02-01 23:40:35 UTC (rev 4767) +++ branches/maskedarray/numpy/ma/tests/test_core.py 2008-02-06 23:11:09 UTC (rev 4768) @@ -1441,7 +1441,6 @@ b = empty(len(a), dtype=datatype) assert_equal(b.shape, a.shape) assert_equal(b.fill_value, a.fill_value) - print "test_empty passed!" #.............................................................................. From numpy-svn at scipy.org Wed Feb 6 18:18:02 2008 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Wed, 6 Feb 2008 17:18:02 -0600 (CST) Subject: [Numpy-svn] r4769 - branches/maskedarray/numpy/ma/tests Message-ID: <20080206231802.D8ACE39C0CD@new.scipy.org> Author: stefan Date: 2008-02-06 17:17:35 -0600 (Wed, 06 Feb 2008) New Revision: 4769 Modified: branches/maskedarray/numpy/ma/tests/test_core.py Log: Ignore DeprecationWarning during testing. Modified: branches/maskedarray/numpy/ma/tests/test_core.py =================================================================== --- branches/maskedarray/numpy/ma/tests/test_core.py 2008-02-06 23:11:09 UTC (rev 4768) +++ branches/maskedarray/numpy/ma/tests/test_core.py 2008-02-06 23:17:35 UTC (rev 4769) @@ -174,15 +174,16 @@ xm /= arange(10) assert_equal(xm, ones((10,))) + warnings.simplefilter('ignore', DeprecationWarning) x = arange(10).astype(float_) xm = arange(10) xm[2] = masked -# id1 = id(x.raw_data()) id1 = x.raw_data().ctypes.data x += 1. -# assert id1 == id(x.raw_data()) assert (id1 == x.raw_data().ctypes.data) assert_equal(x, y+1.) + warnings.simplefilter('default', DeprecationWarning) + # addition w/ array x = arange(10, dtype=float_) xm = arange(10, dtype=float_) @@ -449,6 +450,7 @@ m3 = make_mask(m, copy=1) assert(m is not m3) + warnings.simplefilter('ignore', DeprecationWarning) x1 = numpy.arange(5) y1 = array(x1, mask=m) #assert( y1._data is x1) @@ -456,6 +458,7 @@ assert( allequal(x1,y1.raw_data())) #assert( y1.mask is m) assert_equal(y1._mask.__array_interface__, m.__array_interface__) + warnings.simplefilter('default', DeprecationWarning) y1a = array(y1) #assert( y1a.raw_data() is y1.raw_data()) From numpy-svn at scipy.org Thu Feb 7 06:42:23 2008 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Thu, 7 Feb 2008 05:42:23 -0600 (CST) Subject: [Numpy-svn] r4770 - branches/maskedarray/numpy/ma/tests Message-ID: <20080207114223.74C1639C4DC@new.scipy.org> Author: stefan Date: 2008-02-07 05:42:03 -0600 (Thu, 07 Feb 2008) New Revision: 4770 Modified: branches/maskedarray/numpy/ma/tests/test_core.py branches/maskedarray/numpy/ma/tests/test_old_ma.py Log: Remove .data comparisons in tests. Fix whitespace. Modified: branches/maskedarray/numpy/ma/tests/test_core.py =================================================================== --- branches/maskedarray/numpy/ma/tests/test_core.py 2008-02-06 23:17:35 UTC (rev 4769) +++ branches/maskedarray/numpy/ma/tests/test_core.py 2008-02-07 11:42:03 UTC (rev 4770) @@ -501,13 +501,9 @@ x = masked_array([1,2,3], mask=[0,1,0]) # Copy is False by default y = masked_array(x) -# assert_equal(id(y._data), id(x._data)) -# assert_equal(id(y._mask), id(x._mask)) assert_equal(y._data.ctypes.data, x._data.ctypes.data) assert_equal(y._mask.ctypes.data, x._mask.ctypes.data) y = masked_array(x, copy=True) -# assert_not_equal(id(y._data), id(x._data)) -# assert_not_equal(id(y._mask), id(x._mask)) assert_not_equal(y._data.ctypes.data, x._data.ctypes.data) assert_not_equal(y._mask.ctypes.data, x._mask.ctypes.data) #........................ @@ -1357,7 +1353,6 @@ dtype=[('a',int_),('b',float_),('c','|S8')]) x[-1] = masked assert_equal(x.tolist(), [(1,1.1,'one'),(2,2.2,'two'),(None,None,None)]) - def test_squeeze(self): @@ -1426,7 +1421,7 @@ assert_equal(b._mask, [1,1,0,0]) # x = numpy.array([3,1,2]) - b = a.compress(x >= 2, axis=1) + b = a.compress(x >= 2, axis=1) assert_equal(b._data, [[10,30],[40,60]]) assert_equal(b._mask, [[0,1],[1,0]]) # Modified: branches/maskedarray/numpy/ma/tests/test_old_ma.py =================================================================== --- branches/maskedarray/numpy/ma/tests/test_old_ma.py 2008-02-06 23:17:35 UTC (rev 4769) +++ branches/maskedarray/numpy/ma/tests/test_old_ma.py 2008-02-07 11:42:03 UTC (rev 4770) @@ -255,11 +255,9 @@ self.failUnless( y1.mask is m) y1a = array(y1, copy=0) - self.failUnless( y1a.data is y1.data) self.failUnless( y1a.mask is y1.mask) y2 = array(x1, mask=m, copy=0) - self.failUnless( y2.data is x1) self.failUnless( y2.mask is m) self.failUnless( y2[2] is masked) y2[2]=9 From numpy-svn at scipy.org Thu Feb 7 12:00:05 2008 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Thu, 7 Feb 2008 11:00:05 -0600 (CST) Subject: [Numpy-svn] r4771 - branches/maskedarray/numpy/ma Message-ID: <20080207170005.0B3C739C03A@new.scipy.org> Author: pierregm Date: 2008-02-07 11:00:02 -0600 (Thu, 07 Feb 2008) New Revision: 4771 Modified: branches/maskedarray/numpy/ma/core.py branches/maskedarray/numpy/ma/extras.py Log: comments cleaning and docstring updates. Modified: branches/maskedarray/numpy/ma/core.py =================================================================== --- branches/maskedarray/numpy/ma/core.py 2008-02-07 11:42:03 UTC (rev 4770) +++ branches/maskedarray/numpy/ma/core.py 2008-02-07 17:00:02 UTC (rev 4771) @@ -258,7 +258,8 @@ """ if hasattr(a, 'filled'): return a.filled(value) - elif isinstance(a, ndarray): # and a.flags['CONTIGUOUS']: + elif isinstance(a, ndarray): + # Should we check for contiguity ? and a.flags['CONTIGUOUS']: return a elif isinstance(a, dict): return narray(a, 'O') @@ -441,7 +442,8 @@ m = numpy.logical_or(m, dm) # The following two lines control the domain filling methods. d1 = d1.copy() -# d1[dm] = self.fill + # We could use smart indexing : d1[dm] = self.fill ... + # ... but numpy.putmask looks more efficient, despite the copy. numpy.putmask(d1, dm, self.fill) # Take care of the masked singletong first ... if not m.ndim and m: @@ -549,7 +551,8 @@ if (not m.ndim) and m: return masked rcls = get_masked_subclass(a,b) -# d = self.f.outer(filled(a, self.fillx), filled(b, self.filly)).view(rcls) + # 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) if d.ndim > 0: d._mask = m @@ -864,11 +867,12 @@ floating point, consider `masked_values(x, value)` instead. """ + # An alternative implementation relies on filling first: probably not needed. + # d = filled(x, 0) + # c = umath.equal(d, value) + # m = mask_or(c, getmask(x)) + # return array(d, mask=m, copy=copy) return masked_where((x == value), x, copy=copy) -# d = filled(x, 0) -# c = umath.equal(d, value) -# m = mask_or(c, getmask(x)) -# return array(d, mask=m, copy=copy) def masked_inside(x, v1, v2, copy=True): """Shortcut to masked_where, where condition is True for x inside @@ -970,7 +974,7 @@ else: cls = MaskedArray result = a.view(cls) - result._mask = cond + result._mask = condition return result @@ -1336,6 +1340,7 @@ """ if self is masked: raise MAError, 'Cannot alter the masked element.' + # This test is useful, but we should keep things light... # if getmask(indx) is not nomask: # msg = "Masked arrays must be filled before they can be used as indices!" # raise IndexError, msg @@ -1401,6 +1406,8 @@ """ if mask is not nomask: mask = narray(mask, copy=copy, dtype=MaskType) + # We could try to check whether shrinking is needed.. + # ... but we would waste some precious time # if self._shrinkmask and not mask.any(): # mask = nomask if self._mask is nomask: @@ -1425,8 +1432,9 @@ """Return the current mask. """ - return self._mask + # We could try to force a reshape, but that wouldn't work in some cases. # return self._mask.reshape(self.shape) + return self._mask mask = property(fget=_get_mask, fset=__setmask__, doc="Mask") #............................................ def harden_mask(self): @@ -1566,8 +1574,6 @@ data._update_from(self) if self._mask is not nomask: data = data[numpy.logical_not(ndarray.ravel(self._mask))] -# if not self._shrinkmask: -# data._mask = numpy.zeros(data.shape, dtype=MaskType) return data @@ -1730,7 +1736,6 @@ if self._mask is not nomask: warnings.warn("Warning: converting a masked element to nan.") return numpy.nan - #raise MAError, 'Cannot convert masked element to a Python float.' return float(self.item()) def __int__(self): @@ -1793,7 +1798,7 @@ return masked_array(n1 - n2) #............................................ flatten = _arraymethod('flatten') -# ravel = _arraymethod('ravel') + # def ravel(self): """Returns a 1D version of self, as a view.""" r = ndarray.ravel(self._data).view(type(self)) @@ -1803,6 +1808,7 @@ else: r._mask = nomask return r + # repeat = _arraymethod('repeat') # def reshape (self, *s): @@ -1958,7 +1964,8 @@ d.__setmask__(self._mask.all(axis)) return d elif type(out) is not type(self): - raise TypeError("The external array should have a type %s (got %s instead)" %\ + raise TypeError("The external array should have a type %s "\ + "(got %s instead)" %\ (type(self), type(out))) self.filled(False).any(axis=axis, out=out) if out.ndim: @@ -2011,7 +2018,7 @@ axis : int, optional Axis along which to perform the operation. If None, applies to a flattened version of the array. - dtype : {dtype}, optional + dtype : dtype, optional Datatype for the intermediary computation. If not given, the current dtype is used instead. @@ -2464,13 +2471,10 @@ """ return self.max(axis, fill_value) - self.min(axis, fill_value) - # Array methods --------------------------------------- -# conj = conjugate = _arraymethod('conjugate') copy = _arraymethod('copy') diagonal = _arraymethod('diagonal') take = _arraymethod('take') -# ravel = _arraymethod('ravel') transpose = _arraymethod('transpose') T = property(fget=lambda self:self.transpose()) swapaxes = _arraymethod('swapaxes') @@ -2583,11 +2587,8 @@ _data = ndarray.__new__(baseclass, baseshape, basetype) _mask = ndarray.__new__(ndarray, baseshape, 'b1') return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) -#MaskedArray.__dump__ = dump -#MaskedArray.__dumps__ = dumps - #####-------------------------------------------------------------------------- #---- --- Shortcuts --- #####--------------------------------------------------------------------------- @@ -2597,6 +2598,7 @@ isarray = isMaskedArray 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 = masked_singleton @@ -2885,6 +2887,8 @@ return data # OK, so we have to concatenate the masks dm = numpy.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]) # if shrink and not dm.any(): if not dm.any(): @@ -2958,10 +2962,6 @@ """ # We can't use 'frommethod', the order of arguments is different -# try: -# return a.putmask(values, mask) -# except AttributeError: -# return numpy.putmask(narray(a, copy=False), mask, values) if not isinstance(a, MaskedArray): a = a.view(MaskedArray) (valdata, valmask) = (getdata(values), getmask(values)) @@ -2970,9 +2970,6 @@ a._sharedmask = True a.mask = numpy.zeros(a.shape, dtype=bool_) numpy.putmask(a._mask, mask, valmask) -# m = numpy.zeros(a.shape, dtype=bool_) -# numpy.putmask(m, mask, valmask) -# a = masked_array(a, copy=False, subok=True, mask=m) elif a._hardmask: if valmask is not nomask: m = a._mask.copy() @@ -3094,22 +3091,6 @@ if not d._mask.any(): d._mask = nomask return d -# # Get the data as a (subclass of) MaskedArray -# xv = getdata(x) -# yv = getdata(y) -# d = numpy.choose(fc, (yv, xv)).view(MaskedArray) -# # Get the mask .................... -# xm = getmask(x) -# ym = getmask(y) -# d.mask = numpy.choose(fc, (ym, xm)) | getmask(condition) -# # Fix the dtype if one of the values was masked, to prevent an upload to float -# if y is masked: -# ndtype = xv.dtype -# elif x is masked: -# ndtype = yv.dtype -# else: -# ndtype = d.dtype -# return d.astype(ndtype) def choose (indices, t, out=None, mode='raise'): "Return array shaped like indices with elements chosen from t" @@ -3322,3 +3303,5 @@ def loads(strg): "Load a pickle from the current string.""" return cPickle.loads(strg) + +################################################################################ Modified: branches/maskedarray/numpy/ma/extras.py =================================================================== --- branches/maskedarray/numpy/ma/extras.py 2008-02-07 11:42:03 UTC (rev 4770) +++ branches/maskedarray/numpy/ma/extras.py 2008-02-07 17:00:02 UTC (rev 4771) @@ -52,8 +52,9 @@ def count_masked(arr, axis=None): """Count the number of masked elements along the given axis. - *Parameters*: - axis : {integer}, optional + Parameters + ---------- + axis : int, optional Axis along which to count. If None (default), a flattened version of the array is used. @@ -65,8 +66,9 @@ """Return an empty masked array of the given shape and dtype, where all the data are masked. - *Parameters*: - dtype : {dtype}, optional + Parameters + ---------- + dtype : dtype, optional Data type of the output. """ @@ -90,15 +92,17 @@ """Return an unbiased estimate of the variance. i.e. var = sum((x - x.mean())**2)/(size(x,axis)-1) - *Parameters*: - axis : {integer}, optional + Parameters + ---------- + axis : int, optional Axis along which to perform the operation. If None, applies to a flattened version of the array. dtype : {dtype}, optional Datatype for the intermediary computation. If not given, the current dtype is used instead. - *Notes*: + Notes + ----- The value returned is an unbiased estimate of the true variance. For the (less standard) biased estimate, use var. @@ -121,15 +125,17 @@ standard deviation is the square root of the average of the squared deviations from the mean, i.e. stdu = sqrt(varu(x)). - *Parameters*: - axis : {integer}, optional + Parameters + ---------- + axis : int, optional Axis along which to perform the operation. If None, applies to a flattened version of the array. - dtype : {dtype}, optional + dtype : dtype, optional Datatype for the intermediary computation. If not given, the current dtype is used instead. - *Notes*: + Notes + ----- The value returned is an unbiased estimate of the true standard deviation. For the biased estimate, use std. @@ -144,9 +150,8 @@ # Should we use umath.sqrt instead ? return sqrt(dvar) return sqrt(dvar) -# return a.__class__(sqrt(dvar._data), mask=dvar._mask, -# fill_value=a._fill_value) + MaskedArray.stdu = stdu MaskedArray.varu = varu @@ -300,19 +305,19 @@ def average(a, axis=None, weights=None, returned=False): """Average the array over the given axis. - *Parameters*: - axis : {integer}, optional + Parameters + ---------- + axis : int, optional Axis along which to perform the operation. If None, applies to a flattened version of the array. - weights : {sequence}, optional + weights : sequence, optional Sequence of weights. The weights must have the shape of a, or be 1D with length the size of a along the given axis. If no weights are given, weights are assumed to be 1. - returned : {boolean} - Flag indicating whether a tuple (result, sum of - weights/counts) should be returned as output (True), or - just the result (False). + returned : bool + Flag indicating whether a tuple (result, sum of weights/counts) + should be returned as output (True), or just the result (False). """ a = asarray(a) @@ -381,7 +386,8 @@ ni = ash[axis] r = [None]*len(ash) r[axis] = slice(None, None, 1) - w = eval ("w["+ repr(tuple(r)) + "] * masked_array(ones(ash, float), mask)") + w = eval ("w["+ repr(tuple(r)) + \ + "] * masked_array(ones(ash, float), mask)") n = add.reduce(a*w, axis, dtype=float_) d = add.reduce(w, axis, dtype=float_) else: @@ -415,8 +421,15 @@ - If axis is None, rows and columns are suppressed. - If axis is 0, only rows are suppressed. - If axis is 1 or -1, only columns are suppressed. + + Parameters + ---------- + axis : int, optional + Axis along which to perform the operation. + If None, applies to a flattened version of the array. - *Returns*: + Returns + ------- compressed_array : an ndarray. """ @@ -462,7 +475,15 @@ - If axis is 0, only rows are masked. - If axis is 1 or -1, only columns are masked. - Returns a *pure* ndarray. + Parameters + ---------- + axis : int, optional + Axis along which to perform the operation. + If None, applies to a flattened version of the array. + + Returns + ------- + a *pure* ndarray. """ a = asarray(a) @@ -483,12 +504,22 @@ def mask_rows(a, axis=None): """Mask whole rows of a 2D array that contain masked values. + Parameters + ---------- + axis : int, optional + Axis along which to perform the operation. + If None, applies to a flattened version of the array. """ return mask_rowcols(a, 0) def mask_cols(a, axis=None): """Mask whole columns of a 2D array that contain masked values. + Parameters + ---------- + axis : int, optional + Axis along which to perform the operation. + If None, applies to a flattened version of the array. """ return mask_rowcols(a, 1) @@ -502,12 +533,14 @@ appears in a row or column, the whole row or column is considered masked. - *Parameters*: + Parameters + ---------- strict : {boolean} Whether masked data are propagated (True) or set to 0 for the computation. - *Note*: + Notes + ----- The first argument is not conjugated. """ @@ -528,7 +561,8 @@ """Return the differences between consecutive elements of an array, possibly with prefixed and/or appended values. - *Parameters*: + Parameters + ---------- array : {array} Input array, will be flattened before the difference is taken. to_end : {number}, optional @@ -538,7 +572,8 @@ If provided, this number will be taked onto the beginning of the returned differences. - *Returns*: + Returns + ------- ed : {array} The differences. Loosely, this will be (ary[1:] - ary[:-1]). @@ -693,6 +728,11 @@ of 2 tuples, corresponding to the indices of the first and last unmasked values respectively. + Parameters + ---------- + axis : int, optional + Axis along which to perform the operation. + If None, applies to a flattened version of the array. """ a = asarray(a) if axis is None or a.ndim == 1: @@ -726,9 +766,19 @@ """Find contiguous unmasked data in a masked array along the given axis. - Return a sorted sequence of slices (start index, end index). + Parameters + ---------- + axis : int, optional + Axis along which to perform the operation. + If None, applies to a flattened version of the array. + + Returns + ------- + a sorted sequence of slices (start index, end index). - Note: Only accepts 2D arrays at most. + Notes + ----- + Only accepts 2D arrays at most. """ a = asarray(a) @@ -750,12 +800,3 @@ return result ################################################################################ -if __name__ == '__main__': - # - import numpy as N - from numpy.ma.testutils import assert_equal - if 1: - b = ones(5) - m = [1,0,0,0,0] - d = masked_array(b,mask=m) - c = mr_[d,0,0,d] From numpy-svn at scipy.org Fri Feb 8 04:48:41 2008 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 8 Feb 2008 03:48:41 -0600 (CST) Subject: [Numpy-svn] r4772 - in branches/build_with_scons/numpy: . core/src core/tests doc doc/html f2py f2py/src lib Message-ID: <20080208094841.56BB639C147@new.scipy.org> Author: jarrod.millman Date: 2008-02-08 03:48:31 -0600 (Fri, 08 Feb 2008) New Revision: 4772 Modified: branches/build_with_scons/numpy/add_newdocs.py branches/build_with_scons/numpy/core/src/arraytypes.inc.src branches/build_with_scons/numpy/core/src/multiarraymodule.c branches/build_with_scons/numpy/core/tests/test_regression.py branches/build_with_scons/numpy/ctypeslib.py branches/build_with_scons/numpy/doc/HOWTO_DOCUMENT.txt branches/build_with_scons/numpy/doc/example.py branches/build_with_scons/numpy/doc/html/example-module.html branches/build_with_scons/numpy/doc/html/example-pysrc.html branches/build_with_scons/numpy/doc/html/help.html branches/build_with_scons/numpy/doc/html/identifier-index.html branches/build_with_scons/numpy/doc/html/module-tree.html branches/build_with_scons/numpy/f2py/crackfortran.py branches/build_with_scons/numpy/f2py/src/fortranobject.c branches/build_with_scons/numpy/lib/function_base.py Log: Merge revisions 4721:4771 from the trunk Modified: branches/build_with_scons/numpy/add_newdocs.py =================================================================== --- branches/build_with_scons/numpy/add_newdocs.py 2008-02-07 17:00:02 UTC (rev 4771) +++ branches/build_with_scons/numpy/add_newdocs.py 2008-02-08 09:48:31 UTC (rev 4772) @@ -216,6 +216,7 @@ size is determined by the size of string. If sep is not empty then the string is interpreted in ASCII mode and converted to the desired number type using sep as the separator between elements (extra whitespace is ignored). + ASCII integer conversions are base-10; octal and hex are not supported. """) Modified: branches/build_with_scons/numpy/core/src/arraytypes.inc.src =================================================================== --- branches/build_with_scons/numpy/core/src/arraytypes.inc.src 2008-02-07 17:00:02 UTC (rev 4771) +++ branches/build_with_scons/numpy/core/src/arraytypes.inc.src 2008-02-08 09:48:31 UTC (rev 4772) @@ -935,7 +935,7 @@ { @btype@ result; - result = PyOS_strto at func@(str, endptr, 0); + result = PyOS_strto at func@(str, endptr, 10); *ip = (@type@) result; return 0; } Modified: branches/build_with_scons/numpy/core/src/multiarraymodule.c =================================================================== --- branches/build_with_scons/numpy/core/src/multiarraymodule.c 2008-02-07 17:00:02 UTC (rev 4771) +++ branches/build_with_scons/numpy/core/src/multiarraymodule.c 2008-02-08 09:48:31 UTC (rev 4772) @@ -3065,23 +3065,25 @@ PyArrayObject *ap1=NULL; PyArrayObject *ap2=NULL; PyArrayObject *ret=NULL; - int typenum = 0; + PyArray_Descr *dtype; NPY_BEGIN_THREADS_DEF - typenum = PyArray_ObjectType((PyObject *)op1, 0); - typenum = PyArray_ObjectType(op2, typenum); + dtype = PyArray_DescrFromObject((PyObject *)op2, op1->descr); + + /* need ap1 as contiguous array and of right type */ + Py_INCREF(dtype); + ap1 = (PyArrayObject *)PyArray_FromAny((PyObject *)op1, dtype, + 1, 1, NPY_DEFAULT, NULL); - /* need ap1 as contiguous array and of right type */ - ap1 = (PyArrayObject *)PyArray_ContiguousFromAny((PyObject *)op1, - typenum, - 1, 1); - if (ap1 == NULL) + if (ap1 == NULL) { + Py_DECREF(dtype); return NULL; + } /* need ap2 as contiguous array and of right type */ - ap2 = (PyArrayObject *)PyArray_ContiguousFromAny(op2, typenum, - 0, 0); + ap2 = (PyArrayObject *)PyArray_FromAny(op2, dtype, 0, 0, NPY_DEFAULT, NULL); + if (ap2 == NULL) goto fail; Modified: branches/build_with_scons/numpy/core/tests/test_regression.py =================================================================== --- branches/build_with_scons/numpy/core/tests/test_regression.py 2008-02-07 17:00:02 UTC (rev 4771) +++ branches/build_with_scons/numpy/core/tests/test_regression.py 2008-02-08 09:48:31 UTC (rev 4772) @@ -771,5 +771,14 @@ def check_binary_repr_0_width(self, level=rlevel): assert_equal(np.binary_repr(0,width=3),'000') + def check_fromstring(self, level=rlevel): + assert_equal(np.fromstring("12:09:09", dtype=int, sep=":"), + [12,9,9]) + + def check_searchsorted_variable_length(self, level=rlevel): + x = np.array(['a','aa','b']) + y = np.array(['d','e']) + assert_equal(x.searchsorted(y), [3,3]) + if __name__ == "__main__": NumpyTest().run() Modified: branches/build_with_scons/numpy/ctypeslib.py =================================================================== --- branches/build_with_scons/numpy/ctypeslib.py 2008-02-07 17:00:02 UTC (rev 4771) +++ branches/build_with_scons/numpy/ctypeslib.py 2008-02-08 09:48:31 UTC (rev 4772) @@ -1,8 +1,8 @@ __all__ = ['load_library', 'ndpointer', 'test', 'ctypes_load_library', - 'c_intp'] + 'c_intp', 'as_ctypes', 'as_array'] import sys, os -from numpy import integer, ndarray, dtype as _dtype, deprecate +from numpy import integer, ndarray, dtype as _dtype, deprecate, array from numpy.core.multiarray import _flagdict, flagsobj try: @@ -15,6 +15,8 @@ raise ImportError, "ctypes is not available." ctypes_load_library = _dummy load_library = _dummy + as_ctypes = _dummy + as_array = _dummy from numpy import intp as c_intp else: import numpy.core._internal as nic @@ -160,6 +162,118 @@ _pointer_type_cache[dtype] = klass return klass +if ctypes is not None: + ct = ctypes + ################################################################ + # simple types + + # maps the numpy typecodes like '`__ + Overview -------- In general, we follow the standard Python style conventions as described here: @@ -158,6 +160,11 @@ cd epydoc/src sudo python setup.py install +Since we use reST-formatted docstrings instead of the epytext markup, you will +need to include the following line near the top of your module:: + + __docformat__ = "restructuredtext en" + The appearance of some elements can be changed in the epydoc.css style sheet. Modified: branches/build_with_scons/numpy/doc/example.py =================================================================== --- branches/build_with_scons/numpy/doc/example.py 2008-02-07 17:00:02 UTC (rev 4771) +++ branches/build_with_scons/numpy/doc/example.py 2008-02-08 09:48:31 UTC (rev 4772) @@ -8,6 +8,9 @@ a line by itself, preferably preceeded by a blank line. """ +# Make sure this line is here such that epydoc 3 can parse the docstrings for +# auto-generated documentation. +__docformat__ = "restructuredtext en" import os # standard library imports first Modified: branches/build_with_scons/numpy/doc/html/example-module.html =================================================================== --- branches/build_with_scons/numpy/doc/html/example-module.html 2008-02-07 17:00:02 UTC (rev 4771) +++ branches/build_with_scons/numpy/doc/html/example-module.html 2008-02-08 09:48:31 UTC (rev 4772) @@ -56,12 +56,12 @@

Module example

source code

This is the docstring for the example.py module. Modules names should - have short, all-lowercase names. The module name may have underscores if - this improves readability.

-

Every module should have a docstring at the very top of the file. The - module's docstring may extend over multiple lines. If your docstring - does extend over multiple lines, the closing three quotation marks must - be on a line by itself, preferably preceeded by a blank line.

+have short, all-lowercase names. The module name may have underscores if +this improves readability.

+

Every module should have a docstring at the very top of the file. The +module's docstring may extend over multiple lines. If your docstring does +extend over multiple lines, the closing three quotation marks must be on +a line by itself, preferably preceeded by a blank line.

@@ -168,61 +168,61 @@ -
-One-line summary or signature.
-
-Several sentences providing an extended description. You can put
-text in mono-spaced type like so: ``var``.
-
-Parameters
-----------
-var1 : array_like
-    Array_like means all those objects -- lists, nested lists, etc. --
-    that can be converted to an array.
-var2 : integer
-    Write out the full type
-long_variable_name : {'hi', 'ho'}, optional
-    Choices in brackets, default first when optional.
-
-Returns
--------
-named : type
-    Explanation
-list
-    Explanation
-of
-    Explanation
-outputs
-    even more explaining
-
-Other Parameters
-----------------
-only_seldom_used_keywords : type
-    Explanation
-common_parametrs_listed_above : type
-    Explanation
-
-See Also
---------    
-otherfunc : relationship (optional)
-newfunc : relationship (optional)
-
-Notes
------
-Notes about the implementation algorithm (if needed).
-
-This can have multiple paragraphs as can all sections.
-
-Examples
---------
-
-examples in doctest format
-
->>> a=[1,2,3]
->>> [x + 3 for x in a]
-[4, 5, 6]
-
-
+

One-line summary or signature.

+

Several sentences providing an extended description. You can put +text in mono-spaced type like so: var.

+
+

Parameters

+
+
var1 : array_like
+
Array_like means all those objects -- lists, nested lists, etc. -- +that can be converted to an array.
+
var2 : integer
+
Write out the full type
+
long_variable_name : {'hi', 'ho'}, optional
+
Choices in brackets, default first when optional.
+
+
+
+

Returns

+
+
named : type
+
Explanation
+
list
+
Explanation
+
of
+
Explanation
+
outputs
+
even more explaining
+
+
+
+

Other Parameters

+
+
only_seldom_used_keywords : type
+
Explanation
+
common_parametrs_listed_above : type
+
Explanation
+
+
+
+

See Also

+

otherfunc : relationship (optional) +newfunc : relationship (optional)

+
+
+

Notes

+

Notes about the implementation algorithm (if needed).

+

This can have multiple paragraphs as can all sections.

+
+
+

Examples

+

examples in doctest format

+
+>>> a=[1,2,3]
+>>> [x + 3 for x in a]
+[4, 5, 6]
+
@@ -242,7 +242,7 @@

Do nothing.

-

I never saw a purple cow.

+

I never saw a purple cow.

@@ -262,7 +262,7 @@

Do nothing.

-

I never hope to see one.

+

I never hope to see one.

@@ -294,7 +294,7 @@