Ejemplo n.º 1
0
def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <input> <output>" % args[0])

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

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

    mmff = oeff.OEMMFF()

    # Setup adaptor. The first (false) means not to pass ownership of mmff,
    # and the second (false) means not to exclude interactions related
    # to the subset which would be fixed for calculations.
    adaptor = oeff.OETorAdaptor(mmff, False, False)

    # Use a simple predicate for the subset of torsions to optimize
    adaptor.Set(oechem.OEIsRotor())

    mol = oechem.OEMol()
    while oechem.OEReadMolecule(ifs, mol):
        oechem.OEAddExplicitHydrogens(mol)

        # Use a simple atoms predicate for the subset, followed by setup
        if (not mmff.PrepMol(mol)) or (not adaptor.Setup(mol)):
            oechem.OEThrow.Warning("Unable to process molecule: title = '%s'" % mol.GetTitle())
            oechem.OEWriteMolecule(ofs, mol)
            continue

        vecCoords = oechem.OEDoubleArray(3*mol.GetMaxAtomIdx())
        for conf in mol.GetConfs():
            oechem.OEThrow.Info("Molecule: %s Conformer: %d" % (mol.GetTitle(), conf.GetIdx()+1))
            conf.GetCoords(vecCoords)

            # Get adaptor variables set corresponding to the coordinates
            vecX = oechem.OEDoubleArray(adaptor.NumVar())
            adaptor.GetVar(vecX, vecCoords)

            # Calculate energy using adaptor
            energy = adaptor(vecX)
            oechem.OEThrow.Info("Initial energy: %d kcal/mol" % energy)

            # Optimize the adaptor
            optimizer = oeff.OEBFGSOpt()
            energy = optimizer(adaptor, vecX, vecX)
            oechem.OEThrow.Info("Optimized energy: %d kcal/mol" % energy)

            # Get optimized coordinates corresponding to the adaptor optimized variables
            adaptor.AdaptVar(vecCoords, vecX)
            conf.SetCoords(vecCoords)

        oechem.OEWriteMolecule(ofs, mol)

    return 0
Ejemplo n.º 2
0
def gen_starting_confs(mol, torsion_library, max_one_bond_away=True, 
                       num_conformers=MAX_CONFS, rms_cutoff=0.0, energy_window=25):

    # Identify the atoms in the dihedral
    TAGNAME = 'TORSION_ATOMS_FRAGMENT'
    if not has_sd_data(mol, TAGNAME):
        raise ValueError("Molecule does not have the SD Data Tag '{}'.".format(TAGNAME))

    dihedralAtomIndices = [int(x)-1 for x in get_sd_data(mol, TAGNAME).split()]
    inDih = \
    oechem.OEOrAtom(oechem.OEOrAtom(oechem.OEHasAtomIdx(dihedralAtomIndices[0]), 
                                    oechem.OEHasAtomIdx(dihedralAtomIndices[1])),
                    oechem.OEOrAtom(oechem.OEHasAtomIdx(dihedralAtomIndices[2]), 
                                    oechem.OEHasAtomIdx(dihedralAtomIndices[3]))
                   )

    mol1 = mol.CreateCopy()
    mc_mol = oechem.OEMol(mol1)

    if num_conformers > 1:
        # Set criterion for rotatable bond
        if False and max_one_bond_away:
            # this max function makes this seem potentially broken
            only_one_bond_away = distance_predicate(dihedralAtomIndices[1],
                                                    dihedralAtomIndices[2])
            rotor_predicate = oechem.OEAndBond(only_one_bond_away,
                                               oechem.PyBondPredicate(isRotatableBond))
        elif False:
            # this ONLY samples special bonds & neglects "regualr" torsions
            rotor_predicate = oechem.PyBondPredicate(isRotatableBond)
        else:
            # try this more general sampling, but leave prior versions untouched
            rotor_predicate = oechem.OEOrBond(oechem.OEIsRotor(),
                                              oechem.PyBondPredicate(isRotatableBond))
        
        #Initialize conformer generator and multi-conformer library
        conf_generator = configure_omega(torsion_library, rotor_predicate,
                                         rms_cutoff, energy_window, num_conformers)

        # Generator conformers
        if not conf_generator(mc_mol, inDih):
            raise ValueError("Conformers cannot be generated.")
        logging.debug("Generated a total of %d conformers for %s.", mc_mol.NumConfs(),
                                                                    mol.GetTitle())

    for conf_no, conf in enumerate(mc_mol.GetConfs()):
        conformer_label = mol.GetTitle()+'_' +\
                         '_'.join(get_sd_data(mol, 'TORSION_ATOMS_ParentMol').split()) +\
                         '_{:02d}'.format(conf_no)
        oechem.OESetSDData(conf, "CONFORMER_LABEL", conformer_label)
        conf.SetTitle(conformer_label)

    return mc_mol
