def RingSubSet(ifs, ofs, exo):
    for mol in ifs.GetOEGraphMols():
        submol = oechem.OEGraphMol()
        adjustHcount = True
        if exo:
            isinring = oechem.OEAtomIsInRing()
            isexo = oechem.OEIsNonRingAtomDoubleBondedToRing()
            includeexo = oechem.OEOrAtom(isinring, isexo)
            oechem.OESubsetMol(submol, mol, includeexo, adjustHcount)
        else:
            oechem.OESubsetMol(submol, mol, oechem.OEAtomIsInRing(),
                               adjustHcount)
        submol.SetTitle(mol.GetTitle() + "_rings")
        if submol.NumAtoms() != 0:
            oechem.OEWriteMolecule(ofs, submol)
Beispiel #2
0
def get_binding_site(structure, ligand):
    """
    """
    partlist = oechem.OEIntArray(structure.GetMaxAtomIdx())

    # get all contacts between ligand and assembly
    contacts = oechem.OEGetNearestNbrs(structure, ligand, 5.0)
    binding_site_atom_idxs = set(contact.GetBgn().GetIdx()
                                 for contact in contacts)

    # create the partition map
    for atom in structure.GetAtoms():
        if atom.GetIdx() in binding_site_atom_idxs:
            partlist[atom.GetIdx()] = 1

    entitypred = oechem.OEPartPredAtom(partlist)

    # select the binding site atoms
    entitypred.SelectPart(1)

    # create a new molecule for the entity
    binding_site = oechem.OEGraphMol()
    oechem.OESubsetMol(binding_site, structure, entitypred, False, False)

    return binding_site
Beispiel #3
0
def AtomPathLength(ifs, ofs, itf, atm1, atm2):
    for mol in ifs.GetOEGraphMols():
        oechem.OETriposAtomNames(mol)

        a1 = None
        a2 = None
        for atm in mol.GetAtoms():
            if atm.GetName() == atm1:
                a1 = atm
            if atm.GetName() == atm2:
                a2 = atm
            if a1 is not None and a2 is not None:
                break

        if a1 is None or a2 is None:
            oechem.OEThrow.Warning(
                "Failed to find atoms %s and %s in molecule" % (atm1, atm2))
            continue

        pathlen = oechem.OEGetPathLength(a1, a2)
        if itf.GetBool("-verbose") or not itf.HasString("-o"):
            print("Path length: %s in %s" %
                  (pathlen, oechem.OEMolToSmiles(mol)))

        spath = oechem.OEShortestPath(a1, a2)
        spathmol = oechem.OEGraphMol()
        adjustHCount = True
        oechem.OESubsetMol(spathmol, mol, oechem.OEIsAtomMember(spath),
                           adjustHCount)
        spathsmiles = oechem.OEMolToSmiles(spathmol)

        if itf.HasString("-o"):
            oechem.OEWriteMolecule(ofs, spathmol)
        elif itf.GetBool("-verbose"):
            print(spathsmiles)
def atom_bond_set_to_mol(frag, oemol, adjust_hcount=False, RGroup=True):
    from openeye import oechem
    import warnings
    fragatompred = oechem.OEIsAtomMember(frag.GetAtoms())
    fragbondpred = oechem.OEIsBondMember(frag.GetBonds())

    fragment_oemol = oechem.OEMol()
    adjustHCount = adjust_hcount
    oechem.OESubsetMol(fragment_oemol, oemol, fragatompred, fragbondpred,
                       adjustHCount, RGroup)

    oechem.OEAddExplicitHydrogens(fragment_oemol)
    # sanity check that all atoms are bonded
    for atom in fragment_oemol.GetAtoms():
        if not list(atom.GetBonds()):
            warnings.warn(
                "Yikes!!! An atom that is not bonded to any other atom in the fragment. "
                "You probably ran into a bug. Please report the input molecule to the issue tracker"
            )
    # Perceive stereo and check that defined stereo did not change
    oechem.OEPerceiveChiral(fragment_oemol)
    oechem.OE3DToAtomStereo(fragment_oemol)
    oechem.OE3DToBondStereo(fragment_oemol)

    return fragment_oemol
Beispiel #5
0
def split_molecule_components(
        molecule: oechem.OEGraphMol) -> List[oechem.OEGraphMol]:
    """
    Split an OpenEye Molecule into its bonded components.
    Parameters
    ----------
    molecule: oechem.OEGraphMol
        An OpenEye molecule holding multiple components.
    Returns
    -------
    : list of oechem.OEGraphMol
        A list of OpenEye molecules holding the split components.
    """
    # determine bonded components
    number_of_components, part_list = oechem.OEDetermineComponents(molecule)
    predicate = oechem.OEPartPredAtom(part_list)

    # get bonded components
    components = []
    for i in range(number_of_components):
        predicate.SelectPart(i + 1)
        component = oechem.OEGraphMol()
        oechem.OESubsetMol(component, molecule, predicate)
        components.append(component)

    return components
Beispiel #6
0
def frag_to_smiles(frags, mol):
    """
    Convert fragments (AtomBondSet) to smiles string
    Parameters
    ----------
    frags
    mol

    Returns
    -------
    smiles: list of smiles strings

    """
    smiles = {}
    for frag in frags:
        fragatompred = oechem.OEIsAtomMember(frag.GetAtoms())
        fragbondpred = oechem.OEIsBondMember(frag.GetBonds())

        fragment = oechem.OEGraphMol()
        adjustHCount = True
        oechem.OESubsetMol(fragment, mol, fragatompred, fragbondpred,
                           adjustHCount)
        s = oechem.OECreateIsoSmiString(fragment)
        if s not in smiles:
            smiles[s] = []
        smiles[s].append(frag)
    return smiles
Beispiel #7
0
def get_scaffold(molecule, adjustHcount=False):
    """
    Takes an openeye.oechem.oemol and returns
    an openeye.oechem.oemol of the scaffold

    The scaffold is a molecule where all the atoms that are not in rings, and are not linkers between rings.
    double bonded atoms exo to a ring are included as ring atoms

    This function has been completely taken from openeye's extractscaffold.py script
    https://docs.eyesopen.com/toolkits/python/oechemtk/oechem_examples/oechem_example_extractscaffold.html#section-example-oechem-extractscaffold
    Parameters
    ----------
    mol : openeye.oechem.oemol
        entire molecule to get the scaffold of
    adjustHcount : bool, default=False
        add/remove hydrogens to satisfy valence of scaffold


    Returns
    -------
    openeye.oechem.oemol
        scaffold oemol of the input mol. New oemol.
    """
    def TraverseForRing(visited, atom):
        visited.add(atom.GetIdx())

        for nbor in atom.GetAtoms():
            if nbor.GetIdx() not in visited:
                if nbor.IsInRing():
                    return True

                if TraverseForRing(visited, nbor):
                    return True

        return False

    def DepthFirstSearchForRing(root, nbor):
        visited = set()
        visited.add(root.GetIdx())

        return TraverseForRing(visited, nbor)

    class IsInScaffold(oechem.OEUnaryAtomPred):
        def __call__(self, atom):
            if atom.IsInRing():
                return True

            count = 0
            for nbor in atom.GetAtoms():
                if DepthFirstSearchForRing(atom, nbor):
                    count += 1

            return count > 1

    dst = oechem.OEMol()
    pred = IsInScaffold()

    oechem.OESubsetMol(dst, molecule, pred, adjustHcount)
    return dst
Beispiel #8
0
        def search(self, mol0, mol1):
            mol0 = mol0._struc
            mol1 = mol1._struc

            p0 = mol0.CreateCopy()
            p1 = mol1.CreateCopy()
            #set atom int type.
            for mol in (
                    p0,
                    p1,
            ):
                for atom in mol.GetAtoms():
                    if (atom.IsHydrogen()):
                        atom.SetIntType(1)
                    else:
                        atom.SetIntType(2)
            #suppress hydrogens before mcs search
            oechem.OESuppressHydrogens(p0)
            oechem.OESuppressHydrogens(p1)
            if (self._is_approximate):
                mcss = oechem.OEMCSSearch(p1, self._atom_expr, self._bond_expr,
                                          oechem.OEMCSType_Approximate)
            else:
                mcss = oechem.OEMCSSearch(p1, self._atom_expr, self._bond_expr)
            #set minimum atom of the mcs
            mcss.SetMinAtoms(1)
            #set the function to evalue the mcs search
            mcss.SetMCSFunc(oechem.OEMCSMaxAtomsCompleteCycles(1.5))

            # There could be multiple matches. We select the one with the maximum number of atoms.
            # If there are more than 1 matches with the same maximum number of atoms, we arbitrarily select the first one.
            mcs_mol = None
            max_num = 0
            #do the mcs search
            for match in mcss.Match(p0, True):
                num_atom = 0
                mcs_tmp = oechem.OEMol()
                oechem.OESubsetMol(mcs_tmp, match, True)
                oechem.OEFindRingAtomsAndBonds(mcs_tmp)
                for atom in mcs_tmp.GetAtoms():
                    if (not atom.IsHydrogen()):
                        num_atom += 1

                if (num_atom > max_num):
                    max_num = num_atom
                    mcs_mol = mcs_tmp
                    atom_match0 = []
                    atom_match1 = []
                    for matchpair in match.GetAtoms():
                        atom_match0.append(matchpair.target.GetIdx() + 1)
                        atom_match1.append(matchpair.pattern.GetIdx() + 1)
            #dump search result to kbase
            if (mcs_mol):
                mol0 = struc.OeStruc(mol0)
                mol1 = struc.OeStruc(mol1)
                mcs_mol = struc.OeStruc(mcs_mol)
                return self.deposit_to_kbase(mol0.id(), mol1.id(), atom_match0,
                                             atom_match1)
