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

Source Code for Module rdkit.Chem.DSViewer

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