Ejemplo n.º 3
0
def CountRotors(ifs):
    rotcounts = []
    for mol in ifs.GetOEMols():
        nrots = oechem.OECount(mol, oechem.OEIsRotor())
        while nrots >= len(rotcounts):
            rotcounts.append(0)
        rotcounts[nrots] += 1

    print("Max rotors:", len(rotcounts) - 1)
    print("Rotorcount distribution:")

    for rots, numrot in enumerate(rotcounts):
        print("\t%d:\t%d" % (rots, numrot))
Ejemplo n.º 4
0
def gen_starting_confs(mol,
                       torsion_library,
                       num_conformers=MAX_CONFS,
                       rms_cutoff=0.0,
                       energy_window=25):

    # Identify the atoms in the dihedral
    TAGNAME = 'TORSION_ATOMS_FRAGMENT'
    if not has_sd_data(mol, TAGNAME):
        raise ValueError(
            "Molecule does not have the SD Data Tag '{}'.".format(TAGNAME))

    dihedralAtomIndices = [
        int(x) - 1 for x in get_sd_data(mol, TAGNAME).split()
    ]
    inDih = \
    oechem.OEOrAtom(oechem.OEOrAtom(oechem.OEHasAtomIdx(dihedralAtomIndices[0]),
                                    oechem.OEHasAtomIdx(dihedralAtomIndices[1])),
                    oechem.OEOrAtom(oechem.OEHasAtomIdx(dihedralAtomIndices[2]),
                                    oechem.OEHasAtomIdx(dihedralAtomIndices[3]))
                   )

    mol1 = mol.CreateCopy()
    mc_mol = oechem.OEMol(mol1)

    if num_conformers > 1:
        rotor_predicate = oechem.OEOrBond(
            oechem.OEIsRotor(), oechem.PyBondPredicate(isRotatableBond))

        #Initialize conformer generator and multi-conformer library
        conf_generator = configure_omega(torsion_library, rotor_predicate,
                                         rms_cutoff, energy_window,
                                         num_conformers)

        # Generator conformers
        if not conf_generator(mc_mol, inDih):
            raise ValueError("Conformers cannot be generated.")
        logging.debug("Generated a total of %d conformers for %s.",
                      mc_mol.NumConfs(), mol.GetTitle())

    for conf_no, conf in enumerate(mc_mol.GetConfs()):
        conformer_label = mol.GetTitle()+'_' +\
                         '_'.join(get_sd_data(mol, 'TORSION_ATOMS_ParentMol').split()) +\
                         '_{:02d}'.format(conf_no)
        oechem.OESetSDData(conf, "CONFORMER_LABEL", conformer_label)
        conf.SetTitle(conformer_label)

    return mc_mol
Ejemplo n.º 5
0
def main(argv=[__name__]):
    if len(argv) != 2:
        oechem.OEThrow.Usage("%s <infile>" % argv[0])

    ifs = oechem.oemolistream(sys.argv[1])
    am1 = oequacpac.OEAM1()
    results = oequacpac.OEAM1Results()
    for mol in ifs.GetOEMols():
        for conf in mol.GetConfs():
            print("molecule: ", mol.GetTitle(), "conformer:", conf.GetIdx())
            if am1.CalcAM1(results, mol):
                nbonds = 0
                for bond in mol.GetBonds(oechem.OEIsRotor()):
                    nbonds += 1
                    print(
                        results.GetBondOrder(bond.GetBgnIdx(),
                                             bond.GetEndIdx()))
                print("Rotatable bonds: ", nbonds)
Ejemplo n.º 6
0
    def __call__(self, bond):
        """
        :type mol: oechem.OEBondBase
        :rtype: boolean
        """
        if bond.GetOrder() != 1:
            return False
        if bond.IsAromatic():
            return False

        isrotor = oechem.OEIsRotor()
        if isrotor(bond):
            return True

        if oechem.OEBondGetSmallestRingSize(bond) >= 10:
            return True

        return False
Ejemplo n.º 7
0
def main(argv=[__name__]):
    if len(argv) != 2:
        oechem.OEThrow.Usage("%s <infile>" % argv[0])

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

    print("Title MolWt NumAtoms NumHeavyAtoms NumRingAtoms NumRotors NumConfs")

    for mol in ifs.GetOEMols():
        title = mol.GetTitle()
        if not title:
            title = "Untitled"
        print("%s %.3f %d %d %d %d %d" %
              (title, oechem.OECalculateMolecularWeight(mol), mol.NumAtoms(),
               oechem.OECount(mol, oechem.OEIsHeavy()),
               oechem.OECount(mol, oechem.OEAtomIsInRing()),
               oechem.OECount(mol, oechem.OEIsRotor()), mol.NumConfs()))
