def get_smiles_similarity_indigo(smiles1,
                                 smiles2,
                                 fp_type="sub",
                                 metric="tanimoto"):
    """
    Calculates the structural similarity between the SMILES of two compounds by means of the Indigo package.
    fp_type: sim | sub
      - "sim" = similarity fingerprints: shorter
      - "sub" = substructure fingerprints: more descriptive
    metric: tanimoto | tversky
    """
    import indigo as indigo

    if len(smiles1) == 0 or len(smiles2) == 0:
        return None
    ind = indigo.Indigo()

    # Sometimes the SMILES are not correct, and they fail when loading. This is why I have introduced this exception
    #try:
    m = ind.loadMolecule(smiles1)
    m2 = ind.loadMolecule(smiles2)
    #except indigo.IndigoException:
    #    return None
    m.aromatize()
    fp = m.fingerprint(fp_type)
    m2.aromatize()  # Aromatize molecules in case they are not in aromatic form
    fp2 = m2.fingerprint(
        fp_type)  # Calculate similarity between "similarity" fingerprints
    d = ind.similarity(fp, fp2, metric)
    return d
示例#2
0
def amend_smiles(smi,ioks):
    """ in case Indigo cannot parse a SMILES, amend this by
    calling
    """
    obj = indigo.Indigo()
    # some failure is due to stereo chem, now remove it
    if not ioks.parse_status:
        _pat = re.compile("\@")
        smi = re.sub("", s1)
        iok = T
        try:
            _m = obj.loadMolecule(smi)
        except:
            print(' ** reload mol failed after removing stereochemistry')
            iok = F
        ioks.parse_status = iok
    else:
        # failure largely due to aromization problem
        m = obj.loadMolecule(smi)
        _bom = get_bo_matrix(m)

    #_m.unfolderHydrogens()
    na = _m.countAtoms()
    _bom = get_bo_matrix(_m)
    chgs = np.array([_m.getAtom(i).charge() for i in range(na)],np.int)
    zs = np.array([m.getAtom(i).atomicNumber() for i in range(na)],np.int)

    tvsi = []
    nrmax = 0
    nbmax = 0
    iok, bom = cf.update_bom(nrmax,nbmax,zs,tvsi,_bom,F)

    blk = (zs,chgs,bom,coords)
    rawm = rawmol_indigo(blk)
    return rawm.m
示例#3
0
def get_mcs_indices_indigo(m_sdf, t_sdf, timeout=None, exact=False):
    import indigo
    indigo = indigo.Indigo()

    m_mol = indigo.loadMolecule(m_sdf)
    t_mol = indigo.loadMolecule(t_sdf)

    # find common substructure
    arr = indigo.createArray()
    arr.arrayAdd(m_mol)
    arr.arrayAdd(t_mol)
    mcs = indigo.extractCommonScaffold(arr, 'exact' if exact else 'approx')

    # match to scaffold
    query = indigo.loadQueryMolecule(mcs.smiles())
    m_match = indigo.substructureMatcher(m_mol).match(query)
    t_match = indigo.substructureMatcher(t_mol).match(query)

    # atom indices of match
    m_atoms = [m_match.mapAtom(a) for a in query.iterateAtoms()]
    t_atoms = [t_match.mapAtom(a) for a in query.iterateAtoms()]
    m_indices = [a.index() for a in m_atoms if a is not None]
    t_indices = [a.index() for a in t_atoms if a is not None]

    return m_indices, t_indices
示例#4
0
def rotatable_bonds(smiles):
    """
    Find the number of rotatable bonds in a molecule.
    Rotatable bonds are defined as any single bond, not in a ring, bound
    to a nonterminal heavy (i.e., non-hydrogen) atom.
    Excluded from the count are amide C-N bonds because of their high
    rotational energy barrier.

    The SMARTS definition is that according to
    J. Med. Chem., 2002, 45 (12), pp 2615-2623
    """
    rotatable = 0
    try:
        # Initialise the Indigo library
        indigo = indigo_module.Indigo()
        # Load the molecule into Indigo
        try:
            mol = indigo.loadMolecule(smiles)
        except IndigoException as e:
            # If loading the molecule fails, try turning off chirality error checking and try again.
            indigo.setOption("ignore-stereochemistry-errors", True)
            mol = indigo.loadMolecule(smiles)
        # Aromatize the molecule
        mol.aromatize()
        matcher = indigo.substructureMatcher(mol)
        q = indigo.loadSmarts('[!$([NH]!@C(=O))&!D1&!$(*#*)]-&!@[!$([NH]!@C(=O))&!D1&!$(*#*)]')
        rotatable = matcher.countMatches(q)

    except IndigoException as e:
        print("Indigo Exception: %s" % (e))
    finally:
        return rotatable
示例#5
0
 def __init__(self, arg_ns: argparse.Namespace):
     self.arg_ns = arg_ns
     self.index = arg_ns.elastic_index
     self.session = indigo.Indigo()
     self.es = elasticsearch.Elasticsearch(
         [arg_ns.elastic_url],
         verify_certs=arg_ns.elastic_verify_certs,
         ssl_show_warn=arg_ns.elastic_verify_certs,
     )
示例#6
0
    def __init__(self, arg_ns: argparse.Namespace):
        self.arg_ns = arg_ns
        self.session = indigo.Indigo()

        if arg_ns.bingo_dir:
            self.bingo_dir = arg_ns.bingo_dir
        else:
            self.bingo_dir = Path(arg_ns.pubchem_dir) / 'bingo_dir'

        if self.bingo_dir.is_dir():
            self.bingo_conn = Bingo.loadDatabaseFile(self.session,
                                                     str(self.bingo_dir), '')
        else:
            self.bingo_conn = Bingo.createDatabaseFile(self.session,
                                                       str(self.bingo_dir),
                                                       'molecule', '')
