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

Source Code for Module Pmv.labelCommands

   1  ######################################################################## 
   2  # 
   3  # Date: November 2006 Authors:  
   4  # Authors: Sophie COON, Ruth HUEY, Michel F. SANNER, Guillaume Vareille 
   5  # 
   6  #    vareille@scripps.edu 
   7  #    sanner@scripps.edu 
   8  # 
   9  #       The Scripps Research Institute (TSRI) 
  10  #       Molecular Graphics Lab 
  11  #       La Jolla, CA 92037, USA 
  12  # 
  13  # Copyright: Michel Sanner and TSRI 
  14  # 
  15  ######################################################################### 
  16  # 
  17  # $Header: /opt/cvs/python/packages/share1.5/Pmv/labelCommands.py,v 1.62 2007/01/05 20:21:03 vareille Exp $ 
  18  # 
  19  # $Id: labelCommands.py,v 1.62 2007/01/05 20:21:03 vareille Exp $ 
  20  # 
  21   
  22  """ 
  23  This Module implements commands to label the current selection different ways. 
  24  For example: 
  25      by properties  of the current selection 
  26  """ 
  27  import warnings 
  28  import types,  string, Tkinter, Numeric 
  29  import Pmw 
  30   
  31  from mglutil.gui.BasicWidgets.Tk.colorWidgets import ColorChooser 
  32  from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ListChooser 
  33  from mglutil.util.colorUtil import ToHEX, TkColor 
  34   
  35  from ViewerFramework.VFCommand import CommandGUI 
  36  from mglutil.gui.InputForm.Tk.gui import InputFormDescr, evalString 
  37   
  38  from mglutil.gui.BasicWidgets.Tk.customizedWidgets import LoadOrSaveText,FunctionButton 
  39  from Pmv.mvCommand import MVCommand, MVAtomICOM 
  40   
  41  from MolKit.tree import TreeNode, TreeNodeSet 
  42  from MolKit.molecule import Molecule, Atom, AtomSet, MoleculeSet 
  43  from MolKit.protein import Protein, Residue, Chain, ResidueSet, ChainSet, ProteinSet 
  44   
  45  from DejaVu.glfLabels import GlfLabels 
  46      
  47   