Beispiel #9
0
def strip_water_ions(in_system):
    """
    This function remove waters and ions molecules
    from the input system

    Parameters:
    ----------
    in_system : oechem.OEMol
        The bio-molecular system to clean
    opt: python dictionary
        The system option

    Output:
    -------
    clean_system : oechem.OEMol
        The cleaned system

    """
    # Copy the input system
    system = in_system.CreateCopy()

    # Create a bit vector mask
    bv = oechem.OEBitVector(system.GetMaxAtomIdx())
    bv.NegateBits()

    # Create a Hierarchical View of the protein system
    hv = oechem.OEHierView(
        system,
        oechem.OEAssumption_BondedResidue + oechem.OEAssumption_ResPerceived)

    # Looping over the system residues
    for chain in hv.GetChains():
        for frag in chain.GetFragments():
            for hres in frag.GetResidues():
                res = hres.GetOEResidue()

                # Check if a residue is a mono atomic ion
                natoms = 0
                for at in hres.GetAtoms():
                    natoms += 1

                # Set the atom bit mask off
                if oechem.OEGetResidueIndex(
                        res) == oechem.OEResidueIndex_HOH or natoms == 1:
                    # Set Bit mask
                    atms = hres.GetAtoms()
                    for at in atms:
                        bv.SetBitOff(at.GetIdx())

    # Extract the system without waters or ions
    pred = oechem.OEAtomIdxSelected(bv)
    clean_system = oechem.OEMol()
    oechem.OESubsetMol(clean_system, system, pred)

    return clean_system
Beispiel #10
0
def SmartsPathLength(ifs, ofs, itf, ss1, ss2):
    for mol in ifs.GetOEGraphMols():
        oechem.OEPrepareSearch(mol, ss1)
        oechem.OEPrepareSearch(mol, ss2)
        if not (ss1.SingleMatch(mol) and ss2.SingleMatch(mol)):
            oechem.OEThrow.Warning(
                "Unable to find SMARTS matches in %s, skipping" %
                mol.GetTitle())
            continue

        unique = True
        allminlen = sys.maxsize
        for match1 in ss1.Match(mol, unique):
            for match2 in ss2.Match(mol, unique):
                minlen = sys.maxsize
                for atom1 in match1.GetTargetAtoms():
                    for atom2 in match2.GetTargetAtoms():
                        pathlen = oechem.OEGetPathLength(atom1, atom2)
                        if minlen > pathlen:
                            minlen = pathlen
                            atompairs = []
                            atompairs.append([atom1, atom2])

                        elif minlen == pathlen:
                            atompairs.append([atom1, atom2])

                if minlen < allminlen:
                    allminlen = minlen
                    allatompairs = atompairs[:]

                elif minlen == allminlen:
                    allatompairs += atompairs[:]

        if itf.GetBool("-verbose") or not itf.HasString("-o"):
            print("Shortest path length: %s in %s" %
                  (allminlen, oechem.OEMolToSmiles(mol)))

        spathlist = set()
        for satom1, satom2, in allatompairs:
            spath = oechem.OEShortestPath(satom1, satom2)
            spathmol = oechem.OEGraphMol()
            oechem.OESubsetMol(spathmol, mol, oechem.OEIsAtomMember(spath))
            spathsmiles = oechem.OEMolToSmiles(spathmol)

            if spathsmiles in spathlist:
                continue
            spathlist.add(spathsmiles)

            if itf.HasString("-o"):
                oechem.OEWriteMolecule(ofs, spathmol)
            elif itf.GetBool("-verbose"):
                print(spathsmiles)

    return
Beispiel #11
0
def get_smarts(prefix, atom_idxs):
    """Get the SMARTS corresponding to a list of atom indices"""

    offmol = Molecule.from_file(prefix + '.mol2')
    fix_carboxylate_bond_orders(offmol)
    if prefix in prefix2pmd_struct:
        pmd_struct = prefix2pmd_struct[prefix]
    else:
        pmd_struct = ParmEd.load_file(prefix + '.prmtop')
        prefix2pmd_struct[prefix] = pmd_struct
    oemol = offmol.to_openeye()
    residues_of_interest = set()
    atom_indices_of_interest = set()
    #for atom_idx in atom_idxs:
    #residues_of_interest.add(pmd_struct.atoms[atom_idx].residue.idx)
    #atom_indices_of_interest.add(atom_idx)
    #for neighbor in oemol.GetAtom(atom_idx).GetAtoms():
    #  atom_indices_of_interest.add(neighbor.GetIdx())

    for oeatom, pmd_atom in zip(oemol.GetAtoms(), pmd_struct.atoms):

        # Delete all non-residue-of-interest atoms
        #if (pmd_atom.residue.idx in residues_of_interest):
        #  atom_indices_of_interest.add(pmd_atom.idx)

        # Assign tags to atoms of interest
        if (oeatom.GetIdx() in atom_idxs):
            atom_idx = oeatom.GetIdx()
            map_index = atom_idxs.index(atom_idx) + 1
            oeatom.SetMapIdx(map_index)

            atom_indices_of_interest.add(atom_idx)
            for neighbor in oeatom.GetAtoms():
                atom_indices_of_interest.add(neighbor.GetIdx())
    # Make a "Subset" molecule, so that we don't get weird charges
    # around where we cleave the residues
    subsetmol = OEChem.OEGraphMol()
    oepred = OEChem.PyAtomPredicate(
        lambda x: x.GetIdx() in atom_indices_of_interest)
    OEChem.OESubsetMol(subsetmol, oemol, oepred)
    smiles_options = (OEChem.OESMILESFlag_Canonical
                      | OEChem.OESMILESFlag_Isotopes
                      | OEChem.OESMILESFlag_RGroups)

    # Add the atom and bond stereo flags
    smiles_options |= OEChem.OESMILESFlag_AtomStereo | OEChem.OESMILESFlag_BondStereo

    # Add the hydrogen flag
    smiles_options |= OEChem.OESMILESFlag_Hydrogens
    smiles_options |= OEChem.OESMILESFlag_AtomMaps
    smiles = OEChem.OECreateSmiString(subsetmol, smiles_options)

    return smiles
Beispiel #12
0
def GetFragmentCombinations(mol, fraglist, frag_number):
    fragments = []
    fragcombs = GetFragmentAtomBondSetCombinations(mol, fraglist, frag_number)
    for f in fragcombs:
        fragatompred = oechem.OEIsAtomMember(f.GetAtoms())
        fragbondpred = oechem.OEIsBondMember(f.GetBonds())
        fragment = oechem.OEGraphMol()
        adjustHCount = True
        oechem.OESubsetMol(fragment, mol, fragatompred, fragbondpred,
                           adjustHCount)
        fragments.append(fragment)
    return fragments
Beispiel #13
0
def BackBone(ifs, ofs):
    adjustHCount = True
    mol = oechem.OEGraphMol()
    backboneMol = oechem.OEGraphMol()

    while oechem.OEReadMolecule(ifs, mol):
        if not oechem.OEHasResidues(mol):
            oechem.OEPerceiveResidues(mol, oechem.OEPreserveResInfo_All)
        aiter = mol.GetAtoms(oechem.OEIsBackboneAtom())
        member = oechem.OEIsAtomMember(aiter)

        oechem.OESubsetMol(backboneMol, mol, member, adjustHCount)
        oechem.OEWriteMolecule(ofs, backboneMol)