Ejemplo n.º 8
0
def calculate_ml_profiles(mols, sf_map, model, scaler):
    num_mols = len(mols)
    for count, mol in enumerate(mols):
        logging.info("Generating molecule profile %d/%d", (count + 1),
                     num_mols)

        if mol.HasData(HAS_PROFILES_TAG) and mol.GetData(
                HAS_PROFILES_TAG) == True:
            for bond in mol.GetBonds(oechem.OEIsRotor()):
                if bond.HasData(ENERGY_PROFILE_TAG) and bond.HasData(
                        PROFILE_OFFSET_TAG):
                    continue

                if bond.HasData(SPECIFIC_INCHI_TAG):
                    specific_inchi = bond.GetData(SPECIFIC_INCHI_TAG)

                    profile, offset = calculate_sf_ML_profile(
                        model, scaler, sf_map[specific_inchi])
                    bond.SetData(ENERGY_PROFILE_TAG, profile)
                    bond.SetData(PROFILE_OFFSET_TAG, float(offset))
Ejemplo n.º 9
0
def generate_torsional_strain(mol):
    '''
    Calculate strain energy of each rotatable bond using attached ML profiles
    @param mol: OEGraphMol
    @param gen_confs: bool
    @param num_confs: int
    @return: None
    '''
    for bond in mol.GetBonds(oechem.OEIsRotor()):
        if bond.HasData(ENERGY_PROFILE_TAG):
            energy_profile = bond.GetData(ENERGY_PROFILE_TAG)
            x, y = extract_numeric_data_from_profile_str(energy_profile)
            _, f = get_global_min_interp1d(x, y)

            bond_strain = 1e10
            torsion_atoms_list = extract_torsion_atoms(mol, bond)
            for torsion_atoms in torsion_atoms_list:
                a, b, c, d = torsion_atoms
                angle = oechem.OEGetTorsion(mol, a, b, c, d) * oechem.Rad2Deg
                strainE = float(f(angle))
                if strainE < 0.0:
                    strainE = 0.0
                if bond_strain > strainE:
                    bond_strain = strainE

                tor_atoms_str = ' '.join(
                    list(
                        map(str,
                            [a.GetIdx(),
                             b.GetIdx(),
                             c.GetIdx(),
                             d.GetIdx()])))

                bond.SetData(TORSION_ATOMS_FRAGMENT_TAG, tor_atoms_str)

            bond.SetData(STRAIN_TAG, bond_strain)

    if mol.HasData(HAS_PROFILES_TAG) and mol.GetData(HAS_PROFILES_TAG):
        save_profile_as_sd(mol)

    return mol
Ejemplo n.º 10
0
def check_frag_complexity(frag_smi,
                          filter_type=2,
                          check_n_rings=True,
                          filter_ortho=True):
    from openeye import oechem
    oemol = oechem.OEGraphMol()
    oechem.OESmilesToMol(oemol, frag_smi)
    nrots = oechem.OECount(oemol, oechem.OEIsRotor())
    # print(f'{frag_smi}: {nrots}')
    num_components, component_membership = oechem.OEDetermineComponents(oemol)
    num_rings = oemol.NumBonds() - oemol.NumAtoms() + num_components
    if filter_type == 1:
        if nrots > 0:
            return True, f' nrot: {nrots}'
        else:
            if check_n_rings and num_rings > 1:
                return True, f' nrings: {num_rings}'
            else:
                if filter_ortho and find_ortho_substituents(frag_smi):
                    return True, f'ortho substituent exists.'
                else:
                    return False, 'pass'
    elif filter_type == 2:
        if nrots > 1:
            return True, f' nrot: {nrots}'
        else:  # nrot = 0 or 1
            if check_n_rings and num_rings > 1:
                return True, f' nrings: {num_rings}'
            # remain 1ring with nrot 0 or 1/ chain with nrot 0 or 1
            elif check_n_rings and num_rings == 1 and nrots == 1:
                return True, f' nrings: {num_rings}, nrots: {nrots}'
            else:
                if filter_ortho and find_ortho_substituents(frag_smi):
                    return True, f'ortho substituent exists.'
                else:
                    return False, 'pass'
# 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

mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "N#CCC1CCNC=C1")

print("Number of non-rotatable bonds =", end=" ")
print(oechem.OECount(mol, oechem.OENotBond(oechem.OEIsRotor())))

print("Number of ring double bonds =", end=" ")
print(
    oechem.OECount(
        mol, oechem.OEAndBond(oechem.OEBondIsInRing(), oechem.OEHasOrder(2))))

