Source code for topo.base.arrayutil

"""
General utility functions and classes for Topographica that require numpy.
"""

import re

import numpy as np
from numpy import ufunc

import param

# Ask numpy to print even relatively large arrays by default
np.set_printoptions(threshold=200*200)


[docs]def ufunc_script_repr(f,imports,prefix=None,settings=None): """ Return a runnable representation of the numpy ufunc f, and an import statement for its module. """ # (could probably be generalized if required, because module is # f.__class__.__module__) imports.append('import numpy') return 'numpy.'+f.__name__
from param import parameterized parameterized.script_repr_reg[ufunc]=ufunc_script_repr
[docs]def L2norm(v): """ Return the L2 norm of the vector v. """ return np.sqrt(np.dot(v,v))
[docs]def divisive_normalization(weights): """Divisively normalize an array to sum to 1.0""" s = weights.sum() if s != 0: factor = 1.0/s weights *= factor
[docs]def add_border(matrix,width=1,value=0.0): """ Returns a new matrix consisting of the given matrix with a border or margin of the given width filled with the given value. """ rows,cols = matrix.shape hborder = np.array([ [value]*(cols+2*width) ]*width) vborder = np.array([ [value]*width ] * rows) temp = np.concatenate( (vborder,matrix,vborder), axis=1) return np.concatenate( (hborder,temp,hborder) )
[docs]def arg(z): """ Return the complex argument (phase) of z. (z in radians.) """ z = z + complex(0,0) # so that arg(z) also works for real z return np.arctan2(z.imag, z.real)
[docs]def octave_str(mat,name="mat",owner=""): """ Print the given Numpy matrix in Octave format, listing the given matrix name and the object that owns it (if any). """ # This just prints the string version of the matrix and does search/replace # to convert it; there may be a faster or easier way. mstr=np.array2string(mat) mstr=re.sub('\n','',mstr) mstr=re.sub('[[]','',mstr) mstr=re.sub('[]]','\n',mstr) return ("# Created from %s %s\n# name: %s\n# type: matrix\n# rows: %s\n# columns: %s\n%s" % (owner,name,name,mat.shape[0],mat.shape[1],mstr))
[docs]def octave_output(filename,mat,name="mat",owner=""): """Writes the given matrix to a new file of the given name, in Octave format.""" f = open(filename,'w') f.write(octave_str(mat,name,owner)) f.close()
[docs]def centroid(array_2D): """Return the centroid (center of gravity) for a 2D array.""" rows,cols = array_2D.shape rsum=0 csum=0 rmass_sum=0 cmass_sum=0 for r in xrange(rows): row_sum = array_2D[r,:].sum() rsum += r*row_sum rmass_sum += row_sum for c in xrange(cols): col_sum = array_2D[:,c].sum() csum += c*col_sum cmass_sum += col_sum row_centroid= rsum/rmass_sum col_centroid= csum/cmass_sum return row_centroid, col_centroid
[docs]def clip_lower(arr,lower_bound): """ In-place, one-sided version of numpy.clip(). i.e. numpy.clip(arr,a_min=lower_bound,out=arr) if it existed. """ np.maximum(arr,lower_bound,arr)
[docs]def clip_upper(arr,upper_bound): """ In-place, one-sided version of numpy.clip(). i.e. numpy.clip(arr,a_max=upper_bound,out=arr) if it existed. """ np.minimum(arr,upper_bound,arr)
[docs]def wrap(lower, upper, x): """ Circularly alias the numeric value x into the range [lower,upper). Valid for cyclic quantities like orientations or hues. """ #I have no idea how I came up with this algorithm; it should be simplified. # # Note that Python's % operator works on floats and arrays; # usually one can simply use that instead. E.g. to wrap array or # scalar x into 0,2*pi, just use "x % (2*pi)". range_=upper-lower return lower + np.fmod(x-lower + 2*range_*(1-np.floor(x/(2*range_))), range_)
[docs]def array_argmax(arr): "Returns the coordinates of the maximum element in the given array." return np.unravel_index(arr.argmax(),arr.shape) # CB: Is this of general interest? Used in gcal.ty.
[docs]class DivideWithConstant(param.Parameterized): """ Divide two scalars or arrays with a constant (c) offset on the denominator to allow setting the gain or to avoid divide-by-zero issues. The non-constant part of the denominator (y) is clipped to ensure that it has only positive values. """ c = param.Number(default=1.0) def __call__(self, x, y): return np.divide(x,np.maximum(y,0)+self.c)
[docs]class MultiplyWithConstant(param.Parameterized): """ Allows multiplying with a constant offset parameter. Useful to ensure positive scaling of responses. """ c = param.Number(default=1.0) def __call__(self, x, y): return np.multiply(x, np.maximum(y+self.c, 0))