def GetFragments(mol, minbonds, maxbonds):
    from openeye import oegraphsim
    frags = []
    fptype = oegraphsim.OEGetFPType("Tree,ver=2.0.0,size=4096,bonds=%d-%d,atype=AtmNum,btype=Order"
                                    % (minbonds, maxbonds))

    for abset in oegraphsim.OEGetFPCoverage(mol, fptype, True):
        fragatompred = oechem.OEIsAtomMember(abset.GetAtoms())

        frag = oechem.OEGraphMol()
        adjustHCount = True
        oechem.OESubsetMol(frag, mol, fragatompred, adjustHCount)
        oechem.OEFindRingAtomsAndBonds(frag)
        frags.append(oechem.OEGraphMol(frag))

    return frags
Beispiel #15
0
def get_atom_map(tagged_smiles, molecule=None):
    """
    Returns a dictionary that maps tag on SMILES to atom index in molecule.
    Parameters
    ----------
    tagged_smiles: str
        index-tagged explicit hydrogen SMILES string
    molecule: OEMol
        molecule to generate map for. If None, a new OEMol will be generated from the tagged SMILES, the map will map to
        this molecule and it will be returned.

    Returns
    -------
    atom_map: dict
        a dictionary that maps tag to atom index {tag:idx}
    molecule: OEMol
        If a molecule was not provided, the generated molecule will be returned.
    """
    if molecule is None:
        molecule = openeye.smiles_to_oemol(tagged_smiles)

    ss = oechem.OESubSearch(tagged_smiles)
    oechem.OEPrepareSearch(molecule, ss)
    ss.SetMaxMatches(1)

    atom_map = {}
    t1 = time.time()
    matches = [m for m in ss.Match(molecule)]
    t2 = time.time()
    seconds = t2 - t1
    logger().info("Substructure search took {} seconds".format(seconds))
    if not matches:
        logger().info("MCSS failed for {}, smiles: {}".format(
            molecule.GetTitle(), tagged_smiles))
        return False
    for match in matches:
        for ma in match.GetAtoms():
            atom_map[ma.pattern.GetMapIdx()] = ma.target.GetIdx()

    # sanity check
    mol = oechem.OEGraphMol()
    oechem.OESubsetMol(mol, match, True)
    logger().info("Match SMILES: {}".format(oechem.OEMolToSmiles(mol)))
    if molecule is None:
        return molecule, atom_map

    return atom_map
Beispiel #16
0
def SubSetRes(ifs, ofs, chainid, resname, resnum):
    adjustHCount = True
    mol = oechem.OEGraphMol()
    while oechem.OEReadMolecule(ifs, mol):
        if not oechem.OEHasResidues(mol):
            oechem.OEPerceiveResidues(mol, oechem.OEPreserveResInfo_All)
        hv = oechem.OEHierView(mol)
        res = hv.GetResidue(chainid, resname, resnum)
        if res.GetOEResidue().GetName() is None:
            oechem.OEThrow.Fatal("Failed to find residue")
        atomiter = res.GetAtoms()
        member = oechem.OEIsAtomMember(atomiter)
        resmol = oechem.OEGraphMol()
        oechem.OESubsetMol(resmol, mol, member, adjustHCount)
        if chainid == " ":
            resmol.SetTitle("%s %d" % (resname, resnum))
        else:
            resmol.SetTitle("%s %s %d" % (resname, chainid, resnum))

        oechem.OEWriteMolecule(ofs, resmol)
Beispiel #17
0
def frag_to_smiles(frags, mol):
    """
    Convert fragments (AtomBondSet) to canonical isomeric SMILES string
    Parameters
    ----------
    frags: list
    mol: OEMol
    OESMILESFlag: str
        Either 'ISOMERIC' or 'DEFAULT'. This flag determines which OE function to use to generate SMILES string

    Returns
    -------
    smiles: dict of smiles to frag

    """

    smiles = {}
    for frag in frags:
        fragatompred = oechem.OEIsAtomMember(frag.GetAtoms())
        fragbondpred = oechem.OEIsBondMember(frag.GetBonds())

        #fragment = oechem.OEGraphMol()
        fragment = oechem.OEMol()
        adjustHCount = True
        oechem.OESubsetMol(fragment, mol, fragatompred, fragbondpred, adjustHCount)

        oechem.OEPerceiveChiral(fragment)
        # sanity check that all atoms are bonded
        for atom in fragment.GetAtoms():
            if not list(atom.GetBonds()):
                raise Warning("Yikes!!! An atom that is not bonded to any other atom in the fragment. "
                              "You probably ran into a bug. Please report the input molecule to the issue tracker")
        #s = oechem.OEMolToSmiles(fragment)
        #s2 = fragmenter.utils.create_mapped_smiles(fragment, tagged=False, explicit_hydrogen=False)
        s = mol_to_smiles(fragment, mapped=False, explicit_hydrogen=True, isomeric=True)

        if s not in smiles:
            smiles[s] = []
        smiles[s].append(frag)

    return smiles
Beispiel #18
0
def main(argv=[__name__]):
    if len(argv) != 3:
        oechem.OEThrow.Usage("%s <infile> <outfile>" % argv[0])

    ifs = oechem.oemolistream()
    if not ifs.open(argv[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % argv[1])

    ofs = oechem.oemolostream()
    if not ofs.open(argv[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % argv[2])

    for mol in ifs.GetOEGraphMols():
        numparts, partlist = oechem.OEDetermineComponents(mol)
        pred = oechem.OEPartPredAtom(partlist)

        for i in range(1, numparts + 1):
            pred.SelectPart(i)
            partmol = oechem.OEGraphMol()
            oechem.OESubsetMol(partmol, mol, pred)
            oechem.OEWriteMolecule(ofs, partmol)
Beispiel #19
0
        def around(dist, ls):
            """
            This function select atom not far than the threshold distance from
            the current selection. The threshold distance is in Angstrom

            selection can be:
            mask = '5.0 around ligand'
            """
            # at = system.GetAtom(oechem.OEHasAtomIdx(idx))

            # Atom set selection
            atom_set_around = set()

            # Create a OE bit vector mask for each atoms
            bv_around = oechem.OEBitVector(system.GetMaxAtomIdx())

            # Set the mask atom
            for at in system.GetAtoms():
                if at.GetIdx() in ls:
                    bv_around.SetBitOn(at.GetIdx())

            # Predicate
            pred = oechem.OEAtomIdxSelected(bv_around)

            # Create the system molecule based on the atom mask
            molecules = oechem.OEMol()
            oechem.OESubsetMol(molecules, system, pred)

            # Create the Nearest neighbours
            nn = oechem.OENearestNbrs(system, float(dist))

            for nbrs in nn.GetNbrs(molecules):
                for atom in oechem.OEGetResidueAtoms(nbrs.GetBgn()):
                    if atom.GetIdx() in ls:
                        continue
                    atom_set_around.add(atom.GetIdx())

            return atom_set_around
Beispiel #20
0
def main(argv=[__name__]):
    itf = oechem.OEInterface(InterfaceData, argv)

    exo_dbl_bonds = itf.GetBool("-exo")

    ifs = oechem.oemolistream()
    if not ifs.open(itf.GetString("-i")):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % itf.GetString("-i"))

    ofs = oechem.oemolostream()
    if not ofs.open(itf.GetString("-o")):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-o"))

    for src in ifs.GetOEMols():
        dst = oechem.OEMol()
        pred = IsInScaffold()
        if exo_dbl_bonds:
            pred = oechem.OEOrAtom(pred, oechem.OEIsNonRingAtomDoubleBondedToRing())

        adjustHcount = True
        oechem.OESubsetMol(dst, src, pred, adjustHcount)

        if dst.IsValid():
            oechem.OEWriteMolecule(ofs, dst)
Beispiel #21
0
#!/usr/bin/env python
# (C) 2017 OpenEye Scientific Software Inc. All rights reserved.
#
# TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
# provided to current licensees or subscribers of OpenEye products or
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. OpenEye claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable OpenEye offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
# liable for any damages or liability in connection with the Sample Code
# or its use.

# @ <SNIPPET>
from openeye import oechem
mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "c1ccccc1O")

frag = oechem.OEGraphMol()
oechem.OESubsetMol(frag, mol, oechem.OEIsCarbon())

mol.SetData("just_carbon", frag)
justCarbon = mol.GetData("just_carbon")
# @ </SNIPPET>
Beispiel #22
0
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. OpenEye claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable OpenEye offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
# liable for any damages or liability in connection with the Sample Code
# or its use.

# @ <SNIPPET>
from __future__ import print_function
from openeye import oechem
from openeye import oemedchem

mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "COc1ccc(cc1)CC(=O)N")

