def test_superimpose():
    from mglutil.math.rigidFit import RigidfitBodyAligner
    rigidfitAligner = RigidfitBodyAligner()
    refCoords=[[0,0,0] , [1,0,0], [0,1,0], [0,0,1]]
    mobCoords=[[10,0,0] , [11,0,0], [10,1,0], [10,0,1]]
    rigidfitAligner.setRefCoords(refCoords)                
    rigidfitAligner.rigidFit(mobCoords)
    rmsd=rigidfitAligner.rmsdAfterSuperimposition(mobCoords)
    assert diff(rmsd, 0.0 )
Beispiel #2
0
def test_superimpose():
    from mglutil.math.rigidFit import RigidfitBodyAligner
    rigidfitAligner = RigidfitBodyAligner()
    refCoords = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]]
    mobCoords = [[10, 0, 0], [11, 0, 0], [10, 1, 0], [10, 0, 1]]
    rigidfitAligner.setRefCoords(refCoords)
    rigidfitAligner.rigidFit(mobCoords)
    rmsd = rigidfitAligner.rmsdAfterSuperimposition(mobCoords)
    assert diff(rmsd, 0.0)
class SuperImposeAtomsCommand(MVCommand):

    def onAddCmdToViewer(self):
        self.rigidfitAligner = RigidfitBodyAligner()
        
    def doit(self, refAtoms, mobAtoms):
        """
        The SuperImposeAtomsCommand takes two set of Atoms of the same length
        compute the rotation and translation matrices to superimpose the
        mobAtoms onto the refAtoms using rigidFit module and then transform the
        corresponding geometry.
        """
        refCoords = refAtoms.coords
        mobCoords = mobAtoms.coords
        
        self.rigidfitAligner.setRefCoords(refCoords)

        # Nothing can be done if the two sets of coords are not of the same
        # size
        if not len(refCoords) == len(mobCoords):
            print " ERROR: Cannot perform the superimposition because the 2 \
            mv.lsets of Atoms are not of the same length"
            return

        # Get the rotation and the translation ysing mglutil.math.rigidFit
        self.rigidfitAligner.rigidFit(mobCoords)
        #rotation, translation= rigidFit.rigid_fit( refCoords, inCoords)
        rotMat =  Numeric.identity(4).astype('f')
        rotMat[:3,:3] = self.rigidfitAligner.rotationMatrix
        rotMat = Numeric.reshape(rotMat, (16,))
        transMat = Numeric.array(self.rigidfitAligner.translationMatrix)
        
        # transform the geometry representing the atoms only if a gui has been
        # created:
        if not self.vf.hasGui:
            return

        # Transform the mob geometry
        mobMol = mobAtoms.top.uniq()[0]
        mob = mobMol.geomContainer.masterGeom
        self.vf.transformObject('rotation', mob.fullName, matrix=tuple(rotMat))
        self.vf.transformObject('translation', mob.fullName, matrix=tuple(transMat))
        

    def __call__(self, refAtoms, mobAtoms, **kw):
        """
        None <- superimposeAtoms(refAtoms, mobAtoms, **kw)
        """
        if not kw.has_key('redraw'): kw['redraw'] = 1
        apply(self.doitWrapper, (refAtoms, mobAtoms), kw)
