Exemple #1
0
def test_simple_heterocycle_mapping(iupac_pairs=[('benzene', 'pyridine')]):
    """
    Test the ability to map conjugated heterocycles (that preserves all rings).  Will assert that the number of ring members in both molecules is the same.
    """
    # TODO: generalize this to test for ring breakage and closure.
    from openmoltools.openeye import iupac_to_oemol
    from openeye import oechem
    from perses.rjmc.topology_proposal import AtomMapper

    for iupac_pair in iupac_pairs:
        old_oemol, new_oemol = iupac_to_oemol(iupac_pair[0]), iupac_to_oemol(
            iupac_pair[1])
        new_to_old_map = AtomMapper._get_mol_atom_map(
            old_oemol, new_oemol, allow_ring_breaking=False)

        #assert that the number of ring members is consistent in the mapping...
        num_hetero_maps = 0
        for new_index, old_index in new_to_old_map.items():
            old_atom, new_atom = old_oemol.GetAtom(
                oechem.OEHasAtomIdx(old_index)), new_oemol.GetAtom(
                    oechem.OEHasAtomIdx(new_index))
            if old_atom.IsInRing() and new_atom.IsInRing():
                if old_atom.GetAtomicNum() != new_atom.GetAtomicNum():
                    num_hetero_maps += 1

        assert num_hetero_maps > 0, f"there are no differences in atomic number mappings in {iupac_pair}"
Exemple #2
0
def bond_order_tag(molecule, atom_map, bond_order_array):
    """
    Add psi bond order to bond in molecule. This function adds a tag to the GetData dictionary
    in bond.GetData()

    Parameters
    ----------
    molecule: OEMol
        This molecule must have tags that corresponds to the atom_map
    atom_map: dict
        dictionary that maps atom tag to atom index
    bond_order_array: dict
        maps Wiberg and Meyer bond indices to N x N numpy arrays.
        N - atoms in molecule. This array contains the bond order for bond(i,j) where i,j correspond to
        tag on atom and index in bond_order_array
    """
    wiberg_bond_order = bond_order_array['Wiberg_psi4']
    mayer_bond_order = bond_order_array['Mayer_psi4']
    # Sanity check, both arrays are same shape
    for i, j in itertools.combinations(range(wiberg_bond_order.shape[0]), 2):
        idx_1 = atom_map[i + 1]
        idx_2 = atom_map[j + 1]
        atom_1 = molecule.GetAtom(oechem.OEHasAtomIdx(idx_1))
        atom_2 = molecule.GetAtom(oechem.OEHasAtomIdx(idx_2))
        bond = molecule.GetBond(atom_1, atom_2)
        if bond:
            wbo = wiberg_bond_order[i][j]
            mbo = mayer_bond_order[i][j]
            tag = oechem.OEGetTag('Wiberg_psi4')
            bond.SetData(tag, wbo)
            tag = oechem.OEGetTag('Mayer_psi4')
            bond.SetData(tag, mbo)
Exemple #3
0
def mol_from_json(symbols, connectivity, geometry, permute_xyz=False):
    """
    Generate OEMol from QCSchema molecule specs
    Parameters
    ----------
    inp_molecule: dict
        Must have symbols and connectivity and/or geometry
        Note: If geometry is given, the molecule will have a tag indicating that the goemetry came from QCSchema. This
        will ensure that the order of the atoms and configuration is not change for generation of mapped SMILES and
        isomeric SMILES.

    Returns
    -------
    molecule: OEMol

    """

    molecule = oechem.OEMol()
    for s in symbols:
        molecule.NewAtom(_symbols[s])

    # Add connectivity
    for bond in connectivity:
        a1 = molecule.GetAtom(oechem.OEHasAtomIdx(bond[0]))
        a2 = molecule.GetAtom(oechem.OEHasAtomIdx(bond[1]))
        bond_order = bond[-1]
        if not isinstance(bond_order, int) and not bond_order.is_integer():
            raise ValueError(
                "bond order must be a whole number. A bond order of 1.5 is not allowed"
            )
        molecule.NewBond(a1, a2, int(bond_order))

    # Add geometry
    if molecule.NumAtoms() != geometry.shape[0] / 3:
        raise ValueError(
            "Number of atoms in molecule does not match length of position array"
        )

    molecule.SetCoords(oechem.OEFloatArray(geometry))
    molecule.SetDimension(3)

    if not permute_xyz:
        # Add tag that the geometry is from JSON and shouldn't be changed.
        geom_tag = oechem.OEGetTag("json_geometry")
        molecule.SetData(geom_tag, True)
    oechem.OEDetermineConnectivity(molecule)
    oechem.OEFindRingAtomsAndBonds(molecule)
    # No need to perceive Bond Order because the information was added from the connectivity table. Apparently, this
    # function does many different perceptions under the hood and it can add implicit hydrogens to divalent N that should be negatively charged.
    #oechem.OEPerceiveBondOrders(molecule)
    # This seems to add hydrogens that are not in the json
    #oechem.OEAssignImplicitHydrogens(molecule)
    oechem.OEAssignFormalCharges(molecule)
    oechem.OEAssignAromaticFlags(molecule)
    oechem.OEPerceiveChiral(molecule)
    oechem.OE3DToAtomStereo(molecule)
    oechem.OE3DToBondStereo(molecule)

    return molecule