示例#7
0
 def __init__(self, _obj, addh=True, kekulize=False, amend=False):
     hadd_status = T
     parse_status = T
     kekulize_status = T
     if isinstance(_obj, indigo.IndigoObject):
         m = _obj
     elif isinstance(_obj, str):
         obj = indigo.Indigo()
         if os.path.exists(_obj):
             m = obj.loadMoleculeFromFile(_obj)
         else:
             self.smi = _obj
             try:
                 m = obj.loadMolecule(_obj)
             except:
                 print(' ** failed to parse SMILES')
                 parse_status = F
         if parse_status:
             if addh:
                 try:
                     m.unfoldHydrogens()
                 except:
                     hadd_status = F
                     print(' ** failed to add H')
     elif isinstance(_obj, (tuple,list)):
         # unfortunately, Indigo cannot load file formats other than sdf/mol
         # so we manually construct molecule here
         rawm = rawmol_indigo(_obj)
         m = rawm.m
     else:
         raise '#unknown instance'
     if parse_status and hadd_status:
         if kekulize:
             try:
                 kekulize_status = m.dearomatize()
             except:
                 kekulize_status = F
             if not kekulize_status: print(' ** failed to kekulize')
     ioks = states(parse_status, hadd_status, kekulize_status)
     self.ioks = ioks
     self.status = parse_status and hadd_status and kekulize_status
     if self.status:
         self.m = m
     else:
         print('  # parse_status,hadd_status,kekulize_status=',parse_status,hadd_status,kekulize_status)
         if amend:
             self.m = amend_smiles(self.smi, ioks)
示例#8
0
def draw(smiles, fname):
    _indigo = indigo.Indigo()
    _renderer = indigo_renderer.IndigoRenderer(_indigo)
    _indigo.setOption('render-output-format', 'png')
    _indigo.setOption('render-image-size', 250, 200)
    _indigo.setOption('render-margins', 10, 10)
    _indigo.setOption('render-stereo-style', 'none')
    _indigo.setOption('render-implicit-hydrogens-visible', False)
    _indigo.setOption('render-coloring', True)
    _indigo.setOption('render-bond-length', 50.0)
    _indigo.setOption('render-label-mode', 'hetero')
    
    indigo_mol = _indigo.loadMolecule(smiles)
    indigo_mol.aromatize()
    indigo_mol.layout()
    
    _renderer.renderToFile(indigo_mol, fname)
示例#9
0
def sp3carbon(smiles):
    """
    Calculate the number of carbon atoms, sp3 hybridised carbon atoms and sp3
    fraction of a SMILES string.
    """

    return_value = False
    num_carbon = float(0)
    num_carbon_sp3 = float(0)
    sp3_fraction = float(0)

    try:
        indigo = indigo_module.Indigo()
        try:
            mol = indigo.loadMolecule(smiles)
        except IndigoException as e:
            # If loading the molecule fails, try turning off chirality error checking and try again.
            indigo.setOption("ignore-stereochemistry-errors", True)
            mol = indigo.loadMolecule(smiles)

        mol.aromatize()

        mol.unfoldHydrogens()  # Must add hydrogens to get the correct answer
        for atom in mol.iterateAtoms():
            if (atom.symbol() == 'C'):
                num_carbon = num_carbon + 1
                if (atom.degree() == 4):
                    num_carbon_sp3 = num_carbon_sp3 + 1

        if num_carbon == 0:
            sp3_fraction = 0
        else:
            sp3_fraction = num_carbon_sp3 / num_carbon
        return_value = (int(num_carbon), int(num_carbon_sp3), sp3_fraction)

    except IndigoException as e:
        logging.error("sp3carbon(): Indigo exception: %s" % (e))
    except Exception as e:
        logging.error("sp3carbon(): Exception: %s" % (e))
    finally:
        return return_value
示例#10
0
文件: tpsa.py 项目: mcmont/violet
def tpsa(smiles):
    """
    Compute the topological polar surface area of a molecule specified as a
    SMILES string.
    """

    return_value = False

    # Variables to store the pattern defintions
    Pattern = collections.namedtuple("Pattern", ["value", "subsearch"])
    patterns = []

    try:
        # Initialise the Indigo library
        indigo = indigo_module.Indigo()
        # Build the path to the tpsa data file, relative to this file.
        fn = os.path.join(os.path.dirname(__file__), 'data/tpsa.tab')
        # Get the patterns from the tpsa.tab file, ignoring the header line
        for line in open(fn).readlines()[1:]:
            # Extract the fields
            value, smarts, comment = line.split("\t")
            subsearch = indigo.loadSmarts(smarts)
            # Store for later use
            patterns.append(Pattern(float(value), subsearch))

        # Load the molecule
        mol = indigo.loadMolecule(smiles)
        # Molecules MUST be dearomatized for this TPSA calculation to work correctly.
        mol.dearomatize()
        return_value = sum(
            tpsa_count_matches(indigo, pattern.subsearch, mol) * pattern.value
            for pattern in patterns)

    except IndigoException as e:
        logging.error("Indigo exception: %s" % (e))
    except Exception as e:
        logging.error("Exception: %s" % (e))
    finally:
        return return_value
示例#11
0
 def __init__(self, obj):
     assert isinstance(obj, (list, tuple)), "#ERROR: obj not a list/tuple?"
     assert len(obj) == 4, "#ERROR: `obj should .eq. (zs,chgs,bom,coords)"
     zs, coords, chgs, bom = obj
     # unfortunately, Indigo cannot load file formats other than sdf/mol
     # so we manually construct molecule here
     na = len(zs)
     ias = np.arange(na).astype(np.int)
     newobj = indigo.Indigo()
     m = newobj.createMolecule()
     ats = []
     for ia in range(na):
         ai = m.addAtom(co.chemical_symbols[zs[ia]])
         ai.setXYZ(coords[ia, 0], coords[ia, 1], coords[ia, 2])
         ai.setCharge(chgs[ia])
         ats.append(ai)
     for ia in range(na):
         ai = ats[ia]
         jas = ias[np.logical_and(bom[ia] > 0, ias > ia)]
         for ja in jas:
             bi = ai.addBond(ats[ja], bom[ia, ja])
     self.m = m
