def inertia_eigenvectors(basepos, already_centered=False): """ Given basepos (an array of positions), compute and return (as a 2-tuple) the lists of eigenvalues and eigenvectors of the inertia tensor (computed as if all points had the same mass). These lists are always length 3, even for len(basepos) of 0,1, or 2, overlapping or colinear points, etc, though some evals will be 0 in these cases. Optional small speedup: if caller knows basepos is centered at the origin, it can say so. """ #bruce 060119 split this out of shakedown_poly_evals_evecs_axis() in chunk.py basepos = A(basepos) # make sure it's a Numeric array if not already_centered and len(basepos): center = add.reduce(basepos) / len(basepos) basepos = basepos - center # compute inertia tensor tensor = zeros((3, 3), Float) for p in basepos: rsq = dot(p, p) m = -multiply.outer(p, p) m[0, 0] += rsq m[1, 1] += rsq m[2, 2] += rsq tensor += m evals, evecs = eigenvectors(tensor) assert len(evals) == len(evecs) == 3 return evals, evecs
def pcaN3d(pointListList): '''sets up the pca for a list of list of points in 3d. solves eig problem. the pointListList is a list of sets of points of the same length.''' length = len(pointListList[0]) * 3 #know 3d points times length of list of pts oneList = [0. for count in range(length)] #bunch of 0.0s matrixList = [oneList[:] for count in range(length)] #copy list of 0.0s #let's go ahead and flatten the input list! flattenedList = flatten(pointListList) avgPt = geometry_basic.getAverageArbitraryDimension(flattenedList, dimension=length) diffs = oneList[:] for point in flattenedList: #this point has length dimensions for index in xrange(length): diffs[index] = point[index] - avgPt[index] #matrix is old plus a2 ab ac ad etc # ba b2 bc bd etc # ca cb c2 cd etc # da db dc d2 etc # etc etc etc etc etc (etc) #only compute upper diagonal now #can't get away with hardcoding anymore for row in xrange(length): for col in xrange(row, length): matrixList[row][col] += diffs[row] * diffs[col] #make symmetric for row in xrange(length): for col in xrange(0, row): matrixList[row][col] = matrixList[col][row] #print "mat" #debugging madness #for row in xrange(length): # for col in xrange(length): # print matrixList[row][col], # print " " actualMatrix = Matrix(matrixList) val,vec = eigenvectors(actualMatrix) return val, vec
def _diagonalize(self): dsyev = None try: from lapack_dsy import dsyev except ImportError: pass if dsyev is None: try: from lapack_mmtk import dsyev except ImportError: pass if dsyev is None: from LinearAlgebra import eigenvectors _symmetrize(self.array) ev, modes = eigenvectors(self.array) self.array = modes if ev.typecode() == Numeric.Complex: ev = ev.real if modes.typecode() == Numeric.Complex: modes = modes.real else: ev = Numeric.zeros((self.nmodes,), Numeric.Float) lwork = 3*self.nmodes work = Numeric.zeros((lwork,), Numeric.Float) results = dsyev('V', 'L', self.nmodes, self.array, self.nmodes, ev, work, lwork, 0) if results['info'] > 0: raise ValueError, 'Eigenvalue calculation did not converge' return ev
def inertia_eigenvectors(basepos, already_centered = False): """ Given basepos (an array of positions), compute and return (as a 2-tuple) the lists of eigenvalues and eigenvectors of the inertia tensor (computed as if all points had the same mass). These lists are always length 3, even for len(basepos) of 0,1, or 2, overlapping or colinear points, etc, though some evals will be 0 in these cases. Optional small speedup: if caller knows basepos is centered at the origin, it can say so. """ #bruce 060119 split this out of shakedown_poly_evals_evecs_axis() in chunk.py basepos = A(basepos) # make sure it's a Numeric array if not already_centered and len(basepos): center = add.reduce(basepos)/len(basepos) basepos = basepos - center # compute inertia tensor tensor = zeros((3,3),Float) for p in basepos: rsq = dot(p, p) m= - multiply.outer(p, p) m[0,0] += rsq m[1,1] += rsq m[2,2] += rsq tensor += m evals, evecs = eigenvectors(tensor) assert len(evals) == len(evecs) == 3 return evals, evecs
def diagonalization(self): """Returns the eigenvalues of a rank-2 tensor and a tensor representing the rotation matrix to the diagonalized form.""" if self.rank == 2: from LinearAlgebra import eigenvectors ev, vectors = eigenvectors(self.array) return ev, Tensor(vectors) else: raise ValueError, 'Undefined operation'
def pca(M): "Perform PCA on M, return eigenvectors and eigenvalues, sorted." T, N = shape(M) # if there are fewer rows T than columns N, use snapshot method if T < N: C = dot(M, t(M)) evals, evecsC = eigenvectors(C) # HACK: make sure evals are all positive evals = where(evals < 0, 0, evals) evecs = 1. / sqrt(evals) * dot(t(M), t(evecsC)) else: # calculate covariance matrix K = 1. / T * dot(t(M), M) evals, evecs = eigenvectors(K) # sort the eigenvalues and eigenvectors, descending order order = (argsort(evals)[::-1]) evecs = take(evecs, order, 1) evals = take(evals, order) return evals, t(evecs)
def pca(M): from Numeric import take, dot, shape, argsort, where, sqrt, transpose as t from LinearAlgebra import eigenvectors "Perform PCA on M, return eigenvectors and eigenvalues, sorted." T, N = shape(M) # if there are less rows T than columns N, use # snapshot method if T < N: C = dot(M, t(M)) evals, evecsC = eigenvectors(C) # HACK: make sure evals are all positive evals = where(evals < 0, 0, evals) evecs = 1./sqrt(evals) * dot(t(M), t(evecsC)) else: # calculate covariance matrix K = 1./T * dot(t(M), M) evals, evecs = eigenvectors(K) # sort the eigenvalues and eigenvectors, decending order order = (argsort(evals)[::-1]) evecs = take(evecs, order, 1) evals = take(evals, order) return evals, t(evecs)
def principalAxes(self): r = self._rGrid() cm = N.sum(N.sum(N.sum(self.data[..., N.NewAxis] * r))) r = r - cm[N.NewAxis, N.NewAxis, N.NewAxis, :] nx, ny, nz = self.data.shape t = 0. for i in range(nx): # make loops explicit to conserve memory for j in range(ny): for k in range(nz): t = t + self.data[i, j, k] * r[i, j, k, N.NewAxis, :] * \ r[i, j, k, :, N.NewAxis] ev, axes = eigenvectors(t) return map(lambda a, b: (Vector(a), b), axes, ev)
def pca2d(pointList): '''sets up the pca for a list of points in 2d. solves eig problem''' matrixList = [[0,0],[0,0]] #init to 0 avgPt = geometry_basic.getAverageArbitraryDimension(pointList, 2) diffs = [0,0] for point in pointList: for index in range(2): diffs[index] = point[index] - avgPt[index] #matrix is old plus a2 ab # ba b2 # only compute upper diagonal now matrixList[0][0] += diffs[0]*diffs[0] #just hardcode it matrixList[0][1] += diffs[0]*diffs[1] matrixList[1][1] += diffs[1]*diffs[1] #make symmetric matrixList[1][0] = matrixList[0][1] actualMatrix = Matrix(matrixList) val,vec = eigenvectors(actualMatrix) return val, vec
def pca3d(pointList): '''sets up the pca for a list of points in 3d. solves eig problem''' matrixList = [[0,0,0],[0,0,0],[0,0,0]] #init to 0 avgPt = geometry_basic.getAverage(pointList) diffs = [0,0,0] for point in pointList: for index in range(3): diffs[index] = point[index] - avgPt[index] #matrix is old plus a2 ab ac # ba b2 bc # ca cb c2 only compute upper diagonal now matrixList[0][0] += diffs[0]*diffs[0] #just hardcode it matrixList[0][1] += diffs[0]*diffs[1] matrixList[0][2] += diffs[0]*diffs[2] matrixList[1][1] += diffs[1]*diffs[1] matrixList[1][2] += diffs[1]*diffs[2] matrixList[2][2] += diffs[2]*diffs[2] #make symmetric matrixList[1][0] = matrixList[0][1] matrixList[2][0] = matrixList[0][2] matrixList[2][1] = matrixList[1][2] actualMatrix = Matrix(matrixList) val,vec = eigenvectors(actualMatrix) return val, vec
def solve(self): self.eval, self.evec = eigenvectors(self.H) self.eval, self.evec = evsort(self.eval, self.evec) self.renormalize() return