print("Number of double or triple bonds =", end=" ")
print(
    oechem.OECount(mol,
                   oechem.OEOrBond(oechem.OEHasOrder(2),
                                   oechem.OEHasOrder(3))))
# @ </SNIPPET>
Ejemplo n.º 12
0
def generate_torsion_profile(mol_list):
    sf_map = {}
    for graph_mol in mol_list:
        if oechem.OECount(graph_mol, oechem.OEIsRotor()) == 0:
            logging.warning(
                'WARNING: Skipping molecule %s... rotor count is zero',
                graph_mol.GetTitle())
            continue

        frag_mols = get_molecule_torsion_fragments(graph_mol)
        if len(frag_mols) == 0:
            logging.warning(
                'WARNING: Skipping molecule %s... cannot identify torsional fragments',
                graph_mol.GetTitle())
            continue

        _, torsion_data = extract_molecule_torsion_data(graph_mol, frag_mols)

        for frag_mol in frag_mols:
            if has_undesirable_elements(frag_mol) or oechem.OECount(
                    frag_mol, oechem.OEIsPhosphorus()) > 0:
                logging.warning(
                    'WARNING: Skipping a fragment in molecule %s... fragment has undesirable elements',
                    graph_mol.GetTitle())
                continue

            # skip fragments with one or more formal charge
            skip_torsion = False
            if oechem.OECount(frag_mol, oechem.OEHasFormalCharge(1)) > 0 \
                or oechem.OECount(frag_mol, oechem.OEHasFormalCharge(2)) > 0:
                skip_torsion = True

            specific_inchi = get_specific_dihedral_inchi_key(frag_mol)

            if specific_inchi not in sf_map:
                sf_list = get_profile_sf(frag_mol)
                sf_map[specific_inchi] = sf_list

            torsion_data_items = torsion_data[specific_inchi]
            for torsion_data_item in torsion_data_items:
                a_idx, b_idx, c_idx, d_idx, _ = torsion_data_item
                b = graph_mol.GetAtom(oechem.OEHasAtomIdx(b_idx))
                c = graph_mol.GetAtom(oechem.OEHasAtomIdx(c_idx))

                bond = graph_mol.GetBond(b, c)
                if skip_torsion:
                    bond.SetData(SKIP_TORSION_TAG, True)

                tor_atoms_str = ' '.join(
                    list(map(str, [a_idx, b_idx, c_idx, d_idx])))
                if not bond.HasData(TORSION_ATOMS_FRAGMENT_TAG):
                    bond.SetData(TORSION_ATOMS_FRAGMENT_TAG, tor_atoms_str)
                    bond.SetData(SPECIFIC_INCHI_TAG, specific_inchi)
                else:
                    tmp_data = bond.GetData(TORSION_ATOMS_FRAGMENT_TAG)
                    tmp_data = tmp_data + ':' + tor_atoms_str
                    bond.SetData(TORSION_ATOMS_FRAGMENT_TAG, tmp_data)

        graph_mol.SetData(HAS_PROFILES_TAG, False)
        for bond in graph_mol.GetBonds(oechem.OEIsRotor()):
            if bond.HasData(TORSION_ATOMS_FRAGMENT_TAG):
                graph_mol.SetData(HAS_PROFILES_TAG, True)
                break

    return mol_list, sf_map
Ejemplo n.º 13
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 __future__ import print_function
from openeye import oechem

mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "CC(=O)Nc1c[nH]cc1")

print("Number of ring bonds  =", oechem.OECount(mol, oechem.OEBondIsInRing()))
print("Number of rotor bonds =", oechem.OECount(mol, oechem.OEIsRotor()))
# @ </SNIPPET>
Ejemplo n.º 14
0
# 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.

from openeye import oechem
from openeye import oedepict
from openeye import oegrapheme

# @ <SNIPPET-ANNOTATE-BOND-PROPERTY>
mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "c1cc(NCC)cc(CS(=O)(=O)O)c1")
oedepict.OEPrepareDepiction(mol)

opts = oedepict.OE2DMolDisplayOptions(400, 250, oedepict.OEScale_AutoScale)
opts.SetTitleLocation(oedepict.OETitleLocation_Hidden)
disp = oedepict.OE2DMolDisplay(mol, opts)

pen = oedepict.OEPen(oechem.OEDarkPurple, oechem.OEDarkPurple,
                     oedepict.OEFill_Off, 2.0)
glyph = oegrapheme.OEBondGlyphArrow(pen, 0.5)
oegrapheme.OEAddGlyph(disp, glyph, oechem.OEIsRotor())

