[MATRIX-SIG] Simple UserArray and isarray()

Janko Hauser jhauser@ifm.uni-kiel.de
Sat, 14 Mar 1998 14:35:20 +0100 (CET)


So here is a UserArray class which noirmaly returns an array, only the
slicing and inplace changing methods return an UserArray. I need to
change asarray from Numeric.py to deal with this class or subclasses
of this.  The other functions should treat this as an array. There is
also an isarray() function which can handle UserArrays. This is only
to show the other possibility. And then there is a small typo in
Timothy's UserArray at line 205:

The line:
 return arg_class(self.ufunc(a), a, b)

should be:
 return arg_class(self.ufunc(a), a)

and another one at line 13:
self.__dict__['name'] = string.split(str(self.__class__))[1]

should be:
self.__dict__['name'] = string.split(str(self.__class__),'.')[-1]

with regards,

__Janko

### Simple UserArray
#!/usr/local/bin/python
from Numeric import *
import string
import copy


class UserArray:
    def __init__(self, data, typecode=None, copy=0):
	if typecode == None:
	    self.array = array(data,copy=copy)
	else:
	    self.array = array(data, typecode, copy)

	self.__dict__['shape'] = self.array.shape
	self.name = string.split(str(self.__class__),'.')[-1]

    def __setattr__(self,att,value):
        # perhaps the name attribute should also be shielded
	if att == 'shape':
	    self.__dict__['shape']=value
	    self.array.shape=value
	else:
            # This is normal class behavior
	    self.__dict__[att]=value
            # As this is questionable, one can choose this
            # raise AttributeError, "Attribute cannot be set"

    def __repr__(self):
	return self.name+"\n"+str(self.array)

    def __array__(self, typec = 0, copy = 1):
        if typec:
            stype = typec
        else:
            stype = self.typecode()
        if copy:
            return self.array # this returns only the array
        else:
            return self._rc(self.array, stype) # this returns only the array
            
        #return self._rc(self.array, typecode=stype)

    # If array is used as a sequence
    def __len__(self): return len(self.array)

    def __getitem__(self, index): 
	return self._rc(self.array[index])

    def __getslice__(self, i, j): 
	return self._rc(self.array[i:j])

    def __float__(self):
	return self._rc(self.array.astype(Float))

    def __int__(self):
	return self._rc(self.array.astype(Int))

    def __setitem__(self, index, value): 
        self.array[index] = masarray(value, self.typecode())[...]
    
    def __setslice__(self, i, j, value): 
        self.array[i:j] = masarray(value, self.typecode())[...]

    def __del__(self):
 	for att in dir(self):
 	    delattr(self, att)
        
        del(self)

    # These are changing the values, so make arrays
    def __abs__(self): return absolute(self.array) 
    def __neg__(self): return -self.array          

    def __add__(self, other): 
        return self.array+masarray(other)

    __radd__ = __add__

    def __sub__(self, other): 
        return self.array-masarray(other)

    def __rsub__(self, other): 
        return masarray(other)-self.array

    def __mul__(self, other): 
        return multiply(self.array, masarray(other))

    __rmul__ = __mul__

    def __div__(self, other): 
        return divide(self.array,masarray(other))

    def __rdiv__(self, other): 
        return divide(masarray(other),self.array)

    def __pow__(self,other): 
        return power(self.array,masarray(other))

    def __rpow__(self,other): 
        return power(masarray(other),self.array)

    def __sqrt__(self): 
	return sqrt(self.array)

    def tostring(self): return self.array.tostring()

    def byteswapped(self): return self._rc(self.array.byteswapped())
    def asType(self, typecode): return self._rc(self.array.asType(typecode))
   
    def typecode(self): return self.array.typecode()
    def itemsize(self): return self.array.itemsize()
    def isContiguous(self): return self.array.isContiguous()

UserArray._rc=UserArray

def masarray(a, typecode=None):
    """
    If a is an array of the right type return a, else build a new
    array.
    """
    if typecode == None:
        if isarray(a):
            return a
        else:
            return array(a)
    else:
        if isarray(a):
            if a.typecode() == typecode:
                return a
            else:
                return a.astype(typecode) # this is actually a copy
        else:
            return array(a, typecode) # this also

def isarray(a):
    """
    Test for arrayobjects. Can also handle UserArray instances
    """
    try:
        sh = list(a.shape)
    except AttributeError:
        return 0
    try:
        sh[0] = sh[0]+1
        a.shape = sh
    except ValueError:
        return 1
    except IndexError:
        return 1 # ? this is a scalar array
    return 0

def st(line,comment=''):
    import __main__
    print '>>> '+line+' #'+comment
    exec line in __main__.__dict__,__main__.__dict__

def test():
    st('a=UserArray(arange(9))')
    st('a.shape=(3,3)')
    st('b=a','This should be without copy')
    st('b[0,:]=array([1,2,2])')
    st('print b;print a','Two refs to the same object')
    st('d=array(a)','This should produce a new array')
    st('dd=masarray(a)','No copy but a new UserArray')
    st('print type(d); print type(dd)')
    st('d=sin(a);print d;print type(d)')
    st('print less(a,2)')
    st('d=where(less(a,3),10,0); print d; print type(d)')
    st('a[0,0]=1; print a')
    st('a[0,1]=array(10); print a')
    st('print repeat(a[NewAxis,:,:],(3,))')
    st('print concatenate((a,a))')

#############################################################
# Test of class UserArray
#############################################################
if __name__ == '__main__':

    test()

_______________
MATRIX-SIG  - SIG on Matrix Math for Python

send messages to: matrix-sig@python.org
administrivia to: matrix-sig-request@python.org
_______________