示例#12
0
    def WriteStructureThumbnail(self, output_format='png'):
        if not indigo or not indigo_renderer or not openbabel:
            # the web server is not supposed to be running this function
            logging.error(
                'Indigo/Openbabel are not installed, cannot draw structures.')

        if self.inchi is None:
            return

        _obConversion = openbabel.OBConversion()
        _obConversion.SetInFormat("inchi")
        _obConversion.SetOutFormat("smiles")
        obmol = openbabel.OBMol()
        _obConversion.ReadString(obmol, str(self.inchi))
        smiles = _obConversion.WriteString(obmol)

        _indigo = indigo.Indigo()
        _renderer = indigo_renderer.IndigoRenderer(_indigo)
        _indigo.setOption('render-output-format', output_format)
        _indigo.setOption('render-image-size', 250, 200)
        _indigo.setOption('render-margins', 10, 10)
        _indigo.setOption('render-stereo-style', 'none')
        _indigo.setOption('render-implicit-hydrogens-visible', False)
        _indigo.setOption('render-coloring', True)
        _indigo.setOption('render-bond-length', 50.0)
        _indigo.setOption('render-label-mode', 'hetero')

        try:
            indigo_mol = _indigo.loadMolecule(smiles)
            indigo_mol.aromatize()
            indigo_mol.layout()

            data = _renderer.renderToBuffer(indigo_mol).tostring()
            self.thumbnail = base64.encodestring(data)
        except indigo.IndigoException as e:
            logging.warning("Cannot draw structure of %s: %s" %
                            (self.kegg_id, str(e)))
示例#13
0
 def test_murcko_alpha(self):
     indigo = indigo_module.Indigo()
     icb = "N#CC1C=CC=C(C=1)N=C=O"  # 3-isocyanatobenzonitrile
     mol = indigo.loadMolecule(icb)
     self.assertEqual(
         murcko_alpha(mol).canonicalSmiles(), 'CC1=CC(N)=CC=C1')
