def removeNeighbors(self, atDict):
     #filter out at-itself and at-bondedat up to 1:4
     #NB keys could be hydrogens OR donors
     for at in atDict.keys():
         closeAts = atDict[at]
         bondedAts = AtomSet([])
         for b in at.bonds:
             ###at2 = b.neighborAtom(at)
             at2 = b.atom1
             if id(at2)==id(at): at2 = b.atom2
             bondedAts.append(at2)
             #9/13 remove this:
             ##also remove 1-3
             for b2 in at2.bonds:
                 at3 = b2.atom1
                 if id(at3)==id(at2): at3 = b.atom2
                 #at3 = b2.neighborAtom(at2)
                 if id(at3)!=id(at):
                     bondedAts.append(at3)
                 #for b3 in at3.bonds:
                     #at4 = b2.neighborAtom(at3)
                     #if at4!=at and at4!=at2:
                         #bondedAts.append(at4)
         bondedAts = bondedAts.uniq()
         goodAts = []
         for i in range(len(closeAts)):
             cAt = closeAts[i]
             if cAt not in bondedAts:
                 goodAts.append(cAt)
         if len(goodAts):
             atDict[at] = goodAts
         else:
             del atDict[at]
     return atDict
 def filterAcceptors(self, accAts):
     ntypes = ['Npl', 'Nam']
     npls = accAts.get(lambda x, ntypes=ntypes: x.babel_type=='Npl')
     nams = accAts.get(lambda x, ntypes=ntypes: x.babel_type=='Nam')
     #nAts = accAts.get(lambda x, ntypes=ntypes: x.babel_type in ntypes)
     restAts = accAts.get(lambda x, ntypes=ntypes: x.babel_type not in ntypes)
     if not restAts: restAts = AtomSet([])
     #if nAts:
     if npls:
         #for at in nAts:
         for at in npls:
             s = 0
             for b in at.bonds:
                 if b.bondOrder=='aromatic':
                     s = s + 2
                 else: s = s + b.bondOrder
             #if s<3:
             #apparently this is wrong
             if s<4:
                 restAts.append(at)
     if nams:
         #for at in nAts:
         for at in nams:
             s = 0
             for b in at.bonds:
                 if b.bondOrder=='aromatic':
                     s = s + 2
                 else: s = s + b.bondOrder
                 #s = s + b.bondOrder
             if s<3:
                 restAts.append(at)
     return restAts
Пример #3
0
 def filterAcceptors(self, accAts):
     ntypes = ['Npl', 'Nam']
     npls = accAts.get(lambda x, ntypes=ntypes: x.babel_type == 'Npl')
     nams = accAts.get(lambda x, ntypes=ntypes: x.babel_type == 'Nam')
     #nAts = accAts.get(lambda x, ntypes=ntypes: x.babel_type in ntypes)
     restAts = accAts.get(
         lambda x, ntypes=ntypes: x.babel_type not in ntypes)
     if not restAts: restAts = AtomSet([])
     #if nAts:
     if npls:
         #for at in nAts:
         for at in npls:
             s = 0
             for b in at.bonds:
                 if b.bondOrder == 'aromatic':
                     s = s + 2
                 else:
                     s = s + b.bondOrder
             #if s<3:
             #apparently this is wrong
             if s < 4:
                 restAts.append(at)
     if nams:
         #for at in nAts:
         for at in nams:
             s = 0
             for b in at.bonds:
                 if b.bondOrder == 'aromatic':
                     s = s + 2
                 else:
                     s = s + b.bondOrder
                 #s = s + b.bondOrder
             if s < 3:
                 restAts.append(at)
     return restAts
def get_atoms(mol, list_of_indicies, names_to_use=['N','CA','C'], verbose=False):
    if verbose: 
        print "in get_atoms with list of indicies:" 
        print list_of_indicies
    if not len(list_of_indicies):
        raise 'invalid input: list of indicies is empty!'
    atoms = AtomSet()
    num_res = 0
    for item in list_of_indicies:
        first, second = item
        #check for valid index and for end of chain
        max_index = len(mol.chains.residues)-1
        assert first<=max_index, 'invalid start of residue range'
        assert second<=max_index, 'invalid end of residue range'
        assert second>=first, 'second index cannot be smaller than first'
        if second==max_index:
            #ie mol.chains.residues[second]==mol.chains.residues[-1]:
            these_res = mol.chains.residues[first:]
        else:
            these_res = mol.chains.residues[first:second+1]
        if verbose: print "Adding  %3d residues " %(len(these_res)),
        num_res+=len(these_res)
        if verbose: print "Now there are %d residues total" %(num_res)
        for r in these_res:
            for n in names_to_use:
                atoms.append( r.atoms.get(n)[0])
    assert len(atoms), 'invalid input: lists of indicies did not correspond to any residues!'
    if verbose: print 'returning %d atoms' %(len(atoms))
    return atoms
Пример #5
0
 def removeNeighbors(self, atDict):
     #filter out at-itself and at-bondedat up to 1:4
     #NB keys could be hydrogens OR donors
     for at in atDict.keys():
         closeAts = atDict[at]
         bondedAts = AtomSet([])
         for b in at.bonds:
             ###at2 = b.neighborAtom(at)
             at2 = b.atom1
             if id(at2) == id(at): at2 = b.atom2
             bondedAts.append(at2)
             #9/13 remove this:
             ##also remove 1-3
             for b2 in at2.bonds:
                 at3 = b2.atom1
                 if id(at3) == id(at2): at3 = b.atom2
                 #at3 = b2.neighborAtom(at2)
                 if id(at3) != id(at):
                     bondedAts.append(at3)
                 #for b3 in at3.bonds:
                 #at4 = b2.neighborAtom(at3)
                 #if at4!=at and at4!=at2:
                 #bondedAts.append(at4)
         bondedAts = bondedAts.uniq()
         goodAts = []
         for i in range(len(closeAts)):
             cAt = closeAts[i]
             if cAt not in bondedAts:
                 goodAts.append(cAt)
         if len(goodAts):
             atDict[at] = goodAts
         else:
             del atDict[at]
     return atDict
def get_atoms(mol,
              list_of_indicies,
              names_to_use=['N', 'CA', 'C'],
              verbose=False):
    if verbose:
        print("in get_atoms with list of indicies:")
        print(list_of_indicies)
    if not len(list_of_indicies):
        raise Exception('invalid input: list of indicies is empty!')
    atoms = AtomSet()
    num_res = 0
    for item in list_of_indicies:
        first, second = item
        #check for valid index and for end of chain
        max_index = len(mol.chains.residues) - 1
        assert first <= max_index, 'invalid start of residue range'
        assert second <= max_index, 'invalid end of residue range'
        assert second >= first, 'second index cannot be smaller than first'
        if second == max_index:
            #ie mol.chains.residues[second]==mol.chains.residues[-1]:
            these_res = mol.chains.residues[first:]
        else:
            these_res = mol.chains.residues[first:second + 1]
        if verbose: print("Adding  %3d residues " % (len(these_res)), end=' ')
        num_res += len(these_res)
        if verbose: print("Now there are %d residues total" % (num_res))
        for r in these_res:
            for n in names_to_use:
                atoms.append(r.atoms.get(n)[0])
    assert len(
        atoms
    ), 'invalid input: lists of indicies did not correspond to any residues!'
    if verbose: print('returning %d atoms' % (len(atoms)))
    return atoms
Пример #7
0
    def superimpose_cb(self):
        refAtoms = AtomSet()
        mobAtoms = AtomSet()
        for pair in self.newPairs.values():
            refAtoms.append(pair[0])
            mobAtoms.append(pair[1])

        apply(self.doitWrapper, (refAtoms, mobAtoms), {})
 def superimpose_cb(self):
     refAtoms = AtomSet()
     mobAtoms = AtomSet()
     for pair in self.newPairs.values():
         refAtoms.append(pair[0])
         mobAtoms.append(pair[1])
         
     apply( self.doitWrapper, (refAtoms,mobAtoms),  {} )
 def getAtoms(self,bnds):
     ats0 = AtomSet()
     for b in bnds:
         ats0.append(b.atom1)
         ats0.append(b.atom2)
     d = {}
     for a in ats0:
         d[a] = 0
     return AtomSet(d.keys())
Пример #10
0
 def getAtoms(self, bnds):
     ats0 = AtomSet()
     for b in bnds:
         ats0.append(b.atom1)
         ats0.append(b.atom2)
     d = {}
     for a in ats0:
         d[a] = 0
     return AtomSet(d.keys())
 def doit(self, bonds):
     global var
     var=1 
     ats = AtomSet([])
     for bond in bonds:
         ats.append(bond.atom1)
         ats.append(bond.atom2)
         self.vf.removeBonds(bond.atom1, bond.atom2)
     var=0
     self.vf.GUI.VIEWER.Redraw()
Пример #12
0
 def doit(self, bonds):
     global var
     var = 1
     ats = AtomSet([])
     for bond in bonds:
         ats.append(bond.atom1)
         ats.append(bond.atom2)
         self.vf.removeBonds(bond.atom1, bond.atom2)
     var = 0
     if self.vf.hasGui:
         self.vf.GUI.VIEWER.Redraw()
Пример #13
0
 def onRemoveObjectFromViewer(self, obj):
     removeAts = AtomSet([])
     for at in self.atomList:
         if at in obj.allAtoms:
             removeAts.append(at)
     self.atomList = self.atomList - removeAts
     removeAts = AtomSet([])
     for at in self.undoAtList:
         if at in obj.allAtoms:
             removeAts.append(at)
     self.undoAtList = self.undoAtList - removeAts
     self.update()
Пример #14
0
 def onRemoveObjectFromViewer(self, obj):
     removeAts = AtomSet([])
     for at in self.atomList:
         if at in obj.allAtoms:
             removeAts.append(at)
     self.atomList = self.atomList - removeAts
     removeAts = AtomSet([])
     for at in self.undoAtList:
         if at in obj.allAtoms:
             removeAts.append(at)
     self.undoAtList = self.undoAtList - removeAts
     self.update()
 def getCations(self, atoms):
     #select atoms in ARG and LYS residues
     arg_cations = atoms.get(lambda x: (x.parent.type=='ARG' and \
                             x.name in ['CZ']))
     lys_cations = atoms.get(lambda x: (x.parent.type=='LYS' and \
                             x.name in ['NZ', 'HZ1', 'HZ2', 'HZ3']))
     #select any positively-charged metal ions... cannot include CA here
     metal_cations = atoms.get(lambda x: x.name in ['Mn','MN', 'Mg',\
                             'MG', 'FE', 'Fe', 'Zn', 'ZN'])
     ca_cations = atoms.get(
         lambda x: x.name in ['CA', 'Ca'] and x.parent.type == 'CA')
     cations = AtomSet()
     #cations.extend(arg_cations)
     for a in arg_cations:
         cations.append(a)
     #cations.extend(lys_cations)
     for a in lys_cations:
         cations.append(a)
     #cations.extend(metal_cations)
     for a in metal_cations:
         cations.append(a)
     #cations.extend(ca_cations)
     for a in ca_cations:
         cations.append(a)
     return cations
Пример #16
0
 def checkForPossibleH(self, ats, blen):
     # @@FIX THIS: WHAT IS THE POINT OF THIS???
     # check that if at has all bonds, at least one is to a hydrogen
     # have to do this by element??
     probAts = AtomSet(ats.get(lambda x, blen=blen: len(x.bonds) == blen))
     # probOAts = ats.get(lambda x, blen=blen: len(x.bonds)==blen)
     # probSAts = ats.get(lambda x, blen=blen: len(x.bonds)==blen)
     if probAts:
         rAts = AtomSet([])
         for at in probAts:
             if not len(at.findHydrogens()):
                 rAts.append(at)
         if len(rAts):
             ats = ats.subtract(rAts)
     return ats
 def checkForPossibleH(self, ats, blen):
     #@@FIX THIS: WHAT IS THE POINT OF THIS???
     #check that if at has all bonds, at least one is to a hydrogen
     # have to do this by element??
     probAts = AtomSet(ats.get(lambda x, blen=blen: len(x.bonds)==blen))
     #probOAts = ats.get(lambda x, blen=blen: len(x.bonds)==blen)
     #probSAts = ats.get(lambda x, blen=blen: len(x.bonds)==blen)
     if probAts:
         rAts = AtomSet([])
         for at in probAts:
             if not len(at.findHydrogens()):
                 rAts.append(at)
         if len(rAts):
             ats =  ats.subtract(rAts)
     return ats
Пример #18
0
 def set_carbon_names(self, atoms, type):
     #set carbon names explicitly
     if not atoms or not len(atoms):
         return "ERROR: set_carbon_names called with no atoms"
     assert type in ['C','A']
     if not hasattr(atoms, 'autodock_element'):
         atoms.autodock_element = atoms.element
     changed = AtomSet()
     for at in atoms:
         if at.element!='C': continue
         if at.autodock_element!=type:
             if self.rename:
                 if len(at.name)>1:
                     at.name = type + at.name[1:]
                 else:
                     at.name = type
             at.autodock_element = type
             changed.append(at)
     return changed
Пример #19
0
 def set_carbon_names(self, atoms, type):
     #set carbon names explicitly
     if not atoms or not len(atoms):
         return "ERROR: set_carbon_names called with no atoms"
     assert type in ['C', 'A']
     if not hasattr(atoms, 'autodock_element'):
         atoms.autodock_element = atoms.element
     changed = AtomSet()
     for at in atoms:
         if at.element != 'C': continue
         if at.autodock_element != type:
             if self.rename:
                 if len(at.name) > 1:
                     at.name = type + at.name[1:]
                 else:
                     at.name = type
             at.autodock_element = type
             changed.append(at)
     return changed
Пример #20
0
 def getCations(self, atoms):
     #select atoms in ARG and LYS residues
     arg_cations = atoms.get(lambda x: (x.parent.type=='ARG' and \
                             x.name in ['CZ']))
     lys_cations = atoms.get(lambda x: (x.parent.type=='LYS' and \
                             x.name in ['NZ', 'HZ1', 'HZ2', 'HZ3']))
     #select any positively-charged metal ions... cannot include CA here
     metal_cations = atoms.get(lambda x: x.name in ['Mn','MN', 'Mg',\
                             'MG', 'FE', 'Fe', 'Zn', 'ZN'])
     ca_cations = atoms.get(lambda x: x.name in ['CA', 'Ca'] and x.parent.type=='CA')
     cations = AtomSet() 
     #cations.extend(arg_cations)
     for a in arg_cations:
         cations.append(a)
     #cations.extend(lys_cations)
     for a in lys_cations:
         cations.append(a)
     #cations.extend(metal_cations)
     for a in metal_cations:
         cations.append(a)
     #cations.extend(ca_cations)
     for a in ca_cations:
         cations.append(a)
     return cations
    def nextFrame(self, id):
        #Player.nextFrame(self, id)
        id = int(id)
        if id == self.currentFrameIndex: return
        if self.hasCounter and self.gui:
            self.form.ent2.delete(0,'end')
            self.form.ent2.insert(0, str(id))
            if self.hasSlider:
                self.form.ifd.entryByName['slider']['widget'].set(id)
        self.currentFrameIndex = int(id)        
        removeAtoms = AtomSet([])
        addAtoms = AtomSet([])
        
        id = int(id)
        flood = self.floods[id]
        centers = []
        materials = []
        radii = []
        prev_coords = self.mol.allAtoms.coords
        lenAtoms = len(prev_coords)
        #self.residue.atoms = AtomSet([])
        index = 0        
        #h = self.hp.heap()
        #print h
        for fl in flood:  
            x = (fl[1] - self.xcent)*self.spacing + self.centerx
            y = (fl[2] - self.ycent)*self.spacing + self.centery
            z = (fl[3] - self.zcent)*self.spacing + self.centerz
            if fl[4] == 7:
                atomchr = 'P'
                # note, this will color the NA atom pink (the PDB color for Phosphorus)
                radius = AAradii[13][0]
            if fl[4] == 6:
                atomchr = 'S'
                radius = AAradii[13][0]
            if fl[4] == 5:
                atomchr = 'A'
                radius = AAradii[10][0]
            if fl[4] == 4:
                atomchr = 'O'
                radius = AAradii[1][0]
            if fl[4] == 3:
                atomchr = 'N'
                radius = AAradii[4][0]
            if fl[4] == 2:
                atomchr = 'C'
                radius = AAradii[10][0]
            if fl[4] == 1:
                atomchr = 'H'      
                radius = AAradii[15][0]
            if not [x,y,z] in prev_coords:
                a = Atom(atomchr, self.residue, atomchr, top=self.mol)
                a._coords = [[x,y,z]]
                a._charges = {}
                a.hetatm = 1
                a.radius = radius
                #a.number = lenAtoms + 1
                addAtoms.append(a)
                lenAtoms += 1
                for key in self.colorKeys:
                    a.colors[key]=AtomElements[atomchr]
                    a.opacities[key]=1.0
            else:
                centers.append([x,y,z])
                            
#            a = Atom(atomchr, self.residue, atomchr, top=self.mol)
#            a._coords = [[x,y,z]]
#            a._charges = {}
#            a.hetatm = 1
#            a.number = index 
#            index += 1
            #aterials.append(AtomElements[atomchr])
            #enters.append([x,y,z])
            #adii.append(radius)
        #self.mol.allAtoms = self.residue.atoms
        #self.mol.geomContainer.geoms['lines'].protected = False
        #for com in self.autoLigandCommand.vf.cmdsWithOnAddObj:
        #    com.onAddObjectToViewer(self.mol)        
        #self.autoLigandCommand.vf.displayCPK(self.mol, scaleFactor=0.1)
        
        halo_centers = []
        for coord in prev_coords:
            if not coord in centers:
                index = prev_coords.index(coord)
                removeAtoms.append(self.mol.allAtoms[index])
        
        
        self.residue.assignUniqIndex() #this is needed to avoid Traceback later on
        self.mol.allAtoms.stringRepr = None #stringRepr can be very large aousing memory errors
        event = AddAtomsEvent(objects=addAtoms)
        #self.autoLigandCommand.vf.dispatchEvent(event)
        self.autoLigandCommand.vf.displayCPK.updateGeom(event)        
        event = DeleteAtomsEvent(objects=removeAtoms)
        #self.autoLigandCommand.vf.dispatchEvent(event)
        self.autoLigandCommand.vf.displayCPK.updateGeom(event)
        for atom in removeAtoms:
            self.residue.atoms.remove(atom)
        if id == self.maxFrame:
            self.autoLigandCommand.halo.Set(visible=0)
        else:
            self.autoLigandCommand.halo.Set(centers=addAtoms.coords, materials=((1,1,0,0.5),), radii=0.4)
