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
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
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
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())
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()
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()
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
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
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
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
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)
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)
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)
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()
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)
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
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
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)
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)
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
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)
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)