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

Source Code for Module Pmv.editCommands

   1  ############################################################################ 
   2  # 
   3  # Author: Ruth HUEY, Michel F. SANNER 
   4  # 
   5  # Copyright: M. Sanner TSRI 2000 
   6  # 
   7  ############################################################################# 
   8   
   9  # $Header: /opt/cvs/python/packages/share1.5/Pmv/editCommands.py,v 1.114.2.1 2007/09/12 20:32:18 sargis Exp $ 
  10  # 
  11  # $Id: editCommands.py,v 1.114.2.1 2007/09/12 20:32:18 sargis Exp $ 
  12  # 
  13   
  14  from PyBabel.addh import AddHydrogens 
  15  from PyBabel.aromatic import Aromatic 
  16  from PyBabel.atomTypes import AtomHybridization 
  17  from PyBabel.cycle import RingFinder 
  18  from PyBabel.bo import BondOrder 
  19  from PyBabel.gasteiger import Gasteiger 
  20   
  21  from ViewerFramework.VFCommand import CommandGUI 
  22  from ViewerFramework.VF import DeleteAtomsEvent, AddAtomsEvent 
  23  ##  from ViewerFramework.gui import InputFormDescr 
  24  from mglutil.gui.InputForm.Tk.gui import InputFormDescr 
  25  from mglutil.util.callback import CallBackFunction 
  26  from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ListChooser 
  27  from tkMessageBox import * 
  28   
  29   
  30  from Pmv.mvCommand import MVCommand, MVAtomICOM, MVBondICOM 
  31  from Pmv.measureCommands import MeasureAtomCommand 
  32   
  33  from MolKit.tree import TreeNode, TreeNodeSet 
  34  from MolKit.molecule import Atom, AtomSet, Bond, Molecule, MoleculeSet 
  35  from MolKit.molecule import BondSet 
  36  from MolKit.protein import Protein, ProteinSet, Chain, Residue, ResidueSet 
  37  from MolKit.pdbParser import PdbParser, PdbqParser, PdbqsParser 
  38   
  39  from DejaVu.Geom import Geom 
  40  from DejaVu.Spheres import Spheres 
  41  from DejaVu.Points import CrossSet 
  42   
  43  from Pmv.stringSelectorGUI import StringSelectorGUI 
  44   
  45  import types, Tkinter, Numeric, Pmw, math, os 
  46  from string import letters, strip, find 
  47   
