Package Chem :: Module DSViewer
[hide private]
[frames] | no frames]

Source Code for Module Chem.DSViewer

  1  # $Id: DSViewer.py 746 2008-07-07 13:21:24Z glandrum $ 
  2  # 
  3  # Copyright (C) 2005-2006 Rational Discovery LLC 
  4  # 
  5  #   @@ All Rights Reserved  @@ 
  6  # 
  7  """ uses DSViewer to interact with molecules 
  8   
  9  """ 
 10  import Chem 
 11  from win32com.client import Dispatch 
 12  import tempfile,os 
 13   
 14  _nextDisplayId=1 
15 -class Displayable(object):
16 - def __init__(self,doc,id=-1):
17 global _nextDisplayId 18 if id<0: 19 id = _nextDisplayId 20 _nextDisplayId += 1 21 22 self.doc = doc 23 self.id = id 24 self.visible=True 25 self.children = []
26
27 - def Select(self,atoms=[],state=True,recurse=False):
28 if state: 29 selText = 'true' 30 else: 31 selText = 'false' 32 if not atoms or atoms=='*': 33 atomStr = '; atom "*"' 34 else: 35 # DSViewer has atom ids from 1, we do it from 0: 36 atoms = ['id=%d'%(x) for x in atoms] 37 atomStr = '; atom %s'%','.join(atoms) 38 39 cmd = 'SetProperty object RD_Visual=%d %s: select=%s'%(self.id,atomStr, 40 selText) 41 r = int(str(self.doc.DoCommand(cmd))) 42 if not r and not atoms: 43 # this handles an annoying case where if you try to select 44 # a molecule by ID in DSViewer, you get nothing selected: 45 atomStr='' 46 cmd = 'SetProperty object RD_Visual=%d %s: select=%s'%(self.id,atomStr, 47 selText) 48 r = int(str(self.doc.DoCommand(cmd))) 49 #print 'sel cmd:',cmd 50 #print 'result:', r 51 52 # stupid DSViewer will select the bonds between pairs of highlighted atoms, 53 # stop that nonsense right now: 54 if r: 55 cmd = 'SetProperty object RD_Visual=%d; bond index="*": select=off'%(self.id) 56 self.doc.DoCommand(cmd) 57 58 if recurse: 59 for child in self.children: 60 child.Select(atoms=atoms,state=state,recurse=True) 61 return r
62
63 - def Hide(self,recurse=True):
64 self.Select(state=True,recurse=True) 65 self.doc.DoCommand('hide') 66 self.Select(state=False,recurse=True)
67 - def Show(self,recurse=True):
68 self.Select(state=True,recurse=True) 69 self.doc.DoCommand('Show') 70 self.Select(state=False,recurse=True)
71
72 - def ShowOnly(self,recurse=True):
73 self.doc.DoCommand('HideAll') 74 self.Select(state=True,recurse=True) 75 self.doc.DoCommand('Show') 76 self.Select(state=False,recurse=True)
77
78 - def __del__(self):
79 self.doc.DoCommand('UnselectAll') 80 count=self.Select(state=True,recurse=True) 81 if count: 82 self.doc.DoCommand('Delete')
83
84 -class MolViewer(object):
85 - def __init__(self,force=0,title='Untitled',**kwargs):
86 self.app = Dispatch('WebLabViewerPro.Application') 87 self.app.Visible=1 88 if force or self.app.ActiveDocument is None: 89 self.doc = self.app.New(title) 90 else: 91 self.doc = self.app.ActiveDocument 92 93 self.displayables={}
94
95 - def DeleteAll(self):
96 self.doc.DoCommand('SelectAll') 97 self.doc.DoCommand('Delete') 98 self.displayables = {}
99
100 - def DeleteAllExcept(self,excludes):
101 excludes = [x.lower() for x in excludes] 102 allNames = self.displayables.keys() 103 for nm in allNames: 104 if nm not in excludes: 105 del self.displayables[nm]
106 107 108
109 - def ShowMol(self,mol,name='molecule',showOnly=True,highlightFeatures=[], 110 molB="",confId=-1,zoom=True):
111 if showOnly: 112 self.DeleteAll() 113 obj = None 114 else: 115 obj = self.displayables.get(name.lower(),None) 116 #if obj: 117 # obj.Select(state=True) 118 # self.doc.DoCommand('Delete') 119 # obj.Select(state=False) 120 121 if not molB: 122 molB = Chem.MolToMolBlock(mol,confId=confId) 123 124 tmp = name + "\n" + molB[molB.index('\n')+1:] 125 molB = tmp 126 127 if not obj: 128 obj = Displayable(self.doc) 129 if not hasattr(obj,'_molBlock') or obj._molBlock != molB: 130 obj._molBlock = molB 131 fN = tempfile.mktemp('.mol') 132 open(fN,'w+').write(molB) 133 self.doc.DoCommand('PasteFrom %s'%fN) 134 self.doc.DoCommand('SetProperty molecule id=0 : RD_Visual=%d'%(obj.id)) 135 self.doc.DoCommand('SetProperty molecule id=0 : id=%d'%(obj.id)) 136 self.doc.DoCommand('SetProperty molecule id=0 : select=off') 137 os.unlink(fN) 138 else: 139 obj.Select(state=True) 140 self.doc.DoCommand('Show') 141 142 self.displayables[name.lower()] = obj 143 144 if zoom: 145 self.doc.DoCommand('Center') 146 self.doc.DoCommand('FitView') 147 148 return
149
150 - def LoadFile(self,filename,name,showOnly=False):
151 if showOnly: 152 self.DeleteAll() 153 self.doc.DoCommand('PasteFrom %s'%filename) 154 obj = Displayable(self.doc) 155 self.doc.DoCommand('SetProperty molecule id=0 : id=%d'%(obj.id)) 156 self.doc.DoCommand('SetProperty molecule id=0 : select=off') 157 count = self.doc.DoCommand('SetProperty AminoAcidChain id=0 : RD_Visual=%d'%(obj.id)) 158 if not count or int(count)<=0: 159 count = self.doc.DoCommand('SetProperty molecule id=0 : RD_Visual=%d'%(obj.id)) 160 self.displayables[name.lower()] = obj 161 return obj
162 163
164 - def GetSelectedAtoms(self,whichSelection=''):
165 #print 'WHICH',repr(whichSelection),self.displayables.has_key(whichSelection.lower()) 166 if not whichSelection: 167 d = str(self.doc.DoCommand('GetPropertyValue atom select=true: id=?')) 168 d2 = str(self.doc.DoCommand('GetPropertyValue atom select=true: molecule=?')) 169 if d2: 170 molIds = [] 171 tmpD = {} 172 for id in d2.split(','): 173 id = int(id.split('/')[1])+1 174 if tmpD.has_key(id): 175 molIds.append(tmpD[id]) 176 else: 177 for k,v in self.displayables.iteritems(): 178 if id==v.id: 179 tmpD[id] = k 180 molIds.append(k) 181 else: 182 molIds = ['']*(d.count(',')+1) 183 elif self.displayables.has_key(whichSelection.lower()): 184 whichSelection = whichSelection.lower() 185 whichSelection = self.displayables[whichSelection].id 186 d = str(self.doc.DoCommand('GetPropertyValue molecule RD_Visual=%d; atom select=true: id=?'%whichSelection)) 187 molIds = [whichSelection]*(d.count(',')+1) 188 else: 189 d = None 190 molIds = None 191 192 if d: 193 splitD = d.split(',') 194 #print 'splitD:',splitD 195 #print 'molIds:',molIds 196 try: 197 res = [] 198 for i in range(len(splitD)): 199 # DSViewer has atom ids from 1, we do it from 0: 200 idx = int(splitD[i]) 201 res.append((molIds[i],idx)) 202 except: 203 import traceback 204 traceback.print_exc() 205 res = [] 206 else: 207 res = [] 208 return res
209
210 - def HighlightAtoms(self,indices,where,extraHighlight=False):
211 self.doc.DoCommand('UnSelectAll') 212 self.SelectAtoms(where,indices)
213 - def SelectAtoms(self,itemId,atomIndices,selName='selection'):
214 self.doc.DoCommand('UnSelectAll') 215 self.doc.DoCommand('SetProperty atom id="*": select=off') 216 o = self.displayables.get(itemId.lower(),None) 217 #print 'O:',itemId,atomIndices 218 if o: 219 o.Select(atoms=atomIndices)
220
221 - def SetDisplayUpdate(self,val):
222 if not val: 223 self.doc.DoCommand('UpdateView off') 224 else: 225 self.doc.DoCommand('UpdateView on')
226
227 - def GetAtomCoords(self,sels):
228 res = {} 229 for label,idx in sels: 230 whichSelection = label.lower() 231 whichSelection = self.displayables[label].id 232 # DSViewer has atom ids from 1, we do it from 0: 233 idx += 1 234 cmd = 'GetPropertyValue molecule RD_Visual=%d; atom id=%d: xyz=?'%(whichSelection,idx) 235 coords = self.doc.DoCommand(cmd) 236 coords = [float(x) for x in coords.split(' ')] 237 res[(label,idx)] = coords 238 #print 'grab:',label,idx,coords 239 return res
240
241 - def AddPharmacophore(self,locs,colors,label,sphereRad=0.5):
242 label=label.lower() 243 self.SetDisplayUpdate(False) 244 parent = Displayable(self.doc) 245 for i,loc in enumerate(locs): 246 color = colors[i] 247 color = ' '.join([str(int(255*x)) for x in color]) 248 obj = Displayable(self.doc) 249 nm = 'sphere-%d'%obj.id 250 self.doc.DoCommand('Sphere %s'%nm) 251 self.doc.DoCommand('SetProperty Object name=%s : xyz=%f %f %f'%(nm,loc[0],loc[1],loc[2])) 252 self.doc.DoCommand('SetProperty Object name=%s : radius=%f'%(nm,sphereRad)) 253 self.doc.DoCommand('SetProperty Object name=%s : color=%s'%(nm,color)) 254 self.doc.DoCommand('SetProperty Object name=%s : RD_Visual=%d'%(nm,parent.id)) 255 self.doc.DoCommand('SetProperty Object name=%s : id=%d'%(nm,parent.id)) 256 #parent.children.append(obj) 257 self.displayables[label] = parent 258 self.SetDisplayUpdate(True)
259 260
261 - def SetDisplayStyle(self,obj,style=''):
262 self.doc.DoCommand('UnSelectAll') 263 obj = obj.lower() 264 o = self.displayables.get(obj,None) 265 if o: 266 o.Select(state=True) 267 if style=='sticks': 268 self.doc.DoCommand('DisplayStyle Atom Stick') 269 elif style=='lines': 270 self.doc.DoCommand('DisplayStyle Atom Line') 271 elif style=='': 272 self.doc.DoCommand('DisplayStyle Atom Off') 273 o.Select(state=False)
274 275
276 - def HideAll(self):
277 self.doc.DoCommand('HideAll')
278 - def HideObject(self,objName):
279 self.doc.DoCommand('UnSelectAll') 280 objName = objName.lower() 281 o = self.displayables.get(objName,None) 282 if o: 283 o.Hide()
284
285 - def DisplayObject(self,objName):
286 self.doc.DoCommand('UnSelectAll') 287 objName = objName.lower() 288 o = self.displayables.get(objName,None) 289 if o: 290 o.Show()
291
292 - def Zoom(self,objName):
293 self.doc.DoCommand('UnSelectAll') 294 objName = objName.lower() 295 o = self.displayables.get(objName,None) 296 if o: 297 r = o.Select(state=True) 298 self.doc.DoCommand('Center') 299 self.doc.DoCommand('FitView') 300 o.Select(state=False)
301
302 - def SelectProteinNeighborhood(self,aroundObj,inObj,distance=5.0, 303 name='neighborhood',showSurface=False):
304 305 """ FIX: the surface display stuff here is all screwed up due to 306 differences between the way PyMol and DSViewer handle surfaces. 307 In PyMol they are essentially a display mode for the protein, so 308 they don't need to be managed separately. 309 In DSViewer, on the other hand, the surface is attached to the 310 protein, but it needs to be hidden or shown on its own. I haven't 311 figured out how to do that yet. 312 """ 313 self.doc.DoCommand('UnSelectAll') 314 o = self.displayables.get(aroundObj.lower(),None) 315 p = self.displayables.get(inObj.lower(),None) 316 if o and p: 317 self.SetDisplayUpdate(False) 318 p.Show() 319 self.doc.DoCommand('UnSelectAll') 320 tmp = self.doc.DoCommand('SetProperty object RD_Visual=%d;object id="*":select=on'%o.id) 321 tmp = self.doc.DoCommand('SelectByRadius inside %f atom'%distance) 322 # that selects all atoms in the radius, now we need to make sure 323 # only atoms in _inObj_ are selected: 324 for obj in self.displayables.values(): 325 if obj.id != p.id: 326 self.doc.DoCommand('SetProperty object RD_Visual=%d;object id="*":select=off'%obj.id) 327 328 # ---- 329 # now get all the residue names for the selected atoms: 330 rs = self.doc.DoCommand('GetPropertyValue atom select=true: parent=?') 331 if rs: 332 rs = rs.split(',') 333 residues = {} 334 for r in rs: 335 residues[r] = 1 336 337 # and select each atom in those residues: 338 parents=','.join(['parent="%s"'%x for x in residues.keys()]) 339 cmd = 'SetProperty atom %s: select=on'%parents 340 tmp=self.doc.DoCommand(cmd) 341 if showSurface: 342 # create the surface: 343 self.doc.DoCommand('Surface') 344 obj = Displayable(self.doc) 345 self.displayables[name]=obj 346 self.doc.DoCommand('SetProperty surface id="*":RD_Visual=%d'%obj.id) 347 348 self.doc.DoCommand('UnSelectAll') 349 350 351 self.SetDisplayUpdate(True)
352
353 - def Redraw(self):
354 self.SetDisplayUpdate(True)
355 356 357 358 if __name__=='__main__': 359 import Chem 360 from Chem import rdDistGeom, rdForceFieldHelpers 361 362 m = Chem.MolFromSmiles('c1cccc2c1cccc2') 363 rdDistGeom.EmbedMolecule(m) 364 rdForceFieldHelpers.UFFOptimizeMolecule(m) 365 366 s = MolViewer() 367 s.ShowMol(m) 368