for frag in oemedchem.OEGetRingChainFragments(mol):
    fragatompred = oechem.OEIsAtomMember(frag.GetAtoms())
    fragbondpred = oechem.OEIsBondMember(frag.GetBonds())

    fragment = oechem.OEGraphMol()
    adjustHCount = True
    oechem.OESubsetMol(fragment, mol, fragatompred, fragbondpred, adjustHCount)
    print(oechem.OEMolToSmiles(fragment))
# @ </SNIPPET>
Beispiel #23
0
def get_atom_map(molecule, mapped_smiles, strict=True):
    """
    Map tag in mapped SMILES to atom idx using a substructure search
    A substructure search finds chemically equivalent matches so if atoms are symmetrical, they can flip. The mapped
    SMILES used for the pattern is first used to generate a molecule with the map indices, the order is canonicalized
    and then it is used for the substructure search pattern. This ensures that symmetrical do not flip but there is no
    guarantee that it won't happen.

    Parameters
    ----------
    molecule: oechem.OEMOl
        Must have explicit hydrogen
    mapped_smiles: str
        explicit hydrogen SMILES with map indices on every atom

    Returns
    -------
    atom_map: dict
        {map_idx:atom_idx}

    """
    # check that smiles has explicit hydrogen and map indices
    mapped_mol = oechem.OEMol()
    oechem.OESmilesToMol(mapped_mol, mapped_smiles)
    if not has_atom_map(mapped_mol):
        raise ValueError(
            "Mapped SMILES must have map indices for all atoms and hydrogens")
    # Check molecule for explicit hydrogen
    if not has_explicit_hydrogen(molecule) and strict:
        raise ValueError("Molecule must have explicit hydrogens")

    # canonical order mapped mol to ensure atom map is always generated in the same order
    canonical_order_atoms(mapped_mol)
    aopts = oechem.OEExprOpts_DefaultAtoms
    bopts = oechem.OEExprOpts_DefaultBonds
    ss = oechem.OESubSearch(mapped_mol, aopts, bopts)
    oechem.OEPrepareSearch(molecule, ss)
    ss.SetMaxMatches(1)

    atom_map = {}
    matches = [m for m in ss.Match(molecule)]
    if not matches:
        raise RuntimeError("MCSS failed for {}, smiles: {}".format(
            oechem.OEMolToSmiles(molecule), mapped_smiles))
    for match in matches:
        for ma in match.GetAtoms():
            atom_map[ma.pattern.GetMapIdx()] = ma.target.GetIdx()

    # sanity check
    mol = oechem.OEGraphMol()
    oechem.OESubsetMol(mol, match, True)
    matched_smiles = mol_to_smiles(mol,
                                   isomeric=False,
                                   explicit_hydrogen=False,
                                   mapped=False)
    molcopy = oechem.OEMol(molecule)
    smiles = mol_to_smiles(molcopy,
                           isomeric=False,
                           explicit_hydrogen=False,
                           mapped=False)
    pattern_smiles = mol_to_smiles(mapped_mol,
                                   isomeric=False,
                                   explicit_hydrogen=False,
                                   mapped=False)
    if not matched_smiles == smiles == pattern_smiles:
        raise RuntimeError(
            "Matched molecule, input molecule and mapped SMILES are not the same "
        )
    return atom_map
def generate_restricted_conformers(receptor, refmol, mol, core_smarts=None):
    """
    Generate and select a conformer of the specified molecule using the reference molecule

    Parameters
    ----------
    receptor : openeye.oechem.OEGraphMol
        Receptor (already prepped for docking) for identifying optimal pose
    refmol : openeye.oechem.OEGraphMol
        Reference molecule which shares some part in common with the proposed molecule
    mol : openeye.oechem.OEGraphMol
        Molecule whose conformers are to be enumerated
    core_smarts : str, optional, default=None
        If core_smarts is specified, substructure will be extracted using SMARTS.
    """
    from openeye import oechem, oeomega

    # DEBUG: For benzotriazoles, truncate refmol
    core_smarts = 'c1ccc(NC(=O)[C,N]n2nnc3ccccc32)cc1' # prospective
    core_smarts = 'NC(=O)[C,N]n2nnc3ccccc32' # retrospective

    # Get core fragment
    if core_smarts:
        # Truncate refmol to SMARTS if specified
        #print(f'Trunctating using SMARTS {refmol_smarts}')
        ss = oechem.OESubSearch(core_smarts)
        oechem.OEPrepareSearch(refmol, ss)
        for match in ss.Match(refmol):
            core_fragment = oechem.OEGraphMol()
            oechem.OESubsetMol(core_fragment, match)
            break
        #print(f'refmol has {refmol.NumAtoms()} atoms')
    else:
        core_fragment = GetCoreFragment(refmol, [mol])
        oechem.OESuppressHydrogens(core_fragment)
        #print(f'  Core fragment has {core_fragment.NumAtoms()} heavy atoms')
        MIN_CORE_ATOMS = 6
        if core_fragment.NumAtoms() < MIN_CORE_ATOMS:
            return None

    # Create an Omega instance
    #omegaOpts = oeomega.OEOmegaOptions()
    omegaOpts = oeomega.OEOmegaOptions(oeomega.OEOmegaSampling_Dense)

    # Set the fixed reference molecule
    omegaFixOpts = oeomega.OEConfFixOptions()
    omegaFixOpts.SetFixMaxMatch(10) # allow multiple MCSS matches
    omegaFixOpts.SetFixDeleteH(True) # only use heavy atoms
    omegaFixOpts.SetFixMol(core_fragment)
    #omegaFixOpts.SetFixSmarts(smarts)
    omegaFixOpts.SetFixRMS(0.5)

    atomexpr = oechem.OEExprOpts_Aromaticity | oechem.OEExprOpts_Hybridization
    bondexpr = oechem.OEExprOpts_BondOrder | oechem.OEExprOpts_Aromaticity
    omegaFixOpts.SetAtomExpr(atomexpr)
    omegaFixOpts.SetBondExpr(bondexpr)
    omegaOpts.SetConfFixOptions(omegaFixOpts)

    molBuilderOpts = oeomega.OEMolBuilderOptions()
    molBuilderOpts.SetStrictAtomTypes(False) # don't give up if MMFF types are not found
    omegaOpts.SetMolBuilderOptions(molBuilderOpts)

    omegaOpts.SetWarts(False) # expand molecule title
    omegaOpts.SetStrictStereo(False) # set strict stereochemistry
    omegaOpts.SetIncludeInput(False) # don't include input
    omegaOpts.SetMaxConfs(1000) # generate lots of conformers
    #omegaOpts.SetEnergyWindow(10.0) # allow high energies
    omega = oeomega.OEOmega(omegaOpts)

    from openeye import oequacpac
    if not oequacpac.OEGetReasonableProtomer(mol):
        print('No reasonable protomer found')
        return None

    mol = oechem.OEMol(mol) # multi-conformer molecule

    ret_code = omega.Build(mol)
    if (mol.GetDimension() != 3) or (ret_code != oeomega.OEOmegaReturnCode_Success):
        print(f'Omega failure: {mol.GetDimension()} and {oeomega.OEGetOmegaError(ret_code)}')
        return None

    # Extract poses
    class Pose(object):
        def __init__(self, conformer):
            self.conformer = conformer
            self.clash_score = None
            self.docking_score = None
            self.overlap_score = None

    poses = [ Pose(conf) for conf in mol.GetConfs() ]

    # Score clashes
    bump_check = BumpCheck(receptor)
    for pose in poses:
        pose.clash_score = bump_check.count(pose.conformer)

    # Score docking poses
    from openeye import oedocking
    score = oedocking.OEScore(oedocking.OEScoreType_Chemgauss4)
    score.Initialize(receptor)
    for pose in poses:
        pose.docking_score = score.ScoreLigand(pose.conformer)

    # Compute overlap scores
    from openeye import oeshape
    overlap_prep = oeshape.OEOverlapPrep()
    overlap_prep.Prep(refmol)
    shapeFunc = oeshape.OEExactShapeFunc()
    shapeFunc.SetupRef(refmol)
    oeshape_result = oeshape.OEOverlapResults()
    for pose in poses:
        tmpmol = oechem.OEGraphMol(pose.conformer)
        overlap_prep.Prep(tmpmol)
        shapeFunc.Overlap(tmpmol, oeshape_result)
        pose.overlap_score = oeshape_result.GetRefTversky()

    # Filter poses based on top 10% of overlap
    poses = sorted(poses, key= lambda pose : pose.overlap_score)
    poses = poses[int(0.9*len(poses)):]

    # Select the best docking score
    import numpy as np
    poses = sorted(poses, key=lambda pose : pose.docking_score)
    pose = poses[0]
    mol.SetActive(pose.conformer)
    oechem.OESetSDData(mol, 'clash_score', str(pose.clash_score))
    oechem.OESetSDData(mol, 'docking_score', str(pose.docking_score))
    oechem.OESetSDData(mol, 'overlap_score', str(pose.overlap_score))

    # Convert to single-conformer molecule
    mol = oechem.OEGraphMol(mol)

    return mol
