Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
    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'
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
    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
Ejemplo n.º 12
0
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)