Exemple #4
0
 def __call__(self, bond):
     atomB = bond.GetBgn()
     atomE = bond.GetEnd()
     mol = bond.GetParent()
     atom1 = mol.GetAtom(oechem.OEHasAtomIdx(self.atom1_idx))
     atom2 = mol.GetAtom(oechem.OEHasAtomIdx(self.atom2_idx))
     return max(oechem.OEGetPathLength(atomB, atom1),
                oechem.OEGetPathLength(atomE, atom1),
                oechem.OEGetPathLength(atomB, atom2),
                oechem.OEGetPathLength(atomE, atom2)) <= 3
Exemple #5
0
 def test_tag_molecule(self):
     """Test tag molecule"""
     tagged_rings, tagged_funcgroup = fragment.tag_molecule(charged)
     atom_idx = tagged_rings[1][0].pop()
     atom = charged.GetAtom(oechem.OEHasAtomIdx(atom_idx))
     ringsystem = atom.GetData('ringsystem')
     self.assertEquals(1, ringsystem)
     atom_idx = tagged_funcgroup['amide_0'][0].pop()
     atom = charged.GetAtom(oechem.OEHasAtomIdx(atom_idx))
     funcgroup = atom.GetData('fgroup')
     self.assertEquals('amide_0', funcgroup)
Exemple #6
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
Exemple #7
0
def mol_from_json(symbols, connectivity, geometry, permute_xyz=False):
    """
    Generate OEMol from QCSchema molecule specs
    Parameters
    ----------
    inp_molecule: dict
        Must have symbols and connectivity and/or geometry
        Note: If geometry is given, the molecule will have a tag indicating that the goemetry came from QCSchema. This
        will ensure that the order of the atoms and configuration is not change for generation of mapped SMILES and
        isomeric SMILES.

    Returns
    -------
    molecule: OEMol

    """

    molecule = oechem.OEMol()
    for s in symbols:
        molecule.NewAtom(_symbols[s])

    # Add connectivity
    for bond in connectivity:
        a1 = molecule.GetAtom(oechem.OEHasAtomIdx(bond[0]))
        a2 = molecule.GetAtom(oechem.OEHasAtomIdx(bond[1]))
        molecule.NewBond(a1, a2, bond[-1])

    # Add geometry
    if molecule.NumAtoms() != geometry.shape[0] / 3:
        raise ValueError(
            "Number of atoms in molecule does not match length of position array"
        )

    molecule.SetCoords(oechem.OEFloatArray(geometry))
    molecule.SetDimension(3)

    if not permute_xyz:
        # Add tag that the geometry is from JSON and shouldn't be changed.
        geom_tag = oechem.OEGetTag("json_geometry")
        molecule.SetData(geom_tag, True)
    oechem.OEDetermineConnectivity(molecule)
    oechem.OEFindRingAtomsAndBonds(molecule)
    oechem.OEPerceiveBondOrders(molecule)
    # This seems to add hydrogens that are not in the json
    #oechem.OEAssignImplicitHydrogens(molecule)
    oechem.OEAssignFormalCharges(molecule)
    oechem.OEAssignAromaticFlags(molecule)
    oechem.OEPerceiveChiral(molecule)
    oechem.OE3DToAtomStereo(molecule)
    oechem.OE3DToBondStereo(molecule)

    return molecule