Beispiel #25
0
def oesolvate(solute,
              density=1.0,
              padding_distance=10.0,
              distance_between_atoms=2.5,
              solvents='tip3p',
              molar_fractions='1.0',
              geometry='box',
              close_solvent=True,
              salt='[Na+], [Cl-]',
              salt_concentration=0.0,
              neutralize_solute=True,
              verbose=False,
              return_components=False,
              **kargs):
    """
    This function solvates the passed solute in a cubic box or a sphere by using Packmol. Packmol
    creates an initial point for molecular dynamics simulations by packing molecule in defined regions
    of space. For additional info:
    http://www.ime.unicamp.br/~martinez/packmol/home.shtml

    The geometry volume is estimated by the using the padding parameter and the solute size.
    The number of solvent molecules is calculated by using the specified density and volume.
    Solvent molecules are specified as comma separated smiles strings. The molar fractions
    of each solvent molecule are specified in a similar fashion. By default if the solute is
    charged counter ions are added to neutralize it

    Parameters:
    -----------
    solute: OEMol molecule
        The solute to solvate
    density: float
        The solution density in g/ml
    padding_distance: float
        The largest dimension of the solute (along the x, y, or z axis) is determined (in A), 
        and a cubic box of size (largest dimension)+2*padding is used
    distance_between_atoms: float
        The minimum distance between atoms in A
    solvents: python string
        A comma separated smiles string or keywords for the solvent molecules.
        Special water models can be selected by using the keywords:
        tip3p for TIP3P water model geometry
    molar_fractions: python string
        A comma separated molar fraction string of the solvent molecules
    close_solvent: boolean
        If True solvent molecules will be placed very close to the solute
    salt: python string
        A comma separated string of the dissociated salt in solution
    salt_concentration: float
        Salt concentration in millimolar
    neutralize_solute: boolean
        If True counter-ions will be added to the solution to neutralize the solute
    verbose: Bool
        If True verbose mode is enabled
    return_components: Bool
        If True the added solvent molecules are also returned as OEMol

    Return:
    -------
    oe_mol: OEMol
        The solvated system. If the selected geometry is a box a SD tag with
        name 'box_vector' is attached the output molecule containing
        the system box vectors.
    oe_mol_components: OEMol
        If the return_components flag is True the added solvent molecules are
        returned as an additional OEMol
    """
    def BoundingBox(molecule):
        """
        This function calculates the Bounding Box of the passed
        molecule

        molecule: OEMol

        return: bb (numpy array)
            the calculated bounding box is returned as numpy array:
            [(xmin,ymin,zmin), (xmax,ymax,zmax)]
        """
        coords = [v for k, v in molecule.GetCoords().items()]
        np_coords = np.array(coords)
        min_coord = np_coords.min(axis=0)
        max_coord = np_coords.max(axis=0)
        bb = np.array([min_coord, max_coord])
        return bb

    if shutil.which("packmol") is None:
        raise (IOError("Packmol executable not found"))

    # Extract solvent smiles strings and mole fractions
    solvents = [sm.strip() for sm in solvents.split(',')]
    fractions = [float(mf) for mf in molar_fractions.split(',')]

    # If the smiles string and mole fractions lists have different lengths raise an error
    if len(solvents) != len(fractions):
        raise ValueError(
            "Selected solvent number and selected molar fraction number mismatch: {} vs {}"
            .format(len(solvents), len(fractions)))

    # Remove smiles string with 0.0 mole fraction
    solvent_smiles = [
        solvents[i] for i, v in enumerate(fractions) if fractions[i]
    ]
    mol_fractions = [mf for mf in fractions if mf]

    # Mole fractions are non-negative numbers
    if any([v < 0.0 for v in mol_fractions]):
        raise ValueError("Error: Mole fractions are non-negative real numbers")

    # Mole fractions must sum up to 1.0
    if abs(sum(mol_fractions) - 1.0) > 0.001:
        oechem.OEThrow.Error("Error: Mole fractions do not sum up to 1.0")

    if geometry not in ['box', 'sphere']:
        raise ValueError(
            "Error geometry: the supported geometries are box and sphere not {}"
            .format(geometry))

    # Set Units
    density = density * unit.grams / unit.milliliter
    padding_distance = padding_distance * unit.angstrom
    salt_concentration = salt_concentration * unit.millimolar

    # Calculate the Solute Bounding Box
    BB_solute = BoundingBox(solute)

    # Estimate of the box cube length
    box_edge = 2.0 * padding_distance + np.max(BB_solute[1] -
                                               BB_solute[0]) * unit.angstrom

    if geometry == 'box':
        # Box Volume
        Volume = box_edge**3
    if geometry == 'sphere':
        Volume = (4.0 / 3.0) * 3.14159265 * (0.5 * box_edge)**3

    # Omega engine is used to generate conformations
    omegaOpts = oeomega.OEOmegaOptions()
    omegaOpts.SetMaxConfs(1)
    omegaOpts.SetStrictStereo(False)
    omega = oeomega.OEOmega(omegaOpts)

    # Create a string code to identify the solute residues. The code ID used is based
    # on the residue number id, the residue name and the chain id:
    # id+resname+chainID
    hv_solute = oechem.OEHierView(
        solute,
        oechem.OEAssumption_BondedResidue + oechem.OEAssumption_ResPerceived)
    solute_resid_list = []
    for chain in hv_solute.GetChains():
        for frag in chain.GetFragments():
            for hres in frag.GetResidues():
                oe_res = hres.GetOEResidue()
                solute_resid_list.append(
                    str(oe_res.GetResidueNumber()) + oe_res.GetName() +
                    chain.GetChainID())

    # Solvent component list_names
    solvent_resid_dic_names = dict()

    # Neutralize solute
    ion_sum_wgt_n_ions = 0.0 * unit.grams / unit.mole
    if neutralize_solute:
        # Container for the counter-ions
        oe_ions = []
        # Container for the ion smiles strings
        ions_smiles = []
        solute_formal_charge = 0
        for at in solute.GetAtoms():
            solute_formal_charge += at.GetFormalCharge()
        if solute_formal_charge > 0:
            ions_smiles.append("[Cl-]")
        elif solute_formal_charge < 0:
            ions_smiles.append("[Na+]")
        else:
            pass

        # Total number of counter-ions to neutralize the solute
        n_ions = abs(solute_formal_charge)

        # print("Counter ions to add = {} of {}".format(n_ions, ions_smiles[0]))

        # Ions
        if n_ions >= 1:
            for sm in ions_smiles:
                mol = oechem.OEMol()
                if not oechem.OESmilesToMol(mol, sm):
                    raise ValueError(
                        "Error counter ions: SMILES string parsing fails for the string: {}"
                        .format(sm))

                # Generate conformer
                if not omega(mol):
                    raise ValueError(
                        "Error counter ions: Conformer generation fails for the molecule with "
                        "smiles string: {}".format(sm))

                oe_ions.append(mol)

                if sm == '[Na+]':
                    solvent_resid_dic_names[' NA'] = mol
                else:
                    solvent_resid_dic_names[' CL'] = mol

            ion_sum_wgt = 0.0 * unit.grams / unit.mole
            for ion in oe_ions:
                # Molecular weight
                ion_sum_wgt += oechem.OECalculateMolecularWeight(
                    ion) * unit.grams / unit.mole

            ion_sum_wgt_n_ions = ion_sum_wgt * n_ions

            # Create ions .pdb files
            ions_smiles_pdbs = []
            for i in range(0, len(ions_smiles)):
                pdb_name = os.path.basename(tempfile.mktemp(suffix='.pdb'))
                pdb_name = ions_smiles[i] + '_' + pdb_name
                ions_smiles_pdbs.append(pdb_name)

            for i in range(0, len(ions_smiles)):
                ofs = oechem.oemolostream(ions_smiles_pdbs[i])
                oechem.OEWriteConstMolecule(ofs, oe_ions[i])

    # Add salts to the solution

    # Solvent smiles string parsing
    char_set = string.ascii_uppercase
    salt_sum_wgt_n_salt = 0.0 * unit.grams / unit.mole
    if salt_concentration > 0.0 * unit.millimolar:

        salt_smiles = [sm.strip() for sm in salt.split(',')]

        # Container list of oemol salt molecules generated by using smiles strings
        oe_salt = []

        for sm in salt_smiles:
            mol_salt = oechem.OEMol()
            if not oechem.OESmilesToMol(mol_salt, sm):
                raise ValueError(
                    "Error salt: SMILES string parsing fails for the string: {}"
                    .format(sm))

            # Generate conformer
            if not omega(mol_salt):
                raise ValueError(
                    "Error salt: Conformer generation fails for the "
                    "molecule with smiles string: {}".format(sm))

            # Unique 3 code letter are set as solvent residue names
            solv_id = ''.join(random.sample(char_set * 3, 3))

            # Try to recognize the residue name
            oechem.OEPerceiveResidues(mol_salt)

            for atmol in mol_salt.GetAtoms():
                res = oechem.OEAtomGetResidue(atmol)
                if res.GetName() == 'UNL':
                    res.SetName(solv_id)
                    oechem.OEAtomSetResidue(atmol, res)
                    if solv_id not in solvent_resid_dic_names:
                        solvent_resid_dic_names[solv_id] = mol_salt
                else:
                    if res.GetName() not in solvent_resid_dic_names:
                        solvent_resid_dic_names[res.GetName()] = mol_salt
                    break

            oe_salt.append(mol_salt)

        n_salt = int(
            round(unit.AVOGADRO_CONSTANT_NA * salt_concentration *
                  Volume.in_units_of(unit.liter)))

        # for i in range(0, len(salt_smiles)):
        #     print("Number of molecules for the salt component {} = {}".format(salt_smiles[i], n_salt))

        salt_sum_wgt = 0.0 * unit.grams / unit.mole
        for salt in oe_salt:
            # Molecular weight
            salt_sum_wgt += oechem.OECalculateMolecularWeight(
                salt) * unit.grams / unit.mole

        salt_sum_wgt_n_salt = salt_sum_wgt * n_salt

        # Create salt .pdb files
        if n_salt >= 1:
            salt_pdbs = []
            for i in range(0, len(salt_smiles)):
                pdb_name = os.path.basename(tempfile.mktemp(suffix='.pdb'))
                # pdb_name = salt_smiles[i] + '_' + pdb_name
                salt_pdbs.append(pdb_name)

            for i in range(0, len(salt_smiles)):
                ofs = oechem.oemolostream(salt_pdbs[i])
                oechem.OEWriteConstMolecule(ofs, oe_salt[i])

    # Container list of oemol solvent molecules generated by using smiles strings
    oe_solvents = []

    for sm in solvent_smiles:

        if sm == 'tip3p':
            tip3p_fn = os.path.join(PACKAGE_DIR, 'oeommtools', 'data',
                                    'tip3p.pdb')
            ifs = oechem.oemolistream(tip3p_fn)
            mol_sol = oechem.OEMol()

            if not oechem.OEReadMolecule(ifs, mol_sol):
                raise IOError(
                    "It was not possible to read the tip3p molecule file")
        else:

            mol_sol = oechem.OEMol()

            if not oechem.OESmilesToMol(mol_sol, sm):
                raise ValueError(
                    "Error solvent: SMILES string parsing fails for the string: {}"
                    .format(sm))

            # Generate conformer
            if not omega(mol_sol):
                raise ValueError(
                    "Error solvent: Conformer generation fails for "
                    "the molecule with smiles string: {}".format(sm))

        # Unique 3 code letter are set as solvent residue names
        solv_id = ''.join(random.sample(char_set * 3, 3))

        # Try to recognize the residue name
        oechem.OEPerceiveResidues(mol_sol)

        for atmol in mol_sol.GetAtoms():
            res = oechem.OEAtomGetResidue(atmol)
            if res.GetName() == 'UNL':
                res.SetName(solv_id)
                oechem.OEAtomSetResidue(atmol, res)
                if solv_id not in solvent_resid_dic_names:
                    solvent_resid_dic_names[solv_id] = mol_sol
            else:
                if res.GetName() not in solvent_resid_dic_names:
                    solvent_resid_dic_names[res.GetName()] = mol_sol
                break

        oe_solvents.append(mol_sol)

    # Sum of the solvent molecular weights
    solvent_sum_wgt_frac = 0.0 * unit.grams / unit.mole

    for idx in range(0, len(oe_solvents)):
        # Molecular weight
        wgt = oechem.OECalculateMolecularWeight(
            oe_solvents[idx]) * unit.grams / unit.mole
        solvent_sum_wgt_frac += wgt * mol_fractions[idx]

    # Solute molecular weight
    solute_wgt = oechem.OECalculateMolecularWeight(
        solute) * unit.gram / unit.mole

    # Estimate of the number of each molecular species present in the solution accordingly
    # to their molar fraction fi:
    #
    # ni = fi*(density*volume*NA - wgt_solute - sum_k(wgt_salt_k*nk) - wgt_ion*n_ion)/sum_j(wgt_nj * fj)
    #
    # where ni is the number of molecule of specie i, density the mixture density, volume the
    # mixture volume, wgt_solute the molecular weight of the solute, wgt_salt_k the molecular
    # weight of the salt component k, nk the number of molecule of salt component k, wgt_ion
    # the counter ion molecular weight, n_ions the number of counter ions and wgt_nj the molecular
    # weight of the molecule specie j with molar fraction fj

    div = (unit.AVOGADRO_CONSTANT_NA * density * Volume -
           (solute_wgt + salt_sum_wgt_n_salt +
            ion_sum_wgt_n_ions)) / solvent_sum_wgt_frac

    # Solvent number of monomers
    n_monomers = [int(round(mf * div)) for mf in mol_fractions]

    if not all([nm > 0 for nm in n_monomers]):
        raise ValueError(
            "Error negative number of solvent components: the density could be too low"
        )

    # for i in range(0, len(solvent_smiles)):
    #     print("Number of molecules for the component {} = {}".format(solvent_smiles[i], n_monomers[i]))

    # Packmol Configuration file setting
    if close_solvent:
        header_template = """\n# Mixture\ntolerance {}\nfiletype pdb\noutput {}\nadd_amber_ter\navoid_overlap no"""
    else:
        header_template = """\n# Mixture\ntolerance {}\nfiletype pdb\noutput {}\nadd_amber_ter\navoid_overlap yes"""

    # Templates strings
    solute_template = """\n\n# Solute\nstructure {}\nnumber 1\nfixed 0. 0. 0. 0. 0. 0.\nresnumbers 1\nend structure"""

    if geometry == 'box':
        solvent_template = """\nstructure {}\nnumber {}\ninside box {:0.3f} {:0.3f} {:0.3f} {:0.3f} {:0.3f} {:0.3f}\
        \nchain !\nresnumbers 3\nend structure"""
    if geometry == 'sphere':
        solvent_template = """\nstructure {}\nnumber {}\ninside sphere {:0.3f} {:0.3f} {:0.3f} {:0.3f}\
        \nchain !\nresnumbers 3\nend structure"""

    # Create solvents .pdb files
    solvent_pdbs = []
    for i in range(0, len(solvent_smiles)):
        pdb_name = os.path.basename(tempfile.mktemp(suffix='.pdb'))
        solvent_pdbs.append(pdb_name)

    for i in range(0, len(solvent_smiles)):
        ofs = oechem.oemolostream(solvent_pdbs[i])
        oechem.OEWriteConstMolecule(ofs, oe_solvents[i])

    solute_pdb = 'solute' + '_' + os.path.basename(
        tempfile.mktemp(suffix='.pdb'))
    ofs = oechem.oemolostream(solute_pdb)

    if solute.GetMaxConfIdx() > 1:
        raise ValueError("Solutes with multiple conformers are not supported")
    else:
        oechem.OEWriteConstMolecule(ofs, solute)

    # Write Packmol header section
    mixture_pdb = 'mixture' + '_' + os.path.basename(
        tempfile.mktemp(suffix='.pdb'))
    body = header_template.format(distance_between_atoms, mixture_pdb)
    # Write Packmol configuration file solute section
    body += solute_template.format(solute_pdb)

    # The solute is centered inside the box
    xc = (BB_solute[0][0] + BB_solute[1][0]) / 2.
    yc = (BB_solute[0][1] + BB_solute[1][1]) / 2.
    zc = (BB_solute[0][2] + BB_solute[1][2]) / 2.

    # Correct for periodic box conditions to avoid
    # steric clashes at the box edges
    pbc_correction = 1.0 * unit.angstrom

    xmin = xc - ((box_edge - pbc_correction) / 2.) / unit.angstrom
    xmax = xc + ((box_edge - pbc_correction) / 2.) / unit.angstrom
    ymin = yc - ((box_edge - pbc_correction) / 2.) / unit.angstrom
    ymax = yc + ((box_edge - pbc_correction) / 2.) / unit.angstrom
    zmin = zc - ((box_edge - pbc_correction) / 2.) / unit.angstrom
    zmax = zc + ((box_edge - pbc_correction) / 2.) / unit.angstrom

    # Packmol setting for the solvent section
    body += '\n\n# Solvent'
    for i in range(0, len(solvent_smiles)):
        if geometry == 'box':
            body += solvent_template.format(solvent_pdbs[i], n_monomers[i],
                                            xmin, ymin, zmin, xmax, ymax, zmax)
        if geometry == 'sphere':
            body += solvent_template.format(solvent_pdbs[i], n_monomers[i], xc,
                                            yc, zc,
                                            0.5 * box_edge / unit.angstrom)

    # Packmol setting for the salt section
    if salt_concentration > 0.0 * unit.millimolar and n_salt >= 1:
        body += '\n\n# Salt'
        for i in range(0, len(salt_smiles)):
            if geometry == 'box':
                body += solvent_template.format(salt_pdbs[i],
                                                int(round(n_salt)), xmin, ymin,
                                                zmin, xmax, ymax, zmax)
            if geometry == 'sphere':
                body += solvent_template.format(salt_pdbs[i],
                                                int(round(n_salt)), xc, yc, zc,
                                                0.5 * box_edge / unit.angstrom)

    # Packmol setting for the ions section
    if neutralize_solute and n_ions >= 1:
        body += '\n\n# Counter Ions'
        for i in range(0, len(ions_smiles)):
            if geometry == 'box':
                body += solvent_template.format(ions_smiles_pdbs[i], n_ions,
                                                xmin, ymin, zmin, xmax, ymax,
                                                zmax)
            if geometry == 'sphere':
                body += solvent_template.format(ions_smiles_pdbs[i], n_ions,
                                                xc, yc, zc,
                                                0.5 * box_edge / unit.angstrom)

    # Packmol configuration file
    packmol_filename = os.path.basename(tempfile.mktemp(suffix='.inp'))

    with open(packmol_filename, 'w') as file_handle:
        file_handle.write(body)

    # Call Packmol
    if not verbose:
        mute_output = open(os.devnull, 'w')
        with open(packmol_filename, 'r') as file_handle:
            subprocess.check_call(['packmol'],
                                  stdin=file_handle,
                                  stdout=mute_output,
                                  stderr=mute_output)
    else:
        with open(packmol_filename, 'r') as file_handle:
            subprocess.check_call(['packmol'], stdin=file_handle)

    # Read in the Packmol solvated system
    solvated = oechem.OEMol()

    if os.path.exists(mixture_pdb + '_FORCED'):
        os.rename(mixture_pdb + '_FORCED', mixture_pdb)
        print("Warning: Packing solution is not optimal")

    ifs = oechem.oemolistream(mixture_pdb)
    oechem.OEReadMolecule(ifs, solvated)

    # To avoid to change the user oemol starting solute by reading in
    # the generated mixture pdb file and loosing molecule info, the
    # solvent molecules are extracted from the mixture system and
    # added back to the starting solute

    # Extract from the solution system the solvent molecules
    # by checking the previous solute generated ID: id+resname+chainID
    hv_solvated = oechem.OEHierView(
        solvated,
        oechem.OEAssumption_BondedResidue + oechem.OEAssumption_ResPerceived)

    # This molecule will hold the solvent molecules generated directly from
    # the omega conformers. This is useful to avoid problems related to read in
    # the solvent molecules from pdb files and triggering unwanted perceiving actions
    new_components = oechem.OEMol()

    bv = oechem.OEBitVector(solvated.GetMaxAtomIdx())
    for chain in hv_solvated.GetChains():
        for frag in chain.GetFragments():
            for hres in frag.GetResidues():
                oe_res = hres.GetOEResidue()
                if str(oe_res.GetResidueNumber()) + oe_res.GetName(
                ) + chain.GetChainID() not in solute_resid_list:
                    oechem.OEAddMols(new_components,
                                     solvent_resid_dic_names[oe_res.GetName()])
                    atms = hres.GetAtoms()
                    for at in atms:
                        bv.SetBitOn(at.GetIdx())

    pred = oechem.OEAtomIdxSelected(bv)
    components = oechem.OEMol()
    oechem.OESubsetMol(components, solvated, pred)

    new_components.SetCoords(components.GetCoords())

    # This is necessary otherwise just one big residue is created
    oechem.OEPerceiveResidues(new_components)

    # Add the solvent molecules to the solute copy
    solvated_system = solute.CreateCopy()
    oechem.OEAddMols(solvated_system, new_components)

    # Set Title
    solvated_system.SetTitle(solute.GetTitle())

    # Set ions resname to Na+ and Cl-
    for at in solvated_system.GetAtoms():
        res = oechem.OEAtomGetResidue(at)
        if res.GetName() == ' NA':
            res.SetName("Na+")
            oechem.OEAtomSetResidue(atmol, res)
        elif res.GetName() == ' CL':
            res.SetName("Cl-")
            oechem.OEAtomSetResidue(atmol, res)
        else:
            pass

    # Cleaning
    to_delete = solvent_pdbs + [packmol_filename, solute_pdb, mixture_pdb]

    if salt_concentration > 0.0 * unit.millimolar and n_salt >= 1:
        to_delete += salt_pdbs
    if neutralize_solute and n_ions >= 1:
        to_delete += ions_smiles_pdbs

    for fn in to_delete:
        try:
            os.remove(fn)
        except:
            pass

    # Calculate the solution total density
    total_wgt = oechem.OECalculateMolecularWeight(
        solvated_system) * unit.gram / unit.mole
    density_mix = (1 / unit.AVOGADRO_CONSTANT_NA) * total_wgt / Volume
    print("Computed Solution Density = {}".format(
        density_mix.in_units_of(unit.gram / unit.milliliter)))
    # Threshold checking
    ths = 0.1 * unit.gram / unit.milliliter
    if not abs(density -
               density_mix.in_units_of(unit.gram / unit.milliliter)) < ths:
        raise ValueError(
            "Error: the computed density for the solute {} does not match the selected density {} vs {}"
            .format(solute.GetTitle(), density_mix, density))

    if geometry == 'box':
        # Define the box vector and attached it as SD tag to the solvated system
        # with ID tag: 'box_vectors'
        box_vectors = (Vec3(box_edge / unit.angstrom, 0.0,
                            0.0), Vec3(0.0, box_edge / unit.angstrom, 0.0),
                       Vec3(0.0, 0.0,
                            box_edge / unit.angstrom)) * unit.angstrom

        box_vectors = data_utils.encodePyObj(box_vectors)
        solvated_system.SetData(oechem.OEGetTag('box_vectors'), box_vectors)

    if return_components:
        new_components.SetTitle(solute.GetTitle() + '_solvent_comp')
        return solvated_system, new_components
    else:
        return solvated_system