Пример #22
0
class SetTorsionGUICommand(MeasureTorsionGUICommand):
    def guiCallback(self):
        self.save = self.vf.ICmdCaller.commands.value["Shift_L"]
        self.vf.setICOM(self, modifier="Shift_L", topCommand=0)
        if not hasattr(self, 'form'):
            self.buildForm()
        else:
            self.form.deiconify()

    def onAddCmdToViewer(self):
        if not hasattr(self.vf, 'GUI'):
            return
        self.undoNow = 0
        self.save = None
        from DejaVu.bitPatterns import pat3
        from DejaVu.IndexedPolygons import IndexedPolygons
        if not self.vf.commands.has_key('setICOM'):
            self.vf.loadCommand('interactiveCommands',
                                'setICOM',
                                'Pmv',
                                topCommand=0)
        if not self.vf.commands.has_key('measureTorsion'):
            self.vf.loadCommand('measureCommands',
                                'measureTorsion',
                                'Pmv',
                                topCommand=0)

        self.masterGeom = Geom('setTorsionGeom',
                               shape=(0, 0),
                               pickable=0,
                               protected=True)
        self.masterGeom.isScalable = 0
        self.vf.GUI.VIEWER.AddObject(self.masterGeom,
                                     parent=self.vf.GUI.miscGeom)
        self.lines = IndexedPolygons(
            'settorsionLine',
            materials=((0, 1, 1), ),
            inheritMaterial=0,
            stipplePolygons=1,
            protected=True,
        )
        if self.vf.userpref['Sharp Color Boundaries for MSMS'][
                'value'] == 'blur':
            self.lines.Set(
                inheritSharpColorBoundaries=False,
                sharpColorBoundaries=False,
            )
        self.lines.polygonstipple.Set(pattern=pat3)  #, tagModified=False)
        #self.lines.RenderMode(GL.GL_FILL, face=GL.GL_BACK)
        self.lines.Set(backPolyMode=GL.GL_FILL)
        self.labels = GlfLabels(name='settorsionLabel',
                                shape=(0, 3),
                                inheritMaterial=0,
                                materials=((0, 1, 1), ))
        self.spheres = Spheres(name='settorsionSpheres',
                               shape=(0, 3),
                               radii=0.2,
                               quality=15,
                               inheritMaterial=0,
                               materials=((0., 1., 1.), ),
                               protected=True)
        for item in [self.lines, self.labels, self.spheres]:
            self.vf.GUI.VIEWER.AddObject(item, parent=self.masterGeom)
        self.snakeLength = 1
        self.oldValue = None
        self.torsionType = Tkinter.StringVar()
        self.torsionType.set('1')
        self.newAngList = Tkinter.StringVar()
        self.TAHdata = None
        self.molecule = None
        #self.bondString = Tkinter.StringVar()
        self.callbackDict = {}
        self.callbackDict['measureDistanceGC'] = 'update'
        self.callbackDict['measureAngleGC'] = 'update'
        self.callbackDict['measureTorsionGC'] = 'update'

    def onRemoveObjectFromViewer(self, mol):
        lenAts = len(self.atomList)
        #if cmd has no atoms on its list, nothing to do
        if not lenAts:
            return
        #remove any atoms which are being deleted from viewer
        self.atomList = AtomSet(self.atomList) - mol.allAtoms
        #if some have been removed, do an update
        if lenAts != len(self.atomList):
            self.update()
            self.extslider.set(0)

    def __call__(self, atoms, angle=None, **kw):
        """torsion/None<-setTorsionGC(atoms, angle=None)
        the torsion is returned when the number of atoms is a multiple of 4"""
        ats = self.vf.expandNodes(atoms)
        if not len(ats): return 'ERROR'
        return apply(self.doitWrapper, (
            ats,
            angle,
        ), kw)

    def doit(self, ats, angle):
        for at in ats:
            lenAts = len(self.atomList)
            if lenAts and lenAts % 4 != 0 and at == self.atomList[-1]:
                continue
            if len(self.atomList) == 0:
                self.molecule = at.top
            if at.top == self.molecule:
                self.atomList.append(at)
            else:
                #all atoms in torsion must be in same molecule ...(?)
                s = at.full_name() + " not in " + self.molecule.full_name()
                self.warningMsg(s)
                return 'ERROR'
            if len(self.atomList) > 4 * self.snakeLength:
                self.atomList = self.atomList[4:]
            self.update()
        if len(self.atomList) == 4:
            mol = self.atomList[0].top
            at0, at1, at2, at3 = self.atomList
            self.mov_atoms = mol.subTree(at1, at2, mol.allAtoms)
            self.oldValue = self.vf.measureTorsion.doit(at0, at1, at2, at3)
            self.origValue = self.oldValue
            self.origCoords = self.mov_atoms.coords
            if hasattr(self, 'extslider'):
                self.extslider.set(self.oldValue, update=0)
            if angle:
                #angle is what you want to end up with
                deltaAngle = angle - self.oldValue
                #print 'deltaAngle=', deltaAngle, 'angle=', angle
                self.transformCoords(deltaAngle)
                if hasattr(self, 'extslider'):
                    self.extslider.set(angle, update=0)
                #s = self.atomList[2].full_name()+'--'+self.atomList[3].full_name()
                #self.bondString.set(s)
            self.updateHistory()
            ##if self.undoNow: raise 'abc'
            #return float(self.labelStrs[-1])
            return

    def update(self, forward=1, event=None):
        if not len(self.atomList):
            self.spheres.Set(vertices=[], tagModified=False)
            self.labels.Set(vertices=[], tagModified=False)
            self.lines.Set(vertices=[], tagModified=False)
            self.vf.GUI.VIEWER.Redraw()
            return
        limit = self.snakeLength
        #each time have to recalculate lineVertices
        self.lineVertices = []
        for at in self.atomList:
            c1 = self.getTransformedCoords(at)
            self.lineVertices.append(tuple(c1))
        #display spheres:
        self.spheres.Set(vertices=self.lineVertices, tagModified=False)
        self.vf.GUI.VIEWER.Redraw()
        #label with torsion
        #lines between spheres are only drawn when angle completed
        #that is, len(ats)%4=0
        if len(self.lineVertices) < 4:
            self.labels.Set(vertices=[], tagModified=False)
            self.lines.Set(vertices=[], tagModified=False)
        else:
            #rebuild labels and polygons each time
            self.labelCenters = []
            self.labelStrs = []
            #labelCenters, labelStrs,
            #this gets done lenATs/4 times
            numItems = len(self.atomList) / 4
            for i in range(numItems):
                at0, at1, at2, at3 = self.atomList[i * 4:i * 4 + 4]
                torsion = self.vf.measureTorsion.doit(at0, at1, at2, at3)
                torsionLabel = '%.3f' % torsion
                self.labelStrs.append(torsionLabel)
                c0 = self.getTransformedCoords(at0)
                c1 = self.getTransformedCoords(at3)
                newcenter = tuple((c0 + c1) / 2.0)
                self.labelCenters.append(newcenter)
        self.vf.GUI.VIEWER.Redraw()
        items = self.callbackDict.keys()
        #items = ['measureDistanceGC','measureAngleGC','measureTorsionGC']
        #checkout whether measure update needs to be called
        icomVals = self.vf.ICmdCaller.commands.value.values()
        for item in items:
            if not len(icomVals): break
            if not hasattr(self.vf, item):
                continue
            exec('cmd = self.vf.' + item)
            if cmd in icomVals:
                #cmd.update()
                s = self.callbackDict[item]
                exec('self.vf.' + item + '.' + s + '()')

    def transformCoords(self, deltaAngle):
        """ deltaAngle is NOW not final angle wanted but relative"""
        #mov_coords is the array of the coords of the atoms to be moved,
        #x2 and x3 are atoms which define the axis of the transformation
        #by deltaAngle. NB: effect is that mov_atoms.coords
        #are transformed...
        if not hasattr(self, 'mov_atoms'): return
        if not len(self.mov_atoms): return
        x1, x2, x3, x4 = self.atomList
        nc = self.vf.setRelativeTorsion.doit(x2,
                                             x3,
                                             deltaAngle,
                                             self.mov_atoms,
                                             returnVal=1)
        mol = x2.top
        #mov_atoms = mol.subTree(x2, x3, mol.allAtoms)
        for i in range(len(nc)):
            at = self.mov_atoms[i]
            at._coords[at.conformation] = nc[i].tolist()
        event = EditAtomsEvent('coords', self.mov_atoms)
        self.vf.dispatchEvent(event)
        self.update()