Beispiel #4
0
class SuperImposeAtomsCommand(MVCommand):

    def onAddCmdToViewer(self):
        self.rigidfitAligner = RigidfitBodyAligner()
        
    def doit(self, refAtoms, mobAtoms):
        """
        The SuperImposeAtomsCommand takes two set of Atoms of the same length
        compute the rotation and translation matrices to superimpose the
        mobAtoms onto the refAtoms using rigidFit module and then transform the
        corresponding geometry.
        """
        refCoords = refAtoms.coords
        mobCoords = mobAtoms.coords
        
        self.rigidfitAligner.setRefCoords(refCoords)

        # Nothing can be done if the two sets of coords are not of the same
        # size
        if not len(refCoords) == len(mobCoords):
            print " ERROR: Cannot perform the superimposition because the 2 \
            mv.lsets of Atoms are not of the same length"
            return

        # Get the rotation and the translation ysing mglutil.math.rigidFit
        self.rigidfitAligner.rigidFit(mobCoords)
        #rotation, translation= rigidFit.rigid_fit( refCoords, inCoords)
        rotMat =  Numeric.identity(4).astype('f')
        rotMat[:3,:3] = self.rigidfitAligner.rotationMatrix
        rotMat = Numeric.reshape(rotMat, (16,))
        transMat = Numeric.array(self.rigidfitAligner.translationMatrix)
        
        # transform the geometry representing the atoms only if a gui has been
        # created:
        #if not self.vf.hasGui:
        #    return

        # Transform the mob geometry
        mobMol = mobAtoms.top.uniq()[0]
        mob = mobMol.geomContainer.masterGeom
        self.vf.transformObject('rotation', mob.fullName, matrix=tuple(rotMat))
        self.vf.transformObject('translation', mob.fullName, matrix=tuple(transMat))
        

    def __call__(self, refAtoms, mobAtoms, **kw):
        """
        None <- superimposeAtoms(refAtoms, mobAtoms, **kw)
        """
        if not kw.has_key('redraw'): kw['redraw'] = 1
        apply(self.doitWrapper, (refAtoms, mobAtoms), kw)
    def doit(self, refAtoms, mobAtoms, updateGeom=True, showRMSD=True):
        """
        The SuperImposeAtomsCommand takes two set of Atoms of the same length
        compute the rotation and translation matrices to superimpose the
        mobAtoms onto the refAtoms using rigidFit module and then transform the
        corresponding geometry.

        updateGeom = True : transform the masterGeom of mobAtoms.
        showRMSD   = True : print and return RMSD 
        """

        if refAtoms is None or mobAtoms is None: return
        assert isinstance(refAtoms, TreeNodeSet)
        assert isinstance(mobAtoms, TreeNodeSet)

        refAtoms = refAtoms.findType(Atom)
        mobAtoms = mobAtoms.findType(Atom)
        # validate the inputs
        if len(refAtoms) !=len(mobAtoms):
            print "The two atomSet are not of equal length"
            return
        if len(refAtoms) < 3 :
            print "At least three atoms are needed for superimposition"
            return
        
        refCoords = refAtoms.coords
        mobCoords = mobAtoms.coords
        
        rigidfitAligner = RigidfitBodyAligner()
        rigidfitAligner.setRefCoords(refCoords)                
        rigidfitAligner.rigidFit(mobCoords)

        if updateGeom:
            rotMat =  Numeric.identity(4).astype('d')
            rotMat[:3,:3] = rigidfitAligner.rotationMatrix               
            transMat = Numeric.array(rigidfitAligner.translationMatrix)
            rotMat[3,:3] = transMat
            #print rotMat  # the matrix
            mGeom = mobAtoms[0].top.geomContainer.masterGeom        
            mGeom.SetRotation(Numeric.reshape(rotMat, (16,)).astype('f'))
            mGeom.viewer.Redraw()

        if showRMSD:
            rmsd=rigidfitAligner.rmsdAfterSuperimposition(mobCoords)
            print "RMSD = ", rmsd
            return rmsd
        else:
            return
    def doit(self, refAtoms, mobAtoms, updateGeom=True, showRMSD=True):
        """
        The SuperImposeAtomsCommand takes two set of Atoms of the same length
        compute the rotation and translation matrices to superimpose the
        mobAtoms onto the refAtoms using rigidFit module and then transform the
        corresponding geometry.

        updateGeom = True : transform the masterGeom of mobAtoms.
        showRMSD   = True : print and return RMSD 
        """

        if refAtoms is None or mobAtoms is None: return
        assert isinstance(refAtoms, TreeNodeSet)
        assert isinstance(mobAtoms, TreeNodeSet)

        refAtoms = refAtoms.findType(Atom)
        mobAtoms = mobAtoms.findType(Atom)
        # validate the inputs
        if len(refAtoms) != len(mobAtoms):
            print "The two atomSet are not of equal length"
            return
        if len(refAtoms) < 3:
            print "At least three atoms are needed for superimposition"
            return

        refCoords = refAtoms.coords
        mobCoords = mobAtoms.coords

        rigidfitAligner = RigidfitBodyAligner()
        rigidfitAligner.setRefCoords(refCoords)
        rigidfitAligner.rigidFit(mobCoords)

        if updateGeom:
            rotMat = Numeric.identity(4).astype('d')
            rotMat[:3, :3] = rigidfitAligner.rotationMatrix
            transMat = Numeric.array(rigidfitAligner.translationMatrix)
            rotMat[3, :3] = transMat
            #print rotMat  # the matrix
            mGeom = mobAtoms[0].top.geomContainer.masterGeom
            mGeom.SetRotation(Numeric.reshape(rotMat, (16, )).astype('f'))
            mGeom.viewer.Redraw()

        if showRMSD:
            rmsd = rigidfitAligner.rmsdAfterSuperimposition(mobCoords)
            print "RMSD = ", rmsd
            return rmsd
        else:
            return