Exemple #8
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
def to_atom_bond_set(oemol, atoms, bonds):
    from openeye import oechem
    atom_bond_set = oechem.OEAtomBondSet()
    for a_idx in atoms:
        atom = oemol.GetAtom(oechem.OEHasAtomIdx(a_idx))
        atom_bond_set.AddAtom(atom)

    for b_tuple in bonds:
        a1 = oemol.GetAtom(oechem.OEHasAtomIdx(b_tuple[0]))
        a2 = oemol.GetAtom(oechem.OEHasAtomIdx(b_tuple[-1]))
        bond = oemol.GetBond(a1, a2)
        if not bond:
            raise ValueError("{} is a disconnected bond".format(b_tuple))
        atom_bond_set.AddBond(bond)

    return atom_bond_set
Exemple #10
0
def get_modified_inchi_key(mol, atoms):
    """
    Generates InChIKey for the input molecule.
    Passed atoms of the molecule are mutated (atomic number changed)
    based on the mapping defined in the function.

    @param mol:
    @param atoms:
    @type mol: OEGraphMol
    @type atoms: list[OEAtombase]
    @return: str
    """
    copy_mol = oechem.OEGraphMol(mol)
    atom_map = {
        oechem.OEElemNo_C: oechem.OEElemNo_Pb,
        oechem.OEElemNo_N: oechem.OEElemNo_Bi,
        oechem.OEElemNo_O: oechem.OEElemNo_Po,
        oechem.OEElemNo_F: oechem.OEElemNo_At,
        oechem.OEElemNo_S: oechem.OEElemNo_Te,
        oechem.OEElemNo_Cl: oechem.OEElemNo_I,
        oechem.OEElemNo_P: oechem.OEElemNo_Sb,
        oechem.OEElemNo_Br: 117,
        oechem.OEElemNo_I: 118,
    }
    for ref_atom in atoms:
        copy_atom = copy_mol.GetAtom(oechem.OEHasAtomIdx(ref_atom.GetIdx()))
        if copy_atom is None:
            raise Exception("Null atom found")
        copy_atom.SetAtomicNum(atom_map[copy_atom.GetAtomicNum()])

    return oechem.OECreateInChIKey(copy_mol)
Exemple #11
0
def _ring_substiuents(mol, bond, rotor_bond, tagged_rings, ring_idx, fgroup_tagged):
    """
    This function finds ring substituents that shouldn't be cut off

    Parameters
    ----------
    mol: OpeneEye OEMolGraph
    bond: OpenEye Bond Base
        current bond that the iterator is looking at
    rotor_bond: OpeneEye Bond Base
        rotatable bond that fragment is being grown on
    tagged_rings: dict
        mapping of ring index and atom and bonds indices
    ring_idx: int
        ring index
    fgroup_tagged: dict
        mapping of functional group and atom and bond indices

    Returns
    -------
    rs_atoms, rs_bonds: sets of ring substituents atoms and bonds indices

    """
    rs_atoms = set()
    rs_bonds = set()
    r_atoms, r_bonds = tagged_rings[ring_idx]
    for a_idx in r_atoms:
        atom = mol.GetAtom(oechem.OEHasAtomIdx(a_idx))
        for a in atom.GetAtoms():
            if a.GetIdx() in rs_atoms:
                continue
            fgroup = False
            rs_bond = mol.GetBond(atom, a)
            if not a.IsInRing():
                if not rs_bond.IsRotor():
                    rs_atoms.add(a.GetIdx())
                    rs_bonds.add(rs_bond.GetIdx())
                    # Check for functional group
                    fgroup = _is_fgroup(fgroup_tagged, element=a)
                elif _is_ortho(rs_bond, rotor_bond, bond):
                    # Keep bond and attached atom.
                    rs_atoms.add(a.GetIdx())
                    rs_bonds.add(rs_bond.GetIdx())
                    # Check for functional group
                    fgroup = _is_fgroup(fgroup_tagged, element=a)
                if fgroup:
                    rs_atoms = rs_atoms.union(fgroup[0])
                    rs_bonds = rs_bonds.union(fgroup[-1])
            else:
                # Check if they are in the same ring
                r_idx2 = a.GetData('ringsystem')
                if r_idx2 != ring_idx:
                    if _is_ortho(rs_bond, rotor_bond, bond):
                        # Add ring system
                        rs_bonds.add(rs_bond.GetIdx())
                        r2_atoms, r2_bonds = tagged_rings[r_idx2]
                        rs_atoms = rs_atoms.union(r2_atoms)
                        rs_bonds = rs_bonds.union(r2_bonds)

    return rs_atoms, rs_bonds