示例#14
0
class Molecule(object):

    # for more rendering options visit:
    # http://www.ggasoftware.com/opensource/indigo/api/options#rendering
    _indigo = indigo.Indigo()
    _renderer = indigo_renderer.IndigoRenderer(_indigo)
    _indigo.setOption('render-output-format', 'svg')
    _indigo.setOption('render-margins', 10, 10)
    _indigo.setOption('render-stereo-style', 'none')
    _indigo.setOption('render-implicit-hydrogens-visible', False)
    _indigo.setOption('render-coloring', True)
    _indigo.setOption('render-bond-length', 20.0)
    _indigo.setOption('render-label-mode', 'hetero')
    _obElements = openbabel.OBElementTable()

    @staticmethod
    def GetNumberOfElements():
        return Molecule._obElements.GetNumberOfElements()

    @staticmethod
    def GetAllElements():
        return [
            Molecule._obElements.GetSymbol(i)
            for i in xrange(Molecule.GetNumberOfElements())
        ]

    @staticmethod
    def GetSymbol(atomic_num):
        return Molecule._obElements.GetSymbol(atomic_num)

    @staticmethod
    def GetAtomicNum(elem):
        if type(elem) == types.UnicodeType:
            elem = str(elem)
        return Molecule._obElements.GetAtomicNum(elem)

    @staticmethod
    def SetBondLength(l):
        Molecule._indigo.setOption('render-bond-length', l)

    @staticmethod
    def VerifySmarts(smarts):
        try:
            pybel.Smarts(smarts)
            return True
        except IOError:
            return False

    def __init__(self):
        self.title = None
        self.obmol = openbabel.OBMol()
        self.pybel_mol = None
        self.smiles = None
        self.inchi = None

    def __str__(self):
        return self.title or self.smiles or self.inchi or ""

    def __len__(self):
        return self.GetNumAtoms()

    def Clone(self):
        tmp = Molecule()
        tmp.title = self.title
        tmp.obmol = openbabel.OBMol(self.obmol)
        tmp.pybel_mol = pybel.Molecule(tmp.obmol)
        tmp.smiles = self.smiles
        tmp.inchi = self.inchi
        return tmp

    def SetTitle(self, title):
        self.title = title

    @staticmethod
    def FromSmiles(smiles):
        m = Molecule()
        m.smiles = smiles
        obConversion = openbabel.OBConversion()
        obConversion.SetInFormat("smiles")
        if not obConversion.ReadString(m.obmol, m.smiles):
            raise OpenBabelError("Cannot read the SMILES string: " + smiles)
        try:
            m.UpdateInChI()
            m.UpdatePybelMol()
        except OpenBabelError:
            raise OpenBabelError("Failed to create Molecule from SMILES: " +
                                 smiles)
        m.SetTitle(smiles)
        return m

    @staticmethod
    def FromInChI(inchi):
        m = Molecule()
        m.inchi = inchi
        obConversion = openbabel.OBConversion()
        obConversion.SetInFormat("inchi")
        obConversion.ReadString(m.obmol, m.inchi)
        try:
            m.UpdateSmiles()
            m.UpdatePybelMol()
        except OpenBabelError:
            raise OpenBabelError("Failed to create Molecule from InChI: " +
                                 inchi)
        m.SetTitle(inchi)
        return m

    @staticmethod
    def FromMol(mol):
        m = Molecule()
        obConversion = openbabel.OBConversion()
        obConversion.SetInFormat("mol")
        obConversion.ReadString(m.obmol, mol)
        try:
            m.UpdateInChI()
            m.UpdateSmiles()
            m.UpdatePybelMol()
        except OpenBabelError:
            raise OpenBabelError("Failed to create Molecule from MOL file:\n" +
                                 mol)
        m.SetTitle("")
        return m

    @staticmethod
    def FromOBMol(obmol):
        m = Molecule()
        m.obmol = obmol
        try:
            m.UpdateInChI()
            m.UpdateSmiles()
            m.UpdatePybelMol()
        except OpenBabelError:
            raise OpenBabelError("Failed to create Molecule from OBMol")
        m.SetTitle("")
        return m

    @staticmethod
    def _FromFormat(s, fmt='inchi'):
        if fmt == 'smiles' or fmt == 'smi':
            return Molecule.FromSmiles(s)
        if fmt == 'inchi':
            return Molecule.FromInChI(s)
        if fmt == 'mol':
            return Molecule.FromMol(s)
        if fmt == 'obmol':
            return Molecule.FromOBMol(s)

    @staticmethod
    def _ToFormat(obmol, fmt='inchi'):
        obConversion = openbabel.OBConversion()
        obConversion.SetOutFormat(fmt)
        res = obConversion.WriteString(obmol)
        if not res:
            raise OpenBabelError("Cannot convert OBMol to %s" % fmt)
        if fmt == 'smiles' or fmt == 'smi':
            res = res.split()
            if res == []:
                raise OpenBabelError("Cannot convert OBMol to %s" % fmt)
            else:
                return res[0]
        elif fmt == 'inchi':
            return res.strip()
        else:
            return res

    @staticmethod
    def Smiles2InChI(smiles):
        obConversion = openbabel.OBConversion()
        obConversion.SetInAndOutFormats("smiles", "inchi")
        obmol = openbabel.OBMol()
        if not obConversion.ReadString(obmol, smiles):
            raise OpenBabelError("Cannot read the SMILES string: " + smiles)
        return obConversion.WriteString(obmol).strip()

    @staticmethod
    def InChI2Smiles(inchi):
        obConversion = openbabel.OBConversion()
        obConversion.SetInAndOutFormats("inchi", "smiles")
        obmol = openbabel.OBMol()
        if not obConversion.ReadString(obmol, inchi):
            raise OpenBabelError("Cannot read the InChI string: " + inchi)
        return obConversion.WriteString(obmol).split()[0]

    def RemoveHydrogens(self):
        self.pybel_mol.removeh()

    def RemoveAtoms(self, indices):
        self.obmol.BeginModify()
        for i in sorted(indices, reverse=True):
            self.obmol.DeleteAtom(self.obmol.GetAtom(i + 1))
        self.obmol.EndModify()
        self.smiles = None
        self.inchi = None

    def SetAtomicNum(self, index, new_atomic_num):
        self.obmol.GetAtom(index + 1).SetAtomicNum(new_atomic_num)
        self.smiles = None
        self.inchi = None

    def ToOBMol(self):
        return self.obmol

    def ToPybelMol(self):
        return self.pybel_mol

    def ToFormat(self, fmt='inchi'):
        return Molecule._ToFormat(self.obmol, fmt=fmt)

    def ToMolfile(self):
        return self.ToFormat('mol')

    def UpdateInChI(self):
        self.inchi = Molecule._ToFormat(self.obmol, 'inchi')

    def ToInChI(self):
        """ 
            Lazy storage of the InChI identifier (calculate once only when 
            asked for and store for later use).
        """
        if not self.inchi:
            self.UpdateInChI()
        return self.inchi

    def UpdateSmiles(self):
        self.smiles = Molecule._ToFormat(self.obmol, 'smiles')

    def ToSmiles(self):
        """ 
            Lazy storage of the SMILES identifier (calculate once only when 
            asked for and store for later use).
        """
        if not self.smiles:
            self.UpdateSmiles()
        return self.smiles

    def UpdatePybelMol(self):
        self.pybel_mol = pybel.Molecule(self.obmol)

    @staticmethod
    def _GetFormulaFromInChI(inchi):
        tokens = re.findall('/f([0-9A-Za-z\.]+/)', inchi)
        if len(tokens) == 0:
            tokens = re.findall('InChI=1S?/([0-9A-Za-z\.]+)', inchi)

        if len(tokens) == 1:
            return tokens[0]
        elif len(tokens) > 1:
            raise ValueError('Bad InChI: ' + inchi)
        else:
            return ''

    @staticmethod
    def _GetAtomBagAndChargeFromInChI(inchi):
        fixed_charge = 0
        for q in re.findall('/q([0-9\+\-\;]+)', inchi):
            for s in q.split(';'):
                if s:
                    fixed_charge += int(s)

        fixed_protons = 0
        for p in re.findall('/p([0-9\+\-\;]+)', inchi):
            for s in p.split(';'):
                if s:
                    fixed_protons += int(s)

        formula = Molecule._GetFormulaFromInChI(inchi)

        atom_bag = {}
        for mol_formula_times in formula.split('.'):
            for times, mol_formula in re.findall('^(\d+)?(\w+)',
                                                 mol_formula_times):
                if not times:
                    times = 1
                else:
                    times = int(times)
                for atom, count in re.findall("([A-Z][a-z]*)([0-9]*)",
                                              mol_formula):
                    if count == '':
                        count = 1
                    else:
                        count = int(count)
                    atom_bag[atom] = atom_bag.get(atom, 0) + count * times

        if fixed_protons:
            atom_bag['H'] = atom_bag.get('H', 0) + fixed_protons
            fixed_charge += fixed_protons
        return atom_bag, fixed_charge

    @staticmethod
    def _GetNumElectronsFromInChI(inchi):
        """Calculates the number of electrons in a given molecule."""
        atom_bag, fixed_charge = Molecule._GetAtomBagAndChargeFromInChI(inchi)
        n_protons = 0
        for elem, count in atom_bag.iteritems():
            n_protons += count * Molecule._obElements.GetAtomicNum(elem)
        return n_protons - fixed_charge

    def GetFormula(self):
        return Molecule._GetFormulaFromInChI(self.ToInChI())

    def GetExactMass(self):
        return self.obmol.GetExactMass()

    def GetAtomBagAndCharge(self):
        return Molecule._GetAtomBagAndChargeFromInChI(self.ToInChI())

    def GetHydrogensAndCharge(self):
        atom_bag, charge = self.GetAtomBagAndCharge()
        return atom_bag.get('H', 0), charge

    def GetNumElectrons(self):
        return Molecule._GetNumElectronsFromInChI(self.ToInChI())

    def GetNumAtoms(self):
        return self.obmol.NumAtoms()

    def GetAtoms(self):
        return self.pybel_mol.atoms

    def FindSmarts(self, smarts):
        """
        Corrects the pyBel version of Smarts.findall() which returns results as tuples,
        with 1-based indices even though Molecule.atoms is 0-based.
    
        Args:
            mol: the molecule to search in.
            smarts_str: the SMARTS query to search for.
        
        Returns:
            The re-mapped list of SMARTS matches.
        """
        if type(smarts) == types.StringType:
            smarts = pybel.Smarts(smarts)
        shift_left = lambda m: [(n - 1) for n in m]
        return map(shift_left, smarts.findall(self.pybel_mol))

    def ToSVG(self, comment=None):
        if comment:
            Molecule._indigo.setOption('render-comment', comment)
        else:
            Molecule._indigo.setOption('render-comment', '')
        try:
            indigo_mol = Molecule._indigo.loadMolecule(self.ToSmiles())
            indigo_mol.aromatize()
            indigo_mol.layout()
            svg_str = Molecule._renderer.renderToBuffer(indigo_mol).tostring()
            id = str(uuid.uuid4())
            i = 0
            while True:
                symbol = 'glyph0-%d' % i
                if svg_str.find('id="' + symbol + '"') != -1:
                    svg_str = svg_str.replace('id="' + symbol + '"',
                                              'id="' + id + "_" + symbol + '"')
                    svg_str = svg_str.replace(
                        'href="#' + symbol + '"',
                        'href="#' + id + "_" + symbol + '"')
                else:
                    break
                i += 1
            return svg_str
        except indigo.IndigoException as e:
            return "<b>Indigo error</b>: %s</br>\n" % str(e)

    def Draw(self, show_title=False):
        def expose_cairo(win, event, svg):
            cr = win.window.cairo_create()
            svg.render_cairo(cr)
            return True

        try:
            if show_title:
                svg = rsvg.Handle(data=self.ToSVG(self.title))
            else:
                svg = rsvg.Handle(data=self.ToSVG())
        except glib.GError:  #@UndefinedVariable
            return
        _x, _y, w, h = svg.get_dimension_data()
        win = gtk.Window()
        win.resize(int(w), int(h))
        win.connect("delete-event", lambda w, e: gtk.main_quit())
        win.connect("expose-event", expose_cairo, svg)
        win.show_all()
        win.connect("destroy", lambda w: gtk.main_quit())
        gtk.main()

    def GetAtomCharges(self):
        """
            Returns:
                A list of charges, according to the number of atoms
                in the molecule
        """
        return [atom.formalcharge for atom in self.pybel_mol.atoms]

    @staticmethod
    def _GetDissociationTable(molstring,
                              fmt='inchi',
                              mid_pH=default_pH,
                              min_pKa=0,
                              max_pKa=14,
                              T=default_T,
                              transform_multiples=False):
        """
            Returns the relative potentials of pseudoisomers,
            relative to the most abundant one at pH 7.
        """
        from pygibbs.dissociation_constants import DissociationTable
        from toolbox import chemaxon

        diss_table = DissociationTable()
        try:
            pKa_table, major_ms = chemaxon.GetDissociationConstants(
                molstring,
                mid_pH=mid_pH,
                transform_multiples=transform_multiples)

            mol = Molecule.FromSmiles(major_ms)
            nH, z = mol.GetHydrogensAndCharge()
            diss_table.SetMolString(nH, nMg=0, s=major_ms)
            diss_table.SetCharge(nH, z, nMg=0)

            pKa_higher = [x for x in pKa_table if mid_pH < x[0] < max_pKa]
            pKa_lower = [x for x in pKa_table if mid_pH > x[0] > min_pKa]
            for i, (pKa, _, smiles_above) in enumerate(sorted(pKa_higher)):
                diss_table.AddpKa(pKa,
                                  nH_below=(nH - i),
                                  nH_above=(nH - i - 1),
                                  nMg=0,
                                  ref='ChemAxon',
                                  T=T)
                diss_table.SetMolString((nH - i - 1), nMg=0, s=smiles_above)

            for i, (pKa, smiles_below,
                    _) in enumerate(sorted(pKa_lower, reverse=True)):
                diss_table.AddpKa(pKa,
                                  nH_below=(nH + i + 1),
                                  nH_above=(nH + i),
                                  nMg=0,
                                  ref='ChemAxon',
                                  T=T)
                diss_table.SetMolString((nH + i + 1), nMg=0, s=smiles_below)
        except chemaxon.ChemAxonError:
            mol = Molecule._FromFormat(molstring, fmt)
            diss_table.SetOnlyPseudoisomerMolecule(mol)

        return diss_table

    def GetDissociationTable(self,
                             fmt='inchi',
                             mid_pH=default_pH,
                             min_pKa=0,
                             max_pKa=14,
                             T=default_T):
        """
            Returns the relative potentials of pseudoisomers,
            relative to the most abundant one at pH 7.
        """

        return Molecule._GetDissociationTable(self.ToInChI(), 'inchi', mid_pH,
                                              min_pKa, max_pKa, T)
