Package Pmv :: Module moleculeViewer
[hide private]
[frames] | no frames]

Source Code for Module Pmv.moleculeViewer

   1  ############################################################################# 
   2  # 
   3  # Author: Michel F. SANNER 
   4  # 
   5  # Copyright: M. Sanner TSRI 2000 
   6  # 
   7  ############################################################################# 
   8   
   9  # $Header: /opt/cvs/python/packages/share1.5/Pmv/moleculeViewer.py,v 1.125.2.1 2007/08/16 21:10:48 vareille Exp $ 
  10   
  11  # 
  12  # $Id: moleculeViewer.py,v 1.125.2.1 2007/08/16 21:10:48 vareille Exp $ 
  13  # 
  14   
  15  from MolKit.molecule import Atom, AtomSet, BondSet, Molecule , MoleculeSet 
  16  from MolKit.protein import Protein, ProteinSet, Residue, Chain, ResidueSet 
  17  from MolKit.stringSelector import CompoundStringSelector 
  18  from DejaVu.Geom import Geom 
  19  from ViewerFramework.VF import ViewerFramework, GeomContainer 
  20  from DejaVu.IndexedPolylines import IndexedPolylines 
  21  from DejaVu.Spheres import Spheres 
  22  from DejaVu.Points import CrossSet 
  23  from DejaVu.Cylinders import Cylinders 
  24  from Pmv.mvCommand import MVInteractiveCmdCaller 
  25  from mglutil.util.packageFilePath import getResourceFolderWithVersion, findFilePath 
  26  from mglutil.util.recentFiles import RecentFiles 
  27  import thread 
  28  from types import StringType, ListType 
  29  import Pmw 
  30  import os 
  31  from Numeric import array, fabs, maximum 
  32  from string import find, replace, split 
  33  from MolKit.tree import TreeNode, TreeNodeSet 
  34   
  35  from mglutil.util.packageFilePath import findFilePath 
  36  ICONPATH = findFilePath('Icons', 'Pmv') 
  37   
