Source code for pubchem

from __future__ import print_function
"""Queries the PubChem database using a compound name (i.e. 1,3,5-hexatriene)
   to obtain a molecule string that can be passed to Molecule. ::

      results = getPubChemObj("1,3,5-hexatriene")

      Results is an array of results from PubChem matches to your query.
        for entry in results:
           entry["CID"]         => PubChem compound identifer
           entry["IUPAC"]       => IUPAC name for the resulting compound
           entry["PubChemObj"]  => instance of PubChemObj for this compound

           entry["PubChemObj"].getMoleculeString()   => returns a string compatible
                                                        with PSI4's Molecule creation

"""
try:
    # Python 2 syntax
    from urllib2 import urlopen
    from urllib2 import quote
    from urllib2 import URLError
except ImportError:
    # Python 3 syntax
    from urllib.request import urlopen
    from urllib.parse import quote
    from urllib.error import URLError
import re
import sys


[docs]class PubChemObj(object): def __init__(self, cid, mf, iupac): self.url = 'http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi' self.cid = cid self.mf = mf self.iupac = iupac self.natom = 0 self.dataSDF = '' def __str__(self): return "%17d %s\n" % (self.cid, self.iupac)
[docs] def getSDF(self): """Function to return the SDF (structure-data file) of the PubChem object.""" if (len(self.dataSDF) == 0): # When completed uncomment the following: url = self.url + '?cid=' + quote(str(self.cid)) + '&disopt=3DDisplaySDF' try: location = urlopen(url) except URLError as e: msg = "\tPubchemError\n%s\n\treceived when trying to open\n\t%s\n" % (str(e), url) msg += "\tCheck your internet connection, and the above URL, and try again.\n" raise Exception(msg) print("\tRetrieved entry for chemical ID %d\n" % self.cid) self.dataSDF = location.read().decode(sys.getdefaultencoding()) #f = open("TEST", "w") #f.write(self.dataSDF) return self.dataSDF
[docs] def name(self): """Function to return the IUPAC name of the PubChem object.""" return self.iupac
[docs] def getCartesian(self): """Function to return a string of the atom symbol and XYZ coordinates of the PubChem object. """ try: sdfText = self.getSDF() except Exception as e: raise e # Find # NA NB CONSTANT # 14 13 0 0 0 0 0 0 0999 V2000 m = re.search(r'^\s*(\d+)\s+(?:\d+\s+){8}V2000$', sdfText, re.MULTILINE) self.natom = 0 if (m): self.natom = int(m.group(1)) if (self.natom == 0): raise Exception("PubchemError\n Cannot find the number of atoms. 3D data doesn't appear\n" + "to be available for %s.\n" % self.iupac) lines = re.split('\n', sdfText) # 3.7320 -0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 NUMBER = "((?:[-+]?\\d*\\.\\d+(?:[DdEe][-+]?\\d+)?)|(?:[-+]?\\d+\\.\\d*(?:[DdEe][-+]?\\d+)?))" atom_re = re.compile(r'^\s*' + NUMBER + r'\s+' + NUMBER + r'\s+' + NUMBER + r'\s*(\w+)(?:\s+\d+){12}') molecule_string = "PubchemInput\n" atom_count = 0 for line in lines: if (not line or line.isspace()): continue atom_match = atom_re.match(line) if atom_match: x = float(atom_match.group(1)) y = float(atom_match.group(2)) z = float(atom_match.group(3)) sym = atom_match.group(4) atom_count = atom_count + 1 molecule_string += "%s %10.6f %10.6f %10.6f\n" % (sym, x, y, z) if (atom_count == self.natom): break return molecule_string
[docs] def getXYZFile(self): """Function to obtain preferentially a molecule string through getCartesian() or a query string otherwise. """ try: temp = self.getCartesian() except Exception as e: raise molstr = "%d\n%s\n%s" % (self.natom, self.iupac, temp) return molstr
[docs] def getMoleculeString(self): """Function to obtain a molecule string through getCartesian() or fail. """ try: return self.getCartesian() except Exception as e: return e.message
[docs]def getPubChemResults(name): """Function to query the PubChem database for molecules matching the input string. Builds a PubChem object if found. """ url = 'http://www.ncbi.nlm.nih.gov/sites/entrez?db=pccompound&term=%s&format=text' % quote(name) print("\tSearching PubChem database for %s" % (name)) try: loc = urlopen(url) except URLError as e: msg = "\tPubchemError\n%s\n\treceived when trying to open\n\t%s\n" % (str(e), url) msg += "\tCheck your internet connection, and the above URL, and try again.\n" raise Exception(msg) data = loc.read() ans = [] l = data.find(b"<pre>") l = data.find(b"\n", l) i = 1 while(True): l = data.find(str("%d. " % i).encode(sys.getdefaultencoding()), l) if l == -1: break tag = b"MF: " l = data.find(tag, l) + len(tag) mf = data[l:data.find(b'\n', l)].decode(sys.getdefaultencoding()) tag = b"IUPAC name: " l = data.find(tag, l) + len(tag) iupac = data[l:data.find(b'\n', l)].decode(sys.getdefaultencoding()) tag = b"CID:" l = data.find(tag, l) + len(tag) #if l == 4: # break cid = int(data[l:data.find(b"\n", l)]) l = data.find(b'\t', l) + 1 pubobj = PubChemObj(cid, mf, iupac) ans.append(pubobj) i += 1 print("\tFound %d results" % (len(ans))) return ans
if __name__ == "__main__": try: obj = getPubChemResults("1-methoxy-4-[(E)-prop-1-enyl]benzene") #obj = getPubChemResults("sodium benzenesulfonate") except Exception as e: print(e.message) for r in obj: print(r) print(r.getMoleculeString())