diff options
author | Travis Oliphant <oliphant@enthought.com> | 2005-09-14 22:28:28 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2005-09-14 22:28:28 +0000 |
commit | 61b48697e440f76b2337c790ec5ca763cd55200b (patch) | |
tree | da64ece2ba0b6b97deb51c36ca320c64102e9baa /base/function_base.py | |
parent | 575d373479c63a42bc4a729a058da31a74e75d3e (diff) | |
download | numpy-61b48697e440f76b2337c790ec5ca763cd55200b.tar.gz |
Moving things to live under scipy
Diffstat (limited to 'base/function_base.py')
-rw-r--r-- | base/function_base.py | 620 |
1 files changed, 0 insertions, 620 deletions
diff --git a/base/function_base.py b/base/function_base.py deleted file mode 100644 index 83df69757..000000000 --- a/base/function_base.py +++ /dev/null @@ -1,620 +0,0 @@ -import types -import numeric as _nx -from numeric import ones, zeros, arange, concatenate -from umath import pi, multiply, add, arctan2, maximum, minimum -from oldnumeric import ravel, nonzero, array, choose, \ - sometrue, alltrue, reshape, any, all -from type_check import ScalarType, isscalar -from shape_base import squeeze, atleast_1d -from _compiled_base import digitize, bincount, _insert -from index_tricks import r_ - -__all__ = ['round','logspace','linspace','fix','mod', - 'select','trim_zeros','amax','amin', 'alen', - 'ptp','cumsum','take', 'copy', - 'prod','cumprod','diff','gradient','angle','unwrap','sort_complex', - 'disp','unique','extract','insert','nansum','nanmax','nanargmax', - 'nanargmin','nanmin','sum','vectorize','asarray_chkfinite', - 'average','histogram','bincount','digitize'] - -def logspace(start,stop,num=50,endpoint=1): - """ Evenly spaced samples on a logarithmic scale. - - Return num evenly spaced samples from 10**start to 10**stop. If - endpoint=1 then last sample is 10**stop. - """ - if num <= 0: return array([]) - if endpoint: - step = (stop-start)/float((num-1)) - y = _nx.arange(0,num) * step + start - else: - step = (stop-start)/float(num) - y = _nx.arange(0,num) * step + start - return _nx.power(10.0,y) - -def linspace(start,stop,num=50,endpoint=1,retstep=0): - """ Evenly spaced samples. - - Return num evenly spaced samples from start to stop. If endpoint=1 then - last sample is stop. If retstep is 1 then return the step value used. - """ - if num <= 0: return array([]) - if endpoint: - step = (stop-start)/float((num-1)) - y = _nx.arange(0,num) * step + start - else: - step = (stop-start)/float(num) - y = _nx.arange(0,num) * step + start - if retstep: - return y, step - else: - return y - -def histogram(x, bins=10, range=None, normed=0): - x = asarray(x).ravel() - if not iterable(bins): - if range is None: - range = (x.min(), x.max()) - mn, mx = [x+0.0 for x in range] - if mn == mx: - mn -= 0.5 - mx += 0.5 - bins = linspace(mn, mx, bins) - - n = x.sort().searchsorted(bins) - n = concatenate([n, [len(x)]]) - n = n[1:]-n[:-1] - - if normed: - db = bins[1] - bins[0] - return 1.0/(x.size*db) * n, bins - else: - return n, bins - -def average (a, axis=0, weights=None, returned=0): - """average(a, axis=0, weights=None) - Computes average along indicated axis. - If axis is None, average over the entire array. - Inputs can be integer or floating types; result is type Float. - - If weights are given, result is: - sum(a*weights)/(sum(weights)) - weights must have a's shape or be the 1-d with length the size - of a in the given axis. Integer weights are converted to Float. - - Not supplying weights is equivalent to supply weights that are - all 1. - - If returned, return a tuple: the result and the sum of the weights - or count of values. The shape of these two results will be the same. - - raises ZeroDivisionError if appropriate when result is scalar. - (The version in MA does not -- it returns masked values). - """ - if axis is None: - a = array(a).ravel() - if weights is None: - n = add.reduce(a) - d = len(a) * 1.0 - else: - w = array(weights).ravel() * 1.0 - n = add.reduce(a*w) - d = add.reduce(w) - else: - a = array(a) - ash = a.shape - if ash == (): - a.shape = (1,) - if weights is None: - n = add.reduce(a, axis) - d = ash[axis] * 1.0 - if returned: - d = ones(shape(n)) * d - else: - w = array(weights, copy=0) * 1.0 - wsh = w.shape - if wsh == (): - wsh = (1,) - if wsh == ash: - n = add.reduce(a*w, axis) - d = add.reduce(w, axis) - elif wsh == (ash[axis],): - ni = ash[axis] - r = [newaxis]*ni - r[axis] = slice(None,None,1) - w1 = eval("w["+repr(tuple(r))+"]*ones(ash, Float)") - n = add.reduce(a*w1, axis) - d = add.reduce(w1, axis) - else: - raise ValueError, 'average: weights wrong shape.' - - if not isinstance(d, ArrayType): - if d == 0.0: - raise ZeroDivisionError, 'Numeric.average, zero denominator' - if returned: - return n/d, d - else: - return n/d - - -def isaltered(): - val = str(type(_nx.array([1]))) - return 'scipy' in val - -round = _nx.around - -def asarray_chkfinite(x): - """Like asarray except it checks to be sure no NaNs or Infs are present. - """ - x = asarray(x) - if not all(_nx.isfinite(x)): - raise ValueError, "Array must not contain infs or nans." - return x - - - -def fix(x): - """ Round x to nearest integer towards zero. - """ - x = asarray(x) - y = _nx.floor(x) - return _nx.where(x<0,y+1,y) - -def mod(x,y): - """ x - y*floor(x/y) - - For numeric arrays, x % y has the same sign as x while - mod(x,y) has the same sign as y. - """ - return x - y*_nx.floor(x*1.0/y) - -def select(condlist, choicelist, default=0): - """ Returns an array comprised from different elements of choicelist - depending on the list of conditions. - - condlist is a list of condition arrays containing ones or zeros - - choicelist is a list of choice matrices (of the "same" size as the - arrays in condlist). The result array has the "same" size as the - arrays in choicelist. If condlist is [c0,...,cN-1] then choicelist - must be of length N. The elements of the choicelist can then be - represented as [v0,...,vN-1]. The default choice if none of the - conditions are met is given as the default argument. - - The conditions are tested in order and the first one statisfied is - used to select the choice. In other words, the elements of the - output array are found from the following tree (notice the order of - the conditions matters): - - if c0: v0 - elif c1: v1 - elif c2: v2 - ... - elif cN-1: vN-1 - else: default - - Note, that one of the condition arrays must be large enough to handle - the largest array in the choice list. - """ - n = len(condlist) - n2 = len(choicelist) - if n2 != n: - raise ValueError, "List of cases, must be same length as the list of conditions." - choicelist.insert(0,default) - S = 0 - pfac = 1 - for k in range(1,n+1): - S += k * pfac * asarray(condlist[k-1]) - if k < n: - pfac *= (1-asarray(condlist[k-1])) - # handle special case of a 1-element condition but - # a multi-element choice - if type(S) in ScalarType or max(asarray(S).shape)==1: - pfac = asarray(1) - for k in range(n2+1): - pfac = pfac + asarray(choicelist[k]) - S = S*ones(asarray(pfac).shape) - return choose(S, tuple(choicelist)) - -def _asarray1d(arr): - """Ensure 1d array for one array. - """ - m = asarray(arr) - if len(m.shape)==0: - m = reshape(m,(1,)) - return m - -def copy(a): - """Return an array copy of the object. - """ - return array(a,copy=1) - -def take(a, indices, axis=0): - """Selects the elements in indices from array a along given axis. - """ - try: - a = _nx.take(a,indices,axis) - except ValueError: # a is scalar - pass - return a - -def _no_axis_is_all(function, m, axis): - if axis is None: - m = ravel(m) - axis = 0 - else: - m = _asarray1d(m) - if _nx.which[0] == "numeric": - r = function(m, axis) - else: - import numarray as _na - _na.Error.pushMode(overflow="raise") - try: - r = function(m, axis) - finally: - _na.Error.popMode() - return r - -# Basic operations -def amax(m,axis=-1): - """Returns the maximum of m along dimension axis. - """ - return _no_axis_is_all(maximum.reduce, m, axis) - -def amin(m,axis=-1): - """Returns the minimum of m along dimension axis. - """ - return _no_axis_is_all(minimum.reduce, m, axis) - -def alen(m): - """Returns the length of a Python object interpreted as an array - """ - return len(asarray(m)) - -# Actually from Basis, but it fits in so naturally here... - -def _amin_amax(m, axis): - return amax(m,axis)-amin(m,axis) - -def ptp(m,axis=-1): - """Returns the maximum - minimum along the the given dimension - """ - return _no_axis_is_all(_amin_amax, m, axis) - -def cumsum(m,axis=-1): - """Returns the cumulative sum of the elements along the given axis - """ - return _no_axis_is_all(add.accumulate, m, axis) - -def prod(m,axis=-1): - """Returns the product of the elements along the given axis - """ - return _no_axis_is_all(multiply.reduce, m, axis) - -def cumprod(m,axis=-1): - """Returns the cumulative product of the elments along the given axis - """ - return _no_axis_is_all(multiply.accumulate, m, axis) - -def gradient(f,*varargs): - """Calculate the gradient of an N-dimensional scalar function. - - Uses central differences on the interior and first differences on boundaries - to give the same shape. - - Inputs: - - f -- An N-dimensional array giving samples of a scalar function - - varargs -- 0, 1, or N scalars giving the sample distances in each direction - - Outputs: - - N arrays of the same shape as f giving the derivative of f with respect - to each dimension. - """ - N = len(f.shape) # number of dimensions - n = len(varargs) - if n==0: - dx = [1.0]*N - elif n==1: - dx = [varargs[0]]*N - elif n==N: - dx = list(varargs) - else: - raise SyntaxError, "Invalid number of arguments" - - # use central differences on interior and first differences on endpoints - - print dx - outvals = [] - - # create slice objects --- initially all are [:,:,...,:] - slice1 = [slice(None)]*N - slice2 = [slice(None)]*N - slice3 = [slice(None)]*N - - otype = f.dtypechar - if otype not in ['f','d','F','D']: - otype = 'd' - - for axis in range(N): - # select out appropriate parts for this dimension - out = zeros(f.shape, f.dtypechar) - slice1[axis] = slice(1,-1) - slice2[axis] = slice(2,None) - slice3[axis] = slice(None,-2) - # 1d equivalent -- out[1:-1] = (f[2:] - f[:-2])/2.0 - out[slice1] = (f[slice2] - f[slice3])/2.0 - slice1[axis] = 0 - slice2[axis] = 1 - slice3[axis] = 0 - # 1d equivalent -- out[0] = (f[1] - f[0]) - out[slice1] = (f[slice2] - f[slice3]) - slice1[axis] = -1 - slice2[axis] = -1 - slice3[axis] = -2 - # 1d equivalent -- out[-1] = (f[-1] - f[-2]) - out[slice1] = (f[slice2] - f[slice3]) - - # divide by step size - outvals.append(out / dx[axis]) - - # reset the slice object in this dimension to ":" - slice1[axis] = slice(None) - slice2[axis] = slice(None) - slice3[axis] = slice(None) - - if N == 1: - return outvals[0] - else: - return outvals - - -def diff(x, n=1,axis=-1): - """Calculates the nth order, discrete difference along given axis. - """ - if n==0: - return x - if n<0: - raise ValueError,'Order must be non-negative but got ' + `n` - x = _asarray1d(x) - nd = len(x.shape) - slice1 = [slice(None)]*nd - slice2 = [slice(None)]*nd - slice1[axis] = slice(1,None) - slice2[axis] = slice(None,-1) - if n > 1: - return diff(x[slice1]-x[slice2], n-1, axis=axis) - else: - return x[slice1]-x[slice2] - -def angle(z,deg=0): - """Return the angle of complex argument z.""" - if deg: - fact = 180/pi - else: - fact = 1.0 - z = asarray(z) - if z.dtypechar in ['D','F']: - zimag = z.imag - zreal = z.real - else: - zimag = 0 - zreal = z - return arctan2(zimag,zreal) * fact - -def unwrap(p,discont=pi,axis=-1): - """unwraps radian phase p by changing absolute jumps greater than - discont to their 2*pi complement along the given axis. - """ - p = asarray(p) - nd = len(p.shape) - dd = diff(p,axis=axis) - slice1 = [slice(None,None)]*nd # full slices - slice1[axis] = slice(1,None) - ddmod = mod(dd+pi,2*pi)-pi - _nx.putmask(ddmod,(ddmod==-pi) & (dd > 0),pi) - ph_correct = ddmod - dd; - _nx.putmask(ph_correct,abs(dd)<discont,0) - up = array(p,copy=1,typecode='d') - up[slice1] = p[slice1] + cumsum(ph_correct,axis) - return up - -def sort_complex(a): - """ Doesn't currently work for integer arrays -- only float or complex. - """ - a = asarray(a,typecode=a.dtypechar.upper()) - def complex_cmp(x,y): - res = cmp(x.real,y.real) - if res == 0: - res = cmp(x.imag,y.imag) - return res - l = a.tolist() - l.sort(complex_cmp) - return array(l) - -def trim_zeros(filt,trim='fb'): - """ Trim the leading and trailing zeros from a 1D array. - - Example: - >>> import scipy - >>> a = array((0,0,0,1,2,3,2,1,0)) - >>> scipy.trim_zeros(a) - array([1, 2, 3, 2, 1]) - """ - first = 0 - if 'f' in trim or 'F' in trim: - for i in filt: - if i != 0.: break - else: first = first + 1 - last = len(filt) - if 'B' in trim or 'B' in trim: - for i in filt[::-1]: - if i != 0.: break - else: last = last - 1 - return filt[first:last] - -def unique(inseq): - """Returns unique items in 1-dimensional sequence. - """ - set = {} - for item in inseq: - set[item] = None - return asarray(set.keys()) - -def where(condition,x=None,y=None): - """If x and y are both None, then return the (1-d equivalent) indices - where condition is true. Otherwise, return an array shaped like - condition with elements of x and y in the places where condition is - true or false respectively. - """ - if (x is None) and (y is None): - # Needs work for multidimensional arrays - return nonzero(ravel(condition)) - else: - return choose(not_equal(condition, 0), (y,x)) - -def extract(condition, arr): - """Elements of ravel(condition) where ravel(condition) is true (1-d) - - Equivalent of compress(ravel(condition), ravel(arr)) - """ - return _nx.take(ravel(arr), nonzero(ravel(condition))) - -def insert(arr, mask, vals): - """Similar to putmask arr[mask] = vals but 1d array vals has the - same number of elements as the non-zero values of mask. Inverse of extract. - """ - return _nx._insert(arr, mask, vals) - -def nansum(x,axis=-1): - """Sum the array over the given axis treating nans as missing values. - """ - x = _asarray1d(x).copy() - _nx.putmask(x,isnan(x),0) - return _nx.sum(x,axis) - -def nanmin(x,axis=-1): - """Find the minimium over the given axis ignoring nans. - """ - x = _asarray1d(x).copy() - _nx.putmask(x,isnan(x),inf) - return amin(x,axis) - -def nanargmin(x,axis=-1): - """Find the indices of the minimium over the given axis ignoring nans. - """ - x = _asarray1d(x).copy() - _nx.putmask(x,isnan(x),inf) - return argmin(x,axis) - - -def nanmax(x,axis=-1): - """Find the maximum over the given axis ignoring nans. - """ - x = _asarray1d(x).copy() - _nx.putmask(x,isnan(x),-inf) - return amax(x,axis) - -def nanargmax(x,axis=-1): - """Find the maximum over the given axis ignoring nans. - """ - x = _asarray1d(x).copy() - _nx.putmask(x,isnan(x),-inf) - return argmax(x,axis) - -def disp(mesg, device=None, linefeed=1): - """Display a message to device (default is sys.stdout) with(out) linefeed. - """ - if device is None: - import sys - device = sys.stdout - if linefeed: - device.write('%s\n' % mesg) - else: - device.write('%s' % mesg) - device.flush() - return - -class vectorize: - """ - vectorize(somefunction) Generalized Function class. - - Description: - - Define a vectorized function which takes nested sequence - objects or numerix arrays as inputs and returns a - numerix array as output, evaluating the function over successive - tuples of the input arrays like the python map function except it uses - the broadcasting rules of numerix Python. - - Input: - - somefunction -- a Python function or method - - Example: - - def myfunc(a,b): - if a > b: - return a-b - else - return a+b - - vfunc = vectorize(myfunc) - - >>> vfunc([1,2,3,4],2) - array([3,4,1,2]) - - """ - def __init__(self,pyfunc,otypes=None,doc=None): - if not callable(pyfunc) or type(pyfunc) is types.ClassType: - raise TypeError, "Object is not a callable Python object." - self.thefunc = pyfunc - if doc is None: - self.__doc__ = pyfunc.__doc__ - else: - self.__doc__ = doc - if otypes is None: - self.otypes='' - else: - if isinstance(otypes,types.StringType): - self.otypes=otypes - else: - raise ValueError, "Output types must be a string." - - def __call__(self,*args): - try: - return squeeze(arraymap(self.thefunc,args,self.otypes)) - except IndexError: - return self.zerocall(*args) - - def zerocall(self,*args): - # one of the args was a zeros array - # return zeros for each output - # first --- find number of outputs - # get it from self.otypes if possible - # otherwise evaluate function at 0.9 - N = len(self.otypes) - if N==1: - return zeros((0,),'d') - elif N !=0: - return (zeros((0,),'d'),)*N - newargs = [] - args = atleast_1d(args) - for arg in args: - if arg.dtypechar != 'O': - newargs.append(0.9) - else: - newargs.append(arg[0]) - newargs = tuple(newargs) - try: - res = self.thefunc(*newargs) - except: - raise ValueError, "Zerocall is failing. "\ - "Try using otypes in vectorize." - if isscalar(res): - return zeros((0,),'d') - else: - return (zeros((0,),'d'),)*len(res) - |