class SuperimposeAtomsCommand(MVCommand):

    def onAddCmdToViewer(self):
        self.rigidfitAligner = RigidfitBodyAligner()
        
    def doit(self, refAtoms, mobAtoms):
        """
        The SuperImposeAtomsCommand takes two set of Atoms of the same length
        compute the rotation and translation matrices to superimpose the
        mobAtoms onto the refAtoms using rigidFit module and then transform the
        corresponding geometry.
        """

        refCoords = refAtoms.coords
        mobCoords = mobAtoms.coords
        
        self.rigidfitAligner.setRefCoords(refCoords)

        # Nothing can be done if the two sets of coords are not of the same
        # size
        if not len(refCoords) == len(mobCoords):
            print " ERROR: Cannot perform the superimposition because the 2 \
            mv.lsets of Atoms are not of the same length"
            return

        # Get the rotation and the translation ysing mglutil.math.rigidFit
        self.rigidfitAligner.rigidFit(mobCoords)
        #rotation, translation= rigidFit.rigid_fit( refCoords, inCoords)
        rotMat =  Numeric.identity(4).astype('d')
        rotMat[:3,:3] = self.rigidfitAligner.rotationMatrix
               
        transMat = Numeric.array(self.rigidfitAligner.translationMatrix)
        
        # transform the geometry representing the atoms only if a gui has been
        # created:
        if not self.vf.hasGui:
            return

        # build the geometry name:
        mobMol = mobAtoms.top.uniq()[0]
        mob = mobMol.geomContainer.masterGeom
        #gName = 'root|'+ mobMol[0].name
        vi = self.vf.GUI.VIEWER
        
        oldCurrent = vi.currentObject
        vi.SetCurrentObject(mob)
        
        # transform only the given geometry.
        if vi.redirectTransformToRoot == 1:
            old = vi.redirectTransformToRoot
            vi.TransformRootOnly(0)
        else:
            old = 0

        
        # apply the rotation to the masterGeom of the inMol
        mob.SetRotation(Numeric.reshape(rotMat, (16,)))
        # apply the translation to the masterGeom of the inMol
        mob.SetTranslation(transMat)


##         refMol = refAtoms.top.uniq()[0]
##         refmg = refMol.geomContainer.masterGeom
        
##         refmg = refAtoms.top.uniq()[0].geomContainer.masterGeom
##         mat = refmg.GetMatrix(refmg)
##         tmat = Numeric.transpose(mat)
        