示例#15
0
def reaction(smarts_string, mol1, mol2=False):
    """
    This is a convenience function that quickly runs a virtual reaction
    and return the products.

    """
    products = []
    try:

        # Setup the Indigo library.
        # Enable generation of multiple products from a reaction, but don't
        # allow product molecules to be fed back in to be reacted a second
        # time around.
        indigo = indigo_module.Indigo()
        indigo.setOption("rpe-multistep-reactions", "true")
        indigo.setOption("rpe-max-depth", "1")
        indigo.setOption("rpe-self-reaction", "false")
        indigo.setOption("rpe-mode", "grid")

        # Load the molecules into Indigo
        molecules = indigo.createArray()
        m1 = indigo.loadMolecule(mol1)
        molecules.arrayAdd(m1)

        if (mol2):
            m2 = indigo.loadMolecule(mol2)
            molecules.arrayAdd(m2)

        # Initialise a 2D array to hold the reactant table
        reactant_table = indigo.createArray()

        # Create the reaction Indigo variable
        rxn = indigo.loadReactionSmarts(smarts_string)
        # Keep mapped atoms
        rxn.automap("keep")

        # Build the Indigo array of reactants
        for i in range(0, rxn.countReactants()):
            array = indigo.createArray()
            if (i < molecules.count()):
                array.arrayAdd(molecules.at(i))
            reactant_table.arrayAdd(array)

        # Enumerate the products
        output_reactions = indigo.reactionProductEnumerate(rxn, reactant_table)
        num_products = output_reactions.count()

        if (num_products > 0):
            # The reaction was successful. Add the products to products[]
            for i in range(num_products):
                product = output_reactions.at(i)
                for p in product.iterateProducts():
                    products.append(p.canonicalSmiles())

    except IndigoException as e:
        print("Indigo Exception: %s" % (e))

    except Exception as e:
        print("Exception: %s" % (e))

    finally:
        return products
