예제 #1
0
 def calcReferenceRms(self, reference, keepH=False, debug=False):
     ref = getCoords(getLines(reference), include_hydrogens = keepH)
     if not len(ref['coord']) == len(self.results[0]['coord']):
         print "[atoms mismatch] Warning! The reference stricture doesn't match the docked ligand!"
         print "Reference [ %d ] | Docked ligand [ %d ]" % (  len(ref['coord']), len(self.results[0]['coord']) )
         return 
     rmsdcalc = RMSDCalculator(ref['coord'])
     rmsd = [ rmsdcalc.computeRMSD(self.results[0]['coord']) ]
     if len(self.results) > 1:
         rmsd.append(rmsdcalc.computeRMSD(self.results[1]['coord']))
     if debug:
         dist_pool = []
         for px in self.poses:
             p = px['coord']
             d = []
             for i in range(len(p)):
                 x = quickdist(p[i], ref['coord'][i], sq=True)
                 d.append(x)
                 d.sort()
             dist_pool.append(d)
             #print "================="
             #print d
         return rmsd, dist_pool,self.poses
     else:
         return rmsd
예제 #2
0
    def getRMSD_subset(self, refCoords=None):
        """Return RMSD of this conformations subset relative to refCoords.

        If refCoords is not given, the original coordinates for the
        subset will be used as the reference.
        """
        if not refCoords:
            refCoords = self.getCoords_subset()
        rmsd_calc = RMSDCalculator(refCoords)
        return rmsd_calc.computeRMSD(self.getCoords_subset())
    def getRMSD_subset(self, refCoords=None):
        """Return RMSD of this conformations subset relative to refCoords.

        If refCoords is not given, the original coordinates for the
        subset will be used as the reference.
        """
        if not refCoords:
            refCoords = self.getCoords_subset()
        rmsd_calc = RMSDCalculator(refCoords)            
        return rmsd_calc.computeRMSD(self.getCoords_subset())
예제 #4
0
 def __init__(self, refCoords=None):
     """The constructor of the rigidfitBodyAligner takes one required argument:
     refCoords: cartesian coordinates of reference structure (3,n) (input)
     This method creates:
     self.superimposed: flag when set to 1 the transformation matrices to superimpose
                        a mobile set of coordinates onto the reference coords have been
                        computed.
     self.rmsdCalculator: instance of the RMSDCalculator class that computes the rmsd
                          between two lists of coordinates. This object will be used by
                          the rmsdAfterSuperimposition method.
     """
     self.refCoords = refCoords
     self.superimposed = 0
     self.rmsdCalculator = RMSDCalculator()
예제 #5
0
 def __init__(self, mol, seed, coords):
     UserList.UserList.__init__(self)
     self.seed = seed
     self.mol = mol
     self.seed_coords = coords 
     self.ruler = RMSDCalculator(coords)
     self.min_energy = self.max_energy = mol.autodock_states[seed].e_binding ##### get seed energy HERE
     self.append(seed)
예제 #6
0
    def getRMSD(self, refCoords=None, numCoords=None):
        """Return RMSD of this conformations relative to refCoords.

        If refCoords is not given, the original coordinates for the
        molecule will be used as the reference.
        """
        if not refCoords:
            oldCoords = self.mol.allAtoms.coords[:]
            oldConf = self.mol.allAtoms[0].conformation
            self.mol.allAtoms.setConformation(0)
            refCoords = self.mol.allAtoms.coords[:]
            self.mol.allAtoms.updateCoords(oldCoords, oldConf)
        rmsd_calc = RMSDCalculator(refCoords)
        if numCoords:
            rmsd = rmsd_calc.computeRMSD(self.getCoords()[:numCoords])
        else:
            rmsd = rmsd_calc.computeRMSD(self.getCoords())
        return rmsd
    def getRMSD(self, refCoords=None, numCoords=None):
        """Return RMSD of this conformations relative to refCoords.

        If refCoords is not given, the original coordinates for the
        molecule will be used as the reference.
        """
        if not refCoords:
            oldCoords = self.mol.allAtoms.coords[:]
            oldConf = self.mol.allAtoms[0].conformation
            self.mol.allAtoms.setConformation(0)
            refCoords = self.mol.allAtoms.coords[:]
            self.mol.allAtoms.updateCoords(oldCoords, oldConf)
        rmsd_calc = RMSDCalculator(refCoords)            
        if numCoords:
            rmsd = rmsd_calc.computeRMSD(self.getCoords()[:numCoords])
        else:
            rmsd = rmsd_calc.computeRMSD(self.getCoords())
        return rmsd
    def getRMSD_custom(self, refCoords=None):
        """Return the minimum of the regular RMSD and the
        computed RMSD after the coords have been rotated about
        the c2 axis which was aligned with the y-axis.
        """
        normal_RMSD = self.getRMSD(refCoords)

        c2_coords = self.coords[:]
        # I know there's a clever way to use Numeric to do this...
        for c in c2_coords:
            c[0] = -1.0 * c[0]
            c[2] = -1.0 * c[2]

        if not refCoords:
            self.mol.allAtoms.setConformation(0)
            refCoords = self.mol.allAtoms.coords
        rmsd_calc = RMSDCalculator(refCoords)            
        c2_RMSD = rmsd_calc.computeRMSD(self.getCoords())
        return min( normal_RMSD, c2_RMSD)