Exemple #12
0
def bond_order_to_bond_graph(bond_order,
                             threshold=0.8,
                             hydrogen_bond=True,
                             molecule=None,
                             atom_map=None):
    """
    Get bond graph from bond orders. This function returns a set of bonds where the bond order is above a threshold
    Parameters
    ----------
    bond_order: np array
    threshold: int

    Returns
    -------
    bonds: set

    """
    bonds = set()
    for i in range(bond_order.shape[0]):
        for j in range(bond_order.shape[1]):
            if bond_order[i, j] >= threshold:
                if not hydrogen_bond:
                    idx_1 = atom_map[i + 1]
                    idx_2 = atom_map[j + 1]
                    atom_1 = molecule.GetAtom(oechem.OEHasMapIdx(idx_1))
                    atom_2 = molecule.GetAtom(oechem.OEHasAtomIdx(idx_2))
                    if atom_1.IsHydrogen() or atom_2.IsHydrogen():
                        continue
                if (j + 1, i + 1) in bonds:
                    continue
                bonds.add((i + 1, j + 1))
    return bonds
Exemple #13
0
def to_mapped_xyz(molecule,
                  atom_map=None,
                  conformer=None,
                  xyz_format=True,
                  filename=None):
    """
    Generate xyz coordinates for molecule in the order given by the atom_map. atom_map is a dictionary that maps the
    tag on the SMILES to the atom idex in OEMol.
    Parameters
    ----------
    molecule: OEMol with conformers
    atom_map: dict
        maps tag in SMILES to atom index
    conformer: int
        Which conformer to write xyz file for. If None, write out all conformers. Default is None
    xyz_format: bool
        If True, will write out number of atoms and molecule name. If false, will only write out elements and coordinates
    filename: str
        Name of file to save to. If None, only returns a string.

    Returns
    -------
    str: elements and xyz coordinates (in angstroms) in order of tagged SMILES

    """
    if not atom_map and not cmiles.utils.has_atom_map(molecule):
        raise ValueError(
            "If molecule does not have atom map, you must provide an atom map")
    if not has_conformer(molecule, check_two_dimension=True):
        raise ValueError("Molecule must have conformers")
    xyz = ""
    for k, mol in enumerate(molecule.GetConfs()):
        if k == conformer or conformer is None:
            if xyz_format:
                xyz += "{}\n".format(mol.GetMaxAtomIdx())
                xyz += "{}\n".format(mol.GetTitle())
            coords = oechem.OEFloatArray(mol.GetMaxAtomIdx() * 3)
            mol.GetCoords(coords)
            if k != 0 and not xyz_format:
                xyz += "*"

            for mapping in range(1, molecule.NumAtoms() + 1):
                if not atom_map:
                    atom = molecule.GetAtom(oechem.OEHasMapIdx(mapping))
                    idx = atom.GetIdx()
                else:
                    idx = atom_map[mapping]
                    atom = mol.GetAtom(oechem.OEHasAtomIdx(idx))
                syb = oechem.OEGetAtomicSymbol(atom.GetAtomicNum())
                xyz += "  {}      {:05.3f}   {:05.3f}   {:05.3f}\n".format(
                    syb, coords[idx * 3], coords[idx * 3 + 1],
                    coords[idx * 3 + 2])

    if filename:
        file = open("{}.xyz".format(filename), 'w')
        file.write(xyz)
        file.close()
    else:
        return xyz
