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

Source Code for Module Pmv.repairCommands

   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/repairCommands.py,v 1.71 2007/05/30 17:11:01 rhuey Exp $ 
  10  # 
  11  # $Id: repairCommands.py,v 1.71 2007/05/30 17:11:01 rhuey Exp $ 
  12  # 
  13   
  14   
  15  from ViewerFramework.VFCommand import CommandGUI 
  16  from ViewerFramework.VF import AddAtomsEvent, DeleteAtomsEvent 
  17  ##  from ViewerFramework.gui import InputFormDescr 
  18  from mglutil.gui.InputForm.Tk.gui import InputFormDescr 
  19  from mglutil.util.callback import CallBackFunction 
  20  from mglutil.gui.BasicWidgets.Tk.customizedWidgets import \ 
  21                  ExtendedSliderWidget, ListChooser 
  22  from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel 
  23   
  24  from PyBabel.addh import AddHydrogens 
  25  from PyBabel.util import vec3 
  26   
  27  from Pmv.mvCommand import MVCommand, MVAtomICOM, MVBondICOM 
  28  from Pmv.qkollua import q 
  29   
  30  from MolKit.tree import TreeNode, TreeNodeSet 
  31  from MolKit.molecule import Atom, AtomSet, Bond, Molecule, MoleculeSet 
  32  from MolKit.molecule import BondSet 
  33  from MolKit.protein import Protein, ProteinSet, Chain, Residue, ResidueSet 
  34  from MolKit.pdbParser import PdbParser, PdbqParser, PdbqsParser 
  35  from MolKit.distanceSelector import CloserThanVDWSelector, DistanceSelector  
  36  from MolKit.distanceSelector import CloserThanVDWPlusConstantSelector 
  37  from MolKit.pdbWriter import PdbWriter 
  38   
  39  from DejaVu.Geom import Geom 
  40  from DejaVu.Spheres import Spheres 
  41  from DejaVu.Points import CrossSet 
  42   
  43  from SimpleDialog import SimpleDialog 
  44  from Pmv.stringSelectorGUI import StringSelectorGUI 
  45   
  46  import Tkinter, Numeric, math, types, Pmw 
  47   
  48  from DejaVu.glfLabels import GlfLabels 
  49   
  50   
