def generate_enantiomers( molecule: oechem.OEGraphMol, max_centers: int = 12, force_flip: bool = False, enumerate_nitrogens: bool = True, ) -> List[oechem.OEGraphMol]: """ Generate enantiomers of a given molecule. Parameters ---------- molecule: oechem.OEGraphMol An OpenEye molecule. max_centers: int The maximal number of stereo centers to enumerate. force_flip: bool If specified stereo centers should be ignored. enumerate_nitrogens: bool If nitrogens with invertible pyramidal geometry should be enumerated. Returns ------- enantiomers: list of oechem.OEGraphMol A list of OpenEye molecules holding the enantiomers. """ from openeye import oechem, oeomega enantiomers = [ oechem.OEGraphMol(enantiomer) for enantiomer in oeomega.OEFlipper( molecule, max_centers, force_flip, enumerate_nitrogens) ] return enantiomers
def expand_stereochemistry(mols): """Expand stereochemistry when uncertain Parameters ---------- mols : openeye.oechem.OEGraphMol Molecules to be expanded Returns ------- expanded_mols : openeye.oechem.OEMol Expanded molecules """ expanded_mols = list() from openeye import oechem, oeomega omegaOpts = oeomega.OEOmegaOptions() omega = oeomega.OEOmega(omegaOpts) maxcenters = 12 forceFlip = False enumNitrogen = True warts = True # add suffix for stereoisomers for mol in mols: for enantiomer in oeomega.OEFlipper(mol, maxcenters, forceFlip, enumNitrogen, warts): enantiomer = oechem.OEMol(enantiomer) expanded_mols.append(enantiomer) return expanded_mols
def main(argv=[__name__]): if len(argv) != 3: oechem.OEThrow.Usage("%s <infile> <outfile>" % argv[0]) ifs = oechem.oemolistream() if not ifs.open(argv[1]): oechem.OEThrow.Fatal("Unable to open %s for reading" % argv[1]) ofs = oechem.oemolostream() if not ofs.open(argv[2]): oechem.OEThrow.Fatal("Unable to open %s for writing" % argv[2]) if not oechem.OEIs3DFormat(ofs.GetFormat()): oechem.OEThrow.Fatal("Invalid output file format for 3D coordinates!") omegaOpts = oeomega.OEOmegaOptions() omega = oeomega.OEOmega(omegaOpts) for mol in ifs.GetOEMols(): oechem.OEThrow.Info("Title: %s" % mol.GetTitle()) for enantiomer in oeomega.OEFlipper(mol.GetActive(), 12, True): enantiomer = oechem.OEMol(enantiomer) ret_code = omega.Build(enantiomer) if ret_code == oeomega.OEOmegaReturnCode_Success: oechem.OEWriteMolecule(ofs, enantiomer) else: oechem.OEThrow.Warning( "%s: %s" % (enantiomer.GetTitle(), oeomega.OEGetOmegaError(ret_code))) return 0
def FromMol(mol, isomer=True, num_enantiomers=-1): """ Generates a set of conformers as an OEMol object Inputs: mol is an OEMol isomers is a boolean controling whether or not the various diasteriomers of a molecule are created num_enantiomers is the allowable number of enantiomers. For all, set to -1 """ omegaOpts = oeomega.OEOmegaOptions() omegaOpts.SetMaxConfs(199) omega = oeomega.OEOmega(omegaOpts) out_conf = [] ofs = oechem.oemolostream("test.sdf") if not isomer: ret_code = omega.Build(mol) if ret_code == oeomega.OEOmegaReturnCode_Success: out_conf.append(mol) else: oechem.OEThrow.Warning("%s: %s" % (mol.GetTitle(), oeomega.OEGetOmegaError(ret_code))) elif isomer: for enantiomer in oeomega.OEFlipper(mol.GetActive(), 12, True): enantiomer = oechem.OEMol(enantiomer) ret_code = omega.Build(enantiomer) if ret_code == oeomega.OEOmegaReturnCode_Success: out_conf.append(enantiomer) num_enantiomers -= 1 oechem.OEWriteMolecule(ofs, mol) if num_enantiomers == 0: break else: oechem.OEThrow.Warning("%s: %s" % (mol.GetTitle(), oeomega.OEGetOmegaError(ret_code))) return out_conf
def enumerate_from_smiles(smiles, oe_options=None): oe_options = oe_options or OEOptions() omegaOpts = oeomega.OEOmegaOptions(oeomega.OEOmegaSampling_Pose) omegaOpts.SetMaxSearchTime(60) omega = oeomega.OEOmega(omegaOpts) if oe_options.use_tautomer: tautomer_options = oequacpac.OETautomerOptions() pKa_norm = True taut_iter = lambda x: oequacpac.OEGetReasonableTautomers(x, tautomer_options, pKa_norm) else: taut_iter = lambda x: [x] if oe_options.use_flipper: flipper = lambda x: oeomega.OEFlipper(x.GetActive(), oe_options.num_sterocenters, oe_options.force_flipper) else: flipper = lambda x: [x] # get molecule try: molecule = mol_from_smiles(smiles) except ValueError: return [None] results = [] for enantiomer in flipper(molecule): for tautomer in taut_iter(enantiomer): tautomer = oechem.OEMol(tautomer) omega.Build(tautomer) tautomer2 = oechem.OEMol(tautomer) results.append(tautomer2) return results
def FromMol(mol, use_flipper=True, num_sterocenters=12, force_flipper=False): """ Generates a set of conformers as an OEMol object Inputs: mol is an OEMol isomers is a boolean controling whether or not the various diasteriomers of a molecule are created num_enantiomers is the allowable number of enantiomers. For all, set to -1 """ omegaOpts = oeomega.OEOmegaOptions() omegaOpts.SetMaxConfRange("200,800") omegaOpts.SetRangeIncrement(8) omegaOpts.SetMaxSearchTime(30) omega = oeomega.OEOmega(omegaOpts) out_conf = [] for enantiomer in oeomega.OEFlipper(mol.GetActive(), num_sterocenters, force_flipper): enantiomer = oechem.OEMol(enantiomer) ret_code = omega.Build(enantiomer) if ret_code == oeomega.OEOmegaReturnCode_Success: out_conf.append(enantiomer) else: oechem.OEThrow.Warning( "%s: %s" % (mol.GetTitle(), oeomega.OEGetOmegaError(ret_code))) return out_conf
def from_oemol(self, from_oemol): with self.logger("from_oemol") as logger: tautomer_options = oequacpac.OETautomerOptions() tautomer_options.SetMaxTautomersGenerated(4096) tautomer_options.SetMaxTautomersToReturn(16) tautomer_options.SetCarbonHybridization(True) tautomer_options.SetMaxZoneSize(50) tautomer_options.SetApplyWarts(True) pKa_norm = True omegaOpts = oeomega.OEOmegaOptions(oeomega.OEOmegaSampling_Pose) omegaOpts.SetStrictAtomTypes(False) omegaOpts.SetSampleHydrogens(True) omegaOpts.SetMaxSearchTime(30) omegaOpts.SetFixDeleteH(True) omega = oeomega.OEOmega(omegaOpts) options = oeshape.OEROCSOptions() overlayoptions = oeshape.OEOverlayOptions() overlayoptions.SetOverlapFunc( oeshape.OEOverlapFunc(oeshape.OEAnalyticShapeFunc())) options.SetOverlayOptions(overlayoptions) # options.SetNumBestHits(10) options.SetConfsPerHit(200) # options.SetMaxHits(10000) rocs = oeshape.OEROCS(options) for tautomer in oequacpac.OEGetReasonableTautomers( from_oemol, tautomer_options, pKa_norm): logger.log("got enantiomer") for enantiomer in oeomega.OEFlipper(tautomer, 4, False): logger.log("got tautomer ") enantiomer_ = oechem.OEMol(enantiomer) ret_code = omega.Build(enantiomer_) if ret_code != oeomega.OEOmegaReturnCode_Success: logger.error("got oemeg_failed", oeomega.OEGetOmegaError(ret_code)) else: rocs.AddMolecule(oechem.OEMol(enantiomer_)) for res in rocs.Overlay(self.refmol): outmol = oechem.OEMol(res.GetOverlayConfs()) good_mol = oechem.OEMol(outmol) oechem.OEAddExplicitHydrogens(good_mol) oechem.OEClearSDData(good_mol) oeshape.OEDeleteCompressedColorAtoms(good_mol) oeshape.OEClearCachedSelfColor(good_mol) oeshape.OEClearCachedSelfShape(good_mol) oeshape.OERemoveColorAtoms(good_mol) return good_mol logger.error("Returning None.") return None
def expand_stereochemistry(mols): """Expand stereochemistry when uncertain Parameters ---------- mols : openeye.oechem.OEGraphMol Molecules to be expanded Returns ------- expanded_mols : openeye.oechem.OEMol Expanded molecules """ expanded_mols = list() from openeye import oechem, oeomega omegaOpts = oeomega.OEOmegaOptions() omega = oeomega.OEOmega(omegaOpts) maxcenters = 12 forceFlip = False enumNitrogen = False warts = True # add suffix for stereoisomers for mol in mols: compound_title = mol.GetTitle() compound_smiles = oechem.OEMolToSmiles(mol) enantiomers = list() for enantiomer in oeomega.OEFlipper(mol, maxcenters, forceFlip, enumNitrogen, warts): enantiomer = oechem.OEMol(enantiomer) enantiomer_smiles = oechem.OEMolToSmiles(enantiomer) oechem.OESetSDData(enantiomer, 'compound', compound_title) oechem.OESetSDData(enantiomer, 'compound_smiles', compound_smiles) oechem.OESetSDData(enantiomer, 'enantiomer_smiles', enantiomer_smiles) enantiomers.append(enantiomer) expanded_mols += enantiomers # DEBUG if 'EDJ-MED-e4b030d8-2' in mol.GetTitle(): msg = 'Enumerated microstates for compound: ' msg += mol.GetTitle() + '\n' msg += f'{"":5s} ' + oechem.OEMolToSmiles(mol) + '\n' for index, m in enumerate(enantiomers): msg += f'{index:5d} : ' + oechem.OEMolToSmiles(m) + '\n' print(msg) return expanded_mols
def gen_conf(mol): oemols = [] omegaOpts = oeomega.OEOmegaOptions(oeomega.OEOmegaSampling_FastROCS) omega = oeomega.OEOmega(omegaOpts) for enantiomer in oeomega.OEFlipper(mol.GetActive(), 6, True): enantiomer = oechem.OEMol(enantiomer) ret_code = omega.Build(enantiomer) if ret_code == oeomega.OEOmegaReturnCode_Success: halfMol = oechem.OEMol(mol, oechem.OEMCMolType_HalfFloatCartesian) oemols.append(halfMol) else: oechem.OEThrow.Warning( "%s: %s" % (enantiomer.GetTitle(), oeomega.OEGetOmegaError(ret_code))) return oemols
def expand_stereochemistry(mols): """Expand stereochemistry when uncertain Parameters ---------- mols : openeye.oechem.OEGraphMol Molecules to be expanded Returns ------- expanded_mols : openeye.oechem.OEMol Expanded molecules """ expanded_mols = list() from openeye import oechem, oeomega omegaOpts = oeomega.OEOmegaOptions() omega = oeomega.OEOmega(omegaOpts) maxcenters = 12 forceFlip = False enumNitrogen = True warts = True # add suffix for stereoisomers for mol in mols: compound_title = mol.GetTitle() compound_smiles = oechem.OEMolToSmiles(mol) enantiomers = list() for enantiomer in oeomega.OEFlipper(mol, maxcenters, forceFlip, enumNitrogen, warts): enantiomer = oechem.OEMol(enantiomer) enantiomer_smiles = oechem.OEMolToSmiles(enantiomer) oechem.OESetSDData(enantiomer, 'compound', compound_title) oechem.OESetSDData(enantiomer, 'compound_smiles', compound_smiles) oechem.OESetSDData(enantiomer, 'enantiomer_smiles', enantiomer_smiles) enantiomers.append(enantiomer) expanded_mols += enantiomers return expanded_mols
def _enumerate_stereoisomers(molecule, max_states=200, force_flip=True, enum_nitrogen=True, warts=True, verbose=True): """ Enumerate stereoisomers Parameters ---------- molecule : OEMol max_states : int, optional, default 200 max number of states to enumerate force_flip : bool, optional, default True If True, will flip all steocenters. If False, will only flip centers that are undefined enum_nitrogen : bool, optional, default True Invert non-planar nitrogen warts : bool, optional, default True If True, add int to molecule name verbose : bool, optional, default True Returns ------- stereoisomers: list of oemols """ from openeye import oeomega, oechem stereoisomers = [] if verbose: logger().debug("Enumerating stereoisomers...") i = 0 for enantiomer in oeomega.OEFlipper(molecule, max_states, force_flip, enum_nitrogen, warts): i += 1 enantiomer = oechem.OEMol(enantiomer) stereoisomers.append(enantiomer) return stereoisomers
def compute_conformers(smiles=None, smiles_file=None, start_index=0, batch_size=0, out_file=None, bad_file=None, save_csv=False, overwrite=False, save_gzip=False, license=None, timeout=0, max_failures=2): import csv import os from openeye import oechem from openeye import oeomega from openeye import oemolprop import signal os.environ['OE_LICENSE'] = license if save_gzip or save_csv: raise Exception("GZip and CSV not supported") if not overwrite and os.path.exists(out_file): raise Exception("File exists: %s" % out_file) if smiles_file: with open(smiles_file) as current: current.seek(start_index) smiles = [current.readline() for i in range(batch_size)] if len(smiles) == 0: return "" # function to compute enantiomers # separated out so we can use an alarm to timeout def get_enan(omega, enan): enan = oechem.OEMol(enan) ret = omega.Build(enan) return enan, ret def alarm_handler(signum, frame): #print("ALARM signal received") raise Exception() #ofs = oechem.oemolostream() #ofs.SetFormat(oechem.OEFormat_OEB) #if not ofs.open(out_file): # oechem.OEThrow.Fatal("Unable to open %s for writing" % out_file) sep = "," bad = [] mols = [] for s in smiles: mol = s.split(sep) if len(mol) > 1: mols.append(mol[2].rstrip()) # put all mols in a string as we're told it is faster to process this way in_smiles = "\n".join(mols) ims = oechem.oemolistream() ims.SetFormat(oechem.OEFormat_SMI) ims.openstring(in_smiles) # Turn off logging except errors oechem.OEThrow.SetLevel(5) filt = oemolprop.OEFilter(oemolprop.OEFilterType_BlockBuster) #ofs.open(out_file) signal.signal(signal.SIGALRM, alarm_handler) oe_results = [] for mol in ims.GetOEMols(): if filt(mol): oemols = [] ret_code = None omegaOpts = oeomega.OEOmegaOptions(oeomega.OEOmegaSampling_FastROCS) omega = oeomega.OEOmega(omegaOpts) failures = 0 for enantiomer in oeomega.OEFlipper(mol.GetActive(), 6, True): if max_failures > 0 and failures >= max_failures: break if len(oemols) >= 10: break ret_code = None error = False signal.alarm(timeout) try: enantiomer, ret_code = get_enan(omega, enantiomer) except: print("Timeout %s" % out_file) failures += 1 error = True signal.alarm(0) if not error and ret_code == oeomega.OEOmegaReturnCode_Success: halfMol = oechem.OEMol(mol, oechem.OEMCMolType_HalfFloatCartesian) oemols.append(halfMol) #else: #oechem.OEThrow.Warning("%s: %s" % # (enantiomer.GetTitle(), oeomega.OEGetOmegaError(ret_code))) oe_results.append(oemols) ofs = oechem.oemolostream() ofs.SetFormat(oechem.OEFormat_OEB) ofs.open(out_file) for r in oe_results: for res in r: oechem.OEWriteMolecule(ofs, res) ofs.close() return out_file
def _expand_states(molecules, enumerate='protonation', max_states=200, suppress_hydrogen=True, reasonable=True, carbon_hybridization=True, level=0, verbose=True): """ Expand the state specified by enumerate variable Parameters ---------- molecules: OEMol or list of OEMol molecule to expand states enumerate: str, optional, default='protonation' Kind of state to enumerate. Choice of protonation, tautomers, stereoiserms suppress_hydrogen: bool, optional, default=True If True, will suppress explicit hydrogen reasonable: bool, optional, default=True If True, will rank tautomers by the most reasonable energetically carbon_hybridization: bool, optional, default=True If True, will allow carbon to change hybridization max_states: int, optional, default=200 verbose: Bool, optional, deault=TRue Returns ------- states: list of OEMol enumerated states """ if type(molecules) != type(list()): molecules = [molecules] states = list() for molecule in molecules: ostream = oechem.oemolostream() ostream.openstring() ostream.SetFormat(oechem.OEFormat_SDF) states_enumerated = 0 if suppress_hydrogen: oechem.OESuppressHydrogens(molecule) if enumerate == 'protonation': formal_charge_options = oequacpac.OEFormalChargeOptions() formal_charge_options.SetMaxCount(max_states) formal_charge_options.SetVerbose(verbose) if verbose: logger().debug("Enumerating protonation states...") for protonation_state in oequacpac.OEEnumerateFormalCharges(molecule, formal_charge_options): states_enumerated += 1 oechem.OEWriteMolecule(ostream, protonation_state) states.append(protonation_state) if enumerate == 'tautomers': #max_zone_size = molecule.GetMaxAtomIdx() tautomer_options = oequacpac.OETautomerOptions() tautomer_options.SetMaxTautomersGenerated(max_states) tautomer_options.SetLevel(level) tautomer_options.SetRankTautomers(reasonable) tautomer_options.SetCarbonHybridization(carbon_hybridization) #tautomer_options.SetMaxZoneSize(max_zone_size) tautomer_options.SetApplyWarts(True) if verbose: logger().debug("Enumerating tautomers...") for tautomer in oequacpac.OEEnumerateTautomers(molecule, tautomer_options): states_enumerated += 1 states.append(tautomer) if enumerate == 'stereoisomers': if verbose: logger().debug("Enumerating stereoisomers...") for enantiomer in oeomega.OEFlipper(molecule, max_states, True): states_enumerated += 1 enantiomer = oechem.OEMol(enantiomer) oechem.OEWriteMolecule(ostream, enantiomer) states.append(enantiomer) return states