Exemple #14
0
 def test_tag_funcgroup(self):
     """ Test tag functional groups """
     tagged_funcgroups = fragment._tag_fgroups(charged)
     self.assertEquals(len(tagged_funcgroups), 3)
     atom_idx = tagged_funcgroups['amide_0'][0].pop()
     atom = charged.GetAtom(oechem.OEHasAtomIdx(atom_idx))
     fgroup = atom.GetData('fgroup')
     self.assertEquals('amide_0', fgroup)
Exemple #15
0
 def test_tag_rings(self):
     """ Test tag rings"""
     tagged_rings = fragment._tag_rings(charged)
     self.assertEquals(len(tagged_rings), 3)
     atom_idx = tagged_rings[1][0].pop()
     atom = charged.GetAtom(oechem.OEHasAtomIdx(atom_idx))
     ringsystem = atom.GetData('ringsystem')
     self.assertEquals(1, ringsystem)
Exemple #16
0
def MakeCliques(surf, mol):
    for i in range(surf.GetNumVertices()):
        atom = mol.GetAtom(oechem.OEHasAtomIdx(surf.GetAtomsElement(i)))
        if atom.IsOxygen() or atom.IsNitrogen() or atom.IsPolarHydrogen():
            surf.SetVertexCliqueElement(i, 1)
            surf.SetColorElement(i, 0.0, 0.0, 1.0)
        else:
            surf.SetColorElement(i, 1.0, 0.0, 0.0)
    return True
Exemple #17
0
 def test_is_fgroup(self):
     """Test is functional group """
     tagged_rings, taggged_funcgroup = fragment.tag_molecule(charged)
     atom_idx = taggged_funcgroup['amide_0'][0].pop()
     bond_idx = taggged_funcgroup['amide_0'][-1].pop()
     atom = charged.GetAtom(oechem.OEHasAtomIdx(atom_idx))
     bond = charged.GetBond(oechem.OEHasBondIdx(bond_idx))
     self.assertTrue(fragment._is_fgroup(taggged_funcgroup, atom))
     self.assertTrue(fragment._is_fgroup(taggged_funcgroup, bond))
Exemple #18
0
def _ring_fgroup_union(mol, tagged_rings, tagged_fgroups, wbo_threshold=1.2):
    """
    This function combines rings and fgroups that are conjugated (the bond between them has a Wiberg bond order > 1.2)

    Parameters
    ----------
    mol: OpenEye OEMolGraph
    tagged_rings: dict
        map of ringsystem indices to ring atom and bond indices
    tagged_fgroup: dict
        map of fgroup to fgroup atom and bond indices

    Returns
    -------
    tagged_fgroup: dict
        updated tagged_fgroup mapping with rings that shouldn't be fragmented from fgroups
    """
    ring_idxs = list(tagged_rings.keys())
    fgroups = list(tagged_fgroups.keys())
    tagged_fgroups = copy.deepcopy(tagged_fgroups)

    # Check if fgroups are overlapping. If they are - combine them.
    for func_group_1, func_group_2 in itertools.combinations(list(tagged_fgroups.keys()), 2):
        atoms_intersection = tagged_fgroups[func_group_1][0].intersection(tagged_fgroups[func_group_2][0])
        if len(atoms_intersection) > 1:
            # Combine fgroups
            atoms_union = tagged_fgroups[func_group_1][0].union(tagged_fgroups[func_group_2][0])
            bonds_union = tagged_fgroups[func_group_1][-1].union(tagged_fgroups[func_group_2][-1])
            tagged_fgroups[func_group_1] = (atoms_union, bonds_union)
            tagged_fgroups[func_group_2] = (atoms_union, bonds_union)
    for idx in ring_idxs:
        for fgroup in fgroups:
            atom_intersection = tagged_rings[idx][0].intersection(tagged_fgroups[fgroup][0])
            if len(atom_intersection) > 1:
                # Must include ring if including fgroup. Add ring atoms and bonds to fgroup
                atoms_union = tagged_rings[idx][0].union(tagged_fgroups[fgroup][0])
                bonds_union = tagged_rings[idx][-1].union(tagged_fgroups[fgroup][-1])
                tagged_fgroups[fgroup] = (atoms_union, bonds_union)
            elif len(atom_intersection) > 0:
                # Check Wiberg bond order of bond
                # First find bond connectiong fgroup and ring
                atom = mol.GetAtom(oechem.OEHasAtomIdx(atom_intersection.pop()))
                for a in atom.GetAtoms():
                    if a.GetIdx() in tagged_fgroups[fgroup][0]:
                        bond = mol.GetBond(a, atom)
                        if bond.GetData('WibergBondOrder') > wbo_threshold:
                            # Don't cut off ring.
                            atoms_union = tagged_rings[idx][0].union(tagged_fgroups[fgroup][0])
                            bonds_union = tagged_rings[idx][-1].union(tagged_fgroups[fgroup][-1])
                            tagged_fgroups[fgroup] = (atoms_union, bonds_union)
                        # Should I also combine non-rotatable rings? This will pick up the alkyn in ponatinib?
                        if not bond.IsRotor():
                            atoms_union = tagged_rings[idx][0].union(tagged_fgroups[fgroup][0])
                            bonds_union = tagged_rings[idx][-1].union(tagged_fgroups[fgroup][-1])
                            tagged_fgroups[fgroup] = (atoms_union, bonds_union)
                        # Do something when it's neither for edge cases (Afatinib)?
    return tagged_fgroups
