Package cinfony :: Module silverwebel
[frames] | no frames]

Source Code for Module cinfony.silverwebel

  1  ## Copyright (c) 2009-2011, Noel O'Boyle 
  2  ## All rights reserved. 
  3  ## 
  4  ##  This file is part of Cinfony. 
  5  ##  The contents are covered by the terms of the BSD license 
  6  ##  which is included in the file LICENSE_BSD.txt. 
  7   
  8  """ 
  9  silverwebel - A Cinfony module for Silverlight that runs on web services 
 10   
 11  Global variables: 
 12    informats - a dictionary of supported input formats 
 13    outformats - a dictionary of supported output formats 
 14    fps - a list of supported fingerprint types 
 15  """ 
 16   
 17  import re 
 18  from time import sleep 
 19   
 20  # .NET classes 
 21  from System.Net import WebClient 
 22  from System import Uri, UriKind 
 23  _webclient = WebClient() 
 24   
 25  tk = None 
 26   
 27  informats = {"smi":"SMILES", "inchikey":"InChIKey", "inchi":"InChI", 
 28               "name":"Common name"} 
 29  """A dictionary of supported input formats""" 
 30  outformats = {"smi":"SMILES", "cdxml":"ChemDraw XML", "inchi":"InChI", 
 31                "sdf":"Symyx SDF", "names":"Common names", "inchikey":"InChIKey", 
 32                "alc":"Alchemy", "cerius":"MSI Cerius II", "charmm":"CHARMM", 
 33                "cif":"Crystallographic Information File", 
 34                "cml":"Chemical Markup Language", "ctx":"Gasteiger Clear Text", 
 35                "gjf":"Gaussian job file", "gromacs":"GROMACS", 
 36                "hyperchem":"HyperChem", "jme":"Java Molecule Editor", 
 37                "maestro":"Schrodinger MacroModel", 
 38                "mol":"Symyx mol", "mol2":"Tripos Sybyl MOL2", 
 39                "mrv":"ChemAxon MRV", "pdb":"Protein Data Bank", 
 40                "sdf3000":"Symyx SDF3000", "sln":"Sybl line notation", 
 41                "xyz":"XYZ", "iupac":"IUPAC name"} 
 42  """A dictionary of supported output formats""" 
 43   
 44  fps = ["std", "maccs", "estate"] 
 45  """A list of supported fingerprint types""" 