예제 #9
0
    def getRMSD_custom(self, refCoords=None):
        """Return the minimum of the regular RMSD and the
        computed RMSD after the coords have been rotated about
        the c2 axis which was aligned with the y-axis.
        """
        normal_RMSD = self.getRMSD(refCoords)

        c2_coords = self.coords[:]
        # I know there's a clever way to use Numeric to do this...
        for c in c2_coords:
            c[0] = -1.0 * c[0]
            c[2] = -1.0 * c[2]

        if not refCoords:
            self.mol.allAtoms.setConformation(0)
            refCoords = self.mol.allAtoms.coords
        rmsd_calc = RMSDCalculator(refCoords)
        c2_RMSD = rmsd_calc.computeRMSD(self.getCoords())
        return min(normal_RMSD, c2_RMSD)
예제 #10
0
 def __init__(self, refCoords=None):
     """The constructor of the rigidfitBodyAligner takes one required argument:
     refCoords: cartesian coordinates of reference structure (3,n) (input)
     This method creates:
     self.superimposed: flag when set to 1 the transformation matrices to superimpose
                        a mobile set of coordinates onto the reference coords have been
                        computed.
     self.rmsdCalculator: instance of the RMSDCalculator class that computes the rmsd
                          between two lists of coordinates. This object will be used by
                          the rmsdAfterSuperimposition method.
     """
     self.refCoords = refCoords
     self.superimposed = 0
     self.rmsdCalculator = RMSDCalculator()
            if verbose: print 'set outputfilename to ', a
        if o in ('-t', '--t'):
            rms_tolerance = float(a)
            if verbose: print 'set rms_tolerance to ', a
        if o in ('-v', '--v'):
            verbose = True
            if verbose: print 'set verbose to ', True
        if o in ('-h', '--'):
            usage()
            sys.exit()

    dlg_list = glob.glob('*.dlg')
    d = Docking()
    for dlg in dlg_list:
        d.readDlg(dlg)
    d.clusterer.rmsTool = RMSDCalculator(d.ligMol.allAtoms.coords[:])
    d.clusterer.make_clustering(rms_tolerance)
    clustering = d.clusterer.clustering_dict[rms_tolerance]
    largest = clustering[0]
    for clust in clustering:
        if len(clust)>len(largest):
            largest = clust
    #update the coordinates with those of conf with lowest energy in this largest cluster
    d.ch.set_conformation(largest[0])
    parser = d.ligMol.parser
    lines = []
    #have to add newline character to lines read from dlg
    for l in parser.allLines:
        l+= '\n'
        lines.append(l)
    parser.allLines = lines