def PrepareReceptor(pdb,padding=4,outpath=""):
    """
    Prepares a receptor from a pdb with a crystalized ligand
    Padding controls the docking region.
    If outpath is given, PrepareReceptor will write an openeye binary (oeb) of the receptor structure. This will be faster than rebuilding the receptor every time.
    """
    print("STOP CALLING THIS FUNCTION")
    exit()
    com = oechem.OEGraphMol()
    ifs = oechem.oemolistream()
    if ifs.open(pdb):
        oechem.OEReadPDBFile(ifs, com)
        ifs.close()

    """
    Sorry, this requires some explanation. Openeye wasn't recognizing the previously docked ligand, so I tried to find other ways.
    The next blocks of code take our system and split it based on its connected components, for which its REQUIRED that our protein
      only has a single chain. It assumes that the last component is the ligand. It then creates the ligand (lig) and protein (prot)
      as separate molecules. Next, it finds the minimum and maximum 3D coordinates of the current ligand and produces a box around
      it with the specified padding. Finally it uses this box to create a 'receptor' object into which ligands can be docked.
    Only the receptor is returned.
    Openeye's docking shouldn't be this involved, but I couldn't get it to run the typical 'hybrid' docking without error.
    """
    oechem.OEDetermineConnectivity(com)
    nparts, connect = oechem.OEDetermineComponents(com)
    if(nparts != 2):
        print("ERR in dock_conf::prepareReceptor. PDB doesn't have 2 connected components")
        exit()
        ## TODO: What is a good way to catch errors?
    # Get apo
    pred = oechem.OEPartPredAtom(connect)
    pred.SelectPart(nparts)
    lig = oechem.OEGraphMol()
    oechem.OESubsetMol(lig, com, pred)
    print(lig)
    
    # Get protein
    pred = oechem.OEPartPredAtom(connect)
    pred.SelectPart(1)
    prot = oechem.OEGraphMol()
    oechem.OESubsetMol(prot, com, pred)
    
    # Get box dimensions by iterating over ligand
    x_min = y_min = z_min = float('inf')
    x_max = y_max = z_max = -float('inf')
    crd = lig.GetCoords()
    print("CRD", crd)
    for atm in crd:
        x,y,z = crd[atm]
        if x < x_min:
            x_min = x
        if y < y_min:
            y_min = y
        if z < z_min:
            z_min = z
        if x > x_max:
            x_max = x
        if y > y_max:
            y_max = y
        if z > z_max:
            z_max = z
    x_min -= padding
    y_min -= padding
    z_min -= padding
    x_max += padding
    y_max += padding
    z_max += padding
    print(x_min,y_min,z_max, y_max)
    # Now prepare the receptor
    receptor = oechem.OEGraphMol()
    box = oedocking.OEBox()
    box.Setup(x_max, y_max, z_max, x_min, y_min, z_min)
    oedocking.OEMakeReceptor(receptor, prot, box)
    
    if not outpath == "":
        oedocking.OEWriteReceptorFile(receptor,f'{outpath}/receptor.oeb')
    return receptor