##         rot, trans, scale = refmg.Decompose4x4(Numeric.reshape(tmat, (16,)))
##         rot_1 = refmg.rotation
##         trans_1 = refmg.translation
##         print 'rot',rot
##         print 'trans',trans
##         print 'rot_1',rot_1
##         print 'trans_1',trans_1
        
##         mobPivot = list(mob.pivot)
##         mobPivot.append(1.)
##         transfo = Numeric.identity(4).astype('d')
##         transfo[:3,:3] = rotMat[:3,:3]
##         transfo[3, :3] = transMat
##         hc = Numeric.array(mobPivot)
##         tPivot = Numeric.dot(hc, transfo)
##         print tPivot[:3]
##         mob.SetPivot(tPivot[:3])
        
        #self.vf.centerOnNodes(refMol)
        #mob.ConcatRotationRelative(Numeric.reshape(rot, (16,)))
        #mob.ConcatTranslation(trans_1)
        
        if old == 1:
            vi.TransformRootOnly(1)
        vi.SetCurrentObject(oldCurrent)

        # Not sure to put that here ?
        # Need to concatenate with the transformation of the reference molecule
        # to have the two molecule aligned:
        # - Get the transformatiom matrix of the ref molecule and decompose it
        
##         refmg = refAtoms.top.uniq()[0].geomContainer.masterGeom
##         mat = refmg.GetMatrix(refmg)
##         tmat = Numeric.transpose(mat)
        
##         rot, trans, scale = refmg.Decompose4x4(Numeric.reshape(tmat, (16,)))
        
##         self.vf.transformObject('rot', gName, rot)
##         self.vf.transformObject('tra', gName, trans)
##         #self.vf.transformObject('sca', gName, scale)
        

    def __call__(self, refAtoms, mobAtoms, **kw):
        """
        None <- superimposeAtoms(refAtoms, mobAtoms, **kw)
        """
        if not kw.has_key('redraw'): kw['redraw'] = 1
        apply(self.doitWrapper, (refAtoms, mobAtoms), kw)
        name, ll = l.split()
        ll.strip()
        moving_mol = Read(name)[0]
        indices = list(map(int, ll.split(',')))
        moving_ats = AtomSet()
        for i in indices:
            new_atoms = moving_mol.allAtoms.get(lambda x: x.number == i)
            if not len(new_atoms):
                print("There is no atom in %s with number %d" % (name, i))
                break
            else:
                moving_ats.append(new_atoms[0])
            #moving_ats.append(moving_mol.allAtoms.get(lambda x: x.number==i)[0])
        num_moving_ats = len(moving_ats)
        if num_moving_ats != num_ref_ats:
            print(
                "Number of moving_ats (%d) does not match number of reference atoms (%d). Skipping %s"
                % (num_moving_ats, num_ref_ats, name))
            continue
        #for i in indices: moving_ats.append(moving_mol.allAtoms[i-1])
        RFA.rigidFit(moving_ats.coords)
        newCoords = RFA.transformCoords(moving_mol.allAtoms.coords)
        if not newCoords is None and newCoords.shape[1] != 3:
            newCoords = newCoords[:, :3]
        outputfilename = prefix + name
        moving_mol.parser.write_with_new_coords(newCoords, outputfilename)
        if verbose: print('wrote %s' % outputfilename)