示例#16
0
import os
import indigo

indigo = indigo.Indigo("/var/www/gga/ketcher/lib")

from django.conf.urls.defaults import patterns, url
from django.http import Http404, HttpResponse


def handle_knock(request):
    return HttpResponse(content="You are welcome!", mimetype='text/plain')


def handle_layout(request):
    if request.method == 'GET' and request.GET.has_key("smiles"):
        moldata = request.GET["smiles"]
    elif request.method == 'POST' and request.POST.has_key("moldata"):
        moldata = request.POST["moldata"]
    else:
        raise Http404
    mol = indigo.loadQueryMolecule(moldata)
    mol.layout()
    return HttpResponse(content="Ok.\n" + mol.molfile(), mimetype='text/plain')


def handle_save(request):
    filedata = request.POST['filedata']
    lines = filedata.splitlines()
    first = lines[0]
    rest = "\n".join(lines[1:])
示例#17
0
NEW_RENDER_ENGINE = False

try:
    from rdkit.Chem.Draw import rdMolDraw2D
    if hasattr(rdMolDraw2D, 'MolDraw2DCairo') and hasattr(
            rdMolDraw2D, 'MolDraw2DSVG'):
        NEW_RENDER_ENGINE = True
except:
    pass

try:
    import indigo
    from indigo import IndigoException
    import indigo_renderer
    indigoObj = indigo.Indigo()
except ImportError:
    indigo = None
    indigo_renderer = None

try:
    import cairo
    cffi = False
except ImportError:
    import cairocffi
    cairocffi.install_as_pycairo()
    cffi = True
    import io
    import cairo
    if not hasattr(cairo, 'HAS_PDF_SURFACE'):
        cairo.HAS_PDF_SURFACE = False
示例#18
0
def murcko(indigo_obj):
    """
    Generate the Bemis-Murcko scaffold for a molecule.
    """
    indigo = indigo_module.Indigo()
    if not indigo:
        raise Exception('The Indigo library was not initialised.')
    mol = indigo_obj.clone()

    try:
        hanging_atoms = []
        while True:
            # Exit the while loop if we've removed all of the atoms
            if mol == None:
                break
            natoms = mol.countAtoms()
            nei = False
            found = False
            present = False

            # Atoms with 0 or 1 connections are appended to the
            # hanging_atoms[] list
            for atom in mol.iterateAtoms():
                if (atom.degree() <= 1):
                    hanging_atoms.append(atom.index())

            while (len(hanging_atoms) > 0):
                # Clear down the to_remove and hanging_next lists
                to_remove = []
                hanging_next = []

                for atom in hanging_atoms:
                    if (mol.getAtom(atom).degree() == 0):
                        to_remove.append(atom)
                    else:
                        nei = mol.getAtom(atom).iterateNeighbors().next()

                    if (nei.degree() <= 2 or nei.bond().bondOrder() == 1):
                        to_remove.append(atom)
                    else:
                        present = False
                        for a in hanging_next:
                            if (a == atom):
                                present = True
                        if (present):
                            hanging_next.append(atom)

                for atom in to_remove:
                    if (mol.getAtom(atom).degree() > 0):
                        nei = mol.getAtom(atom).iterateNeighbors().next()
                        if (nei.degree() == 2):
                            found = False
                            for a in to_remove:
                                if (a == nei.index()):
                                    found = True
                                    break

                            if not found:
                                for a in hanging_next:
                                    if (mol.getAtom(a).index() == nei.index()):
                                        found = True
                                        break
                                if not found:
                                    hanging_next.append(nei.index())

                # If there are no atoms left in the to_remove list, break out
                # of the while (len(hanging_atoms) > 0) loop.
                if (len(to_remove) == 0):
                    break

                # Remove the atoms whose indices are in the to_remove array
                mol.removeAtoms(to_remove)
                hanging_atoms = hanging_next

            if mol == None:
                break
            # If we haven't removed any atoms during the last cycle, we've finished.
            if (natoms == mol.countAtoms()):
                break

            # If the number of remaining atoms is less than 3, there can't be a ring, therefore there can't be a scaffold.
            # Return a 'None' result
            if (mol.countAtoms() < 3):
                mol = None

    except (Exception, TypeError, ValueError) as e:
        logging.error("Exception: %s" % (e))
        mol = None

    except IndigoException as e:
        logging.error("IndigoException: %s" % (e))
        mol = None

    finally:
        return mol