48 -class LabelByProperties(MVCommand, MVAtomICOM):
49 """selector.selection,property,textcolor,font,location,only,negate,funcItems Command to label the current selection items according to different properties of the selection level (Actually of the first item in the current selection.) Color can be specified as 'red','green','blue','white' or 'yellow'. Other values can be entered as a RGB tuple.One font can selected per label level: Atom,Residue,Chain,Molecule.Labels can be centered on first atom of selection level item, last atom of item or on the center of the item which is found by averaging the coordinates of all the atoms in the item. (eg all atoms in a residue if labelling at the Residue Level) 50 \nPackage : Pmv 51 \nModule : labelCommands 52 \nClass : LabelByProperties 53 \nCommand : labelByProperty 54 \nSynopsis:\n 55 None<-labelByProperty(nodes, prop, textcolor, font, location,only, negate, funcItems, format, kw) 56 \nRequired Arguments:\n 57 nodes --- TreeNodeSet holding the current selection 58 \nOptional Arguments:\n 59 prop --- attribute to use for label (default 'name') 60 \ntextcolor --- colorname or RGB tuple (default 'white') 61 \nfont --- font understood by DejaVu (default 'Helvetica12') 62 \nlocation --- 'First', 'Center', 'Last' atom in node (default 'Center') 63 \nonly --- show this label only 64 \nnegate --- Boolean flag to toggle visibility of label 65 \nformat --- format string for label 66 """ 67
68 - def __init__(self, func=None):
69 #print "LabelByProperties.__init__"#, self 70 MVCommand.__init__(self, func) 71 MVAtomICOM.__init__(self) 72 self.flag = self.flag | self.negateKw 73 self.flag = self.flag | self.objArgOnly 74 75 self.colorDict={'red':(1,0,0), 'green':(0,1,0), 'blue':(0,0,1), 76 'yellow':(1,1,0), 'cyan':(0,1,1), 77 'white':(1,1,1), 'fushia':(1.,0.,0.5), 78 'purple':(1.,0.,1.), 'orange':(1.,0.6,0.)} 79 80 self.lastGeomOwnGuiShown = None
81 82
83 - def atomPropToVertices(self, geom, atoms, propName, propIndex=None):
84 if len(atoms)==0: return None 85 geomName = string.split(geom.name,'_')[0] 86 prop = [] 87 if propIndex is not None: 88 if not isinstance(atoms[0], Atom): 89 for x in atoms: 90 a = x.findType(Atom)[0] 91 d = getattr(a, propName) 92 prop.append(d[propIndex]) 93 else: 94 for a in atoms: 95 d = getattr(a, propName) 96 prop.append(d[propIndex]) 97 98 else: 99 if not isinstance(atoms[0], Atom): 100 for x in atoms: 101 a = x.findType(Atom)[0] 102 prop.append( getattr(a, propName) ) 103 else: 104 for a in atoms: 105 prop.append( getattr(a, propName) ) 106 return prop
107 108
109 - def onAddCmdToViewer(self):
110 if self.vf.hasGui: 111 self.properties = [] 112 self.colorIndex = 0 113 self.molDict = {'Molecule':Molecule, 114 'Atom':Atom, 'Residue':Residue, 'Chain':Chain} 115 self.nameDict = {Molecule:'Molecule', Atom:'Atom', Residue:'Residue', 116 Chain:'Chain'} 117 self.leveloption={} 118 for name in ['Atom', 'Residue', 'Molecule', 'Chain']: 119 col = self.vf.ICmdCaller.levelColors[name] 120 bg = TkColor((col[0]/1.5,col[1]/1.5,col[2]/1.5)) 121 ag = TkColor(col) 122 self.leveloption[name]={'bg':bg,'activebackground':ag, 123 'borderwidth':3}
124 125
126 - def onAddObjectToViewer(self, obj):
127 #print "LabelByProperties.onAddObjectToViewer", self.name 128 if not self.vf.hasGui: 129 return 130 #from DejaVu.Labels import Labels 131 geomC = obj.geomContainer 132 classNames = ['Atom','Residue','Chain','Protein'] 133 self.level = self.nameDict[self.vf.selectionLevel] 134 #for item in classNames: 135 for i in range(len(classNames)): 136 item = classNames[i] 137 #geomName = eval("'%sLabels'" %item) 138 geomName = '%sLabels'%item 139 for atm in obj.allAtoms: 140 atm.colors[geomName] = (1.0, 1.0, 1.0) 141 atm.opacities[geomName] = 1.0 142 if not geomC.atoms.has_key(geomName): 143 # DON'T KNOW HOW TO REPLACE THIS EVAL 144 geomC.atoms[geomName]=eval("%sSet()" %item) 145 geomC.atomPropToVertices[geomName] = self.atomPropToVertices 146 147 if not geomC.geoms.has_key(geomName): 148 j = i + 1 149 g = GlfLabels(geomName, 150 #inheritMaterial=0, 151 fontTranslation=(0,0,.2), # so the label is less hidden by the structure 152 fontScales=(j*.3,j*.3,j*.3), # different size for atom, res, chain, mol 153 visible=0, 154 pickable=0, 155 ) 156 geomC.addGeom(g, parent=geomC.masterGeom,redo=0) 157 else: 158 g = geomC.VIEWER.FindObjectByName(geomC.masterGeom.fullName+'|'+geomName) 159 if g not in self.managedGeometries: 160 self.managedGeometries.append(g)
161 162
163 - def update_cb(self, tag, force=False):
164 #print "in update_cb with tag=", tag 165 if tag!=self.level or force: 166 self.level = tag 167 #if self.molDict[tag] != self.vf.ICmdCaller.level.value: 168 #self.vf.setIcomLevel(self.molDict[tag]) 169 self.selection=self.vf.getSelection().uniq().findType(self.molDict[tag]).uniq() 170 self.selection.sort() 171 if tag == 'Atom': 172 if self.selection[0].chargeSet: 173 self.selection[0].charge = self.selection[0].__getattr__('charge') 174 self.updateChooser() 175 176 if self.lastGeomOwnGuiShown is not None \ 177 and self.lastGeomOwnGuiShown.ownGui.winfo_ismapped() == 1: 178 self.labelsSettings_cb()
179 180
181 - def updateChooser(self):
182 if not hasattr(self, 'properties'): self.properties = [] 183 oldProp = self.properties 184 self.properties = filter(lambda x: type(x[1]) is types.IntType \ 185 or type(x[1]) is types.FloatType or \ 186 type(x[1]) is types.StringType, 187 self.selection[0].__dict__.items()) 188 # Filter out the private members starting by __. 189 self.properties = filter(lambda x: x[0][:2]!='__', self.properties) 190 if not self.cmdForms.has_key('default'): return 191 descr = self.cmdForms['default'].descr 192 if oldProp != self.properties: 193 # If the list of properties changed then need to update the listchooser 194 widget = descr.entryByName['properties']['widget'] 195 propertyNames = map(lambda x: (x[0],None), self.properties) 196 propertyNames.sort() 197 widget.setlist(propertyNames)
198 199
200 - def buildFormDescr(self, formName='default'):
201 if formName == 'default': 202 # create the form descriptor 203 formTitle = "Label" + self.vf.ICmdCaller.level.value.__name__ +\ 204 " by properties" 205 idf = InputFormDescr(title = formTitle) 206 #val = self.nameDict[self.vf.ICmdCaller.level.value] 207 val = self.level 208 idf.append({'name':'display', 209 'widgetType':Pmw.RadioSelect, 210 'listtext':['label','label only', 'unlabel'], 211 'defaultValue':'label', 212 'wcfg':{'orient':'horizontal', 213 'buttontype':'radiobutton'}, 214 'gridcfg':{'sticky': 'we','columnspan':3}}) 215 216 idf.append({'widgetType':Tkinter.Label, 217 'wcfg':{'text':'________________________________________________________', 218 }, 219 'gridcfg':{'columnspan':3}}) 220 221 idf.append({'widgetType':Pmw.RadioSelect, 222 'name':'level', 223 'listtext':['Atom','Residue','Chain','Molecule'], 224 'listoption':self.leveloption,#listoption, 225 'defaultValue':val, 226 'wcfg':{'label_text':'Change the PCOM level:', 227 'labelpos':'nw', 228 'command':self.update_cb, 229 }, 230 'gridcfg':{'sticky':'we','columnspan':3}}) 231 232 if len(self.properties)>0: 233 propertyNames = map(lambda x: (x[0], None), self.properties) 234 propertyNames.sort() 235 236 idf.append({'name':'properties', 237 'widgetType':ListChooser, 238 'defaultValue':'name', 239 'wcfg':{'entries': propertyNames, 240 'title':'Choose one or more properties:', 241 'lbwcfg':{'exportselection':0}, 242 'mode':'multiple','withComment':0}, 243 'gridcfg':{'sticky':'we', 'rowspan':4, 'padx':5}}) 244 245 self.textColor = (1.,1.,1.) 246 idf.append({'widgetType':Tkinter.Button, 247 'name':'textcolor', 248 'wcfg':{'text':'Choose Label Color:', 249 'command':self.chooseColor_cb, 250 'bg':'white', 'activebackground':'white', 251 'borderwidth':4, 252 }, 253 'gridcfg':{'sticky':'w','row':3, 'column':1}}) 254 255 idf.append({'name':'Labels settings', 256 'widgetType':Tkinter.Button, 257 'wcfg':{'text': 'Labels settings', 258 'command':self.labelsSettings_cb 259 }, 260 'gridcfg':{'row':4,'column':1, 'sticky':'we'}}) 261 262 location = ['First','Center' ,'Last'] 263 idf.append({'widgetType':Pmw.ComboBox, 264 'name':'location', 265 'defaultValue':'Center', 266 'wcfg':{'label_text':'Label location: ', 267 'labelpos':'nw', 268 'scrolledlist_items': location}, 269 'gridcfg':{'sticky':'w','row':5,'column':1}}) 270 formats = ['%d','%4.2f','%f','None'] 271 idf.append({'widgetType':Pmw.ComboBox, 272 'name':'format', 273 'defaultValue' : 'None', 274 'wcfg':{'label_text':'Label format: ', 275 'labelpos':'nw', 276 'scrolledlist_items': formats}, 277 'gridcfg':{'sticky':'w','row':6,'column':1}}) 278 279 return idf 280 281 elif formName=='chooser': 282 idf = InputFormDescr(title = 'Choose Color') 283 284 idf.append({'widgetType':ColorChooser, 285 'name':'colors', 286 'wcfg':{'commands':self.configureButton, 287 'exitFunction':self.dismiss_cb}, 288 'gridcfg':{'sticky':'wens', 'columnspan':3, 289 } 290 }) 291 return idf
292 293
294 - def getRelatedLabelsGeom(self):
295 molecules, nodeSets = self.vf.getNodesByMolecule(self.selection) 296 for mol, nodes in map(None, molecules, nodeSets): 297 break 298 nodes.sort() 299 geomName = nodes[0].__class__.__name__+'Labels' 300 labelsGeom = mol.geomContainer.geoms[geomName] 301 return labelsGeom
302 303
304 - def labelsSettings_cb(self):
305 #print "labelsSettings_cb", self.lastGeomOwnGuiShown 306 if self.lastGeomOwnGuiShown is not None: 307 self.lastGeomOwnGuiShown.hideOwnGui() 308 labelsGeom = self.getRelatedLabelsGeom() 309 labelsGeom.showOwnGui() 310 self.lastGeomOwnGuiShown = labelsGeom
311 312
313 - def dismiss_cb(self):
314 self.cmdForms['chooser'].withdraw() 315 self.cmdForms['default'].grabFocus()
316 317
318 - def configureButton(self, col):
319 f = self.cmdForms['default'] 320 bg = ToHEX(col) 321 but = f.descr.entryByName['textcolor']['widget'] 322 but.configure(bg=bg, activebackground=bg) 323 self.textColor = col
324 325
326 - def chooseColor_cb(self):
327 form = self.showForm('chooser', modal=0, blocking=0) 328 self.cmdForms['default'].releaseFocus() 329 form.grabFocus()
330 331
332 - def getLastUsedValues(self, formName='default', **kw):
333 """Return dictionary of last used values 334 """ 335 values = self.lastUsedValues[formName].copy() 336 values.pop('font') 337 return values
338 339
340 - def guiCallback(self):
341 342 self.selection = self.vf.getSelection() 343 if len(self.selection) == 0 : return 344 ##FIX THIS WHEN MolKit gets straightened out: 345 self.level = self.nameDict[self.vf.selectionLevel] 346 if isinstance(self.selection, MoleculeSet): 347 self.selection = ProteinSet(self.selection) 348 itemName = self.selection[0].__class__.__name__ 349 self.updateChooser() 350 351 # Update the level if the form exists already. 352 if self.cmdForms.has_key('default'): 353 descr = self.cmdForms['default'].descr 354 levelwid = descr.entryByName['level']['widget'] 355 oldlevel =levelwid.getcurselection() 356 #if oldlevel != self.nameDict[self.vf.ICmdCaller.level.value]: 357 # levelwid.invoke(self.nameDict[self.vf.ICmdCaller.level.value]) 358 if oldlevel != self.level: 359 levelwid.invoke(self.level) 360 361 val = self.showForm('default', modal=0, blocking=1) 362 if self.cmdForms.has_key('chooser'): 363 self.cmdForms['chooser'].withdraw() 364 365 if not val: return 366 val['textcolor'] = self.textColor 367 368 lLabelsGeom = self.getRelatedLabelsGeom() 369 lLabelsState = lLabelsGeom.getSubClassState() 370 lLabelsState.pop('labels') # appart from the labels themselves we want everything 371 val['font'] = lLabelsState 372 373 if not val['location']: val['location'] = 'center' 374 else: val['location'] = val['location'][0] 375 376 if not val['format'] or val['format'] == ('None',): 377 val['format'] = None 378 else: val['format'] = val['format'][0] 379 380 if val['display']=='label': 381 val['only']= 0 382 val['negate'] = 0 383 del val['display'] 384 elif val['display']=='label only': 385 val['only']= 1 386 val['negate'] = 0 387 del val['display'] 388 elif val['display']== 'unlabel': 389 val['negate'] = 1 390 val['only'] = 0 391 del val['display'] 392 val['redraw'] = 1 393 if val.has_key('level'): del val['level'] 394 395 if self.lastGeomOwnGuiShown is not None: 396 self.lastGeomOwnGuiShown.hideOwnGui() 397 398 #apply(self.doitWrapper, (self.vf.getSelection(),), val) 399 apply(self.doitWrapper, (self.selection,), val)
400 401
402 - def __call__(self, nodes, properties=['name',], textcolor='white', 403 font='arial1.glf', location='Center', only=False, 404 negate=False, format=None, **kw):
405 """None<-labelByProperty(nodes, prop, textcolor, font, location,only, negate, funcItems, format, kw) 406 \nnodes --- TreeNodeSet holding the current selection 407 \nprop --- attribute to use for label (default 'name') 408 \ntextcolor --- colorname or RGB tuple (default 'white') 409 \nfont --- font understood by DejaVu (default 'arial1.glf') 410 \nlocation --- 'First', 'Center', 'Last' atom in node (default 'Center') 411 \nonly --- show this label only 412 \nnegate --- Boolean flag to toggle visibility of label 413 \nformat --- format string for label 414 """ 415 #print "__call__" 416 kw['properties']=properties 417 kw['textcolor']=textcolor 418 kw['font']=font 419 kw['location']=location 420 kw['only']=only 421 kw['negate']=negate 422 kw['format']=format 423 if type(nodes) is types.StringType: 424 self.nodeLogString = "'"+nodes+"'" 425 self.vf.expandNodes(nodes) 426 if not kw.has_key('redraw'): 427 kw['redraw']=1 428 apply(self.doitWrapper, (nodes,), kw)
429 430
431 - def doit(self, nodes, properties=['name',], textcolor='white', 432 font={}, location='Center', only=False, negate=False, 433 format=None):
434 435 ################################################################### 436 def drawLabels(mol, nodes, materials, properties, 437 font, location, only, negate, format): 438 geomName = nodes[0].__class__.__name__+'Labels' 439 labelGeom = mol.geomContainer.geoms[geomName] 440 441 set = mol.geomContainer.atoms[geomName] 442 ####if negate, remove current atms from displayed set 443 ##if negate: 444 ##set = set - nodes 445 ##if only, replace displayed set with current atms 446 ##else: 447 ##if only: 448 ##set = nodes 449 ##else: 450 ##set = nodes.union(set) 451 ##3/11 452 ##if negate and a previous set, 453 ##remove current atms from displayed set 454 if negate: 455 if len(set): 456 set = set - nodes 457 ##if only or there were no labels, label current atms 458 elif only or not len(set): 459 set = nodes 460 ##not negate, not only and some previous labels, 461 ## label union of old + new 462 else: 463 set = nodes.union(set) 464 465 ##now, update the geometries: 466 # draw atoms with bonds and without bonds 467 if len(set)==0: 468 labelGeom.Set(vertices=[], labels=[], tagModified=False) 469 mol.geomContainer.atoms[geomName] = set 470 return 471 472 # 1st lines need to store the wole set in the 473 # mol.geomContainer.atoms['lines'] because of the picking. 474 mol.geomContainer.atoms[geomName] = set 475 propLabels = [""]*len(set) 476 for property in properties: 477 if type(property) is types.StringType: 478 try: 479 #newPropLabels = eval('set.%s'%property) 480 newPropLabels = getattr(set, property) 481 except KeyError: 482 msg= "all nodes do not have such a property" 483 self.warningMsg(msg) 484 newPropLabels =list("_"*len(set)) 485 486 else: 487 continue 488 489 assert len(newPropLabels) == len(propLabels) 490 for i in range(len(newPropLabels)): 491 item = newPropLabels[i] 492 if format: 493 try: 494 item = format%newPropLabels[i] 495 except: 496 item = str(newPropLabels[i]) 497 ###print item 498 else: 499 item = str(newPropLabels[i]) 500 if propLabels[i] =="" : 501 propLabels[i] = propLabels[i]+item 502 else: 503 propLabels[i] = propLabels[i]+";"+item 504 propLabels=tuple(propLabels) 505 propCenters=[] 506 for item in set: 507 z = item.findType(Atom) 508 if location=='First': 509 z=z[0] 510 zcoords = Numeric.array(z.coords) 511 zcoords = zcoords+0.2 512 zcoords = zcoords.tolist() 513 propCenters.append(zcoords) 514 elif location=='Center': 515 zcoords = Numeric.array(z.coords) 516 zcoords = Numeric.sum(zcoords)/(len(zcoords)*1.0) 517 zcoords = zcoords.tolist() 518 propCenters.append(zcoords) 519 if location=='Last': 520 z=z[-1] 521 zcoords = Numeric.array(z.coords) 522 zcoords = zcoords+0.2 523 zcoords = zcoords.tolist() 524 propCenters.append(zcoords) 525 propCenters = tuple(propCenters) 526 colors = (materials,) 527 528 if isinstance(font, dict): 529 apply( GlfLabels.Set, (labelGeom, 1, 0), font) 530 else: 531 labelGeom.Set(font=font, redo=0) 532 labelGeom.Set(labels=propLabels, 533 vertices=propCenters, 534 materials=colors, 535 visible=1, 536 tagModified=False, 537 inheritMaterial=False, 538 )
539 ################################################################### 540 541 542 if len(nodes) == 0: return 543 if (type(textcolor) is types.TupleType or type(textcolor) is types.ListType)\ 544 and len(textcolor)==3: 545 materials = textcolor 546 547 elif self.colorDict.has_key(textcolor): 548 materials = self.colorDict[textcolor] 549 elif len(textcolor)>0 and textcolor[0]=='(': 550 textlist=string.split(textcolor[1:-1],',') 551 try: 552 materials = (float(textlist[0]), 553 float(textlist[1]), 554 float(textlist[2])) 555 except ValueError: 556 warnings.warn("Invalid number entered: %s" %textcolor) 557 except IndexError: 558 warnings.warn("IndexError for %s" %textcolor) 559 molecules, nodeSets = self.vf.getNodesByMolecule(nodes) 560 561 for mol, nodes in map(None, molecules, nodeSets): 562 nodes.sort() 563 drawLabels(mol, nodes, materials, 564 properties , font, location, only, negate, format)
565 566
567 -class LabelByExpression(LabelByProperties):
568 """Command to label the current selection items according to different expressions of the selection level (Actually of the first item in the current selection.) Color can be specified as 'red','green','blue','white' or 'yellow'. Other values can be entered as a RGB tuple.One font can selected per label level: Atom,Residue,Chain,Molecule.Labels can be centered on first atom of selection level item, last atom of item or on the center of the item which is found by averaging the coordinates of all the atoms in the item. (eg all atoms in a residue if labelling at the Residue Level) 569 \nPackage : Pmv 570 \nModule : labelCommands 571 \nClass : LabelByExpression 572 \nCommand : labelByExpression 573 \nSynopsis:\n 574 None <--- labelByExpression(nodes,function='lambda x: x.full_name()', 575 lambdaFunc = 1, textcolor='white', font='arial1.glf', 576 location='Center', only=0, negate=0, format=None, **kw) 577 \nRequired Arguments:\n 578 nodes --- TreeNode, TreeNodeSet or string representing a TreeNode 579 or a TreeNodeSet holding the current selection. 580 \nOptional Arguments:\n 581 function --- function definition or lambda function returning a 582 list of strings that will used to label the selection. 583 \nlambdaFunc --- Boolean flag when set to True the function is a lambda function 584 otherwise it is a regular function. 585 \ntextcolor --- string representing the color of the label can also be 586 a rgb tuple (r,g,b). 587 \nfont --- Font of the label 588 \nlocation --- Can be one of Center, First or Last specifies the location 589 of the label. 590 \nformat --- Default is None string format of the label can be %4.2f 591 \nonly --- Boolean flag when set to True only the selection is labeled when set 592 to 0 label are added to the existing labels. 593 \nnegate --- Boolean flag when set to True the selection is unlabeled 594 """ 595 # comments for map function definition window 596 mapLabel = """Define a function or a lambda function to be applied 597 on each node of the current selection: """ 598 599 # code example for map function definition window 600 mapText = '\ 601 #def foo(node):\n\ 602 #\t#property <- foo(node)\n\ 603 #\t#property : string that will be used for labelling\n\ 604 #\t#node : node from the current selection\n\ 605 #\t#foo will then be applied to each node from the current selection.\n\ 606 #\treturn str(node.full_name())\n\ 607 #OR\n\ 608 #lambda x: str(x.full_name())\n' 609 610 # comments for function to operate on selection 611 funcLabel = """Define a function to be applied to 612 the current selection:""" 613 614 # code example for function to operate on selection 615 funcText ='\ 616 #def foo(selection):\n\ 617 #\t#values <- foo(node)\n\ 618 #\t#values : list of string used for labelling\n\ 619 #\t#selection: current selection.\n\ 620 #\tvalues = []\n\ 621 #\t#loop on the current selection\n\ 622 #\tfor i in xrange(len(selection)):\n\ 623 #\t\t#build a list of values to label the current selection.\n\ 624 #\t\tif not hasattr(selection[i], "number"):\n\ 625 #\t\t\tvalues.append("-")\n\ 626 #\t\telse:\n\ 627 #\t\t\tif selection[i].number > 20:\n\ 628 #\t\t\t\tvalues.append(selection[i].number*2)\n\ 629 #\t\t\telse:\n\ 630 #\t\t\t\tvalues.append(selection[i].number)\n\ 631 #\t# this list of values is then returned.\n\ 632 #\treturn values\n' 633
634 - def updateInfo_cb(self, value):
635 if not self.cmdForms.has_key('default'): return 636 widget = self.cmdForms['default'].descr.entryByName['function']['widget'] 637 changed = 0 638 if value == 'lambda function': 639 if self.textLabel != self.mapLabel: 640 self.textLabel = self.mapLabel 641 self.textContent = self.mapText 642 changed = 1 643 elif value == 'function': 644 if self.textLabel != self.funcLabel: 645 self.textLabel = self.funcLabel 646 self.textContent = self.funcText 647 changed = 1 648 if changed: 649 widget.text.configure(label_text = self.textLabel) 650 widget.text.settext(self.textContent)
651 652
653 - def update_cb(self, tag):
654 if tag!=self.level: 655 self.level = tag 656 #if self.molDict[tag] != self.vf.ICmdCaller.level.value: 657 # self.vf.setIcomLevel(self.molDict[tag]) 658 self.selection = self.vf.getSelection().uniq().findType(self.molDict[tag]).uniq() 659 self.selection.sort()
660 661
662 - def buildFormDescr(self, formName='default'):
663 if formName == 'default': 664 # Create the form descriptor: 665 formTitle = "Label by expression" 666 idf = InputFormDescr(title = formTitle) 667 668 idf.append({'name':'display', 669 'widgetType':Pmw.RadioSelect, 670 'listtext':['label','label only', 'unlabel'], 671 'defaultValue':'label', 672 'wcfg':{'orient':'horizontal', 673 'buttontype':'radiobutton'}, 674 'gridcfg':{'sticky': 'we','columnspan':3}}) 675 676 idf.append({'widgetType':Tkinter.Label, 677 'wcfg':{'text':'________________________________________________________', 678 }, 679 'gridcfg':{'columnspan':3}}) 680 #val = self.nameDict[self.vf.ICmdCaller.level.value] 681 val = self.level 682 idf.append({'widgetType':Pmw.RadioSelect, 683 'name':'level', 684 'listtext':['Atom','Residue','Chain','Molecule'], 685 'defaultValue':val,'listoption':self.leveloption,#listoption, 686 'wcfg':{'label_text':'Select the property level:', 687 'labelpos':'nw', 688 'command':self.update_cb, 689 }, 690 'gridcfg':{'sticky':'we','columnspan':3}}) 691 692 idf.append({'name':'functiontype', 693 'widgetType':Pmw.RadioSelect, 694 'listtext':['lambda function', 'function'], 695 'defaultValue':'lambda function', 696 'wcfg':{'label_text':'Choose Expression type:', 697 'labelpos':'nw','orient':'horizontal', 698 'buttontype':'radiobutton', 699 'command':self.updateInfo_cb, 700 }, 701 'gridcfg':{'sticky': 'we'}}) 702 703 self.textContent = self.mapText 704 self.textLabel = self.mapLabel 705 idf.append({'name':'function', 706 'widgetType':LoadOrSaveText, 707 'defaultValue': self.textContent, 708 'wcfg':{'textwcfg':{'labelpos':'nw', 709 'label_text': self.textLabel, 710 'usehullsize':1, 711 'hull_width':500, 712 'hull_height':280, 713 'text_wrap':'none'}, 714 }, 715 'gridcfg':{'sticky': 'we','rowspan':4, 'padx':5}}) 716 717 idf.append({'widgetType':Tkinter.Label, 718 'wcfg':{'text':""}, 719 'gridcfg':{'row':-1}}) 720 721 self.textColor = (1.,1.,1.) 722 idf.append({'widgetType':Tkinter.Button, 723 'name':'textcolor', 724 'wcfg':{'text':'Choose Label Color:', 725 'command':self.chooseColor_cb,'borderwidth':4, 726 'bg':'white', 'activebackground':'white', 727 }, 728 'gridcfg':{'sticky':'w','row':4,'column':1}}) 729 730 idf.append({'widgetType':Pmw.ComboBox, 731 'name':'font', 732 'defaultValue':GlfLabels.fontList[0], 733 'wcfg':{'label_text':' Label font:', 734 'labelpos':'nw', 735 'scrolledlist_items': GlfLabels.fontList}, 736 'gridcfg':{'sticky':'we','row':5,'column':1 }}) 737 738 location = ['First','Center' ,'Last'] 739 idf.append({'widgetType':Pmw.ComboBox, 740 'name':'location', 741 'defaultValue':'Center', 742 'wcfg':{'label_text':'Label location: ', 743 'labelpos':'nw', 744 'scrolledlist_items': location}, 745 'gridcfg':{'sticky':'w','row':6,'column':1}}) 746 formats = ['%d','%4.2f','%f', 'None'] 747 idf.append({'widgetType':Pmw.ComboBox, 748 'name':'format', 749 'defaultValue': 'None', 750 'wcfg':{'label_text':'Label format: ', 751 'labelpos':'nw', 752 'scrolledlist_items': formats}, 753 'gridcfg':{'sticky':'w','row':7,'column':1}}) 754 755 return idf 756 757 elif formName=='chooser': 758 idf = InputFormDescr(title = 'Choose Color') 759 760 idf.append({'widgetType':ColorChooser, 761 'name':'colors', 762 'wcfg':{'commands':self.configureButton, 763 'exitFunction':self.dismiss_cb}, 764 'gridcfg':{'sticky':'wens', 'columnspan':3} 765 }) 766 return idf
767 768
769 - def guiCallback(self):
770 self.selection = self.vf.getSelection() 771 if len(self.selection) == 0 : return 772 self.level = self.nameDict[self.vf.selectionLevel] 773 val = self.showForm('default') 774 if self.cmdForms.has_key('chooser'): 775 self.cmdForms['chooser'].withdraw() 776 777 # Update the level if the form exists already. 778 if self.cmdForms.has_key('default'): 779 descr = self.cmdForms['default'].descr 780 levelwid = descr.entryByName['level']['widget'] 781 oldlevel = levelwid.getcurselection() 782 #if oldlevel != self.nameDict[self.vf.ICmdCaller.level.value]: 783 #levelwid.invoke(self.nameDict[self.vf.ICmdCaller.level.value]) 784 if oldlevel != self.level: 785 levelwid.invoke(self.level) 786 787 788 if not val: return 789 val['textcolor'] = self.textColor 790 791 if not val['font']: val['font'] = 'arial1.glf' 792 else: val['font'] = val['font'][0] 793 794 if not val['location']: val['location'] = 'center' 795 else: val['location'] = val['location'][0] 796 797 if not val['format'] or val['format'] == ('None',): 798 val['format'] = None 799 else: val['format'] = val['format'][0] 800 801 if val['functiontype'] == 'lambda function': 802 val['lambdaFunc'] = 1 803 del val['functiontype'] 804 805 elif val['functiontype'] == 'function': 806 val['lambdaFunc'] = 0 807 del val['functiontype'] 808 809 if val['display']=='label': 810 val['only']= 0 811 val['negate'] = 0 812 del val['display'] 813 814 elif val['display']=='label only': 815 val['only']= 1 816 val['negate'] = 0 817 del val['display'] 818 elif val['display']== 'unlabel': 819 val['negate'] = 1 820 val['only'] = 0 821 del val['display'] 822 if val.has_key('level'): del val['level'] 823 val['redraw'] = 1 824 apply(self.doitWrapper, (self.selection,), val)
825 #apply(self.doitWrapper, (self.vf.getSelection(),), val) 826 827
828 - def __call__(self, nodes, function='lambda x: x.full_name()', 829 lambdaFunc=True, textcolor='white', font='arial1.glf', 830 location='Center', only=False, negate=False, format=None, **kw):
831 """None <--- labelByExpression(nodes,function='lambda x: x.full_name()', 832 lambdaFunc = 1, textcolor='white', font='arial1.glf', 833 location='Center', only=0, negate=0, format=None, **kw) 834 \nnodes --- TreeNode, TreeNodeSet or string representing a TreeNode 835 or a TreeNodeSet holding the current selection. 836 \nfunction --- function definition or lambda function returning a 837 list of strings that will used to label the selection. 838 \nlambdaFunc --- Boolean flag when set to True the function is a lambda function 839 otherwise it is a regular function. 840 \ntextcolor --- string representing the color of the label can also be 841 a rgb tuple (r,g,b). 842 \nfont --- Font of the label 843 \nlocation --- Can be one of Center, First or Last specifies the location 844 of the label. 845 \nformat --- Default is None string format of the label can be %4.2f 846 \nonly --- Boolean flag when set to True only the selection is labeled when set 847 to 0 label are added to the existing labels. 848 \nnegate --- Boolean flag when set to True the selection is unlabeled 849 """ 850 851 kw['function'] = function 852 kw['lambdaFunc'] = lambdaFunc 853 kw['textcolor']=textcolor 854 kw['font']=font 855 kw['location']=location 856 kw['only']=only 857 kw['negate']=negate 858 kw['format']=format 859 kw['redraw'] = 1 860 if type(nodes) is types.StringType: 861 self.nodeLogString = "'"+nodes+"'" 862 self.vf.expandNodes(nodes) 863 apply(self.doitWrapper, (nodes,), kw)
864 865
866 - def doit(self, nodes, function='lambda x: x.full_name()', lambdaFunc=True, 867 textcolor='white', font='arial1.glf', location='Center', 868 only=False, negate=False, format=None):
869 870 ################################################################## 871 def drawLabels(mol, nodes, materials, function, lambdaFunc, 872 font, location, only, negate, format): 873 #font = 'glut'+ font 874 geomName = nodes[0].__class__.__name__+'Labels' 875 labelGeom = mol.geomContainer.geoms[geomName] 876 set = mol.geomContainer.atoms[geomName] 877 if negate: 878 if len(set): 879 set = set - nodes 880 ##if only or there were no labels, label current atms 881 elif only or not len(set): 882 set = nodes 883 ##not negate, not only and some previous labels, 884 ## label union of old + new 885 else: 886 set = nodes.union(set) 887 888 ##now, update the geometries: 889 # draw atoms with bonds and without bonds 890 if len(set)==0: 891 labelGeom.Set(vertices=[], labels=[], tagModified=False) 892 mol.geomContainer.atoms[geomName] = set 893 return 894 895 # 1st lines need to store the wole set in the 896 # mol.geomContainer.atoms['lines'] because of the picking. 897 mol.geomContainer.atoms[geomName] = set 898 propLabels = [""]*len(set) 899 try: 900 func = evalString(function) 901 except: 902 self.warningMsg("Error occured while evaluating the expression") 903 return 904 if lambdaFunc == 1: 905 try: 906 newPropLabels = map(func, set) 907 except KeyError: 908 msg= "all nodes do not have such a property" 909 self.warningMsg(msg) 910 newPropLabels =list("?"*len(nodes)) 911 912 else: 913 try: 914 newPropLabels = func(nodes) 915 except KeyError: 916 msg= "all nodes do not have such a property" 917 self.warningMsg(msg) 918 newPropLabels =list("?"*len(nodes)) 919 920 assert len(newPropLabels) == len(propLabels) 921 for i in range(len(newPropLabels)): 922 item = newPropLabels[i] 923 if format: 924 try: 925 item = format%newPropLabels[i] 926 except: 927 item = str(newPropLabels[i]) 928 else: 929 item = str(newPropLabels[i]) 930 if propLabels[i] =="" : 931 propLabels[i] = propLabels[i]+item 932 else: 933 propLabels[i] = propLabels[i]+";"+item 934 propLabels=tuple(propLabels) 935 936 propCenters=[] 937 for item in set: 938 z = item.findType(Atom) 939 if location=='First': 940 z=z[0] 941 zcoords = Numeric.array(z.coords) 942 zcoords = zcoords+0.2 943 zcoords = zcoords.tolist() 944 propCenters.append(zcoords) 945 elif location=='Center': 946 zcoords = Numeric.array(z.coords) 947 zcoords = Numeric.sum(zcoords)/(len(zcoords)*1.0) 948 zcoords = zcoords.tolist() 949 propCenters.append(zcoords) 950 if location=='Last': 951 z=z[-1] 952 zcoords = Numeric.array(z.coords) 953 zcoords = zcoords+0.2 954 zcoords = zcoords.tolist() 955 propCenters.append(zcoords) 956 propCenters = tuple(propCenters) 957 colors = (materials,) 958 labelGeom.Set(labels = propLabels, 959 vertices = propCenters, 960 materials = colors, font = font, visible = 1, 961 tagModified=False)
962 ################################################################### 963 964 if len(nodes) == 0: return 965 966 if (type(textcolor) is types.TupleType or type(textcolor) is types.ListType)\ 967 and len(textcolor)==3: 968 materials = textcolor 969 elif self.colorDict.has_key(textcolor): 970 materials = self.colorDict[textcolor] 971 elif len(textcolor)>0 and textcolor[0]=='(': 972 textlist=string.split(textcolor[1:-1],',') 973 try: 974 materials = (float(textlist[0]), 975 float(textlist[1]), 976 float(textlist[2])) 977 except ValueError: 978 warnings.warn("Invalid number entered: %s" %textcolor) 979 except IndexError: 980 warnings.warn("IndexError for %s" %textcolor) 981 982 molecules, nodeSets = self.vf.getNodesByMolecule(nodes) 983 984 for mol, nodes in map(None, molecules, nodeSets): 985 nodes.sort() 986 drawLabels(mol, nodes, materials, function , lambdaFunc, font, 987 location, only, negate, format)
988 989 990 991 #labelByPropertiesGuiDescr = {'widgetType':'Menu', 'menuBarName':'menuRoot', 992 # 'menuButtonName':'Label', 'menuEntryLabel':'by Properties'} 993 994 LabelByPropertiesGUI = CommandGUI() 995 LabelByPropertiesGUI.addMenuCommand('menuRoot', 'Display', 'by Properties', 996 cascadeName= 'Label') 997 998 LabelByExpressionGUI = CommandGUI() 999 LabelByExpressionGUI.addMenuCommand('menuRoot', 'Display', 'by Expression', 1000 cascadeName= 'Label') 1001 1002 commandList = [ 1003 {'name':'labelByProperty','cmd': LabelByProperties(), 'gui': LabelByPropertiesGUI}, 1004 {'name':'labelByExpression','cmd': LabelByExpression(), 'gui': LabelByExpressionGUI} 1005 ] 1006 1007
1008 -def initModule(viewer):
1009 for dict in commandList: 1010 viewer.addCommand(dict['cmd'], dict['name'], dict['gui'])
1011