oedepict.OERenderMolecule("AnnotateBondPredicate.png", disp)
# @ </SNIPPET-ANNOTATE-BOND-PROPERTY>
oedepict.OERenderMolecule("AnnotateBondPredicate.pdf", disp)
Ejemplo n.º 15
0
    def GetTorsions(mol):
        '''
        Goes through each rotatable bond in the molecule
        and extracts torsion atoms (a-b-c-d)
        Core torsion atoms are extended by one bond
        If core or extended atoms are part of a ring,
        then entire ring is kept
        Keep ortho substitution
        Keep functional groups that have at least one atom overlap
        with the core/extended torsion atoms
        Functional group inclusion criteria:
        - <= 5 heavy atoms
        - must contain at least one hetero atom
        - non-ring
        Add methyl cap if bond involving hetero atom is broken
        @param mol: OEGraphMol
        @type mol: OEGraphMol
        @return: list[OEGraphMol]
        '''
        # mol = OEGraphMol(input_mol)

        oechem.OEAssignHybridization(mol)
        funcGrps = TorsionGenerator.GetFuncGroups(mol)
        includedTorsions = oechem.OEAtomBondSet()
        torsionMols = []
        for atom in mol.GetAtoms():
            atom.SetData("idx", atom.GetIdx() + 1)

        torsions = get_canonical_torsions(mol)
        if torsions is None:
            torsions = oechem.OEGetTorsions(mol, oechem.OEIsRotor())

        for torsion in torsions:
            if torsion.a.IsHydrogen() or torsion.b.IsHydrogen() or \
                torsion.c.IsHydrogen() or torsion.d.IsHydrogen():
                continue

            torsion_bond = mol.GetBond(torsion.b, torsion.c)
            if includedTorsions.HasBond(torsion_bond):
                continue
            # if includedTorsions.HasAtom(torsion.b) and \
            #     includedTorsions.HasAtom(torsion.c):
            #     continue

            # revert map idx to zero in original mol
            for atom in mol.GetAtoms():
                atom.SetMapIdx(0)

            # includedTorsions.AddAtom(torsion.b)
            # includedTorsions.AddAtom(torsion.c)
            includedTorsions.AddBond(torsion_bond)

            torsionSet = oechem.OEAtomBondSet(mol.GetBonds())
            torsionSet.AddAtoms([torsion.a, torsion.b, torsion.c, torsion.d])
            for atom in torsionSet.GetAtoms():
                atom.SetMapIdx(1)

            # extend core torsion atoms by one bond
            nbrs = TorsionGenerator.GetNbrs(torsionSet)
            torsionSet.AddAtoms(nbrs)

            # include ring atoms
            ringAtoms = TorsionGenerator.GetSameRingAtoms(mol, torsionSet)
            torsionSet.AddAtoms(ringAtoms)

            for atom in torsionSet.GetAtoms():
                if not atom.GetMapIdx() == 1:
                    atom.SetMapIdx(2)

            # add functional groups that overlap with torsion set
            TorsionGenerator.AddFuncGroupAtoms(funcGrps, torsionSet)

            # add relevant ring atoms (ortho substituents and ring H)
            TorsionGenerator.AddRelevantRingAtoms(mol, torsion, torsionSet)

            # special treatment for C=O
            for atom in torsionSet.GetAtoms(
                    oechem.OEAndAtom(
                        oechem.OEIsOxygen(),
                        oechem.OEIsAtomHybridization(
                            oechem.OEHybridization_sp2))):
                for nbr in atom.GetAtoms():
                    if torsionSet.HasAtom(nbr):
                        for nbr2 in nbr.GetAtoms(oechem.OEIsHeavy()):
                            if not torsionSet.HasAtom(nbr2):
                                nbr2.SetMapIdx(2)
                                torsionSet.AddAtom(nbr2)

            # mark bridging atom and cap if needed
            BRIDGE_ATOM_IDX = 4
            TorsionGenerator.MarkBridgingAtoms(BRIDGE_ATOM_IDX, mol,
                                               torsionSet)

            A_IDX = 11
            B_IDX = 12
            C_IDX = 13
            D_IDX = 14
            torsion.a.SetMapIdx(A_IDX)
            torsion.b.SetMapIdx(B_IDX)
            torsion.c.SetMapIdx(C_IDX)
            torsion.d.SetMapIdx(D_IDX)

            torsionMol = oechem.OEGraphMol()
            oechem.OESubsetMol(torsionMol, mol, torsionSet, True)
            torsionMol.Sweep()
            torsionMols.append(torsionMol)

            # change bridge atom to Carbon
            for atom in torsionMol.GetAtoms(
                    oechem.OEHasMapIdx(BRIDGE_ATOM_IDX)):
                atom.SetAtomicNum(oechem.OEElemNo_C)
                explicit_valence = atom.GetExplicitValence()
                if explicit_valence < 4:
                    atom.SetImplicitHCount(4 - explicit_valence)

            TorsionGenerator.SetSDData(A_IDX, B_IDX, C_IDX, D_IDX, torsion,
                                       torsionMol)

            # set map idx to zero in torsion mol
            for atom in torsionMol.GetAtoms():
                atom.SetMapIdx(0)

        # revert map idx to zero in original mol
        for atom in mol.GetAtoms():
            atom.SetMapIdx(0)

        return torsionMols
