def __init__(self, title="Molecule Viewer", logMode='no', libraries=[], gui=1, resourceFile = '_pmvrc', customizer = None, master=None, guiVisible=1, withShell=1, verbose=True, trapExceptions=True): """ * title: string used as a title. * logMode: string specifying the mode of logging of mv. 'no': for no loging of commands at all 'overwrite': the log files overwrite the one from the previous session the log files = mvAll.log.py 'unique': the log file name include the date and time * libraries: list of the Python packages containing modules and commands that can be loaded in the application. Such a package needs the following files : cmdlib.py and modlib.py * gui : Flag specifying whether or not to run the application with a gui. * resourceFile: file sourced at startup and where userpreference made as default are saved (default: '.pmvrc') * customizer : file when specified is sourced at startup instead of the resourceFile * master: can be specified to run PMV withing another GUI application. * guiVisible: Flag to specify whether or not to show the GUI. - trapExceptions should be set to False when creating a ViewerFramework for testing, such that exception are seen by the testing framework """ libraries = ['Pmv', 'Volume','AutoDockTools'] + libraries _pmvrc = Find_pmvrc(resourceFile) if _pmvrc: resourceFile = _pmvrc if withShell: from traceback import print_exception def print_exception_modified(etype, value, tb, limit=None, file=None): """ Modified version of traceback.print_exception Deiconifies pyshell when Traceback is printed """ print_exception(etype, value, tb, limit, file) if hasattr(self, 'GUI'): self.GUI.pyshell.top.deiconify() if not 'Pmv' in tb.tb_frame.f_code.co_filename: return if etype == ImportError: if hasattr(value,'message'): package = value.message.split()[-1] print "Please install " +package + " to fix this problem." elif etype == AssertionError: pass else: print "Please include this Traceback in your bug report. Help --> Report a Bug in PMV/ADT." import traceback traceback.print_exception = print_exception_modified ViewerFramework.__init__(self, title, logMode, libraries, gui, resourceFile, master=master, guiVisible=guiVisible, withShell=withShell, verbose=verbose, trapExceptions=trapExceptions) #if sys.platform == 'win32': #this needed to account for camera size # geometry = '%dx%d+%d+%d' % (800,600, 30, 30) #else: # geometry = '%dx%d+%d+%d' % (800,200, 30, 30) #self.GUI.ROOT.geometry(geometry) # Establish interface to Visual Programming environment. if self.visionAPI is not None: # add Molecule, Pmv, Viewer to lookup table from Pmv.VisionInterface.PmvNodes import PmvMolecule, PmvNode, \ PmvViewer, PmvSetNode, PmvVolume self.visionAPI.addToLookup(Protein, PmvMolecule, "Molecules") self.visionAPI.addToLookup(MoleculeViewer, PmvNode, "PMV") from DejaVu import Viewer self.visionAPI.addToLookup(Viewer, PmvViewer, "PMV") self.visionAPI.addToLookup(TreeNodeSet, PmvSetNode, "Sets") # Note: Molecules are added to the interface in addMolecule() below # put Pmv instance into list of objects to be added to Vision self.visionAPI.add(self, "Pmv", kw={ 'vf':self, 'constrkw':{'vf':'masterNet.editor.vf'} } ) # put Pmv Viewer instance in list of objects to be added to Vision if self.hasGui: self.visionAPI.add(self.GUI.VIEWER, "Pmv Viewer", kw={ 'viewer':self.GUI.VIEWER, 'constrkw':{'viewer':'masterNet.editor.vf.GUI.VIEWER'} } ) self.selection = MoleculeSet() # store current selection # replace interactive command caller by MVInteractiveCmdCaller # we need the ICmdCaller even if there is no GUI because it has # the level variable used byu selection commands self.ICmdCaller = MVInteractiveCmdCaller( self ) from mvCommand import MVSetIcomLevel self.addCommand( MVSetIcomLevel(), 'setIcomLevel', None ) from mvCommand import MVSetSelectionLevel, MVSetSelectionLevelGUI self.addCommand( MVSetSelectionLevel(), 'setSelectionLevel', MVSetSelectionLevelGUI) self.setSelectionLevel(Molecule, topCommand = 0) #should this be Protein? from Pmv.displayCommands import BindGeomToMolecularFragment from Pmv.displayCommands import BindGeomToMolecularFragmentGUI self.addCommand( BindGeomToMolecularFragment(), 'bindGeomToMolecularFragment', BindGeomToMolecularFragmentGUI ) # if self.hasGui: # from Pmv.mvCommand import MVPrintNodeNames, MVCenterOnNodes # self.addCommand( MVPrintNodeNames(), 'printNodeNames ', None ) # self.addCommand( MVCenterOnNodes(), 'centerOnNodes', None ) # load out default interactive command which prints out object # names #self.ICmdCaller.setCommands( self.printNodeNames ) self.ICmdCaller.go() self.addMVBasicMenus() # load out default interactive command self.ICmdCaller.setCommands( self.printNodeNames, modifier=None ) self.ICmdCaller.setCommands( self.select, modifier='Shift_L' ) self.ICmdCaller.setCommands( self.centerOnNodes, modifier='Control_L' ) self.ICmdCaller.setCommands( self.deselect, modifier='Alt_L' ) #self.setIcomLevel(Molecule, topCommand = 0) self.setIcomLevel(Atom, topCommand = 0) self.Mols = MoleculeSet() # store the molecules read in self.objects = self.Mols from MolKit.sets import Sets self.sets = Sets() # store user-defined sets in this dict # lock needs to be acquired before volume can be added self.volumesLock = thread.allocate_lock() self.Vols = [] # list of Grid3D objects storing volumetric data if self.visionAPI is not None: from Volume.Grid3D import Grid3D self.visionAPI.addToLookup(Grid3D, PmvVolume, "Volumes") self.allAtoms = AtomSet() # set of all atoms (across molecules) #if self.hasGui: # from Pmv.controlPanelCommands import ControlPanel,ControlPanel_GUI # self.addCommand(ControlPanel(), "controlPanel",ControlPanel_GUI) choices = ['caseSensitive', 'caseInsensitive', 'caseInsensWithEscapedChars'] self.userpref.add('selectStringMatchMode', 'caseSensitive', validValues=choices, doc = """When set to caseSensitive the string match mode will be case sensitive the other possibility is to be case insensitive or case insensitive with escaped characters. """) choices = [1,0] self.userpref.add('showSelectionSpheres', 1, validValues=choices, doc = """When set to 1 the selection visual feedback which are the little yellow crosses will be displayed.""") choices = [1,0] self.userpref.add('raiseExceptionForMissingKey', 1, validValues=choices, callbackFunc = [self.setRaiseException], doc = """When set to 1 an exception will be raised is a a key is not found in a dictionnary. """) choices = [1, 0] self.userpref.add('expandNodeLogString', 0, validValues=choices, doc = """When set to 1 the log string representing the node argument of a doit will be expanded to the full name of each element of the TreeNodeSet, when set to 0 the log string representing the node argument of a doit will be 'self.getSelection()'. In the last case the command log will depend on the current selection.""") # overwrite firstObject only with firstMoleculeOnly self.userpref['centerScene']['validValues'][0] = 'firstMoleculeOnly' self.userpref.set('centerScene', 'firstMoleculeOnly') choices = ['yes','no'] self.userpref.add('useDepthCueing', 'yes', validValues=choices, doc = """ When set to 'yes' the depthCueing is turned on by default""") doc = """When set to yes a warning message is displayed when an empty selection is about to be expanded to all the molecules loaded in the application""" self.userpref.add('warnOnEmptySelection', 'no', validValues=choices, doc=doc) if self.hasGui: self.GUI.VIEWER.suspendRedraw = True self.GUI.drop_cb = self.drop_cb self.GUI.pickLabel.bind("<Button-1>",self.setSelectionLevel.guiCallback) if self.userpref['useDepthCueing']['value']=='yes': self.GUI.VIEWER.currentCamera.fog.Set(enabled=1, tagModified=False) if title != 'AutoDockTools': toolbarDict = {} toolbarDict['name'] = 'ADT' toolbarDict['type'] = 'Checkbutton' toolbarDict['icon1'] = 'adt.png' toolbarDict['balloonhelp'] = 'AutoDock Tools' toolbarDict['icon_dir'] = ICONPATH toolbarDict['index'] = 7 toolbarDict['cmdcb'] = self.Add_ADT toolbarDict['variable'] = None self.GUI.toolbarList.append(toolbarDict) self.GUI.configureToolBar(self.GUI.iconsize) # overwrite unsollicited picking with a version that prints atom names #self.GUI.VIEWER.RemovePickingCallback("unsolicitedPick") #self.GUI.VIEWER.AddPickingCallback(self.unsolicitedPick) top = self.GUI.ROOT.winfo_toplevel() geom = top.geometry() geom = geom.split('x') self.GUI.menuBars['Toolbar']._frame.update_idletasks() winfo_width = self.GUI.menuBars['Toolbar']._frame.winfo_width() if int(geom[0]) < winfo_width + 10: geom[0] = str(winfo_width + 10) top.geometry(geom[0]+'x'+geom[1]) if not trapExceptions and customizer == './.empty': top.update_idletasks() top.deiconify() #self.GUI.vwrCanvasFloating.deiconify() self.GUI.naturalSize() from Pmv.updateCommands import Update, UpdateGUI self.addCommand( Update(), 'update', UpdateGUI ) from Pmv.aboutCommands import About, AboutGUI self.addCommand( About(), 'about', AboutGUI ) self.GUI.VIEWER.suspendRedraw = False self.browseCommands('deleteCommands',package='Pmv', topCommand=0) self.GUI.ROOT.bind('<Delete>', self.deleteAtomSet.guiCallback) self.GUI.vwrCanvasFloating.bind('<Delete>', self.deleteAtomSet.guiCallback) self.browseCommands ('dashboardCommands', package='Pmv', topCommand=0) self.customize(customizer) if self.hasGui: try: import grid3DCommands self.browseCommands("grid3DCommands",package="Pmv", topCommand=0) except ImportError: print "UTpackages are not installed. Disabling grid3DCommands..." rcFile = getResourceFolderWithVersion() if rcFile: rcFile += os.sep + 'Pmv' + os.sep + "recent.pkl" if self.hasGui: fileMenu = self.GUI.menuBars['menuRoot'].menubuttons['File'].menu self.recentFiles = RecentFiles(self, fileMenu, filePath=rcFile, menuLabel = 'Recent Files') try: from DejaVu.Camera import RecordableCamera if isinstance(self.GUI.VIEWER.cameras[0], RecordableCamera): from Pmv.videoCommands import VideoCommand, VideoCommandGUI self.addCommand(VideoCommand(), 'videoCommand', VideoCommandGUI) except: pass #print "Recordable camera is not available" if len(self.dashboard.tree.columns)==0: # this warning is wrong, it appears during test_pmvscript #print "WARNING: update your _pmvrc file to load the dashboard commands" from Pmv.dashboard import loadAllColunms loadAllColunms(self)
class MoleculeViewer(ViewerFramework): """ package : Pmv module : moleculeViewer class : MoleculeViewer description: Class derived from the ViewerFramework base class. It provides a 3D molecular viewer. """ def getSelLev(self): return self.selection.elementType def setSelLev(self, value): if value==Protein: value = Molecule assert value in [Molecule, Chain, Residue, Atom] self.setSelectionLevel(value) selectionLevel = property(getSelLev, setSelLev) def __init__(self, title="Molecule Viewer", logMode='no', libraries=[], gui=1, resourceFile = '_pmvrc', customizer = None, master=None, guiVisible=1, withShell=1, verbose=True, trapExceptions=True): """ * title: string used as a title. * logMode: string specifying the mode of logging of mv. 'no': for no loging of commands at all 'overwrite': the log files overwrite the one from the previous session the log files = mvAll.log.py 'unique': the log file name include the date and time * libraries: list of the Python packages containing modules and commands that can be loaded in the application. Such a package needs the following files : cmdlib.py and modlib.py * gui : Flag specifying whether or not to run the application with a gui. * resourceFile: file sourced at startup and where userpreference made as default are saved (default: '.pmvrc') * customizer : file when specified is sourced at startup instead of the resourceFile * master: can be specified to run PMV withing another GUI application. * guiVisible: Flag to specify whether or not to show the GUI. - trapExceptions should be set to False when creating a ViewerFramework for testing, such that exception are seen by the testing framework """ libraries = ['Pmv', 'Volume','AutoDockTools'] + libraries _pmvrc = Find_pmvrc(resourceFile) if _pmvrc: resourceFile = _pmvrc if withShell: from traceback import print_exception def print_exception_modified(etype, value, tb, limit=None, file=None): """ Modified version of traceback.print_exception Deiconifies pyshell when Traceback is printed """ print_exception(etype, value, tb, limit, file) if hasattr(self, 'GUI'): self.GUI.pyshell.top.deiconify() if not 'Pmv' in tb.tb_frame.f_code.co_filename: return if etype == ImportError: if hasattr(value,'message'): package = value.message.split()[-1] print "Please install " +package + " to fix this problem." elif etype == AssertionError: pass else: print "Please include this Traceback in your bug report. Help --> Report a Bug in PMV/ADT." import traceback traceback.print_exception = print_exception_modified ViewerFramework.__init__(self, title, logMode, libraries, gui, resourceFile, master=master, guiVisible=guiVisible, withShell=withShell, verbose=verbose, trapExceptions=trapExceptions) #if sys.platform == 'win32': #this needed to account for camera size # geometry = '%dx%d+%d+%d' % (800,600, 30, 30) #else: # geometry = '%dx%d+%d+%d' % (800,200, 30, 30) #self.GUI.ROOT.geometry(geometry) # Establish interface to Visual Programming environment. if self.visionAPI is not None: # add Molecule, Pmv, Viewer to lookup table from Pmv.VisionInterface.PmvNodes import PmvMolecule, PmvNode, \ PmvViewer, PmvSetNode, PmvVolume self.visionAPI.addToLookup(Protein, PmvMolecule, "Molecules") self.visionAPI.addToLookup(MoleculeViewer, PmvNode, "PMV") from DejaVu import Viewer self.visionAPI.addToLookup(Viewer, PmvViewer, "PMV") self.visionAPI.addToLookup(TreeNodeSet, PmvSetNode, "Sets") # Note: Molecules are added to the interface in addMolecule() below # put Pmv instance into list of objects to be added to Vision self.visionAPI.add(self, "Pmv", kw={ 'vf':self, 'constrkw':{'vf':'masterNet.editor.vf'} } ) # put Pmv Viewer instance in list of objects to be added to Vision if self.hasGui: self.visionAPI.add(self.GUI.VIEWER, "Pmv Viewer", kw={ 'viewer':self.GUI.VIEWER, 'constrkw':{'viewer':'masterNet.editor.vf.GUI.VIEWER'} } ) self.selection = MoleculeSet() # store current selection # replace interactive command caller by MVInteractiveCmdCaller # we need the ICmdCaller even if there is no GUI because it has # the level variable used byu selection commands self.ICmdCaller = MVInteractiveCmdCaller( self ) from mvCommand import MVSetIcomLevel self.addCommand( MVSetIcomLevel(), 'setIcomLevel', None ) from mvCommand import MVSetSelectionLevel, MVSetSelectionLevelGUI self.addCommand( MVSetSelectionLevel(), 'setSelectionLevel', MVSetSelectionLevelGUI) self.setSelectionLevel(Molecule, topCommand = 0) #should this be Protein? from Pmv.displayCommands import BindGeomToMolecularFragment from Pmv.displayCommands import BindGeomToMolecularFragmentGUI self.addCommand( BindGeomToMolecularFragment(), 'bindGeomToMolecularFragment', BindGeomToMolecularFragmentGUI ) # if self.hasGui: # from Pmv.mvCommand import MVPrintNodeNames, MVCenterOnNodes # self.addCommand( MVPrintNodeNames(), 'printNodeNames ', None ) # self.addCommand( MVCenterOnNodes(), 'centerOnNodes', None ) # load out default interactive command which prints out object # names #self.ICmdCaller.setCommands( self.printNodeNames ) self.ICmdCaller.go() self.addMVBasicMenus() # load out default interactive command self.ICmdCaller.setCommands( self.printNodeNames, modifier=None ) self.ICmdCaller.setCommands( self.select, modifier='Shift_L' ) self.ICmdCaller.setCommands( self.centerOnNodes, modifier='Control_L' ) self.ICmdCaller.setCommands( self.deselect, modifier='Alt_L' ) #self.setIcomLevel(Molecule, topCommand = 0) self.setIcomLevel(Atom, topCommand = 0) self.Mols = MoleculeSet() # store the molecules read in self.objects = self.Mols from MolKit.sets import Sets self.sets = Sets() # store user-defined sets in this dict # lock needs to be acquired before volume can be added self.volumesLock = thread.allocate_lock() self.Vols = [] # list of Grid3D objects storing volumetric data if self.visionAPI is not None: from Volume.Grid3D import Grid3D self.visionAPI.addToLookup(Grid3D, PmvVolume, "Volumes") self.allAtoms = AtomSet() # set of all atoms (across molecules) #if self.hasGui: # from Pmv.controlPanelCommands import ControlPanel,ControlPanel_GUI # self.addCommand(ControlPanel(), "controlPanel",ControlPanel_GUI) choices = ['caseSensitive', 'caseInsensitive', 'caseInsensWithEscapedChars'] self.userpref.add('selectStringMatchMode', 'caseSensitive', validValues=choices, doc = """When set to caseSensitive the string match mode will be case sensitive the other possibility is to be case insensitive or case insensitive with escaped characters. """) choices = [1,0] self.userpref.add('showSelectionSpheres', 1, validValues=choices, doc = """When set to 1 the selection visual feedback which are the little yellow crosses will be displayed.""") choices = [1,0] self.userpref.add('raiseExceptionForMissingKey', 1, validValues=choices, callbackFunc = [self.setRaiseException], doc = """When set to 1 an exception will be raised is a a key is not found in a dictionnary. """) choices = [1, 0] self.userpref.add('expandNodeLogString', 0, validValues=choices, doc = """When set to 1 the log string representing the node argument of a doit will be expanded to the full name of each element of the TreeNodeSet, when set to 0 the log string representing the node argument of a doit will be 'self.getSelection()'. In the last case the command log will depend on the current selection.""") # overwrite firstObject only with firstMoleculeOnly self.userpref['centerScene']['validValues'][0] = 'firstMoleculeOnly' self.userpref.set('centerScene', 'firstMoleculeOnly') choices = ['yes','no'] self.userpref.add('useDepthCueing', 'yes', validValues=choices, doc = """ When set to 'yes' the depthCueing is turned on by default""") doc = """When set to yes a warning message is displayed when an empty selection is about to be expanded to all the molecules loaded in the application""" self.userpref.add('warnOnEmptySelection', 'no', validValues=choices, doc=doc) if self.hasGui: self.GUI.VIEWER.suspendRedraw = True self.GUI.drop_cb = self.drop_cb self.GUI.pickLabel.bind("<Button-1>",self.setSelectionLevel.guiCallback) if self.userpref['useDepthCueing']['value']=='yes': self.GUI.VIEWER.currentCamera.fog.Set(enabled=1, tagModified=False) if title != 'AutoDockTools': toolbarDict = {} toolbarDict['name'] = 'ADT' toolbarDict['type'] = 'Checkbutton' toolbarDict['icon1'] = 'adt.png' toolbarDict['balloonhelp'] = 'AutoDock Tools' toolbarDict['icon_dir'] = ICONPATH toolbarDict['index'] = 7 toolbarDict['cmdcb'] = self.Add_ADT toolbarDict['variable'] = None self.GUI.toolbarList.append(toolbarDict) self.GUI.configureToolBar(self.GUI.iconsize) # overwrite unsollicited picking with a version that prints atom names #self.GUI.VIEWER.RemovePickingCallback("unsolicitedPick") #self.GUI.VIEWER.AddPickingCallback(self.unsolicitedPick) top = self.GUI.ROOT.winfo_toplevel() geom = top.geometry() geom = geom.split('x') self.GUI.menuBars['Toolbar']._frame.update_idletasks() winfo_width = self.GUI.menuBars['Toolbar']._frame.winfo_width() if int(geom[0]) < winfo_width + 10: geom[0] = str(winfo_width + 10) top.geometry(geom[0]+'x'+geom[1]) if not trapExceptions and customizer == './.empty': top.update_idletasks() top.deiconify() #self.GUI.vwrCanvasFloating.deiconify() self.GUI.naturalSize() from Pmv.updateCommands import Update, UpdateGUI self.addCommand( Update(), 'update', UpdateGUI ) from Pmv.aboutCommands import About, AboutGUI self.addCommand( About(), 'about', AboutGUI ) self.GUI.VIEWER.suspendRedraw = False self.browseCommands('deleteCommands',package='Pmv', topCommand=0) self.GUI.ROOT.bind('<Delete>', self.deleteAtomSet.guiCallback) self.GUI.vwrCanvasFloating.bind('<Delete>', self.deleteAtomSet.guiCallback) self.browseCommands ('dashboardCommands', package='Pmv', topCommand=0) self.customize(customizer) if self.hasGui: try: import grid3DCommands self.browseCommands("grid3DCommands",package="Pmv", topCommand=0) except ImportError: print "UTpackages are not installed. Disabling grid3DCommands..." rcFile = getResourceFolderWithVersion() if rcFile: rcFile += os.sep + 'Pmv' + os.sep + "recent.pkl" if self.hasGui: fileMenu = self.GUI.menuBars['menuRoot'].menubuttons['File'].menu self.recentFiles = RecentFiles(self, fileMenu, filePath=rcFile, menuLabel = 'Recent Files') try: from DejaVu.Camera import RecordableCamera if isinstance(self.GUI.VIEWER.cameras[0], RecordableCamera): from Pmv.videoCommands import VideoCommand, VideoCommandGUI self.addCommand(VideoCommand(), 'videoCommand', VideoCommandGUI) except: pass #print "Recordable camera is not available" if len(self.dashboard.tree.columns)==0: # this warning is wrong, it appears during test_pmvscript #print "WARNING: update your _pmvrc file to load the dashboard commands" from Pmv.dashboard import loadAllColunms loadAllColunms(self) def drop_cb(self, files): for file in files: self.readMolecule(file) #def getSelectionLevel(self): # return self.selection.elementType def getMolFromName(self, name): mols = filter(lambda x: x.name == name, self.Mols) if len(mols): mol = mols[0] else: mol = None return mol def setRaiseException(self, name, oldval, val): import MolKit.molecule MolKit.molecule.raiseExceptionForMissingKey = val def unsolicitedPick(self, pick): """treat an unsollicited picking event""" if pick is None: return vi = self.GUI.VIEWER if vi.isShift() or vi.isControl(): vi.unsolicitedPick(pick) else: atom = self.findPickedAtoms(pick) if atom: level = self.ICmdCaller.level.value if level == Molecule: level = Protein node = atom.findType(level) for n in node: self.message( n.full_name() ) def loadMoleculeIfNeeded(self, filename): """load a molecule only if it doesn't exist yet in Pmv, else it aborts silent""" if not os.path.exists(filename): print 'Error! %s not found!'%filename return # find what name would be name = os.path.split(filename)[-1] try: spl = split(name, '.') except: spl = [name] name = spl[0] # ask if name already used if self.Mols: for mol in self.Mols.data: if name == mol.name: # break and return mol return mol # else load molecule if not hasattr(self, 'readMolecule'): self.browseCommands( 'fileCommands', commands=['readMolecule'], package='Pmv', topCommand=0) mol = self.readMolecule(filename) return mol def addMolecule(self, newmol, ask=1): """ Add a molecule to this viewer """ #IN ANY CASE: change any special characters in name to '-' from MolKit.molecule import Molecule if self.hasGui: Molecule.configureProgressBar = self.GUI.progressBarConf Molecule.updateProgressBar = self.GUI.progressBarUpd spChar=['?','*','.','$','#',':','-',','] ## spChar=['?','*','.','$','#',':','_',','] for item in spChar: newmol.name = replace(newmol.name,item,'_') ## newmol.name = replace(newmol.name,item,'-') if len(self.Mols) > 0: if newmol.name in self.Mols.name: if ask==1: from mglutil.gui.InputForm.Tk.gui import InputFormDescr idf = self.ifd = InputFormDescr(title = '') idf.append({'widgetType':Pmw.EntryField, 'name':'newmol', 'required':1, 'wcfg':{'labelpos':'w', 'label_text':'New Name: ', 'validate':None, 'value':'%s-%d'%(newmol.name, len(self.Mols))}, 'gridcfg':{'sticky':'we'}}) vals = self.getUserInput(idf) if len(vals)>0: assert not vals['newmol'] in self.Mols.name newmol.name = vals['newmol'] else: return None else: newmol.name='%s_%d'%(newmol.name,len(self.Mols)) newmol.allAtoms.setStringRepr(newmol.full_name()+':::') # provide hook for progress bar # old code: newmol.allAtoms._bndIndex_ = range(len(newmol.allAtoms)) allAtomsLen = len(newmol.allAtoms) if allAtomsLen == 0: import warnings warnings.warn("%s is empty molecule cannot add it to the viewer"%newmol.name) return None if self.hasGui: self.GUI.configureProgressBar(init=1, mode='increment', max=allAtomsLen, labeltext='add molecule to viewer') i = 0 for a in newmol.allAtoms: a._bndIndex_ = i if self.hasGui: self.GUI.updateProgressBar() i = i + 1 g = None if self.hasGui: g = MolGeomContainer( newmol, self ) # addObject calls updateProgressBar on its own self.addObject('mol%s'%len(self.Mols), newmol, g) self.Mols.setStringRepr(self.Mols.full_name()) # add object to visionAPI (to add them as nodes to Vision library) if self.visionAPI: self.visionAPI.add(newmol, newmol.name, kw={ 'molecule':newmol, 'constrkw':{ 'molecule': 'masterNet.editor.vf.expandNodes("%s")[0]'%newmol.name} } ) self.allAtoms = self.allAtoms + newmol.allAtoms self.allAtoms.setStringRepr(self.Mols.full_name()+':::') #used by cpk command to decide whether or not to compute radii newmol.unitedRadii = None # set to None to force initial radii assignment return newmol def addVolume(self, name, grid): # FIXME we need to check for name unicity and have a repalcement policy #self.volumesLock.acquire() self.Vols.append(grid) grid.name = name #self.volumesLock.release() if self.visionAPI: self.visionAPI.add(grid, name, kw={ 'grid':grid, 'constrkw':{ 'grid': 'masterNet.editor.vf.gridFromName("%s")[0]'%grid.name} } ) def getSelection(self): # FIXME why not return self.Mols always on empty selection ?? # this should speed thing up #ICmdCallerLevel = self.ICmdCaller.level.value selLevel = self.selectionLevel if len(self.selection)==0: # empty selection if self.userpref['warnOnEmptySelection']['value']=='yes': if self.askOkCancelMsg('expand empty selection to all molecules?'): #selection = self.Mols.findType(selLevel)#, uniq=1) return self.Mols #try: # selection = self.Mols.findType(selLevel)#, uniq=1) #except: # if selLevel==Molecule: # selection = self.Mols.findType(Protein) #return selection else: #selection = self.Mols.findType(selLevel)#, uniq=1) return self.Mols #try: # selection = self.Mols.findType(selLevel)#, uniq=1) #except: # if selLevel==Molecule: # selection = self.Mols.findType(Protein) #return selection else: #selection = self.Mols.findType(selLevel)#, uniq=1) return self.Mols #try: # selection = self.Mols.findType(selLevel)#, uniq=1) #except: # if selLevel==Molecule: # selection = self.Mols.findType(Protein) #return selection else: # not empty select #try: # selection = self.selection.findType(selLevel, uniq=1) #except: # if selLevel==Molecule: # selection = self.selection.findType(Protein) return self.selection #selection = self.selection.findType(selLevel, uniq=1) #return selection ## if self.userpref['warnOnEmptySelection']['value']=='yes': ## if self.askOkCancelMsg('expand empty selection to all molecules?'): ## selection = self.Mols.findType(selLevel)#, uniq=1) ## #try: ## # selection = self.Mols.findType(selLevel)#, uniq=1) ## #except: ## # if selLevel==Molecule: ## # selection = self.Mols.findType(Protein) ## return selection ## else: ## selection = self.Mols.findType(selLevel)#, uniq=1) ## #try: ## # selection = self.Mols.findType(selLevel)#, uniq=1) ## #except: ## # if selLevel==Molecule: ## # selection = self.Mols.findType(Protein) ## return selection ## else: ## selection = self.Mols.findType(selLevel)#, uniq=1) ## #try: ## # selection = self.Mols.findType(selLevel)#, uniq=1) ## #except: ## # if selLevel==Molecule: ## # selection = self.Mols.findType(Protein) ## return selection ## else: ## # not empty select ## #try: ## # selection = self.selection.findType(selLevel, uniq=1) ## #except: ## # if selLevel==Molecule: ## # selection = self.selection.findType(Protein) ## selection = self.selection.findType(selLevel, uniq=1) ## return selection def getItems(self, selString=""): """Takes a string and returns a TreeNodeSet The string can contain a series of set descriptors with operators separated by / characters. There is always a first set, followed by pairs of operators and sets. All sets have to describe nodes of the same level. example: '1crn:::CA*/+/1crn:::O*' describes the union of all CA ans all O in 1crn '1crn:::CA*/+/1crn:::O*/-/1crn::TYR29:' """ assert type(selString)==StringType return self.expandNodes(selString) def expandNodes(self, nodes): """Takes nodes as string or TreeNode or TreeNodeSet and returns a TreeNodeSet If nodes is a string it can contain a series of set descriptors with operators separated by / characters. There is always a first set, followed by pairs of operators and sets. All sets ahve to describe nodes of the same level. example: '1crn:::CA*/+/1crn:::O*' describes the union of all CA ans all O in 1crn '1crn:::CA*/+/1crn:::O*/-/1crn::TYR29:' """ if isinstance(nodes,TreeNode): result = nodes.setClass([nodes]) result.setStringRepr(nodes.full_name()) elif type(nodes)==StringType: stringRepr = nodes css = CompoundStringSelector() result = css.select(self.Mols, stringRepr)[0] ## setsStrings = stringRepr.split('/') ## getSet = self.Mols.NodesFromName ## result = getSet(setsStrings[0]) ## for i in range(1, len(setsStrings), 2): ## op = setsStrings[i] ## arg = setsStrings[i+1] ## if op=='|': # or ## result += getSet(arg) ## elif op=='-': # subtract ## result -= getSet(arg) ## elif op=='&': # intersection ## result &= getSet(arg) ## elif op=='^': # xor ## result ^= getSet(arg) ## elif op=='s': # sub select (i.e. select from previous result) ## result = result.get(arg) ## else: ## raise ValueError, '%s bad operation in selection string'%op ## result.setStringRepr(stringRepr) elif isinstance(nodes,TreeNodeSet): result = nodes else: raise ValueError, 'Could not expand nodes %s\n'%str(nodes) return result def getNodesByMolecule(self, nodes, nodeType=None): """ moleculeSet, [nodeSet, nodeSet] <- getNodesByMolecule(nodes, nodeType=None) nodes can be either: a string, a TreeNode or a TreeNodeSet. This method returns a molecule set and for each molecule a TreeNodeSet of the nodes belonging to this molecule. 'nodeType' enables a desired type of nodes to be returned for each molecule """ # special case list of complete molecules to be expanded to atoms # this also covers the case where nothing is selected if isinstance(nodes, MoleculeSet) or isinstance(nodes, ProteinSet): if nodeType is Atom: atms = [] for mol in nodes: atms.append(mol.allAtoms) return nodes, atms elif (nodeType is Protein) or (nodeType is Molecule): return nodes, nodes # if it is a string, get a bunch of nodes from the string if type(nodes)==StringType: nodes = self.expandNodes(nodes) assert issubclass(nodes.__class__, TreeNode) or \ issubclass(nodes.__class__, TreeNodeSet) # if nodes is a single TreeNode make it a singleton TreeNodeSet if issubclass(nodes.__class__, TreeNode): nodes = nodes.setClass([nodes]) nodes.setStringRepr(nodes.full_name()) if len(nodes)==0: return MoleculeSet([]), [] # catch the case when nodes is already a MoleculeSet if nodes.elementType in [Molecule, Protein]: molecules = nodes else: # get the set of molecules molecules = nodes.top.uniq() # build the set of nodes for each molecule nodeSets = [] # find out the type of the nodes we want to return searchType=0 if nodeType is None: Klass = nodes.elementType # class of objects in that set else: assert issubclass(nodeType, TreeNode) Klass = nodeType if Klass != nodes.elementType: searchType=1 for mol in molecules: # get set of nodes for this molecule mol_nodes = nodes.get(lambda x, mol=mol: x.top==mol) # get the required types of nodes if searchType: if Klass == Atom and hasattr(mol_nodes, 'allAtoms'): mol_nodes = mol_nodes.allAtoms else: mol_nodes = mol_nodes.findType( Klass ).uniq() stringRepr = nodes.getStringRepr() if stringRepr: if ':' in stringRepr: mol_nodes.setStringRepr( mol.name+stringRepr[stringRepr.index(':'):]) else: mol_nodes.setStringRepr(stringRepr) nodeSets.append( mol_nodes ) return molecules, nodeSets def addMVBasicMenus(self): from Pmv.selectionCommands import MVSelectCommand, MVDeSelectCommand from Pmv.mvCommand import MVPrintNodeNames, MVCenterOnNodes self.addCommand( MVPrintNodeNames(), 'printNodeNames' ) self.addCommand( MVSelectCommand(), 'select' ) self.addCommand( MVDeSelectCommand(), 'deselect' ) self.addCommand( MVCenterOnNodes(), 'centerOnNodes' ) def findPickedAtoms(self, pick): """ given a PickObject this function finds all corresponding atoms. Each atom in the returned set has its attribute pickedInstances set to a list of 2-tuples [(geom, instance),...]. """ allatoms = AtomSet( [] ) # loop over object, i.e. geometry objects for obj, values in pick.hits.items(): # build a list of vertices and list of instances instances = map(lambda x: x[1], values) vertInds = map(lambda x: x[0], values) # only geometry bound to molecules is packable in PMV if not hasattr(obj, 'mol') or len(vertInds)<1: continue # only vertices of geometry have a mapping to atoms # for other types we return an empty atom set if pick.type!='vertices': return allatoms g = obj.mol.geomContainer # convert vertex indices into atoms if g.geomPickToAtoms.has_key(obj.name): # the geometry obj has a function to convert to atoms # specified it he geomContainer[obj], e.g. MSMS surface func = g.geomPickToAtoms[obj.name] if func: atList = func(obj, vertInds) else: atlist = [] else: # we assume a 1 to 1 mapping of vertices with atoms # e.g. the lines geometry atList = [] allAtoms = g.atoms[obj.name] for i in vertInds: atList.append(allAtoms[int(i)]) # build a dict of atoms used to set the pickedAtomInstance # attribute for the last picking operation pickedAtoms = {} # update the pickedAtoms dict for i, atom in enumerate(atList): atomInstList = pickedAtoms.get(atom, None) if atomInstList: atomInstList.append( (obj, instances[i]) ) else: pickedAtoms[atom] = [ (obj, instances[i]) ] # FIXME atoms might appear multiple times because they were picked # in several geometries OR be cause they correspond to different # instances. In the first case (i.e. multiple geometries) # duplicates should be removed, in the latter (multiple instances) # duplicate should be kept # # Apparently we do not get duplication for multiple geoemtry objects! allatoms = allatoms + AtomSet( atList ) # loop over picked atoms and write the instance list into the atom for atom, instances in pickedAtoms.items(): atom.pickedInstances = instances #print allAtoms return allatoms def findPickedBonds(self, pick): """do a pick operation and return a 2-tuple holding (the picked bond, the picked geometry)""" allbonds = BondSet( [] ) for o, val in pick.hits.items(): #loop over geometries # loop over list of (vertices, instance) (e.g. (45, [0,0,2,0])) for instvert in val: primInd = instvert[0] if not hasattr(o, 'mol'): continue g = o.mol.geomContainer if g.geomPickToBonds.has_key(o.name): func = g.geomPickToBonds[o.name] if func: allbonds = allbonds + func(o, primInd) else: l = [] bonds = g.atoms[o.name].bonds[0] for i in range(len(primInd)): l.append(bonds[int(primInd[i])]) allbonds = allbonds + BondSet(l) return allbonds def transformedCoordinatesWithInstances(self, nodes): """ for a nodeset, this function returns transformed coordinates. This function will use the pickedInstance attribute if found. """ # nodes is a list of atoms, residues, chains, etc. where each member # has a pickedInstances attribute which is a list of 2-tuples # (object, [i,j,..]) vt = [] for node in nodes: #find all atoms and their coordinates coords = nodes.findType(Atom).coords if hasattr(node, 'pickedInstances'): # loop over the pickedInstances of this node for inst in node.pickedInstances: geom, instance = inst # inst is a tuple (object, [i,j,..]) M = geom.GetMatrix(geom.LastParentBeforeRoot(), instance[1:]) for pt in coords: ptx = M[0][0]*pt[0]+M[0][1]*pt[1]+M[0][2]*pt[2]+M[0][3] pty = M[1][0]*pt[0]+M[1][1]*pt[1]+M[1][2]*pt[2]+M[1][3] ptz = M[2][0]*pt[0]+M[2][1]*pt[1]+M[2][2]*pt[2]+M[2][3] vt.append( (ptx, pty, ptz) ) else: # no picking ==> no list of instances ==> use [0,0,0,...] g = nodes[0].top.geomContainer.geoms['master'] M = g.GetMatrix(g.LastParentBeforeRoot()) for pt in coords: ptx = M[0][0]*pt[0]+M[0][1]*pt[1]+M[0][2]*pt[2]+M[0][3] pty = M[1][0]*pt[0]+M[1][1]*pt[1]+M[1][2]*pt[2]+M[1][3] ptz = M[2][0]*pt[0]+M[2][1]*pt[1]+M[2][2]*pt[2]+M[2][3] vt.append( (ptx, pty, ptz) ) return vt def Add_ADT(self): """Adds AutoToolsBar""" if self.GUI.toolbarCheckbuttons['ADT']['Variable'].get(): #if self.GUI.menuBars.has_key('AutoTools4Bar'): # self.GUI.menuBars['AutoTools4Bar'].pack(fill='x',expand=1) if hasattr(self.GUI, 'currentADTBar'): self.GUI.menuBars[self.GUI.currentADTBar].pack(fill='x',expand=1) else: self.browseCommands('autotors4Commands', commands = None, package = 'AutoDockTools') self.browseCommands('autoflex4Commands', commands = None, package = 'AutoDockTools') self.browseCommands('autogpf4Commands', commands = None, package = 'AutoDockTools') self.browseCommands('autodpf4Commands', commands = None, package = 'AutoDockTools') self.browseCommands('autostart4Commands', commands = None, package = 'AutoDockTools') self.browseCommands('autoanalyze4Commands', commands = None, package = 'AutoDockTools') self.GUI.currentADTBar = 'AutoTools4Bar' from AutoDockTools import setADTmode setADTmode('AD4.0', self) self.GUI.adt4ModeLabel.bind("<Double-Button-1>", self.ADTSetMode.guiCallback) else: #self.GUI.menuBars['AutoToolsBar'].pack_forget() self.GUI.menuBars[self.GUI.currentADTBar].pack_forget()