# To execute this command type:
# superpose_molecules.py  -d data_filename [-p prefix] -v
        print("NO REF COORDS!!!")
        raise Exception(
            'Unable to superimpose because no reference coordinates were specified!!!'
        )
    mobAtoms = get_atoms(mobMol, moblist, names_to_use, verbose)
    mobCoords = mobAtoms.coords
    if len(mobCoords) == 0:
        print("NO MOB COORDS!!!")
        raise Exception(
            'Unable to superimpose because no mobile coordinates were specified!!!'
        )
    #check that moblist and reflist are of the same length
    assert len(refCoords) == len(mobCoords)

    rigidfitAligner.setRefCoords(refCoords)
    rigidfitAligner.rigidFit(mobCoords)
    #now rigidfitAligner has attributes 'rotationMatrix' and 'translationMatrix'

    newCoords = rigidfitAligner.transformCoords(mobMol.allAtoms.coords)
    #make sure the coordinates have the correct shape, ie (num_atoms, 3)
    if not newCoords is None and newCoords.shape[1] != 3:
        newCoords = newCoords[:, :3]
    #newCoords is 2D Numeric array with dimensions  num_atoms, and length of each coordinate
    #if verbose: print "newCoords[0]=", newCoords[0]
    # end by writing a file with the transformed coordinates:
    #the parser of the moving molecule knows about all the input lines
    # so use it to write a file with the new coords:
    if outputfilename is None:
        EXT = os.path.splitext(refMol.parser.filename)[1]
        outputfilename = refMol.name + "_superimposed" + EXT
    mobMol.parser.write_with_new_coords(newCoords, outputfilename)
            # break the bond
            if verbose: print "receptor atom for ligand attachment in residue %s is %s" %(resP.full_name(),otherAt.full_name())
            otherAt.bonds.remove(b)
            rat3.bonds.remove(b)
            if verbose: print "removed %s-%s bond from %s and from %s"%(b.atom1.name, b.atom2.name, otherAt.full_name(), rat3.full_name())
    if bond_to_break is None:
        print "unable to locate the bond to break in receptor residue %s: expected a bond from %s to an atom other than %s"%(resP.full_name(), rat3.name, rat2.name)
        raise 'invalid input'

    #setup for the superposition
    ref_coords = ref_atoms.coords 
    lig_coords = lig_atoms.coords
    #(1) create the tool
    rigidfitAligner = RigidfitBodyAligner()
    rigidfitAligner.setRefCoords(ref_coords)
    rigidfitAligner.rigidFit(lig_coords)
    #(2) get new coordinates for the moving atoms
    #    here all the ligand atoms move
    new_coords = rigidfitAligner.transformCoords(lM.allAtoms.coords)
    # get the correct shape for the coords (natoms,3)
    #new_coords.shape
    #(25, 4)
    new_coords=new_coords[:,:3] 
    #(3) add the new to ligand
    lM.allAtoms.addConformation(new_coords)
    confNum = len(lM.allAtoms[0]._coords)-1
    #(4) set the coordinates to use to the new ones 
    lM.allAtoms.setConformation(confNum)
    if verbose: print "new coordinates added to ligand"

    #add the ligand atoms other than at1 + at2 to the residue
        indices = map(int, ll.split(','))
        moving_ats = AtomSet()
        for i in indices: 
            new_atoms = moving_mol.allAtoms.get(lambda x: x.number==i)
            if not len(new_atoms):
                print "There is no atom in %s with number %d" %(name, i)
                break
            else:
                moving_ats.append(new_atoms[0])
            #moving_ats.append(moving_mol.allAtoms.get(lambda x: x.number==i)[0])
        num_moving_ats = len(moving_ats)
        if num_moving_ats!=num_ref_ats:
            print "Number of moving_ats (%d) does not match number of reference atoms (%d). Skipping %s" %(num_moving_ats,num_ref_ats,name)
            continue
        #for i in indices: moving_ats.append(moving_mol.allAtoms[i-1])
        RFA.rigidFit(moving_ats.coords)
        newCoords = RFA.transformCoords(moving_mol.allAtoms.coords)
        if not newCoords is None and newCoords.shape[1]!=3:
            newCoords=newCoords[:,:3]
        outputfilename = prefix + name
        moving_mol.parser.write_with_new_coords(newCoords,outputfilename) 
        if verbose: print 'wrote %s' %outputfilename


# To execute this command type:
# superpose_molecules.py  -d data_filename [-p prefix] -v