Exemple #19
0
def get_fragment_to_parent_atom_mapping(parent_mol, frag_mol):
    try:
        mapping_data = oechem.OEGetSDData(frag_mol,
                                          FRAGMENT_TO_PARENT_ATOMS_KEY)
        idx_map = dict(
            map(int, idx_pair.split('_'))
            for idx_pair in mapping_data.split('-'))
        atom_map = {}
        for frag_idx, parent_idx in idx_map.items():
            frag_atom = frag_mol.GetAtom(oechem.OEHasAtomIdx(frag_idx - 1))
            parent_atom = parent_mol.GetAtom(
                oechem.OEHasAtomIdx(parent_idx - 1))
            if frag_atom is not None and parent_atom is not None:
                atom_map[frag_atom] = parent_atom

        return atom_map

    except Exception as e:
        logging.warning(e)
        return {}
Exemple #20
0
    def test_mapped_xyz(self):
        """Test writing out mapped xyz"""
        from openeye import oechem, oeomega
        tagged_smiles = '[H:10][c:4]1[c:3]([c:2]([c:1]([c:6]([c:5]1[H:11])[H:12])[C:7]([H:13])([H:14])[H:15])[H:8])[H:9]'
        mol_1 = chemi.smiles_to_oemol('Cc1ccccc1')
        inf = get_fn('toluene.mol2')
        ifs = oechem.oemolistream(inf)
        mol_2 = oechem.OEMol()
        oechem.OEReadMolecule(ifs, mol_2)

        mol_1 = chemi.generate_conformers(mol_1, max_confs=1)
        atom_map = get_atom_map(mol_1, tagged_smiles)
        for i, mapping in enumerate(atom_map):
            atom_1 = mol_1.GetAtom(oechem.OEHasAtomIdx(atom_map[mapping]))
            atom_1.SetAtomicNum(i + 1)
            atom_2 = mol_2.GetAtom(oechem.OEHasAtomIdx(mapping - 1))
            atom_2.SetAtomicNum(i + 1)

        xyz_1 = chemi.to_mapped_xyz(mol_1, atom_map, xyz_format=False)
        # molecule generated from mol2 should be in the right order.
        atom_map_mol2 = {
            1: 0,
            2: 1,
            3: 2,
            4: 3,
            5: 4,
            6: 5,
            7: 6,
            8: 7,
            9: 8,
            10: 9,
            11: 10,
            12: 11,
            13: 12,
            14: 13,
            15: 14
        }
        xyz_2 = chemi.to_mapped_xyz(mol_2, atom_map_mol2, xyz_format=False)

        for ele1, ele2 in zip(xyz_1.split('\n')[:-1], xyz_2.split('\n')[:-1]):
            self.assertEqual(ele1.split(' ')[2], ele2.split(' ')[2])
Exemple #21
0
    def test_atom_map_order(self):
        """Test atom map"""
        from openeye import oechem
        tagged_smiles = '[H:5][C:1]#[N+:4][C:3]([H:9])([H:10])[C:2]([H:6])([H:7])[H:8]'
        mol_from_tagged_smiles = openeye.smiles_to_oemol(tagged_smiles)
        atom_map = utils.get_atom_map(tagged_smiles, mol_from_tagged_smiles)

        # Compare atom map to tag
        for i in range(1, len(atom_map) + 1):
            atom_1 = mol_from_tagged_smiles.GetAtom(
                oechem.OEHasAtomIdx(atom_map[i]))
            self.assertEqual(i, atom_1.GetMapIdx())