38 -class MolGeomContainer(GeomContainer):
39 """ 40 Class to hold geometries used to represent molecules in a viewer. 41 An instance of such a class called geomContainer is added to each Molecule 42 as it is loaded into a Viewer 43 """
44 - def __init__(self, mol, viewer):
45 """constructor of the geometry container""" 46 47 GeomContainer.__init__(self) 48 49 self.mol = mol 50 mol.geomContainer = self 51 52 ## Dictionary of AtomSets used to track which atoms are currently 53 ## each mode 54 self.atoms = {} 55 56 ## Dictionary of function to be called to expand an atomic 57 ## property to the corresponding vertices in a geometry 58 ## The function has to accept 4 arguments: a geometry name, 59 ## a list of atoms, the name of the property and an optional argument 60 ## the propIndex default is None, specifying the index of the property 61 ## when needed. 62 ## the key is the geometry name 63 self.atomPropToVertices = {} 64 65 66 ## Dictionary of function to be called to convert a vertex into an atom 67 ## if no function is registered, used default (1vertex to 1atom) 68 ## mapping 69 ## if None is registered: this geometry cannot represent atoms 70 ## else, call the function registered for this geometry 71 self.geomPickToAtoms = {} 72 73 ## Dictionary of function to be called when a part into a bond 74 ## if no function is registered, used default (1vertex to 1bond) 75 ## mapping 76 ## if None is registered: this geometry cannot represent bonds 77 ## else, call the function registered for this geometry 78 self.geomPickToBonds = {} 79 80 ## this set of coordinates should really be shared by all geometries 81 self.allCoords = mol.allAtoms.coords 82 83 if viewer.hasGui: 84 self.VIEWER = viewer.GUI.VIEWER 85 # master Geometry 86 self.masterGeom = Geom(mol.name, shape=(0,0), 87 pickable=0, protected=True) 88 self.masterGeom.isScalable = 0 89 self.geoms['master'] = self.masterGeom 90 self.masterGeom.replace = True 91 self.VIEWER.AddObject( self.masterGeom ) 92 93 # selection Geometry 94 if viewer.viewSelectionIcon=='cross': 95 self.geoms['selectionSpheres'] = CrossSet( 96 'selection', shape=(0,3), materials=((1.0, 1.0, 0.),), 97 lineWidth=2, inheritMaterial=0, protected=True) 98 elif viewer.viewSelectionIcon=='labels': 99 from DejaVu.glfLabels import GlfLabels 100 self.geoms['selectionSpheres'] = GlfLabels( 101 'selection', shape=(0,3), 102 font='times_new1.glf', 103 bilboard=True, 104 fontScales=(.5,.5,.5), 105 materials=((1.0, 1.0, 0.),), 106 inheritMaterial=0, 107 protected=True) 108 else: 109 self.geoms['selectionSpheres'] = Spheres( 110 'selection', shape=(0,3), radii=0.3, quality = 3, 111 materials = ((1.0, 1.0, 0.),), inheritMaterial=0, protected=True) 112 self.geoms['selectionSpheres'].pickable=0 113 self.VIEWER.AddObject(self.geoms['selectionSpheres'], 114 parent=self.masterGeom, redo=0 )
115 116
117 - def addGeom(self, geom, parent=None, redo=False):
118 # add geometry to to geomContainer, create atom set and set pointer 119 # from geom to molecule 120 121 GeomContainer.addGeom(self, geom, parent, redo) 122 self.atoms[geom.name]=AtomSet([]) 123 # FIXME we should use a weakreference to mol here 124 geom.mol = self.mol #need for backtracking picking
125 126
127 - def getGeomColor(self, geomName):
128 # build a list of colors for a geometry from the atom's colors 129 if self.atomPropToVertices.has_key(geomName): 130 func = self.atomPropToVertices[geomName] 131 geom = self.geoms[geomName] 132 atms = self.atoms[geomName] 133 col = func(geom, atms, 'colors', propIndex=geomName) 134 135 else: 136 if geomName in self.atoms.keys(): 137 col = map(lambda x, geomName=geomName: x.colors[geomName], 138 self.atoms[geomName]) 139 else: 140 return 141 142 if col: 143 colarray = array(col, 'f') 144 diff = colarray - colarray[0] 145 maxi = maximum.reduce(fabs(diff.flat)) 146 if maxi==0: 147 return [colarray[0].tolist()] 148 else: 149 return col
150 151
152 - def updateColors(self, geomName=[], updateOpacity=0):
153 for name in geomName: 154 if geomName=='master': continue 155 if geomName=='selectionSpheres': continue 156 if self.atoms.has_key(name) and len(self.atoms[name])==0: continue 157 col = self.getGeomColor(name) 158 159 if updateOpacity: 160 self.geoms[name].Set( materials = col, redo=1, 161 tagModified=False) 162 opac = self.getGeomOpacity(name) 163 else: opac = None 164 165 if col and opac is not None: 166 self.geoms[name].Set( materials=col, opacity=opac, redo=1, 167 tagModified=False) 168 elif col: 169 self.geoms[name].Set( materials=col, redo=1, tagModified=False) 170 elif opac is not None: 171 self.geoms[name].Set( opacity=opac, redo=1, tagModified=False)
172 173
174 - def getGeomOpacity(self, geomName):
175 if self.atomPropToVertices.has_key(geomName): 176 func = self.atomPropToVertices[geomName] 177 geom = self.geoms[geomName] 178 atms = self.atoms[geomName] 179 col = func(geom, atms, 'opacities', propIndex = geomName) 180 else: 181 if geomName in self.atoms.keys(): 182 col = map(lambda x, geomName=geomName: x.opacities[geomName], 183 self.atoms[geomName]) 184 185 else: 186 return 187 if col: 188 colarray = array(col, 'f') 189 diff = colarray - colarray[0] 190 maxi = maximum.reduce(fabs(diff.flat)) 191 if maxi==0: 192 return colarray[0] 193 else: 194 return col
195 196
197 - def updateOpacity(self, geomName=[]):
198 for name in geomName: 199 if geomName=='master': continue 200 if geomName=='selectionSpheres': continue 201 if len(self.atoms[name])==0: continue 202 col = self.getGeomColor(name) 203 if col: 204 col = array(col, 'f') 205 self.geoms[name].Set( materials = col, redo=1, 206 tagModified=False)
207 208 209 from MolKit.molecule import Molecule, MoleculeSet 210 from ViewerFramework.VFCommand import Command, CommandGUI 211 import Tkinter 212
213 -class MoleculeViewer(ViewerFramework):
214 """ 215 package : Pmv 216 module : moleculeViewer 217 class : MoleculeViewer 218 description: 219 Class derived from the ViewerFramework base class. It provides a 3D 220 molecular viewer. 221 """ 222 223
224 - def getSelLev(self):
225 return self.selection.elementType
226 227
228 - def setSelLev(self, value):
229 if value==Protein: value = Molecule 230 assert value in [Molecule, Chain, Residue, Atom] 231 self.setSelectionLevel(value)
232 233 selectionLevel = property(getSelLev, setSelLev) 234
235 - def __init__(self, title="Molecule Viewer", logMode='no', 236 libraries=[], gui=1, resourceFile = '_pmvrc', 237 customizer = None, master=None, guiVisible=1, 238 withShell=1, verbose=True, trapExceptions=True):
239 """ 240 * title: 241 string used as a title. 242 * logMode: 243 string specifying the mode of logging of mv. 244 'no': for no loging of commands at all 245 'overwrite': the log files overwrite the one from the previous 246 session the log files = mvAll.log.py 247 'unique': the log file name include the date and time 248 249 * libraries: 250 list of the Python packages containing modules and commands 251 that can be loaded in the application. Such a package needs the 252 following files : cmdlib.py and modlib.py 253 * gui : 254 Flag specifying whether or not to run the application with a gui. 255 * resourceFile: 256 file sourced at startup and where userpreference made as default 257 are saved (default: '.pmvrc') 258 * customizer : 259 file when specified is sourced at startup instead of the resourceFile 260 * master: 261 can be specified to run PMV withing another GUI application. 262 * guiVisible: 263 Flag to specify whether or not to show the GUI. 264 - trapExceptions should be set to False when creating a ViewerFramework 265 for testing, such that exception are seen by the testing framework 266 """ 267 libraries = ['Pmv', 'Volume','AutoDockTools'] + libraries 268 _pmvrc = Find_pmvrc(resourceFile) 269 if _pmvrc: 270 resourceFile = _pmvrc 271 272 273 ViewerFramework.__init__(self, title, logMode, libraries, gui, 274 resourceFile, master=master, 275 guiVisible=guiVisible, withShell=withShell, 276 verbose=verbose, trapExceptions=trapExceptions) 277 #if sys.platform == 'win32': #this needed to account for camera size 278 # geometry = '%dx%d+%d+%d' % (800,600, 30, 30) 279 #else: 280 # geometry = '%dx%d+%d+%d' % (800,200, 30, 30) 281 #self.GUI.ROOT.geometry(geometry) 282 283 284 # Establish interface to Visual Programming environment. 285 if self.visionAPI is not None: 286 # add Molecule, Pmv, Viewer to lookup table 287 from Pmv.VisionInterface.PmvNodes import PmvMolecule, PmvNode, \ 288 PmvViewer, PmvSetNode, PmvVolume 289 self.visionAPI.addToLookup(Protein, PmvMolecule, "Molecules") 290 self.visionAPI.addToLookup(MoleculeViewer, PmvNode, "PMV") 291 from DejaVu import Viewer 292 self.visionAPI.addToLookup(Viewer, PmvViewer, "PMV") 293 self.visionAPI.addToLookup(TreeNodeSet, PmvSetNode, "Sets") 294 295 # Note: Molecules are added to the interface in addMolecule() below 296 297 # put Pmv instance into list of objects to be added to Vision 298 self.visionAPI.add(self, "Pmv", kw={ 299 'vf':self, 300 'constrkw':{'vf':'masterNet.editor.vf'} } ) 301 # put Pmv Viewer instance in list of objects to be added to Vision 302 if self.hasGui: 303 self.visionAPI.add(self.GUI.VIEWER, "Pmv Viewer", kw={ 304 'viewer':self.GUI.VIEWER, 305 'constrkw':{'viewer':'masterNet.editor.vf.GUI.VIEWER'} } ) 306 307 self.selection = MoleculeSet() # store current selection 308 # replace interactive command caller by MVInteractiveCmdCaller 309 # we need the ICmdCaller even if there is no GUI because it has 310 # the level variable used byu selection commands 311 self.ICmdCaller = MVInteractiveCmdCaller( self ) 312 from mvCommand import MVSetIcomLevel 313 self.addCommand( MVSetIcomLevel(), 'setIcomLevel', None ) 314 from mvCommand import MVSetSelectionLevel, MVSetSelectionLevelGUI 315 self.addCommand( MVSetSelectionLevel(), 'setSelectionLevel', MVSetSelectionLevelGUI) 316 317 self.setSelectionLevel(Molecule, topCommand = 0) #should this be Protein? 318 from Pmv.displayCommands import BindGeomToMolecularFragment 319 from Pmv.displayCommands import BindGeomToMolecularFragmentGUI 320 321 self.addCommand( BindGeomToMolecularFragment(), 322 'bindGeomToMolecularFragment', 323 BindGeomToMolecularFragmentGUI ) 324 325 # if self.hasGui: 326 # from Pmv.mvCommand import MVPrintNodeNames, MVCenterOnNodes 327 # self.addCommand( MVPrintNodeNames(), 'printNodeNames ', None ) 328 # self.addCommand( MVCenterOnNodes(), 'centerOnNodes', None ) 329 330 # load out default interactive command which prints out object 331 # names 332 #self.ICmdCaller.setCommands( self.printNodeNames ) 333 334 self.ICmdCaller.go() 335 self.addMVBasicMenus() 336 337 # load out default interactive command 338 self.ICmdCaller.setCommands( self.printNodeNames, modifier=None ) 339 self.ICmdCaller.setCommands( self.select, modifier='Shift_L' ) 340 self.ICmdCaller.setCommands( self.centerOnNodes, modifier='Control_L' ) 341 self.ICmdCaller.setCommands( self.deselect, modifier='Alt_L' ) 342 343 #self.setIcomLevel(Molecule, topCommand = 0) 344 self.setIcomLevel(Atom, topCommand = 0) 345 346 self.Mols = MoleculeSet() # store the molecules read in 347 self.objects = self.Mols 348 from MolKit.sets import Sets 349 self.sets = Sets() # store user-defined sets in this dict 350 351 # lock needs to be acquired before volume can be added 352 self.volumesLock = thread.allocate_lock() 353 354 self.Vols = [] # list of Grid3D objects storing volumetric data 355 from Volume.Grid3D import Grid3D 356 self.visionAPI.addToLookup(Grid3D, PmvVolume, "Volumes") 357 358 self.allAtoms = AtomSet() # set of all atoms (across molecules) 359 360 #if self.hasGui: 361 # from Pmv.controlPanelCommands import ControlPanel,ControlPanel_GUI 362 # self.addCommand(ControlPanel(), "controlPanel",ControlPanel_GUI) 363 choices = ['caseSensitive', 'caseInsensitive', 364 'caseInsensWithEscapedChars'] 365 366 self.userpref.add('selectStringMatchMode', 'caseSensitive', validValues=choices, 367 doc = """When set to caseSensitive the string match 368 mode will be case sensitive the other possibility is to be case insensitive or 369 case insensitive with escaped characters. 370 """) 371 choices = [1,0] 372 self.userpref.add('showSelectionSpheres', 1, validValues=choices, 373 doc = """When set to 1 the selection visual feedback 374 which are the little yellow crosses will be displayed.""") 375 choices = [1,0] 376 self.userpref.add('raiseExceptionForMissingKey', 1, validValues=choices, 377 callbackFunc = [self.setRaiseException], 378 doc = """When set to 1 an exception will be raised 379 is a a key is not found in a dictionnary. 380 """) 381 382 choices = [1, 0] 383 self.userpref.add('expandNodeLogString', 0, validValues=choices, 384 doc = """When set to 1 the log string representing 385 the node argument of a doit will be expanded to the full name of each element 386 of the TreeNodeSet, when set to 0 the log string representing the node argument 387 of a doit will be 'self.getSelection()'. In the last case the command log will 388 depend on the current selection.""") 389 390 # overwrite firstObject only with firstMoleculeOnly 391 self.userpref['centerScene']['validValues'][0] = 'firstMoleculeOnly' 392 self.userpref.set('centerScene', 'firstMoleculeOnly') 393 394 choices = ['yes','no'] 395 self.userpref.add('useDepthCueing', 'yes', validValues=choices, 396 doc = """ When set to 'yes' the depthCueing is 397 turned on by default""") 398 399 doc = """When set to yes a warning message is displayed when an empty 400 selection is about to be expanded to all the molecules loaded in the 401 application""" 402 self.userpref.add('warnOnEmptySelection', 'no', validValues=choices, doc=doc) 403 404 if self.hasGui: 405 self.GUI.VIEWER.suspendRedraw = True 406 407 self.GUI.drop_cb = self.drop_cb 408 self.GUI.pickLabel.bind("<Button-1>",self.setSelectionLevel.guiCallback) 409 if self.userpref['useDepthCueing']['value']=='yes': 410 self.GUI.VIEWER.currentCamera.fog.Set(enabled=1, 411 tagModified=False) 412 413 if title != 'AutoDockTools': 414 toolbarDict = {} 415 toolbarDict['name'] = 'ADT' 416 toolbarDict['type'] = 'Checkbutton' 417 toolbarDict['icon1'] = 'adt.png' 418 toolbarDict['balloonhelp'] = 'AutoDock Tools' 419 toolbarDict['icon_dir'] = ICONPATH 420 toolbarDict['index'] = 7 421 toolbarDict['cmdcb'] = self.Add_ADT 422 toolbarDict['variable'] = None 423 self.GUI.toolbarList.append(toolbarDict) 424 self.GUI.configureToolBar(self.GUI.iconsize) 425 # overwrite unsollicited picking with a version that prints atom names 426 #self.GUI.VIEWER.RemovePickingCallback("unsolicitedPick") 427 #self.GUI.VIEWER.AddPickingCallback(self.unsolicitedPick) 428 429 top = self.GUI.ROOT.winfo_toplevel() 430 geom = top.geometry() 431 geom = geom.split('x') 432 self.GUI.menuBars['Toolbar']._frame.update_idletasks() 433 winfo_width = self.GUI.menuBars['Toolbar']._frame.winfo_width() 434 if int(geom[0]) < winfo_width + 10: 435 geom[0] = str(winfo_width + 10) 436 top.geometry(geom[0]+'x'+geom[1]) 437 if not trapExceptions and customizer == './.empty': 438 top.update_idletasks() 439 top.deiconify() 440 #self.GUI.vwrCanvasFloating.deiconify() 441 self.GUI.naturalSize() 442 from Pmv.updateCommands import Update, UpdateGUI 443 self.addCommand( Update(), 'update', UpdateGUI ) 444 445 from Pmv.aboutCommands import About, AboutGUI 446 self.addCommand( About(), 'about', AboutGUI ) 447 448 self.GUI.VIEWER.suspendRedraw = False 449 self.browseCommands('deleteCommands',package='Pmv', topCommand=0) 450 self.GUI.ROOT.bind('<Delete>', self.deleteAtomSet.guiCallback) 451 self.GUI.vwrCanvasFloating.bind('<Delete>', self.deleteAtomSet.guiCallback) 452 self.browseCommands ('dashboardCommands', package='Pmv', topCommand=0) 453 self.customize(customizer) 454 if self.hasGui: 455 try: 456 import UTpackages 457 self.browseCommands("grid3DCommands",package="Pmv", topCommand=0) 458 except ImportError: 459 print "UTpackages are not installed. Disabling grid3DCommands..." 460 461 rcFile = getResourceFolderWithVersion() 462 if rcFile: 463 rcFile += os.sep + 'Pmv' + os.sep + "recent.pkl" 464 465 if self.hasGui: 466 fileMenu = self.GUI.menuBars['menuRoot'].menubuttons['File'].menu 467 468 self.recentFiles = RecentFiles(self, fileMenu, filePath=rcFile, 469 menuLabel = 'Recent Files') 470 try: 471 from DejaVu.Camera import RecordableCamera 472 if isinstance(self.GUI.VIEWER.cameras[0], RecordableCamera): 473 from Pmv.videoCommands import VideoCommand, VideoCommandGUI 474 self.addCommand(VideoCommand(), 'videoCommand', VideoCommandGUI) 475 except: 476 pass 477 #print "Recordable camera is not available" 478 if len(self.dashboard.tree.columns)==0: 479 # this warning is wrong, it appears during test_pmvscript 480 #print "WARNING: update your _pmvrc file to load the dashboard commands" 481 from Pmv.dashboard import loadAllColunms 482 loadAllColunms(self)
483 484
485 - def drop_cb(self, files):
486 for file in files: 487 self.readMolecule(file)
488 489 #def getSelectionLevel(self): 490 # return self.selection.elementType 491 492
493 - def getMolFromName(self, name):
494 mols = filter(lambda x: x.name == name, self.Mols) 495 if len(mols): 496 mol = mols[0] 497 else: 498 mol = None 499 return mol
500
501 - def setRaiseException(self, name, oldval, val):
502 import MolKit.molecule 503 MolKit.molecule.raiseExceptionForMissingKey = val
504 505
506 - def unsolicitedPick(self, pick):
507 """treat an unsollicited picking event""" 508 509 if pick is None: return 510 vi = self.GUI.VIEWER 511 if vi.isShift() or vi.isControl(): 512 vi.unsolicitedPick(pick) 513 else: 514 atom = self.findPickedAtoms(pick) 515 if atom: 516 level = self.ICmdCaller.level.value 517 if level == Molecule: level = Protein 518 node = atom.findType(level) 519 for n in node: 520 self.message( n.full_name() )
521 522
523 - def loadMoleculeIfNeeded(self, filename):
524 """load a molecule only if it doesn't exist yet in Pmv, else it 525 aborts silent""" 526 527 if not os.path.exists(filename): 528 print 'Error! %s not found!'%filename 529 return 530 531 # find what name would be 532 name = os.path.split(filename)[-1] 533 try: 534 spl = split(name, '.') 535 except: 536 spl = [name] 537 name = spl[0] 538 539 # ask if name already used 540 if self.Mols: 541 for mol in self.Mols.data: 542 if name == mol.name: 543 # break and return mol 544 return mol 545 546 # else load molecule 547 if not hasattr(self, 'readMolecule'): 548 self.browseCommands( 549 'fileCommands', 550 commands=['readMolecule'], package='Pmv', topCommand=0) 551 552 mol = self.readMolecule(filename) 553 return mol
554 555
556 - def addMolecule(self, newmol, ask=1):
557 """ 558 Add a molecule to this viewer 559 """ 560 #IN ANY CASE: change any special characters in name to '-' 561 562 from MolKit.molecule import Molecule 563 if self.hasGui: 564 Molecule.configureProgressBar = self.GUI.progressBarConf 565 Molecule.updateProgressBar = self.GUI.progressBarUpd 566 567 spChar=['?','*','.','$','#',':','-',','] 568 ## spChar=['?','*','.','$','#',':','_',','] 569 for item in spChar: 570 newmol.name = replace(newmol.name,item,'_') 571 ## newmol.name = replace(newmol.name,item,'-') 572 if len(self.Mols) > 0: 573 if newmol.name in self.Mols.name: 574 if ask==1: 575 from mglutil.gui.InputForm.Tk.gui import InputFormDescr 576 idf = self.ifd = InputFormDescr(title = '') 577 idf.append({'widgetType':Pmw.EntryField, 578 'name':'newmol', 579 'required':1, 580 'wcfg':{'labelpos':'w', 581 'label_text':'New Name: ', 582 'validate':None, 583 'value':'%s-%d'%(newmol.name, 584 len(self.Mols))}, 585 'gridcfg':{'sticky':'we'}}) 586 587 vals = self.getUserInput(idf) 588 if len(vals)>0: 589 assert not vals['newmol'] in self.Mols.name 590 newmol.name = vals['newmol'] 591 else: 592 return None 593 else: 594 newmol.name='%s_%d'%(newmol.name,len(self.Mols)) 595 596 newmol.allAtoms.setStringRepr(newmol.full_name()+':::') 597 598 # provide hook for progress bar 599 # old code: newmol.allAtoms._bndIndex_ = range(len(newmol.allAtoms)) 600 601 allAtomsLen = len(newmol.allAtoms) 602 if allAtomsLen == 0: 603 import warnings 604 warnings.warn("%s is empty molecule cannot add it to the viewer"%newmol.name) 605 return None 606 if self.hasGui: 607 self.GUI.configureProgressBar(init=1, mode='increment', 608 max=allAtomsLen, 609 labeltext='add molecule to viewer') 610 i = 0 611 for a in newmol.allAtoms: 612 a._bndIndex_ = i 613 if self.hasGui: 614 self.GUI.updateProgressBar() 615 i = i + 1 616 617 g = None 618 if self.hasGui: 619 g = MolGeomContainer( newmol, self ) 620 # addObject calls updateProgressBar on its own 621 self.addObject('mol%s'%len(self.Mols), newmol, g) 622 623 self.Mols.setStringRepr(self.Mols.full_name()) 624 625 # add object to visionAPI (to add them as nodes to Vision library) 626 if self.visionAPI: 627 self.visionAPI.add(newmol, newmol.name, kw={ 628 'molecule':newmol, 629 'constrkw':{ 630 'molecule': 631 'masterNet.editor.vf.expandNodes("%s")[0]'%newmol.name} } ) 632 633 self.allAtoms = self.allAtoms + newmol.allAtoms 634 self.allAtoms.setStringRepr(self.Mols.full_name()+':::') 635 636 #used by cpk command to decide whether or not to compute radii 637 newmol.unitedRadii = None # set to None to force initial radii assignment 638 return newmol
639 640
641 - def addVolume(self, name, grid):
642 # FIXME we need to check for name unicity and have a repalcement policy 643 644 #self.volumesLock.acquire() 645 self.Vols.append(grid) 646 grid.name = name 647 #self.volumesLock.release() 648 649 if self.visionAPI: 650 self.visionAPI.add(grid, name, kw={ 651 'grid':grid, 652 'constrkw':{ 653 'grid': 654 'masterNet.editor.vf.gridFromName("%s")[0]'%grid.name} } )
655 656
657 - def getSelection(self):
658 # FIXME why not return self.Mols always on empty selection ?? 659 # this should speed thing up 660 #ICmdCallerLevel = self.ICmdCaller.level.value 661 selLevel = self.selectionLevel 662 663 if len(self.selection)==0: 664 # empty selection 665 if self.userpref['warnOnEmptySelection']['value']=='yes': 666 if self.askOkCancelMsg('expand empty selection to all molecules?'): 667 #selection = self.Mols.findType(selLevel)#, uniq=1) 668 return self.Mols 669 #try: 670 # selection = self.Mols.findType(selLevel)#, uniq=1) 671 #except: 672 # if selLevel==Molecule: 673 # selection = self.Mols.findType(Protein) 674 #return selection 675 else: 676 #selection = self.Mols.findType(selLevel)#, uniq=1) 677 return self.Mols 678 #try: 679 # selection = self.Mols.findType(selLevel)#, uniq=1) 680 #except: 681 # if selLevel==Molecule: 682 # selection = self.Mols.findType(Protein) 683 #return selection 684 else: 685 #selection = self.Mols.findType(selLevel)#, uniq=1) 686 return self.Mols 687 #try: 688 # selection = self.Mols.findType(selLevel)#, uniq=1) 689 #except: 690 # if selLevel==Molecule: 691 # selection = self.Mols.findType(Protein) 692 #return selection 693 694 else: 695 # not empty select 696 #try: 697 # selection = self.selection.findType(selLevel, uniq=1) 698 #except: 699 # if selLevel==Molecule: 700 # selection = self.selection.findType(Protein) 701 return self.selection
702 #selection = self.selection.findType(selLevel, uniq=1) 703 #return selection 704 705 ## if self.userpref['warnOnEmptySelection']['value']=='yes': 706 ## if self.askOkCancelMsg('expand empty selection to all molecules?'): 707 ## selection = self.Mols.findType(selLevel)#, uniq=1) 708 ## #try: 709 ## # selection = self.Mols.findType(selLevel)#, uniq=1) 710 ## #except: 711 ## # if selLevel==Molecule: 712 ## # selection = self.Mols.findType(Protein) 713 ## return selection 714 ## else: 715 ## selection = self.Mols.findType(selLevel)#, uniq=1) 716 ## #try: 717 ## # selection = self.Mols.findType(selLevel)#, uniq=1) 718 ## #except: 719 ## # if selLevel==Molecule: 720 ## # selection = self.Mols.findType(Protein) 721 ## return selection 722 ## else: 723 ## selection = self.Mols.findType(selLevel)#, uniq=1) 724 ## #try: 725 ## # selection = self.Mols.findType(selLevel)#, uniq=1) 726 ## #except: 727 ## # if selLevel==Molecule: 728 ## # selection = self.Mols.findType(Protein) 729 ## return selection 730 731 ## else: 732 ## # not empty select 733 ## #try: 734 ## # selection = self.selection.findType(selLevel, uniq=1) 735 ## #except: 736 ## # if selLevel==Molecule: 737 ## # selection = self.selection.findType(Protein) 738 ## selection = self.selection.findType(selLevel, uniq=1) 739 ## return selection 740 741
742 - def getItems(self, selString=""):
743 """Takes a string and returns a TreeNodeSet 744 The string can contain a series of set descriptors with operators 745 separated by / characters. There is always a first set, followed by pairs of 746 operators and sets. All sets have to describe nodes of the same level. 747 example: 748 '1crn:::CA*/+/1crn:::O*' describes the union of all CA ans all O in 1crn 749 '1crn:::CA*/+/1crn:::O*/-/1crn::TYR29:' 750 """ 751 assert type(selString)==StringType 752 return self.expandNodes(selString)
753 754
755 - def expandNodes(self, nodes):
756 """Takes nodes as string or TreeNode or TreeNodeSet and returns 757 a TreeNodeSet 758 If nodes is a string it can contain a series of set descriptors with operators 759 separated by / characters. There is always a first set, followed by pairs of 760 operators and sets. All sets ahve to describe nodes of the same level. 761 762 example: 763 '1crn:::CA*/+/1crn:::O*' describes the union of all CA ans all O in 1crn 764 '1crn:::CA*/+/1crn:::O*/-/1crn::TYR29:' 765 """ 766 if isinstance(nodes,TreeNode): 767 result = nodes.setClass([nodes]) 768 result.setStringRepr(nodes.full_name()) 769 770 elif type(nodes)==StringType: 771 stringRepr = nodes 772 css = CompoundStringSelector() 773 result = css.select(self.Mols, stringRepr)[0] 774 ## setsStrings = stringRepr.split('/') 775 ## getSet = self.Mols.NodesFromName 776 ## result = getSet(setsStrings[0]) 777 ## for i in range(1, len(setsStrings), 2): 778 ## op = setsStrings[i] 779 ## arg = setsStrings[i+1] 780 ## if op=='|': # or 781 ## result += getSet(arg) 782 ## elif op=='-': # subtract 783 ## result -= getSet(arg) 784 ## elif op=='&': # intersection 785 ## result &= getSet(arg) 786 ## elif op=='^': # xor 787 ## result ^= getSet(arg) 788 ## elif op=='s': # sub select (i.e. select from previous result) 789 ## result = result.get(arg) 790 ## else: 791 ## raise ValueError, '%s bad operation in selection string'%op 792 ## result.setStringRepr(stringRepr) 793 794 elif isinstance(nodes,TreeNodeSet): 795 result = nodes 796 else: 797 raise ValueError, 'Could not expand nodes %s\n'%str(nodes) 798 799 return result
800 801
802 - def getNodesByMolecule(self, nodes, nodeType=None):
803 """ moleculeSet, [nodeSet, nodeSet] <- getNodesByMolecule(nodes, nodeType=None) 804 nodes can be either: a string, a TreeNode or a TreeNodeSet. 805 This method returns a molecule set and for each molecule a TreeNodeSet 806 of the nodes belonging to this molecule. 807 'nodeType' enables a desired type of nodes to be returned for each 808 molecule 809 """ 810 811 # special case list of complete molecules to be expanded to atoms 812 # this also covers the case where nothing is selected 813 if isinstance(nodes, MoleculeSet) or isinstance(nodes, ProteinSet): 814 if nodeType is Atom: 815 atms = [] 816 for mol in nodes: 817 atms.append(mol.allAtoms) 818 return nodes, atms 819 elif (nodeType is Protein) or (nodeType is Molecule): 820 return nodes, nodes 821 822 # if it is a string, get a bunch of nodes from the string 823 if type(nodes)==StringType: 824 nodes = self.expandNodes(nodes) 825 826 assert issubclass(nodes.__class__, TreeNode) or \ 827 issubclass(nodes.__class__, TreeNodeSet) 828 829 # if nodes is a single TreeNode make it a singleton TreeNodeSet 830 if issubclass(nodes.__class__, TreeNode): 831 nodes = nodes.setClass([nodes]) 832 nodes.setStringRepr(nodes.full_name()) 833 834 if len(nodes)==0: return MoleculeSet([]), [] 835 836 # catch the case when nodes is already a MoleculeSet 837 if nodes.elementType in [Molecule, Protein]: 838 molecules = nodes 839 else: # get the set of molecules 840 molecules = nodes.top.uniq() 841 842 # build the set of nodes for each molecule 843 nodeSets = [] 844 845 # find out the type of the nodes we want to return 846 searchType=0 847 if nodeType is None: 848 Klass = nodes.elementType # class of objects in that set 849 else: 850 assert issubclass(nodeType, TreeNode) 851 Klass = nodeType 852 if Klass != nodes.elementType: 853 searchType=1 854 855 for mol in molecules: 856 # get set of nodes for this molecule 857 mol_nodes = nodes.get(lambda x, mol=mol: x.top==mol) 858 859 # get the required types of nodes 860 if searchType: 861 if Klass == Atom and hasattr(mol_nodes, 'allAtoms'): 862 mol_nodes = mol_nodes.allAtoms 863 else: 864 mol_nodes = mol_nodes.findType( Klass ).uniq() 865 866 stringRepr = nodes.getStringRepr() 867 if stringRepr: 868 if ':' in stringRepr: 869 mol_nodes.setStringRepr( 870 mol.name+stringRepr[stringRepr.index(':'):]) 871 else: 872 mol_nodes.setStringRepr(stringRepr) 873 874 nodeSets.append( mol_nodes ) 875 876 return molecules, nodeSets
877 878
879 - def addMVBasicMenus(self):
880 from Pmv.selectionCommands import MVSelectCommand, MVDeSelectCommand 881 from Pmv.mvCommand import MVPrintNodeNames, MVCenterOnNodes 882 self.addCommand( MVPrintNodeNames(), 'printNodeNames' ) 883 self.addCommand( MVSelectCommand(), 'select' ) 884 self.addCommand( MVDeSelectCommand(), 'deselect' ) 885 self.addCommand( MVCenterOnNodes(), 'centerOnNodes' )
886 887
888 - def findPickedAtoms(self, pick):
889 """ 890 given a PickObject this function finds all corresponding atoms. 891 Each atom in the returned set has its attribute pickedInstances set to a list 892 of 2-tuples [(geom, instance),...]. 893 """ 894 895 allatoms = AtomSet( [] ) 896 # loop over object, i.e. geometry objects 897 for obj, values in pick.hits.items(): 898 899 # build a list of vertices and list of instances 900 instances = map(lambda x: x[1], values) 901 vertInds = map(lambda x: x[0], values) 902 903 # only geometry bound to molecules is packable in PMV 904 if not hasattr(obj, 'mol') or len(vertInds)<1: 905 continue 906 907 # only vertices of geometry have a mapping to atoms 908 # for other types we return an empty atom set 909 if pick.type!='vertices': 910 return allatoms 911 912 g = obj.mol.geomContainer 913 914 # convert vertex indices into atoms 915 if g.geomPickToAtoms.has_key(obj.name): 916 # the geometry obj has a function to convert to atoms 917 # specified it he geomContainer[obj], e.g. MSMS surface 918 func = g.geomPickToAtoms[obj.name] 919 if func: 920 atList = func(obj, vertInds) 921 else: 922 atlist = [] 923 else: 924 # we assume a 1 to 1 mapping of vertices with atoms 925 # e.g. the lines geometry 926 atList = [] 927 allAtoms = g.atoms[obj.name] 928 for i in vertInds: 929 atList.append(allAtoms[int(i)]) 930 931 # build a dict of atoms used to set the pickedAtomInstance 932 # attribute for the last picking operation 933 pickedAtoms = {} 934 935 # update the pickedAtoms dict 936 for i, atom in enumerate(atList): 937 atomInstList = pickedAtoms.get(atom, None) 938 if atomInstList: 939 atomInstList.append( (obj, instances[i]) ) 940 else: 941 pickedAtoms[atom] = [ (obj, instances[i]) ] 942 943 # FIXME atoms might appear multiple times because they were picked 944 # in several geometries OR be cause they correspond to different 945 # instances. In the first case (i.e. multiple geometries) 946 # duplicates should be removed, in the latter (multiple instances) 947 # duplicate should be kept 948 # 949 # Apparently we do not get duplication for multiple geoemtry objects! 950 allatoms = allatoms + AtomSet( atList ) 951 952 # loop over picked atoms and write the instance list into the atom 953 for atom, instances in pickedAtoms.items(): 954 atom.pickedInstances = instances 955 956 #print allAtoms 957 return allatoms
958 959
960 - def findPickedBonds(self, pick):
961 """do a pick operation and return a 2-tuple holding (the picked bond, 962 the picked geometry)""" 963 964 allbonds = BondSet( [] ) 965 for o, val in pick.hits.items(): #loop over geometries 966 # loop over list of (vertices, instance) (e.g. (45, [0,0,2,0])) 967 for instvert in val: 968 primInd = instvert[0] 969 if not hasattr(o, 'mol'): continue 970 g = o.mol.geomContainer 971 if g.geomPickToBonds.has_key(o.name): 972 func = g.geomPickToBonds[o.name] 973 if func: allbonds = allbonds + func(o, primInd) 974 else: 975 l = [] 976 bonds = g.atoms[o.name].bonds[0] 977 for i in range(len(primInd)): 978 l.append(bonds[int(primInd[i])]) 979 allbonds = allbonds + BondSet(l) 980 981 return allbonds
982 983
984 - def transformedCoordinatesWithInstances(self, nodes):
985 """ for a nodeset, this function returns transformed coordinates. 986 This function will use the pickedInstance attribute if found. 987 """ 988 # nodes is a list of atoms, residues, chains, etc. where each member 989 # has a pickedInstances attribute which is a list of 2-tuples 990 # (object, [i,j,..]) 991 vt = [] 992 for node in nodes: 993 #find all atoms and their coordinates 994 coords = nodes.findType(Atom).coords 995 if hasattr(node, 'pickedInstances'): 996 # loop over the pickedInstances of this node 997 for inst in node.pickedInstances: 998 geom, instance = inst # inst is a tuple (object, [i,j,..]) 999 M = geom.GetMatrix(geom.LastParentBeforeRoot(), instance[1:]) 1000 for pt in coords: 1001 ptx = M[0][0]*pt[0]+M[0][1]*pt[1]+M[0][2]*pt[2]+M[0][3] 1002 pty = M[1][0]*pt[0]+M[1][1]*pt[1]+M[1][2]*pt[2]+M[1][3] 1003 ptz = M[2][0]*pt[0]+M[2][1]*pt[1]+M[2][2]*pt[2]+M[2][3] 1004 vt.append( (ptx, pty, ptz) ) 1005 else: 1006 # no picking ==> no list of instances ==> use [0,0,0,...] 1007 g = nodes[0].top.geomContainer.geoms['master'] 1008 M = g.GetMatrix(g.LastParentBeforeRoot()) 1009 for pt in coords: 1010 ptx = M[0][0]*pt[0]+M[0][1]*pt[1]+M[0][2]*pt[2]+M[0][3] 1011 pty = M[1][0]*pt[0]+M[1][1]*pt[1]+M[1][2]*pt[2]+M[1][3] 1012 ptz = M[2][0]*pt[0]+M[2][1]*pt[1]+M[2][2]*pt[2]+M[2][3] 1013 vt.append( (ptx, pty, ptz) ) 1014 1015 return vt
1016
1017 - def Add_ADT(self):
1018 """Adds AutoToolsBar""" 1019 if self.GUI.toolbarCheckbuttons['ADT']['Variable'].get(): 1020 if self.GUI.menuBars.has_key('AutoToolsBar'): 1021 self.GUI.menuBars['AutoToolsBar'].pack(fill='x',expand=1) 1022 else: 1023 self.browseCommands('autotorsCommands', commands = None, 1024 package = 'AutoDockTools') 1025 self.browseCommands('autoflexCommands', commands = None, 1026 package = 'AutoDockTools') 1027 self.browseCommands('autogpfCommands', commands = None, 1028 package = 'AutoDockTools') 1029 self.browseCommands('autodpfCommands', commands = None, 1030 package = 'AutoDockTools') 1031 self.browseCommands('autostartCommands', commands = None, 1032 package = 'AutoDockTools') 1033 self.browseCommands('autoanalyzeCommands', commands = None, 1034 package = 'AutoDockTools') 1035 else: 1036 self.GUI.menuBars['AutoToolsBar'].pack_forget()
1037
1038 -def Find_pmvrc(resourceFile):
1039 """ 1040 This function tries to find resource file for Pmv in the User Home folder. 1041 If it can't find one, it will copy it from Pmv._pmvrc 1042 """ 1043 import mglutil 1044 reload(mglutil) # this is needed for updates 1045 pmvrcFolder = getResourceFolderWithVersion() + os.sep + 'Pmv' 1046 if not os.path.exists(pmvrcFolder): 1047 os.mkdir(pmvrcFolder) 1048 pmvrcFile = pmvrcFolder + os.sep + resourceFile 1049 if not os.path.exists(pmvrcFile): 1050 file_out = open(pmvrcFile,'w') 1051 import Pmv 1052 file_in = open(Pmv.__path__[0] + os.sep + resourceFile ) 1053 file_out.write(file_in.read()) 1054 return pmvrcFile
1055 1056 if __name__ == '__main__': 1057 from Pmv.fileCommands import PDBQReader, PDBReader, PQRReader 1058 import pdb 1059 mv = MoleculeViewer(logMode='no') 1060 import pdb 1061