示例#19
0
def murcko_alpha(indigo_obj, murcko_fwk=False):
    """
    Generate the Bemis-Murcko scaffold for a molecule, but leave the 
    alpha atoms attached.

    The general strategy is:
      1) Obtain the molecule's Murcko framework, which is either passed as an
         argument or calculated if necessary.
      2) Find the atom ID numbers of the Murcko framework ring atoms.
      3) Subtract the ring atom IDs from all atom IDs in the Murcko 
         scaffold to recover the remaining (linker) atoms.
      4) Highlight the linker atoms.
      5) Loop until the atom count hasn't changed between two cycles:
         a) If an atom has one or zero bonds, add it to the hanging_atoms list.
            For all hanging atoms:
            i) If the atom isn't connected to any others, flag it for deletion.
           ii) Check whether the neighbouring atom is part of a ring. If it is, 
               we don't want to delete the current atom because it is a ring alpha
               atom.
          iii) If the neighbouring atom isn't in a ring, and 
               (the neighbouring atom is bonded to 2 or fewer atoms and the bond order is 1) and
               the neighbouring atom isn't highlighted,
               flag the atom for deletion.
         b) Remove all atoms that have been flagged for deletion.
      6) Un-highlight all atoms.
    """

    try:
        indigo = indigo_module.Indigo()

        if not indigo:
            raise Exception(
                'The Indigo library instance was passed uninitialised')

        mol = indigo_obj.clone()

        if (murcko_fwk == False):
            # Get the molecule's Murcko framework.
            murcko_fwk = murcko(mol)

        if (murcko_fwk is None):
            raise Exception(
                "This molecule doesn't have a Murcko framework. Stopping.")

        # Initialise a set to hold the atom indices of the Murcko framework.
        murcko_atoms = set()
        # Populate the murcko_atoms set with the atom indices.
        for atom in murcko_fwk.iterateAtoms():
            murcko_atoms.add(atom.index())

        # Initialise a set to hold the atom indices of the ring atoms in the Murcko framework.
        murcko_ring_atoms = set()
        for r in murcko_fwk.iterateRings(3, 1000):
            for atom in r.iterateAtoms():
                #print "Atom index %s is in a ring." % (atom.index())
                murcko_ring_atoms.add(atom.index())

        # Subtract the set of Murcko ring atoms from the whole Murcko set to get the linker atom indices.
        linker_atom_indices = list(murcko_atoms - murcko_ring_atoms)
        # Highlight the linker atoms.
        for atom in mol.iterateAtoms():
            if atom.index() in linker_atom_indices:
                atom.highlight()

        # Hanging atoms are those with one or fewer bonds to other atoms.
        hanging_atoms = []

        # Loop until done
        while True:
            if mol == None:
                break
            # Record the number of atoms in the molecule. This will be
            # compared to the number of atoms at the end of this cycle.
            # If the numbers are the same, we'll have finished.
            natoms = mol.countAtoms()

            # Reset some variables
            nei = False
            found = False
            present = False

            # If an atom is connected to one or fewer other atoms, consider it for deletion.
            for atom in mol.iterateAtoms():
                if (atom.degree() <= 1):
                    hanging_atoms.append(atom.index())

            while (len(hanging_atoms) > 0):

                # Clear down the to_remove and hanging_next lists
                to_remove = []
                hanging_next = []

                for atom in hanging_atoms:
                    if (mol.getAtom(atom).degree() == 0):
                        # The hanging atom is not connected to any other atoms. Add it to to_remove array.
                        to_remove.append(atom)
                    else:
                        nei = mol.getAtom(atom).iterateNeighbors().next()

                        # Check whether the neighbouring atom is part of a ring. If it is, we don't want to delete the current atom.
                        nei_not_in_ring = True
                        # Loop over all bonds in the molecule
                        for bond in mol.iterateBonds():
                            # If the bond is somehow connected to the neighbouring atom, check whether it's a chain or a ring bond.
                            if (bond.source().index() == nei.index()) or (
                                    bond.destination().index() == nei.index()):
                                # The Indigo.RING constant is 10
                                if bond.topology() == 10:
                                    # The neighbouring atom is in a ring. The atom will not be deleted.
                                    nei_not_in_ring = False

                        # If the neighbouring atom isn't in a ring,
                        # and (the neighbouring atom is bonded to 2
                        # or fewer atoms and the bond order is 1) and
                        # the neighbouring atom isn't highlighted,
                        # flag the atom for deletion.
                        if nei_not_in_ring and (nei.degree() <= 2 \
                          or nei.bond().bondOrder() == 1) \
                          and (not(nei.isHighlighted())):
                            # If the atom meets the deletion criteria, add it to the list of atoms to be deleted.
                            to_remove.append(atom)
                        else:
                            present = False
                            for a in hanging_next:
                                if (a == atom):
                                    present = True
                            if (present):
                                hanging_next.append(atom)

                for atom in to_remove:
                    if (mol.getAtom(atom).degree() > 0):
                        nei = mol.getAtom(atom).iterateNeighbors().next()
                        if (nei.degree() == 2):
                            found = False
                            # Is the neighbour's index() already in the to_remove array?
                            for a in to_remove:
                                if (a == nei.index()):
                                    #                                    print "Atom is already in the to_remove array"
                                    found = True
                                    break

                            if not found:
                                for a in hanging_next:
                                    if (mol.getAtom(a).index() == nei.index()):
                                        found = True
                                        break
                                if not found:
                                    hanging_next.append(nei.index())

                if (len(to_remove) == 0):
                    break

                # Remove the atoms whose indices are in the to_remove array
                mol.removeAtoms(to_remove)
                hanging_atoms = hanging_next

            if mol == None:
                break

            # If we haven't removed any atoms during the last cycle, we've finished.
            if (natoms == mol.countAtoms()):
                break

            # If the number of remaining atoms is less than 3, there can't be a ring, therefore there can't be a scaffold.
            # Return a 'None' result
            if (mol.countAtoms() < 3):
                mol = None

        # Remove any atom highlights to prevent them from appearing
        # in the canonical SMILES string when the molecule object is
        # passed back to the calling function.
        if mol is not None:
            for atom in mol.iterateAtoms():
                if atom.index() in linker_atom_indices:
                    atom.unhighlight()

    except (Exception, TypeError, ValueError) as e:
        logging.error("murcko_alpha(): Exception: %s" % (e))
        mol = None

    except IndigoException as e:
        logging.error("murcko_alpha(): IndigoException: %s" % (e))
        mol = None

    finally:
        return mol