Exemple #22
0
def extract_torsion_atoms(mol, bond):
    torsion_atoms_str_list = bond.GetData(TORSION_ATOMS_FRAGMENT_TAG).split(
        ':')
    torsion_atoms_list = []
    for torsion_atoms_str in torsion_atoms_str_list:
        torsion_atoms_idx = list(map(int, torsion_atoms_str.split()))
        torsion_oeatoms \
            = map(lambda idx: mol.GetAtom(oechem.OEHasAtomIdx(idx)),
                  torsion_atoms_idx)
        a, b, c, d = list(torsion_oeatoms)
        torsion_atoms_list.append((a, b, c, d))
    return torsion_atoms_list
Exemple #23
0
    def get_molecule(self):
        """
        Extracts the parent molecule this atom is in

        Returns
        -------
        mol: chemper Mol
            molecule this atom is stored in
        """
        mol = oechem.OEMol(self.atom.GetParent())
        self.atom = mol.GetAtom(oechem.OEHasAtomIdx(self._index))
        return Mol(mol)
def get_torsion_oeatom_list(mol, tag="TORSION_ATOMS_FRAGMENT"):
    if has_sd_data(mol, tag):
        torsion_atoms = get_sd_data(mol, tag)
        try:
            torsion_atoms_idx = list(map(int, torsion_atoms.split()))
            torsion_oeatoms = map(
                lambda idx: mol.GetAtom(oechem.OEHasAtomIdx(idx - 1)),
                torsion_atoms_idx)
            return list(torsion_oeatoms)
        except Exception as e:
            print(e)
            return None
Exemple #25
0
def get_dihedral(mol, dihedralAtomIndices):
    """Get the dihedral corresponding to the indices in dihedralAtomIndices.

    Note that the indices are zero-indexed. The torsion of interest is the bond
    between atoms with indices 1 and 2.
    """
    # dihedralAtomIndices = [int(x) for x in get_sd_data(mol, 'TORSION_ATOMS_FRAGMENT').split()]
    dih = oechem.OEAtomBondSet()
    tor = oechem.OEAtomBondSet()
    for i in range(3):
        srcIdx = dihedralAtomIndices[i]
        destIdx = dihedralAtomIndices[i + 1]
        src = mol.GetAtom(oechem.OEHasAtomIdx(srcIdx))
        dest = mol.GetAtom(oechem.OEHasAtomIdx(destIdx))
        dih.AddAtom(src)
        bond = mol.GetBond(src, dest)
        dih.AddBond(bond)
        if i == 1:
            tor.AddBond(bond)
    dih.AddAtom(dest)

    return dih, tor
Exemple #26
0
    def get_atom_by_index(self, idx):
        """
        Parameters
        ----------
        idx: int
            atom index

        Returns
        -------
        atom: chemper Atom object
            atom with index idx
        """
        return Atom(self.mol.GetAtom(oechem.OEHasAtomIdx(idx)))
Exemple #27
0
def highlight_atoms_in_mol(mol2, dihedralAtomIndices, width=200, height=200):
    mol = mol2.CreateCopy()
    opts = oedepict.OE2DMolDisplayOptions(width, height, oedepict.OEScale_AutoScale)
    oedepict.OEPrepareDepiction(mol)

    disp = oedepict.OE2DMolDisplay(mol, opts)
    img = oedepict.OEImage(width, height)

    hstyle = oedepict.OEHighlightByBallAndStick(oechem.OEBlueTint)
    for atom_idx in dihedralAtomIndices:
        oedepict.OEAddHighlighting(disp, hstyle, oechem.OEHasAtomIdx(atom_idx))

    oedepict.OERenderMolecule(img, disp)
    return img
Exemple #28
0
        def noh(ls, dsets):
            """
            This function remove hydrogens from the selection
            """
            data_set = build_set(ls[1], dsets)

            noh_set = set()
            pred = oechem.OEIsHydrogen()

            for idx in data_set:
                atom = system.GetAtom(oechem.OEHasAtomIdx(idx))
                if not pred(atom):
                    noh_set.add(idx)

            return noh_set