class SuperimposeAtomsCommand(MVCommand):
    def onAddCmdToViewer(self):
        self.rigidfitAligner = RigidfitBodyAligner()

    def doit(self, refAtoms, mobAtoms):
        """
        The SuperImposeAtomsCommand takes two set of Atoms of the same length
        compute the rotation and translation matrices to superimpose the
        mobAtoms onto the refAtoms using rigidFit module and then transform the
        corresponding geometry.
        """

        refCoords = refAtoms.coords
        mobCoords = mobAtoms.coords

        self.rigidfitAligner.setRefCoords(refCoords)

        # Nothing can be done if the two sets of coords are not of the same
        # size
        if not len(refCoords) == len(mobCoords):
            print " ERROR: Cannot perform the superimposition because the 2 \
            mv.lsets of Atoms are not of the same length"

            return

        # Get the rotation and the translation ysing mglutil.math.rigidFit
        self.rigidfitAligner.rigidFit(mobCoords)
        #rotation, translation= rigidFit.rigid_fit( refCoords, inCoords)
        rotMat = Numeric.identity(4).astype('d')
        rotMat[:3, :3] = self.rigidfitAligner.rotationMatrix

        transMat = Numeric.array(self.rigidfitAligner.translationMatrix)

        # transform the geometry representing the atoms only if a gui has been
        # created:
        #if not self.vf.hasGui:
        #    return

        # build the geometry name:
        mobMol = mobAtoms.top.uniq()[0]
        mob = mobMol.geomContainer.masterGeom
        #gName = 'root|'+ mobMol[0].name
        if not self.vf.hasGui:
            vi = self.vf.GUI.VIEWER
            oldCurrent = vi.currentObject
            vi.SetCurrentObject(mob)

            # transform only the given geometry.
            if vi.redirectTransformToRoot == 1:
                old = vi.redirectTransformToRoot
                vi.TransformRootOnly(0)
            else:
                old = 0

        # apply the rotation to the masterGeom of the inMol
        mob.SetRotation(Numeric.reshape(rotMat, (16, )))
        # apply the translation to the masterGeom of the inMol
        mob.SetTranslation(transMat)

        ##         refMol = refAtoms.top.uniq()[0]
        ##         refmg = refMol.geomContainer.masterGeom

        ##         refmg = refAtoms.top.uniq()[0].geomContainer.masterGeom
        ##         mat = refmg.GetMatrix(refmg)
        ##         tmat = Numeric.transpose(mat)

        ##         rot, trans, scale = refmg.Decompose4x4(Numeric.reshape(tmat, (16,)))
        ##         rot_1 = refmg.rotation
        ##         trans_1 = refmg.translation
        ##         print 'rot',rot
        ##         print 'trans',trans
        ##         print 'rot_1',rot_1
        ##         print 'trans_1',trans_1

        ##         mobPivot = list(mob.pivot)
        ##         mobPivot.append(1.)
        ##         transfo = Numeric.identity(4).astype('d')
        ##         transfo[:3,:3] = rotMat[:3,:3]
        ##         transfo[3, :3] = transMat
        ##         hc = Numeric.array(mobPivot)
        ##         tPivot = Numeric.dot(hc, transfo)
        ##         print tPivot[:3]
        ##         mob.SetPivot(tPivot[:3])

        #self.vf.centerOnNodes(refMol)
        #mob.ConcatRotationRelative(Numeric.reshape(rot, (16,)))
        #mob.ConcatTranslation(trans_1)

        if not self.vf.hasGui:
            if old == 1:
                vi.TransformRootOnly(1)
            vi.SetCurrentObject(oldCurrent)

        # Not sure to put that here ?
        # Need to concatenate with the transformation of the reference molecule
        # to have the two molecule aligned:
        # - Get the transformatiom matrix of the ref molecule and decompose it