예제 #12
0
class RigidfitBodyAligner:
    """
    This class implements a set of method to compute transformation matrices
    to superimpose a set of mobile coordinates onto a set of reference
    coordinates, apply the resulting transformation matrices to a given set of
    coordinates and finally compute the RMSD and the distance vectors between
    the set of reference coordinates and a given set of coordinates transformed by
    the computed transformation matrices.
    """
    def __init__(self, refCoords=None):
        """The constructor of the rigidfitBodyAligner takes one required argument:
        refCoords: cartesian coordinates of reference structure (3,n) (input)
        This method creates:
        self.superimposed: flag when set to 1 the transformation matrices to superimpose
                           a mobile set of coordinates onto the reference coords have been
                           computed.
        self.rmsdCalculator: instance of the RMSDCalculator class that computes the rmsd
                             between two lists of coordinates. This object will be used by
                             the rmsdAfterSuperimposition method.
        """
        self.refCoords = refCoords
        self.superimposed = 0
        self.rmsdCalculator = RMSDCalculator()


    def setRefCoords(self, refCoords):
        """ The setRefCoords method allows you to lists the reference coordinates."""
        self.refCoords = refCoords
        # New set of ref coords so set the flag back to 0:
        self.superimposed = 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
            
    def transformCoords(self, setCoords):
        """ The transformCoords method applies the transformation matrices
        computed by rigidFit method to the given list of coordinates.
        """
        # This can only be done if the transformation matrices have been computed
        # by the rigidFit method.
        if not self.superimposed: return

        # 1- apply the rotation and the translation matrix to the given set of coords.
        transfoMatrix = Numeric.identity(4, 'd')
        transfoMatrix[:3,:3] = self.rotationMatrix
        transfoMatrix[3][0] = self.translationMatrix[0]
        transfoMatrix[3][1] = self.translationMatrix[1]
        transfoMatrix[3][2] = self.translationMatrix[2]
        
        # 2- now apply the transformation to the list of given coordinates list:
        # make homogeneous coords
        homoCoords = Numeric.concatenate((setCoords,
                                          Numeric.ones( (len(setCoords), 1), 'd')), 1)
        # 3- apply the transformation matrix to the homogeneous coords.
        transformedCoords = Numeric.dot(homoCoords, transfoMatrix)

        return transformedCoords
        
    def rmsdAfterSuperimposition(self, setCoords):
        """ The computeRMSD method computes the overall root mean square
        distance (rmsd) and also the distance between each pair of points
        (distVect) between the refCoords and the given list of Coords.
        The transformation matrices will be applied to the given list of coords."""
        if not self.superimposed: return

        transformedCoords = self.transformCoords(setCoords)
        self.rmsdCalculator.setRefCoords(self.refCoords)
        #return self.rmsdCalculator.computeRMSD(setCoords)
        return self.rmsdCalculator.computeRMSD(transformedCoords[:,:3].tolist())
        print 'compute_rms_between_conformations: second filename must be specified.'
        usage()
        sys.exit()

    #process docking in reference directory
    #read the molecules
    first = Read(first)[0]
    second = Read(second)[0]
    assert len(first.allAtoms)==len(second.allAtoms)
    first_ats = first.allAtoms
    second_ats = second.allAtoms
    if omit_hydrogens:
        first_ats = first.allAtoms.get(lambda x: x.element!='H')
        second_ats = second.allAtoms.get(lambda x: x.element!='H')
    #setup rmsd tool
    rmsTool = RMSDCalculator(first_ats.coords)
    need_to_open = not os.path.exists(outputfilename)
    if need_to_open:
        fptr = open(outputfilename, 'w')
        ostr= "reference filename      test filename\t\trms \n"
        fptr.write(ostr)
    else:
        fptr = open(outputfilename, 'a')
   
    ostr = "% 10s,\t% 10s,  % 10.4f\n" %(first.parser.filename, second.parser.filename, rmsTool.computeRMSD(second_ats.coords))
    fptr.write(ostr)
    fptr.close()
    

# To execute this command type:
# compute_rms_between_conformations.py -f filename -s secondfilename 
예제 #14
0
        print 'compute_rms_between_conformations: second filename must be specified.'
        usage()
        sys.exit()

    #process docking in reference directory
    #read the molecules
    first = Read(first)[0]
    second = Read(second)[0]
    assert len(first.allAtoms) == len(second.allAtoms)
    first_ats = first.allAtoms
    second_ats = second.allAtoms
    if omit_hydrogens:
        first_ats = first.allAtoms.get(lambda x: x.element != 'H')
        second_ats = second.allAtoms.get(lambda x: x.element != 'H')
    #setup rmsd tool
    rmsTool = RMSDCalculator(first_ats.coords)
    need_to_open = not os.path.exists(outputfilename)
    if need_to_open:
        fptr = open(outputfilename, 'w')
        ostr = "reference filename      test filename\t\trms \n"
        fptr.write(ostr)
    else:
        fptr = open(outputfilename, 'a')

    ostr = "% 10s,\t% 10s,  % 10.4f\n" % (
        first.parser.filename, second.parser.filename,
        rmsTool.computeRMSD(second_ats.coords))
    fptr.write(ostr)
    fptr.close()

# To execute this command type:
예제 #15
0
        print('compute_rms_between_conformations: second filename must be specified.')
        usage()
        sys.exit()

    #process docking in reference directory
    #read the molecules
    first = Read(first)[0]
    second = Read(second)[0]
    assert len(first.allAtoms)==len(second.allAtoms)
    first_ats = first.allAtoms
    second_ats = second.allAtoms
    if omit_hydrogens:
        first_ats = first.allAtoms.get(lambda x: x.element!='H')
        second_ats = second.allAtoms.get(lambda x: x.element!='H')
    #setup rmsd tool
    rmsTool = RMSDCalculator(first_ats.coords)
    need_to_open = not os.path.exists(outputfilename)
    if need_to_open:
        fptr = open(outputfilename, 'w')
        ostr= "reference filename      test filename\t\trms \n"
        fptr.write(ostr)
    else:
        fptr = open(outputfilename, 'a')
   
    ostr = "% 10s,\t% 10s,  % 10.4f\n" %(first.parser.filename, second.parser.filename, rmsTool.computeRMSD(second_ats.coords))
    fptr.write(ostr)
    fptr.close()
    

