def get_bond(mol, bond_idx): a1 = mol.GetAtom(oechem.OEHasMapIdx(bond_idx[0])) a2 = mol.GetAtom(oechem.OEHasMapIdx(bond_idx[1])) bond = mol.GetBond(a1, a2) if not bond: raise ValueError("({}) atoms are not connected".format(bond_idx)) return bond
def test_tag_fgroups(): from openeye import oechem import itertools smiles = '[H:40][c:3]1[c:8]([c:20]2[n:30][c:12]([c:14]([n:32]2[n:31][c:11]1[H:48])[C:2]#[C:1][c:13]3[c:9]([c:15]([c:4]([c:5]([c:16]3[C:26]' \ '([H:58])([H:59])[H:60])[H:42])[H:41])[C:21](=[O:36])[N:35]([H:66])[c:19]4[c:7]([c:6]([c:17]([c:18]([c:10]4[H:47])[C:29]([F:37])([F:38])' \ '[F:39])[C:28]([H:64])([H:65])[N:34]5[C:24]([C:22]([N:33]([C:23]([C:25]5([H:56])[H:57])([H:52])[H:53])[C:27]([H:61])([H:62])[H:63])([H:50])' \ '[H:51])([H:54])[H:55])[H:43])[H:44])[H:46])[H:49])[H:45]' mol = oechem.OEMol() oechem.OESmilesToMol(mol, smiles) frags = fragmenter.fragment.CombinatorialFragmenter(mol) fgroups = {} fgroups['alkyne_0'] = [1, 2] fgroups['carbonyl_0'] = [21, 36] fgroups['amide_0'] = [35] fgroups['tri_halide_0'] = [29, 37, 38, 39] for group in fgroups: for i in fgroups[group]: a = frags.molecule.GetAtom(oechem.OEHasMapIdx(i)) assert a.GetData('fgroup') == group for group in fgroups: atoms = [ frags.molecule.GetAtom(oechem.OEHasMapIdx(i)) for i in fgroups[group] ] for atom in itertools.combinations(atoms, 2): # Check for bond b = frags.molecule.GetBond(atom[0], atom[1]) if b: assert b.GetData('fgroup') == group
def get_bond(mol, bond_tuple): a1 = mol.GetAtom(oechem.OEHasMapIdx(bond_tuple[0])) a2 = mol.GetAtom(oechem.OEHasMapIdx(bond_tuple[1])) if not a1 or not a2: print('no atoms') return False bond = mol.GetBond(a1, a2) if not bond: print('no bond') return False return bond
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
def get_wbo_growth(fragmenter, fragment_mol, atoms, bonds, target_bond, heuristic): wbos = [] fragments = [] fragment_mol = fragmenter.fragments[target_bond] oechem.OEAddExplicitHydrogens(fragment_mol) try: charged_fragment = chemi.get_charges(fragment_mol, strict_stereo=False, strict_types=False) a1 = charged_fragment.GetAtom(oechem.OEHasMapIdx(target_bond[0])) a2 = charged_fragment.GetAtom(oechem.OEHasMapIdx(target_bond[-1])) bond = charged_fragment.GetBond(a1, a2) wbos.append(bond.GetData('WibergBondOrder')) fragments.append(charged_fragment) except RuntimeError: print('Bad fragment. Continuing to adding the next bond') pass while fragment_mol.GetMaxAtomIdx() < fragmenter.molecule.GetMaxAtomIdx(): atoms, bonds = add_one_bond( molecule=fragmenter.molecule, atoms=atoms, bonds=bonds, functional_groups=fragmenter.functional_groups, ring_systems=fragmenter.ring_systems, target_bond=target_bond, heuristic=heuristic) ab_set = fragmenter._to_atom_bond_set(atoms, bonds) fragment_mol = fragmenter.atom_bond_set_to_mol( ab_set, expand_stereoisomers=False) oechem.OEAddExplicitHydrogens(fragment_mol) try: charged_fragment = chemi.get_charges(fragment_mol, strict_stereo=False, strict_types=False) a1 = charged_fragment.GetAtom(oechem.OEHasMapIdx(target_bond[0])) a2 = charged_fragment.GetAtom(oechem.OEHasMapIdx(target_bond[-1])) bond = charged_fragment.GetBond(a1, a2) fragment_wbo = bond.GetData('WibergBondOrder') wbos.append(fragment_wbo) mol_copy = copy.deepcopy(charged_fragment) fragments.append(mol_copy) except RuntimeError: pass return wbos, fragments
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
def test_cap_open_valance(input, bond, output): from openeye import oechem mol = chemi.smiles_to_oemol(input) f = fragmenter.fragment.PfizerFragmenter(mol) atoms, bonds = f._get_torsion_quartet(bond) atoms, bonds = f._get_ring_and_fgroups(atoms, bonds) f._cap_open_valence(atoms, bonds, bond) # Check that carbon bonded to N was added assert f.molecule.GetAtom(oechem.OEHasMapIdx(output))
def sort_by_wbo(molecule, atoms, bonds): sort_by = [] atoms_to_add = [] for m_idx in atoms: a = molecule.GetAtom(oechem.OEHasMapIdx(m_idx)) for nbr in a.GetAtoms(): nbr_m_idx = nbr.GetMapIdx() if not nbr.IsHydrogen() and not nbr_m_idx in atoms: b = molecule.GetBond(a, nbr) atoms_to_add.append((nbr_m_idx, (m_idx, nbr_m_idx))) sort_by.append(b.GetData('WibergBondOrder')) return atoms_to_add, sort_by
def get_bond(mol, bond_tuple): """ Get bond in molecule Parameters ---------- mol : oemole with map indices bond_tuple : tuple with map indices of bond Returns ------- bond if found, False otherwise """ a1 = mol.GetAtom(oechem.OEHasMapIdx(bond_tuple[0])) a2 = mol.GetAtom(oechem.OEHasMapIdx(bond_tuple[1])) if not a1 or not a2: return False bond = mol.GetBond(a1, a2) if not bond: return False return bond
def frags_with_nbrs(parent, frags, nbrs): return_frags = {} for f in frags: keep = True mol = oechem.OEMol() oechem.OESmilesToMol(mol, frags[f]['map_to_parent']) for n in nbrs: a = mol.GetAtom(oechem.OEHasMapIdx(n)) if not a: keep = False if keep: return_frags[f] = frags[f] return return_frags
def SetSDData(A_IDX, B_IDX, C_IDX, D_IDX, torsion, torsionMol): taIdx = torsionMol.GetAtom(oechem.OEHasMapIdx(A_IDX)).GetIdx() + 1 tbIdx = torsionMol.GetAtom(oechem.OEHasMapIdx(B_IDX)).GetIdx() + 1 tcIdx = torsionMol.GetAtom(oechem.OEHasMapIdx(C_IDX)).GetIdx() + 1 tdIdx = torsionMol.GetAtom(oechem.OEHasMapIdx(D_IDX)).GetIdx() + 1 apStr = "cs1:0:1;1%{}:1%{}:1%{}:1%{}".format(taIdx, tbIdx, tcIdx, tdIdx) oechem.OESetSDData(torsionMol, "TORSION_ATOMPROP", apStr) fragTorAtoms = "{} {} {} {}".format(taIdx, tbIdx, tcIdx, tdIdx) oechem.OESetSDData(torsionMol, TORSION_ATOMS_FRAG_KEY, fragTorAtoms) parentTorAtoms = "{} {} {} {}".format(torsion.a.GetIdx() + 1, torsion.b.GetIdx() + 1, torsion.c.GetIdx() + 1, torsion.d.GetIdx() + 1) oechem.OESetSDData(torsionMol, TORSION_ATOMS_PARENT_MOL_KEY, parentTorAtoms) atom_map = "" for atom in torsionMol.GetAtoms(): atom_map += str(atom.GetIdx() + 1) + "_" + str( atom.GetData("idx")) + "-" atom_map = atom_map[:-1] oechem.OESetSDData(torsionMol, FRAGMENT_TO_PARENT_ATOMS_KEY, atom_map)
def generate_grid_conformers(molecule, dihedrals, intervals, max_rotation=360, copy_mol=True): """ Generate conformers using torsion angle grids. Parameters ---------- molecule: OEMol dihedrals: list of intervals Returns ------- """ # molecule must be mapped if copy_mol: molecule = copy.deepcopy(molecule) if cmiles.utils.has_atom_map(molecule): remove_map(molecule) else: raise ValueError("Molecule must have map indices") # Check length of dihedrals match length of intervals conf_mol = generate_conformers(molecule, max_confs=1) conf = conf_mol.GetConfs().next() coords = oechem.OEFloatArray(conf.GetMaxAtomIdx() * 3) conf.GetCoords(coords) torsions = [[conf_mol.GetAtom(oechem.OEHasMapIdx(i + 1)) for i in dih] for dih in dihedrals] for i, tor in enumerate(torsions): copy_conf_mol = copy.deepcopy(conf_mol) conf_mol.DeleteConfs() for conf in copy_conf_mol.GetConfs(): coords = oechem.OEFloatArray(conf.GetMaxAtomIdx() * 3) conf.GetCoords(coords) for angle in range(5, max_rotation + 5, intervals[i]): newconf = conf_mol.NewConf(coords) oechem.OESetTorsion(newconf, tor[0], tor[1], tor[2], tor[3], radians(angle)) restore_map(conf_mol) return conf_mol
def AddRelevantRingAtoms(mol, torsion, torsionSet): atom1or2 = oechem.OEOrAtom(oechem.OEHasMapIdx(1), oechem.OEHasMapIdx(2)) ringNbrs = [] for atom in mol.GetAtoms( oechem.OEAndAtom(oechem.OEAtomIsInRing(), atom1or2)): for nbr in atom.GetAtoms( oechem.OEAndAtom(oechem.OENotAtom(atom1or2), oechem.OENotAtom( oechem.OEAtomIsInRing()))): if nbr.IsHydrogen(): ringNbrs.append(nbr) continue if nbr.IsOxygen() and mol.GetBond(atom, nbr).GetOrder() == 2: ringNbrs.append(nbr) continue if TorsionGenerator.IsOrtho(nbr, torsion): ringNbrs.append(nbr) for nbr in ringNbrs: if not torsionSet.HasAtom(nbr): nbr.SetMapIdx(2) torsionSet.AddAtom(nbr)
def MarkBridgingAtoms(BRIDGE_ATOM_IDX, mol, torsionSet): NorOorS = oechem.OEOrAtom( oechem.OEOrAtom(oechem.OEIsNitrogen(), oechem.OEIsOxygen()), oechem.OEIsSulfur()) for atom in mol.GetAtoms( oechem.OEAndAtom(oechem.OEHasMapIdx(2), NorOorS)): for nbr in atom.GetAtoms(oechem.OEIsHeavy()): if not torsionSet.HasAtom(nbr): if nbr.GetMapIdx() == 0: torsionSet.AddAtom(nbr) if nbr.GetHvyDegree() == 1: nbr.SetMapIdx(3) continue nbr.SetMapIdx(BRIDGE_ATOM_IDX)
def generate_torsion_index(fb_mol, torsion): assert hasattr( fb_mol, 'oe_mol' ), 'fb_mol does not have oe_mol attr, did you create it using read_sdf_to_fb_mol?' oe_mol = fb_mol.oe_mol mapped_smiles = cmiles.utils.mol_to_smiles(oe_mol) # create a new mol and convert mapped smiles back to mol mol = oechem.OEMol() oechem.OESmilesToMol(mol, mapped_smiles) for a in mol.GetAtoms(): if not a.GetMapIdx() - 1 in torsion: a.SetMapIdx(0) for i, t in enumerate(torsion): a = mol.GetAtom(oechem.OEHasMapIdx(t + 1)) a.SetMapIdx(i + 1) return oechem.OEMolToSmiles(mol)
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())
def get_bond(mol, bond_idx): """ Get oebond object Parameters ---------- mol : oemol Molecule to extract bond from bond_idx : tuple of ints tuple of map indices of atoms in bond Returns ------- bond: oebond """ atoms = [mol.GetAtom(oechem.OEHasMapIdx(i)) for i in bond_idx] bond = mol.GetBond(atoms[0], atoms[1]) return bond
def generate_index(mol, labeled_atoms): """ Generate SMILES with labeled atoms Parameters ---------- mol : oechem.OEMol Must have atom indices that correspond to labeled atoms labeled_atoms : tuple of ints ints should be -1 of atom map Returns ------- labeled SMILES """ for a in mol.GetAtoms(): if not a.GetMapIdx() - 1 in labeled_atoms: a.SetMapIdx(0) for i, l in enumerate(labeled_atoms): a = mol.GetAtom(oechem.OEHasMapIdx(l + 1)) a.SetMapIdx(i + 1) return oechem.OEMolToSmiles(mol)
#for i in range(chunk): # for j in range(6) extra = n % (plots - 2) for i in range(int(chunk)): for j in range(plots - 2): try: key = keys[(plots - 2) * i + j] except IndexError: continue figure = plt.subplot2grid((3, 2), (0, 0), rowspan=2) img = mpimg.imread('{}_mapped.png'.format(ki)) imgplot = plt.imshow(img, interpolation='none') plt.xticks([]) plt.yticks([]) bond = bond_order_wiberg[key] atom_1 = molecule_charged.GetAtom(oechem.OEHasMapIdx(key[0])) atom_2 = molecule_charged.GetAtom(oechem.OEHasMapIdx(key[1])) bond_oe = molecule_charged.GetBond(atom_1, atom_2) wiberg_oe = bond_oe.GetData('WibergBondOrder') if j == 0: plt.subplot2grid((3, 2), (0, 1)) #plt.(bond_order_wiberg[key], label='Wiberg_psi4', kde=True) plt.hist(bond_order_wiberg[key], label='Wiberg_psi4', alpha=1.0) plt.hist(bond_order_mayer[key], label='Mayer_psi4', alpha=1.0) plt.vlines(wiberg_oe, ymin=0, ymax=len(bond_order_wiberg[key]) / 2.5,
def highltigh_torsion_by_cluster(mapped_molecule, clustered_dihedrals, fname, width=600, height=400): """ Highlight torsion by cluster. This is used to visualize clustering output. Parameters ---------- mapped_molecule: oemol with map indices clustered_dihedrals fname width height Returns ------- """ mol = oechem.OEMol(mapped_molecule) atom_bond_sets = [] for cluster in clustered_dihedrals: atom_bond_set = oechem.OEAtomBondSet() for dihedral in clustered_dihedrals[cluster]: a = mol.GetAtom(oechem.OEHasMapIdx(dihedral[0] + 1)) atom_bond_set.AddAtom(a) for idx in dihedral[1:]: a2 = mol.GetAtom(oechem.OEHasMapIdx(idx + 1)) atom_bond_set.AddAtom(a2) bond = mol.GetBond(a, a2) atom_bond_set.AddBond(bond) a = a2 atom_bond_sets.append(atom_bond_set) dopt = oedepict.OEPrepareDepictionOptions() dopt.SetSuppressHydrogens(False) oedepict.OEPrepareDepiction(mol, dopt) opts = oedepict.OE2DMolDisplayOptions(width, height, oedepict.OEScale_AutoScale) opts.SetTitleLocation(oedepict.OETitleLocation_Hidden) disp = oedepict.OE2DMolDisplay(mol, opts) aroStyle = oedepict.OEHighlightStyle_Color aroColor = oechem.OEColor(oechem.OEBlack) oedepict.OEAddHighlighting(disp, aroColor, aroStyle, oechem.OEIsAromaticAtom(), oechem.OEIsAromaticBond()) hstyle = oedepict.OEHighlightStyle_BallAndStick # if color: # highlight = oechem.OEColor(color) # # combine all atom_bond_sets # atom_bond_set = oechem.OEAtomBondSet() # for ab_set in atom_bond_sets: # for a in ab_set.GetAtoms(): # atom_bond_set.AddAtom(a) # for b in ab_set.GetBonds(): # atom_bond_set.AddBond(b) # oedepict.OEAddHighlighting(disp, highlight, hstyle, atom_bond_set) # else: highlight = oedepict.OEHighlightOverlayByBallAndStick( oechem.OEGetContrastColors()) oedepict.OEAddHighlightOverlay(disp, highlight, atom_bond_sets) #hcolor = oechem.OEColor(oechem.OELightBlue) #oedepict.OEAddHighlighting(disp, hcolor, hstyle, atom_bond_sets) return oedepict.OERenderMolecule(fname, disp)
def visualize_mols(smiles, fname, rows, cols, bond_idx, wbos, colors, align_to=0, circle=None): """ Visualize molecules with highlighted bond and labeled with WBO Parameters ---------- smiles : list of SMILES to visualize. bond atoms should have map indices fname : str filename rows : int cols : int bond_idx : tuple of atom maps of bond to highlight. wbos : list of floats colors : list of hex values for colors align_to: int, optional, default 0 index for which molecule to align to. If zero, will align to first molecules in SMILES list """ itf = oechem.OEInterface() ropts = oedepict.OEReportOptions(rows, cols) ropts.SetHeaderHeight(25) ropts.SetFooterHeight(25) ropts.SetCellGap(2) ropts.SetPageMargins(10) report = oedepict.OEReport(ropts) cellwidth, cellheight = report.GetCellWidth(), report.GetCellHeight() opts = oedepict.OE2DMolDisplayOptions(cellwidth, cellheight, oedepict.OEScale_AutoScale) oedepict.OESetup2DMolDisplayOptions(opts, itf) # align to chosen molecule ref_mol = oechem.OEGraphMol() oechem.OESmilesToMol(ref_mol, smiles[align_to]) oedepict.OEPrepareDepiction(ref_mol) mols = [] minscale = float("inf") for s in smiles: mol = oechem.OEMol() oechem.OESmilesToMol(mol, s) mols.append(mol) oedepict.OEPrepareDepiction(mol, False, True) minscale = min(minscale, oedepict.OEGetMoleculeScale(mol, opts)) opts.SetScale(minscale) for i, mol in enumerate(mols): cell = report.NewCell() oedepict.OEPrepareDepiction(mol, False, True) bond = get_bond(mol, bond_idx) atom_bond_set = oechem.OEAtomBondSet() atom_bond_set.AddAtoms([bond.GetBgn(), bond.GetEnd()]) atom_bond_set.AddBond(bond) hstyle = oedepict.OEHighlightStyle_BallAndStick if i == 3: hcolor = oechem.OERed else: hcolor = oechem.OEColor(*colors[i]) overlaps = oegraphsim.OEGetFPOverlap( ref_mol, mol, oegraphsim.OEGetFPType(oegraphsim.OEFPType_Tree)) oedepict.OEPrepareMultiAlignedDepiction(mol, ref_mol, overlaps) #opts.SetBondPropLabelFontScale(4.0) disp = oedepict.OE2DMolDisplay(mol, opts) oedepict.OEAddHighlighting(disp, hcolor, hstyle, atom_bond_set) font = oedepict.OEFont(oedepict.OEFontFamily_Default, oedepict.OEFontStyle_Default, 24, oedepict.OEAlignment_Default, oechem.OEBlack) bond_label = oedepict.OEHighlightLabel("{:.2f}".format(wbos[i]), hcolor) bond_label.SetFontScale(4.0) bond_label.SetFont(font) # generate circle atom_bond_set_circle = oechem.OEAtomBondSet() if circle is not None: color = oechem.OEColor(*colors[i]) highlight = oedepict.OEHighlightByCogwheel(color) highlight.SetBallRadiusScale(5.0) for m in circle: print(m) if m == 1: continue atom = mol.GetAtom(oechem.OEHasMapIdx(m)) print(atom) atom_bond_set_circle.AddAtom(atom) for bond_tuple in itertools.combinations(circle, 2): bond_test = get_bond(mol, bond_tuple) if bond_test: atom_bond_set_circle.AddBond(bond_test) #highlight.SetColor(color) oedepict.OEAddHighlighting(disp, highlight, atom_bond_set_circle) oedepict.OEAddLabel(disp, bond_label, atom_bond_set) oedepict.OERenderMolecule(cell, disp) # oedepict.OEDrawCurvedBorder(cell, oedepict.OELightGreyPen, 10.0) return (oedepict.OEWriteReport(fname, report))
def visualize_bond_atom_sensitivity(mols, bonds, scores, fname, rows, cols, atoms=None, min_scale=True): """ Parameters ---------- mols : bonds : scores : fname : wbos : rows : cols : atoms : height : width : Returns ------- """ itf = oechem.OEInterface() ropts = oedepict.OEReportOptions(rows, cols) ropts.SetHeaderHeight(0.01) ropts.SetFooterHeight(0.01) ropts.SetCellGap(0.0001) ropts.SetPageMargins(0.01) report = oedepict.OEReport(ropts) cellwidth, cellheight = report.GetCellWidth(), report.GetCellHeight() opts = oedepict.OE2DMolDisplayOptions(cellwidth, cellheight, oedepict.OEScale_AutoScale) oedepict.OESetup2DMolDisplayOptions(opts, itf) opts.SetAromaticStyle(oedepict.OEAromaticStyle_Circle) opts.SetAtomColorStyle(oedepict.OEAtomColorStyle_WhiteMonochrome) pen = oedepict.OEPen(oechem.OEBlack, oechem.OEBlack, oedepict.OEFill_Off, 0.9) opts.SetDefaultBondPen(pen) oedepict.OESetup2DMolDisplayOptions(opts, itf) if min_scale: minscale = float("inf") for m in mols: oedepict.OEPrepareDepiction(m, False, True) minscale = min(minscale, oedepict.OEGetMoleculeScale(m, opts)) opts.SetScale(minscale) for i, mol in enumerate(mols): cell = report.NewCell() oedepict.OEPrepareDepiction(mol, False, True) atom_bond_sets = [] for j, bond in enumerate(bonds[i]): bo = get_bond(mol, bond) atom_bond_set = oechem.OEAtomBondSet() atom_bond_set.AddBond(bo) atom_bond_sets.append(atom_bond_set) opts.SetTitleLocation(oedepict.OETitleLocation_Hidden) disp = oedepict.OE2DMolDisplay(mol, opts) hstyle = oedepict.OEHighlightStyle_Stick hstyle_2 = oedepict.OEHighlightStyle_Color score = scores[i] norm = plt.Normalize(0, max(score)) colors = plt.cm.coolwarm(norm(score)) colors_oe = [rbg_to_int(c, 200) for c in colors] for j, atom_bond_set in enumerate(atom_bond_sets): highlight = oechem.OEColor(*colors_oe[j]) oedepict.OEAddHighlighting(disp, highlight, hstyle, atom_bond_set) oedepict.OEAddHighlighting(disp, highlight, hstyle_2, atom_bond_set) highlight = oedepict.OEHighlightByCogwheel(oechem.OEDarkPurple) highlight.SetBallRadiusScale(5.0) if not atoms is None: for a_b in atoms[i]: if isinstance(a_b[-1], list): for k, c in enumerate(a_b[-1]): print(c) color = oechem.OEColor(*colors_oe[c]) highlight.SetBallRadiusScale(5.0 - 2.5 * k) highlight.SetColor(color) atom_bond_set_a = oechem.OEAtomBondSet() if len(a_b[0]) == 1: a = mol.GetAtom(oechem.OEHasMapIdx(a_b[0][0])) atom_bond_set_a.AddAtom(a) oedepict.OEAddHighlighting(disp, highlight, atom_bond_set_a) else: color = oechem.OEColor(*colors_oe[a_b[-1]]) highlight.SetColor(color) atom_bond_set_a = oechem.OEAtomBondSet() if len(a_b[0]) == 1: a = mol.GetAtom(oechem.OEHasMapIdx(a_b[0][0])) atom_bond_set_a.AddAtom(a) else: for b in itertools.combinations(a_b[0], 2): bo = get_bond(mol, b) if not bo: continue atom_bond_set_a.AddAtom(bo.GetBgn()) atom_bond_set_a.AddAtom(bo.GetEnd()) atom_bond_set_a.AddBond(bo) oedepict.OEAddHighlighting(disp, highlight, atom_bond_set_a) oedepict.OERenderMolecule(cell, disp) # oedepict.OEDrawCurvedBorder(cell, oedepict.OELightGreyPen, 10.0) return oedepict.OEWriteReport(fname, report)
def add_one_bond(molecule, atoms, bonds, functional_groups, ring_systems, target_bond, heuristic): bond_atom_1 = molecule.GetAtom(oechem.OEHasMapIdx(target_bond[0])) bond_atom_2 = molecule.GetAtom(oechem.OEHasMapIdx(target_bond[1])) atoms_to_add = [] sort_by_1 = [] sort_by_2 = [] sort_by = [] for m_idx in atoms: a = molecule.GetAtom(oechem.OEHasMapIdx(m_idx)) if a is None: print('{} is none'.format(m_idx)) continue for nbr in a.GetAtoms(): nbr_m_idx = nbr.GetMapIdx() if not nbr.IsHydrogen() and not nbr_m_idx in atoms: b = molecule.GetBond(a, nbr) atoms_to_add.append((nbr_m_idx, (m_idx, nbr_m_idx))) if heuristic == 'wbo': sort_by.append(b.GetData('WibergBondOrder')) reverse = True elif heuristic == 'path_length': sort_by_1.append(oechem.OEGetPathLength(bond_atom_1, nbr)) sort_by_2.append(oechem.OEGetPathLength(bond_atom_2, nbr)) #sort_by.append(oechem.OEGetPathLength(bond_atom, nbr)) reverse = False else: raise ValueError( 'Only wbo and path_lenght are supported heuristics') if heuristic == 'path_length': min_1 = min(sort_by_1) min_2 = min(sort_by_2) if min_1 < min_2: sort_by = sort_by_1 elif min_2 < min_1: sort_by = sort_by_2 elif min_1 == min_2: # Find the equivalent atoms and take the one with higher WBO indices = [] for l in [sort_by_1, sort_by_2]: indices.extend([i for i, x in enumerate(l) if x == min_1]) atoms_to_add = [atoms_to_add[i] for i in indices] for a, b in atoms_to_add: a1 = molecule.GetAtom(oechem.OEHasMapIdx(b[0])) a2 = molecule.GetAtom(oechem.OEHasMapIdx(b[1])) bond = molecule.GetBond(a1, a2) sort_by.append(bond.GetData('WibergBondOrder')) reverse = True sorted_atoms = [ a for _, a in sorted(zip(sort_by, atoms_to_add), reverse=reverse) ] a = molecule.GetAtom(oechem.OEHasMapIdx(sorted_atoms[0][0])) if 'ringsystem' in a.GetData(): ring_idx = a.GetData('ringsystem') atoms.update(ring_systems[ring_idx][0]) bonds.update(ring_systems[ring_idx][1]) if 'fgroup' in a.GetData(): fgroup = a.GetData('fgroup') atoms.update(functional_groups[fgroup][0]) bonds.update(functional_groups[fgroup][1]) atoms.add(sorted_atoms[0][0]) bonds.add(sorted_atoms[0][1]) return atoms, bonds
def _oe_render_fragment( parent: Molecule, fragment: Molecule, bond_indices: BondTuple, image_width: int = 283, image_height: int = 169, ) -> str: from openeye import oechem, oedepict # Map the OpenFF molecules into OE ones, making sure to explicitly set the atom # map on the OE object as this is not handled by the OpenFF toolkit. oe_parent = parent.to_openeye() for atom in oe_parent.GetAtoms(): atom.SetMapIdx(get_map_index(parent, atom.GetIdx(), False)) oedepict.OEPrepareDepiction(oe_parent) oe_fragment = fragment.to_openeye() for atom in oe_fragment.GetAtoms(): atom.SetMapIdx(get_map_index(fragment, atom.GetIdx(), False)) oe_parent_bond = oe_parent.GetBond( oe_parent.GetAtom(oechem.OEHasMapIdx(bond_indices[0])), oe_parent.GetAtom(oechem.OEHasMapIdx(bond_indices[1])), ) # Set-up common display options. image = oedepict.OEImage(image_width, image_height) display_options = oedepict.OE2DMolDisplayOptions( image_width, image_height, oedepict.OEScale_AutoScale) display_options.SetTitleLocation(oedepict.OETitleLocation_Hidden) display_options.SetAtomColorStyle( oedepict.OEAtomColorStyle_WhiteMonochrome) display_options.SetAtomLabelFontScale(1.2) # display_options.SetBondPropertyFunctor(_oe_wbo_label_display({bond_indices})) display = oedepict.OE2DMolDisplay(oe_parent, display_options) fragment_atom_predicate, fragment_bond_predicate = _oe_fragment_predicates( {atom.GetMapIdx() for atom in oe_fragment.GetAtoms()}) not_fragment_atoms = oechem.OENotAtom(fragment_atom_predicate) not_fragment_bonds = oechem.OENotBond(fragment_bond_predicate) oedepict.OEAddHighlighting( display, oedepict.OEHighlightByColor(oechem.OEGrey, 0.75), not_fragment_atoms, not_fragment_bonds, ) rotatable_bond = oechem.OEAtomBondSet() rotatable_bond.AddBond(oe_parent_bond) rotatable_bond.AddAtom(oe_parent_bond.GetBgn()) rotatable_bond.AddAtom(oe_parent_bond.GetEnd()) oedepict.OEAddHighlighting( display, oechem.OEColor(oechem.OELimeGreen), oedepict.OEHighlightStyle_BallAndStick, rotatable_bond, ) oedepict.OERenderMolecule(image, display) svg_contents = oedepict.OEWriteImageToString("svg", image) return svg_contents.decode()
cmiles_ids = cmiles.get_molecule_ids(smiles, strict=False) mapped_smiles = cmiles_ids[ 'canonical_isomeric_explicit_hydrogen_mapped_smiles'] qcarchive_mols = [ cmiles.utils.mol_to_map_ordered_qcschema(conf, mapped_smiles) for conf in conformers.GetConfs() ] job_idx = cmiles.utils.to_canonical_label(smiles, torsion) # Map torsion indices to canonical ordered mapped SMILES mol_copy = oechem.OEMol(oemol) oechem.OEAddExplicitHydrogens(mol_copy) cmiles._cmiles_oe.canonical_order_atoms(mol_copy) dih = [] for m_idx in torsion: atom = mol_copy.GetAtom(oechem.OEHasMapIdx(m_idx + 1)) dih.append(atom.GetIdx()) torsion_dict[job_idx] = { 'initial_molecules': qcarchive_mols, 'dihedral': [dih], 'grid': [15], 'cmiles_identifiers': cmiles_ids } if mol not in keep_track: keep_track[mol] = {} if bond not in keep_track[mol]: keep_track[mol][bond] = {} keep_track[mol][bond][frag] = job_idx frag = 'pfizer'
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)
continue if a1.IsHalogen() or a2.IsHalogen(): continue if bond.GetOrder() > 1: continue if bond.IsInRing(): continue key = (a1.GetMapIdx(), a2.GetMapIdx()) if key not in frag_with_bond and tuple(reversed(key)) not in frag_with_bond: frag_with_bond[key] = {} r_bonds.append(key) #r_bonds = [(b.GetBgn().GetMapIdx(), b.GetEnd().GetMapIdx()) for b in oemol.GetBonds() if b.IsRotor()] for b in r_bonds: terminal = False # check if it's terminal bond = oemol.GetBond(oemol.GetAtom(oechem.OEHasMapIdx(b[0])), oemol.GetAtom(oechem.OEHasMapIdx(b[1]))) if not bond.IsRotor(): # This is terminal terminal = True reverse = tuple(reversed(b)) if b not in oe_wbo_deserialized[frag]: # Try reverse bo = oe_wbo_deserialized[frag][reverse] else: bo = oe_wbo_deserialized[frag][b] if terminal: frag_key = frag + '_term' else: frag_key = frag try: frag_with_bond[b][frag_key] = bo
def to_pdf(molecules, bond_map_idx, fname, rows=3, cols=2, align=None): """ Generate PDF of list of oemols or SMILES Parameters ---------- molecules : list of OEMols These mols need to have map indices on bond of interest and WBO attached to that bond's data fname : str Name of PDF rows : int How many rows of molecules per page cols : int How many columns of molecule per page bond_map_idx : tuple of bond to highlight align: oemol molecule to align all other molecules in the list """ itf = oechem.OEInterface() ropts = oedepict.OEReportOptions(rows, cols) ropts.SetHeaderHeight(25) ropts.SetFooterHeight(25) ropts.SetCellGap(2) ropts.SetPageMargins(10) report = oedepict.OEReport(ropts) cellwidth, cellheight = report.GetCellWidth(), report.GetCellHeight() opts = oedepict.OE2DMolDisplayOptions(cellwidth, cellheight, oedepict.OEScale_AutoScale) oedepict.OESetup2DMolDisplayOptions(opts, itf) if align: if isinstance(align, str): ref_mol = oechem.OEGraphMol() oechem.OESmilesToMol(ref_mol, align) elif isinstance(align, (oechem.OEMol, oechem.OEMolBase, oechem.OEGraphMol)): ref_mol = align oedepict.OEPrepareDepiction(ref_mol) for i, mol in enumerate(molecules): cell = report.NewCell() mol_copy = oechem.OEMol(mol) oedepict.OEPrepareDepiction(mol_copy, False, True) atom_bond_set = oechem.OEAtomBondSet() a1 = mol_copy.GetAtom(oechem.OEHasMapIdx(bond_map_idx[0])) a2 = mol_copy.GetAtom(oechem.OEHasMapIdx(bond_map_idx[1])) b = mol_copy.GetBond(a1, a2) opts.SetBondPropertyFunctor(fragmenter.chemi.LabelWibergBondOrder()) atom_bond_set.AddAtom(a1) atom_bond_set.AddAtom(a2) atom_bond_set.AddBond(b) hstyle = oedepict.OEHighlightStyle_BallAndStick hcolor = oechem.OEColor(oechem.OELightBlue) overlaps = oegraphsim.OEGetFPOverlap( ref_mol, mol_copy, oegraphsim.OEGetFPType(oegraphsim.OEFPType_Tree)) oedepict.OEPrepareMultiAlignedDepiction(mol_copy, ref_mol, overlaps) disp = oedepict.OE2DMolDisplay(mol_copy, opts) oedepict.OEAddHighlighting(disp, hcolor, hstyle, atom_bond_set) oedepict.OERenderMolecule(cell, disp) oedepict.OEDrawCurvedBorder(cell, oedepict.OELightGreyPen, 10.0) oedepict.OEWriteReport(fname, report)
def get_bond(mol, bond_idx): atoms = [mol.GetAtom(oechem.OEHasMapIdx(i)) for i in bond_idx] bond = mol.GetBond(atoms[0], atoms[1]) return bond
def generate_constraint_opt_input(qc_molecule, dihedrals, maximum_rotation=30, interval=5, filename=None): """ Parameters ---------- qc_molecule dihedrals Returns ------- QCFractal optimization jobs input """ from openeye import oechem optimization_jobs = {} tagged_smiles = qc_molecule['identifiers']['canonical_isomeric_explicit_hydrogen_mapped_smiles'] mol = oechem.OEMol() oechem.OESmilesToMol(mol, tagged_smiles) atom_map = get_atom_map(mol, tagged_smiles) coords = chemi.from_mapped_xyz_to_mol_idx_order(qc_molecule['geometry'], atom_map) # convert coord to Angstrom coords = coords * utils.BOHR_2_ANGSTROM conf = mol.GetConfs().next() conf.SetCoords(oechem.OEFloatArray(coords)) # new molecule for setting dihedral angles mol_2 = oechem.OEMol(mol) conf_2 = mol_2.GetConfs().next() coords_2 = oechem.OEFloatArray(conf_2.GetMaxAtomIdx()*3) conf.GetCoords(coords_2) mol_2.DeleteConfs() interval = radians(interval) max_rot = radians(maximum_rotation) for dihedral in dihedrals: #j = 0 dih_idx = dihedrals[dihedral] tor = [] for i in dih_idx: a = mol.GetAtom(oechem.OEHasMapIdx(i+1)) tor.append(a) dih_angle = oechem.OEGetTorsion(conf, tor[0], tor[1], tor[2], tor[3]) for i, angle in enumerate(np.arange(dih_angle-max_rot, dih_angle+max_rot, interval)): newconf = mol.NewConf(coords_2) oechem.OESetTorsion(newconf, tor[0], tor[1], tor[2], tor[3], angle) #new_angle = oechem.OEGetTorsion(newconf, tor[0], tor[1], tor[2], tor[3]) # if new_angle == dih_angle: # j += 1 # if j > 1: # # One equivalent angle should be generated. # logger().warning("Openeye did not generate a new conformer for torsion and angle {} {}. Will not generate" # "qcfractal optimizaiton input".format(dih_idx, angle)) # break if filename: pdb = oechem.oemolostream("{}_{}.pdb".format(filename, i)) oechem.OEWritePDBFile(pdb, newconf) symbols, geometry = chemi.to_mapped_geometry(newconf, atom_map) qc_molecule = copy.deepcopy(qc_molecule) qc_molecule['geometry'] = geometry qc_molecule['symbols'] = symbols degree = degrees(angle) optimization_jobs['{}_{}'.format(dih_idx, int(round(degree)))] = { 'type': 'optimization_input', 'initial_molecule': qc_molecule, 'dihedral': dih_idx, 'constraints': { "set": [{ "type": "dihedral", "indices": dih_idx, "value": degree }] } } return optimization_jobs