def _extract_oe_fragment(
    molecule: Molecule, atom_indices: Set[int], bond_indices: Set[Tuple[int, int]]
) -> Molecule:

    from openeye import oechem

    oe_molecule = molecule.to_openeye()

    # Restore the map indices as to_openeye does not automatically add them.
    for atom_index, map_index in molecule.properties["atom_map"].items():

        oe_atom = oe_molecule.GetAtom(oechem.OEHasAtomIdx(atom_index))
        oe_atom.SetMapIdx(map_index)

    # Include any Hs bonded to the included atom set so we can retain their map
    # indices.
    for map_index in {*atom_indices}:

        oe_atom = oe_molecule.GetAtom(oechem.OEHasMapIdx(map_index))

        for neighbour in oe_atom.GetAtoms():

            if (
                neighbour.GetAtomicNum() != 1
                or neighbour.GetMapIdx() < 1
                or neighbour.GetMapIdx() in atom_indices
            ):
                continue

            atom_indices.add(neighbour.GetMapIdx())
            bond_indices.add((map_index, neighbour.GetMapIdx()))

    atom_bond_set = oechem.OEAtomBondSet()

    for map_index in atom_indices:
        atom = oe_molecule.GetAtom(oechem.OEHasMapIdx(map_index))
        atom_bond_set.AddAtom(atom)

    for map_index_1, map_index_2 in bond_indices:

        atom_1 = oe_molecule.GetAtom(oechem.OEHasMapIdx(map_index_1))
        atom_2 = oe_molecule.GetAtom(oechem.OEHasMapIdx(map_index_2))

        bond = oe_molecule.GetBond(atom_1, atom_2)

        if not bond:
            raise ValueError(f"{(map_index_1, map_index_2)} is a disconnected bond")

        atom_bond_set.AddBond(bond)

    atom_predicate = oechem.OEIsAtomMember(atom_bond_set.GetAtoms())
    bond_predicate = oechem.OEIsBondMember(atom_bond_set.GetBonds())

    fragment = oechem.OEMol()
    oechem.OESubsetMol(fragment, oe_molecule, atom_predicate, bond_predicate, True)

    oechem.OEAddExplicitHydrogens(fragment)
    oechem.OEPerceiveChiral(fragment)

    # Always restore map?
    # if restore_maps:
    # In some cases (symmetric molecules) this changes the atom map so skip it
    # restore_atom_map(fragment)
    # atom map should be restored for combinatorial fragmentation
    # Perceive stereo and check that defined stereo did not change
    oechem.OEPerceiveChiral(fragment)
    oechem.OE3DToAtomStereo(fragment)
    oechem.OE3DToBondStereo(fragment)

    return Molecule.from_openeye(fragment, allow_undefined_stereo=True)