46 47 # The following function is taken from urllib.py in the IronPython dist 48 -def _quo(text, safe="/"):
49 always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' 50 'abcdefghijklmnopqrstuvwxyz' 51 '0123456789' '_.-') 52 _safemaps = {} 53 cachekey = (safe, always_safe) 54 try: 55 safe_map = _safemaps[cachekey] 56 except KeyError: 57 safe += always_safe 58 safe_map = {} 59 for i in range(256): 60 c = chr(i) 61 safe_map[c] = (c in safe) and c or ('%%%02X' % i) 62 _safemaps[cachekey] = safe_map 63 res = map(safe_map.__getitem__, text) 64 return ''.join(res)
65
66 -def _makeserver(serverurl):
67 """Curry the name of the server""" 68 def server(*urlcomponents): 69 url = "/%s/" % serverurl + "/".join(urlcomponents) 70 result = [False, None, None] 71 def callback(s, e): 72 result[0] = True 73 result[1] = e.Error 74 if not result[1]: 75 result[2] = e.Result
76 webclient = WebClient() 77 webclient.DownloadStringCompleted += callback 78 webclient.DownloadStringAsync(Uri(url, UriKind.Relative)) 79 while not result[0]: 80 sleep(0.5) 81 if result[1]: 82 raise IOError, "Problem accessing web server\n%s" % result[1] 83 return result[2] 84 return server 85 86 rajweb = _makeserver("rajweb") 87 nci = _makeserver("nci") 88 89 _descs = None # Cache the list of descriptors
90 -def getdescs():
91 """Return a list of supported descriptor types""" 92 global _descs 93 if not _descs: 94 response = rajweb("descriptors").rstrip() 95 _descs = [x.split(".")[-1] for x in response.split("\n")] 96 return _descs
97
98 -def readstring(format, string):
99 """Read in a molecule from a string. 100 101 Required parameters: 102 format - see the informats variable for a list of available 103 input formats 104 string 105 106 Note: For InChIKeys a list of molecules is returned. 107 108 Example: 109 >>> input = "C1=CC=CS1" 110 >>> mymol = readstring("smi", input) 111 """ 112 format = format.lower() 113 if not format in informats: 114 raise ValueError("%s is not a recognised Webel format" % format) 115 116 if format != "smi": 117 smiles = nci(_quo(string), "smiles").rstrip() 118 else: 119 smiles = string 120 if format == "inchikey": 121 return [Molecule(smile) for smile in smiles.split("\n")] 122 else: 123 mol = Molecule(smiles) 124 if format == "name": 125 mol.title = string 126 return mol
127
128 -class Outputfile(object):
129 """Represent a file to which *output* is to be sent. 130 131 Although it's possible to write a single molecule to a file by 132 calling the write() method of a molecule, if multiple molecules 133 are to be written to the same file you should use the Outputfile 134 class. 135 136 Required parameters: 137 format - see the outformats variable for a list of available 138 output formats 139 filename 140 141 Optional parameters: 142 overwrite -- if the output file already exists, should it 143 be overwritten? (default is False) 144 145 Methods: 146 write(molecule) 147 close() 148 """
149 - def __init__(self, format, filename, overwrite=False):
150 self.format = format.lower() 151 self.filename = filename 152 if not overwrite and os.path.isfile(self.filename): 153 raise IOError("%s already exists. Use 'overwrite=True' to overwrite it." % self.filename) 154 if not format in outformats: 155 raise ValueError("%s is not a recognised Webel format" % format) 156 self.file = open(filename, "w")
157
158 - def write(self, molecule):
159 """Write a molecule to the output file. 160 161 Required parameters: 162 molecule 163 """ 164 if self.file.closed: 165 raise IOError("Outputfile instance is closed.") 166 output = molecule.write(self.format) 167 print >> self.file, output
168
169 - def close(self):
170 """Close the Outputfile to further writing.""" 171 self.file.close()
172
173 -class Molecule(object):
174 """Represent a Webel Molecule. 175 176 Required parameter: 177 smiles -- a SMILES string or any type of cinfony Molecule 178 179 Attributes: 180 formula, molwt, title 181 182 Methods: 183 calcfp(), calcdesc(), draw(), write() 184 185 The underlying SMILES string can be accessed using the attribute: 186 smiles 187 """ 188 _cinfony = True 189
190 - def __init__(self, smiles):
191 192 if hasattr(smiles, "_cinfony"): 193 a, b = smiles._exchange 194 if a == 0: 195 smiles = b 196 else: 197 # Must convert to SMILES 198 smiles = smiles.write("smi").split()[0] 199 200 self.smiles = smiles 201 self.title = ""
202 203 @property
204 - def formula(self): return rajweb("mf", _quo(self.smiles))
205 @property
206 - def molwt(self): return float(rajweb("mw", _quo(self.smiles)))
207 @property
208 - def _exchange(self):
209 return (0, self.smiles)
210
211 - def calcdesc(self, descnames=[]):
212 """Calculate descriptor values. 213 214 Optional parameter: 215 descnames -- a list of names of descriptors 216 217 If descnames is not specified, all available descriptors are 218 calculated. See the descs variable for a list of available 219 descriptors. 220 """ 221 if not descnames: 222 descnames = getdescs() 223 else: 224 for descname in descnames: 225 if descname not in getdescs(): 226 raise ValueError("%s is not a recognised Webel descriptor type" % descname) 227 ans = {} 228 p = re.compile("""Descriptor parent="(\w*)" name="([\w\-\+\d]*)" value="([\d\.]*)""") 229 for descname in descnames: 230 longname = "org.openscience.cdk.qsar.descriptors.molecular." + descname 231 response = rajweb("descriptor", longname, _quo(self.smiles)) 232 for match in p.findall(response): 233 if match[2]: 234 ans["%s_%s" % (match[0], match[1])] = float(match[2]) 235 return ans
236
237 - def calcfp(self, fptype="std"):
238 """Calculate a molecular fingerprint. 239 240 Optional parameters: 241 fptype -- the fingerprint type (default is "std"). See the 242 fps variable for a list of of available fingerprint 243 types. 244 """ 245 fptype = fptype.lower() 246 if fptype not in fps: 247 raise ValueError("%s is not a recognised Webel Fingerprint type" % fptype) 248 fp = rajweb("fingerprint/%s/%s" % (fptype, _quo(self.smiles))).rstrip() 249 return Fingerprint(fp)
250
251 - def write(self, format="smi", filename=None, overwrite=False):
252 """Write the molecule to a file or return a string. 253 254 Optional parameters: 255 format -- see the informats variable for a list of available 256 output formats (default is "smi") 257 filename -- default is None 258 overwite -- if the output file already exists, should it 259 be overwritten? (default is False) 260 261 If a filename is specified, the result is written to a file. 262 Otherwise, a string is returned containing the result. 263 264 To write multiple molecules to the same file you should use 265 the Outputfile class. 266 """ 267 format = format.lower() 268 if not format in outformats: 269 raise ValueError("%s is not a recognised Webel format" % format) 270 if format == "smi": 271 output = self.smiles 272 elif format == "names": 273 try: 274 output = nci(_quo(self.smiles), "%s" % format).rstrip().split("\n") 275 except urllib2.URLError, e: 276 if e.code == 404: 277 output = [] 278 elif format in ['inchi', 'inchikey']: 279 format = "std" + format 280 output = nci(_quo(self.smiles), "%s" % format).rstrip() 281 elif format == 'iupac': 282 format = format + "_name" 283 try: 284 output = nci(_quo(self.smiles), "%s" % format).rstrip() 285 except urllib2.URLError, e: 286 if e.code == 404: 287 output = "" 288 else: 289 output = nci(_quo(self.smiles), "file?format=%s" % format).rstrip() 290 291 if filename: 292 if not overwrite and os.path.isfile(filename): 293 raise IOError("%s already exists. Use 'overwrite=True' to overwrite it." % filename) 294 outputfile = open(filename, "w") 295 print >> outputfile, output 296 outputfile.close() 297 else: 298 return output
299
300 - def __str__(self):
301 return self.write()
302
303 - def draw(self):
304 """Create a 2D depiction of the molecule.""" 305 global showimage 306 url = "http://cactus.nci.nih.gov/chemical/structure/%s/image" % _quo(self.smiles) 307 showimage(url)
308
309 -class Fingerprint(object):
310 """A Molecular Fingerprint. 311 312 Required parameters: 313 fingerprint -- a string of 0's and 1's representing a binary fingerprint 314 315 Attributes: 316 fp -- the underlying fingerprint object 317 bits -- a list of bits set in the Fingerprint 318 319 Methods: 320 The "|" operator can be used to calculate the Tanimoto coeff. For example, 321 given two Fingerprints 'a', and 'b', the Tanimoto coefficient is given by: 322 tanimoto = a | b 323 """
324 - def __init__(self, fingerprint):
325 self.fp = fingerprint
326 - def __or__(self, other):
327 mybits = set(self.bits) 328 otherbits = set(other.bits) 329 return len(mybits&otherbits) / float(len(mybits|otherbits))
330 @property
331 - def bits(self):
332 return [i for i,x in enumerate(self.fp) if x=="1"]
333 - def __str__(self):
334 return self.fp
335
336 -class Smarts(object):
337 """A Smarts Pattern Matcher 338 339 Required parameters: 340 smartspattern 341 342 Methods: 343 match(molecule) 344 345 Example: 346 >>> mol = readstring("smi","CCN(CC)CC") # triethylamine 347 >>> smarts = Smarts("[#6][#6]") # Matches an ethyl group 348 >>> smarts.match(mol) 349 True 350 """
351 - def __init__(self, smartspattern):
352 """Initialise with a SMARTS pattern.""" 353 self.pat = smartspattern
354 - def match(self, molecule):
355 """Does a SMARTS pattern match a particular molecule? 356 357 Required parameters: 358 molecule 359 """ 360 resp = rajweb("substruct", _quo(molecule.smiles), _quo(self.pat)).rstrip() 361 return resp == "true"
362 363 if __name__=="__main__": #pragma: no cover 364 import doctest 365 doctest.run_docstring_examples(rajweb, globals()) 366