Ejemplo n.º 16
0
def gen_starting_confs(
    mol,
    torsion_library,
    max_one_bond_away=True,
    num_conformers=MAX_CONFS,
    rms_cutoff=0.0,
    energy_window=25,
):

    # Identify the atoms in the dihedral
    TAGNAME = "TORSION_ATOMS_FRAGMENT"
    if not has_sd_data(mol, TAGNAME):
        raise ValueError(
            "Molecule does not have the SD Data Tag '{}'.".format(TAGNAME))

    dihedralAtomIndices = [
        int(x) - 1 for x in get_sd_data(mol, TAGNAME).split()
    ]
    inDih = oechem.OEOrAtom(
        oechem.OEOrAtom(
            oechem.OEHasAtomIdx(dihedralAtomIndices[0]),
            oechem.OEHasAtomIdx(dihedralAtomIndices[1]),
        ),
        oechem.OEOrAtom(
            oechem.OEHasAtomIdx(dihedralAtomIndices[2]),
            oechem.OEHasAtomIdx(dihedralAtomIndices[3]),
        ),
    )

    mol1 = mol.CreateCopy()
    mc_mol = oechem.OEMol(mol1)

    # Tag torsion atoms with their dihedral index
    for atom in mc_mol.GetAtoms():
        if atom.GetIdx() == dihedralAtomIndices[0]:
            atom.SetData("dihidx", 0)
        if atom.GetIdx() == dihedralAtomIndices[1]:
            atom.SetData("dihidx", 1)
        if atom.GetIdx() == dihedralAtomIndices[2]:
            atom.SetData("dihidx", 2)
        if atom.GetIdx() == dihedralAtomIndices[3]:
            atom.SetData("dihidx", 3)

    if num_conformers > 1:
        # Set criterion for rotatable bond
        if False and max_one_bond_away:
            # this max function makes this seem potentially broken
            only_one_bond_away = distance_predicate(dihedralAtomIndices[1],
                                                    dihedralAtomIndices[2])
            rotor_predicate = oechem.OEAndBond(
                only_one_bond_away, oechem.PyBondPredicate(isRotatableBond))
        elif False:
            # this ONLY samples special bonds & neglects "regualr" torsions
            rotor_predicate = oechem.PyBondPredicate(isRotatableBond)
        else:
            # try this more general sampling, but leave prior versions untouched
            rotor_predicate = oechem.OEOrBond(
                oechem.OEIsRotor(), oechem.PyBondPredicate(isRotatableBond))

        # Initialize conformer generator and multi-conformer library
        conf_generator = configure_omega(torsion_library, rotor_predicate,
                                         rms_cutoff, energy_window,
                                         num_conformers)

        # Generator conformers
        if not conf_generator(mc_mol, inDih):
            raise ValueError("Conformers cannot be generated.")
        logging.debug(
            "Generated a total of %d conformers for %s.",
            mc_mol.NumConfs(),
            mol.GetTitle(),
        )

        # Reassign
        new_didx = [-1, -1, -1, -1]
        for atom in mc_mol.GetAtoms():
            if atom.HasData("dihidx"):
                new_didx[atom.GetData("dihidx")] = atom.GetIdx()
        oechem.OEClearSDData(mc_mol)
        oechem.OESetSDData(mc_mol, TAGNAME,
                           " ".join(str(x + 1) for x in new_didx))
        oechem.OESetSDData(
            mc_mol,
            "TORSION_ATOMS_ParentMol",
            get_sd_data(mol, "TORSION_ATOMS_ParentMol"),
        )
        oechem.OESetSDData(
            mc_mol,
            "TORSION_ATOMPROP",
            f"cs1:0:1;1%{new_didx[0]+1}:1%{new_didx[1]+1}:1%{new_didx[2]+1}:1%{new_didx[3]+1}",
        )

    for conf_no, conf in enumerate(mc_mol.GetConfs()):
        conformer_label = (
            mol.GetTitle() + "_" +
            "_".join(get_sd_data(mol, "TORSION_ATOMS_ParentMol").split()) +
            "_{:02d}".format(conf_no))
        oechem.OESetSDData(conf, "CONFORMER_LABEL", conformer_label)
        conf.SetTitle(conformer_label)

    return mc_mol
