def createOEMolFromSDF(sdf_filename, index=0): """ Load an SDF file into an OEMol. Since SDF files can contain multiple molecules, an index can be provided as well. Parameters ---------- sdf_filename : str The name of the SDF file index : int, default 0 The index of the molecule in the SDF file Returns ------- mol : openeye.oechem.OEMol object The loaded oemol object """ #TODO this needs a test ifs = oechem.oemolistream() ifs.open(sdf_filename) # get the list of molecules mol_list = [oechem.OEMol(mol) for mol in ifs.GetOEMols()] # we'll always take the first for now # Assign aromaticity and hydrogens. for molecule in mol_list: oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) oechem.OEAssignHybridization(molecule) oechem.OEAddExplicitHydrogens(molecule) mol_to_return = mol_list[index] return mol_to_return
def generate_molecule_from_smiles(smiles, name=None): """ Parameters ---------- smiles : str The canonical isomeric SMILES string. name : str, optional, default=None If specified, the molecule title will be set to this; if not, the IUPAC name will be assigned. """ # Generate a molecule from canonical isomeric SMILES. molecule = oechem.OEMol() if not oechem.OEParseSmiles(molecule, smiles): raise ValueError("The supplied SMILES '%s' could not be parsed." % smiles) # Assign aromaticity. oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) # Add hydrogens. oechem.OEAddExplicitHydrogens(molecule) # Set title. if name is None: # Set title to IUPAC name. name = oeiupac.OECreateIUPACName(molecule) molecule.SetTitle(name) # Check for any missing atom names, if found reassign all of them. if any([atom.GetName() == '' for atom in molecule.GetAtoms()]): oechem.OETriposAtomNames(molecule) return molecule
def parametrize_mol(inname,resname): """ Parameterizes molecule with antechamber and adds charges using Open Eye's am1-bcc method from a mol2 file. Parameters ---------- inname : str the names of the mol2 file of the molecule resname : str the name you wish to assign as the residue name Returns ------- nothing BUT 'resname'_gaff.mol2 and 'resname'.frcmod are created in the working directory. """ mol = oechem.OEGraphMol() # initialising molecule object ifs = oechem.oemolistream() # initialising input stream for reading in data ifs.SetFormat(oechem.OEFormat_MOL2) # specifying mol2 format input ifs.open(inname) if oechem.OEReadMolecule(ifs,mol): # this function automatically returns True or False, to help spot for errors. pass else: print "Problem loading molecule!" mol = oechem.OEMol(mol) oechem.OEAssignAromaticFlags(mol, oechem.OEAroModelOpenEye) oechem.OEAddExplicitHydrogens(mol) mol.SetTitle(resname) if any([atom.GetName() == '' for atom in mol.GetAtoms()]): oechem.OETriposAtomNames(mol) oemol_to_antechamber(mol,resname+'_gaff.mol2',resname+'.frcmod',residue_name=resname)
def createOEMolFromSMILES(smiles='CC', title='MOL'): """ Generate an oemol with a geometry """ from openeye import oechem, oeiupac, oeomega # Create molecule mol = oechem.OEMol() oechem.OESmilesToMol(mol, smiles) # Set title. mol.SetTitle(title) # Assign aromaticity and hydrogens. oechem.OEAssignAromaticFlags(mol, oechem.OEAroModelOpenEye) oechem.OEAddExplicitHydrogens(mol) # Create atom names. oechem.OETriposAtomNames(mol) # Assign geometry omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega.SetIncludeInput(False) omega.SetStrictStereo(True) omega(mol) return mol
def set_aromaticity_mdl(self): """ Sets the aromaticity flags in this molecule to use the MDL model """ oechem.OEClearAromaticFlags(self.mol) oechem.OEAssignAromaticFlags(self.mol, oechem.OEAroModel_MDL) oechem.OEAssignHybridization(self.mol)
def createOEMolFromIUPAC(iupac_name='bosutinib'): from openeye import oechem, oeiupac, oeomega # Create molecule. mol = oechem.OEMol() oeiupac.OEParseIUPACName(mol, iupac_name) mol.SetTitle(iupac_name) # Assign aromaticity and hydrogens. oechem.OEAssignAromaticFlags(mol, oechem.OEAroModelOpenEye) oechem.OEAddExplicitHydrogens(mol) # Create atom names. oechem.OETriposAtomNames(mol) # Create bond types oechem.OETriposBondTypeNames(mol) # Assign geometry omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega.SetIncludeInput(False) omega.SetStrictStereo(True) omega(mol) return mol
def normalize_molecule(molecule): """Normalize a copy of the molecule by checking aromaticity, adding explicit hydrogens, and renaming by IUPAC name. Parameters ---------- molecule : OEMol the molecule to be normalized. Returns ------- molcopy : OEMol A (copied) version of the normalized molecule """ molcopy = oechem.OEMol(molecule) # Assign aromaticity. oechem.OEAssignAromaticFlags(molcopy, oechem.OEAroModelOpenEye) # Add hydrogens. oechem.OEAddExplicitHydrogens(molcopy) # Set title to IUPAC name. name = oeiupac.OECreateIUPACName(molcopy) molcopy.SetTitle(name) # Check for any missing atom names, if found reassign all of them. if any([atom.GetName() == '' for atom in molcopy.GetAtoms()]): oechem.OETriposAtomNames(molcopy) return molcopy
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
def sanitizeOEMolecule(molecule): """ This function checks if the molecule has coordinates, explicit hydrogens, aromaticity missing and not unique atom names. If the molecule does not have coordinates a fatal error is raised. If the molecule does not have hydrogens or aramatic flags are missing then a copy of the molecule is fixed, if missing or not unique atom names are found then a copy of the molecule is fixed Parameters: ----------- molecule: OEMol The molecule to be checked Return: ------- mol_copy: OEMol A copy of the checked molecule with fixed aromaticity, hydrogens and unique atom names if they are missing """ mol_copy = oechem.OEMol(molecule) # Check if the molecule has 3D coordinates if not mol_copy.NumAtoms() == 1: # Mono-atomic molecules are skipped if not oechem.OEGetDimensionFromCoords(mol_copy): raise ValueError("The molecule coordinates are set to zero") # Check if the molecule has hydrogens if not oechem.OEHasExplicitHydrogens(mol_copy): oechem.OEAddExplicitHydrogens(mol_copy) # Check if the molecule has assigned aromaticity if not mol_copy.HasPerceived(oechem.OEPerceived_Aromaticity): # oechem.OEAssignAromaticFlags(mol_copy, oechem.OEAroModelOpenEye) oechem.OEAssignAromaticFlags(mol_copy, oechem.OEAroModelMDL) if not mol_copy.HasPerceived(oechem.OEPerceived_Chiral): oechem.OEPerceiveChiral(mol_copy) # Check for any missing and not unique atom names. # If found reassign all of them as Tripos atom names atm_list_names = [] for atom in mol_copy.GetAtoms(): atm_list_names.append(atom.GetName()) reassign_names = False if len(set(atm_list_names)) != len(atm_list_names): reassign_names = True if '' in atm_list_names: reassign_names = True if reassign_names: oechem.OETriposAtomNames(mol_copy) return mol_copy
def create_molecule_from_smiles(smiles): """ Create an ``OEMol`` molecule from a smiles pattern. .. todo:: Replace with the toolkit function when finished. Parameters ---------- smiles : str Smiles pattern Returns ------- molecule : OEMol OEMol with 3D coordinates, but no charges """ from openeye import oechem, oeomega # Check cache if smiles in _cached_molecules: return copy.deepcopy(_cached_molecules[smiles]) # Create molecule from smiles. molecule = oechem.OEMol() parse_smiles_options = oechem.OEParseSmilesOptions(quiet=True) if not oechem.OEParseSmiles(molecule, smiles, parse_smiles_options): logging.warning('Could not parse SMILES: ' + smiles) return False # Normalize molecule oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) oechem.OEAddExplicitHydrogens(molecule) # oechem.OETriposAtomNames(molecule) # Create configuration omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega.SetIncludeInput(False) omega.SetCanonOrder(False) omega.SetSampleHydrogens(True) omega.SetStrictStereo(True) omega.SetStrictAtomTypes(False) status = omega(molecule) if not status: logging.warning('Could not generate a conformer for ' + smiles) return False _cached_molecules[smiles] = molecule return molecule
def smiles_to_oemol(smiles, title='MOL', max_confs=1): """ Generate an oemol from a SMILES string Parameters ---------- smiles : str SMILES string of molecule title : str, default 'MOL' title of OEMol molecule max_confs : int, default 1 maximum number of conformers to generate Returns ------- molecule : openeye.oechem.OEMol OEMol object of the molecule """ from openeye import oeomega # Create molecule molecule = oechem.OEMol() oechem.OESmilesToMol(molecule, smiles) # create unique atom names if len([atom.GetName() for atom in molecule.GetAtoms()]) > len( set([atom.GetName() for atom in molecule.GetAtoms()])): # the atom names are not unique molecule = generate_unique_atom_names(molecule) else: pass # Set title. molecule.SetTitle(title) # Assign aromaticity and hydrogens. oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) oechem.OEAssignHybridization(molecule) oechem.OEAddExplicitHydrogens(molecule) oechem.OEPerceiveChiral(molecule) # Create atom names. oechem.OETriposAtomNames(molecule) oechem.OETriposBondTypeNames(molecule) # perceive chirality before attempting omega geometry proposal assert oechem.OEPerceiveChiral(molecule), f"chirality perception failed" # Assign geometry omega = oeomega.OEOmega() omega.SetMaxConfs(max_confs) omega.SetIncludeInput(False) omega.SetStrictStereo(True) omega(molecule) return molecule
def createOEMolFromSDF(sdf_filename, index=0, add_hydrogens=True, allow_undefined_stereo=False): """ # TODO change this to return a list of all the mols if required Load an SDF file into an OEMol. Since SDF files can contain multiple molecules, an index can be provided as well. Parameters ---------- sdf_filename : str The name of the SDF file index : int, default 0 The index of the molecule in the SDF file allow_undefined_stereo : bool, default=False wether to skip stereo perception Returns ------- mol : openeye.oechem.OEMol object The loaded oemol object """ # TODO this needs a test ifs = oechem.oemolistream() ifs.open(sdf_filename) # get the list of molecules mol_list = [oechem.OEMol(mol) for mol in ifs.GetOEMols()] # we'll always take the first for now # pick out molecule of interest molecule = mol_list[index] # Generate unique atom names if len([atom.GetName() for atom in molecule.GetAtoms()]) > len( set([atom.GetName() for atom in molecule.GetAtoms()])): molecule = generate_unique_atom_names(molecule) # Assign aromaticity and hydrogens. oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) oechem.OEAssignHybridization(molecule) if add_hydrogens: oechem.OEAddExplicitHydrogens(molecule) oechem.OEPerceiveChiral(molecule) # perceive chirality if not allow_undefined_stereo: assert oechem.OE3DToInternalStereo( molecule ), f"the stereochemistry perception from 3D coordinates failed" assert not has_undefined_stereocenters( molecule), f"there is an atom with an undefined stereochemistry" return molecule
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
def _process_mol(mol: oechem.OEMol, explicit_H: Optional[str] = None): if explicit_H == 'all': oechem.OEAddExplicitHydrogens(mol) elif explicit_H == 'polar': oechem.OESuppressHydrogens(mol, explicit_H) elif explicit_H is None: oechem.OESuppressHydrogens(mol) else: raise ValueError oechem.OEAssignAromaticFlags(mol) oechem.OEAssignHybridization(mol) oechem.OEAssignFormalCharges(mol) mol.Sweep()
def _createMolecule(self, iupac_name): """Create molecule from IUPAC name. Best practices for creating initial coordinates can be applied here. Parameters ---------- iupac_name : str IUPAC name Returns ------- molecule : OEMol OEMol with 3D coordinates, but no charges """ # Check cache if iupac_name in self._cached_molecules: return copy.deepcopy(self._cached_molecules[iupac_name]) # Create molecule from IUPAC name. molecule = oechem.OEMol() if not oeiupac.OEParseIUPACName(molecule, iupac_name): raise ValueError( "The supplied IUPAC name '%s' could not be parsed." % iupac_name) # Set molecule name molecule.SetTitle(iupac_name) # Normalize molecule oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) oechem.OEAddExplicitHydrogens(molecule) oechem.OETriposAtomNames(molecule) # Create configuration omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega.SetIncludeInput(False) omega.SetCanonOrder(False) omega.SetSampleHydrogens(True) omega.SetStrictStereo(True) omega.SetStrictAtomTypes(False) status = omega(molecule) if not status: raise (RuntimeError("omega returned error code %d" % status)) # Cache molecule self._cached_molecules[iupac_name] = molecule return molecule
def assignTypes(self, mol): # Assign null types. for atom in mol.GetAtoms(): atom.SetStringData(self.pattyTag, "") # Assign atom types using rules. oechem.OEAssignAromaticFlags(mol) for pat, type, smarts in self.smartsList: for matchbase in pat.Match(mol): for matchpair in matchbase.GetAtoms(): matchpair.target.SetStringData(self.pattyTag, type) # Check if any atoms remain unassigned. for atom in mol.GetAtoms(): if atom.GetStringData(self.pattyTag) == "": raise AtomTyper.TypingException(mol, atom)
def normalize_molecule(mol): # Assign aromaticity. oechem.OEAssignAromaticFlags(mol, oechem.OEAroModelOpenEye) # Add hydrogens. oechem.OEAddExplicitHydrogens(mol) # Check for any missing atom names, if found reassign all of them. if any([atom.GetName() == '' for atom in mol.GetAtoms()]): oechem.OETriposAtomNames(mol) ofs = oechem.oemolostream('out.mol2') ofs.SetFormat(oechem.OEFormat_MOL2H) oechem.OEWriteMolecule(ofs, mol) ofs.close() return mol
def CanSmi(mol, isomeric, kekule): oechem.OEFindRingAtomsAndBonds(mol) oechem.OEAssignAromaticFlags(mol, oechem.OEAroModel_OpenEye) smiflag = oechem.OESMILESFlag_Canonical if isomeric: smiflag |= oechem.OESMILESFlag_ISOMERIC if kekule: for bond in mol.GetBonds(oechem.OEIsAromaticBond()): bond.SetIntType(5) oechem.OECanonicalOrderAtoms(mol) oechem.OECanonicalOrderBonds(mol) oechem.OEClearAromaticFlags(mol) oechem.OEKekulize(mol) smi = oechem.OECreateSmiString(mol, smiflag) return smi
def generate_initial_molecule(mol_smiles): """ Generate an oemol with a geometry """ import openeye.oechem as oechem import openeye.oeomega as oeomega mol = oechem.OEMol() oechem.OESmilesToMol(mol, mol_smiles) mol.SetTitle("MOL") # Assign aromaticity and hydrogens and hybridization. oechem.OEAddExplicitHydrogens(mol) oechem.OEAssignAromaticFlags(mol, oechem.OEAroModelOpenEye) oechem.OEAssignHybridization(mol) oechem.OETriposAtomNames(mol) oechem.OETriposBondTypeNames(mol) omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega(mol) return mol
def standardizeSmiles(self, smiles, type="ISOMERIC"): # pylint: disable=redefined-builtin """ Return a standardized SMILES (type) or None """ smilesOut = None try: mol = oechem.OEGraphMol() if (oechem.OEParseSmiles(mol, smiles) == 1): oechem.OEAssignAromaticFlags(mol) if type == "CANNONICAL": smilesOut = oechem.OECreateCanSmiString(mol) elif type == "ISOMERIC": smilesOut = oechem.OECreateIsoSmiString(mol) else: logger.error("Unable to parse input SMILES '%s'", smiles) except Exception as e: logger.exception("Error '%s' occured. Arguments %s.", str(e), e.args) return smilesOut
def main(infile): # open multi-molecule, multi-conformer file ifs = oechem.oemolistream() ifs.SetConfTest(oechem.OEAbsCanonicalConfTest()) if not ifs.open(infile): raise FileNotFoundError(f"Unable to open {infile} for reading") mols = ifs.GetOEMols() for i, mol in enumerate(mols): # perceive stereochemistry for mol oechem.OEPerceiveChiral(mol) oechem.OEAssignAromaticFlags(mol, oechem.OEAroModel_MDL) # assign charges to copy of mol # note that chg_mol does NOT have conformers try: chg_mol = charge_mol(mol) except RuntimeError: # perceive stereochem #find_unspecified_stereochem(mol) oechem.OE3DToInternalStereo(mol) # reset perceived and call OE3DToBondStereo, since it may be missed # by OE3DToInternalStereo if it thinks mol is flat mol.ResetPerceived() oechem.OE3DToBondStereo(mol) try: chg_mol = charge_mol(mol) print(f'fixed stereo: {mol.GetTitle()}') except RuntimeError: find_unspecified_stereochem(mol) title = mol.GetTitle() smilabel = oechem.OEGetSDData(mol, "SMILES QCArchive") print(' >>> Charge assignment failed due to unspecified ' f'stereochemistry {title} {smilabel}') continue
def iupac_to_oemol(iupac, title='MOL', max_confs=1): """ Generate an oemol from an IUPAC name Parameters ---------- iupac : str iupac name of molecule title : str, default 'MOL' title of OEMol molecule max_confs : int, default 1 maximum number of conformers to generate Returns ------- molecule : openeye.oechem.OEMol OEMol object of the molecule """ from openeye import oeiupac, oeomega # Create molecule molecule = oechem.OEMol() oeiupac.OEParseIUPACName(molecule, iupac) # Set title. molecule.SetTitle(title) # Assign aromaticity and hydrogens. oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) oechem.OEAssignHybridization(molecule) oechem.OEAddExplicitHydrogens(molecule) oechem.OEPerceiveChiral(molecule) # Create atom names. oechem.OETriposAtomNames(molecule) oechem.OETriposBondTypeNames(molecule) # Assign geometry omega = oeomega.OEOmega() omega.SetMaxConfs(max_confs) omega.SetIncludeInput(False) omega.SetStrictStereo(True) omega(molecule) return molecule
def smiles_to_oemol(smiles, title='MOL',max_confs=1): """ Generate an oemol from a SMILES string Parameters ---------- smiles : str SMILES string of molecule title : str, default 'MOL' title of OEMol molecule max_confs : int, default 1 maximum number of conformers to generate Returns ------- molecule : openeye.oechem.OEMol OEMol object of the molecule """ from openeye import oeiupac, oeomega # Create molecule molecule = oechem.OEMol() oechem.OESmilesToMol(molecule, smiles) # Set title. molecule.SetTitle(title) # Assign aromaticity and hydrogens. oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) oechem.OEAssignHybridization(molecule) oechem.OEAddExplicitHydrogens(molecule) # Create atom names. oechem.OETriposAtomNames(molecule) # Assign geometry omega = oeomega.OEOmega() omega.SetMaxConfs(max_confs) omega.SetIncludeInput(False) omega.SetStrictStereo(True) omega(molecule) return molecule
def main(infile, ffxml): # open multi-molecule, multi-conformer file ifs = oechem.oemolistream() ifs.SetConfTest(oechem.OEAbsCanonicalConfTest()) if not ifs.open(infile): raise FileNotFoundError(f"Unable to open {infile} for reading") mols = ifs.GetOEMols() for i, mol in enumerate(mols): # perceive stereochemistry for mol oechem.OEPerceiveChiral(mol) oechem.OEAssignAromaticFlags(mol, oechem.OEAroModel_MDL) for j, conf in enumerate(mol.GetConfs()): # perceive sterochemistry for conf coordinates oechem.OE3DToInternalStereo(conf) min_ffxml(conf, ffxml)
def CanSmi(mol, isomeric, kekule): """ Returns the cannonical smile from the OEMol provided :param mol: OEMolBase object :param isomeric: force isometric :param kekule: use kekule cleaning :return: string of OESmiles """ oechem.OEFindRingAtomsAndBonds(mol) oechem.OEAssignAromaticFlags(mol, oechem.OEAroModel_OpenEye) smiflag = oechem.OESMILESFlag_Canonical if isomeric: smiflag |= oechem.OESMILESFlag_ISOMERIC if kekule: for bond in mol.GetBonds(oechem.OEIsAromaticBond()): bond.SetIntType(5) oechem.OECanonicalOrderAtoms(mol) oechem.OECanonicalOrderBonds(mol) oechem.OEClearAromaticFlags(mol) oechem.OEKekulize(mol) smi = oechem.OECreateSmiString(mol, smiflag) return smi
def generateOEMolFromTopologyResidue(residue, geometry=False, tripos_atom_names=False): """ Generate an OpenEye OEMol molecule from an OpenMM Topology Residue. Parameters ---------- residue : simtk.openmm.app.topology.Residue The topology Residue from which an OEMol is to be created. An Exception will be thrown if this residue has external bonds. geometry : bool, optional, default=False If True, will generate a single configuration with OEOmega. Note that stereochemistry will be *random*. tripos_atom_names : bool, optional, default=False If True, will generate and assign Tripos atom names. Returns ------- molecule : openeye.oechem.OEMol The OEMol molecule corresponding to the topology. Atom order will be preserved and bond orders assigned. The Antechamber `bondtype` program will be used to assign bond orders, and these will be converted back into OEMol bond type assignments. Note that there is no way to preserve stereochemistry since `Residue` does not note stereochemistry in any way. """ # Raise an Exception if this residue has external bonds. if len(list(residue.external_bonds())) > 0: raise Exception( "Cannot generate an OEMol from residue '%s' because it has external bonds." % residue.name) from openeye import oechem # Create OEMol where all atoms have bond order 1. molecule = oechem.OEMol() molecule.SetTitle(residue.name) # name molecule after first residue for atom in residue.atoms(): oeatom = molecule.NewAtom(atom.element.atomic_number) oeatom.SetName(atom.name) oeatom.AddData("topology_index", atom.index) oeatoms = {oeatom.GetName(): oeatom for oeatom in molecule.GetAtoms()} for (atom1, atom2) in residue.bonds(): order = 1 molecule.NewBond(oeatoms[atom1.name], oeatoms[atom2.name], order) # Write out a mol2 file without altering molecule. import tempfile tmpdir = tempfile.mkdtemp() mol2_input_filename = os.path.join(tmpdir, 'molecule-before-bond-perception.mol2') ac_output_filename = os.path.join(tmpdir, 'molecule-after-bond-perception.ac') ofs = oechem.oemolostream(mol2_input_filename) m2h = True substruct = False oechem.OEWriteMol2File(ofs, molecule, m2h, substruct) ofs.close() # Run Antechamber bondtype import subprocess #command = 'bondtype -i %s -o %s -f mol2 -j full' % (mol2_input_filename, ac_output_filename) command = 'antechamber -i %s -fi mol2 -o %s -fo ac -j 2' % ( mol2_input_filename, ac_output_filename) [status, output] = getstatusoutput(command) # Define mapping from GAFF bond orders to OpenEye bond orders. order_map = {1: 1, 2: 2, 3: 3, 7: 1, 8: 2, 9: 5, 10: 5} # Read bonds. infile = open(ac_output_filename) lines = infile.readlines() infile.close() antechamber_bond_types = list() for line in lines: elements = line.split() if elements[0] == 'BOND': antechamber_bond_types.append(int(elements[4])) oechem.OEClearAromaticFlags(molecule) for (bond, antechamber_bond_type) in zip(molecule.GetBonds(), antechamber_bond_types): #bond.SetOrder(order_map[antechamber_bond_type]) bond.SetIntType(order_map[antechamber_bond_type]) oechem.OEFindRingAtomsAndBonds(molecule) oechem.OEKekulize(molecule) oechem.OEAssignFormalCharges(molecule) oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) # Clean up. os.unlink(mol2_input_filename) os.unlink(ac_output_filename) os.rmdir(tmpdir) # Generate Tripos atom names if requested. if tripos_atom_names: oechem.OETriposAtomNames(molecule) # Assign geometry if geometry: from openeye import oeomega omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega.SetIncludeInput(False) omega.SetStrictStereo(False) omega(molecule) return molecule
def PerceiveAromaticity(mol, modelname, aromodel): oechem.OEAssignAromaticFlags(mol, aromodel) cansmi = oechem.OECreateCanSmiString(mol) print(modelname, ":", cansmi)
def main(infile, outfile, ffxml, minimizer): # open multi-molecule, multi-conformer file ifs = oechem.oemolistream() ifs.SetConfTest(oechem.OEAbsCanonicalConfTest()) if not ifs.open(infile): raise FileNotFoundError(f"Unable to open {infile} for reading") mols = ifs.GetOEMols() # open an outstream file ofs = oechem.oemolostream() if os.path.exists(outfile): raise FileExistsError("Output file {} already exists in {}".format( outfile, os.getcwd())) if not ofs.open(outfile): oechem.OEThrow.Fatal("Unable to open %s for writing" % outfile) # minimize with openforcefield ffxml file for i, mol in enumerate(mols): # perceive stereochemistry for mol oechem.OEPerceiveChiral(mol) oechem.OEAssignAromaticFlags(mol, oechem.OEAroModel_MDL) # assign charges to copy of mol # note that chg_mol does NOT have conformers try: chg_mol = charge_mol(mol) except RuntimeError: # perceive stereochem #find_unspecified_stereochem(mol) oechem.OE3DToInternalStereo(mol) # reset perceived and call OE3DToBondStereo, since it may be missed # by OE3DToInternalStereo if it thinks mol is flat mol.ResetPerceived() oechem.OE3DToBondStereo(mol) try: chg_mol = charge_mol(mol) print(f'fixed stereo: {mol.GetTitle()}') except RuntimeError: title = mol.GetTitle() smilabel = oechem.OEGetSDData(mol, "SMILES QCArchive") print(' >>> Charge assignment failed due to unspecified ' f'stereochemistry {title} {smilabel}') continue for j, conf in enumerate(mol.GetConfs()): # perceive sterochemistry for conf coordinates oechem.OE3DToInternalStereo(conf) # assign charges to the conf itself chg_conf = charge_conf(chg_mol, conf) if minimizer == 'ffxml': # minimize with parsley (charges set by ff not used from conf) min_ffxml(chg_conf, ofs, ffxml) if minimizer == 'mmff94': # minimize with mmff94 min_mmff94x(chg_conf, ofs, mmff94s=False) if minimizer == 'mmff94s': # minimize with mmff94S min_mmff94x(chg_conf, ofs, mmff94s=True) if minimizer == 'gaff': # minimize with gaff min_gaffx(chg_conf, ofs, gaff2=False) if minimizer == 'gaff2': # minimize with gaff2 min_gaffx(chg_conf, ofs, gaff2=True) ifs.close() ofs.close()
def create_molecule_from_smiles(smiles, number_of_conformers=1): """ Create an ``OEMol`` molecule from a smiles pattern. .. todo:: Replace with the toolkit function when finished. Parameters ---------- smiles : str The smiles pattern to create the molecule from. number_of_conformers: int The number of conformers to generate for the molecule using Omega. Returns ------- molecule : OEMol OEMol with no charges, and a number of conformers as specified by `number_of_conformers` """ from openeye import oechem, oeomega # Check cache if (number_of_conformers, smiles) in _cached_molecules: return copy.deepcopy(_cached_molecules[(number_of_conformers, smiles)]) # Create molecule from smiles. molecule = oechem.OEMol() parse_smiles_options = oechem.OEParseSmilesOptions(quiet=True) if not oechem.OEParseSmiles(molecule, smiles, parse_smiles_options): logging.warning('Could not parse SMILES: ' + smiles) return None # Normalize molecule oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) oechem.OEAddExplicitHydrogens(molecule) # Create configuration if number_of_conformers > 0: omega = oeomega.OEOmega() omega.SetMaxConfs(number_of_conformers) omega.SetIncludeInput(False) omega.SetCanonOrder(False) omega.SetSampleHydrogens(True) omega.SetStrictStereo(True) omega.SetStrictAtomTypes(False) status = omega(molecule) if not status: logging.warning('Could not generate a conformer for ' + smiles) return None _cached_molecules[(number_of_conformers, smiles)] = molecule return molecule
# modifications. Modification of Sample Code is at Customer's sole and # exclusive risk. Sample Code may require Customer to have a then # current license or subscription to the applicable OpenEye offering. # THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED. OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT # NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be # liable for any damages or liability in connection with the Sample Code # or its use. # @ <SNIPPET> from openeye import oechem # @ <SNIPPET-CORRECT-COMPLEX> mol = oechem.OEGraphMol() oechem.OESmilesToMol(mol, "c1ccccc1") # Code that modifies the molecule # and creates new atoms and bonds oechem.OEFindRingAtomsAndBonds(mol) oechem.OEAssignAromaticFlags(mol) for bond in mol.GetBonds(): if bond.IsAromatic(): bond.SetIntType(5) elif bond.GetOrder() != 0: bond.SetIntType(bond.GetOrder()) else: bond.SetIntType(1) oechem.OEKekulize(mol) # @ </SNIPPET-CORRECT-COMPLEX> # @ </SNIPPET>