48 -def check_edit_geoms(VFGUI):
49 edit_geoms_list = VFGUI.VIEWER.findGeomsByName('edit_geoms') 50 if edit_geoms_list==[]: 51 edit_geoms = Geom("edit_geoms", shape=(0,0), protected=True) 52 VFGUI.VIEWER.AddObject(edit_geoms, parent=VFGUI.miscGeom) 53 edit_geoms_list = [edit_geoms] 54 return edit_geoms_list[0]
55 56 57
58 -class TypeAtomsCommand(MVCommand):
59 """This class uses the AtomHybridization class to assign atom types. 60 \nPackage:Pmv 61 \nModule :editCommands 62 \nClass:TypeAtomsCommand 63 \nCommand:typeAtoms 64 \nSynopsis:\n 65 None <--- typeAtoms(nodes, **kw) 66 \nRequired Arguments:\n 67 nodes --- TreeNodeSet holding the current selection 68 \nexample:\n 69 >>> atype = AtomHybridization()\n 70 >>> atype.assignHybridization(atoms)\n 71 atoms has to be a list of atom objects\n 72 Atom:\n 73 a .element : atom's chemical element symbol (string)\n 74 a .coords : 3-sequence of floats\n 75 a .bonds : list of Bond objects\n 76 Bond:\n 77 b .atom1 : instance of Atom\n 78 b .atom2 : instance of Atom\n 79 After completion each atom has the following additional members:\n 80 babel_type: string\n 81 babel_atomic_number: int\n 82 babel_organic\n 83 reimplementation of Babel1.6 in Python by Michel Sanner April 2000 84 Original code by W. Patrick Walters and Matthew T. Stahl\n 85 86 """
87 - def __init__(self, func=None):
88 MVCommand.__init__(self, func) 89 self.flag = self.flag | self.objArgOnly
90
91 - def doit(self, nodes):
92 nodes = self.vf.expandNodes(nodes) 93 if len(nodes)==0: 94 return 'ERROR' 95 mols = nodes.top.uniq() 96 for mol in mols: 97 #if hasattr(mol.allAtoms[0], 'babel_type'): 98 #continue 99 # try: 100 # mol.allAtoms.babel_type 101 # except: 102 babel = AtomHybridization() 103 babel.assignHybridization(mol.allAtoms)
104 105
106 - def __call__(self, nodes, **kw):
107 """None<---typeAtoms(nodes, **kw) 108 \nnodes --- TreeNodeSet holding the current selection""" 109 if type(nodes) is types.StringType: 110 self.nodeLogString = "'"+nodes+"'" 111 try: 112 nodes = self.vf.expandNodes(nodes) 113 except: 114 raise IOError 115 apply ( self.doitWrapper, (nodes,), kw )
116 117
118 - def guiCallback(self):
119 sel = self.vf.getSelection() 120 if len(sel): 121 self.doitWrapper(sel, log=1, redraw=0)
122 123 124 typeAtomsCommandGuiDescr = {'widgetType':'Menu', 'menuBarName':'menuRoot', 125 'menuButtonName':'Edit', 126 'menuEntryLabel':'Type', 127 'menuCascadeName': 'Atoms'} 128 129 130 TypeAtomsCommandGUI = CommandGUI() 131 TypeAtomsCommandGUI.addMenuCommand('menuRoot', 'Edit', 'Type', 132 cascadeName='Atoms')#, index=1) 133 134
135 -class EditAtomTypeGUICommand(MVCommand, MVAtomICOM):
136 """This class provides the GUI to EditAtom Type which allows the user 137 to change assigned atom types. 138 \nPackage:Pmv 139 \nModule :editCommands 140 \nClass:EditAtomTypeGUICommand 141 \nCommand:editAtomTypeGC 142 \nSynopsis:\n 143 None<---editAtomTypeGC(nodes, **kw) 144 \nRequired Arguments:\n 145 nodes --- TreeNodeSet 146 """ 147 148
149 - def __init__(self, func=None):
150 MVCommand.__init__(self, func) 151 MVAtomICOM.__init__(self) 152 self.atmTypeDict={} 153 self.atmTypeDict['B']=['B', 'Bac', 'Box'] 154 self.atmTypeDict['C']=['C', 'C1','C2','C3','Cac', 'Cbl', 'Car', 'C-',\ 155 'C+', 'Cx', 'Cany'] 156 self.atmTypeDict['H']=['H', 'HC', 'H-','HO','H+', 'HN'] 157 self.atmTypeDict['N']=['Ng+', 'Npl','Nam', 'N1','N2','N3', 'N4',\ 158 'Naz', 'Nox', 'Ntr', 'NC', 'N2+', 'Nar', 'Nany', 'N3+'] 159 self.atmTypeDict['O']=['O', 'O-','O2','O3','Oes', 'OCO2', \ 160 'Oco2', 'Oany'] 161 self.atmTypeDict['P']=['P', 'P3', 'P3+', 'Pac', 'Pox'] 162 self.atmTypeDict['S']=['S', 'S2', 'S3', 'S3+', 'Sac', 'So',\ 163 'So2', 'Sox', 'Sany']
164 165
166 - def onAddCmdToViewer(self):
167 if self.vf.hasGui: 168 miscGeom = self.vf.GUI.miscGeom 169 edit_geoms = check_edit_geoms(self.vf.GUI) 170 self.spheres = Spheres(name='editAtomTypeSphere', shape=(0,3), 171 radii=0.2, #inheritMaterial=0, 172 pickable=0, quality=15, 173 materials=((1.,1.,0.),), protected=True) 174 self.vf.GUI.VIEWER.AddObject(self.spheres, parent=edit_geoms) 175 if not hasattr(self.vf, 'editAtomType'): 176 self.vf.loadCommand('editCommands', 'editAtomType','Pmv', 177 topCommand=0)
178 179
180 - def __call__(self, nodes, **kw):
181 """None<---editAtomTypeGC(nodes, **kw) 182 \nnodes --- TreeNodeSet """ 183 if type(nodes) is types.StringType: 184 self.nodeLogString = "'"+nodes+"'" 185 ats = self.vf.expandNodes(nodes) 186 if not len(ats): return 'ERROR' 187 ats = ats.findType(Atom) 188 apply ( self.doitWrapper, (ats,), kw )
189 190
191 - def doit(self, ats):
192 for atom in ats: 193 self.spheres.Set(vertices=(atom.coords,)) 194 self.vf.GUI.VIEWER.Redraw() 195 if not hasattr(atom,'babel_type'): 196 #msg = 'atom has no babel_type: calling typeAtoms' 197 #self.warningMsg(msg) 198 #typeAtoms does whole molecule 199 self.vf.typeAtoms(atom, topCommand=0) 200 if atom.element not in self.atmTypeDict.keys(): 201 msg = 'No alternative atom types available for this element' 202 self.warningMsg(msg) 203 continue 204 else: 205 bVals = self.atmTypeDict[atom.element] 206 initialValue = (atom.babel_type,None) 207 entries = [] 208 for item in bVals: 209 entries.append((item, None)) 210 ifd = self.ifd = InputFormDescr(title='Select New AtomType') 211 ifd.append({'name': 'typesList', 212 'title':'Choose New Type', 213 'widgetType':'ListChooser', 214 'entries': entries, 215 'defaultValue':initialValue, 216 'mode': 'single', 217 'gridcfg':{'row':0,'column':0}, 218 'lbwcfg':{'height':5}}) 219 vals = self.vf.getUserInput(ifd) 220 if vals is not None and len(vals)>0 and len(vals['typesList'])>0: 221 self.vf.editAtomType(atom, vals['typesList'][0],topCommand=0) 222 else: 223 return 'ERROR' 224 self.spheres.Set(vertices=[]) 225 self.vf.GUI.VIEWER.Redraw()
226 227
228 - def startICOM(self):
229 self.vf.setIcomLevel(Atom)
230 231
232 - def stopICOM(self):
233 self.spheres.Set(vertices=[]) 234 self.vf.GUI.VIEWER.Redraw()
235 236 237 #def setupUndoBefore(self, ats, btype=None): 238 #ustr = '' 239 #for at in ats: 240 ##typeAtoms types everything so can't undo it 241 #if hasattr(at, 'babel_type'): 242 #ustr=ustr + '"at=self.expandNodes('+'\''+at.full_name()+'\''+')[0];at.babel_type=\''+ at.babel_type+'\';"' 243 #self.undoCmds = "exec("+ustr+")" 244 245 246
247 - def guiCallback(self):
248 showinfo("Picking level is set to editAtomType", 249 "Please pick on atom to change the type.") 250 251 self.vf.setICOM(self, topCommand=0)
252 253 254 editAtomTypeGUICommandGuiDescr = {'widgetType':'Menu', 'menuBarName':'menuRoot', 255 'menuButtonName':'Edit', 256 'menuCascadeName':'Atoms', 257 'menuEntryLabel':'Edit Type'} 258 259 260 EditAtomTypeGUICommandGUI = CommandGUI() 261 EditAtomTypeGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 'Edit Type', 262 cascadeName='Atoms')#, index=1) 263 264 265
266 -class EditAtomTypeCommand(MVCommand):
267 """This class allows the user to change assigned atom types. 268 \nPackage:Pmv 269 \nModule :editCommands 270 \nClass:EditAtomTypeCommand 271 \nCommand:editAtomType 272 \nSynopsis:\n 273 None <- editAtomType(ats, btype, **kw)\n 274 \nRequired Arguments:\n 275 at --- atom\n 276 btype --- babel_type\n 277 """
278 - def __init__(self, func=None):
279 MVCommand.__init__(self, func)
280 281
282 - def __call__(self, ats, btype, **kw):
283 """None <- editAtomType(ats, btype, **kw) 284 \nat --- atom 285 \nbtype --- babel_type""" 286 if type(ats) is types.StringType: 287 self.nodeLogString = "'"+ats+"'" 288 ats = self.vf.expandNodes(ats) 289 if not len(ats): return 'ERROR' 290 at = ats.findType(Atom)[0] 291 apply ( self.doitWrapper, (at, btype,), kw )
292 293
294 - def doit(self, at, btype):
295 at.babel_type = btype
296 297
298 - def setupUndoBefore(self, at, btype):
299 ustr = '' 300 #typeAtoms types everything so can't undo it 301 if hasattr(at, 'babel_type'): 302 ustr = ustr + '"at=self.expandNodes('+'\''+at.full_name()+'\''+')[0];at.babel_type=\''+ at.babel_type+'\';"' 303 self.undoCmds = "exec("+ustr+")"
304 305 306
307 -class EditAtomChargeGUICommand(MVCommand, MVAtomICOM):
308 """This class provides the GUI to EditAtomCharge which allows the user 309 to change atom charge. 310 \nPackage:Pmv 311 \nModule :editCommands 312 \nClass:EditAtomTypeGUICommand 313 \nCommand:editAtomTypeGC 314 \nSynopsis:\n 315 None<---editAtomChargeGC(nodes, **kw) 316 \nRequired Arguments:\n 317 nodes --- TreeNodeSet 318 319 320 """
321 - def __init__(self, func=None):
322 MVCommand.__init__(self, func) 323 MVAtomICOM.__init__(self) 324 self.flag = self.flag | self.objArgOnly
325 326
327 - def onAddCmdToViewer(self):
328 if self.vf.hasGui: 329 miscGeom = self.vf.GUI.miscGeom 330 edit_geoms = check_edit_geoms(self.vf.GUI) 331 self.spheres = Spheres(name='editAtomChargeSphere', shape=(0,3), 332 radii=0.2, #inheritMaterial=0, 333 pickable=0, quality=15, 334 materials=((1.,1.,0.),), protected=True) 335 self.vf.GUI.VIEWER.AddObject(self.spheres, parent=edit_geoms) 336 self.oldCharge = Tkinter.StringVar()
337 338
339 - def __call__(self, nodes, **kw):
340 """None<---editAtomChargeGC(nodes, **kw) 341 \nnodes --- TreeNodeSet """ 342 if type(nodes) is types.StringType: 343 self.nodeLogString = "'"+nodes+"'" 344 nodes = self.vf.expandNodes(nodes) 345 if not len(nodes): return 'ERROR' 346 apply ( self.doitWrapper, (nodes,), kw )
347 348
349 - def doit(self, nodes,):
350 ats = nodes.findType(Atom) 351 res = ats[0].parent 352 self.setUp(res) 353 atom = nodes[0] 354 self.spheres.Set(vertices=(atom.coords,)) 355 self.vf.GUI.VIEWER.Redraw() 356 if not hasattr(atom,'charge'): 357 msg = 'atom has no charge: calling XXXXX' 358 print msg 359 #self.warningMsg(msg) 360 self.oldCharge.set(atom.charge) 361 ifd = self.ifd = InputFormDescr(title='Enter New Charge') 362 ifd.append({'name':'eCLab', 363 'widgetType':Tkinter.Label, 364 'text':'Enter new charge for:\n' + atom.full_name(), 365 'gridcfg':{'sticky':'we'}}) 366 ifd.append({'name':'eCEnt', 367 'widgetType':Tkinter.Entry, 368 'wcfg':{'textvariable':self.oldCharge}, 369 'gridcfg':{'sticky':'we', 'row':-1, 'column':1}}) 370 vals = self.vf.getUserInput(ifd) 371 if len(vals)>0: 372 atom._charges[atom.chargeSet] = float(vals['eCEnt']) 373 self.vf.labelByExpression(AtomSet([atom]), 374 textcolor=(1.0, 1.0, 1.0), 375 negate=0, 376 format=None, 377 location='Center', 378 log=0, 379 font='arial1.glf', 380 only=0, 381 lambdaFunc=1, 382 function='lambda x: str(x.charge)') 383 #also update something showing the sum on this residue 384 self.vf.setIcomLevel(Residue, topCommand=0) 385 res = atom.parent 386 res.new_sum = round(Numeric.sum(res.atoms.charge),4) 387 self.vf.labelByProperty(ResidueSet([res]), properties=("new_sum",), \ 388 textcolor="yellow", log=0, font="arial1.glf") 389 self.vf.setIcomLevel(Atom, topCommand=0) 390 else: 391 return 'ERROR' 392 self.spheres.Set(vertices=[]) 393 self.vf.GUI.VIEWER.Redraw()
394 395
396 - def checkStartOk(self):
397 self.vf.setIcomLevel(Atom) 398 sel = self.vf.getSelection() 399 lenSel = len(sel) 400 if lenSel: 401 resSet = sel.findType(Residue).uniq() 402 ats = resSet[0].atoms 403 self.vf.setIcomLevel(Atom, topCommand=0) 404 #make sure each atom has a charge 405 chrgdAts = ats.get(lambda x: hasattr(x, 'charge')) 406 if chrgdAts is None or len(chrgdAts)!=len(ats): 407 self.warningMsg('not all atoms have charge') 408 self.stopICOM() 409 return 0 410 else: 411 return 1 412 else: 413 return 0
414 415
416 - def setUp(self, res):
417 #print 'setUp with ', res.full_name() 418 #label with the smaller error either the floor or ceiling 419 chsum = Numeric.sum(res.atoms.charge) 420 fl_sum = math.floor(chsum) 421 ceil_sum = math.ceil(chsum) 422 #always add err to end up with either fl_sum or ceil_sum 423 errF = fl_sum - chsum 424 #errF = chsum - fl_sum 425 #errC = chsum - ceil_sum 426 errC = ceil_sum - chsum 427 absF = math.fabs(errF) 428 absC = math.fabs(errC) 429 #make which ever is the smaller adjustment 430 if absC<absF: 431 err = round(errC, 4) 432 else: 433 err = round(errF, 4) 434 #print 'labelling with err = ', err 435 res.err = err 436 437 self.vf.setIcomLevel(Atom, topCommand=0) 438 self.vf.labelByExpression(res.atoms,textcolor=(1.0, 1.0, 1.0), 439 negate=0, 440 format=None, 441 location='Center', 442 log=0, 443 font='arial1.glf', 444 only=0, 445 lambdaFunc=1, 446 function='lambda x: str(x.charge)') 447 self.vf.setIcomLevel(Residue, topCommand=0) 448 #res.new_sum = round(Numeric.sum(res.atoms.charge),4) 449 #self.vf.labelByProperty(ResidueSet([res]), properties=("new_sum",), \ 450 self.vf.labelByProperty(ResidueSet([res]), properties=("err",), \ 451 textcolor="yellow", log=0, font="arial1.glf") 452 self.vf.setIcomLevel(Atom, topCommand=0)
453 454
455 - def startICOM(self):
456 self.vf.setIcomLevel(Atom)
457 #ok = self.checkStartOk() 458 #if ok: 459 #nodes = self.vf.getSelection() 460 #res = nodes.findType(Residue).uniq() 461 #if not len(res): 462 # return 'ERROR' 463 #self.setUp(res[0]) 464 465
466 - def stopICOM(self):
467 self.spheres.Set(vertices=[]) 468 sel = self.vf.getSelection() 469 selAts = sel.findType(Atom) 470 self.vf.setIcomLevel(Residue, topCommand=0) 471 self.vf.labelByProperty(selAts.parent.uniq(), log=0, negate=1) 472 self.vf.setIcomLevel(Atom, topCommand=0) 473 self.vf.labelByExpression(sel, lambdaFunc=1, function='lambda x:2',\ 474 log=0, negate=1) 475 self.vf.GUI.VIEWER.Redraw()
476 477
478 - def setupUndoBefore(self, ats):
479 ustr = '' 480 for at in ats: 481 ##typeAtoms types everything so can't undo it 482 #if hasattr(at, 'babel_type'): 483 ustr=ustr + '"at=self.expandNodes('+'\''+at.full_name()+'\''+')[0];at._charges[at.chargeSet]=float(\''+ str(at.charge)+'\');res = at.parent; import Numeric;from MolKit.protein import ResidueSet; res.new_sum = round(Numeric.sum(res.atoms.charge),4);self.labelByProperty(ResidueSet([res]), properties = (\'new_sum\',),textcolor = \'yellow\',font=\'arial1.glf\',log=0)"' 484 self.undoCmds = "exec("+ustr+")"
485 #NEED to redo labels here, too 486 487
488 - def guiCallback(self):
489 if not len(self.vf.Mols): 490 self.warningMsg('no molecules in viewer') 491 return 492 ok = self.checkStartOk() 493 if ok: 494 #nodes = self.vf.getSelection() 495 #res = nodes.findType(Residue).uniq() 496 #set up list of residues with non-integral charges 497 #self.setUp(res[0]) 498 #self.setUp(self.vf.getSelection()) 499 self.vf.setICOM(self, topCommand=0)
500 501 502 editAtomChargeGUICommandGuiDescr = {'widgetType':'Menu', 'menuBarName':'menuRoot', 503 'menuButtonName':'Edit', 504 'menuCascadeName':'Atoms', 505 'menuEntryLabel':'Edit Charge'} 506 507 508 EditAtomChargeGUICommandGUI = CommandGUI() 509 EditAtomChargeGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 'Edit Charge', 510 cascadeName='Charges')#, index=1) 511 512 513
514 -class TypeBondsCommand(MVCommand):
515 """This class uses the BondOrder class to compute bond order. 516 \nPackage:Pmv 517 \nModule :editCommands 518 \nClass:TypeBondsCommand 519 \nCommand:typeBonds 520 \nSynopsis:\n 521 None<---typeBonds(nodes, withRings=0, **kw) 522 \nRequired Arguments:\n 523 nodes --- TreeNodeSet holding the current selection 524 withRings: default is 0 525 Before a BondOrder object can be used, atoms must have been assigned 526 a type see (AtomHybridization in types.py).\n 527 Bond order can be calculated using 2 different methods depending on whether 528 rings have been identified previously or not. Babel decides to use the first 529 method for molecules with more than 200 atoms and the second one else.\n 530 example:\n 531 532 >>> atype = AtomHybridization()\n 533 >>> atype.assignHybridization(atoms)\n 534 >>> bo = BondOrder()\n 535 >>> bo.assignBondOrder( atoms, bonds )\n 536 537 or\n 538 539 >>> atype = AtomHybridization()\n 540 >>> atype.assignHybridization(atoms)\n 541 >>> rings = RingFinder()\n 542 >>> rings.findRings(allAtoms, bonds)\n 543 >>> bo = BondOrder()\n 544 >>> bo.assignBondOrder( atoms, bonds, rings )\n 545 546 atoms has to be a list of atom objects\n 547 Atom:\n 548 a .coords : 3-sequence of floats\n 549 a .bonds : list of Bond objects\n 550 babel_type: string\n 551 babel_atomic_number: int\n 552 553 Bond:\n 554 b .atom1 : instance of Atom\n 555 b .atom2 : instance of Atom\n 556 557 after completion each bond has a 'bondOrder' attribute (integer)\n 558 559 reimplementation of Babel1.6 in Python by Michel Sanner April 2000 560 Original code by W. Patrick Walters and Matthew T. Stahl\n 561 562 """ 563
564 - def __init__(self, func=None):
565 MVCommand.__init__(self, func) 566 self.flag = self.flag | self.objArgOnly
567
568 - def doit(self, nodes, withRings=False):
569 nodes = self.vf.expandNodes(nodes) 570 if len(nodes)==0: return 'ERROR' 571 mols = nodes.top.uniq() 572 for mol in mols: 573 allAtoms = mol.allAtoms 574 if hasattr(mol, 'rings'): continue 575 try: 576 allAtoms.babel_type 577 except: 578 babel = AtomHybridization() 579 babel.assignHybridization(allAtoms) 580 581 #allAtoms = nodes.findType(Atom) 582 bonds = allAtoms.bonds[0] 583 584 if withRings: 585 rings = RingFinder() 586 rings.findRings2(allAtoms, bonds) 587 else: 588 rings = None 589 mol.rings = rings 590 # create a new attribute to know which rings a bond belongs to maybe should be done in cycle.py 591 if not mol.rings is None: 592 mol.rings.bondRings = {} 593 for ind in xrange(len(mol.rings.rings)): 594 r = mol.rings.rings[ind] 595 for b in r['bonds']: 596 if not mol.rings.bondRings.has_key(b): 597 mol.rings.bondRings[b] = [ind,] 598 else: 599 mol.rings.bondRings[b].append(ind) 600 601 602 bo = BondOrder() 603 bo.assignBondOrder(allAtoms, bonds, rings) 604 allAtoms._bndtyped = 1 605 606 if withRings: 607 # do aromatic here 608 arom = Aromatic(rings) 609 arom.find_aromatic_atoms(allAtoms)
610 611 612
613 - def __call__(self, nodes, withRings=False, **kw):
614 """None<---typeBonds(nodes, withRings=0, **kw) 615 \nnodes --- TreeNodeSet holding the current selection 616 \nwithRings --- default is 0""" 617 618 kw['withRings'] = withRings 619 if type(nodes) is types.StringType: 620 self.nodeLogString = "'"+nodes+"'" 621 apply ( self.doitWrapper, (nodes,), kw )
622 623
624 - def guiCallback(self):
625 #put in checkbutton here for w/ or w/out rings 626 ifd = InputFormDescr(title="Type bonds:") 627 ifd.append({'name': 'rings', 628 'text': 'With Rings', 629 'widgetType': Tkinter.Checkbutton, 630 'variable': Tkinter.IntVar(), 631 'gridcfg': {'sticky':'w'}}) 632 val = self.vf.getUserInput(ifd) 633 sel = self.vf.getSelection() 634 if val and len(sel): 635 self.doitWrapper(sel, val['rings'],log=1,redraw=0)
636 637 638 typeBondsCommandGuiDescr = {'widgetType':'Menu', 'menuBarName':'menuRoot', 639 'menuButtonName':'Edit', 640 'menuCascadeName':'Bonds', 641 'menuEntryLabel':'Type'} 642 643 644 TypeBondsCommandGUI = CommandGUI() 645 TypeBondsCommandGUI.addMenuCommand('menuRoot', 'Edit', 'Type' , 646 cascadeName='Bonds') 647 648 649
650 -class AddHydrogensGUICommand(MVCommand):
651 """This GUICOMMAND class calls the AddHydrogenCommand class. 652 \nPackage:Pmv 653 \nModule :editCommands 654 \nClass:AddHydrogensGUICommand 655 \nCommand:add_hGC 656 \nSynopsis:\n 657 None<---add_hGC(nodes, polarOnly=0, method='noBondOrder', renumber=1,**kw)\n 658 \nRequired Arguments:\n 659 nodes --- TreeNodeSet holding the current selection\n 660 polarOnly --- default is 0\n 661 method --- Hydrogen atoms can be added using 2 different methods, ex: method='withBondOrder', default is 'noBondOrder'\n 662 renumber --- default is 1\n 663 """
664 - def __init__(self, func=None):
665 MVCommand.__init__(self, func) 666 self.flag = self.flag | self.objArgOnly
667 668
669 - def onAddCmdToViewer(self):
670 if not hasattr(self.vf, 'add_h'): 671 self.vf.loadCommand('editCommands', 'add_h','Pmv', 672 topCommand=0)
673 674
675 - def __call__(self, nodes, polarOnly=False, method='noBondOrder', 676 renumber=True, **kw):
677 """None<---add_hGC(nodes, polarOnly=False, method='noBondOrder', 678 renumber=1,**kw) 679 \nnodes --- TreeNodeSet holding the current selection 680 \npolarOnly --- default is False 681 \nmethod --- Hydrogen atoms can be added using 2 different methods, 682 ex: method='withBondOrder', default is 'noBondOrder' 683 \nrenumber --- Boolean flag when set to True the atoms are renumbered. (default is True) 684 """ 685 #kw['topCommand'] = 0 686 if type(nodes) is types.StringType: 687 self.nodeLogString = "'"+nodes+"'" 688 apply(self.doitWrapper,(nodes,polarOnly,method,renumber,), kw)
689 690
691 - def doit(self, nodes, polarOnly, method, renumber):
692 """ None <- add_h(nodes, polarOnly=0, method='noBondOrder', 693 renumber=1)""" 694 newHs = self.vf.add_h(nodes, polarOnly, method, renumber,topCommand=0) 695 #it could be that there are no new hydrogens: then don't log + return 696 if not len(newHs): return 'ERROR' 697 698 molecules, ats = self.vf.getNodesByMolecule(newHs)
699 ## for mol, hSet in map(None, molecules, ats): 700 ## #to update display 701 ## done = 0 702 ## for name, g in mol.geomContainer.geoms.items(): 703 ## #if name in ['lines', 'cpk', 'balls', 'sticks']: 704 ## if name=='lines': 705 ## if g.visible: 706 ## kw = self.vf.displayLines.getLastUsedValues() 707 ## kw['topCommand']=0 708 ## kw['redraw']=1 709 ## apply(self.vf.displayLines, (hSet,), kw) 710 711 ## if name=='cpk': 712 ## if g.visible: 713 ## kw = self.vf.displayCPK.getLastUsedValues() 714 ## kw['topCommand']=0 715 ## kw['redraw']=1 716 ## apply(self.vf.displayCPK, (hSet,), kw) 717 718 ## if not done and (name=='balls' or name=='sticks'): 719 ## if g.visible: 720 ## kw = self.vf.displaySticksAndBalls.getLastUsedValues() 721 ## kw['topCommand']=0 722 ## kw['redraw']=1 723 ## apply(self.vf.displaySticksAndBalls, (hSet,), kw) 724 ## done = 1 725 726
727 - def guiCallback(self):
728 sel = self.vf.getSelection() 729 if not len(sel): 730 self.warningMsg("No Molecules in Viewer!") 731 return 732 ifd = InputFormDescr(title = "Add Hydrogens:") 733 hydrogenChoice = Tkinter.IntVar() 734 hydrogenChoice.set(0) 735 methodChoice = Tkinter.StringVar() 736 if os.path.splitext(sel.top[0].parser.filename)[1]=='.pdb': 737 methodChoice.set('noBondOrder') 738 else: 739 methodChoice.set('withBondOrder') 740 #if len(sel.findType(Atom))>200: 741 #methodChoice.set('noBondOrder') 742 #else: 743 #methodChoice.set('withBondOrder') 744 #methodChoice.set('noBondOrder') 745 renumberChoice = Tkinter.IntVar() 746 renumberChoice.set(1) 747 ifd.append({'name': 'allHs', 748 'text': 'All Hydrogens', 749 'widgetType': Tkinter.Radiobutton, 750 'value':0, 751 'variable': hydrogenChoice, 752 'gridcfg': {'sticky':'w'}}) 753 ifd.append({'name': 'polarOnly', 754 'text': 'Polar Only', 755 'widgetType': Tkinter.Radiobutton, 756 'value':1, 757 'variable': hydrogenChoice, 758 'gridcfg': {'sticky':'w'}}) 759 ifd.append({'name':'methodLab', 760 'widgetType':Tkinter.Label, 761 'text':'Method', 762 'gridcfg':{'sticky':Tkinter.W}}) 763 ifd.append({'name': 'noBondOrder', 764 'text': 'noBondOrder (for pdb files...)', 765 'widgetType': Tkinter.Radiobutton, 766 'value':'noBondOrder', 767 'variable': methodChoice, 768 'gridcfg': {'sticky':'w'}}) 769 ifd.append({'name': 'withBondOrder', 770 'text': 'withBondOrder (if you trust the bond order info)', 771 'widgetType': Tkinter.Radiobutton, 772 'value':'withBondOrder', 773 'variable': methodChoice, 774 'gridcfg': {'sticky':'w'}}) 775 ifd.append({'name':'renumberLab', 776 'widgetType':Tkinter.Label, 777 'text':'Renumber atoms to include new hydrogens', 778 'gridcfg':{'sticky':Tkinter.W}}) 779 ifd.append({'name': 'yesRenumber', 780 'text': 'yes', 781 'widgetType': Tkinter.Radiobutton, 782 'value':1, 783 'variable': renumberChoice, 784 'gridcfg': {'sticky':'w'}}) 785 ifd.append({'name': 'noRenumber', 786 'text': 'no', 787 'widgetType': Tkinter.Radiobutton, 788 'value':0, 789 'variable': renumberChoice, 790 'gridcfg': {'sticky':'w'}}) 791 val = self.vf.getUserInput(ifd) 792 if val: 793 ## if self.vf.userpref['expandNodeLogString']['value'] == 0: 794 ## # need to set the nodeLogString of the command that will 795 ## # be logged and it is not the GUICommand. 796 ## self.vf.add_h.nodeLogString = "self.getSelection()" 797 self.doitWrapper(sel, polarOnly=hydrogenChoice.get(), 798 method=methodChoice.get(), renumber=renumberChoice.get(), 799 redraw=1)
800 801 802 addHydrogensGUICommandGuiDescr = {'widgetType':'Menu','menuBarName':'menuRoot', 803 'menuButtonName':'Edit', 804 'menuCascadeName':'Hydrogens', 805 'menuEntryLabel':'Add'} 806 807 AddHydrogensGUICommandGUI = CommandGUI() 808 AddHydrogensGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 'Add', 809 cascadeName='Hydrogens') 810 811 812 813
814 -class AddHydrogensCommand(MVCommand):
815 """This command adds hydrogen atoms to all atoms in all molecules that have at least one member (i.e atom, residue, chain, base-pair etc..) specified in the first argument. 816 \nPackage:Pmv 817 \nModule :editCommands 818 \nClass:AddHydrogensCommand 819 \nCommand:add_h 820 \nSynopsis:\n 821 AtomSet<---add_h(nodes, polarOnly=0, method='noBondOrder, 822 renumber=1,**kw)\n 823 \nRequired Arguments:\n 824 nodes --- TreeNodeSet holding the current selection\n 825 polarOnly --- default is 0\n 826 method --- Hydrogen atoms can be added using 2 different methods, ex: method='withBondOrder', default is 'noBondOrder'\n 827 renumber --- default is 1\n 828 Returns an atomSet containing the created H atoms\n 829 NOTE: This command adds hydrogens to all atoms in the molecule specified using the nodes argument.\n 830 The hydrogen atoms added to each molecule are also saved as a set called mol.name + '_addedH'\n 831 This class uses the AddHydrogens class from the PyBabel package.\n 832 833 Before this AddHydrogens object can be used, atoms must have been assigned 834 a type see (AtomHybridization in types.py).\n 835 836 Hydrogen atoms can be added using 2 different methods. The first one requires 837 bondOrders to have been calculated previousely.\n 838 839 example:\n 840 841 >>> atype = AtomHybridization()\n 842 >>> atype.assignHybridization(atoms)\n 843 >>> addh = AddHydrogens()\n 844 >>> hat = addh.addHydrogens(atoms)\n 845 846 atoms has to be a list of atom objects\n 847 Atom:\n 848 a .coords : 3-sequence of floats\n 849 a .bonds : list of Bond objects\n 850 babel_type: string\n 851 babel_atomic_number: int\n 852 853 Bond:\n 854 b .atom1 : instance of Atom\n 855 b .atom2 : instance of Atom\n 856 857 or\n 858 >>> addh = AddHydrogens()\n 859 >>> hat = addh.addHydrogens(atoms, method='withBondOrder')\n 860 861 atoms has to be a list of atom objects as above and\n 862 Bond:\n 863 b .atom1 : instance of Atom\n 864 b .atom2 : instance of Atom\n 865 b .bondOrder : integer\n 866 867 these calls return a list 'hat' containing a tuple for each Hydrogen 868 atom to be added. This tuple provides:\n 869 coordsH : 3-float coordinates of the H atom\n 870 atom : the atom to which the H atom is to be connected\n 871 atomic_number : the babel_atomic_number of the H atom\n 872 type : tyhe b:wabel_type of the H atom\n 873 874 reimplementation of Babel1.6 in Python by Michel Sanner April 2000 875 Original code by W. Patrick Walters and Matthew T. Stahl\n 876 """
877 - def __init__(self, func=None):
878 MVCommand.__init__(self, func) 879 self.flag = self.flag | self.objArgOnly
880
881 - def onAddCmdToViewer(self):
882 if not self.vf.commands.has_key('typeBonds'): 883 self.vf.loadCommand('editCommands', 'typeBonds','Pmv', 884 topCommand=0) 885 if not self.vf.commands.has_key("saveSet"): 886 self.vf.loadCommand("selectionCommands", "saveSet", "Pmv", 887 topCommand=0) 888 if not self.vf.commands.has_key("selectSet"): 889 self.vf.loadCommand("selectionCommands", "selectSet", "Pmv", 890 topCommand=0) 891 if not self.vf.commands.has_key("fixHNames"): 892 self.vf.loadCommand("editCommands", "fixHNames", "Pmv", 893 topCommand=0)
894 895
896 - def __call__(self, nodes, polarOnly=False, method='noBondOrder', 897 renumber=True, **kw):
898 """ 899 AtomSet <- add_h(nodes, polarOnly=0, method='noBondOrder, 900 renumber=1,**kw) 901 \nnodes --- TreeNodeSet holding the current selection 902 \npolarOnly --- default is False 903 \nmethod --- Hydrogen atoms can be added using 2 different methods, 904 \nex --- method='withBondOrder', default is 'noBondOrder' 905 \nrenumber --- default is True 906 \nReturns an atomSet containing the created H atoms 907 \nNOTE: This command adds hydrogens to all atoms in the molecule 908 specified using the nodes argument. 909 \nThe hydrogen atoms added to each molecule are also saved as a set 910 called mol.name + '_addedH' 911 """ 912 if type(nodes) is types.StringType: 913 self.nodeLogString = "'"+nodes+"'" 914 return apply(self.doitWrapper,(nodes,polarOnly,method,renumber,), kw)
915 916
917 - def doit(self, nodes, polarOnly=False, method='noBondOrder', 918 renumber=True):
919 """ None <- add_h(nodes, polarOnly=False, method='noBondOrder', renumber=True)""" 920 nodes = self.vf.expandNodes(nodes) 921 if len(nodes)==0: return 'ERROR' 922 923 mols = nodes.top.uniq() 924 925 newHs = AtomSet([]) # list of created H atoms (will be returned) 926 resList = {} # used to get a list of residues with added H atoms 927 928 for mol in mols: 929 # check if we need to assign babel atom types 930 try: 931 t = mol.allAtoms.babel_type 932 except: 933 babel = AtomHybridization() 934 babel.assignHybridization(mol.allAtoms) 935 936 # check if we need to assign bond orders 937 if method=='withBondOrder': 938 allBonds, noBonds = mol.allAtoms.bonds 939 haveBO = 1 940 for b in allBonds: 941 if b.bondOrder is None: 942 haveBO = 0 943 break 944 945 if haveBO==0: 946 self.vf.typeBonds(mol, withRings=1, topCommand=0) 947 948 # add hydrogen atoms to this molecule 949 addh = AddHydrogens() 950 hat = addh.addHydrogens(mol.allAtoms, method=method) 951 # build lists of all H atoms bonded to the same heavy atom 952 bondedAtomDict = {} # key is heavy atom 953 for a in hat: 954 if bondedAtomDict.has_key(a[1]): 955 bondedAtomDict[a[1]].append(a) 956 else: 957 bondedAtomDict[a[1]] = [a] 958 959 # now create Atom object for hydrogens 960 # and add the to the residues's atom list 961 962 molNewHs = AtomSet([]) # list of created H atoms for this molecule 963 heavyAtoms = AtomSet([]) # list of atoms that need new radii 964 965 for heavyAtom, HatmsDscr in bondedAtomDict.items(): 966 # do not add H to Carbon atoms if polarOnly is specified 967 if polarOnly: 968 if heavyAtom.element=='C': continue 969 970 res = heavyAtom.parent 971 resList[res] = 1 972 # find where to insert H atom 973 childIndex = res.children.index(heavyAtom)+1 974 975 # loop over H atoms description to be added 976 # start art the end because (go ask RUTH) 977 l = len(HatmsDscr) 978 for i in range(l-1,-1,-1): 979 a = HatmsDscr[i] 980 # build H atom's name 981 if len(heavyAtom.name)==1: 982 name = 'H' + heavyAtom.name 983 else: 984 name = 'H' + heavyAtom.name[1:] 985 986 # if more than 1 H atom, add H atom index 987 # for instance HD11, HD12, Hd13 (index is 1,2,3) 988 if l > 1: 989 name = name + str(i+1) 990 #this is needed to avoid bug #752 alternate position atoms 991 if '@' in name and '@' in a[1].name: 992 at_position = name.find('@') 993 name = name[:at_position] + name[at_position+2:] + \ 994 name[at_position:at_position+2] 995 # create the H atom object 996 atom = Atom(name, res, top=heavyAtom.top, 997 chemicalElement='H', 998 childIndex=childIndex, assignUniqIndex=0) 999 1000 # set atoms attributes 1001 atom._coords = [ a[0] ] 1002 if hasattr(a[1], 'segID'): atom.segID = a[1].segID 1003 atom.hetatm = heavyAtom.hetatm 1004 atom.alternate = [] 1005 #atom.element = 'H' 1006 atom.occupancy = 1.0 1007 atom.conformation = 0 1008 atom.temperatureFactor = 0.0 1009 atom.babel_atomic_number = a[2] 1010 atom.babel_type = a[3] 1011 atom.babel_organic = 1 1012 atom.radius = 1.2 1013 1014 # create the Bond object bonding Hatom to heavyAtom 1015 bond = Bond( a[1], atom, bondOrder=1) 1016 1017 # add the created atom the the list 1018 newHs.append(atom) 1019 molNewHs.append(atom) 1020 1021 # create the color entries for all geoemtries 1022 # available for the heavyAtom 1023 for key, value in heavyAtom.colors.items(): 1024 atom.colors[key]=(0.0, 1.0, 1.0) 1025 atom.opacities[key]=1.0 1026 # DO NOT set charges to 0.0 1027 ##for key in heavyAtom._charges.keys(): 1028 ##atom._charges[key] = 0.0 1029 heavyAtoms.append(heavyAtom) 1030 1031 if not len(newHs): 1032 # if there are no newHs, return empty AtomSet here 1033 return newHs 1034 1035 # assign non united radii to heavy atoms 1036 mol.defaultRadii(atomSet=heavyAtoms, united=0 ) 1037 1038 # update the allAtoms set in the molecule 1039 mol.allAtoms = mol.findType(Atom) 1040 1041 if renumber: 1042 fst = mol.allAtoms[0].number 1043 mol.allAtoms.number = range(fst, len(mol.allAtoms)+fst) 1044 1045 1046 # save the added atoms as a set 1047 if len(molNewHs) > 0: 1048 setName = mol.name + '_addedH' 1049 self.vf.saveSet( molNewHs, setName, 1050 'added by addh command', topCommand=0) 1051 1052 for r in resList.keys(): 1053 r.assignUniqIndex() 1054 1055 # update self.vf.Mols.allAtoms 1056 self.vf.allAtoms = self.vf.Mols.allAtoms 1057 1058 event = AddAtomsEvent(objects=newHs) 1059 self.vf.dispatchEvent(event) 1060 1061 return newHs
1062 1063 1064
1065 -class FixHydrogenAtomNamesGUICommand(MVCommand):
1066 """This class provides Graphical User Interface to FixHydrogenAtomsNameCommand 1067 which is invoked by it with the current selection, if there is one. 1068 \nPackage:Pmv 1069 \nModule :editCommands 1070 \nClass:FixHydrogenAtomNamesGUICommand 1071 \nCommand:fixHNamesGC 1072 \nSynopsis:\n 1073 None<---fixHNamesGC(nodes, **kw) 1074 \nRequired Arguments:\n 1075 nodes --- TreeNodeSet holding the current selection 1076 """ 1077
1078 - def __init__(self, func=None):
1079 MVCommand.__init__(self, func) 1080 self.flag = self.flag | self.objArgOnly
1081
1082 - def onAddCmdToViewer(self):
1083 if not hasattr(self.vf, 'fixHNames'): 1084 self.vf.loadCommand('editCommands', 'fixHNames','Pmv', 1085 topCommand=0)
1086 1087 1088
1089 - def doit(self, nodes):
1090 self.vf.fixHNames(nodes)
1091 1092
1093 - def __call__(self, nodes, **kw):
1094 """None <- fixHNamesGC(nodes, **kw) 1095 \nnodes --- TreeNodeSet holding the current selection""" 1096 if type(nodes) is types.StringType: 1097 self.nodeLogString = "'"+nodes+"'" 1098 1099 apply( self.doitWrapper, (nodes,), kw )
1100 1101
1102 - def guiCallback(self):
1103 sel=self.vf.getSelection() 1104 if len(sel): 1105 ## if self.vf.userpref['expandNodeLogString']['value'] == 0: 1106 ## # The GUI command doesn't log itself but the associated command 1107 ## # does so we need to set the nodeLogString of the Command 1108 ## self.vf.fixHNames.nodeLogString = "self.getSelection()" 1109 self.doitWrapper(sel, topCommand=0)
1110 1111 1112 fixHydrogenAtomNamesGUICommandGuiDescr = {'widgetType':'Menu', 1113 'menuBarName':'menuRoot', 1114 'menuButtonName':'Edit', 1115 'menuCascadeName':'Hydrogens', 1116 'menuEntryLabel':'Fix Pdb Names'} 1117 1118 1119 FixHydrogenAtomNamesGUICommandGUI = CommandGUI() 1120 FixHydrogenAtomNamesGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 1121 'Fix Pdb Names', cascadeName='Hydrogens') 1122 1123 1124
1125 -class FixHydrogenAtomNamesCommand(MVCommand):
1126 """\nThis class checks hydrogen atom names and modifies them to conform to 'IUPAC-IUB' conventions 1127 \nPackage:Pmv 1128 \nModule :editCommands 1129 \nClass:FixHydrogenAtomNamesCommand 1130 \nCommand:fixHNames 1131 \nSynopsis:\n 1132 None <- fixHNames(nodes, **kw) 1133 \nRequired Arguments:\n 1134 nodes --- TreeNodeSet holding the current selection\n 1135 1136 Hydrogen names have 4 spaces:'H _ _ _', (here referred to as 1-4).\n 1137 'H' is always in space 1.\n 1138 Space 2 references the name of the atom to which H is bonded 1139 using the following scheme: \n 1140 IF the name has 1 letter, space 2 is that letter. \n 1141 IF the name has more than 1 letter, space 2 is the second letter 1142 in that name and space 3 the third letter if it exists. \n 1143 (Please note that the second space in the bonded atom name is a 'remoteness' 1144 indicator and the third used to number items equally remote.)\n 1145 1146 In all cases, the LAST space (which could be space 3 or space 4 1147 depending on the bonded-atom's name) is used to number hydrogen atoms 1148 when more than one are bound to the same atom.\n 1149 1150 EXAMPLES:\n 1151 HN <- hydrogen bonded to atom named 'N'\n 1152 HA <- hydrogen bonded to atom named 'CA'\n 1153 HE <- hydrogen bonded to atom named 'NE'\n 1154 HH11 <- first hydrogen bonded to atom named 'NH1'\n 1155 HH12 <- second hydrogen bonded to atom named 'NH1'\n 1156 HD21 <- first hydrogen bonded to atom named 'CD2'\n 1157 ________________________________________________________________________\n 1158 A final complexity results when these names are written in pdb files:\n 1159 The name of the atom appears RIGHT-JUSTIFIED in the first two columns of 1160 the 4 columns involved (13-16). Thus 'H' appears in column 14 for all hydrogen 1161 atoms. This creates a problem for 4 character hydrogen names. They are 1162 accommodated by wrapping so that space 4 appears in column 13.\n 1163 1164 EXAMPLE:\n 1165 1HD2 <- first hydrogen bonded to atom named 'CD2' as represented 1166 in a pdb file.\n 1167 """
1168 - def __init__(self, func=None):
1169 MVCommand.__init__(self, func) 1170 self.flag = self.flag | self.objArgOnly
1171
1172 - def doit(self, nodes):
1173 nodes = self.vf.expandNodes(nodes) 1174 if not len(nodes): return 'ERROR' 1175 1176 allAtoms = nodes.findType(Atom) 1177 allHs = allAtoms.get('H*') 1178 if allHs is None or len(allHs)==0: return 'ERROR' 1179 ct = 0 1180 for a in allHs: 1181 if not len(a.bonds): continue 1182 b=a.bonds[0] 1183 a2=b.atom1 1184 if a2==a: a2=b.atom2 1185 if a2.name=='N': 1186 hlist = a2.findHydrogens() 1187 if len(hlist) == 1: 1188 if a.name!='HN': 1189 #print 'fixing atom ', a.full_name() 1190 a.name = 'HN' 1191 ct = ct + 1 1192 else: 1193 for i in range(len(hlist)): 1194 if hlist[i].name[:2]!='HN' or len(hlist[i].name)<3: 1195 #print 'fixing atom ', hlist[i].full_name() 1196 ct = ct + 1 1197 hlist[i].name = 'HN'+str(i+1) 1198 if len(a2.name)>1: 1199 remote=a2.name[1] 1200 if remote in letters: 1201 if len(a.name)<2 or remote!=a.name[1]: 1202 #print 'fixing remote atom', a.full_name() 1203 ct = ct + 1 1204 a.name = a.name[0]+a2.name[1] 1205 if len(a.name)>2: 1206 a.name=a.name+a.name[2:] 1207 else: 1208 newname = a.name + remote 1209 if len(a.name)>1: 1210 newname=newname+a.name[1:]
1211 1212
1213 - def __call__(self, nodes, **kw):
1214 """None <--- fixHNames(nodes, **kw) 1215 \nnodes --- TreeNodeSet holding the current selection""" 1216 if type(nodes) is types.StringType: 1217 self.nodeLogString = "'"+nodes+"'" 1218 apply ( self.doitWrapper, (nodes,), kw )
1219 1220 1221 1222 ## class FixHydrogenAtomNamesGUICommand(MVCommand): 1223 ## """ 1224 ## This class provides Graphical User Interface to FixHydrogenAtomsNameCommand 1225 ## which is invoked by it with the current selection, if there is one. 1226 ## """ 1227 1228