Ejemplo n.º 17
0
def cal_molecule_torsion_strain(mol, profiles_map):
    """

    @type mol: oechem.OEGraphMol|oechem.OEMol
    :param mol:
    :param profiles_map:
    :return:
    """
    if type(mol) is oechem.OEMol:
        graph_mol = oechem.OEGraphMol(mol.GetActive())
        data = extract_molecule_torsion_data(graph_mol)
    else:
        data = extract_molecule_torsion_data(mol)

    if data is not None:
        _, tor_map = data

        if type(mol) is oechem.OEGraphMol:
            for tor_inchi, tor_data_list in tor_map.items():
                if tor_inchi in profiles_map:
                    for tor_data in tor_data_list:
                        _, b_idx, c_idx, _, angle = tor_data
                        bond = mol.GetBond(
                            mol.GetAtom(oechem.OEHasAtomIdx(b_idx)),
                            mol.GetAtom(oechem.OEHasAtomIdx(c_idx)),
                        )
                        if bond is not None:
                            strain_energy = profiles_map[tor_inchi](angle)
                            if strain_energy < 0:
                                strain_energy = 0
                            if (bond.HasData(STRAIN_TAG) and
                                    bond.GetData(STRAIN_TAG) > strain_energy):
                                bond.SetData(STRAIN_TAG, strain_energy)

            total_strain = 0.0
            for bond in mol.GetBonds():
                if bond.HasData(STRAIN_TAG):
                    total_strain += bond.GetData(STRAIN_TAG)

            mol.SetData(STRAIN_TAG, total_strain)

        elif type(mol) is oechem.OEMol:
            for conf in mol.GetConfs():
                bondIdx2energy = {}
                bondIdx2profile = {}
                bondIdx2toratoms = {}
                bondIdx2angles = {}
                for tor_inchi, tor_data_list in tor_map.items():
                    if tor_inchi in profiles_map:
                        for tor_data in tor_data_list:
                            a_idx, b_idx, c_idx, d_idx, _ = tor_data
                            b_atm = conf.GetAtom(oechem.OEHasAtomIdx(b_idx))
                            c_atm = conf.GetAtom(oechem.OEHasAtomIdx(c_idx))
                            bond = conf.GetBond(b_atm, c_atm)
                            if bond is not None:
                                a_atm = conf.GetAtom(
                                    oechem.OEHasAtomIdx(a_idx))
                                d_atm = conf.GetAtom(
                                    oechem.OEHasAtomIdx(d_idx))
                                angle = (oechem.OEGetTorsion(
                                    conf, a_atm, b_atm, c_atm, d_atm) *
                                         oechem.Rad2Deg)
                                strain_energy = float(
                                    profiles_map[tor_inchi](angle))
                                if strain_energy < 0:
                                    strain_energy = 0

                                x = range(-165, 181, 15)
                                y = []
                                for a in x:
                                    y.append(float(profiles_map[tor_inchi](a)))

                                energy_profile = generate_energy_profile_sd_data_1d(
                                    list(zip(x, y)))
                                bondIdx = bond.GetIdx()
                                if bondIdx not in bondIdx2energy:
                                    bondIdx2energy[bondIdx] = strain_energy
                                    bondIdx2profile[bondIdx] = energy_profile
                                    bondIdx2toratoms[bondIdx] = [
                                        a_idx + 1,
                                        b_idx + 1,
                                        c_idx + 1,
                                        d_idx + 1,
                                    ]
                                    bondIdx2angles[bondIdx] = angle
                                elif bondIdx2energy[bondIdx] > strain_energy:
                                    bondIdx2energy[bondIdx] = strain_energy
                                    bondIdx2profile[bondIdx] = energy_profile
                                    bondIdx2toratoms[bondIdx] = [
                                        a_idx + 1,
                                        b_idx + 1,
                                        c_idx + 1,
                                        d_idx + 1,
                                    ]
                                    bondIdx2angles[bondIdx] = angle

                # sd property place holder
                oechem.OESetSDData(conf, "QM_STRAIN", "0.0")
                oechem.OESetSDData(conf, "NUM_QM_TORSION_PROFILES", "0")
                oechem.OESetSDData(conf, "NUM_MISSING_QM_TORSIONS", "-1")

                total_strain = 0.0
                tor_idx = 1
                for tor_count, bond in enumerate(
                        conf.GetBonds(oechem.OEIsRotor())):
                    bidx = bond.GetIdx()
                    if bidx in bondIdx2energy:
                        total_strain += bondIdx2energy[bidx]

                        tmp = ":1%".join(list(map(str,
                                                  bondIdx2toratoms[bidx])))
                        tor_atomprop = "cs1:0:1;1%" + tmp
                        oechem.OESetSDData(
                            conf,
                            "QM_TORSION_ATOMS_%d_" % tor_idx + "ATOMPROP",
                            tor_atomprop,
                        )
                        oechem.OESetSDData(
                            conf,
                            "QM_TORSION_%d_" % tor_idx + ENERGY_PROFILE_TAG,
                            bondIdx2profile[bidx],
                        )
                        oechem.OESetSDData(
                            conf,
                            "TORSION_ANGLE_%d" % tor_idx,
                            "%.1f" % bondIdx2angles[bidx],
                        )
                        oechem.OESetSDData(
                            conf,
                            "QM_STRAIN_TORSION_%d" % tor_idx,
                            "%.1f" % bondIdx2energy[bidx],
                        )
                        tor_idx += 1

                oechem.OESetSDData(conf, "QM_STRAIN", "%.1f" % total_strain)
                oechem.OESetSDData(conf, "NUM_QM_TORSION_PROFILES",
                                   "%d" % (tor_count + 1))
                num_missing_torsions = (tor_count + 1) - (tor_idx - 1)
                oechem.OESetSDData(conf, "NUM_MISSING_QM_TORSIONS",
                                   "%d" % num_missing_torsions)
                conf.SetData(STRAIN_TAG, total_strain)
