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)
class SuperimposeAtomsGUICommand(SuperimposeCommand, MVAtomICOM): """ The SuperimposeAtomsGUICommand provides a GUI interface to the SuperimposeAtomsCommand. This commands allows the user to create two sets of atoms one reference and mobile of the same length by picking, by string or using the alignment editor. These two sets are then fed to the SuperimposeAtoms command. - For now Only two 2 sets of Atoms belonging to a ref molecule and a mobile molecule can be superimposed simultaneously. - The command provides two way of defining those two sets of atoms: * By picking nodes * By string: * Using the alignment editor """ # The superimposeAtomsGC provides an GU interface to allow the user to create two sets of atoms # which will be used to do a pairwise superimposition. def __init__(self, func=None): MVCommand.__init__(self, func) MVAtomICOM.__init__(self) self.refAtomList = [] self.inAtomList = [] #self.superImposedPairs = {} self.newPairs = {} self.pair = [] self.mobMol = None self.refMol = None self.refNodes = {} self.mobNodes = {} self.filters = { 'CA Atoms': lambda x: x.name == 'CA', 'Backbone Atoms': lambda x: x.name in ['CA', 'C', 'N', 'O', 'CA@A', 'C@A', 'N@A', 'O@A'], 'Heavy Atoms': lambda x: not x.element == 'H', 'All Atoms': None } self.defaultFilter = 'Backbone Atoms' ## def doit(self, refAtoms, mobAtoms, updateGeom=True, showRMSD=True): ## """same as in SuperimposeCommand """ ## SuperimposeCommand.doit(self, refAtoms, mobAtoms, updateGeom=True, showRMSD=True) def onAddCmdToViewer(self): # Check first is any of the command that superimpose depends on are # already loaded. if not self.vf.commands.has_key('setICOM'): self.vf.loadCommand('interactiveCommands', 'setICOM', 'Pmv', topCommand=0) if not self.vf.commands.has_key('superimposeAtoms'): self.vf.loadCommand('superImposeCommands', 'superimposeAtoms', 'Pmv', topCommand=0) if not self.vf.commands.has_key('startContinuousPicking'): self.vf.loadCommand('dejaVuCommands', 'startContinuousPicking', 'ViewerFramework', topCommand=0) if not self.vf.commands.has_key('stopContinuousPicking'): self.vf.loadCommand('dejaVuCommands', 'stopContinuousPicking', 'ViewerFramework', topCommand=0) if not self.vf.commands.has_key('labelByExpression'): self.vf.loadCommand('labelCommands', 'labelByExpression', 'Pmv', topCommand=0) self.sphere1 = Spheres(name='elt1', radii=0.5, materials=((0., 1., 0.), ), protected=True) self.sphere2 = Spheres(name='elt2', radii=0.5, materials=((1., 1., 0.), ), protected=True) def onRemoveObjectFromViewer(self, obj): if hasattr(self.vf, 'alignment'): self.vf.alnEditor.deleteSequence(obj.name) self.vf.alnEditor.redraw() if obj.name == self.refMol: self.refMol = None if obj.name == self.mobMol: self.mobMol = None ########################################################################## #### BY PICKING... ########################################################################## def initICOM(self, modifier): # set the callback of continuousPicking to label the picked node # 1- get a handle on the cbManager cbManager = self.vf.startContinuousPicking.cbManager # 2- Save the existing callbacks #self.oldCallBacks = cbManager.callbacks # 3- Set to the new callback cbManager.SetCallback(CallBackFunction(self.labelByName)) self.vf.startContinuousPicking() self.supcb = 0 def labelByName(self, pick): # Continuous labeling. if pick is None: return atom = self.vf.findPickedAtoms(pick) if atom: level = self.vf.ICmdCaller.level.value self.vf.ICmdCaller.level.AddCallback(self.unlabelLevel) if level == Molecule: level = Protein self.node = atom.findType(level) funcItems = map(lambda x: x.full_name(), self.node) self.vf.labelByExpression( self.node, font='arial1.glf', location='First', textcolor='red', only=0, lambdaFunc=1, negate=0, function='lambda x: str(x.full_name())\n\n', topCommand=0) def unlabelLevel(self, newLevel, oldLevel): if not hasattr(self, 'node'): return if oldLevel == Molecule: oldLevel = Protein # need to be at the former level for all the former picked stuff # so take it all. node = self.vf.getSelection() nodes = node.findType(oldLevel) # Careful in labelByProperty fix a bug if no label should not break! self.vf.labelByExpression(nodes, negate=1, log=0) def stopICOM(self): # Destroy the inputForm #self.cmdForms['superimpose'].root.destroy() # Set the form to None. #del self.cmdForms['superimpose'] # Set back the continuousPicking to unsolicitedPick cbManager = self.vf.startContinuousPicking.cbManager if not len(self.oldCallBacks) == 0: cbManager.SetCallback(self.oldCallBacks[0]) if len(self.oldCallBacks) > 1: for cb in self.oldCallBacks[1:]: cbManager.AddCallBack(cb) # Remove the unlabel callback bound to the self.vf.ICmdCaller.level if self.unlabelLevel in self.vf.ICmdCaller.level.callbacks: self.vf.ICmdCaller.level.RemoveCallback(self.unlabelLevel) # Unlabel whatever is labeled level = self.vf.ICmdCaller.level.value nodes = self.vf.getSelection().findType(level) if not nodes is None or len(nodes) != 0: self.vf.labelByExpression(nodes, negate=1, log=0) # Stop the continuous picking. self.vf.stopContinuousPicking() self.sphere1.Set(vertices=[]) self.sphere2.Set(vertices=[]) ## self.visualFeedBack(vertices =[]) ########################################################################## #### ########################################################################## def createNodesSets(self, refnodes=None, mobnodes=None): # Set the reference molecule and the mobile molecule.... # 1- set the reference molecule and the mobile from MolKit.protein import ProteinSet if refnodes: refMols = refnodes.top.uniq() if refMols == self.vf.Mols: self.warningMsg( "Reference and mobile molecules should be selected.") return if len(refMols) > 1: self.warningMsg( "Can have one and only one reference molecule.") return self.refMol = refMols[0] if mobnodes: mobMols = mobnodes.top.uniq() if refMols == self.vf.Mols: self.warningMsg( "Reference and mobile molecules should be selected.") return if len(mobMols) > 1: self.warningMsg("Can have one and only one mobile molecule.") return if mobMols[0] == self.refMol: self.warningMsg( "The mobile molecule must be different from the ref molecule" ) return self.mobMol = mobMols[0] # 2- Create the entries for the refNodes listChooser ebn = self.cmdForms['addPairs'].descr.entryByName if refnodes: reflc = ebn['refnodes']['widget'] for rn in refnodes: if not rn.top == self.refMol: continue self.refNodes[rn.full_name()] = rn reflc.add((rn.full_name(), None)) # Create the entries for the mobNodes listChooser if mobnodes: moblc = ebn['mobnodes']['widget'] for mn in mobnodes: if not mn.top == self.mobMol: continue self.mobNodes[mn.full_name()] = mn moblc.add((mn.full_name(), None)) def createPairs(self, refnames, mobnames, slice, choice): # This is where the atom pairs are created # Get the ref atom set refAtms = AtomSet([]) mobAtms = AtomSet([]) for name in refnames: refnod = self.refNodes[name] atms = refnod.findType(Atom) refAtms = refAtms + atms for name in mobnames: mobnod = self.mobNodes[name] atms = mobnod.findType(Atom) mobAtms = mobAtms + atms # Now apply the filters to the sets if choice: refFiltAtms = refAtms.get(self.filters[choice]) mobFiltAtms = mobAtms.get(self.filters[choice]) if not len(refFiltAtms) == len(mobFiltAtms): #print 'slicing', slice self.warningMsg( "the two sets of atoms needs to be of the same length") return ebn = self.cmdForms['pairs'].descr.entryByName lc = ebn['newpairs']['widget'] for refatm, mobatm in map(None, refFiltAtms, mobFiltAtms): #self.pairs.append((refatm, mobatm)) pairName = refatm.full_name() + '---' + mobatm.full_name() self.newPairs[pairName] = (refatm, mobatm) lc.add((pairName, None)) ########################################################################## #### GUI CALLBACKS ########################################################################## def pick_cb(self): ebn = self.cmdForms['addPairs'].descr.entryByName cbVar = int(ebn['pick']['variable'].get()) if cbVar: self.vf.setICOM(self, modifier="Shift_L", topCommand=0) else: self.stopICOM() def string_cb(self): ebn = self.cmdForms['addPairs'].descr.entryByName cbVar = ebn['string']['variable'] #print cbVar.get() if cbVar.get(): # if pushed show the form val = self.showForm('editString', modal=1, blocking=0, force=1) cbVar.set(0) if val: if not val['srefNodes'] and not val['smobNodes']: return refnodes = val['srefNodes'] if refnodes: refnodes.sort() mobnodes = val['smobNodes'] if mobnodes: mobnodes.sort() self.createNodesSets(refnodes, mobnodes) def setDefault(self, text): pass ## self.defaultFilter = text ## if hasattr(self, 'pair') and len(self.pair) == 2: ## filter = self.filters[text] ## set1 = self.pair[0] ## set2 = self.pair[1] ## if filter: ## set1 = set1.get(filter) ## set2 = set2.get(filter) ## if (set1 and set2) and (len(set1) == len(set2)): ## self.updateChooser(set1, set2)): def delete_cb(self): ebn = self.cmdForms['pairs'].descr.entryByName lc = ebn['newpairs']['widget'] lc.clear() self.newPairs = {} return def dismiss_cb(self): if self.cmdForms.has_key('pairs'): self.cmdForms['pairs'].withdraw() if self.cmdForms.has_key('addPairs'): self.cmdForms['addPairs'].withdraw() if self.cmdForms.has_key('editString'): self.cmdForms['addPairs'].withdraw() # Dismiss all the forms ??? ## for v in self.cmdForms.values(): ## v.withdraw() def continuous_cb(self): # Sets the continuous flag to the right value ???? pass def reset_cb(self): # Reset the superposition put back the mob molecule to the right place.. pass 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 add_cb(self): val = self.showForm('addPairs', modal=1, blocking=0, force=1, okCfg={'text': 'Create Pairs'}) # need to get all the nodes... from each listchooser if not val: return # Need this for the order of the nodes in the pairs... ebn = self.cmdForms['addPairs'].descr.entryByName reflc = ebn['refnodes']['widget'] refnames = map(lambda x: x[0], reflc.entries) moblc = ebn['mobnodes']['widget'] mobnames = map(lambda x: x[0], moblc.entries) self.createPairs(refnames, mobnames, val['slice'][0], val['choice'][0]) def refremove_cb(self): ebn = self.cmdForms['addPairs'].descr.entryByName lc = ebn['refnodes']['widget'] sel = lc.get() if sel: lc.remove(sel[0]) if sel[0] in self.refNodes: del self.refNodes[sel[0]] def mobremove_cb(self): ebn = self.cmdForms['addPairs'].descr.entryByName lc = ebn['mobnodes']['widget'] sel = lc.get() if sel: lc.remove(sel[0]) if sel[0] in self.refNodes: del self.mobNodes[sel[0]] def refmoveup_cb(self): ebn = self.cmdForms['addPairs'].descr.entryByName lc = ebn['refnodes']['widget'] sel = lc.get() if not sel: return sel = sel[0] selIndex = lc.entries.index((sel, None)) if selIndex == 0: return lc.remove(sel) lc.insert(selIndex - 1, sel) lc.select(sel) def mobmoveup_cb(self): ebn = self.cmdForms['addPairs'].descr.entryByName lc = ebn['mobnodes']['widget'] sel = lc.get() if not sel: return sel = sel[0] selIndex = lc.entries.index((sel, None)) if selIndex == 0: return lc.remove(sel) lc.insert(selIndex - 1, sel) lc.select(sel) def refmovedown_cb(self): ebn = self.cmdForms['addPairs'].descr.entryByName lc = ebn['refnodes']['widget'] sel = lc.get() if not sel: return sel = sel[0] selIndex = lc.entries.index((sel, None)) if selIndex == len(lc.entries) - 1: return lc.remove(sel) lc.insert(selIndex + 1, sel) lc.select(sel) def mobmovedown_cb(self): ebn = self.cmdForms['addPairs'].descr.entryByName lc = ebn['mobnodes']['widget'] sel = lc.get() if not sel: return sel = sel[0] selIndex = lc.entries.index((sel, None)) if selIndex == len(lc.entries) - 1: return lc.remove(sel) lc.insert(selIndex + 1, sel) lc.select(sel) def guiCallback(self): #form = self.showForm('pairs', modal=0, blocking=0) val = self.showForm('pairs', modal=0, blocking=0) def buildFormDescr(self, formName): if formName == 'addPairs': # CREATE PAIRS GROUP idf = InputFormDescr(title="Superimpose") idf.append({ 'name': "mode", 'widgetType': Pmw.Group, 'container': { 'mode': 'w.interior()' }, 'wcfg': { 'tag_text': "Create Reference Nodes and Mobile Nodes Lists" }, 'gridcfg': { 'sticky': 'wnse' } }) idf.append({ 'widgetType': Tkinter.Label, 'parent': 'mode', 'wcfg': { 'text': 'By String' }, 'gridcfg': { 'sticky': 'we' } }) idf.append({ 'widgetType': Tkinter.Checkbutton, 'name': 'string', 'parent': 'mode', #'tooltip':'Use the string selector to create refnode-mobnodes pairs', 'wcfg': { 'text': 'on/off', 'command': self.string_cb }, 'gridcfg': { 'sticky': 'we', 'row': -1 } }) idf.append({ 'widgetType': Tkinter.Label, 'parent': 'mode', 'wcfg': { 'text': 'By Picking' }, 'gridcfg': { 'sticky': 'we', 'row': -1 } }) idf.append({ 'widgetType': Tkinter.Checkbutton, 'name': 'pick', 'tooltip': 'Use the picking event to create refnode-mobnodes pairs', 'parent': 'mode', 'wcfg': { 'text': 'on/off', 'command': self.pick_cb }, 'gridcfg': { 'sticky': 'we', 'row': -1 } }) ############################################################### ## EDIT REF/MOB NODES ############################################################### idf.append({ 'name': "editnodes", 'widgetType': Pmw.Group, 'container': { 'editnodes': 'w.interior()' }, 'wcfg': { 'tag_text': "Edit Reference Nodes and Mobile Nodes Lists:" }, 'gridcfg': { 'sticky': 'wnse' } }) idf.append({ 'name': 'refremove', 'parent': 'editnodes', 'widgetType': Tkinter.Button, 'tooltip': """ Remove the selected entry from the commands to be applied to the object when loaded in the application""", 'wcfg': { 'text': 'REMOVE', 'width': 10, 'command': self.refremove_cb }, 'gridcfg': { 'sticky': 'we', 'row': 0, 'column': 0 } }) idf.append({ 'name': 'refoneup', 'parent': 'editnodes', 'widgetType': Tkinter.Button, 'tooltip': """Move the selected entry up one entry""", 'wcfg': { 'text': 'Move up', 'width': 10, 'command': self.refmoveup_cb }, 'gridcfg': { 'sticky': 'we', 'row': 1, 'column': 0 } }) idf.append({ 'name': 'refonedown', 'parent': 'editnodes', 'widgetType': Tkinter.Button, 'tooltip': """Move the selected entry down one entry""", 'wcfg': { 'text': 'Move down', 'width': 10, 'command': self.refmovedown_cb }, 'gridcfg': { 'sticky': 'we', 'row': 2, 'column': 0 } }) # RefNodes listchooser idf.append({ 'widgetType': ListChooser, 'name': 'refnodes', 'parent': 'editnodes', 'tooltip': """list of the reference nodes""", 'wcfg': { 'entries': [], 'mode': 'single', 'lbwcfg': { 'exportselection': 0 }, 'title': 'Reference Nodes' }, 'gridcfg': { 'sticky': 'we', 'row': 0, 'column': 1, 'rowspan': 3 } }) # MobNodes listchooser idf.append({ 'widgetType': ListChooser, 'name': 'mobnodes', 'parent': 'editnodes', 'tooltip': """list of the mobile nodes""", 'wcfg': { 'entries': [], 'mode': 'single', 'lbwcfg': { 'exportselection': 0 }, 'title': 'Mobile Nodes' }, 'gridcfg': { 'sticky': 'we', 'row': 0, 'column': 2, 'rowspan': 3 } }) idf.append({ 'name': 'mobremove', 'parent': 'editnodes', 'widgetType': Tkinter.Button, 'tooltip': """ Remove the selected mobile node""", 'wcfg': { 'text': 'REMOVE', 'width': 10, 'command': self.mobremove_cb }, 'gridcfg': { 'sticky': 'we', 'row': 0, 'column': 3 } }) idf.append({ 'name': 'moboneup', 'parent': 'editnodes', 'widgetType': Tkinter.Button, 'tooltip': """Move the selected entry up one entry""", 'wcfg': { 'text': 'Move up', 'width': 10, 'command': self.mobmoveup_cb }, 'gridcfg': { 'sticky': 'we', 'row': 1, 'column': 3 } }) idf.append({ 'name': 'mobonedown', 'parent': 'editnodes', 'widgetType': Tkinter.Button, 'tooltip': """Move the selected entry down one entry""", 'wcfg': { 'text': 'Move down', 'width': 10, 'command': self.mobmovedown_cb }, 'gridcfg': { 'sticky': 'we', 'row': 2, 'column': 3 } }) ############################################################### ## FILTERS ############################################################### idf.append({ 'name': "filter", 'widgetType': Pmw.Group, 'container': { 'filters': 'w.interior()' }, 'wcfg': { 'tag_text': "Apply Filters To The Ref/Mob nodes lists:" }, 'gridcfg': { 'sticky': 'wnse' } }) idf.append({ 'widgetType': Pmw.ComboBox, 'name': 'choice', 'parent': 'filters', 'tooltip': """This filter allows the user to choose which atom to consider from the ref node or mob nodes sets to create the atom pairs""", 'defaultValue': self.defaultFilter, 'wcfg': { 'scrolledlist_items': self.filters.keys(), 'selectioncommand': self.setDefault }, 'gridcfg': { 'sticky': 'w' } }) # If sets not of the same length: idf.append({ 'widgetType': Pmw.ComboBox, 'name': 'slice', 'parent': 'filters', 'defaultValue': 'Beginning', 'tooltip': """When the two sets of atoms are not of the same length the user can chose what subset of the longest set to take, beginning, the end or half and half""", 'wcfg': { 'scrolledlist_items': ['Beginning', 'End', 'Half/Half'], }, 'gridcfg': { 'sticky': 'w', 'row': -1 } }) return idf elif formName == 'pairs': idf = InputFormDescr(title="Pairwise Superimposition") # EDIT PAIRS GROUP idf.append({ 'name': "edit", 'widgetType': Pmw.Group, 'container': { 'edit': 'w.interior()' }, 'wcfg': { 'tag_text': "Edit Atom Pairs" }, 'gridcfg': { 'sticky': 'wnse' } }) entries = map(lambda x: (x, None), self.newPairs.keys()) idf.append({ 'widgetType': ListChooser, 'name': 'newpairs', 'parent': 'edit', 'wcfg': { 'mode': 'extended', 'entries': entries, 'lbwcfg': { 'exportselection': 1 }, 'title': 'Reference Atoms -- Mobile Atoms' }, 'gridcfg': { 'sticky': 'wens', 'columnspan': 2 } }) idf.append({ 'widgetType': Tkinter.Button, 'name': 'delete', 'parent': 'edit', 'wcfg': { 'width': 15, 'text': 'Add Pairs', 'command': self.add_cb }, 'gridcfg': { 'sticky': 'we' } }) idf.append({ 'widgetType': Tkinter.Button, 'name': 'delete', 'parent': 'edit', 'wcfg': { 'width': 15, 'text': 'Delete Pairs', 'command': self.delete_cb }, 'gridcfg': { 'sticky': 'we', 'row': -1 } }) idf.append({ 'name': "superimpose", 'widgetType': Pmw.Group, 'container': { 'superimpose': 'w.interior()' }, 'wcfg': { 'tag_text': "Superimposation parameters" }, 'gridcfg': { 'sticky': 'wnse' } }) # Continuous Superimposition idf.append({ 'widgetType': Tkinter.Checkbutton, 'name': 'continuous', 'parent': 'superimpose', 'wcfg': { 'variable': Tkinter.IntVar(), 'text': 'Continuous', 'command': self.continuous_cb, 'padx': 10, 'pady': 10 }, 'gridcfg': { 'sticky': 'w' } }) # Reset & SuperImpose button. idf.append({ 'widgetType': Tkinter.Button, 'name': 'final', 'parent': 'superimpose', 'wcfg': { 'width': 15, 'text': 'Superimpose', 'command': self.superimpose_cb }, 'gridcfg': { 'sticky': 'we', 'row': -1 } }) idf.append({ 'widgetType': Tkinter.Button, 'parent': 'superimpose', 'name': 'reset', 'wcfg': { 'text': 'Reset', 'command': self.reset_cb }, 'gridcfg': { 'sticky': 'we', 'row': -1 } }) idf.append({ 'widgetType': Tkinter.Button, 'name': 'dismiss', 'wcfg': { 'text': 'DISMISS', 'command': self.dismiss_cb }, 'gridcfg': { 'sticky': 'we', 'columnspan': 2 } }) return idf elif formName == 'editString': idf = InputFormDescr(title='Get Nodes From String') idf.append({ 'name': "refgroup", 'widgetType': Pmw.Group, 'container': { 'refgroup': 'w.interior()' }, 'wcfg': { 'tag_text': "Reference Nodes:" }, 'gridcfg': { 'sticky': 'wnse' } }) idf.append({ 'name': "mobgroup", 'widgetType': Pmw.Group, 'container': { 'mobgroup': 'w.interior()' }, 'wcfg': { 'tag_text': "Mobile Nodes:" }, 'gridcfg': { 'sticky': 'wnse', 'row': -1 } }) idf.append({ 'widgetType': StringSelectorGUI, 'parent': 'refgroup', 'name': 'srefNodes', #'defaultValue':self.vf.Mols[0].name+", , , ", 'tooltip': 'Please select the reference nodes set. By default the ref nodes will be the first molecule loaded in the viewer', 'wcfg': { 'molSet': self.vf.Mols, 'vf': self.vf, 'all': 1, 'crColor': (1., 0., 0.), 'forceEmpty': 1, }, 'gridcfg': { 'sticky': 'we' } }) idf.append({ 'widgetType': StringSelectorGUI, 'parent': 'mobgroup', #'defaultValue':self.vf.Mols[1].name+", , , ", 'tooltip': 'Please select the mobile nodes set. By default the mobile nodes will be the second molecule loaded in the viewer', 'name': 'smobNodes', 'wcfg': { 'molSet': self.vf.Mols, 'vf': self.vf, 'all': 1, 'crColor': (0., 0., 1.), 'forceEmpty': 1, }, 'gridcfg': { 'row': -1, 'sticky': 'we' } }) return idf
class AutoLigandCommand(MVCommand, MVAtomICOM): "GUI for AutoLigand: extends MVCommand, overwrites guiCallback" def __init__(self, func=None): MVCommand.__init__(self, func) MVAtomICOM.__init__(self) self.save = None self.showPlayer = False self.floodFile = None def onAddCmdToViewer(self): from DejaVu.Points import CrossSet self.startCross = CrossSet('StartCross', materials=((1., 1., 0), ), inheritMaterial=0, protected=True, offset=1.0, lineWidth=5, visible=0, pickable=0, listed=0) self.endCross = CrossSet('EndCross', materials=((0, 1, 1), ), inheritMaterial=0, protected=True, offset=1.0, lineWidth=5, visible=0, pickable=0, listed=0) from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.Box import Box from DejaVu.Spheres import Spheres from DejaVu import viewerConst from DejaVu.bitPatterns import patternList from opengltk.OpenGL import GL face = ((0, 3, 2, 1), (3, 7, 6, 2), (7, 4, 5, 6), (0, 1, 5, 4), (1, 2, 6, 5), (0, 4, 7, 3)) coords = ((1, 1, -1), (-1, 1, -1), (-1, -1, -1), (1, -1, -1), (1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1)) #new style RGB-> materials = ( (0, 0, 1), (0, 1, 0), (0, 0, 1), (0, 1, 0), (1, 0, 0), (1, 0, 0), ) box = IndexedPolygons('Box', materials=materials, vertices=coords, faces=face, inheritMaterial=0, visible=0, protected=True, listed=0) box.Set(frontPolyMode=GL.GL_LINE) box.Set(backPolyMode=GL.GL_LINE) box.Set(culling=GL.GL_NONE) box.inheritShading = 0 box.shading = GL.GL_FLAT box.Set(matBind=viewerConst.PER_PART) box.polygonstipple.Set(pattern=patternList[0]) box.Set(stipplePolygons=1) box.transparent = 0 self.box = box self.spheres = Spheres('Spheres', visible=0, inheritMaterial=0, radii=(0.3, ), protected=True, listed=0) self.halo = Spheres('Halo', visible=0, inheritMaterial=0, radii=(0.5, ), protected=True, listed=0) from DejaVu.Geom import Geom AutoLigand_geoms = Geom("AutoLigand_geoms", shape=(0, 0), listed=0) self.vf.GUI.VIEWER.AddObject(AutoLigand_geoms, parent=self.vf.GUI.miscGeom) self.vf.GUI.VIEWER.AddObject(self.startCross, parent=AutoLigand_geoms) self.vf.GUI.VIEWER.AddObject(self.endCross, parent=AutoLigand_geoms) self.vf.GUI.VIEWER.AddObject(self.box, parent=AutoLigand_geoms) self.vf.GUI.VIEWER.AddObject(self.spheres, parent=AutoLigand_geoms) self.vf.GUI.VIEWER.AddObject(self.halo, parent=AutoLigand_geoms) self.grids = {} self.vf.showCitation.citations["AutoLigand"] = """ Please acknowledge the use of the AutoLigand that results in any published work, including scientific papers, films and videotapes, by citing the following reference: Harris R, Olson AJ, Goodsell DS. Proteins. (2008) 70 1506.. """ def guiCallback(self, event=None): fileList = [] fld_list = glob.glob('*.maps.fld') if not fld_list: tkMessageBox.showinfo( "AutoLigand Info", "AutoLigand requires input AutoGrid maps. \nPlease click OK to select directory containing grid maps." ) folder = tkFileDialog.askdirectory(title="Select A Folder") if folder: os.chdir(folder) fld_list = glob.glob('*.maps.fld') else: return for fld in fld_list: fileList.append(fld.split('.')[0]) entryfield_value = "" if fileList: fileList.sort() entryfield_value = fileList[0] ifd = InputFormDescr(title="Run AutoLigand") ifd.append({ 'name': "fileName", 'widgetType': Pmw.Group, 'container': { 'fileName': 'w.interior()' }, 'wcfg': { 'tag_text': "Base Name for Receptor Map Files" }, }) ifd.append({ 'widgetType': Pmw.ComboBox, 'name': 'FileBaseName', 'parent': 'fileName', 'tooltip': 'FileBaseName = Just the name part from map files (i.e., FileBaseName.C.map)', 'wcfg': { 'dropdown': 1, 'scrolledlist_items': fileList, 'entryfield_value': entryfield_value, 'selectioncommand': self.selectGrid, 'labelpos': 'w', } }) ifd.append({ 'name': "nGroup", 'widgetType': Pmw.Group, 'container': { 'nGroup': 'w.interior()' }, 'tooltip': 'Number of heavy atom for ligand or number of fill points to use.', 'wcfg': { 'tag_text': "Number of " }, }) ifd.append({ 'widgetType': Pmw.RadioSelect, 'parent': 'nGroup', 'name': 'type', 'defaultValue': 'Points', 'listtext': ["Heavy Atoms", "Points"], }) ifd.append({ 'widgetType': Pmw.EntryField, 'parent': 'nGroup', 'name': 'number', 'wcfg': { 'labelpos': 'w', 'value': '100', 'validate': { 'validator': 'integer' } } }) ifd.append({ 'widgetType': Pmw.NoteBook, 'name': 'autoligandNotebook', 'container': { 'Single Fill': "w.page('Single Fill')", 'Connected Fill': "w.page('Connected Fill')", 'Scan': "w.page('Scan')" }, 'componentcfg': [ { 'name': 'Single Fill', 'cfg': {} }, { 'name': 'Connected Fill', 'cfg': {} }, { 'name': 'Scan', 'cfg': {} }, # {'raisecommand':self.pageChanged} ], 'wcfg': { 'raisecommand': self.pageChanged }, 'gridcfg': { 'sticky': 'we' }, }) #Single Fill ifd.append({ 'name': "StartLoc", 'parent': 'Single Fill', 'widgetType': Pmw.Group, 'container': { 'StartLoc': 'w.interior()' }, 'wcfg': { 'tag_text': "Start Location" }, }) ifd.append({ 'widgetType': ExtendedSliderWidget, 'name': 'gridPointsX', 'parent': 'StartLoc', 'wcfg': { 'label': 'X: ', 'width': 190, 'immediate': 1, 'command': self.changeStartCross, 'entrypackcfg': { 'side': 'left' }, }, }) ifd.append({ 'widgetType': ExtendedSliderWidget, 'name': 'gridPointsY', 'parent': 'StartLoc', 'wcfg': { 'label': 'Y: ', 'width': 190, 'immediate': 1, 'command': self.changeStartCross, 'entrypackcfg': { 'side': 'left' }, }, }) ifd.append({ 'widgetType': ExtendedSliderWidget, 'name': 'gridPointsZ', 'parent': 'StartLoc', 'wcfg': { 'label': 'Z: ', 'width': 190, 'immediate': 1, 'command': self.changeStartCross, 'entrypackcfg': { 'side': 'left' }, }, }) ifd.append({ 'name': "output", 'widgetType': Pmw.Group, 'parent': 'Single Fill', 'container': { 'output': 'w.interior()' }, 'wcfg': { 'tag_text': "Output Options" }, }) ifd.append({ 'name': 'pdbFile', 'tooltip': """Creates PDB_fill_#Nout1.pdb file where #N is the number of fill points.""", 'parent': 'output', 'widgetType': Tkinter.Checkbutton, 'defaultValue': 1, 'wcfg': { 'text': 'Create PDB of the Final Fill', 'state': 'disabled', }, 'gridcfg': { 'sticky': 'w' } }) ifd.append({ 'name': 'showProgress', 'parent': 'output', 'tooltip': """Save intermediate results in a file and open flood player when AutoLigand finishes.""", 'widgetType': Tkinter.Checkbutton, 'defaultValue': 0, 'wcfg': { 'text': 'Save Intermediate Results for Movie', 'variable': Tkinter.IntVar(), }, 'gridcfg': { 'sticky': 'w' } }) #Connected Fill ifd.append({ 'widgetType': Tkinter.Label, 'name': 'label', 'parent': 'Connected Fill', 'wcfg': { 'text': 'Select End Location for Connected Fill' } }) ifd.append({ 'name': "EndLoc", 'parent': 'Connected Fill', 'widgetType': Pmw.Group, 'container': { 'EndLoc': 'w.interior()' }, 'wcfg': { 'tag_text': "End Location" }, }) ifd.append({ 'widgetType': ExtendedSliderWidget, 'name': 'gridPointsXEnd', 'parent': 'EndLoc', 'wcfg': { 'label': 'X: ', 'width': 190, 'immediate': 1, 'command': self.changeEndCross, 'entrypackcfg': { 'side': 'left' }, }, }) ifd.append({ 'widgetType': ExtendedSliderWidget, 'name': 'gridPointsYEnd', 'parent': 'EndLoc', 'wcfg': { 'label': 'Y: ', 'width': 190, 'immediate': 1, 'command': self.changeEndCross, 'entrypackcfg': { 'side': 'left' }, }, }) ifd.append({ 'widgetType': ExtendedSliderWidget, 'name': 'gridPointsZEnd', 'parent': 'EndLoc', 'wcfg': { 'label': 'Z: ', 'width': 190, 'immediate': 1, 'command': self.changeEndCross, 'entrypackcfg': { 'side': 'left' }, }, }) #Connected Fill # ifd.append({'widgetType':Tkinter.Label, # 'name':'label', # 'parent':'Scan', # 'wcfg':{'text':"""Results from the Scan mode will #be available under\n"""+os.getcwd()} # }) ifd.append({ 'widgetType': Pmw.EntryField, 'parent': 'Scan', 'name': 'nFills', 'wcfg': { 'label_text': "Number of Fills:", 'labelpos': 'w', 'value': '10', 'validate': { 'validator': 'integer' } } }) def initselect(arg): self.selectGrid(entryfield_value) self.ifd = ifd self.save = self.vf.ICmdCaller.commands.value["Shift_L"] self.vf.setICOM(self, modifier="Shift_L", topCommand=0) self.vf.setIcomLevel(Atom) self.endCross.Set(visible=0) val = self.vf.getUserInput(ifd, modal=0, blocking=1, initFunc=initselect) if self.save: self.vf.setICOM(self.save, modifier="Shift_L", topCommand=0) self.save = None # import pdb;pdb.set_trace() if val: if not val['FileBaseName'][0]: msg = "AutoGrid files are missing.\n" msg += "Please generate grid maps. AutoLigand requires input AutoGrid maps." tkMessageBox.showerror("Error!", msg) return selection = self.ifd.entryByName['autoligandNotebook'][ 'widget'].getcurselection() cmdString = [sys.executable, AutoLigandPath] cmdString.append('-r') cmdString.append(val['FileBaseName'][0]) self.fileBaseName = val['FileBaseName'][0] if val['type'] == 'Points': cmdString.append('-p') cmdString.append(str(val['number'])) else: cmdString.append('-a') cmdString.append(str(val['number'])) val['number'] = 6 * int(val['number']) if selection in ['Single Fill', 'Connected Fill']: cmdString.append('-x') cmdString.append(str(val['gridPointsX'])) cmdString.append('-y') cmdString.append(str(val['gridPointsY'])) cmdString.append('-z') cmdString.append(str(val['gridPointsZ'])) if selection == 'Connected Fill': cmdString.append('-i') cmdString.append(str(val['gridPointsXEnd'])) cmdString.append('-j') cmdString.append(str(val['gridPointsYEnd'])) cmdString.append('-k') cmdString.append(str(val['gridPointsZEnd'])) if os.name == 'nt': #sys.platform == "win32": self.cmdTxt = subprocess.list2cmdline(cmdString) else: self.cmdTxt = ' '.join(cmdString) if val['showProgress']: self.cmdTxt += " -m" self.showPlayer = True else: self.showPlayer = False self.cmd = SysCmdInThread(self.cmdTxt, shell=True) self.cmd.start() self.checkResults() self.N_of_pts = val['number'] elif selection == "Scan": cmdString.append('-f') cmdString.append(str(val['nFills'])) if os.name == 'nt': #sys.platform == "win32": self.cmdTxt = subprocess.list2cmdline(cmdString) else: self.cmdTxt = ' '.join(cmdString) self.cmdTxt += ' &' #run in a background subprocess.Popen(self.cmdTxt, shell=True) tkMessageBox.showinfo("Success!", """AutoLigand launched successfully.""") else: self.hideGeoms() def pageChanged(self, name): if name == 'Single Fill': self.startCross.Set(visible=1) elif name == 'Connected Fill': self.endCross.Set(visible=1) else: self.startCross.Set(visible=0) self.endCross.Set(visible=0) def selectGrid(self, value): if not value: return lines = open(value + ".maps.fld").readlines() if not lines: return for line in lines: if line.startswith("#SPACING"): spacing = float(line.split()[-1]) if line.startswith("#NELEMENTS"): tmp = line.split() dimX = int(tmp[1]) dimY = int(tmp[2]) dimZ = int(tmp[3]) if line.startswith("#CENTER"): tmp = line.split() centerX = float(tmp[1]) centerY = float(tmp[2]) centerZ = float(tmp[3]) #this variables are the same used in AutoLigand.py self.xcent = int(dimX / 2) self.ycent = int(dimY / 2) self.zcent = int(dimZ / 2) self.centerx = centerX self.centery = centerY self.centerz = centerZ self.spacing = spacing c = [centerX, centerY, centerZ] xlen = round(spacing * dimX, 4) ylen = round(spacing * dimY, 4) zlen = round(spacing * dimZ, 4) self.minX = c[0] - xlen * 0.5 self.maxX = c[0] + xlen * 0.5 if self.grids.has_key(value): centerX = self.grids[value][0] centerY = self.grids[value][1] centerZ = self.grids[value][2] self.ifd.entryByName['gridPointsX']['widget'].configure( minval=self.minX, maxval=self.maxX, ) self.ifd.entryByName['gridPointsXEnd']['widget'].configure( minval=self.minX, maxval=self.maxX, ) self.minY = c[1] - ylen * 0.5 self.maxY = c[1] + ylen * 0.5 self.ifd.entryByName['gridPointsY']['widget'].configure( minval=self.minY, maxval=self.maxY, ) self.ifd.entryByName['gridPointsYEnd']['widget'].configure( minval=self.minY, maxval=self.maxY, ) self.minZ = c[2] - zlen * 0.5 self.maxZ = c[2] + zlen * 0.5 self.ifd.entryByName['gridPointsZ']['widget'].configure( minval=self.minZ, maxval=self.maxZ, ) self.ifd.entryByName['gridPointsZEnd']['widget'].configure( minval=self.minY, maxval=self.maxY, ) self.startCross.Set(vertices=((centerX, centerY, centerZ), )) self.ifd.entryByName['gridPointsX']['widget'].set(centerX) self.ifd.entryByName['gridPointsY']['widget'].set(centerY) self.ifd.entryByName['gridPointsZ']['widget'].set(centerZ) self.ifd.entryByName['gridPointsXEnd']['widget'].set(centerX + 12) self.ifd.entryByName['gridPointsYEnd']['widget'].set(centerY + 12) self.ifd.entryByName['gridPointsZEnd']['widget'].set(centerZ + 12) self.endCross.Set(vertices=((centerX + 12, centerY + 12, centerZ + 12), )) pts = [(self.maxX, self.maxY, self.minZ), (self.minX, self.maxY, self.minZ), (self.minX, self.minY, self.minZ), (self.maxX, self.minY, self.minZ), (self.maxX, self.maxY, self.maxZ), (self.minX, self.maxY, self.maxZ), (self.minX, self.minY, self.maxZ), (self.maxX, self.minY, self.maxZ)] self.box.Set(visible=1) #self.startCross.Set(visible=1) self.box.vertexSet.vertices.array[:] = pts self.box.RedoDisplayList() self.vf.GUI.VIEWER.Normalize_cb() self.vf.GUI.VIEWER.Redraw() def changeStartCross(self, val): centerX = self.ifd.entryByName['gridPointsX']['widget'].get() centerY = self.ifd.entryByName['gridPointsY']['widget'].get() centerZ = self.ifd.entryByName['gridPointsZ']['widget'].get() grid = self.ifd.entryByName['FileBaseName']['widget'].get() if grid: self.grids[grid] = [centerX, centerY, centerZ] self.startCross.Set(visible=1) self.startCross.Set(vertices=((centerX, centerY, centerZ), )) self.vf.GUI.VIEWER.Redraw() def changeEndCross(self, val): centerX = self.ifd.entryByName['gridPointsXEnd']['widget'].get() centerY = self.ifd.entryByName['gridPointsYEnd']['widget'].get() centerZ = self.ifd.entryByName['gridPointsZEnd']['widget'].get() grid = self.ifd.entryByName['FileBaseName']['widget'].get() #self.endCross.Set(visible=1) self.endCross.Set(vertices=((centerX, centerY, centerZ), )) self.vf.GUI.VIEWER.Redraw() def checkResults(self): """Checks the queue for results until we get one""" if self.cmd.ok.configure()['state'][-1] == 'normal': if self.showPlayer: self.openPklData() else: molName = "FILL_" + str(self.N_of_pts) + "out1" if os.path.exists(molName + ".pdb"): self.vf.readMolecule(molName + ".pdb") self.vf.displaySticksAndBalls( molName, cradius=0.0, sticksBallsLicorice="Sticks and Balls") self.vf.displayLines(molName, negate=True, displayBO=False) self.vf.colorByAtomType(molName, ['sticks', 'balls']) self.vf.GUI.ROOT.after(2050, self.hideGeoms) return self.vf.GUI.ROOT.after(100, self.checkResults) def hideGeoms(self): self.box.Set(visible=0) self.startCross.Set(visible=0) self.endCross.Set(visible=0) self.spheres.Set(visible=0) self.halo.Set(visible=0) def __call__(self, atom, **kw): if not atom: return 'ERROR' atoms = self.vf.expandNodes(atom) if not atoms: return 'ERROR' atoms = atoms.findType(Atom) if not atoms: return 'ERROR' apply(self.doitWrapper, (atoms, ), kw) def doit(self, atoms=None): if len(atoms) == 0: return atom = atoms[0] if self.minX < atom.coords[0] > self.maxX: return if self.minY < atom.coords[1] > self.maxY: return if self.minZ < atom.coords[2] > self.maxZ: return selection = self.ifd.entryByName['autoligandNotebook'][ 'widget'].getcurselection() if selection == "Single Fill": self.ifd.entryByName['gridPointsX']['widget'].set(atom.coords[0]) self.ifd.entryByName['gridPointsY']['widget'].set(atom.coords[1]) self.ifd.entryByName['gridPointsZ']['widget'].set(atom.coords[2]) # self.startCross.Set(visible=1) self.startCross.Set(vertices=((atom.coords[0], atom.coords[1], atom.coords[2]), )) elif selection == "Connected Fill": self.ifd.entryByName['gridPointsXEnd']['widget'].set( atom.coords[0]) self.ifd.entryByName['gridPointsYEnd']['widget'].set( atom.coords[1]) self.ifd.entryByName['gridPointsZEnd']['widget'].set( atom.coords[2]) self.endCross.Set(vertices=((atom.coords[0], atom.coords[1], atom.coords[2]), )) self.vf.GUI.VIEWER.Redraw() def openPklData(self): self.vf.AutoLigandMovieCommand(self.fileBaseName + '_flood.pkl')
class MeasureTorsionGUICommand(MeasureGUICommand): """Label torsion between four atoms (color coded cyan) Accumulates picked atoms.Draws polygons and labels showing the torsion angle between groups of 4 selected atoms (color-coded cyan).Userpref 'measureTorsionSL' sets the 'snakeLength' which is how many torsion measureDisplays can be seen at the same time.When more than that number are measured, the first torsion measured is no longer labeled. \nPackage : Pmv \nModule : measureCommands \nClass : MeasureTorsionGUICommand \nCommand : measureTorsionGC \nSynopsis:\n torsion/None<---measureTorsionGC(atoms) \nRequired Argument:\n atoms --- the atom(s) \ntorsion --- returned when the number of atoms is a multiple of 4 """ def __init__(self, func=None): MeasureGUICommand.__init__(self, func=func) self.flag = self.flag | self.objArgOnly def onAddCmdToViewer(self): 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('measureAngle'): self.vf.loadCommand('measureCommands', 'measureAngle', 'Pmv', topCommand=0) self.masterGeom = Geom('measureTorsionGeom', shape=(0, 0), pickable=0, protected=True) self.masterGeom.isScalable = 0 if self.vf.hasGui: measure_geoms = check_measure_geoms(self.vf.GUI) self.vf.GUI.VIEWER.AddObject(self.masterGeom, parent=measure_geoms) self.lines = IndexedPolygons('torsionLine', materials=((0, 1, 1), ), culling=GL.GL_NONE, inheritStipplePolygons=0, inheritMaterial=0, stipplePolygons=1, backPolyMode=GL.GL_FILL, frontPolyMode=GL.GL_FILL, protected=True, pickable=0) if self.vf.userpref['Sharp Color Boundaries for MSMS'][ 'value'] == 'blur': self.lines.Set( inheritSharpColorBoundaries=False, sharpColorBoundaries=False, ) self.lines.polygonstipple.Set(pattern=pat3) #self.lines.polygonstipple.Set(pattern=pat3, tagModified=False) #self.lines.RenderMode(GL.GL_FILL) #self.lines.RenderMode(GL.GL_FILL, face=GL.GL_BACK) self.labels = GlfLabels(name='torsionLabel', shape=(0, 3), font='arial1.glf', fontStyle='solid3d', fontScales=(.5, .5, .3), inheritMaterial=0, materials=((0, 1, 1), )) self.spheres = Spheres(name='torsionSpheres', shape=(0, 3), inheritMaterial=0, radii=0.2, quality=15, materials=((0., 1., 1.), ), protected=True) if self.vf.hasGui: for item in [self.lines, self.labels, self.spheres]: self.vf.GUI.VIEWER.AddObject(item, parent=self.masterGeom) doc = """Number of labeled torsions displayed. Valid values are integers>0""" self.vf.userpref.add('Measured Torsions', 4, callbackFunc=[self.setLength_cb], category="Molecules", validateFunc=lambda x: x > 0, doc=doc) #used after startICOM is invoked doc = """Continuous update of torsions if 'transformRoot only' is turned off and viewer's current object is not Root.""" choices = ['yes', 'no'] self.vf.userpref.add('Continuous Update Torsion', 'yes', choices, callbackFunc=[self.continuousUpdate_cb], category="Molecules", doc=doc) self.snakeLength = 4 def __call__(self, atoms, **kw): """torsion/None<-measureTorsionGC(atoms) \natoms --- the atom(s) \ntorsion --- returned when the number of atoms is a multiple of 4""" if type(atoms) is types.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): for at in ats: lenAts = len(self.atomList) if lenAts and lenAts % 4 != 0 and at == self.atomList[-1]: continue self.atomList.append(at) if len(self.atomList) > 4 * self.snakeLength: self.atomList = self.atomList[4:] self.update() if len(self.labelStrs) and len(self.atomList) % 4 == 0: return float(self.labelStrs[-1]) def update(self, forward=1, event=None): if not len(self.atomList): self.spheres.Set(vertices=[]) #self.spheres.Set(vertices=[], tagModified=False) self.labels.Set(vertices=[]) #self.labels.Set(vertices=[], tagModified=False) self.lines.Set(vertices=[]) #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: if len(self.lineVertices) % 4: self.spheres.Set( vertices=self.lineVertices[-(len(self.lineVertices) % 4):]) else: self.spheres.Set(vertices=[]) #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=[]) #self.labels.Set(vertices=[], tagModified=False) self.lines.Set(vertices=[]) #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 = self.atomList[i * 4] at1 = self.atomList[i * 4 + 1] at2 = self.atomList[i * 4 + 2] at3 = self.atomList[i * 4 + 3] torsion = self.vf.measureTorsion(at0, at1, at2, at3, topCommand=0) 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) #to reset labels, lines and fan, EACH TIME self.labels.Set(vertices=self.labelCenters, labels=self.labelStrs) #tagModified=False) #if len(self.lineVertices)%4!=0: #self.lineVertices = self.lineVertices[:numItems*4] #only draw lines in groups of 4 #numItems*4 if len(self.atomList) % 4 == 0: faces = range(numItems * 4) faces = Numeric.reshape(faces, (-1, 4)) ###FIX THIS ###on undo: if you have just wrapped, undoing the next pt ###breaks because trying to set the vertices uses the old ###faces if not forward: self.lines.Set(vertices=[], faces=[]) #self.lines.Set(vertices=[], faces=[], tagModified=False) self.lines.Set(vertices=self.lineVertices, faces=faces, freshape=1) #freshape=1, tagModified=False) self.vf.GUI.VIEWER.Redraw() else: #this only works going forward: undo breaks here if len(self.lines.faceSet.faces.array) > numItems: faces = range((numItems + 1) * 4) faces = Numeric.reshape(faces, (-1, 4)) if forward: faces = faces[1:] else: faces = faces[:-1] self.lines.Set(faces=faces) self.vf.GUI.VIEWER.Redraw()
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
class MeasureAngleGUICommand(MeasureGUICommand): """Accumulates picked atoms.Draws fans, lines and labels labelling the angle between trios of selected atoms (color-coded orange).Userpref 'measureAngleSL' sets the 'snakeLength' which is how many angle measureDisplays can be seen at the same time.When more than that number are measured, the first angle measured is no longer labeled. \nPackage : Pmv \nModule : measureCommands \nClass : MeasureAngleGUICommand \nCommand : measureAngleGC \nSynopsis:\n angle/None<---measureAngleGC(atoms) \nRequired Argument:\n atoms --- atom(s) \nangle --- returned when the number of atoms is a multiple of 3 """ def __init__(self, func=None): MeasureGUICommand.__init__(self, func=func) self.flag = self.flag | self.objArgOnly def onAddCmdToViewer(self): from DejaVu.Arcs3D import Fan3D from DejaVu.bitPatterns import pat3 self.arcNormals = [] self.arcVectors = [] self.arcCenters = [] if not self.vf.commands.has_key('setICOM'): self.vf.loadCommand('interactiveCommands', 'setICOM', 'Pmv', topCommand=0) if not self.vf.commands.has_key('measureAngle'): self.vf.loadCommand('measureCommands', 'measureAngle', 'Pmv', topCommand=0) self.masterGeom = Geom('measureAngleGeom', shape=(0, 0), pickable=0, protected=True) self.masterGeom.isScalable = 0 if self.vf.hasGui: measure_geoms = check_measure_geoms(self.vf.GUI) self.vf.GUI.VIEWER.AddObject(self.masterGeom, parent=measure_geoms) self.lines = IndexedPolylines('angleLine', materials=((1, .5, 0), ), inheritMaterial=0, lineWidth=3, stippleLines=1, protected=True, pickable=0) self.fan = Fan3D('angles', materials=((1, .5, 0), ), culling=GL.GL_NONE, inheritMaterial=0, stipplePolygons=1, radii=(1., ), inheritStipplePolygons=0, backPolyMode=GL.GL_FILL, pickable=0) self.fan.polygonstipple.Set(pattern=pat3) #self.fan.polygonstipple.Set(pattern=pat3, tagModified=False) #self.fan.RenderMode(GL.GL_FILL) #self.fan.RenderMode(GL.GL_FILL, face=GL.GL_BACK) self.labels = GlfLabels(name='angleLabel', shape=(0, 3), font='arial1.glf', fontStyle='solid3d', fontScales=(.5, .5, .3), inheritMaterial=0, materials=((1., .5, 0.), )) self.spheres = Spheres(name='angleSpheres', shape=(0, 3), inheritMaterial=0, radii=0.2, quality=15, materials=((1., .5, 0.), ), protected=True) if self.vf.hasGui: for item in [self.lines, self.labels, self.spheres, self.fan]: self.vf.GUI.VIEWER.AddObject(item, parent=self.masterGeom) doc = """Number of labeled angles displayed. Valid values are integers>0""" self.vf.userpref.add('Number of Measure Angles', 4, callbackFunc=[self.setLength_cb], category="Molecules", validateFunc=lambda x: x > 0, doc=doc) #used after startICOM is invoked doc = """Continuous update of angles if 'transformRoot only' is turned off and viewer's current object is not Root.""" choices = ['yes', 'no'] self.vf.userpref.add('Continuous Update Angle', 'yes', choices, callbackFunc=[self.continuousUpdate_cb], category="Molecules", doc=doc) self.snakeLength = 4 def __call__(self, atoms, **kw): """angle/None<---measureAngleGC(atoms) \natoms --- atom(s) \nangle --- returned when the number of atoms is a multiple of 3""" if type(atoms) is types.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): for at in ats: lenAts = len(self.atomList) if lenAts and lenAts % 3 != 0 and at == self.atomList[-1]: continue self.atomList.append(at) l = len(self.atomList) #for this command, reset after every 3 #wrap when len(atoms)=3*self.snakeLength+1 if l > 3 * self.snakeLength: self.atomList = self.atomList[3:] self.update() if len(self.labelStrs) and len(self.atomList) % 3 == 0: return float(self.labelStrs[-1]) def update(self, forward=1, event=None): if not len(self.atomList): self.spheres.Set(vertices=[]) #self.spheres.Set(vertices=[], tagModified=False) self.labels.Set(vertices=[]) #self.labels.Set(vertices=[], tagModified=False) self.lines.Set(vertices=[]) #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: if len(self.lineVertices) % 3: self.spheres.Set( vertices=self.lineVertices[-(len(self.lineVertices) % 3):]) else: self.spheres.Set(vertices=[]) #self.spheres.Set(vertices=self.lineVertices, tagModified=False) self.vf.GUI.VIEWER.Redraw() #label with angle #lines between spheres are only drawn when angle completed #that is, len(ats)%3=0 if len(self.lineVertices) < 3: self.labels.Set(vertices=[]) #self.labels.Set(vertices=[], tagModified=False) self.fan.Set(vertices=[]) #self.fan.Set(vertices=[], tagModified=False) self.lines.Set(vertices=[]) #self.lines.Set(vertices=[], tagModified=False) else: #should all of these be reset? self.arcNormals = [] self.arcVectors = [] self.arcCenters = [] self.labelCenters = [] self.labelStrs = [] #rebuild arcNormals, arcVectors, arcCenters #labelCenters, labelStrs, #this gets done lenATs/3 times numItems = len(self.atomList) / 3 for i in range(numItems): at0 = self.atomList[i * 3] at1 = self.atomList[i * 3 + 1] at2 = self.atomList[i * 3 + 2] ang = self.vf.measureAngle(at0, at1, at2, topCommand=0) v, n = self.normal(at0, at1, at2) self.arcNormals.append(n) #self.arcNormals = self.arcNormals[-limit:] self.arcVectors.append(v) #self.arcVectors = self.arcVectors[-limit:] self.arcCenters.append(self.getTransformedCoords(at1)) #self.arcCenters = self.arcCenters[-limit:] angLabel = '%.3f' % ang self.labelStrs.append(angLabel) c0 = self.getTransformedCoords(at0) c1 = self.getTransformedCoords(at2) newcenter = tuple((c0 + c1) / 2.0) self.labelCenters.append(newcenter) #to reset labels, lines and fan, EACH TIME self.labels.Set(vertices=self.labelCenters, labels=self.labelStrs) #tagModified=False) faces = range(numItems * 3) faces = Numeric.reshape(faces, (-1, 3)) self.lines.Set(vertices=self.lineVertices, type=GL.GL_LINE_STRIP, faces=faces, freshape=1) #faces=faces, freshape=1, tagModified=False) self.fan.angles = map(float, self.labelStrs) self.fan.vectors = self.arcVectors self.fan.Set(vertices=self.arcCenters, vnormals=self.arcNormals) #tagModified=False) def normal(self, at0, at1, at2): c0 = self.getTransformedCoords(at0) c1 = self.getTransformedCoords(at1) c2 = self.getTransformedCoords(at2) v1 = c1 - c0 v2 = c1 - c2 l1 = math.sqrt(Numeric.sum(v1 * v1)) l2 = math.sqrt(Numeric.sum(v2 * v2)) #FIXME #protect against divide by 0 n = self.vvmult(v1 / l1, v2 / l2) n = n / math.sqrt(Numeric.sum(n * n)) return -v2 / l2, n.astype('f')
class MeasureDistanceGUICommand(MeasureGUICommand): """ This command measures distance between atoms. Lines are drawn between pairs of consecutively picked atoms and labels are display showing the distance. \nPackage : Pmv \nModule : measureCommands \nClass : MeasureDistanceGUICommand \nCommand : measureDistanceGC \nSynopsis:\n distance/None<---measureDistanceGC(atoms) \nRequired Argument:\n atoms --- atom(s) """ def __init__(self, func=None): MeasureGUICommand.__init__(self, func=func) self.flag = self.flag | self.objArgOnly def guiCallback(self, event=None): MeasureGUICommand.guiCallback(self, event) self.vf.setICOM(self.vf.measureDistGUI, modifier='Control_L', topCommand=0) 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('measureDistance'): self.vf.loadCommand('measureCommands', 'measureDistance', 'Pmv', topCommand=0) self.masterGeom = Geom('measureDistGeom', shape=(0, 0), pickable=0) self.masterGeom.isScalable = 0 if self.vf.hasGui: measure_geoms = check_measure_geoms(self.vf.GUI) self.vf.GUI.VIEWER.AddObject(self.masterGeom, parent=measure_geoms) self.lines = IndexedPolylines('distLine', materials=((1, 1, 0), ), inheritMaterial=0, lineWidth=3., stippleLines=1, pickable=0) self.labels = GlfLabels(name='distLabel', shape=(0, 3), font='arial1.glf', fontStyle='solid3d', fontScales=(.5, .5, .3), inheritMaterial=0, materials=((1, 1, 0), )) self.spheres = Spheres(name='distSpheres', shape=(0, 3), inheritMaterial=0, radii=0.2, quality=15, materials=((1., 1., 0.), )) if self.vf.hasGui: for item in [self.lines, self.labels, self.spheres]: self.vf.GUI.VIEWER.AddObject(item, parent=self.masterGeom) def __call__(self, atoms, **kw): """distance/None<---measureDistanceGC(atoms) \natoms --- atom(s)""" if type(atoms) is types.StringType: self.nodeLogString = "'" + atoms + "'" ats = self.vf.expandNodes(atoms) if not len(ats): return 'ERROR' return self.doitWrapper(*(ats, ), **kw) def doit(self, ats): for at in ats: lenAts = len(self.atomList) if lenAts and at == self.atomList[-1]: continue self.atomList.append(at) self.update() if len(self.labelStrs): return float(self.labelStrs[-1]) def update(self, forward=1, event=None): if not len(self.atomList): self.spheres.Set(vertices=[]) #self.spheres.Set(vertices=[], tagModified=False) self.labels.Set(vertices=[]) #self.labels.Set(vertices=[], tagModified=False) self.lines.Set(vertices=[]) #self.lines.Set(vertices=[], tagModified=False) return self.lineVertices = [] #each time have to recalculate lineVertices for at in self.atomList: c1 = self.getTransformedCoords(at) self.lineVertices.append(tuple(c1)) if len(self.lineVertices) % 2: self.spheres.Set(vertices=[self.lineVertices[-1]]) else: self.spheres.Set(vertices=[]) #self.spheres.Set(vertices=self.lineVertices, tagModified=False) #setting spheres doesn't trigger redraw so do it explicitly self.vf.GUI.VIEWER.Redraw() #each time have to recalculate labelCenters and labelStrs if len(self.lineVertices) > 1: self.labelCenters = [] self.labelStrs = [] self.faces = [] numLabels = len(self.lineVertices) - 1 for i in range(0, numLabels, 2): c0 = Numeric.array(self.lineVertices[i]) c1 = Numeric.array(self.lineVertices[i + 1]) newCenter = tuple((c1 + c0) / 2.0) self.labelCenters.append(newCenter) at1 = self.atomList[i] at2 = self.atomList[i + 1] d = self.vf.measureDistance(at1, at2, topCommand=0) dLabel = '%.3f' % d self.labelStrs.append(dLabel) self.faces.append([i, i + 1]) #correct length of labels here self.labels.Set(vertices=self.labelCenters, labels=self.labelStrs) #tagModified=False) self.lines.Set(vertices=self.lineVertices, type=GL.GL_LINE_STRIP, faces=self.faces, freshape=1) #tagModified=False) elif len(self.lineVertices) == 1 and len(self.labelCenters) == 1: #this fixes case of stepping back over 1st label self.labels.Set(vertices=[]) #self.labels.Set(vertices=[], tagModified=False) self.lines.Set(vertices=[])
class SuperImposeAtomsGUICommand(MVCommand, MVAtomICOM): """ The SuperImposeAtomsGUICommand provides a GUI interface to the SuperImposeAtomsCommand. - For now Only two 2 sets of Atoms belonging to a ref molecule and a mobile molecule can be superimposed simultaneously. - The command provides two way of defining those two sets of atoms: * By picking nodes at the different levels (Molecule, Chain, Residue, Atom) the first pick will define the reference set and the second the mobile set. The picking process will have be done later on the same way and defines a list of pairs of atoms. If the user drags a box only the first node will be considered. Nodes are then converted into an set of Atoms. The 'Edit Atoms Pairs' allows the user to see the pairs but also to alter those sets. For example only the backbone atoms can be considered or all atoms etc. The user can also create his own filter by typing a lambda function in the entry of the combobox. If the 2 sets are not of the same length the extra atoms can be removed either from the beginning, the end or half and half of the longest set allowing a bit more flexibility. If the resulting 2 sets are None then the superimposition cannot be computed. You can reset the process and start over or alter your set using the tools described above. * By string: If the user knows the set of nodes of respectively the reference molecule and mobile molecule to be use for the computation two string selector widgets allows him to proceed more efficiently. - Known bug: * If the reference molecule is transformed independently of the mobile molecule the mobile molecule will be superimposed onto the original location of the reference molecule. (Working on it) * Cannot superimpose simultaneously multiple sets of molecule. * And probably many more .... """ def __init__(self, func=None): MVCommand.__init__(self, func) MVAtomICOM.__init__(self) self.refAtomList = [] self.inAtomList = [] #self.superImposedPairs = {} self.newPairs = {} self.pair = [] self.mobMolName = None self.refMolName = None self.filters = {'CA Atoms':lambda x: x.name == 'CA', 'Backbone Atoms': lambda x: x.name in ['CA', 'C', 'N', 'O', 'CA@A','C@A', 'N@A','O@A'], 'Heavy Atoms': lambda x: not x.element == 'H', 'All Atoms': None} self.defaultFilter = 'Backbone Atoms' def onAddCmdToViewer(self): # Check first is any of the command that superimpose depends on are # already loaded. if not self.vf.commands.has_key('setICOM'): self.vf.loadCommand('interactiveCommands', 'setICOM', 'Pmv', topCommand = 0) if not self.vf.commands.has_key('superimposeAtoms'): self.vf.loadCommand('superImposeCommands', 'superimposeAtoms', 'Pmv', topCommand = 0) if not self.vf.commands.has_key('startContinuousPicking'): self.vf.loadCommand('dejaVuCommands','startContinuousPicking', 'ViewerFramework', topCommand = 0) if not self.vf.commands.has_key('stopContinuousPicking'): self.vf.loadCommand('dejaVuCommands','stopContinuousPicking', 'ViewerFramework', topCommand = 0) if not self.vf.commands.has_key('labelByExpression'): self.vf.loadCommand('labelCommands', 'labelByExpression', 'Pmv', topCommand = 0) self.sphere1 = Spheres(name='elt1', radii=0.5, materials = ( (0.,1.,0.),), protected=True) self.sphere2 = Spheres(name = 'elt2', radii=0.5, materials = ( (1.,1.,0.),), protected=True) #self.form = None def onRemoveObjectFromViewer(self,obj): if hasattr(self.vf,'alignment'): self.vf.alnEditor.deleteSequence(obj.name) self.vf.alnEditor.redraw() if obj.name == self.refMolName: self.refMolName=None if obj.name == self.mobMolName: self.mobMolName=None def guiCallback(self): self.vf.setICOM(self, modifier="Shift_L", topCommand=0) def buildFormDescr(self, formName): if formName == 'superimpose': idf = InputFormDescr(title="Set Superimposition Parameters") idf.append( {'widgetType':Tkinter.Label, 'wcfg': {'text':'Get Nodes:'}, 'gridcfg':{'sticky':'w'}}) self.typeVar = Tkinter.StringVar() self.typeVar.set('By Picking') idf.append( {'widgetType':Tkinter.Radiobutton, 'name': 'string', 'wcfg':{'variable':self.typeVar, 'text': 'From String', 'value':'From String', 'command':self.string_cb, }, 'gridcfg':{'sticky':'w', 'columnspan':3}}) idf.append( {'widgetType':Tkinter.Radiobutton, 'name': 'string', 'wcfg':{'variable':self.typeVar, 'text': 'From Alignment', 'value':'From Alignment', 'command':self.alignment_cb, }, 'gridcfg':{'sticky':'w', 'columnspan':3}}) idf.append( {'widgetType':Tkinter.Radiobutton, 'name': 'refPicking', 'wcfg':{'variable':self.typeVar, 'text': 'By Picking', 'value':'By Picking', }, 'gridcfg':{'sticky':'w'} }) idf.append( {'widgetType':Tkinter.Label, 'wcfg': {'text':'Reference nodes:'}, 'gridcfg':{'sticky':'w'}}) idf.append( {'widgetType':Tkinter.Label, 'wcfg': {'text':'Mobile nodes:'}, 'gridcfg':{'sticky':'e', 'row':-1}}) idf.append({'widgetType':Tkinter.Label, 'name':'firstNode', 'wcfg':{ 'text':''}, 'gridcfg':{'sticky':'we'}}) idf.append({'widgetType': Tkinter.Label, 'name':'secondNode', 'wcfg':{ 'text':''}, 'gridcfg':{'sticky':'we', 'row':-1}}) idf.append({'widgetType':Tkinter.Button, 'name':'editPairs', 'wcfg':{'text':'Edit Ref Atom -- Mob Atom Pairs', 'command':self.editPairs_cb,}, 'gridcfg':{'sticky':'we','columnspan':3} }) # Continuous Superimposition idf.append({'widgetType':Tkinter.Checkbutton, 'name':'continuous', 'wcfg':{'variable':Tkinter.IntVar(), 'text':'Continuous Superimposition', 'command':self.continuous_cb, 'padx':10,'pady':10}, 'gridcfg':{'sticky':'w'}}) # Reset & SuperImpose button. idf.append({'widgetType':Tkinter.Button, 'name':'final', 'wcfg':{'width':15,'text':'Superimpose', 'command':self.superimpose_cb}, 'gridcfg':{'sticky':'we', 'row':-1}}) idf.append({'widgetType':Tkinter.Button, 'name':'reset', 'wcfg':{'text':'Reset', 'command':self.reset_cb}, 'gridcfg':{'sticky':'we', 'row':-1}}) elif formName == 'editPair': idf = InputFormDescr(title='Edit Reference Atom - Mobile Atom Pairs') idf.append({'widgetType':Pmw.ComboBox, 'name':'choice', 'defaultValue':self.defaultFilter, 'wcfg': {'label_text':'Atoms to be consider for superimposition:', 'labelpos':'n','label_padx':10,'label_pady':10, 'scrolledlist_items': self.filters.keys(), 'selectioncommand':self.setDefault}, 'gridcfg':{'sticky':'w'}}) # If sets not of the same length: idf.append({'widgetType':Pmw.ComboBox, 'name':'slice', 'defaultValue':'Beginning', 'wcfg': {'label_text':'Sets not of the same length', 'labelpos':'n','label_padx':10,'label_pady':10, 'scrolledlist_items':['Beginning', 'End', 'Half/Half'] }, 'gridcfg':{'sticky':'w', 'row':-1}}) entries = map(lambda x: (x, None), self.newPairs.keys()) idf.append({'widgetType':ListChooser, 'name':'newpairs', 'wcfg':{'mode':'extended', 'entries':entries, 'lbwcfg':{'exportselection':1}, 'title':'Reference Atoms -- Mobile Atoms'}, 'gridcfg':{'sticky':'wens', 'columnspan':2}}) idf.append({'widgetType':Tkinter.Button, 'name': 'delete', 'wcfg':{'width':15,'text': 'Delete Pairs', 'command':self.delete_cb}, 'gridcfg':{'sticky':'we', 'columnspan':2}}) idf.append({'widgetType':Tkinter.Button, 'name': 'dismiss', 'wcfg':{'text': 'DISMISS', 'command':self.dismiss_cb}, 'gridcfg':{'sticky':'we', 'columnspan':2}}) elif formName == 'editString': idf = InputFormDescr(title = 'Get Nodes From String') idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':'Reference Nodes: '}, 'gridcfg':{'sticky':'w'}}) idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':'Mobile Nodes: '}, 'gridcfg':{'sticky':'w', 'row':-1}}) idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':' '}, 'gridcfg':{'columnspan':2, 'sticky':'w'}}) idf.append({ 'widgetType':StringSelectorGUI, 'name':'refNodes','required':1, 'wcfg':{ 'molSet': self.vf.Mols, 'vf': self.vf, 'all':1, 'crColor':(1.,0.,0.), }, 'gridcfg':{'sticky':'we' }}) idf.append({ 'widgetType':StringSelectorGUI, 'name':'mobNodes','required':1, 'wcfg':{ 'molSet': self.vf.Mols, 'vf': self.vf, 'all':1, 'crColor':(0.,0.,1.), }, 'gridcfg':{'row':-1, 'sticky':'we' }}) return idf def initICOM(self, modifier): # Create the form if not existing yet form = self.showForm(formName = 'superimpose', modal=0, blocking=0) self.firstLabel = form.descr.entryByName['firstNode']['widget'] self.secondLabel = form.descr.entryByName['secondNode']['widget'] self.contVar = form.descr.entryByName['continuous']['wcfg']['variable'] self.pairForm = None # set the callback of continuousPicking to label the picked node # 1- get a handle on the cbManager cbManager = self.vf.startContinuousPicking.cbManager # 2- Save the existing callbacks self.oldCallBacks = cbManager.callbacks # 3- Set to the new callback cbManager.SetCallback(CallBackFunction(self.labelByName)) self.vf.startContinuousPicking() self.supcb = 0 def setDefault(self, text): self.defaultFilter = text if hasattr(self, 'pair') and len(self.pair) == 2: filter = self.filters[text] set1 = self.pair[0] set2 = self.pair[1] if filter: set1 = set1.get(filter) set2 = set2.get(filter) if (set1 and set2) and (len(set1) == len(set2)): self.updateChooser(set1, set2) def editPairs_cb(self, event=None): pairForm = self.showForm('editPair', force = 1, modal=0, blocking=0, onDestroy= self.dismiss_cb) # show panel with the listchooser of the panel and # Choose the atoms to do the superimposition self.chooser = pairForm.descr.entryByName['newpairs']['widget'] def dismiss_cb(self, event=None): if self.cmdForms.has_key('editPair'): self.cmdForms['editPair'].destroy() del self.cmdForms['editPair'] def string_cb(self, event=None): #get rid of the alignment GUI if hasattr(self.vf,'alnEditor'): self.vf.alnEditor.exit() val = self.showForm('editString') print val if not val == {} or (val.has_key('refNodes') and val.has_key('mobNodes')): apply(self.doitWrapper, (val['refNodes'],), {'log':0}) apply(self.doitWrapper, (val['mobNodes'],), {'log':0}) self.typeVar.set('By Picking') def continuous_cb(self, event=None): #get rid of the alignment GUI if hasattr(self.vf,'alnEditor'): self.vf.alnEditor.exit() form = self.cmdForms['superimpose'] supButton = form.descr.entryByName['final']['widget'] if self.contVar.get() == 1: supButton.configure(state=Tkinter.DISABLED) if len(self.newPairs)>=4: self.superimpose_cb() else: supButton.configure(state=Tkinter.NORMAL) def labelByName(self, pick): # Continuous labeling. if pick is None: return atom = self.vf.findPickedAtoms(pick) if atom: level = self.vf.ICmdCaller.level.value self.vf.ICmdCaller.level.AddCallback(self.unlabelLevel) if level == Molecule : level = Protein self.node = atom.findType(level) funcItems = map(lambda x: x.full_name(), self.node) self.vf.labelByExpression(self.node, font = 'arial1.glf', location = 'First', textcolor = 'red', only = 1, lambdaFunc = 1,negate=0, function = 'lambda x: str(x.full_name())\n\n', topCommand=0, ) def unlabelLevel(self, newLevel, oldLevel): if not hasattr(self, 'node'): return if oldLevel == Molecule: oldLevel = Protein # need to be at the former level for all the former picked stuff # so take it all. node = self.vf.getSelection() nodes = node.findType(oldLevel) # Careful in labelByProperty fix a bug if no label should not break! self.vf.labelByExpression(nodes, negate=1, log=0) def stopICOM(self): # Destroy the inputForm self.cmdForms['superimpose'].root.destroy() # Set the form to None. del self.cmdForms['superimpose'] # Set back the continuousPicking to unsolicitedPick cbManager = self.vf.startContinuousPicking.cbManager if not len(self.oldCallBacks) == 0: cbManager.SetCallback(self.oldCallBacks[0]) if len(self.oldCallBacks)>1: for cb in self.oldCallBacks[1:]: cbManager.AddCallBack(cb) # Remove the unlabel callback bound to the self.vf.ICmdCaller.level if self.unlabelLevel in self.vf.ICmdCaller.level.callbacks: self.vf.ICmdCaller.level.RemoveCallback(self.unlabelLevel) # Unlabel whatever is labeled level = self.vf.ICmdCaller.level.value nodes = self.vf.getSelection().findType(level) if not nodes is None or len(nodes)!=0: self.vf.labelByExpression(nodes, negate=1, log=0) # Stop the continuous picking. self.vf.stopContinuousPicking() self.sphere1.Set(vertices=[], tagModified=False) self.sphere2.Set(vertices=[], tagModified=False) ## self.visualFeedBack(vertices =[]) def updateChooser(self, set1, set2): for elt1, elt2 in map(None, set1, set2): key = elt1.full_name() + '--' + elt2.full_name() self.newPairs[key] = (elt1, elt2) if not self.pairForm is None: entry = (key, None) self.chooser.add(entry) def reset_cb(self, event=None): """Button to reset the superimposition and the list of pairs.""" # Reset the chooser and the lists of pairs if self.newPairs == {}: return if not self.pairForm is None: self.chooser.clear() self.newPairs = {} # Reset the geometry. vi = self.vf.GUI.VIEWER geom = self.mobileMol.geomContainer.masterGeom oldCurrent = vi.currentObject vi.SetCurrentObject(geom) # transform only the given geometry. if vi.redirectTransformToRoot == 1: old = vi.redirectTransformToRoot vi.TransformRootOnly(0) else: old = 0 # Right now reset all the transformations applied to the mobile object. # Maybe should separate from the superimposition and only reset these. vi.ResetCurrentObject() # Put everything back like it was before. if old == 1: vi.TransformRootOnly(1) vi.SetCurrentObject(oldCurrent) self.sphere1.Set(vertices=[], tagModified=False) self.sphere2.Set(vertices=[], tagModified=False) self.firstLabel.configure(text='') self.secondLabel.configure(text='') ## self.visualFeedBack.Set(vertices=[], tagModified=False) def delete_cb(self, event = None): # Delete the selected pair from the listchooser and from the pairlist selectedNewPairs = self.chooser.get() # Undisplay the label (Maybe only if the last pair is being deleted ) self.firstLabel.configure(text='') self.secondLabel.configure(text='') for pair in selectedNewPairs: if len(self.chooser.entries) >=4: self.chooser.remove(pair) del self.newPairs[pair] if self.contVar.get()==1 or self.supcb==1: self.superimpose_cb() def superimpose_cb(self, event=None): if len(self.newPairs) >= 4 : # Need at least 4 pairs of atoms to do the superimposition setAtm1 = AtomSet(map(lambda x: x[0], self.newPairs.values())) setAtm2 = AtomSet(map(lambda x: x[1], self.newPairs.values())) if len(setAtm1) != len(setAtm2): message = ' ERROR: the 2 sets of atoms are not of the length\nthe superimposition cannot be performed. ' self.warningMsg(msg) return self.vf.superimposeAtoms(setAtm1, setAtm2) self.supcb = 1 ## self.visualFeedBack.Set(vertices=self.visualVertices, ## tagModified=False) def __call__(self, atoms, **kw): ats = self.vf.expandNodes(atoms) if not len(ats): return 'ERROR' kw['redraw']=1 kw['log']=0 return apply(self.doitWrapper, (ats,), kw) def doit(self, nodes): """ Create the 2 sets of atom that will be used to do the superimposition. Then call the superImposeCommand with these 2 sets. If continuous is on then the superimposition will be updated each time a pair of atoms is added otherwise the superimposition will be updated every 4 pairs of atoms. """ # Get the ICOM level icomLevel = self.vf.ICmdCaller.level.value # Not doing anything if no nodes picked: if not nodes: return if self.typeVar.get() == 'By Picking': # only take the first node picked. node = nodes[0] nodeMol = node.top elif self.typeVar.get() == 'From String': node = nodes molecules = nodes.top.uniq() if len(molecules)>1: # nodes need to belong to only one molecule return else: nodeMol = molecules[0] elif self.typeVar.get() == 'From Alignment': node = nodes molecules = nodes.top.uniq() if len(molecules)>1: # nodes need to belong to only one molecule return else: nodeMol = molecules[0] # 2- Get the atoms from the chosen nodes atms = node.findType(Atom) # First set of nodes == defines the first set of 1st elt in the pairs if len(self.pair) == 0 : self.secondLabel.configure(text ='') # Defines reference molecule: if self.newPairs == {}: self.refMol = nodeMol # Draw the feedBack sphere. mGeom = self.refMol.geomContainer.masterGeom self.vf.GUI.VIEWER.AddObject(self.sphere1, parent = mGeom) if nodeMol != self.refMol: self.firstLabel.configure(text ='') # if the node belongs to the another molecule return. # The pairs are defined allways in the same order. return self.pair.append(atms) #self.pair.append(node) if self.typeVar.get() == 'By Picking': self.firstLabel.configure(text=node.full_name()) elif len(self.pair) == 1 : # Creates Second set of elt in the pair. if self.newPairs=={}: if nodeMol != self.refMol: # set the mobile molecule and finish the first pair self.mobileMol = nodeMol mGeom = self.mobileMol.geomContainer.masterGeom self.vf.GUI.VIEWER.AddObject(self.sphere2, parent = mGeom) if nodeMol != self.mobileMol: return self.pair.append(atms) #self.pair.append(node) if self.typeVar.get() == 'By Picking': self.secondLabel.configure(text=node.full_name()) # Now we have the two set of elts to create pairs: # 1- Check if the 2 sets have the same length: set1 = self.pair[0] set1.sort() set2 = self.pair[1] set2.sort() if not set1 or not set2: print "ERROR: One of the sets is None" return elif len(set1) != len(set2): if node.__class__ == Atom: print 'ERROR: the 2 sets of atoms are not of the same size' return set1,set2 if node.__class__ in [Protein,ProteinSet, Residue, ResidueSet, Chain, ChainSet]: filter = self.defaultFilter if self.filters.has_key(filter): set1 = self.pair[0].get(self.filters[filter]) set2 = self.pair[1].get(self.filters[filter]) if not set1 or not set2: print 'ERROR: cannot compute the superimposition' print 'not set1 or not set2' return elif len(set1) != len(set2): print 'ERROR: cannot compute the superimposition' print 'len(set1) != len(set2)' return #print 'set1', set1 #print 'set2', set2 self.updateChooser(set1, set2) self.pair = [] if len(self.newPairs)>=4 and self.contVar.get() == 1: # Continuous picking is on and superimposition can be done if # there are more than 4 pairs. self.superimpose_cb() def alignment_cb(self, event=None): if not hasattr(self.vf,'alignment'): self.vf.alignment = Alignment() if not hasattr(self.vf,'alnEditor'): self.vf.alnEditor = PmvAlignmentEditor(vf=self.vf) self.vf.alnEditor.alignment = self.vf.alignment else: self.vf.alnEditor.redraw() self.vf.alnEditor.master.deiconify() for mol in self.vf.Mols: if mol.name not in self.vf.alignment.seqNames: self.vf.alnEditor.getSequence(mol)
else: r1 = r2 = radii[0] / 2. self.entries.append('\t%s, %f, %s, %f\n' % (self.coord3( v[f[i][j]]), r1, self.coord3(v[f[i][j + 1]]), r2)) if fp: col = c[f[i][j]][:3] else: col = (1., 1., 1.) self.entries.append( "\tpigment { color rgb<%6.3f, %6.3f, %6.3f> }\n" % tuple(col)) self.entries.append( "\tfinish { specular 1 roughness 0.001 ambient 0.3 }\n") self.endShape() if __name__ == '__main__': from DejaVu import Viewer vi = Viewer() from DejaVu.Spheres import Spheres s = Spheres('test', centers=((0.0, 0., 0.), (3., 0., 0.))) s.Set(quality=4) vi.AddObject(s) from DejaVu.povray3 import PovRay p = PovRay() p.addCamera(vi.cameras[0]) p.addLight(vi.lights[0]) p.addGeom(s) p.write('test.pov')
if fp: col = c[f[i][j]][:3] alpha = c[f[i][j]][3] else: col = (1., 1., 1.) alpha = 1.0 self.entries.append( self.addOneCylinder(v[f[i][j]], v[f[i][j + 1]], col)) self.entries.append( self.addOneCylinder(v[f[i][j + 1]], v[f[i][j]], col)) #self.entries.append("\tpigment { color rgb<%6.3f, %6.3f, %6.3f> }\n"% tuple(col)) #self.entries.append("\tfinish { specular 1 roughness 0.001 ambient 0.3 }\n") #self.endShape() #########From blendergelato.py############################# if __name__ == '__main__': from DejaVu import Viewer vi = Viewer() from DejaVu.Spheres import Spheres s = Spheres('test', centers=((0.0, 0., 0.), (3., 0., 0.))) s.Set(quality=15) vi.AddObject(s) from DejaVu.povray3 import PovRay p = PovRay() p.addCamera(vi.cameras[0]) p.addLight(vi.lights[0]) p.addGeom(s) p.write('test.pov')