##         refmg = refAtoms.top.uniq()[0].geomContainer.masterGeom
##         mat = refmg.GetMatrix(refmg)
##         tmat = Numeric.transpose(mat)

##         rot, trans, scale = refmg.Decompose4x4(Numeric.reshape(tmat, (16,)))

##         self.vf.transformObject('rot', gName, rot)
##         self.vf.transformObject('tra', gName, trans)
##         #self.vf.transformObject('sca', gName, scale)

    def __call__(self, refAtoms, mobAtoms, **kw):
        """
        None <- superimposeAtoms(refAtoms, mobAtoms, **kw)
        """
        if not kw.has_key('redraw'): kw['redraw'] = 1
        apply(self.doitWrapper, (refAtoms, mobAtoms), kw)
    refAtoms = get_atoms(refMol, reflist, names_to_use, verbose)
    refCoords = refAtoms.coords #or refMol.chains.residues.atoms.get('backbone').coords
    #check that there are some
    if len(refCoords)==0:
        print "NO REF COORDS!!!"
        raise 'Unable to superimpose because no reference coordinates were specified!!!' 
    mobAtoms = get_atoms(mobMol, moblist, names_to_use, verbose)
    mobCoords = mobAtoms.coords
    if len(mobCoords)==0:
        print "NO MOB COORDS!!!"
        raise 'Unable to superimpose because no mobile coordinates were specified!!!' 
    #check that moblist and reflist are of the same length    
    assert len(refCoords)==len(mobCoords)

    rigidfitAligner.setRefCoords(refCoords)  
    rigidfitAligner.rigidFit(mobCoords)
    #now rigidfitAligner has attributes 'rotationMatrix' and 'translationMatrix'

    newCoords = rigidfitAligner.transformCoords(mobMol.allAtoms.coords)
    #make sure the coordinates have the correct shape, ie (num_atoms, 3)
    if not newCoords is None and newCoords.shape[1]!=3:
        newCoords=newCoords[:,:3]   
    #newCoords is 2D Numeric array with dimensions  num_atoms, and length of each coordinate
    #if verbose: print "newCoords[0]=", newCoords[0]
    # end by writing a file with the transformed coordinates:
    #the parser of the moving molecule knows about all the input lines
    # so use it to write a file with the new coords:
    if outputfilename is None:
        EXT = os.path.splitext(refMol.parser.filename)[1]
        outputfilename = refMol.name + "_superimposed"+ EXT
    mobMol.parser.write_with_new_coords(newCoords, outputfilename)
            if verbose:
                print "removed %s-%s bond from %s and from %s" % (
                    b.atom1.name, b.atom2.name, otherAt.full_name(),
                    rat3.full_name())
    if bond_to_break is None:
        print "unable to locate the bond to break in receptor residue %s: expected a bond from %s to an atom other than %s" % (
            resP.full_name(), rat3.name, rat2.name)
        raise 'invalid input'

    #setup for the superposition
    ref_coords = ref_atoms.coords
    lig_coords = lig_atoms.coords
    #(1) create the tool
    rigidfitAligner = RigidfitBodyAligner()
    rigidfitAligner.setRefCoords(ref_coords)
    rigidfitAligner.rigidFit(lig_coords)
    #(2) get new coordinates for the moving atoms
    #    here all the ligand atoms move
    new_coords = rigidfitAligner.transformCoords(lM.allAtoms.coords)
    # get the correct shape for the coords (natoms,3)
    #new_coords.shape
    #(25, 4)
    new_coords = new_coords[:, :3]
    #(3) add the new to ligand
    lM.allAtoms.addConformation(new_coords)
    confNum = len(lM.allAtoms[0]._coords) - 1
    #(4) set the coordinates to use to the new ones
    lM.allAtoms.setConformation(confNum)
    if verbose: print "new coordinates added to ligand"

    #add the ligand atoms other than at1 + at2 to the residue