51 -def check_repair_geoms(VFGUI):
52 repair_geoms_list = VFGUI.VIEWER.findGeomsByName('repair_geoms') 53 if repair_geoms_list==[]: 54 repair_geoms = Geom("repair_geoms", shape=(0,0), protected=True) 55 VFGUI.VIEWER.AddObject(repair_geoms, parent=VFGUI.miscGeom) 56 repair_geoms_list = [repair_geoms] 57 return repair_geoms_list[0]
58 59
60 -class CheckForMissingAtomsGUICommand(MVCommand):
61 """This class provides Graphical User Interface to CheckForMissingAtomsCommand which is invoked by it with the current selection, if there is one. 62 \nPackage : Pmv 63 \nModule : repairCommands 64 \nClass : CheckForMissingAtomsGUICommand 65 \nCommand : checkForMissingAtomsGC 66 \nSynopsis:\n 67 dictOfMissingAts <--- checkForMissingAtomsGC(nodes, **kw) 68 \nRequired Arguments:\n 69 nodes --- TreeNodeSet holding the current selection 70 """ 71
72 - def __init__(self, func=None):
73 MVCommand.__init__(self, func) 74 self.flag = self.flag | self.objArgOnly
75
76 - def onRemoveObjFromViewer(self, obj):
77 if self.oldNode==obj: 78 del self.oldNode
79 80
81 - def onAddCmdToViewer(self):
82 if not self.vf.commands.has_key('labelByProperty'): 83 self.vf.loadCommand('labelCommands', 'labelByProperty','Pmv', 84 topCommand=0) 85 #self.vf.loadModule('labelCommands', 'Pmv') 86 self.oldNode = None
87 88
89 - def __call__(self, nodes, **kw):
90 """dictOfMissingAts <--- checkForMissingAtomsGC(nodes, **kw) 91 \nnodes --- TreeNodeSet holding the current selection""" 92 if type(nodes) is types.StringType: 93 self.nodeLogString = "'"+nodes+"'" 94 nodes = self.vf.expandNodes(nodes) 95 if not len(nodes): return 'ERROR' 96 resSet = nodes.findType(Residue).uniq() 97 return apply( self.doitWrapper, (resSet,), kw )
98 99
100 - def doit(self, nodes):
101 dict = self.vf.checkForMissingAtoms(nodes) 102 resNames = [] 103 resSet = ResidueSet(dict.keys()) 104 for item in resSet: 105 resNames.append(item.full_name()) 106 item.missing = str(dict[item])[1:-1] 107 #put up a form here with button 108 ifd = self.ifd=InputFormDescr(title = 'Check for MissingAtoms Results:') 109 ifd.append({'name': 'numResErrsLabel', 110 'widgetType': Tkinter.Label, 111 'wcfg':{'text': str(len(resSet)) + ' Residues with missing atoms:'}, 112 'gridcfg':{'sticky': Tkinter.W+Tkinter.E}}) 113 ifd.append({'name': 'resLC', 114 'widgetType':'ListChooser', 115 'entries': resNames, 116 #'defaultValue':resSet[0], 117 'mode': 'single', 118 #'mode': 'multiple', 119 'gridcfg':{'row':2,'column':0}, 120 'title': '', 121 #'command': CallBackFunction(self.showMissingRes, dict), 122 'lbwcfg':{'height':5, 123 'selectforeground': 'red', 124 'exportselection': 0, 125 'width': 30}}) 126 ifd.append({'name':'selAllBut', 127 'widgetType':Tkinter.Button, 128 'wcfg': { 'text':'Select All Residues', 129 'command': self.selectAllRes}, 130 'gridcfg':{'sticky':Tkinter.W+Tkinter.E}}) 131 ifd.append({'name':'selCurrBut', 132 'widgetType':Tkinter.Button, 133 'wcfg': { 'text':'Select Current Residue', 134 'command': CallBackFunction(self.selectCurRes, dict) 135 }, 136 'gridcfg':{'sticky':Tkinter.W+Tkinter.E}}) 137 ifd.append({'name':'closeBut', 138 'widgetType':Tkinter.Button, 139 'wcfg': { 'text':'Dismiss', 140 'command': self.dismiss_cb}, 141 'gridcfg':{'sticky':Tkinter.W+Tkinter.E}}) 142 self.form = self.vf.getUserInput(ifd, modal=0, blocking=0, 143 scrolledFrame=1, width=337, height=305) 144 self.form.root.protocol('WM_DELETE_WINDOW',self.dismiss_cb)
145 146 147
148 - def dismiss_cb(self, event=None):
149 res = self.vf.Mols.chains.residues.get(lambda x: hasattr(x,'missing')) 150 if res is not None: 151 self.vf.labelByProperty(res, negate=1, topCommand=0) 152 self.form.destroy()
153 154
155 - def selectAllRes(self, event=None):
156 try: 157 resSet = self.vf.Mols.chains.residues 158 except AttributeError: 159 self.warningMsg('no residues in viewer') 160 return 161 missingResSet = resSet.get(lambda x: hasattr(x, 'missing')) 162 if not missingResSet: 163 self.warningMsg('no residues missing atoms') 164 return 165 self.vf.select(missingResSet, topCommand=0)
166 167 168 #def selectCurRes(self, dict, event=None): 169 # resSet = ResidueSet(dict.keys()) 170 # lb = self.ifd.entryByName['resLC']['widget'].lb 171 # if lb.curselection() == (): return 172 # resName = lb.get(lb.curselection()) 173 # resNode = self.vf.Mols.NodesFromName(resName)[0] 174 # self.vf.select(resNode, topCommand=0) 175 176 177 #def showMissingRes(self, dict, event=None): 178 #pass 179 180
181 - def selectCurRes(self, dict, event=None):
182 resSet = ResidueSet(dict.keys()) 183 lb = self.ifd.entryByName['resLC']['widget'].lb 184 #unlabel anything from the previous time 185 if self.oldNode is not None: 186 self.vf.labelByProperty(self.oldNode, properties = ("missing",), textcolor = "yellow", location = "Last", log = 0, font = "arial1.glf", negate=1) 187 self.vf.select(self.oldNode.atoms, negate=1, topCommand=0) 188 #if nothing new is selected, remember that via oldNode + return 189 if lb.curselection() == (): 190 self.oldNode = None 191 return 192 #get new nodes to label 193 resNodes = ResidueSet() 194 for ind in lb.curselection(): 195 resName = lb.get(ind) 196 resNodes.append( self.vf.Mols.NodesFromName(resName)[0]) 197 self.vf.clearSelection(topCommand=0) 198 self.vf.setIcomLevel(Residue, topCommand=0) 199 self.vf.setICOM(self.vf.select, modifier=None, topCommand=0) 200 self.vf.labelByProperty(resNodes, properties = ("missing",), textcolor = "yellow", location = "Last", log = 0, font = "arial1.glf", only=1) 201 self.vf.select(resNodes, topCommand=0) 202 self.oldNode = resNodes
203 204
205 - def guiCallback(self):
206 if self.vf.userpref['expandNodeLogString']['value'] == 0: 207 self.vf.checkForMissingAtoms.nodeLogString = "self.getSelection()" 208 sel=self.vf.getSelection() 209 if len(sel): 210 return self.doitWrapper(sel, topCommand=0)
211 212 213 checkForMissingAtomsGUICommandGuiDescr = {'widgetType':'Menu', 214 'menuBarName':'menuRoot', 215 'menuButtonName':'Edit', 216 'menuCascadeName':'Misc', 217 'menuEntryLabel':'Check For Missing Atoms '} 218 219 220 CheckForMissingAtomsGUICommandGUI = CommandGUI() 221 CheckForMissingAtomsGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 222 'Check for Missing Atoms ', cascadeName='Misc') 223 224 225
226 -class CheckForMissingAtoms(MVCommand):
227 """This command compares atoms present in residues with those expected by the dictionary used to assign Kollman charges, qkollua. It returns a dictionary of whose keys are residues missing atoms and whose values are the names of the missing atoms. The keys are strings built from the residue name + its chain id. 228 \nPackage : Pmv 229 \nModule : repairCommands 230 \nClass : CheckForMissingAtomsCommand 231 \nCommand : checkForMissingAtoms 232 \nSynopsis:\n 233 dictOfMissingAts <--- checkForMissingAtoms(nodes, **kw) 234 \nRequired Arguments:\n 235 nodes --- TreeNodeSet holding the current selection 236 """ 237
238 - def onRemoveObjFromViewer(self, obj):
239 if obj in self.resAts.keys(): 240 del self.resAts[obj]
241 242
243 - def onAddCmdToViewer(self):
244 self.resAtomNum = {} 245 self.resAts = {} 246 self.resKeys = q.keys() 247 for item in self.resKeys: 248 self.resAtomNum[item] = len(q[item].keys()) 249 self.resAts[item] = q[item].keys()
250 251
252 - def doit(self, resSet):
253 d = {} 254 for res in resSet: 255 resType = res.type 256 if resType in self.resKeys and \ 257 len(res.atoms)<self.resAtomNum[resType]: 258 ats = [] 259 for atName in self.resAts[resType]: 260 if atName not in res.atoms.name: 261 ats.append(atName) 262 #nameStr = res.name + res.parent.id 263 #d[nameStr] = ats 264 d[res] = ats 265 return d
266 267 268
269 - def __call__(self, nodes, **kw):
270 """dictOfMissingAts <--- checkForMissingAtoms(nodes, **kw) 271 \nnodes --- TreeNodeSet holding the current selection""" 272 if type(nodes) is types.StringType: 273 self.nodeLogString = "'"+nodes+"'" 274 nodes = self.vf.expandNodes(nodes) 275 if not len(nodes): return 'ERROR' 276 resSet = nodes.findType(Residue).uniq() 277 return apply( self.doitWrapper, (resSet,), kw )
278 279 280 281 from opengltk.OpenGL import GL 282 283
284 -class CheckForCloseContactsGUICommand(MVCommand):
285 """This class provides Graphical User Interface to CheckForCloseContactsCommand which is invoked by it 286 \nPackage : Pmv 287 \nModule : repairCommands 288 \nClass : CheckForCloseContactsGUICommand 289 \nCommand : checkForCloseContactsGC 290 \nSynopsis:\n 291 None <--- checkForCloseContactsGC(keynodes,checkNodes, percentCutoff,distanceCutoff, distSelectorString,**kw) 292 \nRequired Arguments:\n 293 keyNodes --- atoms to use as reference points 294 \ncheckNodes --- atoms to check to see if close to keyNodes 295 \nOptional Arguments:\n 296 percentCutoff --- vdw scaling factor 297 \ndistanceCutoff --- distance for DistanceSelector 298 \ndistSelectorString --- name of class of selector to use 299 \nconstant --- possible constant value to be added into selection 300 \nclose is defined as interatomic distance< percentCutoff*(key_radius+check_radius) where the radii depend on atom element . 301 """ 302
303 - def onRemoveObjFromViewer(self, obj):
304 if self.oldNode==obj: 305 del self.oldNode
306 307
308 - def onAddCmdToViewer(self):
309 if self.vf.hasGui and \ 310 not self.vf.commands.has_key('checkForCloseContacts'): 311 self.vf.loadCommand('repairCommands', ['checkForCloseContacts'], 312 package='Pmv', topCommand=0) 313 if self.vf.hasGui and \ 314 not self.vf.commands.has_key('saveSet'): 315 self.vf.loadCommand('selectionCommands', ['saveSet'], 316 package='Pmv', topCommand=0) 317 318 from DejaVu.IndexedPolylines import IndexedPolylines 319 #from DejaVu.Labels import Labels 320 miscGeom = self.vf.GUI.miscGeom 321 repair_geoms = check_repair_geoms(self.vf.GUI) 322 self.masterGeom = Geom('closeContactGeoms',shape=(0,0), 323 pickable=0, protected=True) 324 self.masterGeom.isScalable = 0 325 self.vf.GUI.VIEWER.AddObject(self.masterGeom, parent = repair_geoms) 326 self.lines = IndexedPolylines('closeContLines', 327 inheritMaterial=0, 328 materials=((1,0,0),), lineWidth=3, 329 stippleLines=1, protected=True) 330 self.labels = GlfLabels(name='closeContLabels', shape=(0,3), 331 inheritMaterial=0, materials=((1,.2,0),), 332 billboard=True, fontStyle='solid', fontScales=(.3,.3,.3,)) 333 self.labels.font = 'arial1.glf' 334 self.vf.GUI.VIEWER.AddObject(self.lines, parent=self.masterGeom) 335 self.vf.GUI.VIEWER.AddObject(self.labels, parent=self.masterGeom) 336 self.vf.loadModule('labelCommands', 'Pmv') 337 self.oldNode = None 338 self.keyss_oldvalue = 0 339 self.checkss_oldvalue = 0 340 #initialize self.selector to 341 self.distSelectorDict = {'DistanceSelector':DistanceSelector, 342 'CloserThanVDWSelector': CloserThanVDWSelector, 343 'CloserThanVDWPlusConstant':CloserThanVDWPlusConstantSelector} 344 self.distSelectorString = 'CloserThanVDWSelector'
345 346
347 - def __call__(self, keyNodes, checkNodes, percentCutoff=1.0, 348 distanceCutoff=3.0, 349 distSelectorString='CloserThanVDWSelector', 350 constant=0., **kw):
351 """None <--- checkForCloseContactsGC(keynodes,checkNodes, percentCutoff,distanceCutoff, distSelectorString,**kw) 352 \nRequired Arguments:\n 353 keyNodes --- atoms to use as reference points 354 \ncheckNodes --- atoms to check to see if close to keyNodes 355 \nOptional Arguments:\n 356 percentCutoff --- vdw scaling factor 357 \ndistanceCutoff --- distance for DistanceSelector 358 \ndistSelectorString --- name of class of selector to use 359 \nconstant --- possible constant value to be added into selection 360 \nfor vdw selectors ,close is defined as interatomic distance< percentCutoff*(key_radius+check_radius) where the radii depend on atom element. 361 """ 362 if type(keyNodes) is types.StringType: 363 self.nodeLogString = "'"+keyNodes+"'" 364 keyNodes = self.vf.expandNodes(keyNodes) 365 if not len(keyNodes): return 'ERROR' 366 if type(checkNodes) is types.StringType: 367 self.nodeLogString = "'"+checkNodes+"'" 368 checkNodes = self.vf.expandNodes(checkNodes) 369 if not len(checkNodes): return 'ERROR' 370 return apply( self.doitWrapper, (keyNodes, checkNodes, percentCutoff, 371 distanceCutoff, distSelectorString, 372 constant), kw )
373 374
375 - def doit(self, keyNodes, checkNodes, percentCutoff, 376 distanceCutoff, distSelectorString, 377 constant):
378 import time 379 t1 = time.time() 380 distSelectorClass = self.distSelectorDict[distSelectorString] 381 kw = {'constant':constant} 382 self.atDict, self.distDict = apply(self.vf.checkForCloseContacts,( keyNodes, 383 checkNodes, percentCutoff, distanceCutoff, 384 distSelectorClass), kw) 385 t2 = time.time() 386 print 'Found them in ', t2-t1 387 atDict = self.atDict 388 distDict = self.distDict 389 #MUST GET RID of previous results window, else create a zombie... 390 if hasattr(self, 'ifd_results'): 391 #cleanup previous results here!?! 392 self.dismiss_cb() 393 if not len(atDict.keys()): 394 self.warningMsg('no atoms with close contacts') 395 return 396 atNames = [] 397 # to sort keys: 398 ats = AtomSet(atDict.keys()) 399 ats.sort() 400 atNames = [] 401 for a in ats: 402 atNames.append((a.full_name(), None)) 403 #figure out what the height of the listbox should be 404 result_height = len(ats) 405 if result_height>10: 406 result_height = 10 407 ifd = self.ifd_results=InputFormDescr(title = 'Check for CloseContacts Results:') 408 ifd.append({'name': 'closeContactLabel', 409 'widgetType': Tkinter.Label, 410 'wcfg':{'text': str(len(atNames)) + ' Atom(s) with Close Contacts:\nred:dist<criteria; green:dist<VDWsum*factor'}, 411 'gridcfg':{'sticky': Tkinter.W+Tkinter.E,'columnspan':2}}) 412 ifd.append({'name': 'atsLC', 413 #'widgetType':'ListChooser', 414 'widgetType':ListChooser, 415 'wcfg':{ 'entries': atNames, 416 'mode': 'single', 417 'withComment':0, 418 'title': '', 419 'command': CallBackFunction(self.showCloseContacts, atDict, distDict), 420 'lbwcfg':{'height':result_height, 421 'selectforeground': 'red', 422 'exportselection': 0, 423 #'lbpackcfg':{'fill':'both','expand':1}, 424 'width': 30}}, 425 'gridcfg':{'row':2,'column':0, 426 'columnspan':2, 'sticky':'ew'}}) 427 #'sticky':Tkinter.W+Tkinter.E+Tkinter.N+Tkinter.S}, 428 ifd.append({'name':'showAllBut', 429 'widgetType':Tkinter.Button, 430 'wcfg': { 'text':'Show All ', 431 'command': CallBackFunction(self.showAllCloseContacts, \ 432 atDict ,distDict)}, 433 'gridcfg':{'sticky':'wens'}}) 434 ifd.append({'name':'saveSetsBut', 435 'widgetType':Tkinter.Button, 436 'wcfg': { 'text':'Save as 2 sets', 437 'command': self.save_sets,}, 438 'gridcfg':{'sticky':'nesw', 439 'row':-1, 'column':1 }}) 440 ifd.append({'name':'closeBut', 441 'widgetType':Tkinter.Button, 442 'wcfg': { 'text':'Dismiss', 443 'command': self.dismiss_cb}, 444 'gridcfg':{'sticky':'nesw', 'columnspan':2}}) 445 self.result_form = self.vf.getUserInput(ifd, modal=0, blocking=0, 446 scrolledFrame=1)#, width=340, height=240) 447 self.result_form.root.protocol('WM_DELETE_WINDOW',self.dismiss_cb) 448 #1/27: show all results 449 self.showAllCloseContacts(atDict, distDict) 450 t3 = time.time() 451 print 'displayed them in ', t3-t2
452 453
454 - def cleanupDicts(self, atDict, distDict):
455 for at in atDict.keys(): 456 closeAts = atDict[at] 457 dists = distDict[at] 458 bondedAts = AtomSet([]) 459 for b in at.bonds: 460 at2 = b.atom1 461 if at2==at: at2 = b.atom2 462 bondedAts.append(at2) 463 goodAts = [] 464 goodDists = [] 465 for i in range(len(closeAts)): 466 cAt = closeAts[i] 467 if cAt not in bondedAts: 468 goodAts.append(cAt) 469 goodDists.append(dists[i]) 470 if len(goodAts): 471 atDict[at] = goodAts 472 distDict[at] = goodDists 473 else: 474 del atDict[at] 475 del distDict[at] 476 return atDict, distDict
477 478
479 - def dismiss_cb(self, event=None):
480 self.lines.Set(faces=[], vertices=[], tagModified=False) 481 self.labels.Set(vertices=[], tagModified=False) 482 self.vf.GUI.VIEWER.Redraw() 483 self.result_form.destroy()
484 485
486 - def setupDisplay(self, lineVerts, faces, labelVerts, labelStrs, colors):
487 #draw lines between at(s) and closeAts 488 self.labels.Set(vertices=labelVerts, labels=labelStrs, 489 materials=colors, tagModified=False) 490 self.lines.Set(vertices=lineVerts, type=GL.GL_LINE_STRIP, 491 materials=colors, 492 faces=faces, freshape=1, tagModified=False) 493 self.vf.GUI.VIEWER.Redraw()
494 495
496 - def save_sets(self, event=None):
497 keyAts = AtomSet(self.atDict.keys()) 498 #build an AtomSet of atoms close to any key 499 closeAts = AtomSet([]) 500 for v in self.atDict.values(): 501 closeAts.extend(AtomSet(v)) 502 #there could be duplication here... 503 #NOTE: THIS DISORDERS the atoms 504 closeAts = closeAts.uniq() 505 self.vf.saveSet(keyAts, 'closeContact_keys',comments="keys for checkForCloseContact") 506 self.vf.saveSet(closeAts, 'closeContact_values', comments="results of checkForCloseContact")
507 508
509 - def showAllCloseContacts(self, atDict, distDict, event=None):
510 lineVerts = [] 511 faces = [] 512 labelVerts = [] 513 labelStrs = [] 514 faces = [] 515 ctr = 1 516 atCtr = 0 517 colors = [] 518 colorCutOff = 1.0 # FIXME should be user setable 519 for at in atDict.keys(): 520 lineVerts.append(at.coords) 521 c1 = Numeric.array(at.coords, 'f') 522 r1 = at.vdwRadius 523 closeAts = atDict[at] 524 thisAtCtr = 1 525 for cAt in closeAts: 526 lineVerts.append(cAt.coords) 527 faces.append((atCtr, ctr)) 528 #build labelVert and labelStr 529 c2 = Numeric.array(cAt.coords, 'f') 530 #newCenter = tuple((c1 + c2)/2.0) 531 labelVerts.append(tuple((c1 + c2)/2.0)) 532 j = thisAtCtr/2 533 labelStrs.append(str(round(distDict[at][j],3))) 534 r2 = cAt.vdwRadius 535 if distDict[at][j]<(r1+r2)*colorCutOff: 536 colors.append( (1,0,0) ) 537 else: 538 colors.append( (0,1,0) ) 539 thisAtCtr = thisAtCtr + 1 540 ctr = ctr+1 541 atCtr = ctr 542 ctr = ctr+1 543 self.resultCtr = atCtr 544 #print "set resultCtr to ", atCtr 545 self.setupDisplay(lineVerts, faces, labelVerts, labelStrs, colors)
546 547
548 - def showCloseContacts(self, atDict, distDict, event=None):
549 print "#############in SHOWCLOSECONTACTS#############" 550 lb = self.ifd_results.entryByName['atsLC']['widget'].lb 551 if lb.curselection() == (): return 552 atName = lb.get(lb.curselection()) 553 at = self.vf.Mols.NodesFromName(atName)[0] 554 closeAts = atDict[at] 555 lineVerts = [] 556 faces = [] 557 labelVerts = [] 558 labelStrs = [] 559 ctr = 1 560 lineVerts.append(at.coords) 561 c1 = Numeric.array(at.coords, 'f') 562 j = 0 563 r1 = at.vdwRadius 564 colors = [] 565 colorCutOff = 1.0 # FIXME should be user setable 566 for cAt in closeAts: 567 lineVerts.append(cAt.coords) 568 faces.append((0, ctr)) 569 #build labelVert and labelStr 570 c2 = Numeric.array(cAt.coords, 'f') 571 labelVerts.append(tuple((c1 + c2)/2.0)) 572 labelStrs.append(str(round(distDict[at][j],3))) 573 ctr = ctr+1 574 r2 = cAt.vdwRadius 575 if distDict[at][j]<(r1+r2)*colorCutOff: 576 colors.append( (1,0,0) ) 577 else: 578 colors.append( (0,1,0) ) 579 j = j + 1 580 self.setupDisplay(lineVerts, faces, labelVerts, labelStrs, colors)
581 582
583 - def buildForm(self):
584 if hasattr(self, 'ifd0'): 585 return 586 self.selType = Tkinter.StringVar() 587 self.selType.set("CloserThanVDW") 588 ifd = self.ifd0 = InputFormDescr(title = "Select Two Sets:") 589 ifd.append({'name':'keyLab', 590 'widgetType':Tkinter.Label, 591 'text':'Select Key Atoms:', 592 'gridcfg':{'sticky':Tkinter.W, 'columnspan':4}}) 593 ifd.append({'name': 'keySelector', 594 'wtype':StringSelectorGUI, 595 'widgetType':StringSelectorGUI, 596 'wcfg':{ 'molSet': self.vf.Mols, 597 'vf': self.vf, 598 'all':1, 599 'crColor':(0.,1.,0.), 600 }, 601 'gridcfg':{'sticky':'we' , 'columnspan':4}}) 602 ifd.append({'name':'interSelLab', 603 'widgetType':Tkinter.Label, 604 'text':'_____________________________________________', 605 'gridcfg':{'sticky':Tkinter.W, 'columnspan':4}}) 606 ifd.append({'name':'checkLab', 607 'widgetType':Tkinter.Label, 608 'text':'Select Atoms to check vs Keys:', 609 'gridcfg':{'sticky':Tkinter.W, 'columnspan':4}}) 610 ifd.append({'name': 'checkSelector', 611 'wtype':StringSelectorGUI, 612 'widgetType':StringSelectorGUI, 613 'wcfg':{ 'molSet': self.vf.Mols, 614 'vf': self.vf, 615 'all':1, 616 'crColor':(0.,0.,1.), 617 }, 618 'gridcfg':{'sticky':'we', 'columnspan':4 }}) 619 ifd.append({'name':'noteLab', 620 'widgetType':Tkinter.Label, 621 'text':'(empty form uses all atoms in viewer)', 622 'gridcfg':{'sticky':'we', 'columnspan':4}}) 623 ifd.append({'name':'interSelLab2', 624 'widgetType':Tkinter.Label, 625 'text':'_____________________________________________', 626 'gridcfg':{'sticky':Tkinter.W, 'columnspan':4}}) 627 ifd.append({'name':'selectorLab', 628 'widgetType':Tkinter.Label, 629 'text':'Select Selection Algorithm:', 630 'gridcfg':{'sticky':Tkinter.W, 'columnspan':4}}) 631 #ifd.append({'name':'interSelLab3', 632 #'widgetType':Tkinter.Label, 633 #'text':'_____________________________________________', 634 #'gridcfg':{'sticky':Tkinter.W, 'columnspan':4}}) 635 ifd.append({'name':'VDWsel', 636 'widgetType':Tkinter.Radiobutton, 637 'wcfg':{'text':"CloserThanVDW", 638 'variable':self.selType, 639 'value':"CloserThanVDWSelector", 640 'command':self.setDistSelector_cb, 641 }, 642 'gridcfg':{'sticky':'w'}}) 643 ifd.append({'name':'vdwPercentCutoff', 644 'widgetType':ThumbWheel, 645 #'The critical distance will be multiplied by this factor', 646 'tooltip': 'VDW Scaling Factor:\n(cutoff=Sum of vdwRadii*scale)', 647 'wcfg':{'labCfg':{'text': ' scale:'}, 648 'showLabel':1, 'width':150, 649 'min':0.1, 'type':float, 'precision':2, 650 'value':1.0, 'continuous':1, 'oneTurn':2, 651 'wheelPad':2, 'height':20}, 652 'gridcfg':{'row':-1,'column':1, 'columnspan':3,'sticky':'we'}}) 653 ifd.append({'name':'VDWPlussel', 654 'widgetType':Tkinter.Radiobutton, 655 'wcfg':{'text':"CloserThanVDWPlusConstant", 656 'variable':self.selType, 657 'value':"CloserThanVDWPlusConstant", 658 'command':self.setDistSelector_cb, 659 }, 660 'gridcfg':{'sticky':'w'}}) 661 ifd.append({'name':'vdwPlusConstant', 662 'widgetType':ThumbWheel, 663 #'The critical distance will be multiplied by this factor', 664 'tooltip': 'VDW Plus Constant Factor:\n(cutoff=Sum of vdwRadii+constant)', 665 'wcfg':{'labCfg':{'text': 'const:'}, 666 'showLabel':1, 'width':150, 667 'type':float, 'precision':2, 668 'value':0.0, 'continuous':1, 'oneTurn':2, 669 'wheelPad':2, 'height':20}, 670 'gridcfg':{'row':-1,'column':1, 'columnspan':3,'sticky':'we'}}) 671 ifd.append({'name':'Distsel', 672 'widgetType':Tkinter.Radiobutton, 673 'wcfg':{'text':"Distance", 674 'variable':self.selType, 675 'value':"DistanceSelector", 676 'command':self.setDistSelector_cb, 677 }, 678 'gridcfg':{'sticky':'w'}}) 679 680 ifd.append({'name':'distanceCutoff', 681 'widgetType':ThumbWheel, 682 'tooltip':'angstrom distance cutoff', 683 'wcfg':{'labCfg':{'text': 'cutoff:'}, 684 'showLabel':1, 'width':150, 685 'min':0.1, 'type':float, 'precision':2, 686 'value':3.0, 'continuous':1, 'oneTurn':2, 687 'wheelPad':2, 'height':20}, 688 'gridcfg':{'row':-1,'column':1, 'columnspan':3,'sticky':'we'}}) 689 ifd.append({'name': 'ok', 690 'widgetType': Tkinter.Button, 691 'wcfg':{ 'text': 'OK', 692 'command': self.ok_cb,}, 693 'gridcfg': {'sticky':'we'}}), 694 ifd.append({'name': 'cancel', 695 'widgetType': Tkinter.Button, 696 'wcfg':{ 'text': 'Cancel', 697 'command': self.cancel_cb,}, 698 'gridcfg': {'sticky':'we', 'row':-1, 'column':1, 699 'columnspan':3}}), 700 self.form = self.vf.getUserInput(ifd, modal=0, blocking=0, 701 scrolledFrame=1)#, width=440, height=540) 702 self.key_ss = self.ifd0.entryByName['keySelector']['widget'] 703 self.check_ss = self.ifd0.entryByName['checkSelector']['widget'] 704 #make the default distance selector CloserThanVDWSelector 705 self.ifd0.entryByName['VDWsel']['widget'].invoke()
706 707
708 - def setDistSelector_cb(self, event=None):
709 #value is a string: eg 'vdwSum' 710 self.selector = self.selType.get()
711 #print "set self.selector to ", self.selector 712 713
714 - def update_old_values(self):
715 if hasattr(self, 'key_ss'): 716 self.keyss_oldvalue = self.key_ss.showCurrent.get() 717 if hasattr(self, 'check_ss'): 718 self.checkss_oldvalue = self.check_ss.showCurrent.get()
719 720
721 - def ok_cb(self, event=None):
722 keys = self.key_ss.get() 723 if not len(keys): 724 keyAts = self.vf.allAtoms 725 else: 726 cl = keys[0].setClass 727 keySet = cl(keys) 728 keyAts = keySet 729 if cl!=Atom: 730 keyAts = keySet.findType(Atom) 731 checks = self.check_ss.get() 732 if not len(checks): 733 checkAts = self.vf.allAtoms 734 else: 735 cl = checks[0].setClass 736 checkSet = cl(checks) 737 checkAts = checkSet 738 if cl!=Atom: 739 checkAts = checkSet.findType(Atom) 740 percentCutoff = self.ifd0.entryByName['vdwPercentCutoff']['widget'].get() 741 #print 'using ', percentCutoff,' for percentCutoff' 742 distanceCutoff = self.ifd0.entryByName['distanceCutoff']['widget'].get() 743 #print 'using ', distanceCutoff,' for distanceCutoff' 744 constant = self.ifd0.entryByName['vdwPlusConstant']['widget'].get() 745 self.update_old_values() 746 return self.doitWrapper(keyAts, checkAts, percentCutoff, distanceCutoff, self.selector, constant=constant, topCommand=0)
747 748
749 - def cancel_cb(self, event=None):
750 #force the CrossSets to undisplay, but remember the old values 751 self.update_old_values() 752 if hasattr(self, 'key_ss'): 753 self.key_ss.showCurrent.set(0) 754 self.key_ss.Show_cb() 755 if hasattr(self, 'check_ss'): 756 self.check_ss.showCurrent.set(0) 757 self.check_ss.Show_cb() 758 self.form.withdraw() 759 return
760 761
762 - def guiCallback(self):
763 if not len(self.vf.Mols): 764 self.warningMsg('no molecules in viewer') 765 return 766 if hasattr(self, 'ifd0'): 767 self.form.deiconify() 768 #force the CrossSets to display 769 self.key_ss.showCurrent.set(self.keyss_oldvalue) 770 self.key_ss.Show_cb() 771 self.check_ss.showCurrent.set(self.checkss_oldvalue) 772 self.check_ss.Show_cb() 773 else: 774 self.buildForm()
775 776 777 checkForCloseContactsGUICommandGuiDescr = {'widgetType':'Menu', 778 'menuBarName':'menuRoot', 779 'menuButtonName':'Edit', 780 'menuEntryLabel':'Check For Close Contacts'} 781 782 783 CheckForCloseContactsGUICommandGUI = CommandGUI() 784 CheckForCloseContactsGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 785 'Check for Close Contacts', cascadeName='Misc', index=0) 786 787 788 789
790 -class CheckForCloseContacts(MVCommand):
791 """This command detects atoms which are selected as "close" by a MolKit.distanceSelector. These selectors use criteria such as closer than combined atomic radii distance of nodes or closer than a specific distance. 792 \nPackage : Pmv 793 \nModule : repairCommands 794 \nClass : CheckForCloseContacts 795 \nCommand : checkForCloseContacts 796 \nSynopsis:\n 797 closeAts <--- checkForCloseContacts(keyNodes, nodesToCheck, percentCutoff, **kw) 798 \nRequired Arguments:\n 799 keyNodes --- nodes to use as centers for selectInSphere of distance keyNode.radius + radius nodes in nodesToCheck 800 \nnodesToCheck --- nodes to test to see if within sumRadii distance of keyNodes. 801 \nOptional Arguments:\n 802 percentCutoff --- each sum of radii * this number is used to pick close contacts 803 \ndistSelectorClass=None --- optional distanceSelector Class.default class is CloserThanVDWSelector 804 """ 805
806 - def onAddCmdToViewer(self):
807 self.distSelector = CloserThanVDWSelector()
808
809 - def doit(self, keyAts, checkAts, percentCutoff, distanceCutoff, **kw):
810 distSelectorClass = kw.get('distSelectorClass') 811 if distSelectorClass is None: 812 print "using self.distSelector" 813 distSelector = self.distSelector 814 else: 815 dict = {} 816 if kw.has_key("constant"): 817 dict['constant'] = kw.get('constant') 818 distSelector = apply(distSelectorClass,(), dict) 819 820 pairDict, distDict = distSelector.select(keyAts, checkAts, 821 percentCutoff=percentCutoff, cutoff=distanceCutoff) 822 pairDict, distDict = self.cleanupDicts(pairDict, distDict) 823 return pairDict, distDict
824 825
826 - def cleanupDicts(self, atDict, distDict):
827 for at in atDict.keys(): 828 closeAts = atDict[at] 829 dists = distDict[at] 830 bondedAts = AtomSet([]) 831 #CA-N-H 832 for b in at.bonds: 833 at2 = b.atom1 834 if at2==at: at2 = b.atom2 835 bondedAts.append(at2) 836 # need to exclude 1:3 bonds here 837 for bd in at2.bonds: 838 at3 = bd.atom1 839 if at3==at2: at3 = bd.atom2 840 if at3!=at: 841 bondedAts.append(at3) 842 # need to exclude 1:4 bonds here 843 for bnd in at3.bonds: 844 at4 = bnd.atom1 845 if at4 == at3: 846 at4 = bnd.atom2 847 if at4!=at and at4!=at2: 848 bondedAts.append(at4) 849 goodAts = [] 850 goodDists = [] 851 for i in range(len(closeAts)): 852 cAt = closeAts[i] 853 if cAt not in bondedAts: 854 goodAts.append(cAt) 855 goodDists.append(dists[i]) 856 if len(goodAts): 857 atDict[at] = goodAts 858 distDict[at] = goodDists 859 else: 860 del atDict[at] 861 del distDict[at] 862 return atDict, distDict
863 864
865 - def __call__(self, keyNodes, nodesToCheck, percentCutoff=1.0, distanceCutoff=3.0, 866 distSelectorClass=None,**kw):
867 """closeAts <- checkForCloseContacts(keyNodes, nodesToCheck, percentCutoff, **kw) 868 \nRequired Arguments:\n 869 keyNodes --- nodes to use as centers for selectInSphere of distance keyNode.radius + radius nodes in nodesToCheck\n 870 nodesToCheck --- nodes to test to see if within sumRadii distance of keyNodes.\n 871 \nOptional Arguments:\n 872 percentCutoff --- each sum of radii * this number is used to pick close contacts\n 873 distSelectorClass=None --- optional distanceSelector Class\n 874 """ 875 # be sure that all ats have radius 876 # WHAT ABOUT UNITED ATOM v. plain??? 877 #tops1 = keyNodes.top.uniq() 878 #tops2 = nodesToCheck.top.uniq() 879 #tops = tops1+tops2 880 #tops = tops.uniq() 881 #for top in tops: 882 #top.defaultRadii(united=0) 883 ## if type(keyNodes) is types.StringType: 884 ## self.nodeLogString = "'"+keyNodes+"'" 885 keyNodes = self.vf.expandNodes(keyNodes) 886 887 if not len(keyNodes): return 'ERROR' 888 keyAts = keyNodes.findType(Atom) 889 nodesToCheck = self.vf.expandNodes(nodesToCheck) 890 if not len(nodesToCheck): return 'ERROR' 891 checkAts = nodesToCheck.findType(Atom) 892 kw['distSelectorClass'] = distSelectorClass 893 return apply( self.doitWrapper, (keyAts, checkAts, percentCutoff, distanceCutoff), kw )
894 895
896 -class RepairMissingAtomsGUICommand(MVCommand):
897 """This class provides Graphical User Interface to RepairMissingAtomsCommand which is invoked by it with the current selection, if there is one. 898 \nPackage : Pmv 899 \nModule : repairCommands 900 \nClass : RepairMissingAtomsGUICommand 901 \nCommand : repairMissingAtomsGC 902 \nSynopsis:\n 903 closeContactDict<---repairMissingAtomsGC(nodes) 904 \nRequired Arguments:\n 905 nodes --- molecule(s) to check for missing atoms 906 """ 907
908 - def __init__(self, func=None):
909 MVCommand.__init__(self, func) 910 self.flag = self.flag | self.objArgOnly
911
912 - def onRemoveObjFromViewer(self, obj):
913 if self.oldNode==obj: 914 del self.oldNode
915 916
917 - def onAddCmdToViewer(self):
918 self.oldNode = None
919 920
921 - def __call__(self, nodes, **kw):
922 """closeContactDict<---repairMissingAtomsGC(nodes) 923 \nnodes --- molecule(s) to check for missing atoms 924 """ 925 if type(nodes) is types.StringType: 926 self.nodeLogString = "'"+nodes+"'" 927 nodes = self.vf.expandNodes(nodes) 928 if not len(nodes): return 'ERROR' 929 return apply(self.doitWrapper,(nodes,), kw)
930 931
932 - def doit(self, nodes):
933 dict = self.vf.checkForMissingAtoms(nodes) 934 if not len(dict.keys()): 935 self.warningMsg('no residues to repair') 936 return 'ERROR' 937 resNames = [] 938 resSet = ResidueSet(dict.keys()) 939 newAts = self.vf.repairMissingAtoms(resSet) 940 mol = resSet[0].top 941 self.vf.GUI.VIEWER.Redraw() 942 #check for closeContacts of newAts vs self.vf.allAtoms 943 return self.vf.checkForCloseContactsGC(newAts, self.vf.allAtoms, 0.9, 944 topCommand=0)
945 946
947 - def guiCallback(self):
948 sel = self.vf.getSelection() 949 if len(sel): 950 if self.vf.userpref['expandNodeLogString']['value'] == 0: 951 self.vf.repairMissingAtoms.nodeLogString = "self.getSelection()" 952 mol = sel.top.uniq()[0] 953 #FIX THIS: why not just use sel.top.uniq()???? 954 return self.doitWrapper(mol, topCommand=0)
955 956 957 repairMissingAtomsGUICommandGuiDescr = {'widgetType':'Menu', 958 'menuBarName':'menuRoot', 959 'menuButtonName':'Edit', 960 'menuEntryLabel':'Repair Missing Atoms '} 961 962 963 RepairMissingAtomsGUICommandGUI = CommandGUI() 964 RepairMissingAtomsGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 965 'Repair Missing Atoms ', cascadeName='Misc') 966 967 968
969 -class RepairMissingAtoms(MVCommand):
970 """This command compares atoms present in residues with those expected by the dictionary used to assign Kollman charges, qkollua. It builds the missing atoms. 971 \nPackage : Pmv 972 \nModule : repairCommands 973 \nClass : RepairMissingAtoms 974 \nCommand : repairMissingAtoms 975 \nSynopsis:\n 976 dictOfMissingAts <--- repairMissingAtoms(nodes, **kw) 977 \nRequired Arguments:\n 978 nodes --- TreeNodeSet holding the current selection 979 """ 980
981 - def onRemoveObjFromViewer(self, obj):
982 if obj in self.resAts.keys(): 983 del self.resAts[obj]
984 985
986 - def onAddCmdToViewer(self):
987 #from Pmv.gmmRes import resDict 988 from Pmv.qkollRes import resDict 989 self.vf.loadModule('superImposeCommands', 'Pmv') 990 self.vf.loadModule('deleteCommands', 'Pmv') 991 self.resDict = resDict
992 993
994 - def getRefMol(self, resType, ptype = PdbParser):
995 newparser = ptype(None) 996 atLines = self.resDict[resType] 997 refmol = newparser.buildMolFromAtomLines(atLines, resType) 998 self.vf.addMolecule(refmol) 999 return refmol
1000 1001
1002 - def doit(self, resSet):
1003 newAts = AtomSet([]) 1004 for res in resSet: 1005 #print 'repairing ', res.name 1006 if res.type not in self.resDict.keys(): 1007 #print 'skipping ', res 1008 continue 1009 mol = res.top 1010 resType = res.type 1011 resAts = res.atoms 1012 #oxt = resAts.get(lambda x: x.name=='OXT') 1013 #if oxt: 1014 #resAts = resAts - oxt[0] 1015 1016 resAtNames = resAts.name 1017 refmol = self.getRefMol(resType) 1018 #refmol = self.getRefMol(resType, ptype) 1019 ats2 = refmol.allAtoms 1020 # inAts are atoms in refmol which are also in mol 1021 inAts = ats2.get(lambda x,resAtNames=resAtNames:x.name in resAtNames) 1022 inAtsname = inAts.name 1023 # resATS2 are atoms in mol which are also in refmol 1024 resAts2 = resAts.get(lambda x,inAtsname=inAtsname:x.name in inAtsname) 1025 #move new refmol ontop of res 1026 self.vf.superimposeCoords(resAts2, inAts, refmol.allAtoms, topCommand=0) 1027 #the diff between refmol's shared ats and all atoms is atsToBuild 1028 atsToBuild = ats2 - inAts 1029 builtAts = AtomSet([]) 1030 for at in atsToBuild: 1031 #print 'building copy of ', at.full_name() 1032 newAt = Atom(name=at.name, parent=res, 1033 elementType = at.elementType, top=mol) 1034 for k in at.colors.keys(): 1035 newAt.colors[k] = at.colors[k] 1036 #for k in at._charges.keys(): 1037 # newAt._charges[k] = at._charges[k] 1038 newAt.chargeSet = at.chargeSet 1039 newAt.element = at.element 1040 newAt.hetatm = at.hetatm 1041 newAt._coords = [] 1042 newAt._coords.append(at.coords) 1043 #redo number at end 1044 newAt.number = at.number 1045 #after redoing numbers set up mol.atmNum[newAt.number] = newAt 1046 newAt.occupancy = at.occupancy 1047 newAt.temperatureFactor = at.temperatureFactor 1048 #need to build bonds to all Atoms which at has bonds(?) 1049 for b in at.bonds: 1050 at2 = b.atom1 1051 if at2==at: at2 = b.atom2 1052 #see if other atom has been built yet 1053 if at2.name in res.atoms.name: 1054 atom2 = res.atoms.get(lambda x, at2=at2: x.name == at2.name)[0] 1055 bond = Bond(newAt, atom2, origin = 'UserDefined') 1056 for k in atom2._charges.keys(): 1057 #can't use at_charges 1058 newAt._charges[k] = 0.00 1059 newAt.chargeSet = atom2.chargeSet 1060 #after adding allAtoms and removing mol2, call buildBondsByDist. 1061 builtAts.append(newAt) 1062 newAts.append(newAt) 1063 mol.allAtoms = mol.allAtoms + builtAts 1064 1065 #after building all atsToBuild for this residue, delete mol2 +bbByD 1066 self.vf.deleteMol(refmol, topCommand=0) 1067 if len(newAts): 1068 #don't forget to rebuild mv.allAtoms 1069 self.vf.allAtoms = self.vf.Mols.chains.residues.atoms 1070 event = AddAtomsEvent(objects=newAts) 1071 self.vf.dispatchEvent(event) 1072 1073 return newAts
1074 1075
1076 - def __call__(self, nodes, **kw):
1077 """dictOfMissingAts <--- checkForMissingAtoms(nodes, **kw) 1078 \nnodes --- TreeNodeSet holding the current selection""" 1079 if type(nodes) is types.StringType: 1080 self.nodeLogString = "'"+nodes+"'" 1081 nodes = self.vf.expandNodes(nodes) 1082 if not len(nodes): return 'ERROR' 1083 resSet = nodes.findType(Residue).uniq() 1084 return apply( self.doitWrapper, (resSet,), kw )
1085 1086 1087
1088 -class EditHistHydrogensGUICommand(MVCommand):
1089 """Allows user to call editHistHydrogens on each histidine residue in selection. 1090 \nPackage : Pmv 1091 \nModule : repairCommands 1092 \nClass : EditHistHydrogensGUICommand 1093 \nCommand : editHist_hGC 1094 \nSynopsis:\n 1095 newHydrogens <--- editHist_hGC(nodes, resSet, **kw) 1096 \nRequired Arguments:\n 1097 nodes --- TreeNodeSet holding the current selection 1098 \nresSet --- residueSet 1099 """ 1100 1101
1102 - def __init__(self, func=None):
1103 MVCommand.__init__(self, func) 1104 self.flag = self.flag | self.objArgOnly
1105
1106 - def guiCallback(self):
1107 if self.vf.userpref['expandNodeLogString']['value'] == 0: 1108 self.vf.editHist_h.nodeLogString = "self.getSelection()" 1109 sel = self.vf.getSelection() 1110 if len(sel): 1111 res = sel.findType(Residue, uniq=1) 1112 resSet = res.get(lambda x: x.type == 'HIS') 1113 if resSet is None or not len(resSet): 1114 self.warningMsg('No Histidines in selection') 1115 return 'ERROR' 1116 self.doitWrapper(resSet, topCommand=0) 1117 else: 1118 self.warningMsg('Nothing to select!')
1119 1120
1121 - def __call__(self, nodes, resSet, **kw):
1122 """newHydrogens <--- editHist_hGC(nodes, resSet, **kw) 1123 \nnodes --- TreeNodeSet holding the current selection 1124 \nresSet --- residueSet 1125 """ 1126 if type(nodes) is types.StringType: 1127 self.nodeLogString = "'"+nodes+"'" 1128 kw['topCommand'] = 0 1129 nodes = self.vf.expandNodes(nodes) 1130 if not len(nodes): return 'ERROR' 1131 res = nodes.findType(Residue, uniq=1) 1132 resSet = res.get(lambda x: x.type == 'HIS') 1133 if not resSet: 1134 self.warningMsg('No Histidines in selection') 1135 return 'ERROR' 1136 apply(self.doitWrapper,(resSet,), kw)
1137 1138
1139 - def doit(self, resSet):
1140 resNames = [] 1141 for r in resSet: 1142 resNames.append(r.full_name()) 1143 #put up a form here with buttons 1144 ifd = self.ifd=InputFormDescr(title = 'Edit Histidine Hydrogens :') 1145 ifd.append({'name': 'histLabel1', 1146 'widgetType': Tkinter.Label, 1147 'wcfg':{'text': 'Histidine'}, 1148 'gridcfg':{'sticky': 'nesw'}}) 1149 ifd.append({'name': 'histLabel2', 1150 'widgetType': Tkinter.Label, 1151 'wcfg':{'text': ' 0, HD1 '}, 1152 'gridcfg':{'sticky': 'nesw', 'row':-1, 'column':1}}) 1153 ifd.append({'name': 'histLabel3', 1154 'widgetType': Tkinter.Label, 1155 'wcfg':{'text': ' 0, HE2 '}, 1156 'gridcfg':{'sticky': 'nesw', 'row':-1, 'column':2}}) 1157 ifd.append({'name': 'histLabel3', 1158 'widgetType': Tkinter.Label, 1159 'wcfg':{'text': '+1 '}, 1160 'gridcfg':{'sticky': 'nesw', 'row':-1, 'column':3}}) 1161 ifd.append({'name': 'histLabel4', 1162 'widgetType': Tkinter.Label, 1163 'wcfg':{'text': '_______________________________________________'}, 1164 'gridcfg':{'sticky': 'nesw', 'columnspan':5}}) 1165 #build the rest of it here 1166 self.cbDict = {} 1167 cbFuncs = [None, 'HD1', 'HE2', 'HD1HE2'] 1168 nameLabs = [] 1169 for n in range(len(resNames)): 1170 name = resNames[n] 1171 r = resSet[n] 1172 nameLab = name + 'lab' 1173 nameLabs.append(nameLab) 1174 cbNames = [] 1175 self.cbDict[name] = newvar = Tkinter.StringVar() 1176 ratomnames = r.atoms.name 1177 hasHD1 = 'HD1' in ratomnames 1178 hasHE2 = 'HE2' in ratomnames 1179 if hasHD1 and hasHE2: 1180 newvar.set('HD1HE2') 1181 elif hasHD1 and not hasHE2: 1182 newvar.set('HD1') 1183 elif hasHE2 and not hasHD1: 1184 newvar.set('HE2') 1185 ifd.append({'name': nameLab, 1186 'widgetType': Tkinter.Label, 1187 'wcfg':{'text': name}, 1188 'gridcfg':{'sticky': Tkinter.W+Tkinter.E}}) 1189 for i in range(1,4): 1190 newname = name + str(i) 1191 cbNames.append(newname) 1192 ifd.append({'name': newname, 1193 'widgetType': Tkinter.Radiobutton, 1194 'variable': newvar, 1195 'value': cbFuncs[i], 1196 'gridcfg':{'sticky': 'we', 'row':-1, 'column':i}}) 1197 ifd.append({'name':'applyBut', 1198 'widgetType':Tkinter.Button, 1199 'wcfg': { 'text':'Apply', 1200 'command': self.apply_cb}, 1201 'gridcfg':{'sticky':Tkinter.W+Tkinter.E, 'columnspan':2}}) 1202 ifd.append({'name':'closeBut', 1203 'widgetType':Tkinter.Button, 1204 'wcfg': { 'text':'Dismiss', 1205 'command': self.dismiss_cb}, 1206 'gridcfg':{'sticky':'we', 'columnspan':3, 1207 'row':-1, 'column':2}}) 1208 self.form = self.vf.getUserInput(ifd, modal=0, blocking=0, 1209 scrolledFrame=1, width=500) 1210 self.form.root.protocol('WM_DELETE_WINDOW',self.dismiss_cb) 1211 for name in nameLabs: 1212 ifd.entryByName[name]['widget'].bind('<Button-1>', CallBackFunction(self.highLight, name) )
1213 1214
1215 - def highLight(self, name, event=None):
1216 self.vf.clearSelection() 1217 self.vf.setIcomLevel(Residue, topCommand=0) 1218 self.vf.select(name[:-3])
1219 1220
1221 - def apply_cb(self, event=None):
1222 #FIX THIS: may not need any changes 1223 nodeDict = {} 1224 for k, v in self.cbDict.items(): 1225 nodeDict[k] = v.get() 1226 #print 'nodeDict=', nodeDict 1227 1228 newHydrogens = self.vf.editHist_h(nodeDict) 1229 1230 self.vf.GUI.VIEWER.Redraw()
1231 1232
1233 - def dismiss_cb(self, event=None):
1234 self.form.root.destroy()
1235 1236 1237 EditHistHydrogensGUICommandGUI=CommandGUI() 1238 EditHistHydrogensGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 1239 'Edit Histidine Hydrogens', cascadeName='Hydrogens') 1240 1241 1242
1243 -class EditHistHydrogens(MVCommand):
1244 """Allows user to edit hydrogens in histidine residues 1245 \nPackage : Pmv 1246 \nModule : repairCommands 1247 \nClass : EditHistHydrogens 1248 \nCommand : editHist_h 1249 \nSynopsis:\n 1250 newHydrogens <--- editHist_h(nodeDict, **kw) 1251 \nRequired Arguments:\n 1252 nodeDict --- a dictionary of a TreeNodeSet holding the current selection 1253 """ 1254 1255
1256 - def onAddCmdToViewer(self):
1257 if not self.vf.commands.has_key('typeAtoms'): 1258 self.vf.loadCommand('editCommands', 'typeAtoms','Pmv', 1259 topCommand=0) 1260 if not self.vf.commands.has_key('deleteAtomSet'): 1261 self.vf.loadCommand('deleteCommands', 'deleteAtomSet','Pmv', 1262 topCommand=0) 1263 if not self.vf.commands.has_key('computeGasteiger'): 1264 self.vf.loadCommand('editCommands', 'computeGasteiger','Pmv', 1265 topCommand=0) 1266 from PyBabel.addh import AddHydrogens, SP2_N_H_DIST 1267 self.addh = AddHydrogens() 1268 self.SP2_N_H_DIST = SP2_N_H_DIST
1269 1270
1271 - def __call__(self, nodeDict, **kw):
1272 """newHydrogens <--- editHist_h(nodeDict, **kw) 1273 \nnodeDict --- a dictionary of a TreeNodeSet holding the current selection""" 1274 #nodeDict keys had better be full_names 1275 #values can be the name of the function to do it 1276 theseNodes = ResidueSet([]) 1277 for name in nodeDict.keys(): 1278 newNodes = self.vf.expandNodes(name) 1279 if len(newNodes): 1280 theseNodes = theseNodes + self.vf.expandNodes(name) 1281 if len(theseNodes): 1282 #if there are nodes, there have to be Residues 1283 mols = theseNodes.top.uniq() 1284 for mol in mols: 1285 self.vf.typeAtoms(mol, topCommand=0) 1286 return apply(self.doitWrapper,(nodeDict,), kw) 1287 else: return 'ERROR'
1288 1289
1290 - def doit(self, nodeDict):
1291 #for each node set its type 1292 #have to call typeAtoms on the mols involved 1293 atmsToDelete = AtomSet([]) 1294 newHydrogens = AtomSet([]) 1295 self.hasKollman = 0 1296 self.hasgasteiger = 0 1297 for node, value in nodeDict.items(): 1298 res = self.vf.expandNodes(node)[0] 1299 badHs, newHs = self.editHIS(res, value) 1300 if badHs: 1301 atmsToDelete = atmsToDelete + badHs 1302 if newHs: 1303 newHydrogens = newHydrogens + newHs 1304 #check the userpref here 1305 if len(atmsToDelete): 1306 self.vf.allAtoms = self.vf.allAtoms - atmsToDelete 1307 for mol in atmsToDelete.top.uniq(): 1308 mol.allAtoms = mol.allAtoms - atmsToDelete 1309 for at in atmsToDelete: 1310 for b in at.bonds: 1311 at2 = b.atom1 1312 if at2==at: at2=b.atom2 1313 at2.bonds.remove(b) 1314 at.parent.remove(at, cleanup=1) 1315 # add the new atoms and make an effort to add the correct charges... 1316 if len(newHydrogens): 1317 self.vf.allAtoms = self.vf.allAtoms + newHydrogens 1318 mols, atms = self.vf.getNodesByMolecule(newHydrogens, Atom) 1319 for m, ats in map(None, mols, atms): 1320 m.allAtoms = m.allAtoms + ats 1321 if self.hasKollman: 1322 self.vf.addKollmanCharges(newHydrogens, topCommand=0) 1323 if self.hasgasteiger: 1324 self.vf.computeGasteiger(newHydrogens, topCommand=0) 1325 1326 if len(newHydrogens): 1327 event = DeleteAtomsEvent(objects=atmsToDelete) 1328 self.vf.dispatchEvent(event) 1329 1330 event = AddAtomsEvent(objects=newHydrogens) 1331 self.vf.dispatchEvent(event) 1332 1333 return newHydrogens
1334 1335
1336 - def editHIS(self, res, key):
1337 resatomnames = res.atoms.name 1338 hasHD1 = 'HD1' in resatomnames 1339 hasHE2 = 'HE2' in resatomnames 1340 if len(key)>3: 1341 return self.HD1HE2(res, hasHD1, hasHE2) 1342 elif key=='HD1': 1343 return self.HD1(res, hasHD1, hasHE2) 1344 else: 1345 return self.HE2(res, hasHD1, hasHE2)
1346 1347
1348 - def fixCharges(self, h, a, kollCh, gastCh):
1349 if a._charges.get('Kollman', None): 1350 self.hasKollman = 1 1351 h._charges['Kollman'] = kollCh 1352 if a._charges.get('pdbqs', None): 1353 if a.charge in [-0.613, -0.686, -0.444, -0.527]: 1354 self.hasKollman = 1 1355 h._charges['pdbqs'] = kollCh 1356 if a._charges.get('pdbq', None): 1357 if a.charge in [-0.613, -0.686, -0.444, -0.527]: 1358 self.hasKollman = 1 1359 h._charges['pdbq'] = kollCh 1360 if a._charges.get('gasteiger', None): 1361 self.hasgasteiger = 1 1362 h._charges['gasteiger'] = gastCh 1363 h.chargeSet = a.chargeSet
1364 1365
1366 - def HD1(self, res, hasHD1, hasHE2):
1367 newH = AtomSet([]) 1368 badH = AtomSet([]) 1369 if not hasHD1: 1370 a = res.atoms.get(lambda x: x.name=='ND1')[0] 1371 newH.append(self.addNewH(a, 'HD1')) 1372 self.fixCharges(newH[-1], a, .32, .1672) 1373 if hasHE2: 1374 badH.append(res.atoms.get(lambda x: x.name=='HE2')[0]) 1375 return badH, newH
1376 1377
1378 - def HE2(self, res, hasHD1, hasHE2):
1379 newH = AtomSet([]) 1380 badH = AtomSet([]) 1381 if not hasHE2: 1382 a = res.atoms.get(lambda x: x.name=='NE2')[0] 1383 newH.append(self.addNewH(a, 'HE2')) 1384 self.fixCharges(newH[-1], a, .32, .1675) 1385 if hasHD1: 1386 badH.append(res.atoms.get(lambda x: x.name=='HD1')[0]) 1387 return badH, newH
1388 1389
1390 - def HD1HE2(self, res, hasHD1, hasHE2):
1391 newH = AtomSet([]) 1392 badH = AtomSet([]) 1393 if not hasHD1: 1394 a = res.atoms.get(lambda x: x.name=='ND1')[0] 1395 newH.append(self.addNewH(a, 'HD1')) 1396 self.fixCharges(newH[-1], a, .4780, .1671) 1397 if not hasHE2: 1398 a = res.atoms.get(lambda x: x.name=='NE2')[0] 1399 newH.append(self.addNewH(a, 'HE2')) 1400 self.fixCharges(newH[-1], a, .4860, .1675) 1401 return badH, newH
1402 1403
1404 - def addNewH(self, a, name):
1405 hat = self.addh.add_sp2_hydrogen(a, self.SP2_N_H_DIST) 1406 a = hat[0][1] 1407 atom = Atom(name, a.parent, top=a.top) 1408 atom._coords = [ hat[0][0] ] 1409 atom.hetatm = 0 1410 atom.alternate = [] 1411 atom.element = 'H' 1412 atom.number = -1 1413 atom.occupancy = 1.0 1414 atom.radius = 1.2 1415 atom.conformation = 0 1416 atom.temperatureFactor = 0.0 1417 atom.babel_atomic_number = hat[0][2] 1418 atom.babel_type = hat[0][3] 1419 atom.babel_organic = 1 1420 bond = Bond( a, atom ) 1421 for key, value in a.colors.items(): 1422 atom.colors[key] = (1.0, 1.0, 1.0) 1423 atom.opacities[key] = 1.0 1424 #also add whatever kinds of charges a._charges has 1425 chargeKeys = a._charges.keys() 1426 if 'Kollman' in chargeKeys: 1427 self.hasKollman = 1 1428 if 'gasteiger' in chargeKeys: 1429 self.hasgasteiger = 1 1430 return atom
1431 1432 1433
1434 -class AddOXTGUICommand(MVCommand, MVAtomICOM):
1435 """This class provides GUICommand for AddOXT which adds oxygen atom to 1436 terminal carbon atom. 1437 \nPackage : Pmv 1438 \nModule : repairCommands 1439 \nClass : AddOXTGUICommand 1440 \nCommand : add_oxtGC 1441 \nSynopsis:\n 1442 AtomSet([oxt]) <--- add_oxtGC(atoms) 1443 \nRequired Arguments:\n 1444 atoms --- atom(s) 1445 \noxt --- the new oxt atom 1446 """ 1447 1448
1449 - def __init__(self, func=None):
1450 MVCommand.__init__(self, func) 1451 MVAtomICOM.__init__(self) 1452 self.save = None
1453 1454
1455 - def onAddCmdToViewer(self):
1456 if not self.vf.commands.has_key('add_oxt'): 1457 self.vf.loadCommand('repairCommands', 'add_oxt','Pmv', 1458 topCommand=0) 1459 if self.vf.hasGui and not hasattr(self.vf, 'setICOM'): 1460 self.vf.loadCommand('interactiveCommands', 'setICOM', 'Pmv')
1461 1462
1463 - def __call__(self, atoms, **kw):
1464 """AtomSet([oxt]) <--- add_oxtGC(atoms) 1465 \natoms --- atom(s) 1466 \noxt --- the new oxt atom 1467 """ 1468 if type(atoms) is types.StringType: 1469 self.nodeLogString = "'"+atoms+"'" 1470 ats = self.vf.expandNodes(atoms) 1471 if not len(ats): return 'ERROR' 1472 return apply(self.doitWrapper, (ats,), kw)
1473 1474
1475 - def doit(self, ats):
1476 """ats[0] must be a carbon with two bonds, one of which is to an 1477 oxygen 1478 """ 1479 at = ats[0] 1480 if at.element!='C': 1481 t = 'can only add oxt to carbon atom, not ' + at.element 1482 self.warningMsg(t) 1483 return 'ERROR' 1484 elif at.name!='C': 1485 t = 'can only add oxt to C carbon atom, not ' + at.name 1486 self.warningMsg(t) 1487 return 'ERROR' 1488 if len(at.bonds)>=3: 1489 t = 'can only add oxt to carbon atom with two bonds' 1490 self.warningMsg(t) 1491 return 'ERROR' 1492 elif len(at.bonds)==1: 1493 t = 'can only add oxt to carbon atom with two bonds' 1494 self.warningMsg(t) 1495 return 'ERROR' 1496 #must only have two bonds: 1497 hasO = 0 1498 at2 = at.bonds[0].atom1 1499 if at2==at: 1500 at2 = at.bonds[0].atom2 1501 if at2.element=='O': 1502 hasO = 1 1503 else: 1504 at2 = at.bonds[1].atom1 1505 if at2==at: 1506 at2 = at.bonds[1].atom2 1507 if at2.element=='O': 1508 hasO = 1 1509 if not hasO: 1510 t = 'can only add oxt to carbon atom with bond to 1 oxygen' 1511 self.warningMsg(t) 1512 return 'ERROR' 1513 #if you get to this point: add the oxygen 1514 #newOXT is an AtomSet containing the new oxt 1515 newOXT = self.vf.add_oxt(at, topCommand=0) 1516 1517 if self.save: 1518 self.vf.setICOM(self.save) 1519 self.save = None 1520 return newOXT
1521 1522
1523 - def guiCallback(self, event=None):
1524 if not len(self.vf.Mols): 1525 self.warningMsg('no molecules in viewer') 1526 return 1527 self.vf.setICOM(self, topCommand=0)
1528 1529
1530 - def startICOM(self):
1531 self.vf.setIcomLevel( Atom )
1532 1533 1534 1535 AddOXTGUICommandGUI=CommandGUI() 1536 AddOXTGUICommandGUI.addMenuCommand('menuRoot', 'Edit', 1537 'Add OXT', cascadeName='Misc') 1538 1539 1540
1541 -class AddOXT(MVCommand):
1542 """This class uses add_sp2_hydrogen method of the AddHydrogens class from the PyBabel package to compute coordinates of oxygen to be added to carbon atom.The carbon atom is bonded to another oxygen and a CA. If it is bonded to a hydrogen, the hydrogen is removed and replaced by the new OXT atom. 1543 \nPackage : Pmv 1544 \nModule : repairCommands 1545 \nClass : AddOXT 1546 \nCommand : add_oxt 1547 \nSynopsis:\n 1548 oxt<--- add_oxt(catom,**kw) 1549 \nRequired Arguments:\n 1550 catom --- carbon atom to get new oxt oxygen atom. 1551 oxt --- the new oxygen atom 1552 """ 1553
1554 - def onAddCmdToViewer(self):
1555 if not self.vf.commands.has_key('typeAtoms'): 1556 self.vf.loadCommand('editCommands', 'typeAtoms','Pmv', 1557 topCommand=0) 1558 if not self.vf.commands.has_key('typeBonds'): 1559 self.vf.loadCommand('editCommands', 'typeBonds','Pmv', 1560 topCommand=0) 1561 if not self.vf.commands.has_key('deleteAtomSet'): 1562 self.vf.loadCommand('deleteCommands', 'deleteAtomSet','Pmv', 1563 topCommand=0) 1564 #self.addh = AddHydrogens() 1565 from MolKit.oxtBuilder import OxtBuilder 1566 self.oxtBuilder = OxtBuilder()
1567 1568
1569 - def __call__(self, catom, polarOnly=0,method='noBondOrder',renumber=1,**kw):
1570 """oxt<- add_oxt(catom,**kw) 1571 \ncatom --- carbon atom to get new oxt oxygen atom. 1572 \noxt --- the new oxygen atom 1573 """ 1574 return apply(self.doitWrapper,(catom,), kw)
1575 1576
1577 - def doit(self, catom):
1578 """ oxt <- add_oxt(catom)""" 1579 nodes = self.vf.expandNodes(catom) 1580 if len(nodes)==0: return 'ERROR' 1581 1582 catom = nodes[0] 1583 if catom.element!='C': 1584 return 'ERROR' 1585 1586 atom = self.oxtBuilder.add_oxt(catom) 1587 mol = catom.top 1588 1589 # #check whether catom has a hydrogen to delete 1590 # hatoms = catom.parent.atoms.get(lambda x: x.name=='HC') 1591 # if hatoms is not None: 1592 # self.vf.deleteAtomSet(hatoms) 1593 1594 # #have to type atoms before call to add_sp2_hydrogen: 1595 # if not hasattr(catom,'babel_type'): 1596 # msg = 'catom has no babel_type: calling typeAtoms' 1597 # print msg 1598 # #self.warningMsg(msg) 1599 # #typeAtoms does whole molecule 1600 # self.vf.typeAtoms(catom, topCommand=0) 1601 # 1602 # #NB: bond_length 1.28 measured from OXT-C bond in 1crn 1603 # tup1 = self.addh.add_sp2_hydrogen(catom, 1.28) 1604 1605 res = catom.parent 1606 1607 # # find where to insert H atom 1608 # childIndex = res.children.index(catom)+1 1609 # name = 'OXT' 1610 1611 # # create the OXT atom object 1612 # atom = Atom(name, res, top=mol, 1613 # childIndex=childIndex, assignUniqIndex=0) 1614 1615 # # set atoms attributes 1616 # atom._coords = [ tup1[0][0] ] 1617 # if hasattr(catom, 'segID'): atom.segID = catom.segID 1618 # atom.hetatm = 0 1619 # atom.alternate = [] 1620 # atom.element = 'O' 1621 # atom.occupancy = 1.0 1622 # atom.conformation = 0 1623 # atom.temperatureFactor = 0.0 1624 # atom.babel_atomic_number = 8 1625 # atom.babel_type = 'O-' 1626 # atom.babel_organic = 1 1627 1628 # # create the Bond object bonding Hatom to heavyAtom 1629 # bond = Bond( catom, atom, bondOrder=2) 1630 1631 # create the color entries for all geometries 1632 # available for the other oxygen atom attached to 'C' 1633 oatom = res.atoms.get(lambda x: x.name=='O')[0] 1634 if oatom is not None: 1635 for key, value in oatom.colors.items(): 1636 atom.colors[key] = value 1637 #atom.opacities[key] = oatom.opacities[key] 1638 1639 # update the allAtoms set in the molecule 1640 mol.allAtoms = mol.chains.residues.atoms 1641 1642 fst = mol.allAtoms[0].number 1643 mol.allAtoms.number = range(fst, len(mol.allAtoms)+fst) 1644 1645 res.assignUniqIndex() 1646 1647 # update self.vf.Mols.allAtoms 1648 self.vf.allAtoms = self.vf.Mols.allAtoms 1649 1650 #update the display 1651 newOXT = AtomSet([atom]) 1652 event = AddAtomsEvent(objects=newOXT) 1653 self.vf.dispatchEvent(event) 1654 self.vf.GUI.VIEWER.Redraw() 1655 1656 return newOXT
1657 1658 1659
1660 -class ModifyCTerminus(MVCommand):
1661 """This command removes hydrogens from C-atom of internal c-termini residues. 1662 An internal c-terminus occurs when residues are missing from a chain. 1663 \nPackage : Pmv 1664 \nModule : repairCommands 1665 \nClass : ModifyCTerminus 1666 \nCommand : modifyCTerminus 1667 \nSynopsis:\n 1668 None<---modifyCTerminus(resSet,**kw) 1669 \nRequired Arguments:\n 1670 resSet --- residues which are inside a chain and not bonded to a next residue in chain 1671 """ 1672
1673 - def onAddCmdToViewer(self):
1674 if not self.vf.commands.has_key('typeAtoms'): 1675 self.vf.loadCommand('editCommands', 'typeAtoms','Pmv', 1676 topCommand=0) 1677 if not self.vf.commands.has_key('typeBonds'): 1678 self.vf.loadCommand('editCommands', 'typeBonds','Pmv', 1679 topCommand=0) 1680 if not self.vf.commands.has_key('deleteAtomSet'): 1681 self.vf.loadCommand('deleteCommands', 'deleteAtomSet','Pmv', 1682 topCommand=0) 1683 self.addh = AddHydrogens()
1684 1685
1686 - def __call__(self, resSet,**kw):
1687 """None<---modifyCTerminus(resSet,**kw) 1688 \nresSet --- residues which are inside a chain and not bonded to a next residue in chain 1689 """ 1690 return apply(self.doitWrapper,(resSet,), kw)
1691 1692
1693 - def doit(self, resSet):
1694 """ None<---modifyCTerminus(resSet)""" 1695 nodes = self.vf.expandNodes(resSet) 1696 if len(nodes)==0: return 'ERROR' 1697 1698 catoms = resSet.atoms.get(lambda x: x.name=='C') 1699 if not catoms: 1700 msg = resSet.full_name() + ' missing C atoms' 1701 self.warningMsg(msg) 1702 return 'ERROR' 1703 #catom = catoms[0] 1704 #hs = catom.findHydrogens() 1705 hs = catoms.top.uniq().allAtoms.get(lambda x: x.element=='H') 1706 if not hs: 1707 return "ERROR" 1708 #possibly could just look for atoms with name 'HC' 1709 hcs = hs.get(lambda x: x.bonds[0].atom1.name=='C' or \ 1710 x.bonds[0].atom2.name=='C') 1711 if not hcs: 1712 #there is nothing to delete here 1713 return 'ERROR' 1714 self.vf.deleteAtomSet(hcs)
1715 1716 1717
1718 -class ModifyNTerminus(MVCommand):
1719 """This command is used to modify residues which become internal n-termini 1720 because some residues are missing within a chain in a crystal structure. 1721 Hydrogens are added or subtracted from nitrogen atom of the internal 1722 n-terminus so that the natom ends up with one sp2-hydrogen which is what it 1723 would have in an intact chain. 1724 \nPackage : Pmv 1725 \nModule : repairCommands 1726 \nClass : ModifyNTerminus 1727 \nCommand : modifyNTerminus 1728 \nSynopsis:\n 1729 None<--- modifyNTerminus(res,**kw) 1730 \nRequired Arguments:\n 1731 resSet --- set of residues which are inside a chain and not bonded to a previous residue 1732 """ 1733
1734 - def onAddCmdToViewer(self):
1735 if not self.vf.commands.has_key('typeAtoms'): 1736 self.vf.loadCommand('editCommands', 'typeAtoms','Pmv', 1737 topCommand=0) 1738 if not self.vf.commands.has_key('typeBonds'): 1739 self.vf.loadCommand('editCommands', 'typeBonds','Pmv', 1740 topCommand=0) 1741 if not self.vf.commands.has_key('deleteAtomSet'): 1742 self.vf.loadCommand('deleteCommands', 'deleteAtomSet','Pmv', 1743 topCommand=0) 1744 self.addh = AddHydrogens()
1745 1746
1747 - def __call__(self, resSet, renumber=1, **kw):
1748 """None<---modifyNTerminus(res,**kw) 1749 \nresSet --- set of residues which are inside a chain and not bonded to a previous residue 1750 """ 1751 return apply(self.doitWrapper,(resSet, renumber,), kw)
1752 1753
1754 - def doit(self, resSet, renumber):
1755 """ None <--- modifyNTerminus(resSet)""" 1756 resSet = self.vf.expandNodes(resSet) 1757 if len(resSet)==0: return 'ERROR' 1758 1759 resATS = resSet.atoms 1760 #make sure natom has 1 sp2 hydrogen 'HN', only 1761 #if it's already there, return 1762 natoms = resATS.get(lambda x: x.name=='N') 1763 #print 'natoms=', natoms 1764 if not natoms: 1765 msg = resSet.name + ' missing N atom' 1766 self.warningMsg(msg) 1767 return 'ERROR' 1768 self.vf.fixHNames(self.vf.allAtoms) 1769 #remove any residues which already have atom 'HN' 1770 #print 'before subtract resSet.name=', resSet.name 1771 #resSet = resSet - resSet.get(lambda x:'HN' in x.children.name) 1772 #print 'after subtract resSet.name=', resSet.name 1773 1774 mols = resATS.top.uniq() 1775 hs = resATS.get(lambda x: x.element=='H') 1776 if hs is not None: 1777 NHs = hs.get(lambda x:(x.bonds[0].atom1.name=='N' or \ 1778 x.bonds[0].atom2.name=='N') and \ 1779 x.name!='HN') 1780 print 'NHs==None', NHs==None 1781 if NHs: 1782 print 'deleting ', NHs 1783 self.vf.deleteAtomSet(NHs) 1784 1785 for at in resATS: 1786 if not hasattr(at,'babel_type'): 1787 msg = 'atom has no babel_type: calling typeAtoms' 1788 self.warningMsg(msg) 1789 #typeAtoms does whole molecule 1790 self.vf.typeAtoms(at, topCommand=0) 1791 break 1792 resBONDS = resATS.bonds[0] 1793 untypedBonds = filter(lambda x:x.bondOrder==None, resBONDS) 1794 #don't do this if it is not necessary 1795 if len(untypedBonds): 1796 for m in mols: 1797 self.vf.typeBonds(m, withRings=0, topCommand=0) 1798 1799 natoms.babel_type = 'Npl' 1800 for n in natoms: 1801 print 'processing n=', n.full_name() 1802 if n.parent.type!='PRO': 1803 hat = self.addh.add_vinyl_hydrogens(n, 1.02) 1804 else: 1805 continue 1806 #this adds a bogus hydrogen along what would be the N_C bond 1807 #hat = self.addh.add_sp2_hydrogen(n, 1.02) 1808 #always just add one hydrogen 1809 h = hat[0] 1810 #for h in hat: 1811 childIndex = n.parent.children.index(n) + 1 1812 name = 'HN' 1813 # create the HN atom object 1814 atom = Atom(name, n.parent, top=n.top, 1815 childIndex=childIndex, assignUniqIndex=0) 1816 atom._coords = [ h[0] ] 1817 1818 if hasattr(n, 'segID'): 1819 atom.segID = n.segID 1820 atom.hetatm = 0 1821 atom.alternate = [] 1822 atom.element = 'H' 1823 atom.occupancy = 1.0 1824 atom.conformation = 0 1825 atom.temperatureFactor = 0.0 1826 atom.babel_atomic_number = 1 1827 atom.babel_type = 'H' 1828 atom.babel_organic = 1 1829 1830 # create the Bond object bonding Hatom to heavyAtom 1831 bond = Bond( n, atom, bondOrder=1) 1832 1833 # create the color entries for all geoemtries 1834 # available for the heavyAtom 1835 for key, value in n.colors.items(): 1836 atom.colors[key]=(0.0, 1.0, 1.0) 1837 atom.opacities[key]=1.0 1838 if hasattr(n, 'chargeSet') and n.chargeSet=='Kollman': 1839 #FIX THIS 1840 atom._charges['Kollman'] = n.charge/2.0 1841 atom.chargeSet = 'Kollman' 1842 1843 # update the allAtoms set in the molecules 1844 for mol in mols: 1845 mol.allAtoms = mol.<