示例#20
0
    def populate(self, target_model_name, target_database, source_model_name,
                 source_database, size, limit, offset, inchi_conversion, idx,
                 display_offset):

        from django.db import connections
        from django.db import transaction
        from django.db.models import get_model
        from django.db.utils import DatabaseError, IntegrityError

        source_model = get_model(self.app_name, source_model_name)
        target_model = get_model(self.app_name, target_model_name)

        target_conn = connections[target_database]

        source_pk = source_model._meta.pk.name

        writer = Writer(self.term, (idx, 0))
        pbar = ProgressBar(widgets=[
            '{0} ({1}) [{2}-{3}]: '.format(target_model_name,
                                           idx - display_offset + 1, offset,
                                           offset + limit),
            Percentage(), ' (',
            Counter(), ') ',
            Bar(marker=RotatingMarker()), ' ',
            ETA()
        ],
                           fd=writer,
                           maxval=limit).start()

        inchi_kwargs = {}

        if inchi_conversion == 'indigo':
            indigo_obj = indigo.Indigo()
            indigo_inchi_obj = indigo_inchi.IndigoInchi(indigo_obj)
            inchi_kwargs = {"inchiObj": indigo_inchi_obj}

        elif inchi_conversion == 'rdkit' and self.verbosity < 1:
            from rdkit import rdBase
            rdBase.DisableLog('rdApp.error')
            from rdkit import RDLogger
            lg = RDLogger.logger()
            lg.setLevel(RDLogger.CRITICAL)

        inchi_converter = inchi_converters.get(inchi_conversion)
        last_pk = None

        for i in range(offset, offset + limit, size):
            success = 0
            failure = 0
            empty = 0
            ignored = 0
            transaction.commit_unless_managed(using=target_database)
            transaction.enter_transaction_management(using=target_database)
            transaction.managed(True, using=target_database)
            with target_conn.constraint_checks_disabled():

                try:

                    chunk_size = min(size, limit + offset - i)
                    original_data = None

                    if not last_pk:
                        if i:
                            last_pk = source_model.objects.using(
                                source_database).order_by(source_pk).only(
                                    source_pk).values_list(source_pk)[i][0]
                        else:
                            original_data = source_model.objects.using(
                                source_database).order_by(
                                    source_pk).values_list(
                                        'pk', 'standardinchi')[:chunk_size]

                    if not original_data:
                        original_data = source_model.objects.using(
                            source_database).order_by(source_pk).values_list(
                                'pk', 'standardinchi').filter(
                                    pk__gt=last_pk)[:chunk_size]

                    last_pk = original_data[chunk_size - 1][0]

                    target_data = []
                    for pk, inchi in original_data:
                        if not inchi:
                            empty += 1
                            continue

                        if int(pk) in self.ignores:
                            ignored += 1
                            continue

                        ctab = self.convert_inchi(inchi_converter, pk, inchi,
                                                  inchi_kwargs)
                        if not ctab:
                            failure += 1
                            continue
                        target_data.append(
                            target_model(pk=int(pk), molfile=ctab))
                        success += 1

                    target_model.objects.using(target_database).bulk_create(
                        target_data)

                except IntegrityError as e:
                    if self.verbosity >= 1:
                        self.stderr.write(
                            "ERROR: integrity error ({0}) occurred when processing chunk {1}-{2}"
                            .format(e.message, i, i + size))
                    transaction.rollback(using=target_database)
                    transaction.leave_transaction_management(
                        using=target_database)
                    continue

                except DatabaseError as e:
                    if self.verbosity >= 1:
                        self.stderr.write(
                            "ERROR: database error ({0}) occurred when processing chunk {1}-{2}"
                            .format(e.message, i, i + size))
                    transaction.rollback(using=target_database)
                    transaction.leave_transaction_management(
                        using=target_database)
                    raise e

            pbar.update(i - offset + 1)
            transaction.commit(using=target_database)
            transaction.leave_transaction_management(using=target_database)

            self.total_success += success
            self.total_failure += failure
            self.total_empty += empty
            self.total_ignored += ignored

        pbar.update(limit)
        pbar.finish()
示例#21
0
文件: test.py 项目: nomad-nmr/msp
import sys
import getopt
import unittest
import urllib
import urllib2
import indigo
import indigo_inchi

indigo = indigo.Indigo()
indigo_inchi = indigo_inchi.IndigoInchi(indigo)
indigo.setOption('ignore-stereochemistry-errors', 'true')

base_url = "http://localhost:8080/"


def make_request(request, data, use_post=True):
    global base_url
    data = urllib.urlencode(data) if data is not None else None
    if use_post:
        r = urllib2.urlopen(base_url + '/' + request, data)
    else:
        r = urllib2.urlopen(base_url + '/' + request +
                            ("" if data is None else "?" + data))
    return r


class TestKetcherServerApi(unittest.TestCase):
    def test_knocknock(self):
        r = make_request("knocknock", None, False)
        self.assertEquals(200, r.code)
        self.assertEquals("You are welcome!", r.read().strip())
示例#22
0
文件: ketcher.py 项目: nomad-nmr/msp
            return self.FileWrapper(fd) if self.method == 'GET' else ['']
        except (IOError, OSError):
            raise self.HttpException(
                "402 Payment Required",  # or 403, hmm..
                "Must get more money for overtime")

    def is_form_request(self):
        return self.method == 'POST' and \
               (self.content_type.startswith('application/x-www-form-urlencoded')
                or self.content_type.startswith('multipart/form-data'))


try:
    import indigo
    import indigo_inchi
    application.indigo = indigo.Indigo()
    application.indigo_inchi = indigo_inchi.IndigoInchi(application.indigo)
    application.indigo.setOption('ignore-stereochemistry-errors', 'true')
except:
    pass

if __name__ == '__main__':
    import socket
    from wsgiref.simple_server import make_server

    def parse_args():
        dir = sys.argv[1] if len(sys.argv) > 1 else ''
        addr = sys.argv[2] if len(sys.argv) > 2 else ''
        res = addr.rsplit(':', 1)
        return dir, \
               res[0] if len(res) > 1 else '0.0.0.0', \