# To execute this command type:
# compute_rms_between_conformations.py -f filename -s secondfilename 
예제 #16
0
    for dlg in dlg_list:
        d.readDlg(dlg)

    #setup rmsd tool
    coords = d.ligMol.allAtoms.coords[:]
    refCoords = None
    if rms_reference is not None:
        file = directory + '/' + rms_reference
        ref = Read(file)
        if not len(ref):
            print("unable to read ", rms_reference)
        else:
            ref = ref[0]
            coords = ref.allAtoms.coords
            refCoords = coords[:]
    d.clusterer.rmsTool = RMSDCalculator(coords)

    d.clusterer.make_clustering(rms_tolerance)

    # for building hydrogen bonds or reporting energy breakdown
    # setup receptor:
    if build_hydrogen_bonds or report_energy_breakdown:
        d.ligMol.buildBondsByDistance()
        receptor_filename = directory + '/' + receptor_filename
        receptor = Read(receptor_filename)[0]
        receptor.buildBondsByDistance()
    if build_hydrogen_bonds:
        hbondBuilder = HydrogenBondBuilder()
        #do next two lines for each conf
        #d.ligMol.set_conformation(conf)
        #atDict = hbondBuilder.build(receptor.allAtoms, d.ligMol.allAtoms)
예제 #17
0
class RigidfitBodyAligner:
    """
    This class implements a set of method to compute transformation matrices
    to superimpose a set of mobile coordinates onto a set of reference
    coordinates, apply the resulting transformation matrices to a given set of
    coordinates and finally compute the RMSD and the distance vectors between
    the set of reference coordinates and a given set of coordinates transformed by
    the computed transformation matrices.
    """
    def __init__(self, refCoords=None):
        """The constructor of the rigidfitBodyAligner takes one required argument:
        refCoords: cartesian coordinates of reference structure (3,n) (input)
        This method creates:
        self.superimposed: flag when set to 1 the transformation matrices to superimpose
                           a mobile set of coordinates onto the reference coords have been
                           computed.
        self.rmsdCalculator: instance of the RMSDCalculator class that computes the rmsd
                             between two lists of coordinates. This object will be used by
                             the rmsdAfterSuperimposition method.
        """
        self.refCoords = refCoords
        self.superimposed = 0
        self.rmsdCalculator = RMSDCalculator()

    def setRefCoords(self, refCoords):
        """ The setRefCoords method allows you to lists the reference coordinates."""
        self.refCoords = refCoords
        # New set of ref coords so set the flag back to 0:
        self.superimposed = 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 = numpy.linalg.eig(e)
        evecs = evecs.T

        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 transformCoords(self, setCoords):
        """ The transformCoords method applies the transformation matrices
        computed by rigidFit method to the given list of coordinates.
        """
        # This can only be done if the transformation matrices have been computed
        # by the rigidFit method.
        if not self.superimposed: return

        # 1- apply the rotation and the translation matrix to the given set of coords.
        transfoMatrix = Numeric.identity(4, 'd')
        transfoMatrix[:3, :3] = self.rotationMatrix
        transfoMatrix[3][0] = self.translationMatrix[0]
        transfoMatrix[3][1] = self.translationMatrix[1]
        transfoMatrix[3][2] = self.translationMatrix[2]

        # 2- now apply the transformation to the list of given coordinates list:
        # make homogeneous coords
        homoCoords = Numeric.concatenate(
            (setCoords, Numeric.ones((len(setCoords), 1), 'd')), 1)
        # 3- apply the transformation matrix to the homogeneous coords.
        transformedCoords = Numeric.dot(homoCoords, transfoMatrix)

        return transformedCoords

    def rmsdAfterSuperimposition(self, setCoords):
        """ The computeRMSD method computes the overall root mean square
        distance (rmsd) and also the distance between each pair of points
        (distVect) between the refCoords and the given list of Coords.
        The transformation matrices will be applied to the given list of coords."""
        if not self.superimposed: return

        transformedCoords = self.transformCoords(setCoords)
        self.rmsdCalculator.setRefCoords(self.refCoords)
        #return self.rmsdCalculator.computeRMSD(setCoords)
        return self.rmsdCalculator.computeRMSD(
            transformedCoords[:, :3].tolist())