def glr_Uaxes(self, position, U, prob, color, line_width): """Draw the anisotropic axies of the atom at the given probability. """ ## rotate U R = self.matrix[:3, :3] Ur = numpy.dot(numpy.dot(R, U), numpy.transpose(R)) evals, evecs = linalg.eigenvectors(Ur)
def findQuaternionMatrix(collection, point_ref, conf1, conf2 = None, matrix = True ): universe = collection.universe() if conf1.universe != universe: raise ValueError, "conformation is for a different universe" if conf2 is None: conf1, conf2 = conf2, conf1 else: if conf2.universe != universe: raise ValueError, "conformation is for a different universe" ref = conf1 conf = conf2 weights = universe.masses() weights = weights/collection.mass() ref_cms = point_ref.position().array pos = N.zeros((3,), N.Float) pos = point_ref.position(conf).array possq = 0. cross = N.zeros((3, 3), N.Float) for a in collection.atomList(): r = a.position(conf).array - pos r_ref = a.position(ref).array-ref_cms w = weights[a] possq = possq + w*N.add.reduce(r*r) \ + w*N.add.reduce(r_ref*r_ref) cross = cross + w*r[:, N.NewAxis]*r_ref[N.NewAxis, :] k = N.zeros((4, 4), N.Float) k[0, 0] = -cross[0, 0]-cross[1, 1]-cross[2, 2] k[0, 1] = cross[1, 2]-cross[2, 1] k[0, 2] = cross[2, 0]-cross[0, 2] k[0, 3] = cross[0, 1]-cross[1, 0] k[1, 1] = -cross[0, 0]+cross[1, 1]+cross[2, 2] k[1, 2] = -cross[0, 1]-cross[1, 0] k[1, 3] = -cross[0, 2]-cross[2, 0] k[2, 2] = cross[0, 0]-cross[1, 1]+cross[2, 2] k[2, 3] = -cross[1, 2]-cross[2, 1] k[3, 3] = cross[0, 0]+cross[1, 1]-cross[2, 2] for i in range(1, 4): for j in range(i): k[i, j] = k[j, i] k = 2.*k for i in range(4): k[i, i] = k[i, i] + possq - N.add.reduce(pos*pos) import numpy.oldnumeric.linear_algebra as LinearAlgebra e, v = LinearAlgebra.eigenvectors(k) i = N.argmin(e) v = v[i] if v[0] < 0: v = -v if e[i] <= 0.: rms = 0. else: rms = N.sqrt(e[i]) if matrix: emax = N.argmax(e) QuatMatrix = v return Quaternion.Quaternion(QuatMatrix),v, e, e[i],e[emax], rms else: return Quaternion.Quaternion(v), Vector(ref_cms), Vector(pos), rms
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 numpy.oldnumeric.linear_algebra 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 calc_inertia_tensor(atom_iter, origin): """Calculate a moment-of-inertia tensor at the given origin assuming all atoms have the same mass. """ I = numpy.zeros((3, 3), float) for atm in atom_iter: x = atm.position - origin I[0, 0] += x[1]**2 + x[2]**2 I[1, 1] += x[0]**2 + x[2]**2 I[2, 2] += x[0]**2 + x[1]**2 I[0, 1] += -x[0] * x[1] I[1, 0] += -x[0] * x[1] I[0, 2] += -x[0] * x[2] I[2, 0] += -x[0] * x[2] I[1, 2] += -x[1] * x[2] I[2, 1] += -x[1] * x[2] evals, evecs = linalg.eigenvectors(I) ## order the tensor such that the largest ## principal component is along the z-axis, and ## the second largest is along the y-axis if evals[0] >= evals[1] and evals[0] >= evals[2]: if evals[1] >= evals[2]: R = numpy.array((evecs[2], evecs[1], evecs[0]), float) else: R = numpy.array((evecs[1], evecs[2], evecs[0]), float) elif evals[1] >= evals[0] and evals[1] >= evals[2]: if evals[0] >= evals[2]: R = numpy.array((evecs[2], evecs[0], evecs[1]), float) else: R = numpy.array((evecs[0], evecs[2], evecs[1]), float) elif evals[2] >= evals[0] and evals[2] >= evals[1]: if evals[0] >= evals[1]: R = numpy.array((evecs[1], evecs[0], evecs[2]), float) else: R = numpy.array((evecs[0], evecs[1], evecs[2]), float) ## make sure the tensor is right-handed if numpy.allclose(linalg.determinant(R), -1.0): I = numpy.identity(3, float) I[0, 0] = -1.0 R = numpy.dot(I, R) assert numpy.allclose(linalg.determinant(R), 1.0) return R
def calc_inertia_tensor(atom_iter, origin): """Calculate a moment-of-inertia tensor at the given origin assuming all atoms have the same mass. """ I = numpy.zeros((3,3), float) for atm in atom_iter: x = atm.position - origin I[0,0] += x[1]**2 + x[2]**2 I[1,1] += x[0]**2 + x[2]**2 I[2,2] += x[0]**2 + x[1]**2 I[0,1] += - x[0]*x[1] I[1,0] += - x[0]*x[1] I[0,2] += - x[0]*x[2] I[2,0] += - x[0]*x[2] I[1,2] += - x[1]*x[2] I[2,1] += - x[1]*x[2] evals, evecs = linalg.eigenvectors(I) ## order the tensor such that the largest ## principal component is along the z-axis, and ## the second largest is along the y-axis if evals[0] >= evals[1] and evals[0] >= evals[2]: if evals[1] >= evals[2]: R = numpy.array((evecs[2], evecs[1], evecs[0]), float) else: R = numpy.array((evecs[1], evecs[2], evecs[0]), float) elif evals[1] >= evals[0] and evals[1] >= evals[2]: if evals[0] >= evals[2]: R = numpy.array((evecs[2], evecs[0], evecs[1]), float) else: R = numpy.array((evecs[0], evecs[2], evecs[1]), float) elif evals[2] >= evals[0] and evals[2] >= evals[1]: if evals[0] >= evals[1]: R = numpy.array((evecs[1], evecs[0], evecs[2]), float) else: R = numpy.array((evecs[0], evecs[1], evecs[2]), float) ## make sure the tensor is right-handed if numpy.allclose(linalg.determinant(R), -1.0): I = numpy.identity(3, float) I[0,0] = -1.0 R = numpy.dot(I, R) assert numpy.allclose(linalg.determinant(R), 1.0) return R
def PrincipalComponents(mat,reverseOrder=1): """ do a principal components analysis """ import numpy.oldnumeric.linear_algebra as LinearAlgebra covMat = FormCorrelationMatrix(mat) eigenVals,eigenVects = LinearAlgebra.eigenvectors(covMat) try: eigenVals = eigenVals.real except: pass try: eigenVects = eigenVects.real except: pass # and now sort: ptOrder = numpy.argsort(eigenVals).tolist() if reverseOrder: ptOrder.reverse() eigenVals = numpy.array([eigenVals[x] for x in ptOrder]) eigenVects = numpy.array([eigenVects[x] for x in ptOrder]) return eigenVals,eigenVects
def SuperimposePoints(src_points, dst_points): """Takes two 1:1 set of points and returns a 3x3 rotation matrix and translation vector. """ num_points = src_points.shape[0] ## shift both sets of coordinates to their centroids src_org = numpy.add.reduce(src_points) / float(src_points.shape[0]) dst_org = numpy.add.reduce(dst_points) / float(dst_points.shape[0]) X = numpy.add(src_points, -src_org) Y = numpy.add(dst_points, -dst_org) xy2n = 0.0 R = numpy.zeros((3,3), float) for k in xrange(num_points): x = X[k] y = Y[k] xy2n += numpy.add.reduce(x*x) + numpy.add.reduce(y*y) R[0,0] += x[0]*y[0] R[0,1] += x[0]*y[1] R[0,2] += x[0]*y[2] R[1,0] += x[1]*y[0] R[1,1] += x[1]*y[1] R[1,2] += x[1]*y[2] R[2,0] += x[2]*y[0] R[2,1] += x[2]*y[1] R[2,2] += x[2]*y[2] F = numpy.zeros((4,4), float) F[0,0] = R[0,0] + R[1,1] + R[2,2] F[0,1] = R[1,2] - R[2,1] F[0,2] = R[2,0] - R[0,2] F[0,3] = R[0,1] - R[1,0] F[1,0] = F[0,1] F[1,1] = R[0,0] - R[1,1] - R[2,2] F[1,2] = R[0,1] + R[1,0] F[1,3] = R[0,2] + R[2,0] F[2,0] = F[0,2] F[2,1] = F[1,2] F[2,2] =-R[0,0] + R[1,1] - R[2,2] F[2,3] = R[1,2] + R[2,1] F[3,0] = F[0,3] F[3,1] = F[1,3] F[3,2] = F[2,3] F[3,3] =-R[0,0] - R[1,1] + R[2,2] evals, evecs = linalg.eigenvectors(F) i = numpy.argmax(evals) eval = evals[i] evec = evecs[i] msd = (xy2n - 2.0*eval) / num_points if msd < 0.0: rmsd = 0.0 else: rmsd = math.sqrt(msd) return SuperpositionResults(evec, src_org, dst_org, rmsd, num_points)
def rigidFit(self, mobileCoords): """ the rigidFit method computes the necessary transformation matrices to superimpose the list of mobileCoords onto the list of referenceCoords, and stores the resulting matrices (rot, trans) <- rigidFit(mobileCoords) Rigid body fit. Finds transformation (rot,trans) such that r.m.s dist(x,rot*y+trans) --> min ! mobileCoords: cartesian coordinates of mobile structure (3,n) (input) rot : rotation matrix (3,3) (output) trans : translation vector (3) (output) status: 0 if OK, 1 if singular problem (n<3 ...) Method: W.Kabsch, Acta Cryst. (1976). A32,922-923 W.Kabsch, Acta Cryst. (1978). A34,827-828 """ if self.refCoords is None: raise RuntimeError(" no reference coordinates specified") refCoords = self.refCoords if len(refCoords) != len(mobileCoords): raise RuntimeError("input vector length mismatch") refCoords = Numeric.array(refCoords) mobileCoords = Numeric.array(mobileCoords) # # 1. Compute centroids: refCentroid = Numeric.sum(refCoords)/ len(refCoords) mobileCentroid = Numeric.sum(mobileCoords)/ len(mobileCoords) # # 2. Wolfgang Kabsch's method for rotation matrix rot: rot = Numeric.identity(3).astype('f') # LOOK how to modify that code. for i in xrange(3): for j in xrange(3): rot[j][i] = Numeric.sum((refCoords[:,i]-refCentroid[i])* (mobileCoords[:,j]-mobileCentroid[j])) rotTransposed = Numeric.transpose(rot) e = Numeric.dot(rot, rotTransposed) evals, evecs = LinearAlgebra.eigenvectors(e) ev = Numeric.identity(3).astype('d') # set ev[0] to be the evec or the largest eigenvalue # and ev[1] to be the evec or the second largest eigenvalue eigenValues = list(evals) discard = eigenValues.index(min(eigenValues)) i = j =0 while i<3: if i==discard: i = i + 1 continue ev[j] = evecs[i] j = j + 1 i = i + 1 evecs = ev evecs[2][0] = evecs[0][1]*evecs[1][2] - evecs[0][2]*evecs[1][1] evecs[2][1] = evecs[0][2]*evecs[1][0] - evecs[0][0]*evecs[1][2] evecs[2][2] = evecs[0][0]*evecs[1][1] - evecs[0][1]*evecs[1][0] b = Numeric.dot(evecs, rot) norm = math.sqrt(b[0][0]*b[0][0] + b[0][1]*b[0][1] + b[0][2]*b[0][2]) if math.fabs(norm)<1.0e-20: return -1, -1 b[0] = b[0]/norm norm = math.sqrt(b[1][0]*b[1][0] + b[1][1]*b[1][1] + b[1][2]*b[1][2]) if math.fabs(norm)<1.0e-20: return -1, -1 b[1] = b[1]/norm # vvmult(b[0],b[1],b[2]) b[2][0] = b[0][1]*b[1][2] - b[0][2]*b[1][1] b[2][1] = b[0][2]*b[1][0] - b[0][0]*b[1][2] b[2][2] = b[0][0]*b[1][1] - b[0][1]*b[1][0] # mtrans3(e) e = evecs tempo=e[0][1]; e[0][1]=e[1][0]; e[1][0]=tempo tempo=e[0][2]; e[0][2]=e[2][0]; e[2][0]=tempo tempo=e[1][2]; e[1][2]=e[2][1]; e[2][1]=tempo # mmmult3(b,e,rot) rot[0][0] = b[0][0]*e[0][0] + b[1][0]*e[0][1] + b[2][0]*e[0][2] rot[0][1] = b[0][1]*e[0][0] + b[1][1]*e[0][1] + b[2][1]*e[0][2] rot[0][2] = b[0][2]*e[0][0] + b[1][2]*e[0][1] + b[2][2]*e[0][2] rot[1][0] = b[0][0]*e[1][0] + b[1][0]*e[1][1] + b[2][0]*e[1][2] rot[1][1] = b[0][1]*e[1][0] + b[1][1]*e[1][1] + b[2][1]*e[1][2] rot[1][2] = b[0][2]*e[1][0] + b[1][2]*e[1][1] + b[2][2]*e[1][2] rot[2][0] = b[0][0]*e[2][0] + b[1][0]*e[2][1] + b[2][0]*e[2][2] rot[2][1] = b[0][1]*e[2][0] + b[1][1]*e[2][1] + b[2][1]*e[2][2] rot[2][2] = b[0][2]*e[2][0] + b[1][2]*e[2][1] + b[2][2]*e[2][2] # # Compute translation vector trans: # mvmult3(rot,cy,cy); trans3 = [0, 0, 0] for i in range(3): trans3[i] = mobileCentroid[0]*rot[0][i] + mobileCentroid[1]*rot[1][i] + \ mobileCentroid[2]*rot[2][i] #bcopy(t3,cy,sizeof(t3)); #vvdiff(cx,cy,trans); trans = ( refCentroid[0]-trans3[0], refCentroid[1]-trans3[1], refCentroid[2]-trans3[2] ) # # That's it... self.rotationMatrix = rot self.translationMatrix = trans self.superimposed = 1
def rigidFit(self, mobileCoords): """ the rigidFit method computes the necessary transformation matrices to superimpose the list of mobileCoords onto the list of referenceCoords, and stores the resulting matrices (rot, trans) <- rigidFit(mobileCoords) Rigid body fit. Finds transformation (rot,trans) such that r.m.s dist(x,rot*y+trans) --> min ! mobileCoords: cartesian coordinates of mobile structure (3,n) (input) rot : rotation matrix (3,3) (output) trans : translation vector (3) (output) status: 0 if OK, 1 if singular problem (n<3 ...) Method: W.Kabsch, Acta Cryst. (1976). A32,922-923 W.Kabsch, Acta Cryst. (1978). A34,827-828 """ if self.refCoords is None: raise RuntimeError(" no reference coordinates specified") refCoords = self.refCoords if len(refCoords) != len(mobileCoords): raise RuntimeError("input vector length mismatch") refCoords = Numeric.array(refCoords) mobileCoords = Numeric.array(mobileCoords) # # 1. Compute centroids: refCentroid = Numeric.sum(refCoords) / len(refCoords) mobileCentroid = Numeric.sum(mobileCoords) / len(mobileCoords) # # 2. Wolfgang Kabsch's method for rotation matrix rot: rot = Numeric.identity(3).astype('f') # LOOK how to modify that code. for i in xrange(3): for j in xrange(3): rot[j][i] = Numeric.sum( (refCoords[:, i] - refCentroid[i]) * (mobileCoords[:, j] - mobileCentroid[j])) rotTransposed = Numeric.transpose(rot) e = Numeric.dot(rot, rotTransposed) evals, evecs = LinearAlgebra.eigenvectors(e) ev = Numeric.identity(3).astype('d') # set ev[0] to be the evec or the largest eigenvalue # and ev[1] to be the evec or the second largest eigenvalue eigenValues = list(evals) discard = eigenValues.index(min(eigenValues)) i = j = 0 while i < 3: if i == discard: i = i + 1 continue ev[j] = evecs[i] j = j + 1 i = i + 1 evecs = ev evecs[2][0] = evecs[0][1] * evecs[1][2] - evecs[0][2] * evecs[1][1] evecs[2][1] = evecs[0][2] * evecs[1][0] - evecs[0][0] * evecs[1][2] evecs[2][2] = evecs[0][0] * evecs[1][1] - evecs[0][1] * evecs[1][0] b = Numeric.dot(evecs, rot) norm = math.sqrt(b[0][0] * b[0][0] + b[0][1] * b[0][1] + b[0][2] * b[0][2]) if math.fabs(norm) < 1.0e-20: return -1, -1 b[0] = b[0] / norm norm = math.sqrt(b[1][0] * b[1][0] + b[1][1] * b[1][1] + b[1][2] * b[1][2]) if math.fabs(norm) < 1.0e-20: return -1, -1 b[1] = b[1] / norm # vvmult(b[0],b[1],b[2]) b[2][0] = b[0][1] * b[1][2] - b[0][2] * b[1][1] b[2][1] = b[0][2] * b[1][0] - b[0][0] * b[1][2] b[2][2] = b[0][0] * b[1][1] - b[0][1] * b[1][0] # mtrans3(e) e = evecs tempo = e[0][1] e[0][1] = e[1][0] e[1][0] = tempo tempo = e[0][2] e[0][2] = e[2][0] e[2][0] = tempo tempo = e[1][2] e[1][2] = e[2][1] e[2][1] = tempo # mmmult3(b,e,rot) rot[0][0] = b[0][0] * e[0][0] + b[1][0] * e[0][1] + b[2][0] * e[0][2] rot[0][1] = b[0][1] * e[0][0] + b[1][1] * e[0][1] + b[2][1] * e[0][2] rot[0][2] = b[0][2] * e[0][0] + b[1][2] * e[0][1] + b[2][2] * e[0][2] rot[1][0] = b[0][0] * e[1][0] + b[1][0] * e[1][1] + b[2][0] * e[1][2] rot[1][1] = b[0][1] * e[1][0] + b[1][1] * e[1][1] + b[2][1] * e[1][2] rot[1][2] = b[0][2] * e[1][0] + b[1][2] * e[1][1] + b[2][2] * e[1][2] rot[2][0] = b[0][0] * e[2][0] + b[1][0] * e[2][1] + b[2][0] * e[2][2] rot[2][1] = b[0][1] * e[2][0] + b[1][1] * e[2][1] + b[2][1] * e[2][2] rot[2][2] = b[0][2] * e[2][0] + b[1][2] * e[2][1] + b[2][2] * e[2][2] # # Compute translation vector trans: # mvmult3(rot,cy,cy); trans3 = [0, 0, 0] for i in range(3): trans3[i] = mobileCentroid[0]*rot[0][i] + mobileCentroid[1]*rot[1][i] + \ mobileCentroid[2]*rot[2][i] #bcopy(t3,cy,sizeof(t3)); #vvdiff(cx,cy,trans); trans = (refCentroid[0] - trans3[0], refCentroid[1] - trans3[1], refCentroid[2] - trans3[2]) # # That's it... self.rotationMatrix = rot self.translationMatrix = trans self.superimposed = 1
def SuperimposePoints(src_points, dst_points): """Takes two 1:1 set of points and returns a 3x3 rotation matrix and translation vector. """ num_points = src_points.shape[0] ## shift both sets of coordinates to their centroids src_org = numpy.add.reduce(src_points) / float(src_points.shape[0]) dst_org = numpy.add.reduce(dst_points) / float(dst_points.shape[0]) X = numpy.add(src_points, -src_org) Y = numpy.add(dst_points, -dst_org) xy2n = 0.0 R = numpy.zeros((3, 3), float) for k in xrange(num_points): x = X[k] y = Y[k] xy2n += numpy.add.reduce(x * x) + numpy.add.reduce(y * y) R[0, 0] += x[0] * y[0] R[0, 1] += x[0] * y[1] R[0, 2] += x[0] * y[2] R[1, 0] += x[1] * y[0] R[1, 1] += x[1] * y[1] R[1, 2] += x[1] * y[2] R[2, 0] += x[2] * y[0] R[2, 1] += x[2] * y[1] R[2, 2] += x[2] * y[2] F = numpy.zeros((4, 4), float) F[0, 0] = R[0, 0] + R[1, 1] + R[2, 2] F[0, 1] = R[1, 2] - R[2, 1] F[0, 2] = R[2, 0] - R[0, 2] F[0, 3] = R[0, 1] - R[1, 0] F[1, 0] = F[0, 1] F[1, 1] = R[0, 0] - R[1, 1] - R[2, 2] F[1, 2] = R[0, 1] + R[1, 0] F[1, 3] = R[0, 2] + R[2, 0] F[2, 0] = F[0, 2] F[2, 1] = F[1, 2] F[2, 2] = -R[0, 0] + R[1, 1] - R[2, 2] F[2, 3] = R[1, 2] + R[2, 1] F[3, 0] = F[0, 3] F[3, 1] = F[1, 3] F[3, 2] = F[2, 3] F[3, 3] = -R[0, 0] - R[1, 1] + R[2, 2] evals, evecs = linalg.eigenvectors(F) i = numpy.argmax(evals) eval = evals[i] evec = evecs[i] msd = (xy2n - 2.0 * eval) / num_points if msd < 0.0: rmsd = 0.0 else: rmsd = math.sqrt(msd) return SuperpositionResults(evec, src_org, dst_org, rmsd, num_points)