Exemple #29
0
    def test_atom_map(self):
        """Test get atom map"""
        from openeye import oechem
        tagged_smiles = '[H:5][C:1]#[N+:4][C:3]([H:9])([H:10])[C:2]([H:6])([H:7])[H:8]'
        mol_1 = openeye.smiles_to_oemol('CC[N+]#C')
        inf = get_fn('ethylmethylidyneamonium.mol2')
        ifs = oechem.oemolistream(inf)
        mol_2 = oechem.OEMol()
        oechem.OEReadMolecule(ifs, mol_2)

        atom_map = utils.get_atom_map(tagged_smiles, mol_1)

        for i, mapping in enumerate(atom_map):
            atom_1 = mol_1.GetAtom(oechem.OEHasAtomIdx(atom_map[mapping]))
            atom_1.SetAtomicNum(i + 1)
            atom_2 = mol_2.GetAtom(oechem.OEHasAtomIdx(mapping - 1))
            atom_2.SetAtomicNum(i + 1)
            self.assertEqual(oechem.OECreateCanSmiString(mol_1),
                             oechem.OECreateCanSmiString(mol_2))

        # Test aromatic molecule
        tagged_smiles = '[H:10][c:4]1[c:3]([c:2]([c:1]([c:6]([c:5]1[H:11])[H:12])[C:7]([H:13])([H:14])[H:15])[H:8])[H:9]'
        mol_1 = openeye.smiles_to_oemol('Cc1ccccc1')
        inf = get_fn('toluene.mol2')
        ifs = oechem.oemolistream(inf)
        mol_2 = oechem.OEMol()
        oechem.OEReadMolecule(ifs, mol_2)

        atom_map = utils.get_atom_map(tagged_smiles, mol_1)
        for i, mapping in enumerate(atom_map):
            atom_1 = mol_1.GetAtom(oechem.OEHasAtomIdx(atom_map[mapping]))
            atom_1.SetAtomicNum(i + 1)
            atom_2 = mol_2.GetAtom(oechem.OEHasAtomIdx(mapping - 1))
            atom_2.SetAtomicNum(i + 1)
            self.assertEqual(oechem.OECreateCanSmiString(mol_1),
                             oechem.OECreateCanSmiString(mol_2))
Exemple #30
0
def to_mapped_xyz(molecule,
                  atom_map,
                  conformer=None,
                  xyz_format=False,
                  filename=None):
    """
    Generate xyz coordinates for molecule in the order given by the atom_map. atom_map is a dictionary that maps the
    tag on the SMILES to the atom idex in OEMol.
    Parameters
    ----------
    molecule: OEMol with conformers
    atom_map: dict
        maps tag in SMILES to atom index
    conformer: int
        Which conformer to write xyz file for. If None, write out all conformers. Default is None
    xyz_format: bool
        If True, will write out number of atoms and molecule name. If false, will only write out elements and coordinates
    filename: str
        Name of file to save to. If None, only returns a string.

    Returns
    -------
    str: elements and xyz coordinates in order of tagged SMILES

    """
    xyz = ""
    for k, mol in enumerate(molecule.GetConfs()):
        if k == conformer or conformer is None:
            if xyz_format:
                xyz += "{}\n".format(mol.GetMaxAtomIdx())
                xyz += "{}\n".format(mol.GetTitle())
            coords = oechem.OEFloatArray(mol.GetMaxAtomIdx() * 3)
            mol.GetCoords(coords)
            if k != 0 and not xyz_format:
                xyz += "*"
            for mapping in range(1, len(atom_map) + 1):
                idx = atom_map[mapping]
                atom = mol.GetAtom(oechem.OEHasAtomIdx(idx))
                syb = oechem.OEGetAtomicSymbol(atom.GetAtomicNum())
                xyz += "  {}      {:05.3f}   {:05.3f}   {:05.3f}\n".format(
                    syb, coords[idx * 3], coords[idx * 3 + 1],
                    coords[idx * 3 + 2])

    if filename:
        file = open("{}.xyz".format(filename, 'w'))
        file.write(xyz)
        file.close()
    return xyz