Beispiel #28
0
pattern = oechem.OEGraphMol()
target = oechem.OEGraphMol()
oechem.OESmilesToMol(pattern, "c1(cc(nc2c1C(CCC2)Cl)CCl)O")
oechem.OESmilesToMol(target, "c1(c2c(nc(n1)CF)COC=C2)N")

# @ <SNIPPET-EXPR>
atomexpr = oechem.OEExprOpts_DefaultAtoms
bondexpr = oechem.OEExprOpts_DefaultBonds
# @ </SNIPPET-EXPR>

patternQ = oechem.OEQMol(pattern)
# generate query with atom and bond expression options
# @ <SNIPPET-BUILDEXPR>
patternQ.BuildExpressions(atomexpr, bondexpr)
# @ </SNIPPET-BUILDEXPR>
mcss = oechem.OEMCSSearch(patternQ)

unique = True
count = 1
# loop over matches
for match in mcss.Match(target, unique):
    print("Match %d:" % count)
    print("Number of matched atoms: %d" % match.NumAtoms())
    print("Number of matched bonds: %d" % match.NumBonds())
    # create match subgraph
    m = oechem.OEGraphMol()
    oechem.OESubsetMol(m, match, True)
    print("match smiles = %s" % oechem.OEMolToSmiles(m))
    count += 1
# @ </SNIPPET>
# TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
# provided to current licensees or subscribers of OpenEye products or
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. OpenEye claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable OpenEye offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
# liable for any damages or liability in connection with the Sample Code
# or its use.

# @ <SNIPPET>
from __future__ import print_function
from openeye import oechem
from openeye import oemedchem

mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "CCOc1ccc(cc1)CC(OC)c2ccccc2CC(=O)N")

adjustHCount = True
for frag in oemedchem.OEGetBemisMurcko(mol):
    fragment = oechem.OEGraphMol()
    oechem.OESubsetMol(fragment, mol, frag, adjustHCount)
    print(".".join(r.GetName() for r in frag.GetRoles()),
          oechem.OEMolToSmiles(fragment))
# @ </SNIPPET>
def main(argv=[__name__]):
    itf = oechem.OEInterface(InterfaceData, argv)

    # flag on command line indicates uncoloring option or not
    bUncolor = itf.GetBool("-uncolor")

    # input structure(s) to transform
    ifsmols = oechem.oemolistream()
    if not ifsmols.open(itf.GetString("-i")):
        oechem.OEThrow.Fatal("Unable to open %s for reading" %
                             itf.GetString("-i"))

    # save output structure(s) to this file
    ofs = oechem.oemolostream()
    if not ofs.open(itf.GetString("-o")):
        oechem.OEThrow.Fatal("Unable to open %s for writing" %
                             itf.GetString("-o"))
    if not oechem.OEIsSDDataFormat(ofs.GetFormat()):
        oechem.OEThrow.Fatal("Unable to open %s for writing" %
                             itf.GetString("-o"))

    irec = 0
    ototal = 0
    frag = oechem.OEGraphMol()
    for mol in ifsmols.GetOEGraphMols():
        irec += 1
        oechem.OEDeleteEverythingExceptTheFirstLargestComponent(mol)
        iter = oemedchem.OEGetBemisMurcko(mol)
        if not iter.IsValid():
            name = mol.GetTitle()
            if not mol.GetTitle():
                name = 'Record ' + str(irec)
            oechem.OEThrow.Warning("%s: no perceived regions" % name)
            continue
        for bmregion in iter:
            # create a fragment from the perceived region
            oechem.OESubsetMol(frag, mol, bmregion, True)
            if bUncolor:
                # ignore 3D stereo parities
                if (frag.GetDimension() == 3):
                    frag.SetDimension(0)
                # uncolor the fragment
                oechem.OEUncolorMol(frag)
            smi = oechem.OEMolToSmiles(frag)
            # annotate the input molecule with the role information
            for role in bmregion.GetRoles():
                oechem.OEAddSDData(mol, role.GetName(), smi)
        ototal += 1
        oechem.OEWriteMolecule(ofs, mol)

    if not irec:
        oechem.OEThrow.Fatal('No records in input structure file to perceive')

    if not ototal:
        oechem.OEThrow.Warning('No annotated structures generated')

    print(
        "Input molecules={0:d}, output annotated {1:s}molecules={2:d}".format(
            irec, ("(uncolored) " if bUncolor else ""), ototal))

    return 0