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)
def get_specific_dihedral_inchi_key(mol): """ generates unique dihedral inchi key by mutating all four dihedral atoms """ try: a, b, c, d = get_torsion_oeatom_list(mol) modified_inchi = get_modified_inchi_key(mol, [a, b, c, d]) inchiKey = oechem.OECreateInChIKey(mol) + modified_inchi return inchiKey except Exception as e: logging.warning(e) return None
def get_generic_dihedral_inchi_key(mol): """ generates dihedral inchi key after mutating only the central two atoms """ try: _, b, c, _ = get_torsion_oeatom_list(mol) modified_inchi = get_modified_inchi_key(mol, [b, c]) inchiKey = oechem.OECreateInChIKey(mol) + modified_inchi return inchiKey except Exception as e: logging.warning(e) return None
def __makeChemCompDescriptorCategory(self, ccId, oeMol): """ loop_ _pdbx_chem_comp_descriptor.comp_id _pdbx_chem_comp_descriptor.type _pdbx_chem_comp_descriptor.program _pdbx_chem_comp_descriptor.program_version _pdbx_chem_comp_descriptor.descriptor ARG SMILES ACDLabs 10.04 "O=C(O)C(N)CCCNC(=[NH2+])N" ARG SMILES_CANONICAL CACTVS 3.341 "N[C@@H](CCCNC(N)=[NH2+])C(O)=O" ARG SMILES CACTVS 3.341 "N[CH](CCCNC(N)=[NH2+])C(O)=O" ARG SMILES_CANONICAL "OpenEye OEToolkits" 1.5.0 "C(C[C@@H](C(=O)O)N)CNC(=[NH2+])N" ARG SMILES "OpenEye OEToolkits" 1.5.0 "C(CC(C(=O)O)N)CNC(=[NH2+])N" ARG InChI InChI 1.03 "InChI=1S/C6H14N4O2/c7-4(5(11)12)2-1-3-1..... " ARG InChIKey InChI 1.03 ODKSFYDXXFIFQN-BYPYZUCNSA-O # """ rowL = [] # aRow = {} aRow["comp_id"] = ccId aRow["type"] = "SMILES_CANONICAL" aRow["program"] = "OpenEye OEToolkits" aRow["program_version"] = self.__oeVersion aRow["descriptor"] = oechem.OECreateIsoSmiString(oeMol) rowL.append(aRow) # aRow = {} aRow["comp_id"] = ccId aRow["type"] = "SMILES" aRow["program"] = "OpenEye OEToolkits" aRow["program_version"] = self.__oeVersion aRow["descriptor"] = oechem.OECreateCanSmiString(oeMol) rowL.append(aRow) # aRow = {} aRow["comp_id"] = ccId aRow["type"] = "InChI" aRow["program"] = "OpenEye OEToolkits" aRow["program_version"] = self.__oeVersion aRow["descriptor"] = oechem.OECreateInChI(oeMol) rowL.append(aRow) # aRow = {} aRow["comp_id"] = ccId aRow["type"] = "InChIKey" aRow["program"] = "OpenEye OEToolkits" aRow["program_version"] = self.__oeVersion aRow["descriptor"] = oechem.OECreateInChIKey(oeMol) rowL.append(aRow) # return rowL
def extract_molecule_torsion_data(parent_mol, frag_mols=None): """ extract dihedral angle associated with each torsion motif in the input molecule Torsion motifs are represented using generic modified inchi (central two atoms) and specific modified inchi (4 torsion atoms) @param parent_mol: @type parent_mol: oechem.OEGraphMol @return: tuple(str, dict[str, list[float]]) """ if frag_mols is None: frag_mols = get_molecule_torsion_fragments(parent_mol) torsion_data = collections.defaultdict(list) for frag_mol in frag_mols: inchi_key = oechem.OECreateInChIKey(frag_mol) atom_map = get_fragment_to_parent_atom_mapping(parent_mol, frag_mol) try: _, b, c, _ = get_torsion_oeatom_list(frag_mol) for a in b.GetAtoms(oechem.OEIsHeavy()): for d in c.GetAtoms(oechem.OEIsHeavy()): if a.GetIdx() == c.GetIdx() or d.GetIdx() == b.GetIdx(): continue ap = atom_map[a] bp = atom_map[b] cp = atom_map[c] dp = atom_map[d] if (a.GetAtomicNum() == ap.GetAtomicNum() and b.GetAtomicNum() == bp.GetAtomicNum() and c.GetAtomicNum() == cp.GetAtomicNum() and d.GetAtomicNum() == dp.GetAtomicNum()): angle = ( oechem.OEGetTorsion(parent_mol, ap, bp, cp, dp) * oechem.Rad2Deg) torsion_inchi = inchi_key + get_modified_inchi_key( frag_mol, [a, b, c, d]) torsion_data[torsion_inchi].append( (ap.GetIdx(), bp.GetIdx(), cp.GetIdx(), dp.GetIdx(), angle)) except Exception as e: logging.warning(e) continue parent_inchi = get_modified_molecule_inchi(parent_mol) return (parent_inchi, torsion_data)
def get_dihedral_inchi_key(mol): try: a, b, c, d = get_torsion_oeatom_list(mol) ad = a.GetAtomicNum() * d.GetAtomicNum() bc = b.GetAtomicNum() * c.GetAtomicNum() adAro = int(a.IsAromatic()) + int(d.IsAromatic()) bcAro = int(b.IsAromatic()) + int(c.IsAromatic()) count1 = len(list(oechem.OEGetSubtree(b, c))) count2 = len(list(oechem.OEGetSubtree(c, b))) count = count1 * count2 inchiKey = oechem.OECreateInChIKey(mol) inchiKey = inchiKey + str(ad) + str(bc) + str(adAro) + str( bcAro) + str(count) return inchiKey except Exception as e: logging.warning(e) return None
def get_modified_molecule_inchi(mol): title = mol.GetTitle().replace(",", "") inchi = oechem.OECreateInChIKey(mol) return inchi + title
def construct_dihedral_energy_profile(torsion_conformers, num_points=24): angle_list = np.array([360 * i / num_points for i in range(num_points)]) num_confs = 0 profile = np.full(num_points, np.nan) for mol in torsion_conformers: if not mol: continue num_confs += 1 conf = mol.GetActive() conf_title = get_sd_data(conf, "CONFORMER_LABEL") tor_atoms = get_sd_data(mol, "TORSION_ATOMS_ParentMol").split() parent_name = conf_title[:-3] dih_label = "_".join(str(x) for x in tor_atoms) fragment_label = parent_name + "_" + dih_label angle_idx = int(conf_title[-2:]) profile[angle_idx] = np.float(get_sd_data(conf, "PSI4_ENERGY")) logging.debug("angle_idx: %d", angle_idx) logging.debug("Psi4 Energy: %f", float(get_sd_data(conf, "PSI4_ENERGY"))) # check for angles where no energies are available for angle in angle_list[np.all(np.isnan(profile))]: logging.warning( "Warning: No energies found for angle {:.1f} for fragment: {}". format(angle, fragment_label)) # calculate relative energies min_energy = np.nanmin(profile) profile -= min_energy profile[np.isnan(profile)] = -1 # set nans to -1 torsional_strain = np.column_stack((angle_list, profile)) # combine conformers output_conformers = oechem.OEMol(torsion_conformers[0]) output_conformers.DeleteConfs() title = fragment_label output_conformers.SetTitle(title) # setup normalization torsion_tag = "TORSION_ATOMS_FRAGMENT" torsion_atoms_in_fragment = get_sd_data(mol, torsion_tag).split() print(torsion_atoms_in_fragment) dihedral_atom_indices = [int(x) - 1 for x in torsion_atoms_in_fragment] dih, _ = get_dihedral(output_conformers, dihedral_atom_indices) for old_conf in torsion_conformers: if old_conf: new_conf = output_conformers.NewConf(old_conf) normalize_coordinates(new_conf, dih) oechem.OEClearSDData(new_conf) for dp in oechem.OEGetSDDataPairs(old_conf.GetActive()): if dp.GetTag() not in ["OEConfTitle", "CONFORMER_LABEL"]: oechem.OESetSDData(new_conf, dp.GetTag(), dp.GetValue()) torsion_angle = get_sd_data(old_conf, "TORSION_ANGLE") title = fragment_label + ": Angle " + torsion_angle new_conf.SetTitle(title) write_energy_profile_to_sddata(output_conformers, torsional_strain.copy()) # Calculate all possible torsion inchi keys for this fragment torsion_inchi_list = [] inchi_key = oechem.OECreateInChIKey(output_conformers) _, b, c, _ = get_torsion_oeatom_list(output_conformers) for a in b.GetAtoms(oechem.OEIsHeavy()): for d in c.GetAtoms(oechem.OEIsHeavy()): if a.GetIdx() == c.GetIdx() or d.GetIdx() == b.GetIdx(): continue torsion_inchi = inchi_key + get_modified_inchi_key( output_conformers, [a, b, c, d]) torsion_inchi_list.append(torsion_inchi) return output_conformers, torsional_strain, torsion_inchi_list