Ejemplo n.º 18
0
def get_canonical_torsions(mol):
    '''
    Return unique torsions in canonical order.
    Only one torsion containing the same central two atoms are return
    Cannonical ordering is determined using the order of atoms
    in canonical smiles representation
    1. generate a canonical smiles representation from the input molecule
    2. create a list of (min(b_idx, c_idx), min(a_idx, d_idx), max(a_idx, d_idx), OETorsion)
    3. sort the list in #2, extract subset with unique rotatable bonds
    :param mol: OEGraphMol
    :return: list[OEGraphMol]
    '''
    CANONICAL_IDX_TAG = 'can_idx'

    def assign_canonical_idx(mol):
        for atom in mol.GetAtoms():
            atom.SetMapIdx(0)
        for map_idx, atom in enumerate(mol.GetAtoms(oechem.OEIsHeavy())):
            atom.SetMapIdx(map_idx + 1)

        can_smiles = oechem.OEMolToSmiles(mol)

        can_mol = oechem.OEGraphMol()
        # smiles_opt = OEParseSmilesOptions(canon=True)
        # OEParseSmiles(can_mol, can_smiles, smiles_opt)
        oechem.OESmilesToMol(can_mol, can_smiles)

        for can_atom in can_mol.GetAtoms(oechem.OEIsHeavy()):
            atom = mol.GetAtom(oechem.OEHasMapIdx(can_atom.GetMapIdx()))
            atom.SetData(CANONICAL_IDX_TAG, can_atom.GetIdx())

    try:
        assign_canonical_idx(mol)
    except Exception as e:
        print('Error GetCanonicalizedTorsions. ', e)
        return None

    torsions = []
    for torsion in oechem.OEGetTorsions(mol, oechem.OEIsRotor()):
        if torsion.a.IsHydrogen() or torsion.b.IsHydrogen() or \
            torsion.c.IsHydrogen() or torsion.d.IsHydrogen():
            continue

        sum_bc = torsion.b.GetData(CANONICAL_IDX_TAG) + torsion.c.GetData(
            CANONICAL_IDX_TAG)
        min_bc = min(torsion.b.GetData(CANONICAL_IDX_TAG),
                     torsion.c.GetData(CANONICAL_IDX_TAG))
        max_bc = max(torsion.b.GetData(CANONICAL_IDX_TAG),
                     torsion.c.GetData(CANONICAL_IDX_TAG))
        min_ad = min(torsion.a.GetData(CANONICAL_IDX_TAG),
                     torsion.d.GetData(CANONICAL_IDX_TAG))
        max_ad = max(torsion.a.GetData(CANONICAL_IDX_TAG),
                     torsion.d.GetData(CANONICAL_IDX_TAG))

        torsions.append((sum_bc, min_bc, max_bc, min_ad, max_ad, torsion))

    # sort
    torsions.sort(key=operator.itemgetter(0, 1, 2, 3, 4))

    seen = {}
    unique_torsions = []
    for _, _, _, _, _, torsion in torsions:
        bond = mol.GetBond(torsion.b, torsion.c)
        if bond is not None and bond.GetIdx() not in seen:
            unique_torsions.append(torsion)
            seen[bond.GetIdx()] = True

    # revert mol to original state
    for atom in mol.GetAtoms(oechem.OEIsHeavy()):
        atom.SetMapIdx(0)
        atom.DeleteData(CANONICAL_IDX_TAG)

    return unique_torsions