#####Callback Functions for the Dial:
#####slideCallback

    def slideCallback(self, eventval):
        #print 'in slideCallback'
        if len(self.atomList) != 4: return
        if not hasattr(self, 'oldValue'): return
        if self.oldValue == None:
            return
        #self.setupUndoBefore(self.atomList, self.oldValue)
        try:
            newAngle = self.extslider.get()
            tT = self.torsionType.get()
            at0, at1, at2, at3 = self.atomList
            #torsion = self.vf.measureTorsion.doit(at0, at1, at2, at3)
            torsion = self.oldValue
            if tT == '1':
                #NEWdeltaAngle = newAngle
                deltaAngle = newAngle - torsion
            else:
                #NEWdeltaAngle = newAngle + torsion
                deltaAngle = newAngle
            self.transformCoords(deltaAngle)
            #print 'deltaAngle=', deltaAngle
            self.oldValue = newAngle
            #self.oldValue = newAngle
        except ValueError:
            self.vf.GUI.message("error in slideCallback\n")

    def rdSet(self, event=None):
        #"""radiobutton selection of torsionType:
        #Absolute: initial angle to be displayed in slider/entry
        #Relative: 0 is displayed """
        if self.torsionType.get() == '1':
            aL = self.atomList
            if len(aL) == 4:
                torsion = self.vf.measureTorsion.doit(aL[0], aL[1], aL[2],
                                                      aL[3])
                self.extslider.set(torsion)
        else:
            self.extslider.set(0)

    def setupUndoBefore(self, ats, angle):
        pass

    #def setupUndoBefore(self, ats, angle):
    ##no atoms, <4 atoms,
    #aSet = AtomSet(self.atomList)
    #self.undoMenuString = self.name
    #if len(self.atomList)==0:
    #undoCmd = 'self.setTorsionGC.atomList=[]; self.setTorsionGC.update()'
    #elif len(self.atomList)<4:
    ##need to step back here
    #undoCmd = 'self.setTorsionGC.atomList=self.setTorsionGC.atomList[:-1]; self.setTorsionGC.update()'
    #else:
    ##print 'self.oldValue=', self.oldValue
    #undoCmd = 'self.setTorsionGC(\''+ aSet.full_name()+ '\',' + str(self.oldValue) + ', topCommand=0)'
    ##self.oldValue = str(self.extslider.get())
    #self.vf.undo.addEntry((undoCmd), (self.name))

    def setupUndoAfter(self, ats, angle, **kw):
        #no atoms, <4 atoms,
        aSet = AtomSet(self.atomList)
        self.undoMenuString = self.name
        if len(self.atomList) == 0:
            undoCmd = 'self.setTorsionGC.atomList=[]; self.setTorsionGC.update()'
        elif len(self.atomList) < 4:
            #need to step back here
            undoCmd = 'self.setTorsionGC.atomList=self.setTorsionGC.atomList[:-1]; self.setTorsionGC.update()'
        elif self.origValue == self.oldValue:
            return
        else:
            restoreAngle = self.origValue
            self.undoNow = 1
            undoCmd = 'self.setTorsionGC(\'' + aSet.full_name() + '\',' + str(
                restoreAngle) + ', topCommand=0)'
        self.vf.undo.addEntry((undoCmd), (self.name))

    def Accept_cb(self):
        apply(self.setupUndoAfter, (self.atomList, self.oldValue), {})
        self.origValue = self.oldValue

    def Done_cb(self):
        self.vf.setICOM(self.save,
                        modifier="Shift_L",
                        mode='pick',
                        topCommand=0)
        self.stopICOM()

    def startICOM(self):
        self.vf.setIcomLevel(Atom)
        if not hasattr(self, 'form'):
            self.buildForm()
        else:
            self.form.deiconify()

    def stopICOM(self):
        if hasattr(self, 'form'):
            self.form.withdraw()
        self.atomList = []
        self.atomCenters = []
        self.labelStrs = []
        self.labelCenters = []
        self.lineVertices = []
        self.spheres.Set(vertices=[], tagModified=False)
        self.lines.Set(vertices=[], faces=[], tagModified=False)
        self.labels.Set(vertices=[], tagModified=False)
        self.vf.GUI.VIEWER.Redraw()
        #when cmd stops being icom, remove callback
        ##         ehm = self.vf.GUI.ehm
        ##         for event in ['<B2-Motion>', '<B3-Motion>']:
        ##             if ehm.eventHandlers.has_key(event) and self.update_cb in \
        ##                     ehm.eventHandlers[event]:
        ##                 ehm.RemoveCallback(event, self.update_cb)
        for event in ['<B2-Motion>', '<B3-Motion>']:
            self.vf.GUI.removeCameraCallback(event, self.update_cb)

    def repeat_transTors(self, event=None):
        deltaAngle = self.extslider.get()
        if self.torsionType.get() != '1':
            self.transformCoords(deltaAngle)
        #this is here in order to create a log message
        nc = self.vf.setRelativeTorsion(self.atomList[1],
                                        self.atomList[2],
                                        deltaAngle,
                                        self.mov_atoms,
                                        returnVal=1)
        event = EditAtomsEvent('coords', self.mov_atoms)
        self.vf.dispatchEvent(event)

    def new_Tors(self, event=0):
        self.atomList = []
        self.update()

    #when called, most recent 4 atoms are in self.atomList
    def updateHistory(self):
        """1: call TorsionHistory.getTorsion:
        make a new TorsionAngle or add current angle to angleList
        2: put TA.name_string into ListBox
        3: best if insert a tuple (string to be displayed, item itself)
        4: adjust size with self.historyList.configure(height=self.[].size)
        5: limit overall size to 4"""
        #print 'in updateHistory'
        molecule = self.atomList[-1].top
        if self.TAHdata is None:
            self.TAHdata = TorsionHistory(molecule)
        a1, a2, a3, a4 = self.atomList
        newone = self.TAHdata.getTorsion(a1, a2, a3, a4)
        #first check to see if it is in there already???
        #need to get info back from getTorsion....(???)
        if hasattr(self, 'historyList'):
            if newone.new:
                self.historyList.insert('end', newone.name_string)
                if int(self.historyList.cget('height')) < 4:
                    self.historyList.configure(height=self.historyList.size())
            if self.historyList.curselection():
                self.historyList.select_clear(self.historyList.curselection())
            newindex = self.TAHdata.getIndex(newone)
            self.historyList.select_set(newindex)
            self.historyList.see(newindex)
        #set entry to a string ==current TA's angleList
        newstring = ""
        for item in newone.angleList:
            newstring = newstring + " " + "%5.3f" % item
        self.newAngList.set(newstring)

    def HLCommand(self, event=None):
        """double-clicking selection in listbox causes curselection to be picked...
        1:self.atomList set to atoms of curselection
        2:self.mov_atoms set to atoms of curselection
        3:self.selAtom[1-4].Set(vertices=atoms.coords)
        4:reset entry +slider and init_bondAngle etc
        5.add current angle to selection's.angleList"""
        #get TA:
        if self.historyList.get(0) == '': return
        items = self.historyList.curselection()
        if type(items) == types.TupleType:
            items = items[0]
        try:
            items = map(int, items)
        except ValueError:
            pass
        thisTA = self.TAHdata.torslist[items[0]]
        #get currentAngle
        current = thisTA.getCurrentAngle()
        if not thisTA.inList(current):
            thisTA.angleList.append(current)
        newAts = AtomSet([thisTA.atom1,thisTA.atom2, thisTA.atom3,\
                    thisTA.atom4])
        #reset self.molecule
        self.atomList = []
        self.molecule = newAts[0].top
        self.doit(newAts, current)
        #self.setTorsionAngle(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4, current, 'A')
        #self.drawTransformedAngle()
        #self.updatespheres(items[0])
        #self.update()
        self.extslider.set(current, 0)
        newstring = ""
        for item in thisTA.angleList:
            newstring = newstring + " " + "%5.3f" % item
        self.newAngList.set(newstring)

    def getAngList(self, event=None):
        items = self.historyList.curselection()
        try:
            items = map(int, items)
        except ValueError:
            pass
        thisTA = self.TAHdata.torslist[items[0]]
        thisTA.angleList = map(float, split(self.newAngList.get()))
        last = thisTA.angleList[-1]
        newAts = AtomSet([thisTA.atom1,thisTA.atom2, thisTA.atom3,\
                    thisTA.atom4])
        #reset self.molecule
        self.atomList = []
        self.molecule = newAts[0].top
        self.doit(newAts, last)
        #self.doit(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,last,'A')
        #self.setTorsionAngle(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,last,'A')
        #self.drawTransformedAngle()
        #self.updatespheres(items[0])
        self.extslider.set(last, 0)

    def stepBack(self, event=None):
        items = self.historyList.curselection()
        if len(items) == 0: return
        try:
            items = map(int, items)
        except ValueError:
            pass
        thisTA = self.TAHdata.torslist[items[0]]
        ####last angle is thisTA.angleList[-1]
        if len(thisTA.angleList) > 1:
            last = thisTA.angleList[-1]
            lastIndex = thisTA.angleList.index(last)
            thisTA.angleList = thisTA.angleList[:lastIndex]
            last = thisTA.angleList[-1]
        else:
            last = thisTA.angleList[0]
        newAts = AtomSet([thisTA.atom1,thisTA.atom2, thisTA.atom3,\
                    thisTA.atom4])
        #reset self.molecule
        self.atomList = []
        self.molecule = newAts[0].top
        self.doit(newAts, last)
        #self.doit(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,last,'A')
        #self.setTorsionAngle(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,last,'A')
        #self.drawTransformedAngle()
        #self.updatespheres(items[0])
        newstring = ""
        for item in thisTA.angleList:
            newstring = newstring + " " + "%5.3f" % item
        self.newAngList.set(newstring)
        self.extslider.set(last, 0)
        #IS THIS ENOUGH in order to create correct log?
        self.mouseUp()

    def startOver(self, event=None):
        items = self.historyList.curselection()
        if len(items) == 0: return
        try:
            items = map(int, items)
        except ValueError:
            pass
        thisTA = self.TAHdata.torslist[items[0]]
        self.resetAngle(thisTA)

    def resetAngle(self, thisTA, event=None):
        #first angle is thisTA.angleList[0]
        ang = thisTA.angleList[0]
        newAts = AtomSet([thisTA.atom1,thisTA.atom2, thisTA.atom3,\
                    thisTA.atom4])
        #reset self.molecule
        self.atomList = []
        self.molecule = newAts[0].top
        self.doit(newAts, ang)
        #self.doit(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,ang,'A')
        #self.setTorsionAngle(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,ang,'A')
        if len(thisTA.angleList) > 1:
            thisTA.angleList = thisTA.angleList[:1]
        #self.drawTransformedAngle()
        self.extslider.set(ang, 0)
        self.mouseUp()
        self.newAngList.set("%5.3f" % ang)

    def resetAll(self, event=None):
        if self.TAHdata == None: return
        for item in self.TAHdata.torslist:
            self.resetAngle(item)
        self.spheres.Set(vertices=[], tagModified=False)
        self.vf.GUI.VIEWER.Redraw()

    def buildForm(self):
        if hasattr(self, 'ifd'):
            return
        self.torsionType = Tkinter.StringVar()
        self.torsionType.set('1')
        self.ifd = ifd = InputFormDescr(title='Set Torsion Angle')
        ifd.append({
            'name': 'extLabel',
            'widgetType': Tkinter.Label,
            'wcfg': {
                'text': 'Set Angle:\n(180=trans)'
            },
            'gridcfg': {
                'sticky': Tkinter.W + Tkinter.E,
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'extslider',
            'widgetType': ExtendedSliderWidget,
            'wcfg': {
                'label': 'torsion',
                'minval': -360.,
                'maxval': 360.,
                'width': 150,
                'immediate': 1,
                'command': self.slideCallback,
                'sliderType': 'float',
                'entrypackcfg': {
                    'side': 'bottom'
                }
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'typeLabel',
            'widgetType': Tkinter.Label,
            'wcfg': {
                'text': 'Torsion Type'
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'rdbut1',
            'widgetType': Tkinter.Radiobutton,
            'wcfg': {
                'text': 'Absolute',
                'variable': self.torsionType,
                'value': 1,
                'command': self.rdSet
            },
            'gridcfg': {
                'sticky': 'we'
            }
        })
        ifd.append({
            'name': 'rdbut2',
            'widgetType': Tkinter.Radiobutton,
            'wcfg': {
                'text': 'Relative ',
                'variable': self.torsionType,
                'value': 0,
                'command': self.rdSet
            },
            'gridcfg': {
                'sticky': 'we',
                'row': -1,
                'column': 1
            }
        })
        ifd.append({
            'name': 'historyList',
            'widgetType': ListChooser,
            'wcfg': {
                'title': 'TorsionAngle\nTranformation History',
                'mode': 'single',
                'command': self.HLCommand,
                'lbwcfg': {
                    'height': 5,
                    'selectforeground': 'yellow',
                    'exportselection': 0,
                    'width': 30
                },
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'hbut1',
            'widgetType': Tkinter.Button,
            'wcfg': {
                'text': 'Step Back ',
                'command': self.stepBack
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'hbut2',
            'widgetType': Tkinter.Button,
            'wcfg': {
                'text': 'Start Over ',
                'command': self.startOver
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'hbut3',
            'widgetType': Tkinter.Button,
            'wcfg': {
                'text': 'Reset All ',
                'command': self.resetAll
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'angListEnt',
            'widgetType': Tkinter.Entry,
            'wcfg': {
                'width': 5,
                'command': self.getAngList,
                'textvariable': self.newAngList
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'hbut4',
            'widgetType': Tkinter.Button,
            'wcfg': {
                'text': 'Move',
                'command': self.repeat_transTors
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        ifd.append({
            'name': 'hbut5',
            'widgetType': Tkinter.Button,
            'wcfg': {
                'text': 'New Torsion',
                'command': self.new_Tors
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        #ifd.append({'name':'accept',
        #'widgetType': Tkinter.Button,
        #'wcfg':{'text' : 'Accept',
        #'command': self.Accept_cb},
        #'gridcfg':{'sticky':'we'}})
        ifd.append({
            'name': 'done',
            'widgetType': Tkinter.Button,
            'wcfg': {
                'text': 'Done',
                'command': self.Done_cb
            },
            'gridcfg': {
                'sticky': 'we',
                'columnspan': 2
            }
        })
        #'gridcfg':{'sticky':'we','column':1, 'row':-1}})
        self.form = self.vf.getUserInput(ifd, modal=0, blocking=0)
        self.form.root.protocol('WM_DELETE_WINDOW', self.Done_cb)
        self.extslider = self.ifd.entryByName['extslider']['widget']
        self.extslider.draw.bind('<ButtonRelease-1>', self.mouseUp, add='+')
        self.extslider.entry.bind('<Return>', self.mouseUp, add='+')
        self.historyList = self.ifd.entryByName['historyList']['widget'].lb
        #self.historyList.bind("<Double-Button-1>",self.HLCommand)
        self.hbut1 = self.ifd.entryByName['hbut1']['widget']
        self.hbut2 = self.ifd.entryByName['hbut2']['widget']
        self.hbut3 = self.ifd.entryByName['hbut3']['widget']
        self.angListEnt = self.ifd.entryByName['angListEnt']['widget']

    def mouseUp(self, event=None):
        #print "in mouseUp"
        #fix this: atomList length dependent
        if len(self.atomList) == 4:
            at0, at1, at2, at3 = self.atomList
            angle = self.extslider.get()
            if self.torsionType.get() == '1':
                self.vf.setTorsion(at0, at1, at2, at3, angle)
            else:
                self.vf.setRelativeTorsion(at1, at2, angle)
Пример #23
0
    def addHydrogens(self, mol):
        #check for bonds
        if len(mol.allAtoms.bonds[0]) == 0:
            mol.buildBondsByDistance()
        bonds = mol.allAtoms.bonds[0]
        #could have preset babel_types
        #so check if allAtoms are already typed
        try:
            t = mol.allAtoms.babel_type
        except:
            #if all are not pretyped, type them
            babel = AtomHybridization()
            babel.assignHybridization(mol.allAtoms)

        if self.method == 'withBondOrder':
            mol.rings = RingFinder()
            mol.rings.findRings2(mol.allAtoms, mol.allAtoms.bonds[0])
            mol.rings.bondRings = {}
            for ind in xrange(len(mol.rings.rings)):
                r = mol.rings.rings[ind]
                for b in r['bonds']:
                    if not mol.rings.bondRings.has_key(b):
                        mol.rings.bondRings[b] = [
                            ind,
                        ]
                    else:
                        mol.rings.bondRings[b].append(ind)
            bo = BondOrder()
            bo.assignBondOrder(mol.allAtoms, bonds, mol.rings)
            mol.allAtoms._bndtyped = 1
            # do aromatic here
            arom = Aromatic(mol.rings)
            arom.find_aromatic_atoms(mol.allAtoms)

        hat = AddHydrogens().addHydrogens(mol.allAtoms, method=self.method)
        bondedAtomDict = {}  # key is heavy atom
        for a in hat:
            if bondedAtomDict.has_key(a[1]):
                bondedAtomDict[a[1]].append(a)
            else:
                bondedAtomDict[a[1]] = [a]

        # now create Atom object for hydrogens
        # and add the to the residues's atom list
        molNewHs = AtomSet([])  # list of created H atoms for this molecule
        heavyAtoms = AtomSet([])  # list of atoms that need new radii

        for heavyAtom, HatmsDscr in bondedAtomDict.items():
            #don't add hydrogens to carbons: polar Only!!!
            if self.htype != 'all' and heavyAtom.element == 'C':
                continue
            res = heavyAtom.parent
            # find where to insert H atom
            childIndex = res.children.index(heavyAtom) + 1

            # loop over H atoms description to be added
            # start at the end to number correctly
            l = len(HatmsDscr)
            for i in range(l - 1, -1, -1):
                a = HatmsDscr[i]
                # build H atom's name
                if len(heavyAtom.name) == 1:
                    name = 'H' + heavyAtom.name
                else:
                    name = 'H' + heavyAtom.name[1:]

                # if more than 1 H atom, add H atom index
                # for instance HD11, HD12, Hd13 (index is 1,2,3)
                if l > 1:
                    name = name + str(i + 1)

                # create the H atom object
                atom = Atom(name,
                            res,
                            top=heavyAtom.top,
                            chemicalElement='H',
                            childIndex=childIndex,
                            assignUniqIndex=0)

                # set atoms attributes
                atom._coords = [a[0]]
                if hasattr(a[1], 'segID'): atom.segID = a[1].segID
                atom.hetatm = 0
                atom.alternate = []
                #atom.element = 'H'
                atom.occupancy = 1.0
                atom.conformation = 0
                atom.temperatureFactor = 0.0
                atom.babel_atomic_number = a[2]
                atom.babel_type = a[3]
                atom.babel_organic = 1
                atom.radius = 1.2

                # create the Bond object bonding Hatom to heavyAtom
                bond = Bond(a[1], atom, bondOrder=1)

                # add the created atom the the list
                molNewHs.append(atom)
                # in case this new hydrogen atom ever ends up in pmv
                # HAVE TO CREATE THESE ENTRIES
                # create the color entries for all geoemtries
                # available for the heavyAtom
                for key, value in heavyAtom.colors.items():
                    atom.colors[key] = (0.0, 1.0, 1.0)
                    atom.opacities[key] = 1.0

        mol.allAtoms = mol.chains.residues.atoms
        if self.renumber:
            mol.allAtoms.number = range(1, len(mol.allAtoms) + 1)
        return len(molNewHs)
Пример #24
0
class AddBondsGUICommand(MVCommand, MVAtomICOM):
    """
    The AddBondGUICommand provides an interactive way of creating bonds between two given atoms by picking on them. To use this command you need first to load it into PMV. Then you can find the entry 'addBonds' under the Edit menu. To add bonds  you just need to pick on the 2 atoms you want to bind. If you drag select  a bunch of atoms, the command will buildBondsByDistance between them.This command is undoable.
   \nPackage : Pmv
   \nModule  : bondsCommands
   \nClass   : AddBondsGUICommand
   \nCommand : addBondsGC
   \nSynopsis:\n
        None<-addBondsGC(atoms)\n
    \nRequired Arguments:\n    
        atoms  : atom(s)\n
    """
    
    def __init__(self, func=None):
        MVCommand.__init__(self, func)
        MVAtomICOM.__init__(self)
        self.atomList = AtomSet([])
        self.undoAtList = AtomSet([])
        self.labelStrs = []


    def onRemoveObjectFromViewer(self, obj):
        removeAts = AtomSet([])
        for at in self.atomList:
            if at in obj.allAtoms:
                removeAts.append(at)
        self.atomList = self.atomList - removeAts
        removeAts = AtomSet([])
        for at in self.undoAtList:
            if at in obj.allAtoms:
                removeAts.append(at)
        self.undoAtList = self.undoAtList - removeAts
        self.update()

       
    def onAddCmdToViewer(self):
        if not self.vf.commands.has_key('setICOM'):
            self.vf.loadCommand('interactiveCommands', 'setICOM', 'Pmv',
                                topCommand=0) 
        if not self.vf.commands.has_key('addBonds'):
            self.vf.loadCommand('bondsCommands', 'addBonds', 'Pmv',
                                topCommand=0) 
        if not self.vf.commands.has_key('removeBondsGC'):
            self.vf.loadCommand('bondsCommands', 'removeBondsGC', 'Pmv',
                                topCommand=0) 
        self.masterGeom = Geom('addBondsGeom',shape=(0,0), 
                               pickable=0, protected=True)
        self.masterGeom.isScalable = 0
        self.spheres = Spheres(name='addBondsSpheres', shape=(0,3),
                               inheritMaterial=0,
                               radii=0.2, quality=15,
                               materials = ((1.,1.,0.),), protected=True) 
        if not self.vf.commands.has_key('labelByExpression'):
            self.vf.loadCommand('labelCommands', 
                                ['labelByExpression',], 'Pmv', topCommand=0)
        if self.vf.hasGui:
            miscGeom = self.vf.GUI.miscGeom
            self.vf.GUI.VIEWER.AddObject(self.masterGeom, parent=miscGeom)
            self.vf.GUI.VIEWER.AddObject(self.spheres, parent=self.masterGeom)


    def __call__(self, atoms, **kw):
        """None<-addBondsGC(atoms)
           \natoms  : atom(s)"""
        if type(atoms) is StringType:
            self.nodeLogString = "'"+atoms+"'"
        ats = self.vf.expandNodes(atoms)
        if not len(ats): return 'ERROR'
        return apply(self.doitWrapper, (ats,), kw)


    def doit(self, ats):
        if len(ats)>2:
            if len(self.atomList):
                atSet = ats + self.atomList
            else: atSet = ats
            parent = atSet[0].parent
            parent.buildBondsByDistanceOnAtoms(atSet)
            self.atomList = AtomSet([])
            self.update(True)
        else:
            lenAts = len(self.atomList)
            last = None
            if lenAts:
                last = self.atomList[-1]
                top = self.atomList[0].top
            for at in ats:
                #check for repeats of same atom
                if lenAts and at==last:
                    continue
                #lenAts = len(self.atomList)
                #if lenAts and at==self.atomList[-1]:
                #    continue
                if lenAts and at.top!=self.atomList[-1].top:
                    msg = "intermolecular bond to %s disallowed"%(at.full_name())
                    self.warningMsg(msg)
                self.atomList.append(at)
                self.undoAtList.append(at)
                lenAts = len(self.atomList)
            self.update(True)
            #if only have one atom, there is nothing else to do
            if lenAts<2: return
            #now build bonds between pairs of atoms
            atSet = self.atomList
            if lenAts%2!=0:
                atSet = atSet[:-1]
                #all pairs of atoms will be bonded
                #so keep only the last one
                self.atomList = atSet[-1:]
                lenAts = lenAts -1
            else:
                self.vf.labelByExpression(self.atomList, negate=1, topCommand=0)
                self.atomList = AtomSet([])
            for i in range(0, lenAts, 2):
                at1 = atSet[i]
                at2 = atSet[i+1]
                self.vf.addBonds(at1, at2, origin='UserDefined', topCommand=0)
        self.update(True)


    def applyTransformation(self, pt, mat):
        pth = [pt[0], pt[1], pt[2], 1.0]
        return Numeric.dot(mat, pth)[:3]


    def getTransformedCoords(self, atom):
        if not atom.top.geomContainer:
            return atom.coords
        g = atom.top.geomContainer.geoms['master']
        c = self.applyTransformation(atom.coords, g.GetMatrix(g))
        return  c.astype('f')


    def update(self, event=None):
        if not len(self.atomList):
            self.spheres.Set(vertices=[], tagModified=False)
            self.vf.labelByExpression(self.atomList, negate=1, topCommand=0)
            if self.vf.hasGui:
                self.vf.GUI.VIEWER.Redraw()
            return
        self.lineVertices=[]
        #each time have to recalculate lineVertices
        for at in self.atomList:
            c1 = self.getTransformedCoords(at)
            self.lineVertices.append(tuple(c1))
            
        if event:
            self.spheres.Set(vertices=self.lineVertices, tagModified=False)
            self.vf.labelByExpression(self.atomList,
                                      function = 'lambda x: x.full_name()',
                                      lambdaFunc = 1,
                                      textcolor = 'yellow',
                                      format = '', negate = 0,
                                      location = 'Last', log = 0,
                                      font = 'arial1.glf', only = 1,
                                      topCommand=0)
        #setting spheres doesn't trigger redraw so do it explicitly
        if self.vf.hasGui:
            self.vf.GUI.VIEWER.Redraw()


    def guiCallback(self, event=None):
        self.save = self.vf.ICmdCaller.commands.value["Shift_L"]
        self.vf.setICOM(self, modifier="Shift_L", topCommand=0)


    def setupUndoAfter(self, ats, **kw):
        
        lenUndoAts = len(self.undoAtList)
        lenAts = len(ats)
        if lenAts==1:
            #after adding 1 self.atomList would be 1 or 0
            if len(self.atomList)==1:            
                s = '0'
                ustr='"c=self.addBondsGC; self.labelByExpression(c.atomList, negate=1, topCommand=0);c.atomList=c.atomList[:'+s+'];c.undoAtList=c.undoAtList[:-1];c.update()"'
            else:
                self.vf.undoCmdStack.remove(self.prev_undoCmds)
                ind = str(lenUndoAts - 2)
                ustr = '"c=self.addBondsGC;nodes=self.expandNodes('+'\''+self.undoAtList[-2:].full_name()+'\''+'); bonds=nodes.bonds[0];self.removeBondsGC(bonds, topCommand=0);c.atomList=nodes[:1];c.undoAtList=c.undoAtList[:'+ind+'];c.update()"'
        elif lenUndoAts>lenAts:
            ustr='"c=self.addBondsGC;nodes=self.expandNodes('+'\''+ats.full_name()+'\''+');bonds = nodes.bonds[0];self.removeBondsGC(bonds, topCommand=0);c.undoAtList=c.undoAtList[:'+str(lenAts)+']"'
        else:
            ustr='"c=self.addBondsGC;nodes=self.expandNodes('+'\''+ats.full_name()+'\''+');bonds = nodes.bonds[0];self.removeBondsGC(bonds, topCommand=0);c.undoAtList=c.undoAtList[:0]"'
        if len(self.atomList) and lenAts>1:
            atStr = self.atomList.full_name()
            estr = ';nodes=self.expandNodes('+'\''+self.atomList.full_name()+'\''+');c.atomList=nodes;c.update()"'
            ustr = ustr + estr
        self.undoCmds = "exec("+ustr+")"
        self.prev_undoCmds = (self.undoCmds, "addBondsGC")
        
    def startICOM(self):
        self.vf.setIcomLevel( Atom, topCommand=0)

    def stopICOM(self):
        if len(self.atomList)!=0:
            self.vf.labelByExpression(self.atomList, negate=1, topCommand = 0)
        del self.atomList[:]
        self.labelStrs = []
        self.spheres.Set(vertices=[], tagModified=False)
        self.vf.GUI.VIEWER.Redraw()
        self.save = None
    #setup the reference molecule
    from MolKit import Read
    from MolKit.molecule import AtomSet
    ref_name, ref_ll = lines[0].split()
    ref_mol = Read(ref_name)[0]
    ref_ats = AtomSet()
    ref_indices = list(map(int, ref_ll.split(',')))
    num_ref_indices = len(ref_indices)
    if num_ref_indices < 3:
        print(" At least 3 indices are required! only %d indices found!!!" %
              (num_ref_indices))
        exit()
    for i in ref_indices:
        #ref_ats.append(ref_mol.allAtoms[i-1])
        ref_ats.append(ref_mol.allAtoms.get(lambda x: x.number == i)[0])

    num_ref_ats = len(ref_ats)

    #setup the tool for the rigid fit
    from mglutil.math.rigidFit import RigidfitBodyAligner
    RFA = RigidfitBodyAligner()
    RFA.setRefCoords(ref_ats.coords)

    #transform the rest of the molecules
    for l in lines[1:]:
        name, ll = l.split()
        ll.strip()
        moving_mol = Read(name)[0]
        indices = list(map(int, ll.split(',')))
        moving_ats = AtomSet()
Пример #26
0
 def filterBasedOnAngs(self, pD, d2Ats, d3Ats, a2Ats, a3ats, paramDict):
     badAtDict = {}
     d2max = paramDict['d2max']
     d2min = paramDict['d2min']
     d3max = paramDict['d3max']
     d3min = paramDict['d3min']
     # NEED these parameters
     a2max = paramDict['a2max']
     a2min = paramDict['a2min']
     a3max = paramDict['a3max']
     a3min = paramDict['a3min']
     # NB now pD keys could be hydrogens OR donors
     for k in list(pD.keys()):
         if k.element == 'H':
             d = k.bonds[0].atom1
             if id(d) == id(k):
                 d = k.bonds[0].atom2
             # d = k.bonds[0].neighborAtom(k)
             h = k
         else:
             d = k
             h = None
         badAts = AtomSet([])
         ct = 0
         for ac in pD[k]:
             if h is not None:
                 ang = getAngle(ac, h, d)
             else:
                 acN = ac.bonds[0].atom1
                 if id(acN) == id(ac):
                     acN = ac.bonds[0].atom2
                 # acN = ac.bonds[0].neighborAtom(ac)
                 ang = getAngle(d, ac, acN)
             # print 'ang=', ang
             dSp2 = d in d2Ats
             aSp2 = ac in a2Ats
             # these limits could be adjustable
             if h is not None:
                 if dSp2:
                     upperLim = d2max
                     lowerLim = d2min
                     # upperLim = 170
                     # lowerLim = 130
                 else:
                     upperLim = d3max
                     lowerLim = d3min
                     # upperLim = 180
                     # lowerLim = 120
             else:
                 # if there is no hydrogen use d-ac-acN angles
                 if dSp2:
                     upperLim = a2max
                     lowerLim = a2min
                     # upperLim = 150
                     # lowerLim = 110
                 else:
                     upperLim = a3max
                     lowerLim = a3min
                     # upperLim = 150
                     # lowerLim = 100
             if ang > lowerLim and ang < upperLim:
                 # AT THIS MOMENT BUILD HYDROGEN BOND:
                 if dSp2:
                     if aSp2:
                         typ = 22
                     else:
                         typ = 23
                 elif aSp2:
                     typ = 32
                 else:
                     typ = 33
                 # THEY could be already bonded
                 alreadyBonded = 0
                 if hasattr(d, 'hbonds') and hasattr(ac, 'hbonds'):
                     for hb in d.hbonds:
                         if hb.donAt == ac or hb.accAt == ac:
                             alreadyBonded = 1
                 if not alreadyBonded:
                     newHB = HydrogenBond(d, ac, h, theta=ang, typ=typ)
                     if not hasattr(ac, 'hbonds'):
                         ac.hbonds = []
                     if not hasattr(d, 'hbonds'):
                         d.hbonds = []
                     ac.hbonds.append(newHB)
                     d.hbonds.append(newHB)
                     if h is not None:
                         # hydrogens can have only 1 hbond
                         h.hbonds = [newHB]
                     #    newHB.hlen = dist
                     # else:
                     #    newHB.dlen = dist
             else:
                 badAts.append(ac)
             ct = ct + 1
         badAtDict[k] = badAts
     return badAtDict
    def doit(self, ats):
        """ Function to delete all the references to each atom  of a
        AtomSet."""

        # Remove the atoms of the molecule you are deleting from the
        # the AtomSet self.vf.allAtoms
        self.vf.allAtoms = self.vf.allAtoms - ats

        # If the current selection
        atmsInSel = self.vf.selection.findType(Atom)[:]
        atmsInSel.sort()
        ats.sort()
        #  Call the updateGeoms function for all the command having an
        # updateGeom function
        molecules, atomSets = self.vf.getNodesByMolecule(ats)
        done = 0
        
        event = DeleteAtomsEvent(objects=ats)
        self.vf.dispatchEvent(event)
        
        allAtoms = AtomSet([])
        for mol, atSet in map(None, molecules, atomSets):
            if len(atSet)==len(mol.allAtoms):
                #have to add atoms back to allAtoms for deleteMol to work
                self.vf.allAtoms = self.vf.allAtoms + atSet
                self.vf.deleteMol.deleteMol(mol)
                #if this is the last atom, quit the loop
                if mol==molecules[-1]:
                    done=1
                    break
                continue

            mol.allAtoms = mol.allAtoms - atSet
            allAtoms = allAtoms + atSet
            #FIRST remove any possible hbonds
            hbondAts = atSet.get(lambda x: hasattr(x, 'hbonds'))
            if hbondAts is not None:
                #for each atom with hbonds
                for at in hbondAts:
                    if not hasattr(at, 'hbonds'):
                        continue
                    #remove each of its hbonds 
                    for b in at.hbonds:
                        self.removeHBond(b)
            for at in atSet:
                for b in at.bonds:
                    at2 = b.atom1
                    if at2 == at: at2 = b.atom2
                    at2.bonds.remove(b)
                at.parent.remove(at, cleanup=1)

        if len(atmsInSel):
            if atmsInSel == ats:
                # the current selection was deleted 
                self.vf.clearSelection(topCommand=0)
            else:
                nodes = self.vf.selection
                lenSel = len(nodes)
                setClass = nodes.__class__
                elementClass = nodes.elementType
                if lenSel>0:
                    # this breaks if selectionlevel is Molecule, for instance
                    # setClass = nodes.__class__
                    # newSel = setClass(nodes.findType(Atom) - ats)
                    # newSel2 = setClass([])
                    newSel = atmsInSel-ats
                    newSel2 = AtomSet([])
                    # may have ats which have been deleted everywhere else
                    for at in newSel:
                        if at in at.top.allAtoms:
                            newSel2.append(at)
                    if len(newSel2)!=lenSel:
                        self.vf.clearSelection(topCommand=0)
                        if len(newSel2):
                            newSel2 = newSel2.findType(elementClass).uniq()
                            self.vf.select(newSel2, topCommand=0)


        #this fixed a bug which occurred when only 1 molecule present
        #and cmd invoked with mv.deleteAtomSet(mv.Mols[0].allAtoms)
        if not done:
            for at in ats: del at
        self.vf.resetUndo(topCommand=0)
Пример #28
0
    fptr.close()

    #setup the reference molecule
    from MolKit import Read
    from MolKit.molecule import AtomSet
    ref_name, ref_ll = lines[0].split()
    ref_mol = Read(ref_name)[0]
    ref_ats = AtomSet()
    ref_indices = map(int, ref_ll.split(','))
    num_ref_indices = len(ref_indices)
    if num_ref_indices<3: 
        print " At least 3 indices are required! only %d indices found!!!"%(num_ref_indices)
        exit()
    for i in ref_indices:
        #ref_ats.append(ref_mol.allAtoms[i-1])
        ref_ats.append(ref_mol.allAtoms.get(lambda x: x.number==i)[0])

    num_ref_ats = len(ref_ats)

    #setup the tool for the rigid fit
    from mglutil.math.rigidFit import RigidfitBodyAligner
    RFA = RigidfitBodyAligner()
    RFA.setRefCoords(ref_ats.coords)

    #transform the rest of the molecules
    for l in lines[1:]:
        name, ll = l.split() 
        ll.strip()
        moving_mol = Read(name)[0]
        indices = map(int, ll.split(','))
        moving_ats = AtomSet()
    def getDonors(self, nodes, paramDict):
        donorList = paramDict['donorTypes']
        #print 'donorList=', donorList
        # currently this is a set of hydrogens
        hats = AtomSet(nodes.get(lambda x: x.element=='H'))
        #hats are optional: if none, process donors
        # if there are hats: dAts are all atoms bonded to all hydrogens
        if hats:
            dAts = AtomSet([])
            for at in hats:
                for b in at.bonds:
                    at2 = b.atom1
                    if id(at2)==id(at): at2 = b.atom2
                    dAts.append(at2)
                    #dAts.append(b.neighborAtom(at))
        else:
            dAts = nodes
        #get the sp2 hybridized possible donors which are all ns
        sp2 = []
        for t in ['Nam', 'Ng+', 'Npl']:
            if t in donorList:
                sp2.append(t)
        #ntypes = ['Nam', 'Ng+', 'Npl']

        sp2DAts = None
        if len(sp2):
            sp2DAts = AtomSet(dAts.get(lambda x, sp2=sp2: x.babel_type in sp2))

        hsp2 = AtomSet([])
        if sp2DAts:
            if hats:
                hsp2 = AtomSet(hats.get(lambda x, sp2DAts=sp2DAts:x.bonds[0].atom1 \
                        in sp2DAts or x.bonds[0].atom2 in sp2DAts))
        if sp2DAts:
            #remove any sp2 N atoms which already have 3 bonds not to hydrogens
            n2Dons = AtomSet(sp2DAts.get(lambda x: x.element=='N'))
            if n2Dons:
                n2Dons.bl=0
                for at in n2Dons:
                    for b in at.bonds:
                        if type(b.bondOrder)==type(2):
                            at.bl = at.bl + b.bondOrder
                        else:
                            at.bl = at.bl + 2
                        #allow that there might already be a hydrogen
                    nH = at.findHydrogens()
                    at.bl = at.bl - len(nH)
                badAts = AtomSet(n2Dons.get(lambda x: x.bl>2))
                if badAts:
                    sp2DAts = sp2DAts - badAts
                delattr(n2Dons,'bl')
        #get the sp3 hybridized possible donors
        sp3 = []
        for t in ['N3+', 'S3', 'O3']:
            if t in donorList:
                sp3.append(t)
        n3DAts = None
        if 'N3+' in sp3:
            n3DAts = AtomSet(dAts.get(lambda x: x.babel_type=='N3+'))
        o3DAts = None
        if 'O3' in sp3:
            o3DAts = AtomSet(dAts.get(lambda x: x.babel_type=='O3'))
        if o3DAts:
            #remove any O3 atoms which already have 2 bonds not to hydrogens
            badO3s = AtomSet([])
            for at in o3DAts:
                if len(at.bonds)<2: continue
                if len(at.findHydrogens()): continue
                else:
                    badO3s.append(at)
            if len(badO3s):
                o3DAts = o3DAts - badO3s
        s3DAts = None
        if 'S3' in sp3:
            s3DAts = AtomSet(dAts.get(lambda x: x.babel_type=='S3'))
        sp3DAts = AtomSet([])
        for item in [n3DAts, o3DAts, s3DAts]:
            if item:
                sp3DAts = sp3DAts + item
        hsp3 = AtomSet([])
        if sp3DAts:
            if hats:
                hsp3 = AtomSet(hats.get(lambda x, sp3DAts=sp3DAts:x.bonds[0].atom1 \
                    in sp3DAts or x.bonds[0].atom2 in sp3DAts))
        hsp = hsp2 + hsp3
        #print 'hsp=', hsp.name
        #print 'sp2DAts=', sp2DAts.name
        #print 'sp3DAts=', sp3DAts.name
        return hsp, sp2DAts, sp3DAts
 def filterBasedOnAngs(self, pD, d2Ats, d3Ats, a2Ats, a3ats, paramDict):
     badAtDict = {}
     d2max = paramDict['d2max']
     d2min = paramDict['d2min']
     d3max = paramDict['d3max']
     d3min = paramDict['d3min']
     #NEED these parameters
     a2max = paramDict['a2max']
     a2min = paramDict['a2min']
     a3max = paramDict['a3max']
     a3min = paramDict['a3min']
     #NB now pD keys could be hydrogens OR donors
     for k in pD.keys():
         if k.element=='H':
             d = k.bonds[0].atom1
             if id(d)==id(k): d = k.bonds[0].atom2
             #d = k.bonds[0].neighborAtom(k)
             h = k
         else: 
             d = k
             h = None
         badAts = AtomSet([])
         ct = 0
         for ac in pD[k]:
             if h is not None:
                 ang = getAngle(ac, h, d)
             else:
                 acN = ac.bonds[0].atom1
                 if id(acN) == id(ac): acN = ac.bonds[0].atom2
                 #acN = ac.bonds[0].neighborAtom(ac)
                 ang = getAngle(d, ac, acN)
             #print 'ang=', ang
             dSp2 = d in d2Ats
             aSp2 = ac in a2Ats
             #these limits could be adjustable
             if h is not None:
                 if dSp2:
                     upperLim = d2max
                     lowerLim = d2min
                     #upperLim = 170
                     #lowerLim = 130
                 else:
                     upperLim = d3max
                     lowerLim = d3min
                     #upperLim = 180
                     #lowerLim = 120
             else:
                 #if there is no hydrogen use d-ac-acN angles
                 if dSp2:
                     upperLim = a2max
                     lowerLim = a2min
                     #upperLim = 150
                     #lowerLim = 110
                 else:
                     upperLim = a3max
                     lowerLim = a3min
                     #upperLim = 150
                     #lowerLim = 100
             if ang>lowerLim and ang <upperLim:
                 #AT THIS MOMENT BUILD HYDROGEN BOND:
                 if dSp2:
                     if aSp2: typ = 22
                     else: typ = 23
                 elif aSp2: typ = 32
                 else: typ = 33
                 #THEY could be already bonded
                 alreadyBonded = 0
                 if hasattr(d, 'hbonds') and hasattr(ac,'hbonds'):
                     for hb in d.hbonds:
                         if hb.donAt==ac or hb.accAt==ac:
                             alreadyBonded = 1
                 if not alreadyBonded:
                     newHB = HydrogenBond(d, ac, h, theta=ang, typ=typ)
                     if not hasattr(ac, 'hbonds'):
                         ac.hbonds=[]
                     if not hasattr(d, 'hbonds'):
                         d.hbonds=[]
                     ac.hbonds.append(newHB)
                     d.hbonds.append(newHB)
                     if h is not None:
                         #hydrogens can have only 1 hbond
                         h.hbonds = [newHB]
                     #    newHB.hlen = dist
                     #else:
                     #    newHB.dlen = dist
             else:
                 badAts.append(ac)
             ct = ct + 1
         badAtDict[k] = badAts
     return badAtDict
Пример #31
0
class LigandMixin(Subject):
    """ lfo adds capability to a protein/molecule to be used as a ligand 
            in an AutoDock docking

    """
    def setup(self,
              useProteinAromaticList=1,
              aromaticCutOff=7.5,
              maxtors=32,
              autoMergeNPHS=1):
        if self.chains[0].hasBonds == 0:
            self.buildBondsByDistance()
        self.useProteinAromaticList = useProteinAromaticList
        self.aromaticCutOff = aromaticCutOff
        self.maxtors = 32
        self.autoMergeNPHS = autoMergeNPHS
        self.bondClassifier = AutoDockBondClassifier()
        self.torsionTree = None
        self.message = ""
        self.torscount = 0
        self.possible_torscount = 0
        self.TORSDOF = 0
        self.resKeys = list(q.keys())
        self.PdbqWriter = PdbqWriter()
        #should this be here?
        msg = 'initialized ' + self.name + ':\n'
        #detect whether isPeptide
        msg += self.checkIsPeptide()
        #process charges
        msg += self.checkCharges()
        ##process hydrogens
        msg += self.checkHydrogens()
        #process bonds
        #this doesn't report anything???
        newmsg, nphs = self.checkBonds()
        msg += newmsg
        #process aromaticCarbons
        msg += self.checkAromatics()
        return msg, nphs

    def checkIsPeptide(self):
        """
        checkIsPeptide
        """
        #check whether each restype is in std list
        #if so, self is a peptide
        resSet = self.chains.residues
        dict = {}
        for r in resSet:
            dict[r.type] = 0
        for t in list(dict.keys()):
            if t not in self.resKeys:
                self.isPeptide = 0
                return '    -it is not a peptide\n'
        #only get to this point if all
        #residue types were found
        self.isPeptide = 1
        return '    -it is a peptide\n'

    def checkCharges(self):
        """
        checkCharges
        """
        msg = '     -already had charges'
        if hasattr(self, 'checked_charges'):
            return msg
        msg = ""
        needToAdd = 0
        chargedAts = self.allAtoms.get(lambda x: hasattr(x, 'charge'))
        if not chargedAts:
            needToAdd = 1
        elif len(chargedAts) != len(self.allAtoms):
            needToAdd = 1
        elif len([x for x in chargedAts if x.charge == 0]) == len(chargedAts):
            #this checks that each atom doesn't have charge=0
            needToAdd = 1
        #to add Kollman need to:
        #   look up each atom's parent in q to get dict=q[at.parent.type]
        #   find the atom's name in dict to get a charge
        #   set atom._charges['Kollman'] to that charge
        #   there are special problems with his, cys and termini
        #   set allAtoms.chargeSet to 'Kollman'
        if needToAdd:
            if not hasattr(self, 'isPeptide'):
                msg = self.checkIsPeptide()
            if self.isPeptide:
                #self.checked_charges = 'needs Kollman'
                self.addKollman()
                self.checked_charges = 'has Kollman'
                #self.vf.addKollmanCharges(self, topCommand=0, log=0)
                msg = msg + '    -added Kollman charges\n'
            else:
                #self.checked_charges = 'needs gasteiger'
                self.computeGasteiger()
                self.checked_charges = 'has gasteiger'
                #self.vf.computeGasteiger(self, topCommand=0, log=0)
                msg = msg + '    -added gasteiger charges\n'
        else:
            self.checked_charges = 'has charges'
            msg = msg + '   -already had charges\n'
        # adt will have to add charges... AND check them
        #at this point, every atom has a charge and charges are not all 0k
        #have to have unit charges per residue
        #print 'calling checkMolCharges'
        #errCharge, resList = checkMolCharges(self, self.vf)
        #FIX THIS: need to add mechanism to adjust charges
        #gui to let user pick + change
        #or either change on first atom or spread over all
        #self.checked_charges = 1
        #if added charges, msg will say which one
        #if did't add charges, msg will be 'ERROR'
        return msg

    def computeGasteiger(self):
        #to compute Gasteiger need to:
        #   create an AtomHybridization()
        #   call its assignHybridization method on self.allAtoms
        #   create a Gasteiger()
        #   call its compute method on self.allAtoms
        # THEN move gast_charge into _charges with gasteiger key
        #   set allAtoms.chargeSet to 'gasteiger'
        # THEN delattr gast_charge from allAtoms
        allAts = self.allAtoms
        ah = AtomHybridization()
        ah.assignHybridization(allAts)
        Gast = Gasteiger()
        Gast.compute(allAts)
        gastCharges = []
        for c in allAts.gast_charge:
            gastCharges.append(round(c, 3))
        allAts.addCharges('gasteiger', gastCharges)
        del allAts.gast_charge
        allAts.chargeSet = 'gasteiger'

    def addKollman(self):
        #to add Kollman need to:
        #   look up each atom's parent in q to get dict=q[at.parent.type]
        #   find the atom's name in dict to get a charge
        #   set atom._charges['Kollman'] to that charge
        #   there are special problems with his, cys and termini
        #   set allAtoms.chargeSet to 'Kollman'

        for a in self.allAtoms:
            dict = q.get(a.parent.type, {})
            if len(dict):
                a._charges['Kollman'] = dict.get(a.parent.type, 0)
            else:
                a._charges['Kollman'] = 0
            a.chargeSet = 'Kollman'

    def checkHydrogens(self):
        """
        checkHydrogens
        """
        #what if self doesn't have bonds
        if not self.chains[0].hasBonds:
            self.buildBondsByDistance()
        hs = self.allAtoms.get(lambda x: x.element == 'H')
        self.nphs = AtomSet()
        if not hs:
            msg = '    -no polar hydrogens found!\n'
        if hs:
            nphs = hs.get(lambda x: x.bonds[0].atom1.element=='C' or \
                    x.bonds[0].atom2.element=='C')
            if nphs:
                self.nphs = nphs
                msg = '    -found ' + str(len(
                    self.nphs)) + ' nonpolar hydrogens\n'
            else:
                msg = '    -no nonpolar hydrogens\n'
        return msg

    def mergeNPHS(self):
        lenNPHS = len(self.nphs)
        if not lenNPHS:
            return
        nphs = self.nphs
        atLen = len(self.allAtoms)
        self.allAtoms = self.allAtoms - nphs
        #first add charge to nph's heavy atom
        chList = list(nphs[0]._charges.keys())
        if not len(chList):
            print('no charges present')
            return 'XXX'
        #check that all nphs have a certain kind of charge
        for at in nphs:
            chs = list(at._charges.keys())
            for c in chList:
                if c not in chs:
                    chList.remove(c)
        if len(chList):
            for chargeSet in chList:
                for h in nphs:
                    b = h.bonds[0]
                    c = b.atom1
                    if c == h:
                        c = b.atom2
                    c._charges[chargeSet] = c._charges[chargeSet] + h._charges[
                        chargeSet]
        #next delete nphs
        for h in nphs:
            b = h.bonds[0]
            c = b.atom1
            if c == h:
                c = b.atom2
            c.bonds.remove(b)
            h.bonds = BondSet()
            h.parent.remove(h)
            #nb:
            #these don't show up in deleteMol.getFreeMemoryInformation
            del h
        self.nphs = AtomSet()
        return '        and merged them\n', nphs

    def checkBonds(self):
        """
        checkBonds
        """
        msg = ""
        #print self.name, ':'
        nphs = AtomSet()
        if len(self.nphs) and self.autoMergeNPHS:
            newmsg, nphs = self.mergeNPHS()
            msg = msg + newmsg
        bc = self.bondClassifier
        bonds = self.chains.residues.atoms.bonds[0]
        for b in bonds:
            b.activeTors = 0
            b.possibleTors = 0
            b.leaf = 0
        #FIX THIS:
        #if isPeptide, don't get cycles this way
        #if self.isPeptide:
        #cycleSelector = bc['cycles']
        #del bc['cycles']
        results = bc.classify(bonds)
        #if self.isPeptide:
        #bc['cycles'] = cycleSelector
        #results['cycles'] = self.getPeptideBondDict()
        #for k,v in results.items():
        #    print k,' = ', len(v)
        self.rotatable = results['rotatable']
        self.torscount = len(self.rotatable)
        self.possible_torscount = self.torscount
        for b in self.rotatable:
            b.activeTors = 1
            b.possibleTors = 1
        for b in results['leaf']:
            b.leaf = 1
        for b in results['cycle']:
            b.incycle = 1
        hydrogenRotators = results['hydrogenRotators']
        self.hydrogenRotators = hydrogenRotators
        self.TORSDOF = self.torscount - len(hydrogenRotators)
        ptAts = bc.dict['rotatable'].getAtoms(self.rotatable)
        d = {}
        for a in ptAts:
            d[a] = 0
        self.pTatomset = AtomSet(list(d.keys()))
        #print 'len(pTatomset=', len(self.pTatomset)
        self.leafbonds = results['leaf']
        self.pepbackbonds = results['ppbb']
        self.amidebonds = results['amide']
        self.cyclebonds = results['cycle']
        return msg, nphs

    def checkAromatics(self):
        """
        checkAromatics
        """
        #this depends on userPref useProteinAromaticList
        if not len(self.cyclebonds):
            self.aromaticCs = AtomSet()
            return ""
        if self.isPeptide and self.useProteinAromaticList:
            self.aromaticCs = self.getPeptideAromatics()
            return ""
        if self.isPeptide:
            self.getPeptideBondDict()
        else:
            self.getLigandBondDict()
        counter = 0
        while counter < self.cyclecount:
            counter = counter + 1
            blist = self.bondDict[counter]
            for item in blist:
                at = item.atom1
                self._getAdjAtom(item, blist)
                #now each bond has 3 atoms specified for it: its own two and the next1 to atom1
                result = self._getNormal(item)
                item.nrmsize = result[0]
                item.nrms = result[1]
                #next find the other bond w/atom2:
                z2 = list(
                    filter(lambda x, item=item, at2=item.atom2, blist=blist: x
                           != item and x.atom1 == at2 or x.atom2 == at2,
                           blist))
                #finally, return the other atom in this bond
                item.nextbond2 = z2[0]
                if item.nextbond2 == item:
                    item.nextbond2 = z2[1]
                neighbor2 = self._getnxtAtom(item.atom2, item.nextbond2)
                item.next2 = neighbor2
                #next have to check whether the normals are parallel
                #check each pair in each bond, how to keep track??
                #have to get normal at item's atom2: so have to get next2 for this bond:
            #have to loop twice to make sure neighbor has nrms
            for item in blist:
                p = item.nrms
                psize = item.nrmsize
                q = item.nextbond2.nrms
                qsize = item.nextbond2.nrmsize
                #theta is the critical test for planarity:
                #if angle between 2 nrms is 0, atoms are planar
                #NB>test is comparing theta,cos(angle), w/zero
                item.theta = numpy.dot(p, q) / (psize * qsize)
                for p in ['next1', 'next2', 'nextbond', 'nextbond2']:
                    delattr(item, p)
        self.updateAromatics(self.aromaticCutOff)
        msg = '    -found ' + str(len(self.aromaticCs)) + ' aromatic carbons\n'
        return msg

    def updateAromatics(self, cutoff):
        self.aromaticCutOff = cutoff
        #cutoff = self.aromaticCutOff
        cutoffValue = math.cos(cutoff * math.pi / 180.)
        aromaticCs = AtomSet([])
        atD = {}
        #to keep from overwriting names of aromatic carbons at
        #junctions of rings use this klug
        for blist in list(self.bondDict.values()):
            for item in blist:
                item.atom1.setThisTime = 0
                item.atom2.setThisTime = 0
        for blist in list(self.bondDict.values()):
            ct = 0
            for item in blist:
                #these are values for the default 7.5degrees:
                #if theta>=0.997 or theta<=-0.997:
                if item.theta >= cutoffValue or item.theta <= -cutoffValue:
                    item.posAromatic = 1
                    ct = ct + 1
                else:
                    item.posAromatic = 0
            #after checking all the bonds in current cycle, compare #posAromatic w/number
            if ct == len(blist):
                #and change the name and autodock_element here....
                for b in blist:
                    at1 = b.atom1
                    at2 = b.atom2
                    if at1.element == 'C':
                        at1.name = 'A' + at1.name[1:]
                        at1.autodock_element = 'A'
                        atD[at1] = 0
                        at1.setThisTime = 1
                    if at2.element == 'C':
                        at2.name = 'A' + at2.name[1:]
                        at2.autodock_element = 'A'
                        atD[at2] = 0
                        at2.setThisTime = 1
                aromaticCs = AtomSet(list(atD.keys()))
            else:
                #if there were any aromatic carbons which no longer
                #meet the criteria, change them back
                for b in blist:
                    at1 = b.atom1
                    at2 = b.atom2
                    if at1.name[0] == 'A' and not at1.setThisTime:
                        at2.autodock_element = 'C'
                        at1.name = 'C' + at1.name[1:]
                    if at2.name[0] == 'A' and not at2.setThisTime:
                        at2.autodock_element = 'C'
                        at2.name = 'C' + at2.name[1:]
        #remove klug
        for blist in list(self.bondDict.values()):
            for item in blist:
                if hasattr(item.atom1, 'setThisTime'):
                    delattr(item.atom1, 'setThisTime')
                if hasattr(item.atom2, 'setThisTime'):
                    delattr(item.atom2, 'setThisTime')
        for a in aromaticCs:
            a.autodock_element = 'A'
        self.aromaticCs = aromaticCs

    def restoreCarbons(self):
        for a in self.aromaticCs:
            if len(a.name) == 1:
                a.name = 'C'
            else:
                a.name = 'C' + a.name[1:]
        a.autodock_element = 'C'

    def nameAromatics(self):
        for a in self.aromaticCs:
            if len(a.name) == 1:
                a.name = 'A'
            else:
                a.name = 'A' + a.name[1:]
        a.autodock_element = 'A'

    def addAromatic(self, at):
        if at.element != 'C':
            print(at.name, ' is not a carbon')
            return 'ERROR'
        if at in self.aromaticCs:
            print(at.name, ' is already in aromatic set')
            return 'ERROR'
        at.autodock_element = 'A'
        self.aromaticCs.append(at)
        print(at.name, ' added to aromatic set')

    def removeAromatic(self, at):
        if at not in self.aromaticCs:
            print(at.name, ' is not in aromatic set')
            return 'ERROR'
        self.aromaticCs.remove(at)
        at.autodock_element = 'C'
        print(at.name, ' removed from aromatic set')

    def getPeptideAromatics(self):
        atSet = AtomSet()
        allAts = self.allAtoms
        arom_ats = allAts.get(lambda x, l = pep_aromList:\
            x.parent.type+'_'+x.name in l)
        if not arom_ats:
            return AtomSet([])
        for at in arom_ats:
            at.name = 'A' + at.name[1:]
            at.autodock_element = 'A'
        #print 'returning ', len(arom_ats), ' arom_ats'
        return arom_ats

    def getPeptideBondDict(self):
        resSet = self.chains.residues.get(lambda x, \
                    d = list(aromDict.keys()):x.type in d)
        if not resSet:
            return BondSet()
        self.cyclecount = numres = len(resSet)
        #NB: cyclenum is 1 based because 0 means not numbered
        for i in range(numres):
            res = resSet[i]
            ats = res.atoms
            #bondDict keys are 1 based too
            keys = aromDict[res.type]
            bnds = bondDict[i+1] = ats.get(lambda x, \
                                keys=keys:x.name in keys).bonds[0]
            for b in bnds:
                bnds.cyclenum = i + 1
        self.bondDict = bondDict

    def getLigandBondDict(self):
        ats = self.allAtoms
        babel = AtomHybridization()
        babel.assignHybridization(self.allAtoms)
        #typeBonds???
        #typeAtoms(ats)
        rf = RingFinder()
        rf.findRings2(ats, ats.bonds[0])
        ct = 1
        bondDict = {}
        for ring in rf.rings:
            bondDict[ct] = ring['bonds']
            for b in ring['bonds']:
                b.cyclenum = ct
            ct = ct + 1
        self.cyclecount = rf.ringCount
        self.bondDict = bondDict

    def _numberCycle(self, at):
        for b in at.bonds:
            if hasattr(b, 'incycle') and b.cyclenum == 0:
                b.cyclenum = self.cyclecount
                nxtAtom = b.atom1
                if nxtAtom == at:
                    nxtAtom = b.atom2
                self._numberCycle(nxtAtom)

    def _getnxtAtom(self, at, b):
        nxtAtom = b.atom1
        if nxtAtom == at:
            nxtAtom = b.atom2
        return nxtAtom

    def _getAdjAtom(self, b, z):
        #first get the bonds in this cycle
        at = b.atom1
        #next find the other one with at as one of the atoms:
        z2 = list(
            filter(lambda x, b=b, at=at, z=z: x != b and x.atom1 == at or x.
                   atom2 == at,
                   z))
        #finally, return the other atom in this bond
        b.nextbond = z2[0]
        neighbor = self._getnxtAtom(at, z2[0])
        b.next1 = neighbor

    def _getNormal(self, b):
        at1 = b.next1
        at2 = b.atom1
        at3 = b.atom2
        pt1 = at1.coords
        pt2 = at2.coords
        pt3 = at3.coords
        a = numpy.subtract(pt2, pt1)
        b = numpy.subtract(pt3, pt2)
        p = (a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],
             a[0] * b[1] - a[1] * b[0])
        nrmsize = numpy.sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2])
        return (nrmsize, p)

    def setroot(self, atom):
        """
        setroot to 'C11' or 'hsg1:A:ILE2:CA'
        """
        if type(atom) == bytes:
            if find(atom, ':') > -1:
                #have to use full_name list
                #check that it is an atom
                mols = ProteinSet([self])
                nodes = mols.NodesFromName(atom)
                if not nodes:
                    return 'invalid root name'
                if nodes.__class__ != AtomSet:
                    return 'invalid root name: not atom level'
            else:
                nodes = self.allAtoms.get(lambda x, n=atom: x.name == n)
            if not nodes:
                return 'invalid root name'
            if len(nodes) > 1:
                return 'root name must be unique'
            atom = nodes[0]
        #elif type(atom)!=types.InstanceType:
        elif isInstance(atom) is False:
            return atom, ' invalid root atom'
        elif atom.__class__ != Atom:
            return atom, ' can only select an Atom instance as root'
        #fix this rnum0 stuff
        #in case toggling back and forth
        if hasattr(self, 'autoRoot') and hasattr(self.autoRoot, 'rnum0'):
            delattr(self.autoRoot, 'rnum0')
        #if there is an old root, remove rnum0
        if hasattr(self, 'ROOT') and hasattr(self.ROOT, 'rnum0'):
            delattr(self.ROOT, 'rnum0')
        self.ROOT = atom
        self.ROOT.rnum0 = 0
        return self.ROOT

    def autoroot(self):
        """
        autoRoot
        """
        #clear old root
        if hasattr(self, 'ROOT') and hasattr(self.ROOT, 'rnum0'):
            delattr(self.ROOT, 'rnum0')
        if hasattr(self, 'autoRoot'):
            self.ROOT = self.autoRoot
            self.ROOT.rnum0 = 0
            return
        if len(self.chains) > 1:
            return "AutoRoot not implemented for molecules with >1 chain"
        self.bestBranch = len(self.allAtoms)
        bestList = []
        for item in self.allAtoms:
            if not hasattr(item, 'bonds'): continue
            if len(item.bonds) == 1 and item.bonds[0].leaf: continue
            if hasattr(item, 'leaf'): continue
            item.maxbranch = 0
            for b in item.bonds:
                nxtAtom = self._getnxtAtom(item, b)
                if not b.leaf:
                    thistree = self.subTree(item, nxtAtom, self.allAtoms)
                    thisbranch = len(thistree)
                    if thisbranch > item.maxbranch:
                        item.maxbranch = thisbranch
            #bestList holds all current best choices for Root..
            if item.maxbranch < self.bestBranch:
                bestList = []
                bestList.append(item)
                self.bestBranch = item.maxbranch
            if item.maxbranch == self.bestBranch and item not in bestList:
                bestList.append(item)
        if len(bestList) > 1:
            foundCycle = 0
            for at in bestList:
                at.cycleatom = 0
                for b in at.bonds:
                    #4/29: peptides won't have aromatic
                    #but will have incycle
                    #if b.bondOrder=='aromatic':
                    if hasattr(b, 'incycle'):
                        at.cycleatom = 1
                        continue
            for at in bestList:
                if at.cycleatom:
                    self.ROOT = at
                    self.autoRoot = at
                    self.ROOT.rnum0 = 0
                    foundCycle = 1
                    break
            #if bestList had a cycle atom, it's been set to root..if NOT:
            if not foundCycle:
                self.autoRoot = bestList[0]
                self.ROOT = bestList[0]
                self.ROOT.rnum0 = 0
        #no ties for possible root, use bestRoot...
        else:
            self.autoRoot = bestList[0]
            self.ROOT = bestList[0]
            self.ROOT.rnum0 = 0
        return self.ROOT

    def buildTorsionTree(self):
        if not hasattr(self, 'ROOT'):
            print('must set ROOT first!')
            return
        self.torTree = TorTree(self.parser, self.ROOT)

    def turnOnTorsion(self, bnd):
        """
        turnOnTorsion 
        """
        if not bnd in self.rotatable:
            return
        #this is redundant (??)
        if not bnd.possibleTors:
            return
        if not bnd.activeTors:
            self.torscount = self.torscount + 1
            bnd.activeTors = 1
            self.torTree.addTorsion(bnd.atom1.number, bnd.atom2.number)

    def turnOffTorsion(self, bnd):
        """
        turnOffTorsion 
        """
        if not bnd in self.rotatable:
            return
        #this is redundant (??)
        if not bnd.possibleTors:
            return
        if bnd.activeTors:
            self.torscount = self.torscount - 1
            bnd.activeTors = 0
            self.torTree.removeTorsion(bnd.atom1.number, bnd.atom2.number)

    def limitTorsions(self, numTors, type, simpleModel=1):
        """sets number of torsions to specified number by inactivating either those which
move the fewest atoms or those which move the most. if number is > than
current but less than possible, torsions are reactivated
        """

        print('lT: numTors=', numTors, ' type=', type)
        allAts = self.allAtoms
        root = self.ROOT
        torscount = self.torscount
        print('torscount=', torscount, end=' ')
        #NB: torscount is not necessarily the max
        #ie it could have been adjusted already
        at0 = self.allAtoms[0]
        if not hasattr(self, 'torTree') or not hasattr(at0, 'tt_ind'):
            self.torTree = TorTree(self.parser, root)
        torsionMap = self.torTree.torsionMap
        torsionMapNum = len(torsionMap)
        print('len(tm)=', torsionMapNum)
        possibleTors = self.possible_torscount
        if simpleModel:
            self.setTorsions(numTors, type)
            return

        #FIX THIS: what if want to increase active torsions
        if torscount == numTors:
            msg = 'specified number==number present: no adjustment'
            return 'msg'
        elif torscount < numTors:
            if torscount == possibleTors:
                #if torscount==torsionMapNum:
                msg = 'specified number == number possible: no adjustment'
                return msg
            else:
                #in this case turn on as many as possible
                #if numTors>=torsionMapNum:
                if numTors >= possibleTors:
                    #turn on everything
                    delta = possibleTors - torscount
                    #delta = torsionMapNum - torscount
                else:
                    delta = numTors - torscount
                self.turnOnTorsions(delta, type)
        else:
            #torscount>numTors
            #in this case turn them off
            delta = torscount - numTors
            self.turnOffTorsions(delta, type)
        msg = str(delta) + ' torsions changed'
        return msg

    def setTorsions(self, numTors, type):
        #this assumes atoms have tt_ind field
        tNum = len(self.torTree.base_torsionMap)
        msg = ""
        if numTors > tNum:
            msg = 'too many torsions specified! ' + str(
                numTors) + ' reducing to' + str(tNum)
            numTors = tNum
        if type == 'fewest':
            rangeList = list(range(numTors))
        else:
            rangeList = []
            for k in range(1, numTors + 1):
                rangeList.append(-k)
        #turn them all off
        baseTorsionMap = self.torTree.base_torsionMap
        torsionMap = self.torTree.torsionMap
        #turn all active nodes off
        active_nodes = torsionMap[:]
        for node in active_nodes:
            #print 'turning off node ', node.number
            self.torTree.removeTorsion(node.bond[0], node.bond[1])
            b = self.allAtoms.get(
                lambda x, node=node: x.tt_ind in node.bond).bonds[0][0]
            b.activeTors = 0

        #turn on the right number at correct end
        for i in rangeList:
            node = baseTorsionMap[i]
            #print '2:turning on node ', node.number
            self.torTree.addTorsion(node.bond[0], node.bond[1])
            b = self.allAtoms.get(
                lambda x, node=node: x.tt_ind in node.bond).bonds[0][0]
            b.activeTors = 1
            #print 'now len(torsionMap)=', len(torsionMap)
        self.torscount = numTors
        return msg

    def turnOnTorsions(self, delta, type='fewest'):
        allAts = self.allAtoms
        torsionMap = self.torTree.torsionMap
        baseTorsionMap = self.torTree.base_torsionMap
        torscount = self.torscount
        #turn on delta torsions + adjust torscount in dict
        if type == 'fewest':
            rangeList = list(range(delta))
        else:
            rangeList = []
            for k in range(1, delta + 1):
                rangeList.append(-k)
        #FIX THIS: probably doesn't work
        for i in rangeList:
            node = baseTorsionMap[i]
            b = allAts.get(
                lambda x, node=node: x.tt_ind in node.bond).bonds[0][0]
            if not b.activeTors:
                self.torTree.addTorsion(node.bond[0], node.bond[1])
                b.activeTors = 1
            else:
                lastInd = rangeList[-1]
                if type == 'fewest':
                    rangeList.append(lastInd + 1)
                else:
                    rangeList.append(lastInd - 1)
        #torscount should be torscount + delta here
        self.torscount = torscount + delta

    def turnOffTorsions(self, delta, type='fewest'):
        allAts = self.allAtoms
        torsionMap = self.torTree.torsionMap
        baseTorsionMap = self.torTree.base_torsionMap
        torscount = self.torscount
        #turn on delta torsions + adjust torscount in dict
        if type == 'fewest':
            rangeList = list(range(delta))
        else:
            rangeList = []
            for k in range(1, delta + 1):
                rangeList.append(-k)
        for i in rangeList:
            node = baseTorsionMap[i]
            if node.bond == (None, None):
                print('error in turnOff torsions with ', rangeList)
                break
            b = allAts.get(
                lambda x, node=node: x.tt_ind in node.bond).bonds[0][0]
            if b.activeTors:
                self.torTree.removeTorsion(node.bond[0], node.bond[1])
                b.activeTors = 0
            else:
                lastInd = rangeList[-1]
                if type == 'fewest':
                    rangeList.append(lastInd + 1)
                else:
                    rangeList.append(lastInd - 1)
        self.torscount = torscount - delta

    def setCarbonName(self, at):
        """
        setCarbonName 
        """
        if not at.element == 'C':
            return
        if len(at.name) == 1:
            at.name = 'C'
        else:
            at.name = 'C' + at.name[1:]

    def setAromaticName(self, at):
        """
        setAromaticName 
        """
        if not at.element == 'C':
            return
        if len(at.name) == 1:
            at.name = 'A'
        else:
            at.name = 'A' + at.name[1:]
def getBondedAtoms(atom):
    l = AtomSet()
    for b in atom.bonds:
        l.append(b.neighborAtom(atom))
    return l
Пример #33
0
    def doit(self, ats):
        """ Function to delete all the references to each atom  of a
        AtomSet."""

        # Remove the atoms of the molecule you are deleting from the
        # the AtomSet self.vf.allAtoms
        self.vf.allAtoms = self.vf.allAtoms - ats

        # If the current selection
        atmsInSel = self.vf.selection.findType(Atom)[:]
        atmsInSel.sort()
        ats.sort()
        #  Call the updateGeoms function for all the command having an
        # updateGeom function
        molecules, atomSets = self.vf.getNodesByMolecule(ats)
        done = 0

        event = DeleteAtomsEvent(objects=ats)
        self.vf.dispatchEvent(event)

        allAtoms = AtomSet([])
        for mol, atSet in map(None, molecules, atomSets):
            if len(atSet) == len(mol.allAtoms):
                #have to add atoms back to allAtoms for deleteMol to work
                self.vf.allAtoms = self.vf.allAtoms + atSet
                self.vf.deleteMol.deleteMol(mol)
                #if this is the last atom, quit the loop
                if mol == molecules[-1]:
                    done = 1
                    break
                continue

            mol.allAtoms = mol.allAtoms - atSet
            allAtoms = allAtoms + atSet
            #FIRST remove any possible hbonds
            hbondAts = atSet.get(lambda x: hasattr(x, 'hbonds'))
            if hbondAts is not None:
                #for each atom with hbonds
                for at in hbondAts:
                    if not hasattr(at, 'hbonds'):
                        continue
                    #remove each of its hbonds
                    for b in at.hbonds:
                        self.removeHBond(b)
            atSetCopy = atSet.copy()  #fixed bug#:       1143
            for at in atSetCopy:
                for b in at.bonds:
                    at2 = b.atom1
                    if at2 == at: at2 = b.atom2
                    at2.bonds.remove(b)
                if at.parent.children:
                    at.parent.remove(at, cleanup=1)

        if len(atmsInSel):
            if atmsInSel == ats:
                # the current selection was deleted
                self.vf.clearSelection(topCommand=0, createEvents=False)
            else:
                nodes = self.vf.selection
                lenSel = len(nodes)
                setClass = nodes.__class__
                elementClass = nodes.elementType
                if lenSel > 0:
                    # this breaks if selectionlevel is Molecule, for instance
                    # setClass = nodes.__class__
                    # newSel = setClass(nodes.findType(Atom) - ats)
                    # newSel2 = setClass([])
                    newSel = atmsInSel - ats
                    newSel2 = AtomSet([])
                    # may have ats which have been deleted everywhere else
                    for at in newSel:
                        if at in at.top.allAtoms:
                            newSel2.append(at)
                    if len(newSel2) != lenSel:
                        self.vf.clearSelection(topCommand=0)
                        if len(newSel2):
                            newSel2 = newSel2.findType(elementClass).uniq()
                            self.vf.select(newSel2, topCommand=0)

        # this fixes an exception that occured when the last chain was split
        # out of a ptrotein
        if not done:
            event = AfterDeleteAtomsEvent(objects=ats)
            self.vf.dispatchEvent(event)

        #this fixed a bug which occured when only 1 molecule present
        #and cmd invoked with mv.deleteAtomSet(mv.Mols[0].allAtoms)
        if not done:
            for at in ats:
                del at
        self.vf.resetUndo(topCommand=0)
def getBondedAtoms(atom):
    l = AtomSet()
    for b in atom.bonds:
        l.append(b.neighborAtom(atom))
    return l
Пример #35
0
class LigandMixin(Subject):
    """ lfo adds capability to a protein/molecule to be used as a ligand 
            in an AutoDock docking

    """


    def setup(self, useProteinAromaticList=1,
                    aromaticCutOff=7.5, maxtors=32,
                    autoMergeNPHS=1):
        if self.chains[0].hasBonds==0:
            self.buildBondsByDistance()
        self.useProteinAromaticList = useProteinAromaticList
        self.aromaticCutOff = aromaticCutOff
        self.maxtors = 32
        self.autoMergeNPHS = autoMergeNPHS
        self.bondClassifier = AutoDockBondClassifier()
        self.torsionTree = None
        self.message = ""
        self.torscount = 0
        self.possible_torscount = 0
        self.TORSDOF = 0
        self.resKeys = q.keys()
        self.PdbqWriter = PdbqWriter()
        #should this be here?
        msg = 'initialized ' + self.name +':\n'
        #detect whether isPeptide
        msg += self.checkIsPeptide()
        #process charges
        msg += self.checkCharges()
        ##process hydrogens
        msg += self.checkHydrogens()
        #process bonds
        #this doesn't report anything???
        newmsg, nphs = self.checkBonds()
        msg += newmsg
        #process aromaticCarbons
        msg += self.checkAromatics()
        return msg, nphs


    def checkIsPeptide(self):
        """
        checkIsPeptide
        """
        #check whether each restype is in std list
        #if so, self is a peptide
        resSet = self.chains.residues
        dict = {}
        for r in resSet:
            dict[r.type] = 0
        for t in dict.keys():
            if t not in self.resKeys:
                self.isPeptide = 0
                return '    -it is not a peptide\n'
        #only get to this point if all
        #residue types were found
        self.isPeptide = 1
        return '    -it is a peptide\n'


    def checkCharges(self):
        """
        checkCharges
        """
        msg = '     -already had charges'
        if hasattr(self, 'checked_charges'):
            return msg
        msg = ""
        needToAdd = 0
        chargedAts = self.allAtoms.get(lambda x: hasattr(x, 'charge'))
        if not chargedAts:
            needToAdd = 1
        elif len(chargedAts)!=len(self.allAtoms):
            needToAdd = 1
        elif len(filter(lambda x:x.charge==0, chargedAts))==len(chargedAts):
            #this checks that each atom doesn't have charge=0
            needToAdd = 1
        #to add Kollman need to:
        #   look up each atom's parent in q to get dict=q[at.parent.type]
        #   find the atom's name in dict to get a charge
        #   set atom._charges['Kollman'] to that charge
        #   there are special problems with his, cys and termini
        #   set allAtoms.chargeSet to 'Kollman'
        if needToAdd:     
            if not hasattr(self, 'isPeptide'):
                msg = self.checkIsPeptide()
            if self.isPeptide:
                #self.checked_charges = 'needs Kollman'
                self.addKollman()
                self.checked_charges = 'has Kollman'
                #self.vf.addKollmanCharges(self, topCommand=0, log=0)
                msg = msg + '    -added Kollman charges\n'
            else:
                #self.checked_charges = 'needs gasteiger'
                self.computeGasteiger()
                self.checked_charges = 'has gasteiger'
                #self.vf.computeGasteiger(self, topCommand=0, log=0)
                msg = msg + '    -added gasteiger charges\n'
        else:
            self.checked_charges = 'has charges'
            msg = msg + '   -already had charges\n'
        # adt will have to add charges... AND check them
        #at this point, every atom has a charge and charges are not all 0k
        #have to have unit charges per residue
        #print 'calling checkMolCharges'
        #errCharge, resList = checkMolCharges(self, self.vf)
        #FIX THIS: need to add mechanism to adjust charges
        #gui to let user pick + change
        #or either change on first atom or spread over all
        #self.checked_charges = 1
        #if added charges, msg will say which one
        #if did't add charges, msg will be 'ERROR'
        return msg


    def computeGasteiger(self):
        #to compute Gasteiger need to:
        #   create an AtomHybridization()
        #   call its assignHybridization method on self.allAtoms
        #   create a Gasteiger()
        #   call its compute method on self.allAtoms
        # THEN move gast_charge into _charges with gasteiger key
        #   set allAtoms.chargeSet to 'gasteiger'
        # THEN delattr gast_charge from allAtoms
        allAts = self.allAtoms
        ah = AtomHybridization()
        ah.assignHybridization(allAts)
        Gast = Gasteiger()
        Gast.compute(allAts)
        gastCharges = []
        for c in allAts.gast_charge:
            gastCharges.append(round(c, 3))
        allAts.addCharges('gasteiger', gastCharges)
        del allAts.gast_charge
        allAts.chargeSet = 'gasteiger'


    def addKollman(self):
        #to add Kollman need to:
        #   look up each atom's parent in q to get dict=q[at.parent.type]
        #   find the atom's name in dict to get a charge
        #   set atom._charges['Kollman'] to that charge
        #   there are special problems with his, cys and termini
        #   set allAtoms.chargeSet to 'Kollman'

        for a in self.allAtoms:
            dict = q.get(a.parent.type, {})
            if len(dict):
                a._charges['Kollman'] = dict.get(a.parent.type, 0)
            else:
                a._charges['Kollman'] = 0
            a.chargeSet = 'Kollman'


    def checkHydrogens(self):
        """
        checkHydrogens
        """
        #what if self doesn't have bonds
        if not self.chains[0].hasBonds:
            self.buildBondsByDistance()
        hs = self.allAtoms.get(lambda x: x.element=='H')
        self.nphs = AtomSet()
        if not hs:
            msg = '    -no polar hydrogens found!\n'
        if hs:
            nphs = hs.get(lambda x: x.bonds[0].atom1.element=='C' or \
                    x.bonds[0].atom2.element=='C')
            if nphs:
                self.nphs = nphs
                msg = '    -found ' + str(len(self.nphs)) + ' nonpolar hydrogens\n'
            else:
                msg = '    -no nonpolar hydrogens\n'
        return msg


    def mergeNPHS(self):
        lenNPHS = len(self.nphs)
        if not lenNPHS:
            return
        nphs = self.nphs
        atLen = len(self.allAtoms)
        self.allAtoms = self.allAtoms - nphs
        #first add charge to nph's heavy atom
        chList = nphs[0]._charges.keys()
        if not len(chList):
            print 'no charges present'
            return 'XXX'
        #check that all nphs have a certain kind of charge
        for at in nphs:
            chs = at._charges.keys()
            for c in chList:
                if c not in chs:
                    chList.remove(c)
        if len(chList):
            for chargeSet in chList:
                for h in nphs:
                    b = h.bonds[0]
                    c = b.atom1
                    if c==h: 
                        c = b.atom2
                    c._charges[chargeSet] = c._charges[chargeSet] + h._charges[chargeSet]
        #next delete nphs
        for h in nphs:
            b = h.bonds[0]
            c = b.atom1
            if c==h: 
                c = b.atom2
            c.bonds.remove(b)
            h.bonds = BondSet()
            h.parent.remove(h)
            #nb: 
            #these don't show up in deleteMol.getFreeMemoryInformation
            del h
        self.nphs = AtomSet()
        return '        and merged them\n', nphs


    def checkBonds(self):
        """
        checkBonds
        """
        msg = ""
        #print self.name, ':'
        nphs = AtomSet()
        if len(self.nphs) and self.autoMergeNPHS:
            newmsg, nphs = self.mergeNPHS()
            msg = msg + newmsg
        bc = self.bondClassifier
        bonds = self.chains.residues.atoms.bonds[0]
        for b in bonds:
            b.activeTors = 0
            b.possibleTors = 0
            b.leaf = 0
        #FIX THIS:
        #if isPeptide, don't get cycles this way
        #if self.isPeptide:
            #cycleSelector = bc['cycles']
            #del bc['cycles']
        results = bc.classify(bonds)
        #if self.isPeptide:
            #bc['cycles'] = cycleSelector
            #results['cycles'] = self.getPeptideBondDict()
        #for k,v in results.items():
        #    print k,' = ', len(v)
        self.rotatable = results['rotatable']
        self.torscount = len(self.rotatable) 
        self.possible_torscount = self.torscount
        for b in self.rotatable:
            b.activeTors = 1
            b.possibleTors = 1
        for b in results['leaf']:
            b.leaf = 1
        for b in results['cycle']:
            b.incycle = 1
        hydrogenRotators = results['hydrogenRotators']
        self.hydrogenRotators = hydrogenRotators 
        self.TORSDOF = self.torscount - len(hydrogenRotators)
        ptAts = bc.dict['rotatable'].getAtoms(self.rotatable)
        d = {}
        for a in ptAts:
            d[a] = 0
        self.pTatomset = AtomSet(d.keys())
        #print 'len(pTatomset=', len(self.pTatomset)
        self.leafbonds = results['leaf']
        self.pepbackbonds = results['ppbb']
        self.amidebonds = results['amide']
        self.cyclebonds = results['cycle']
        return msg, nphs


    def checkAromatics(self):
        """
        checkAromatics
        """
        #this depends on userPref useProteinAromaticList
        if not len(self.cyclebonds):
            self.aromaticCs = AtomSet()
            return ""
        if self.isPeptide and self.useProteinAromaticList:
            self.aromaticCs = self.getPeptideAromatics()
            return ""
        if self.isPeptide:
            self.getPeptideBondDict()
        else:
            self.getLigandBondDict()
        counter = 0
        while counter < self.cyclecount:
            counter = counter + 1
            blist = self.bondDict[counter]
            for item in blist:
                at = item.atom1
                self._getAdjAtom(item, blist)
                #now each bond has 3 atoms specified for it: its own two and the next1 to atom1
                result = self._getNormal(item)
                item.nrmsize = result[0]
                item.nrms = result[1]
                #next find the other bond w/atom2:
                z2 = filter(lambda x,item=item, at2=item.atom2, blist=blist:x!=item and x.atom1==at2 or x.atom2==at2, blist)
                #finally, return the other atom in this bond
                item.nextbond2 = z2[0]
                if item.nextbond2==item:
                    item.nextbond2 = z2[1]
                neighbor2 = self._getnxtAtom(item.atom2,item.nextbond2)
                item.next2 = neighbor2
                #next have to check whether the normals are parallel
                #check each pair in each bond, how to keep track??
                #have to get normal at item's atom2: so have to get next2 for this bond:
            #have to loop twice to make sure neighbor has nrms
            for item in blist:
                p = item.nrms
                psize = item.nrmsize
                q = item.nextbond2.nrms
                qsize = item.nextbond2.nrmsize
                #theta is the critical test for planarity:
                #if angle between 2 nrms is 0, atoms are planar
                #NB>test is comparing theta,cos(angle), w/zero
                item.theta = Numeric.dot(p,q)/(psize*qsize)
                for p in ['next1','next2','nextbond','nextbond2']:
                    delattr(item, p)
        self.updateAromatics(self.aromaticCutOff)
        msg = '    -found '+ str(len(self.aromaticCs)) + ' aromatic carbons\n'
        return  msg


    def updateAromatics(self, cutoff):
        self.aromaticCutOff = cutoff
        #cutoff = self.aromaticCutOff
        cutoffValue = math.cos(cutoff*math.pi/180.)
        aromaticCs = AtomSet([])
        atD = {}
        #to keep from overwriting names of aromatic carbons at 
        #junctions of rings use this klug
        for blist in self.bondDict.values():
            for item in blist:
                item.atom1.setThisTime = 0
                item.atom2.setThisTime = 0
        for blist in self.bondDict.values():
            ct = 0
            for item in blist:
                #these are values for the default 7.5degrees:
                #if theta>=0.997 or theta<=-0.997:
                if item.theta>=cutoffValue or item.theta<=-cutoffValue:
                    item.posAromatic = 1
                    ct = ct + 1
                else:
                    item.posAromatic = 0
            #after checking all the bonds in current cycle, compare #posAromatic w/number
            if ct==len(blist):
                #and change the name and autodock_element here....
                for b in blist:
                    at1 = b.atom1
                    at2 = b.atom2
                    if at1.element=='C':
                        at1.name = 'A' + at1.name[1:]
                        at1.autodock_element = 'A'
                        atD[at1] = 0
                        at1.setThisTime = 1
                    if at2.element=='C':
                        at2.name = 'A' + at2.name[1:]
                        at2.autodock_element = 'A'
                        atD[at2] = 0
                        at2.setThisTime = 1
                aromaticCs = AtomSet(atD.keys())
            else:
                #if there were any aromatic carbons which no longer 
                #meet the criteria, change them back
                for b in blist:
                    at1 = b.atom1
                    at2 = b.atom2
                    if at1.name[0]=='A' and not at1.setThisTime:
                        at2.autodock_element = 'C'
                        at1.name = 'C' + at1.name[1:]
                    if at2.name[0]=='A'and not at2.setThisTime:
                        at2.autodock_element = 'C'
                        at2.name = 'C' + at2.name[1:]
        #remove klug
        for blist in self.bondDict.values():
            for item in blist:
                if hasattr(item.atom1, 'setThisTime'):
                    delattr(item.atom1,'setThisTime')
                if hasattr(item.atom2, 'setThisTime'):
                    delattr(item.atom2,'setThisTime')
        for a in aromaticCs:
            a.autodock_element = 'A'
        self.aromaticCs = aromaticCs

            
    def restoreCarbons(self):
        for a in self.aromaticCs:
            if len(a.name)==1:
                a.name = 'C'
            else:
                a.name = 'C' + a.name[1:]
        a.autodock_element = 'C'

   
    def nameAromatics(self):
        for a in self.aromaticCs:
            if len(a.name)==1:
                a.name = 'A'
            else:
                a.name = 'A' + a.name[1:]
        a.autodock_element = 'A'


    def addAromatic(self, at):
        if at.element!='C':
            print at.name, ' is not a carbon'
            return 'ERROR'
        if at in self.aromaticCs:
            print at.name, ' is already in aromatic set'
            return 'ERROR'
        at.autodock_element = 'A'
        self.aromaticCs.append(at)
        print at.name, ' added to aromatic set'
   

    def removeAromatic(self, at):
        if at not in self.aromaticCs:
            print at.name, ' is not in aromatic set'
            return 'ERROR'
        self.aromaticCs.remove(at)
        at.autodock_element = 'C'
        print at.name, ' removed from aromatic set'
   

    def getPeptideAromatics(self):
        atSet = AtomSet()
        allAts = self.allAtoms
        arom_ats = allAts.get(lambda x, l = pep_aromList:\
            x.parent.type+'_'+x.name in l)
        if not arom_ats:
            return AtomSet([])
        for at in arom_ats:
            at.name = 'A' + at.name[1:]
            at.autodock_element = 'A'
        #print 'returning ', len(arom_ats), ' arom_ats'
        return arom_ats

       
    def getPeptideBondDict(self):
        resSet = self.chains.residues.get(lambda x, \
                    d = aromDict.keys():x.type in d)
        if not resSet:
            return BondSet()
        self.cyclecount = numres = len(resSet)
        #NB: cyclenum is 1 based because 0 means not numbered
        for i in range(numres):
            res = resSet[i]
            ats = res.atoms
            #bondDict keys are 1 based too
            keys = aromDict[res.type]
            bnds = bondDict[i+1] = ats.get(lambda x, \
                                keys=keys:x.name in keys).bonds[0]
            for b in bnds:
                bnds.cyclenum = i + 1
        self.bondDict = bondDict


    def getLigandBondDict(self):
        ats = self.allAtoms
        babel = AtomHybridization()
        babel.assignHybridization(self.allAtoms)
        #typeBonds???
        #typeAtoms(ats)
        rf = RingFinder()
        rf.findRings2(ats, ats.bonds[0])
        ct = 1
        bondDict = {}
        for ring in rf.rings:
            bondDict[ct] = ring['bonds']
            for b in ring['bonds']:
                b.cyclenum = ct
            ct = ct + 1
        self.cyclecount = rf.ringCount
        self.bondDict = bondDict

 
    def _numberCycle(self, at):
        for b in at.bonds:
            if hasattr(b,'incycle') and b.cyclenum==0 :
                b.cyclenum = self.cyclecount
                nxtAtom = b.atom1
                if nxtAtom==at:
                    nxtAtom = b.atom2
                self._numberCycle(nxtAtom)


    def _getnxtAtom(self, at,b):
        nxtAtom = b.atom1
        if nxtAtom==at:
            nxtAtom = b.atom2
        return nxtAtom


    def _getAdjAtom(self,b,z):
        #first get the bonds in this cycle
        at = b.atom1
        #next find the other one with at as one of the atoms:
        z2 = filter(lambda x,b=b,at=at,z=z:x!=b and x.atom1==at or x.atom2==at, z)
        #finally, return the other atom in this bond
        b.nextbond = z2[0]
        neighbor = self._getnxtAtom(at,z2[0])
        b.next1 = neighbor


    def _getNormal(self,b):
        at1 = b.next1
        at2 = b.atom1
        at3 = b.atom2
        pt1 = at1.coords
        pt2 = at2.coords
        pt3 = at3.coords
        a = Numeric.subtract(pt2,pt1)
        b = Numeric.subtract(pt3,pt2)
        p = (a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0])
        nrmsize = Numeric.sqrt(p[0]*p[0]+p[1]*p[1]+p[2]*p[2])
        return (nrmsize, p)


    def setroot(self, atom):
        """
        setroot to 'C11' or 'hsg1:A:ILE2:CA'
        """
        if type(atom)==types.StringType:
            if find(atom, ':')>-1:
                #have to use full_name list
                #check that it is an atom
                mols = ProteinSet([self])
                nodes = mols.NodesFromName(atom)
                if not nodes:
                    return 'invalid root name'
                if nodes.__class__!=AtomSet:
                    return 'invalid root name: not atom level'
            else:
                nodes = self.allAtoms.get(lambda x, n = atom:x.name==n)
            if not nodes:
                return 'invalid root name'
            if len(nodes)>1:
                return 'root name must be unique'
            atom = nodes[0]
        elif type(atom)!=types.InstanceType:
            return atom, ' invalid root atom'
        elif atom.__class__!=Atom:
            return atom, ' can only select an Atom instance as root'
        #fix this rnum0 stuff
        #in case toggling back and forth
        if hasattr(self, 'autoRoot') and hasattr(self.autoRoot, 'rnum0'):
            delattr(self.autoRoot, 'rnum0')
        #if there is an old root, remove rnum0
        if hasattr(self, 'ROOT') and hasattr(self.ROOT, 'rnum0'):
            delattr(self.ROOT, 'rnum0')
        self.ROOT = atom
        self.ROOT.rnum0 = 0
        return self.ROOT


    def autoroot(self):
        """
        autoRoot
        """
        #clear old root
        if hasattr(self, 'ROOT') and hasattr(self.ROOT, 'rnum0'):
            delattr(self.ROOT, 'rnum0')
        if hasattr(self, 'autoRoot'):
            self.ROOT = self.autoRoot
            self.ROOT.rnum0 = 0
            return
        if len(self.chains)>1:
            return  "AutoRoot not implemented for molecules with >1 chain"
        self.bestBranch = len(self.allAtoms)
        bestList = []
        for item in self.allAtoms:
            if not hasattr(item, 'bonds'): continue
            if len(item.bonds)==1 and item.bonds[0].leaf: continue
            if hasattr(item,'leaf'): continue
            item.maxbranch = 0
            for b in item.bonds:
                nxtAtom = self._getnxtAtom(item,b)
                if not b.leaf:
                    thistree = self.subTree(item,nxtAtom, self.allAtoms)
                    thisbranch = len(thistree)
                    if thisbranch>item.maxbranch:
                        item.maxbranch = thisbranch
            #bestList holds all current best choices for Root..
            if item.maxbranch<self.bestBranch:
                bestList = []
                bestList.append(item)
                self.bestBranch = item.maxbranch
            if item.maxbranch==self.bestBranch and item not in bestList:
                bestList.append(item)
        if len(bestList)>1:
            foundCycle = 0
            for at in bestList:
                at.cycleatom = 0
                for b in at.bonds:
                    #4/29: peptides won't have aromatic 
                    #but will have incycle
                    #if b.bondOrder=='aromatic':
                    if hasattr(b,'incycle'):
                        at.cycleatom = 1
                        continue
            for at in bestList:
                if at.cycleatom:
                    self.ROOT = at
                    self.autoRoot = at
                    self.ROOT.rnum0 =0
                    foundCycle = 1
                    break
            #if bestList had a cycle atom, it's been set to root..if NOT:
            if not foundCycle:
                self.autoRoot = bestList[0]
                self.ROOT = bestList[0]
                self.ROOT.rnum0 =0
        #no ties for possible root, use bestRoot...
        else:
            self.autoRoot = bestList[0]
            self.ROOT = bestList[0]
            self.ROOT.rnum0 =0
        return self.ROOT


    def buildTorsionTree(self):
        if not hasattr(self, 'ROOT'):
            print 'must set ROOT first!'
            return
        self.torTree = TorTree(self.parser, self.ROOT)


    def turnOnTorsion(self, bnd):
        """
        turnOnTorsion 
        """
        if not bnd in self.rotatable:
            return
        #this is redundant (??)
        if not bnd.possibleTors:
            return
        if not bnd.activeTors:
            self.torscount = self.torscount + 1
            bnd.activeTors = 1
            self.torTree.addTorsion(bnd.atom1.number, bnd.atom2.number)


    def turnOffTorsion(self, bnd):
        """
        turnOffTorsion 
        """
        if not bnd in self.rotatable:
            return
        #this is redundant (??)
        if not bnd.possibleTors:
            return
        if bnd.activeTors:
            self.torscount = self.torscount - 1
            bnd.activeTors = 0
            self.torTree.removeTorsion(bnd.atom1.number, bnd.atom2.number)


    def limitTorsions(self, numTors, type, simpleModel=1):
        """sets number of torsions to specified number by inactivating either those which
move the fewest atoms or those which move the most. if number is > than
current but less than possible, torsions are reactivated
        """

        print 'lT: numTors=', numTors, ' type=', type
        allAts = self.allAtoms
        root = self.ROOT
        torscount = self.torscount
        print 'torscount=', torscount, 
        #NB: torscount is not necessarily the max
        #ie it could have been adjusted already
        at0 = self.allAtoms[0]
        if not hasattr(self, 'torTree') or not hasattr(at0, 'tt_ind'):
            self.torTree = TorTree(self.parser, root)
        torsionMap = self.torTree.torsionMap
        torsionMapNum = len(torsionMap)
        print 'len(tm)=', torsionMapNum
        possibleTors = self.possible_torscount
        if simpleModel:
            self.setTorsions(numTors, type)
            return 

        #FIX THIS: what if want to increase active torsions
        if torscount==numTors:
            msg = 'specified number==number present: no adjustment'
            return 'msg'
        elif torscount<numTors:
            if torscount==possibleTors:
                #if torscount==torsionMapNum:
                msg = 'specified number == number possible: no adjustment'
                return msg
            else:
                #in this case turn on as many as possible
                #if numTors>=torsionMapNum:
                if numTors>=possibleTors:
                    #turn on everything
                    delta = possibleTors - torscount
                    #delta = torsionMapNum - torscount
                else:
                    delta = numTors - torscount
                self.turnOnTorsions(delta, type)
        else:
            #torscount>numTors
            #in this case turn them off 
            delta = torscount - numTors
            self.turnOffTorsions(delta, type)
        msg = str(delta) + ' torsions changed'
        return msg


    def setTorsions(self, numTors, type):
        #this assumes atoms have tt_ind field
        tNum = len(self.torTree.base_torsionMap)
        msg = ""
        if numTors>tNum:
            msg = 'too many torsions specified! '+ str(numTors)+  ' reducing to'+str(tNum)
            numTors = tNum
        if type=='fewest':
            rangeList = range(numTors)
        else:
            rangeList = []
            for k in range(1, numTors+1):
                rangeList.append(-k)
        #turn them all off
        baseTorsionMap = self.torTree.base_torsionMap
        torsionMap = self.torTree.torsionMap
        #turn all active nodes off
        active_nodes = torsionMap[:]
        for node in active_nodes:
            #print 'turning off node ', node.number
            self.torTree.removeTorsion(node.bond[0], node.bond[1])
            b = self.allAtoms.get(lambda x, node=node: x.tt_ind in node.bond).bonds[0][0]
            b.activeTors = 0

        #turn on the right number at correct end
        for i in rangeList:
            node = baseTorsionMap[i]
            #print '2:turning on node ', node.number
            self.torTree.addTorsion(node.bond[0], node.bond[1])
            b = self.allAtoms.get(lambda x, node=node: x.tt_ind in node.bond).bonds[0][0]
            b.activeTors = 1
            #print 'now len(torsionMap)=', len(torsionMap)
        self.torscount = numTors
        return msg


    def turnOnTorsions(self, delta, type = 'fewest'):
        allAts = self.allAtoms
        torsionMap = self.torTree.torsionMap
        baseTorsionMap = self.torTree.base_torsionMap
        torscount = self.torscount
        #turn on delta torsions + adjust torscount in dict 
        if type=='fewest':
            rangeList = range(delta)
        else:
            rangeList = []
            for k in range(1, delta+1):
                rangeList.append(-k)
        #FIX THIS: probably doesn't work
        for i in rangeList:
            node = baseTorsionMap[i]
            b = allAts.get(lambda x, node=node: x.tt_ind in node.bond).bonds[0][0]
            if not b.activeTors:
                self.torTree.addTorsion(node.bond[0], node.bond[1])
                b.activeTors = 1
            else:
                lastInd = rangeList[-1]
                if type=='fewest':
                    rangeList.append(lastInd+1)
                else:
                    rangeList.append(lastInd-1)
        #torscount should be torscount + delta here
        self.torscount = torscount + delta

        
    def turnOffTorsions(self, delta, type = 'fewest'):
        allAts = self.allAtoms
        torsionMap = self.torTree.torsionMap
        baseTorsionMap = self.torTree.base_torsionMap
        torscount = self.torscount
        #turn on delta torsions + adjust torscount in dict 
        if type=='fewest':
            rangeList = range(delta)
        else:
            rangeList = []
            for k in range(1, delta+1):
                rangeList.append(-k)
        for i in rangeList:
            node = baseTorsionMap[i]
            if node.bond==(None,None):
                print 'error in turnOff torsions with ', rangeList
                break
            b = allAts.get(lambda x, node=node: x.tt_ind in node.bond).bonds[0][0]
            if b.activeTors:
                self.torTree.removeTorsion(node.bond[0], node.bond[1])
                b.activeTors = 0
            else:
                lastInd = rangeList[-1]
                if type=='fewest':
                    rangeList.append(lastInd+1)
                else:
                    rangeList.append(lastInd-1)
        self.torscount = torscount - delta


    def setCarbonName(self, at):
        """
        setCarbonName 
        """
        if not at.element=='C':
            return
        if len(at.name)==1:
            at.name = 'C'
        else:
            at.name = 'C' + at.name[1:]



    def setAromaticName(self, at):
        """
        setAromaticName 
        """
        if not at.element=='C':
            return
        if len(at.name)==1:
            at.name = 'A'
        else:
            at.name = 'A' + at.name[1:]
    def addHydrogens(self, mol):
        #check for bonds
        if len(mol.allAtoms.bonds[0])==0:
            mol.buildBondsByDistance()
        bonds = mol.allAtoms.bonds[0]
        #could have preset babel_types
        #so check if allAtoms are already typed
        try:
            t = mol.allAtoms.babel_type
        except:
            #if all are not pretyped, type them
            babel = AtomHybridization()
            babel.assignHybridization(mol.allAtoms)

        if self.method=='withBondOrder':
            mol.rings = RingFinder()
            mol.rings.findRings2(mol.allAtoms, mol.allAtoms.bonds[0])
            mol.rings.bondRings = {}
            for ind in xrange(len(mol.rings.rings)):
                r = mol.rings.rings[ind]
                for b in r['bonds']:
                    if not mol.rings.bondRings.has_key(b):
                        mol.rings.bondRings[b] = [ind,]
                    else:
                        mol.rings.bondRings[b].append(ind)
            bo = BondOrder()
            bo.assignBondOrder(mol.allAtoms, bonds, mol.rings)
            mol.allAtoms._bndtyped = 1
            # do aromatic here
            arom = Aromatic(mol.rings)
            arom.find_aromatic_atoms(mol.allAtoms)
            
        hat = AddHydrogens().addHydrogens(mol.allAtoms, method=self.method)
        bondedAtomDict = {}  # key is heavy atom
        for a in hat:
            if bondedAtomDict.has_key(a[1]):
                bondedAtomDict[a[1]].append(a)
            else:
                bondedAtomDict[a[1]] = [a]

        # now create Atom object for hydrogens
        # and add the to the residues's atom list
        molNewHs = AtomSet([]) # list of created H atoms for this molecule
        heavyAtoms = AtomSet([]) # list of atoms that need new radii
        
        for heavyAtom, HatmsDscr in bondedAtomDict.items():
            #don't add hydrogens to carbons: polar Only!!!
            if self.htype!='all' and heavyAtom.element=='C': 
                continue
            res = heavyAtom.parent
            # find where to insert H atom
            childIndex = res.children.index(heavyAtom)+1

            # loop over H atoms description to be added
            # start at the end to number correctly
            l = len(HatmsDscr)
            for i in range(l-1,-1,-1):
                a = HatmsDscr[i]
                # build H atom's name
                if len(heavyAtom.name)==1:
                    name = 'H' + heavyAtom.name
                else:
                    name = 'H' + heavyAtom.name[1:]

                # if more than 1 H atom, add H atom index
                # for instance HD11, HD12, Hd13 (index is 1,2,3)
                if l > 1:
                    name = name + str(i+1)

                # create the H atom object
                atom = Atom(name, res, top=heavyAtom.top,
                            chemicalElement='H',
                            childIndex=childIndex, assignUniqIndex=0)

                # set atoms attributes
                atom._coords = [ a[0] ]
                if hasattr(a[1], 'segID'): atom.segID = a[1].segID
                atom.hetatm = 0
                atom.alternate = []
                #atom.element = 'H'
                atom.occupancy = 1.0
                atom.conformation = 0
                atom.temperatureFactor = 0.0
                atom.babel_atomic_number = a[2]
                atom.babel_type = a[3]
                atom.babel_organic = 1
                atom.radius = 1.2
                
                # create the Bond object bonding Hatom to heavyAtom
                bond = Bond( a[1], atom, bondOrder=1)

                # add the created atom the the list
                molNewHs.append(atom)
                # in case this new hydrogen atom ever ends up in pmv 
                # HAVE TO CREATE THESE ENTRIES 
                # create the color entries for all geoemtries
                # available for the heavyAtom
                for key, value in heavyAtom.colors.items():
                    atom.colors[key]=(0.0, 1.0, 1.0)
                    atom.opacities[key]=1.0

        mol.allAtoms = mol.chains.residues.atoms
        if self.renumber:
            mol.allAtoms.number = range(1, len(mol.allAtoms)+1)
        return len(molNewHs)
Пример #37
0
class AddBondsGUICommand(MVCommand, MVAtomICOM):
    """
    The AddBondGUICommand provides an interactive way of creating bonds between two given atoms by picking on them. To use this command you need first to load it into PMV. Then you can find the entry 'addBonds' under the Edit menu. To add bonds  you just need to pick on the 2 atoms you want to bind. If you drag select  a bunch of atoms, the command will buildBondsByDistance between them.This command is undoable.
   \nPackage : Pmv
   \nModule  : bondsCommands
   \nClass   : AddBondsGUICommand
   \nCommand : addBondsGC
   \nSynopsis:\n
        None<-addBondsGC(atoms)\n
    \nRequired Arguments:\n    
        atoms  : atom(s)\n
    """
    def __init__(self, func=None):
        MVCommand.__init__(self, func)
        MVAtomICOM.__init__(self)
        self.atomList = AtomSet([])
        self.undoAtList = AtomSet([])
        self.labelStrs = []

    def onRemoveObjectFromViewer(self, obj):
        removeAts = AtomSet([])
        for at in self.atomList:
            if at in obj.allAtoms:
                removeAts.append(at)
        self.atomList = self.atomList - removeAts
        removeAts = AtomSet([])
        for at in self.undoAtList:
            if at in obj.allAtoms:
                removeAts.append(at)
        self.undoAtList = self.undoAtList - removeAts
        self.update()

    def onAddCmdToViewer(self):
        if not self.vf.commands.has_key('setICOM'):
            self.vf.loadCommand('interactiveCommands',
                                'setICOM',
                                'Pmv',
                                topCommand=0)
        if not self.vf.commands.has_key('addBonds'):
            self.vf.loadCommand('bondsCommands',
                                'addBonds',
                                'Pmv',
                                topCommand=0)
        if not self.vf.commands.has_key('removeBondsGC'):
            self.vf.loadCommand('bondsCommands',
                                'removeBondsGC',
                                'Pmv',
                                topCommand=0)
        self.masterGeom = Geom('addBondsGeom',
                               shape=(0, 0),
                               pickable=0,
                               protected=True)
        self.masterGeom.isScalable = 0
        self.spheres = Spheres(name='addBondsSpheres',
                               shape=(0, 3),
                               inheritMaterial=0,
                               radii=0.2,
                               quality=15,
                               materials=((1., 1., 0.), ),
                               protected=True)
        if not self.vf.commands.has_key('labelByExpression'):
            self.vf.loadCommand('labelCommands', [
                'labelByExpression',
            ],
                                'Pmv',
                                topCommand=0)
        if self.vf.hasGui:
            miscGeom = self.vf.GUI.miscGeom
            self.vf.GUI.VIEWER.AddObject(self.masterGeom, parent=miscGeom)
            self.vf.GUI.VIEWER.AddObject(self.spheres, parent=self.masterGeom)

    def __call__(self, atoms, **kw):
        """None<-addBondsGC(atoms)
           \natoms  : atom(s)"""
        if type(atoms) is StringType:
            self.nodeLogString = "'" + atoms + "'"
        ats = self.vf.expandNodes(atoms)
        if not len(ats): return 'ERROR'
        return apply(self.doitWrapper, (ats, ), kw)

    def doit(self, ats):
        if len(ats) > 2:
            if len(self.atomList):
                atSet = ats + self.atomList
            else:
                atSet = ats
            parent = atSet[0].parent
            parent.buildBondsByDistanceOnAtoms(atSet)
            self.atomList = AtomSet([])
            self.update(True)
        else:
            lenAts = len(self.atomList)
            last = None
            if lenAts:
                last = self.atomList[-1]
                top = self.atomList[0].top
            for at in ats:
                #check for repeats of same atom
                if lenAts and at == last:
                    continue
                #lenAts = len(self.atomList)
                #if lenAts and at==self.atomList[-1]:
                #    continue
                if lenAts and at.top != self.atomList[-1].top:
                    msg = "intermolecular bond to %s disallowed" % (
                        at.full_name())
                    self.warningMsg(msg)
                self.atomList.append(at)
                self.undoAtList.append(at)
                lenAts = len(self.atomList)
            self.update(True)
            #if only have one atom, there is nothing else to do
            if lenAts < 2: return
            #now build bonds between pairs of atoms
            atSet = self.atomList
            if lenAts % 2 != 0:
                atSet = atSet[:-1]
                #all pairs of atoms will be bonded
                #so keep only the last one
                self.atomList = atSet[-1:]
                lenAts = lenAts - 1
            else:
                self.vf.labelByExpression(self.atomList,
                                          negate=1,
                                          topCommand=0)
                self.atomList = AtomSet([])
            for i in range(0, lenAts, 2):
                at1 = atSet[i]
                at2 = atSet[i + 1]
                self.vf.addBonds(at1, at2, origin='UserDefined', topCommand=0)
        self.update(True)

    def applyTransformation(self, pt, mat):
        pth = [pt[0], pt[1], pt[2], 1.0]
        return Numeric.dot(mat, pth)[:3]

    def getTransformedCoords(self, atom):
        if not atom.top.geomContainer:
            return atom.coords
        g = atom.top.geomContainer.geoms['master']
        c = self.applyTransformation(atom.coords, g.GetMatrix(g))
        return c.astype('f')

    def update(self, event=None):
        if not len(self.atomList):
            self.spheres.Set(vertices=[], tagModified=False)
            self.vf.labelByExpression(self.atomList, negate=1, topCommand=0)
            if self.vf.hasGui:
                self.vf.GUI.VIEWER.Redraw()
            return
        self.lineVertices = []
        #each time have to recalculate lineVertices
        for at in self.atomList:
            c1 = self.getTransformedCoords(at)
            self.lineVertices.append(tuple(c1))

        if event:
            self.spheres.Set(vertices=self.lineVertices, tagModified=False)
            self.vf.labelByExpression(self.atomList,
                                      function='lambda x: x.full_name()',
                                      lambdaFunc=1,
                                      textcolor='yellow',
                                      format='',
                                      negate=0,
                                      location='Last',
                                      log=0,
                                      font='arial1.glf',
                                      only=1,
                                      topCommand=0)
        #setting spheres doesn't trigger redraw so do it explicitly
        if self.vf.hasGui:
            self.vf.GUI.VIEWER.Redraw()

    def guiCallback(self, event=None):
        self.save = self.vf.ICmdCaller.commands.value["Shift_L"]
        self.vf.setICOM(self, modifier="Shift_L", topCommand=0)

    def setupUndoAfter(self, ats, **kw):

        lenUndoAts = len(self.undoAtList)
        lenAts = len(ats)
        if lenAts == 1:
            #after adding 1 self.atomList would be 1 or 0
            if len(self.atomList) == 1:
                s = '0'
                ustr = '"c=self.addBondsGC; self.labelByExpression(c.atomList, negate=1, topCommand=0);c.atomList=c.atomList[:' + s + '];c.undoAtList=c.undoAtList[:-1];c.update()"'
            else:
                self.vf.undoCmdStack.remove(self.prev_undoCmds)
                ind = str(lenUndoAts - 2)
                ustr = '"c=self.addBondsGC;nodes=self.expandNodes(' + '\'' + self.undoAtList[
                    -2:].full_name(
                    ) + '\'' + '); bonds=nodes.bonds[0];self.removeBondsGC(bonds, topCommand=0);c.atomList=nodes[:1];c.undoAtList=c.undoAtList[:' + ind + '];c.update()"'
        elif lenUndoAts > lenAts:
            ustr = '"c=self.addBondsGC;nodes=self.expandNodes(' + '\'' + ats.full_name(
            ) + '\'' + ');bonds = nodes.bonds[0];self.removeBondsGC(bonds, topCommand=0);c.undoAtList=c.undoAtList[:' + str(
                lenAts) + ']"'
        else:
            ustr = '"c=self.addBondsGC;nodes=self.expandNodes(' + '\'' + ats.full_name(
            ) + '\'' + ');bonds = nodes.bonds[0];self.removeBondsGC(bonds, topCommand=0);c.undoAtList=c.undoAtList[:0]"'
        if len(self.atomList) and lenAts > 1:
            atStr = self.atomList.full_name()
            estr = ';nodes=self.expandNodes(' + '\'' + self.atomList.full_name(
            ) + '\'' + ');c.atomList=nodes;c.update()"'
            ustr = ustr + estr
        self.undoCmds = "exec(" + ustr + ")"
        self.prev_undoCmds = (self.undoCmds, "addBondsGC")

    def startICOM(self):
        self.vf.setIcomLevel(Atom, topCommand=0)

    def stopICOM(self):
        if len(self.atomList) != 0:
            self.vf.labelByExpression(self.atomList, negate=1, topCommand=0)
        del self.atomList[:]
        self.labelStrs = []
        self.spheres.Set(vertices=[], tagModified=False)
        self.vf.GUI.VIEWER.Redraw()
        self.save = None
Пример #38
0
    def nextFrame(self, id):
        #Player.nextFrame(self, id)
        id = int(id)
        if id == self.currentFrameIndex: return
        if self.hasCounter and self.gui:
            self.form.ent2.delete(0, 'end')
            self.form.ent2.insert(0, str(id))
            if self.hasSlider:
                self.form.ifd.entryByName['slider']['widget'].set(id)
        self.currentFrameIndex = int(id)
        removeAtoms = AtomSet([])
        addAtoms = AtomSet([])

        id = int(id)
        flood = self.floods[id]
        centers = []
        materials = []
        radii = []
        prev_coords = self.mol.allAtoms.coords
        lenAtoms = len(prev_coords)
        #self.residue.atoms = AtomSet([])
        index = 0
        #h = self.hp.heap()
        #print h
        for fl in flood:
            x = (fl[1] - self.xcent) * self.spacing + self.centerx
            y = (fl[2] - self.ycent) * self.spacing + self.centery
            z = (fl[3] - self.zcent) * self.spacing + self.centerz
            if fl[4] == 7:
                atomchr = 'P'
                # note, this will color the NA atom pink (the PDB color for Phosphorus)
                radius = AAradii[13][0]
            if fl[4] == 6:
                atomchr = 'S'
                radius = AAradii[13][0]
            if fl[4] == 5:
                atomchr = 'A'
                radius = AAradii[10][0]
            if fl[4] == 4:
                atomchr = 'O'
                radius = AAradii[1][0]
            if fl[4] == 3:
                atomchr = 'N'
                radius = AAradii[4][0]
            if fl[4] == 2:
                atomchr = 'C'
                radius = AAradii[10][0]
            if fl[4] == 1:
                atomchr = 'H'
                radius = AAradii[15][0]
            if not [x, y, z] in prev_coords:
                a = Atom(atomchr, self.residue, atomchr, top=self.mol)
                a._coords = [[x, y, z]]
                a._charges = {}
                a.hetatm = 1
                a.radius = radius
                #a.number = lenAtoms + 1
                addAtoms.append(a)
                lenAtoms += 1
                for key in self.colorKeys:
                    a.colors[key] = AtomElements[atomchr]
                    a.opacities[key] = 1.0
            else:
                centers.append([x, y, z])


#            a = Atom(atomchr, self.residue, atomchr, top=self.mol)
#            a._coords = [[x,y,z]]
#            a._charges = {}
#            a.hetatm = 1
#            a.number = index
#            index += 1
#aterials.append(AtomElements[atomchr])
#enters.append([x,y,z])
#adii.append(radius)
#self.mol.allAtoms = self.residue.atoms
#self.mol.geomContainer.geoms['lines'].protected = False
#for com in self.autoLigandCommand.vf.cmdsWithOnAddObj:
#    com.onAddObjectToViewer(self.mol)
#self.autoLigandCommand.vf.displayCPK(self.mol, scaleFactor=0.1)

        halo_centers = []
        for coord in prev_coords:
            if not coord in centers:
                index = prev_coords.index(coord)
                removeAtoms.append(self.mol.allAtoms[index])

        self.residue.assignUniqIndex(
        )  #this is needed to avoid Traceback later on
        self.mol.allAtoms.stringRepr = None  #stringRepr can be very large aousing memory errors
        event = AddAtomsEvent(objects=addAtoms)
        #self.autoLigandCommand.vf.dispatchEvent(event)
        self.autoLigandCommand.vf.displayCPK.updateGeom(event)
        event = DeleteAtomsEvent(objects=removeAtoms)
        #self.autoLigandCommand.vf.dispatchEvent(event)
        self.autoLigandCommand.vf.displayCPK.updateGeom(event)
        for atom in removeAtoms:
            self.residue.atoms.remove(atom)
        if id == self.maxFrame:
            self.autoLigandCommand.halo.Set(visible=0)
        else:
            self.autoLigandCommand.halo.Set(centers=addAtoms.coords,
                                            materials=((1, 1, 0, 0.5), ),
                                            radii=0.4)
Пример #39
0
    def getDonors(self, nodes, paramDict):
        donorList = paramDict['donorTypes']
        # print 'donorList=', donorList
        # currently this is a set of hydrogens
        hats = AtomSet(nodes.get(lambda x: x.element == 'H'))
        # hats are optional: if none, process donors
        # if there are hats: dAts are all atoms bonded to all hydrogens
        if hats:
            dAts = AtomSet([])
            for at in hats:
                for b in at.bonds:
                    at2 = b.atom1
                    if id(at2) == id(at):
                        at2 = b.atom2
                    dAts.append(at2)
                    # dAts.append(b.neighborAtom(at))
        else:
            dAts = nodes
        # get the sp2 hybridized possible donors which are all ns
        sp2 = []
        for t in ['Nam', 'Ng+', 'Npl']:
            if t in donorList:
                sp2.append(t)
        # ntypes = ['Nam', 'Ng+', 'Npl']

        sp2DAts = None
        if len(sp2):
            sp2DAts = AtomSet(dAts.get(lambda x, sp2=sp2: x.babel_type in sp2))

        hsp2 = AtomSet([])
        if sp2DAts:
            if hats:
                hsp2 = AtomSet(
                    hats.get(lambda x, sp2DAts=sp2DAts: x.bonds[0].atom1 in
                             sp2DAts or x.bonds[0].atom2 in sp2DAts))
        if sp2DAts:
            # remove any sp2 N atoms which already have 3 bonds not to hydrogens
            n2Dons = AtomSet(sp2DAts.get(lambda x: x.element == 'N'))
            if n2Dons:
                n2Dons.bl = 0
                for at in n2Dons:
                    for b in at.bonds:
                        if type(b.bondOrder) == type(2):
                            at.bl = at.bl + b.bondOrder
                        else:
                            at.bl = at.bl + 2
                        # allow that there might already be a hydrogen
                    nH = at.findHydrogens()
                    at.bl = at.bl - len(nH)
                badAts = AtomSet(n2Dons.get(lambda x: x.bl > 2))
                if badAts:
                    sp2DAts = sp2DAts - badAts
                delattr(n2Dons, 'bl')
        # get the sp3 hybridized possible donors
        sp3 = []
        for t in ['N3+', 'S3', 'O3']:
            if t in donorList:
                sp3.append(t)
        n3DAts = None
        if 'N3+' in sp3:
            n3DAts = AtomSet(dAts.get(lambda x: x.babel_type == 'N3+'))
        o3DAts = None
        if 'O3' in sp3:
            o3DAts = AtomSet(dAts.get(lambda x: x.babel_type == 'O3'))
        if o3DAts:
            # remove any O3 atoms which already have 2 bonds not to hydrogens
            badO3s = AtomSet([])
            for at in o3DAts:
                if len(at.bonds) < 2:
                    continue
                if len(at.findHydrogens()):
                    continue
                else:
                    badO3s.append(at)
            if len(badO3s):
                o3DAts = o3DAts - badO3s
        s3DAts = None
        if 'S3' in sp3:
            s3DAts = AtomSet(dAts.get(lambda x: x.babel_type == 'S3'))
        sp3DAts = AtomSet([])
        for item in [n3DAts, o3DAts, s3DAts]:
            if item:
                sp3DAts = sp3DAts + item
        hsp3 = AtomSet([])
        if sp3DAts:
            if hats:
                hsp3 = AtomSet(
                    hats.get(lambda x, sp3DAts=sp3DAts: x.bonds[0].atom1 in
                             sp3DAts or x.bonds[0].atom2 in sp3DAts))
        hsp = hsp2 + hsp3
        # print 'hsp=', hsp.name
        # print 'sp2DAts=', sp2DAts.name
        # print 'sp3DAts=', sp3DAts.name
        return hsp, sp2DAts, sp3DAts
class SetTorsionGUICommand(MeasureTorsionGUICommand):


    def guiCallback(self):
        self.save = self.vf.ICmdCaller.commands.value["Shift_L"]
        self.vf.setICOM(self, modifier="Shift_L", topCommand=0)
        if not hasattr(self, 'form'):
            self.buildForm()
        else:
            self.form.deiconify()


    def onAddCmdToViewer(self):
        if not hasattr(self.vf, 'GUI'):
            return
        self.undoNow = 0
        self.save = None
        from DejaVu.bitPatterns import pat3
        from DejaVu.IndexedPolygons import IndexedPolygons
        if not self.vf.commands.has_key('setICOM'):
            self.vf.loadCommand('interactiveCommands', 'setICOM', 'Pmv',
                                topCommand=0)
        if not self.vf.commands.has_key('measureTorsion'):
            self.vf.loadCommand('measureCommands', 'measureTorsion', 'Pmv',
                                topCommand=0) 

        self.masterGeom = Geom('setTorsionGeom',shape=(0,0), 
                                pickable=0, protected=True)
        self.masterGeom.isScalable = 0
        self.vf.GUI.VIEWER.AddObject(self.masterGeom,
                                parent=self.vf.GUI.miscGeom)
        self.lines = IndexedPolygons('settorsionLine', materials = ((0,1,1),),
                                     inheritMaterial=0,
                                     stipplePolygons=1, protected=True,)
        if self.vf.userpref['Sharp Color Boundaries for MSMS']['value'] == 'blur':                
            self.lines.Set(inheritSharpColorBoundaries=False, sharpColorBoundaries=False,)
        self.lines.polygonstipple.Set(pattern=pat3)#, tagModified=False)
        #self.lines.RenderMode(GL.GL_FILL, face=GL.GL_BACK)
        self.lines.Set(backPolyMode=GL.GL_FILL)
        self.labels = GlfLabels(name='settorsionLabel', shape=(0,3),
                                    inheritMaterial=0,
                   materials = ((0,1,1),))
        self.spheres = Spheres(name='settorsionSpheres', shape=(0,3),
                               radii=0.2, quality=15,
                                    inheritMaterial=0,
                               materials = ((0.,1.,1.),), protected=True) 
        for item in [self.lines, self.labels, self.spheres]:
            self.vf.GUI.VIEWER.AddObject(item, parent=self.masterGeom)
        self.snakeLength = 1
        self.oldValue = None
        self.torsionType = Tkinter.StringVar()
        self.torsionType.set('1')
        self.newAngList = Tkinter.StringVar()
        self.TAHdata = None
        self.molecule = None
        #self.bondString = Tkinter.StringVar()
        self.callbackDict = {}
        self.callbackDict['measureDistanceGC'] = 'update'
        self.callbackDict['measureAngleGC'] = 'update'
        self.callbackDict['measureTorsionGC'] = 'update'


    def onRemoveObjectFromViewer(self, mol):
        lenAts = len(self.atomList)
        #if cmd has no atoms on its list, nothing to do
        if not lenAts:
            return
        #remove any atoms which are being deleted from viewer
        self.atomList = AtomSet(self.atomList) - mol.allAtoms
        #if some have been removed, do an update
        if lenAts!=len(self.atomList):
            self.update()
            self.extslider.set(0)



    def __call__(self, atoms, angle=None,**kw):
        """torsion/None<-setTorsionGC(atoms, angle=None)
        the torsion is returned when the number of atoms is a multiple of 4"""
        ats = self.vf.expandNodes(atoms)
        if not len(ats): return 'ERROR'
        return apply(self.doitWrapper, (ats, angle,), kw)


    def doit(self, ats, angle):
        for at in ats:
            lenAts = len(self.atomList)
            if lenAts and lenAts%4!=0 and at==self.atomList[-1]:
                continue
            if len(self.atomList)==0:
                self.molecule = at.top
            if at.top == self.molecule:
                self.atomList.append(at)
            else:
                #all atoms in torsion must be in same molecule ...(?)
                s = at.full_name()+ " not in " + self.molecule.full_name()
                self.warningMsg(s)
                return 'ERROR'
            if len(self.atomList)>4*self.snakeLength:
                self.atomList = self.atomList[4:]
            self.update()
        if  len(self.atomList)==4:
            mol = self.atomList[0].top
            at0,at1,at2,at3 = self.atomList
            self.mov_atoms = mol.subTree(at1, at2, mol.allAtoms)
            self.oldValue = self.vf.measureTorsion.doit(at0,at1,at2,at3)
            self.origValue = self.oldValue
            self.origCoords = self.mov_atoms.coords
            if hasattr(self, 'extslider'):
                self.extslider.set(self.oldValue, update=0)
            if angle: 
                #angle is what you want to end up with
                deltaAngle = angle - self.oldValue
                #print 'deltaAngle=', deltaAngle, 'angle=', angle
                self.transformCoords(deltaAngle)
                if hasattr(self, 'extslider'):
                    self.extslider.set(angle, update=0)
                #s = self.atomList[2].full_name()+'--'+self.atomList[3].full_name()
                #self.bondString.set(s)
            self.updateHistory()
            ##if self.undoNow: raise 'abc'
            #return float(self.labelStrs[-1])
            return


    def update(self, forward=1, event=None):
        if not len(self.atomList):
            self.spheres.Set(vertices=[], tagModified=False)
            self.labels.Set(vertices=[], tagModified=False)
            self.lines.Set(vertices=[], tagModified=False)
            self.vf.GUI.VIEWER.Redraw()
            return
        limit = self.snakeLength
        #each time have to recalculate lineVertices
        self.lineVertices=[]
        for at in self.atomList:
            c1 = self.getTransformedCoords(at)
            self.lineVertices.append(tuple(c1))
        #display spheres:
        self.spheres.Set(vertices=self.lineVertices, tagModified=False)
        self.vf.GUI.VIEWER.Redraw()
        #label with torsion
        #lines between spheres are only drawn when angle completed
        #that is, len(ats)%4=0
        if len(self.lineVertices)<4:
            self.labels.Set(vertices=[], tagModified=False)
            self.lines.Set(vertices=[], tagModified=False)
        else:
            #rebuild labels and polygons each time
            self.labelCenters=[]
            self.labelStrs=[]
            #labelCenters, labelStrs, 
            #this gets done lenATs/4 times
            numItems = len(self.atomList)/4
            for i in range(numItems):
                at0,at1,at2,at3 = self.atomList[i*4:i*4+4]
                torsion = self.vf.measureTorsion.doit(at0, at1, at2, at3)
                torsionLabel = '%.3f' %torsion
                self.labelStrs.append(torsionLabel)
                c0 = self.getTransformedCoords(at0)
                c1 = self.getTransformedCoords(at3)
                newcenter = tuple((c0+c1)/2.0)
                self.labelCenters.append(newcenter)
        self.vf.GUI.VIEWER.Redraw()
        items = self.callbackDict.keys()
        #items = ['measureDistanceGC','measureAngleGC','measureTorsionGC']
        #checkout whether measure update needs to be called
        icomVals = self.vf.ICmdCaller.commands.value.values()
        for item in items: 
            if not len(icomVals): break
            if not hasattr(self.vf, item):
                continue
            exec('cmd = self.vf.'+item)
            if cmd in icomVals:
                #cmd.update()
                s = self.callbackDict[item]
                exec('self.vf.' + item + '.'+ s + '()')



    def transformCoords(self, deltaAngle):
        """ deltaAngle is NOW not final angle wanted but relative"""
        #mov_coords is the array of the coords of the atoms to be moved,
        #x2 and x3 are atoms which define the axis of the transformation
        #by deltaAngle. NB: effect is that mov_atoms.coords 
        #are transformed...
        if not hasattr(self, 'mov_atoms'): return
        if not len(self.mov_atoms): return
        x1, x2, x3, x4 = self.atomList
        nc = self.vf.setRelativeTorsion.doit(x2, x3, deltaAngle, 
                self.mov_atoms, returnVal=1)
        mol = x2.top
        #mov_atoms = mol.subTree(x2, x3, mol.allAtoms)
        for i in range(len(nc)):
            at = self.mov_atoms[i]
            at._coords[at.conformation] = nc[i].tolist()
        event = EditAtomsEvent('coords', self.mov_atoms)
        self.vf.dispatchEvent(event)
        self.update()


#####Callback Functions for the Dial:
#####slideCallback 
    def slideCallback(self, eventval):
        #print 'in slideCallback'
        if len(self.atomList)!=4: return
        if not hasattr(self, 'oldValue'): return
        if self.oldValue==None:
            return
        #self.setupUndoBefore(self.atomList, self.oldValue)
        try:
            newAngle = self.extslider.get()
            tT = self.torsionType.get()
            at0, at1, at2, at3 = self.atomList
            #torsion = self.vf.measureTorsion.doit(at0, at1, at2, at3)
            torsion = self.oldValue
            if tT == '1':
                #NEWdeltaAngle = newAngle
                deltaAngle = newAngle - torsion
            else:
                #NEWdeltaAngle = newAngle + torsion
                deltaAngle = newAngle
            self.transformCoords(deltaAngle)
            #print 'deltaAngle=', deltaAngle
            self.oldValue = newAngle
            #self.oldValue = newAngle
        except ValueError:
            self.vf.GUI.message("error in slideCallback\n")


    def rdSet(self, event=None):
        #"""radiobutton selection of torsionType:
        #Absolute: initial angle to be displayed in slider/entry
        #Relative: 0 is displayed """
        if self.torsionType.get()=='1':
            aL = self.atomList
            if len(aL)==4:
                torsion = self.vf.measureTorsion.doit(aL[0],aL[1],aL[2],aL[3])
                self.extslider.set(torsion)
        else:
            self.extslider.set(0)

            

    def setupUndoBefore(self, ats, angle):
        pass


    #def setupUndoBefore(self, ats, angle):
        ##no atoms, <4 atoms, 
        #aSet = AtomSet(self.atomList)
        #self.undoMenuString = self.name
        #if len(self.atomList)==0:
            #undoCmd = 'self.setTorsionGC.atomList=[]; self.setTorsionGC.update()'
        #elif len(self.atomList)<4:
            ##need to step back here
            #undoCmd = 'self.setTorsionGC.atomList=self.setTorsionGC.atomList[:-1]; self.setTorsionGC.update()'
        #else:
            ##print 'self.oldValue=', self.oldValue
            #undoCmd = 'self.setTorsionGC(\''+ aSet.full_name()+ '\',' + str(self.oldValue) + ', topCommand=0)'
            ##self.oldValue = str(self.extslider.get())
        #self.vf.undo.addEntry((undoCmd), (self.name))
            

    def setupUndoAfter(self, ats, angle,**kw):
        #no atoms, <4 atoms, 
        aSet = AtomSet(self.atomList)
        self.undoMenuString = self.name
        if len(self.atomList)==0:
            undoCmd = 'self.setTorsionGC.atomList=[]; self.setTorsionGC.update()'
        elif len(self.atomList)<4:
            #need to step back here
            undoCmd = 'self.setTorsionGC.atomList=self.setTorsionGC.atomList[:-1]; self.setTorsionGC.update()'
        elif self.origValue==self.oldValue:
            return
        else:
            restoreAngle = self.origValue
            self.undoNow = 1
            undoCmd = 'self.setTorsionGC(\''+ aSet.full_name()+ '\',' + str(restoreAngle) + ', topCommand=0)'
        self.vf.undo.addEntry((undoCmd), (self.name))


    def Accept_cb(self):
        apply(self.setupUndoAfter,(self.atomList, self.oldValue),{})
        self.origValue = self.oldValue


    def Done_cb(self):
        self.vf.setICOM(self.save, modifier="Shift_L", mode='pick',topCommand = 0)
        self.stopICOM()



    def startICOM(self):
        self.vf.setIcomLevel( Atom )
        if not hasattr(self, 'form'):
            self.buildForm()
        else:
            self.form.deiconify()


    def stopICOM(self):
        if hasattr(self, 'form'):
            self.form.withdraw()
        self.atomList = []
        self.atomCenters = []
        self.labelStrs = []
        self.labelCenters = []
        self.lineVertices = []
        self.spheres.Set(vertices=[], tagModified=False)
        self.lines.Set(vertices=[], faces=[], tagModified=False)
        self.labels.Set(vertices=[], tagModified=False)
        self.vf.GUI.VIEWER.Redraw()
        #when cmd stops being icom, remove callback
##         ehm = self.vf.GUI.ehm
##         for event in ['<B2-Motion>', '<B3-Motion>']:
##             if ehm.eventHandlers.has_key(event) and self.update_cb in \
##                     ehm.eventHandlers[event]:
##                 ehm.RemoveCallback(event, self.update_cb)
        for event in ['<B2-Motion>', '<B3-Motion>']:
            self.vf.GUI.removeCameraCallback(event, self.update_cb)


    def repeat_transTors(self, event=None):
        deltaAngle = self.extslider.get()
        if self.torsionType.get() != '1':
            self.transformCoords(deltaAngle)
        #this is here in order to create a log message
        nc = self.vf.setRelativeTorsion(self.atomList[1], self.atomList[2], deltaAngle, 
                self.mov_atoms, returnVal=1)
        event = EditAtomsEvent('coords', self.mov_atoms)
        self.vf.dispatchEvent(event)


    def new_Tors(self, event = 0):
        self.atomList = []
        self.update()


    #when called, most recent 4 atoms are in self.atomList
    def updateHistory(self):
        """1: call TorsionHistory.getTorsion:
        make a new TorsionAngle or add current angle to angleList
        2: put TA.name_string into ListBox
        3: best if insert a tuple (string to be displayed, item itself)
        4: adjust size with self.historyList.configure(height=self.[].size)
        5: limit overall size to 4"""
        #print 'in updateHistory'
        molecule = self.atomList[-1].top
        if self.TAHdata is None:
            self.TAHdata = TorsionHistory(molecule)
        a1,a2,a3,a4 = self.atomList
        newone=self.TAHdata.getTorsion(a1,a2,a3,a4 )
        #first check to see if it is in there already??? 
        #need to get info back from getTorsion....(???)
        if hasattr(self, 'historyList'):
            if newone.new:
                self.historyList.insert('end',newone.name_string)
                if int(self.historyList.cget('height'))<4:
                    self.historyList.configure(height=self.historyList.size())
            if self.historyList.curselection():
                    self.historyList.select_clear(self.historyList.curselection())
            newindex=self.TAHdata.getIndex(newone)
            self.historyList.select_set(newindex)
            self.historyList.see(newindex)
        #set entry to a string ==current TA's angleList
        newstring= ""
        for item in newone.angleList:
            newstring=newstring +" " + "%5.3f" %item
        self.newAngList.set(newstring)



    def HLCommand(self, event=None):
        """double-clicking selection in listbox causes curselection to be picked...
        1:self.atomList set to atoms of curselection
        2:self.mov_atoms set to atoms of curselection
        3:self.selAtom[1-4].Set(vertices=atoms.coords)
        4:reset entry +slider and init_bondAngle etc
        5.add current angle to selection's.angleList"""
        #get TA:
        if self.historyList.get(0)=='': return
        items=self.historyList.curselection()
        if type(items)==types.TupleType:
            items = items[0]
        try:
            items=map(int, items)
        except ValueError:pass
        thisTA=self.TAHdata.torslist[items[0]]
        #get currentAngle
        current= thisTA.getCurrentAngle()
        if not thisTA.inList(current):
            thisTA.angleList.append(current)
        newAts = AtomSet([thisTA.atom1,thisTA.atom2, thisTA.atom3,\
                    thisTA.atom4])
        #reset self.molecule
        self.atomList = []
        self.molecule = newAts[0].top
        self.doit(newAts, current)
        #self.setTorsionAngle(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4, current, 'A')
        #self.drawTransformedAngle()
        #self.updatespheres(items[0])
        #self.update()
        self.extslider.set(current,0)
        newstring= ""
        for item in thisTA.angleList:
            newstring=newstring +" " + "%5.3f" %item
        self.newAngList.set(newstring)


    def getAngList(self, event=None):
        items=self.historyList.curselection()
        try:
            items=map(int, items)
        except ValueError:pass
        thisTA=self.TAHdata.torslist[items[0]]
        thisTA.angleList=map(float, split(self.newAngList.get()))
        last=thisTA.angleList[-1]
        newAts = AtomSet([thisTA.atom1,thisTA.atom2, thisTA.atom3,\
                    thisTA.atom4])
        #reset self.molecule
        self.atomList = []
        self.molecule = newAts[0].top
        self.doit(newAts, last)
        #self.doit(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,last,'A')
        #self.setTorsionAngle(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,last,'A')
        #self.drawTransformedAngle()
        #self.updatespheres(items[0])
        self.extslider.set(last,0)
       

    def stepBack(self, event=None):
        items=self.historyList.curselection()
        if len(items)==0: return
        try:
            items=map(int, items)
        except ValueError:
            pass
        thisTA=self.TAHdata.torslist[items[0]]
        ####last angle is thisTA.angleList[-1]
        if len(thisTA.angleList)>1:
            last=thisTA.angleList[-1]
            lastIndex=thisTA.angleList.index(last)
            thisTA.angleList=thisTA.angleList[:lastIndex]
            last=thisTA.angleList[-1]
        else:
            last=thisTA.angleList[0]
        newAts = AtomSet([thisTA.atom1,thisTA.atom2, thisTA.atom3,\
                    thisTA.atom4])
        #reset self.molecule
        self.atomList = []
        self.molecule = newAts[0].top
        self.doit(newAts, last)
        #self.doit(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,last,'A')
        #self.setTorsionAngle(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,last,'A')
        #self.drawTransformedAngle()
        #self.updatespheres(items[0])
        newstring= ""
        for item in thisTA.angleList:
            newstring=newstring +" " + "%5.3f" %item
        self.newAngList.set(newstring)
        self.extslider.set(last, 0)
        #IS THIS ENOUGH in order to create correct log?
        self.mouseUp()
       

    def startOver(self, event=None):
        items=self.historyList.curselection()
        if len(items)==0: return
        try:
            items=map(int, items)
        except ValueError:pass
        thisTA=self.TAHdata.torslist[items[0]]
        self.resetAngle(thisTA)


    def resetAngle(self, thisTA, event=None):
        #first angle is thisTA.angleList[0]
        ang=thisTA.angleList[0]
        newAts = AtomSet([thisTA.atom1,thisTA.atom2, thisTA.atom3,\
                    thisTA.atom4])
        #reset self.molecule
        self.atomList = []
        self.molecule = newAts[0].top
        self.doit(newAts, ang)
        #self.doit(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,ang,'A')
        #self.setTorsionAngle(thisTA.atom1, thisTA.atom2, thisTA.atom3, thisTA.atom4,ang,'A')
        if len(thisTA.angleList)>1:
            thisTA.angleList=thisTA.angleList[:1]
        #self.drawTransformedAngle()
        self.extslider.set(ang,0)
        self.mouseUp()
        self.newAngList.set("%5.3f" %ang)
    

    def resetAll(self, event=None):
        if self.TAHdata==None: return
        for item in self.TAHdata.torslist:
            self.resetAngle(item)
        self.spheres.Set(vertices=[], tagModified=False)
        self.vf.GUI.VIEWER.Redraw()


    def buildForm(self):
        if hasattr(self, 'ifd'):
            return
        self.torsionType = Tkinter.StringVar()
        self.torsionType.set('1')
        self.ifd = ifd = InputFormDescr(title = 'Set Torsion Angle')
        ifd.append({'name':'extLabel',
                    'widgetType': Tkinter.Label,
                    'wcfg':{'text':'Set Angle:\n(180=trans)'},
                    'gridcfg':{'sticky':Tkinter.W+Tkinter.E,
                                'columnspan':2}})
        ifd.append( {'name':'extslider',
            'widgetType': ExtendedSliderWidget,
            'wcfg':{'label':'torsion',
                'minval':-360., 'maxval':360.,
                'width':150,
                'immediate':1,
                'command':self.slideCallback,
                'sliderType':'float',
                'entrypackcfg':{'side':'bottom'}},
            'gridcfg':{'sticky':'we', 'columnspan':2}})
        ifd.append({'name':'typeLabel',
                    'widgetType': Tkinter.Label,
                    'wcfg':{'text':'Torsion Type'},
                    'gridcfg':{'sticky':'we', 'columnspan':2}})
        ifd.append({'name':'rdbut1',
            'widgetType':Tkinter.Radiobutton,
            'wcfg':{'text':'Absolute',
                'variable': self.torsionType,
                'value':1,
                'command':self.rdSet
                },
            'gridcfg':{'sticky':'we'}})
        ifd.append({'name':'rdbut2',
            'widgetType':Tkinter.Radiobutton,
            'wcfg':{'text':'Relative ',
                'variable': self.torsionType,
                'value':0,
                'command':self.rdSet
                },
            'gridcfg':{'sticky':'we', 'row':-1, 'column':1}})
        ifd.append({'name':'historyList',
            'widgetType':ListChooser,
            'wcfg':{
                'title':'TorsionAngle\nTranformation History',
                'mode': 'single',
                'command': self.HLCommand,
                'lbwcfg':{'height':5, 
                    'selectforeground': 'yellow',
                    'exportselection': 0,
                    'width': 30},
            },
            'gridcfg':{'sticky':'we', 'columnspan':2}})
        ifd.append({'name':'hbut1',
            'widgetType':Tkinter.Button,
            'wcfg': { 'text':'Step Back ',
                'command': self.stepBack},
            'gridcfg':{'sticky':'we','columnspan':2}})
        ifd.append({'name':'hbut2',
            'widgetType':Tkinter.Button,
            'wcfg': { 'text':'Start Over ',
                'command': self.startOver},
            'gridcfg':{'sticky':'we','columnspan':2}})
        ifd.append({'name':'hbut3',
            'widgetType':Tkinter.Button,
            'wcfg': { 'text':'Reset All ',
                'command': self.resetAll},
            'gridcfg':{'sticky':'we','columnspan':2}})
        ifd.append({'name':'angListEnt',
           'widgetType':Tkinter.Entry, 
           'wcfg':{'width':5,
                'command':self.getAngList,
                'textvariable':self.newAngList},
           'gridcfg':{'sticky':'we','columnspan':2}})
        ifd.append({'name':'hbut4',
            'widgetType':Tkinter.Button,
            'wcfg': { 'text':'Move',
                'command': self.repeat_transTors},
            'gridcfg':{'sticky':'we','columnspan':2}})
        ifd.append({'name':'hbut5',
            'widgetType':Tkinter.Button,
            'wcfg': { 'text':'New Torsion',
                'command': self.new_Tors},
            'gridcfg':{'sticky':'we','columnspan':2}})
        #ifd.append({'name':'accept',
                    #'widgetType': Tkinter.Button,
                    #'wcfg':{'text' : 'Accept',
                            #'command': self.Accept_cb},
                    #'gridcfg':{'sticky':'we'}})
        ifd.append({'name':'done',
                    'widgetType': Tkinter.Button,
                    'wcfg':{'text' : 'Done',
                            'command': self.Done_cb},
                    'gridcfg':{'sticky':'we','columnspan':2}})
                    #'gridcfg':{'sticky':'we','column':1, 'row':-1}})
        self.form = self.vf.getUserInput(ifd, modal=0, blocking=0)
        self.form.root.protocol('WM_DELETE_WINDOW',self.Done_cb)
        self.extslider = self.ifd.entryByName['extslider']['widget']
        self.extslider.draw.bind('<ButtonRelease-1>', self.mouseUp, add='+')
        self.extslider.entry.bind('<Return>', self.mouseUp, add='+')
        self.historyList = self.ifd.entryByName['historyList']['widget'].lb
        #self.historyList.bind("<Double-Button-1>",self.HLCommand)
        self.hbut1 = self.ifd.entryByName['hbut1']['widget']
        self.hbut2 = self.ifd.entryByName['hbut2']['widget']
        self.hbut3 = self.ifd.entryByName['hbut3']['widget']
        self.angListEnt = self.ifd.entryByName['angListEnt']['widget']
            

    def mouseUp(self, event=None):
        #print "in mouseUp"
        #fix this: atomList length dependent
        if len(self.atomList)==4:
            at0,at1,at2,at3 = self.atomList
            angle = self.extslider.get()
            if self.torsionType.get()=='1':
                self.vf.setTorsion(at0, at1, at2, at3, angle)
            else:
                self.vf.setRelativeTorsion(at1, at2, angle)