def test_change_parameters(verbose=False): """Test modification of forcefield parameters.""" from openeye import oechem # Load simple OEMol ifs = oechem.oemolistream( get_data_filename('molecules/AlkEthOH_c100.mol2')) mol = oechem.OEMol() flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_MOL2_Default | oechem.OEIFlavor_MOL2_Forcefield ifs.SetFlavor(oechem.OEFormat_MOL2, flavor) oechem.OEReadMolecule(ifs, mol) oechem.OETriposAtomNames(mol) # Load forcefield file ffxml = get_data_filename('forcefield/Frosst_AlkEtOH.ffxml') ff = ForceField(ffxml) from smarty.forcefield import generateTopologyFromOEMol topology = generateTopologyFromOEMol(mol) # Create initial system system = ff.createSystem(topology, [mol], verbose=verbose) # Get initial energy before parameter modification positions = positions_from_oemol(mol) old_energy = get_energy(system, positions) # Get params for an angle params = ff.getParameter(smirks='[a,A:1]-[#6X4:2]-[a,A:3]') # Modify params params['k'] = '0.0' ff.setParameter(params, smirks='[a,A:1]-[#6X4:2]-[a,A:3]') # Write params ff.writeFile(tempfile.TemporaryFile(suffix='.ffxml')) # Make sure params changed energy! (Test whether they get rebuilt on system creation) system = ff.createSystem(topology, [mol], verbose=verbose) energy = get_energy(system, positions) if verbose: print("New energy/old energy:", energy, old_energy) if np.abs(energy - old_energy) < 0.1: raise Exception("Error: Parameter modification did not change energy.")
def main(argv=[__name__]): itf = oechem.OEInterface(InterfaceData) if oechem.OECheckHelp(itf, argv): return 0 if not oechem.OEParseCommandLine(itf, argv): return 1 ifs = oechem.oemolistream() if not ifs.open(itf.GetString("-i")): oechem.OEThrow.Fatal("Unable to open %s for reading" % itf.GetString("-i")) ofs = oechem.oemolostream() if not ofs.open(itf.GetString("-o")): oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-o")) omega = oeomega.OEOmega() maxConfs = 0 omega.SetMaxConfs(maxConfs) omega.SetStrictStereo(False) omega.SetSampleHydrogens(True) omega.SetEnumNitrogen(oeomega.OENitrogenEnumeration_All) mol = oechem.OEMol() for mol in ifs.GetOEMols(): #print( mol.GetTitle() ) if not omega(mol): print("omega failed on %s" % mol.GetTitle()) title = mol.GetTitle() oechem.OETriposAtomNames(mol) oequacpac.OEAssignPartialCharges(mol, oequacpac.OECharges_AM1BCCSym) oechem.OEWriteConstMolecule(ofs, mol) ofs.close() return 0
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) # Assign geometry omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega.SetIncludeInput(False) omega.SetStrictStereo(True) omega(mol) return mol
def write_host(host_oemol: oechem.OEMol, filepath: str): """ Write out the host molecule on its own. Parameters ---------- host_oemol : oechem.OEMol the OEMol containing the host filepath : str where to write the OEMol """ ostream = oechem.oemolostream() ostream.open(filepath) # set title to avoid template name collision: host_oemol.SetTitle("host") # set tripos atom names oechem.OETriposAtomNames(host_oemol) oechem.OEWriteMolecule(ostream, host_oemol) ostream.close()
def smi2sdf(wdir, smiles): """ From a file containing smiles strings, generate omega conformers, resolve steric clashes, do a quick MM opt, and write SDF output. Parameters ---------- wdir: str - working directory containing .smi file smiles: str - name of the smiles file. E.g. "name.smi" """ sdfout = smiles.split('.')[0] + '.sdf' os.chdir(wdir) ### Read in smiles file. ifs = oechem.oemolistream() if not ifs.open(smiles): oechem.OEThrow.Warning("Unable to open %s for reading" % smiles) ### Open output file to write molecules. ofs = oechem.oemolostream() if os.path.exists(sdfout): #sys.exit("Output .sdf file already exists. Exiting.\n") print "Output .sdf file already exists. Exiting.\n" return if not ofs.open(sdfout): oechem.OEThrow.Fatal("Unable to open %s for writing" % sdfout) ### For each molecule: label atoms, generate 1 conf, write output. for smimol in ifs.GetOEMols(): oechem.OETriposAtomNames(smimol) mol = GenerateConfs(smimol) oechem.OEWriteConstMolecule(ofs, mol) ### Close files. ifs.close() ofs.close()
def check_boxes(forcefield, description="", chargeMethod=None, verbose=False): """Test creation of System from boxes of mixed solvents. """ # Read monomers mols = list() monomers = ['cyclohexane', 'ethanol', 'propane', 'methane', 'butanol'] from openeye import oechem mol = oechem.OEGraphMol() for monomer in monomers: filename = get_data_filename( os.path.join('systems', 'monomers', monomer + '.sdf')) ifs = oechem.oemolistream(filename) while oechem.OEReadMolecule(ifs, mol): oechem.OETriposAtomNames(mol) mols.append(oechem.OEGraphMol(mol)) if verbose: print('%d reference molecules loaded' % len(mols)) # Read systems. boxes = [ 'cyclohexane_ethanol_0.4_0.6.pdb', 'propane_methane_butanol_0.2_0.3_0.5.pdb' ] from simtk.openmm.app import PDBFile for box in boxes: filename = get_data_filename( os.path.join('systems', 'packmol_boxes', box)) pdbfile = PDBFile(filename) f = partial(check_system_creation_from_topology, forcefield, pdbfile.topology, mols, pdbfile.positions, chargeMethod=chargeMethod, verbose=verbose) f.description = 'Test creation of System object from %s %s' % ( box, description) yield f
def constructDataFrame(mol_files): """ Construct a pandas dataframe to be populated with computed single molecule properties. Each unique bond, angle and torsion has it's own column for a value and uncertainty. inputs: a list of mol2 files from which we determine connectivity using OpenEye Tools and construct the dataframe using Pandas. """ molnames = [] for i in mol_files: molname = i.replace(' ', '')[:-5] molname = molname.rsplit('/', 1)[1] print molname molnames.append(molname) OEMols = [] for i in mol_files: mol = oechem.OEGraphMol() ifs = oechem.oemolistream(i) flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_MOL2_Default | oechem.OEIFlavor_MOL2_Forcefield ifs.SetFlavor(oechem.OEFormat_MOL2, flavor) oechem.OEReadMolecule(ifs, mol) oechem.OETriposAtomNames(mol) OEMols.append(mol) ff = ForceField(get_data_filename('/data/forcefield/smirff99Frosst.ffxml')) labels = [] lst0 = [] lst1 = [] lst2 = [] lst00 = [[] for i in molnames] lst11 = [[] for i in molnames] lst22 = [[] for i in molnames] for ind, val in enumerate(OEMols): label = ff.labelMolecules([val], verbose=False) for entry in range(len(label)): for bond in label[entry]['HarmonicBondGenerator']: lst0.extend([str(bond[0])]) lst00[ind].extend([str(bond[0])]) for angle in label[entry]['HarmonicAngleGenerator']: lst1.extend([str(angle[0])]) lst11[ind].extend([str(angle[0])]) for torsion in label[entry]['PeriodicTorsionGenerator']: lst2.extend([str(torsion[0])]) lst22[ind].extend([str(torsion[0])]) # Return unique strings from lst0 cols0 = set() for x in lst0: cols0.add(x) cols0 = list(cols0) # Generate data lists to populate dataframe data0 = [[] for i in range(len(lst00))] for val in cols0: for ind, item in enumerate(lst00): if val in item: data0[ind].append(1) else: data0[ind].append(0) # Return unique strings from lst1 cols1 = set() for x in lst1: cols1.add(x) cols1 = list(cols1) # Generate data lists to populate frame (1 means val in lst11 was in cols1, 0 means it wasn't) data1 = [[] for i in range(len(lst11))] for val in cols1: for ind, item in enumerate(lst11): if val in item: data1[ind].append(1) else: data1[ind].append(0) # Return unique strings from lst2 cols2 = set() for x in lst2: cols2.add(x) cols2 = list(cols2) # Generate data lists to populate frame (1 means val in lst22 was in cols2, 0 means it wasn't) data2 = [[] for i in range(len(lst22))] for val in cols2: for ind, item in enumerate(lst22): if val in item: data2[ind].append(1) else: data2[ind].append(0) # Clean up clarity of column headers and molecule names cols0t = ["BondEquilibriumLength " + i for i in cols0] cols0temp = ["BondEquilibriumLength_std " + i for i in cols0] cols0 = cols0t + cols0temp cols1t = ["AngleEquilibriumAngle " + i for i in cols1] cols1temp = ["AngleEquilibriumAngle_std " + i for i in cols1] cols1 = cols1t + cols1temp cols2t = ["TorsionFourier1 " + i for i in cols2] cols2temp = ["TorsionFourier1_std " + i for i in cols2] cols2 = cols2t + cols2temp data0 = [i + i for i in data0] data1 = [i + i for i in data1] data2 = [i + i for i in data2] # Construct dataframes df0 = pd.DataFrame(data=data0, index=molnames, columns=cols0) df0['molecule'] = df0.index df1 = pd.DataFrame(data=data1, index=molnames, columns=cols1) df1['molecule'] = df1.index df2 = pd.DataFrame(data=data2, index=molnames, columns=cols2) df2['molecule'] = df2.index dftemp = pd.merge(df0, df1, how='outer', on='molecule') df = pd.merge(dftemp, df2, how='outer', on='molecule') return df, OEMols, cols2
def test_component_combination(): """Test that a system still yields the same energy after building it again out of its components.""" # We've had issues where subsequent instances of a molecule might have zero charges # Here we'll try to catch this (and also explicitly check the charges) by re-building # a system out of its components forcefield = ForceField( get_data_filename('forcefield/Frosst_AlkEthOH.ffxml')) filename = get_data_filename( os.path.join('systems', 'packmol_boxes', 'cyclohexane_ethanol_0.4_0.6.pdb')) from simtk.openmm.app import PDBFile pdbfile = PDBFile(filename) mol2files = [ get_data_filename(os.path.join('systems', 'monomers', 'ethanol.mol2')), get_data_filename( os.path.join('systems', 'monomers', 'cyclohexane.mol2')) ] flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_MOL2_Default | oechem.OEIFlavor_MOL2_Forcefield mols = [] mol = oechem.OEMol() for mol2file in mol2files: ifs = oechem.oemolistream(mol2file) ifs.SetFlavor(oechem.OEFormat_MOL2, flavor) mol = oechem.OEGraphMol() while oechem.OEReadMolecule(ifs, mol): oechem.OETriposAtomNames(mol) mols.append(oechem.OEGraphMol(mol)) # setup system system = forcefield.createSystem(pdbfile.topology, mols, chargeMethod='OECharges_AM1BCCSym') # Make parmed structure structure = parmed.openmm.topsystem.load_topology(pdbfile.topology, system, pdbfile.positions) # Split the system, then re-compose it out of its components tmp = structure.split() strs, nums = [], [] for s, n in tmp: strs.append(s) nums.append(n) nums = [len(n) for n in nums] # Re-compose system from components new_structure = strs[0] * nums[0] for idx in range(1, len(nums)): new_structure += strs[idx] * nums[idx] # Swap in coordinates again new_structure.positions = structure.positions # Create System newsys = new_structure.createSystem(nonbondedMethod=app.NoCutoff, constraints=None, implicitSolvent=None) # Cross check energies groups0, groups1, energy0, energy1 = compare_system_energies( pdbfile.topology, pdbfile.topology, system, newsys, pdbfile.positions, verbose=False) # Also check that that the number of components is equal to the number I expect if not len(nums) == 2: print("Error: Test system has incorrect number of components.") raise Exception( 'Incorrect number of components in cyclohexane/ethanol test system.' ) # Also check that none of residues have zero charge for resnr in range(len(structure.residues)): abscharges = [ abs(structure.residues[resnr].atoms[idx].charge) for idx in range(len(structure.residues[resnr].atoms)) ] if sum(abscharges) == 0: raise Exception( 'Error: Residue %s in cyclohexane-ethanol test system has a charge of zero, which is incorrect.' % resnr)
def sanitizeSMILES(smiles_list, mode='drop', verbose=False): """ Sanitize set of SMILES strings by ensuring all are canonical isomeric SMILES. Duplicates are also removed. Parameters ---------- smiles_list : iterable of str The set of SMILES strings to sanitize. mode : str, optional, default='drop' When a SMILES string that does not correspond to canonical isomeric SMILES is found, select the action to be performed. 'exception' : raise an `Exception` 'drop' : drop the SMILES string 'expand' : expand all stereocenters into multiple molecules verbose : bool, optional, default=False If True, print verbose output. Returns ------- sanitized_smiles_list : list of str Sanitized list of canonical isomeric SMILES strings. Examples -------- Sanitize a simple list. >>> smiles_list = ['CC', 'CCC', '[H][C@]1(NC[C@@H](CC1CO[C@H]2CC[C@@H](CC2)O)N)[H]'] Throw an exception if undefined stereochemistry is present. >>> sanitized_smiles_list = sanitizeSMILES(smiles_list, mode='exception') Traceback (most recent call last): ... Exception: Molecule '[H][C@]1(NC[C@@H](CC1CO[C@H]2CC[C@@H](CC2)O)N)[H]' has undefined stereocenters Drop molecules iwth undefined stereochemistry. >>> sanitized_smiles_list = sanitizeSMILES(smiles_list, mode='drop') >>> len(sanitized_smiles_list) 2 Expand molecules iwth undefined stereochemistry. >>> sanitized_smiles_list = sanitizeSMILES(smiles_list, mode='expand') >>> len(sanitized_smiles_list) 4 """ from openeye import oechem from openeye.oechem import OEGraphMol, OESmilesToMol, OECreateIsoSmiString from perses.tests.utils import has_undefined_stereocenters, enumerate_undefined_stereocenters sanitized_smiles_set = set() OESMILES_OPTIONS = oechem.OESMILESFlag_DEFAULT | oechem.OESMILESFlag_ISOMERIC | oechem.OESMILESFlag_Hydrogens ## IVY for smiles in smiles_list: molecule = OEGraphMol() OESmilesToMol(molecule, smiles) oechem.OEAddExplicitHydrogens(molecule) if verbose: molecule.SetTitle(smiles) oechem.OETriposAtomNames(molecule) if has_undefined_stereocenters(molecule, verbose=verbose): if mode == 'drop': if verbose: print("Dropping '%s' due to undefined stereocenters." % smiles) continue elif mode == 'exception': raise Exception("Molecule '%s' has undefined stereocenters" % smiles) elif mode == 'expand': if verbose: print('Expanding stereochemistry:') print('original: %s', smiles) molecules = enumerate_undefined_stereocenters(molecule, verbose=verbose) for molecule in molecules: smiles_string = oechem.OECreateSmiString(molecule, OESMILES_OPTIONS) ## IVY sanitized_smiles_set.add(smiles_string) ## IVY if verbose: print('expanded: %s', smiles_string) else: # Convert to OpenEye's canonical isomeric SMILES. smiles_string = oechem.OECreateSmiString(molecule, OESMILES_OPTIONS) ## IVY sanitized_smiles_set.add(smiles_string) ## IVY sanitized_smiles_list = list(sanitized_smiles_set) return sanitized_smiles_list
def generate_complex_topologies_and_positions(ligand_filename, protein_pdb_filename): """ Generate the topologies and positions for complex phase simulations, given an input ligand file (in supported openeye format) and protein pdb file. Note that the input ligand file should have coordinates placing the ligand in the binding site. Parameters ---------- ligand_filename : str Name of the file containing ligands protein_pdb_filename : str Name of the protein pdb file Returns ------- complex_topologies_dict : dict of smiles: md.topology Dictionary of topologies for various complex systems complex_positions_dict : dict of smiles: [n, 3] array of Quantity Positions for corresponding complexes """ ifs = oechem.oemolistream() ifs.open(ligand_filename) # get the list of molecules mol_list = [oechem.OEMol(mol) for mol in ifs.GetOEMols()] for idx, mol in enumerate(mol_list): mol.SetTitle("MOL{}".format(idx)) oechem.OETriposAtomNames(mol) mol_dict = {oechem.OEMolToSmiles(mol): mol for mol in mol_list} ligand_topology_dict = { smiles: forcefield_generators.generateTopologyFromOEMol(mol) for smiles, mol in mol_dict.items() } protein_pdbfile = open(protein_pdb_filename, 'r') pdb_file = app.PDBFile(protein_pdbfile) protein_pdbfile.close() receptor_positions = pdb_file.positions receptor_topology = pdb_file.topology receptor_md_topology = md.Topology.from_openmm(receptor_topology) n_receptor_atoms = receptor_md_topology.n_atoms complex_topologies = {} complex_positions_dict = {} for smiles, ligand_topology in ligand_topology_dict.items(): ligand_md_topology = md.Topology.from_openmm(ligand_topology) n_complex_atoms = ligand_md_topology.n_atoms + n_receptor_atoms copy_receptor_md_topology = copy.deepcopy(receptor_md_topology) complex_positions = unit.Quantity(np.zeros([n_complex_atoms, 3]), unit=unit.nanometers) complex_topology = copy_receptor_md_topology.join(ligand_md_topology) complex_topologies[smiles] = complex_topology ligand_positions = extractPositionsFromOEMol(mol_dict[smiles]) complex_positions[:n_receptor_atoms, :] = receptor_positions complex_positions[n_receptor_atoms:, :] = ligand_positions complex_positions_dict[smiles] = complex_positions return complex_topologies, complex_positions_dict
def initialize_confs(smiles, resolve_clash=True, do_opt=True): """ From a file containing smiles strings, generate omega conformers, resolve steric clashes, do a quick MM opt, and write SDF output. Parameters ---------- smiles : string Name of the input molecule file. Note: this isn't strictly limited to SMILES files, can also work with SDF, MOL2, etc. The file can be in a different location than the directory of which this function is called. The output SDF and txt files will be placed in the directory of which the function is called. resolve_clash : Boolean True to resolve steric clashes by geometry optimization using OESzybki do_opt : Boolean True to run quick geometry optimization using OESzybki with MMFF94S force field and Sheffield solvent model """ base, extension = os.path.splitext(os.path.basename(smiles)) if extension == '.sdf': base = base + '_quanformer' sdfout = base + '.sdf' ### Read in smiles file. ifs = oechem.oemolistream() if not ifs.open(smiles): oechem.OEThrow.Warning("Unable to open %s for reading" % smiles) ### Open output file to write molecules. ofs = oechem.oemolostream() if os.path.exists(sdfout): print( "Output .sdf file already exists. Exiting initialize_confs.\n{}\n". format(os.path.abspath(sdfout))) return if not ofs.open(sdfout): oechem.OEThrow.Fatal("Unable to open %s for writing" % sdfout) ### Output files detailing number of resolved clashes ### and original number of conformers before MM opt. conffile = open('numConfs.txt', 'a') conffile.write("Number of original conformers\n") ### For each molecule: label atoms, generate confs, resolve clashes, optimize. for smimol in ifs.GetOEMols(): oechem.OETriposAtomNames(smimol) oechem.OEAddExplicitHydrogens(smimol) mol = generate_confs(smimol) if mol is None: continue conffile.write("%s\t%s\n" % (mol.GetTitle(), mol.NumConfs())) for i, conf in enumerate(mol.GetConfs()): print(mol.GetTitle(), i + 1) ### Resolve bad clashes. if resolve_clash: print("Resolving bad clashes...") if not resolve_clashes(conf, "numClashes.txt"): print('Resolving bad clashes failed for molecule %s \ conformer %d:' % (mol.GetTitle(), i + 1)) continue ### MM optimization. if do_opt: print("Doing a quick MM (SD) optimization...") if not quick_opt(conf): print('Quick optimization failed for molecule %s \ conformer %d:' % (mol.GetTitle(), i + 1)) continue oechem.OEWriteConstMolecule(ofs, mol) ### Close files. ifs.close() ofs.close() conffile.close()
def smi2confs(smiles, resClash=True, quickOpt=True): """ From a file containing smiles strings, generate omega conformers, resolve steric clashes, do a quick MM opt, and write SDF output. Parameters ---------- smiles: str - PATH+name of the smiles file. resClash: boolean - Resolve steric clashes or not. quickOpt: boolean - QuickOpt or not. """ wdir, fname = os.path.split(smiles) base, extension = os.path.splitext(fname) sdfout = base + '.sdf' os.chdir(wdir) ### Read in smiles file. ifs = oechem.oemolistream() if not ifs.open(smiles): oechem.OEThrow.Warning("Unable to open %s for reading" % smiles) ### Open output file to write molecules. ofs = oechem.oemolostream() if os.path.exists(sdfout): #sys.exit("Output .sdf file already exists. Exiting.\n") print("Output .sdf file already exists. Exiting.\n") return if not ofs.open(sdfout): oechem.OEThrow.Fatal("Unable to open %s for writing" % sdfout) ### Output files detailing number of resolved clashes ### and original number of conformers before MM opt. conffile = open('numConfs.txt', 'a') conffile.write("Number of original conformers\n") ### For each molecule: label atoms, generate confs, resolve clashes, optimize. for smimol in ifs.GetOEMols(): oechem.OETriposAtomNames(smimol) mol = GenerateConfs(smimol) conffile.write("%s\t%s\n" % (mol.GetTitle(), mol.NumConfs())) for i, conf in enumerate(mol.GetConfs()): print(mol.GetTitle(), i + 1) ### Resolve bad clashes. if resClash: print("Resolving bad clashes...") if not ResolveBadClashes(conf, "numClashes.txt"): print('Resolving bad clashes failed for molecule %s \ conformer %d:' % (mol.GetTitle(), i + 1)) continue ### MM optimization. if quickOpt: print("Doing a quick MM (SD) optimization...") if not QuickOpt(conf): print('Quick optimization failed for molecule %s \ conformer %d:' % (mol.GetTitle(), i + 1)) continue oechem.OEWriteConstMolecule(ofs, mol) ### Close files. ifs.close() ofs.close() conffile.close()
oechem.OEWriteMolecule(ofs, receptor) # Filter out receptor atoms with atom names of UNK for atom in receptor.GetAtoms(): if atom.GetName() == 'UNK': receptor.DeleteAtom(atom) # Write joined PDB with ligand and receptor output_filename = os.path.join(docking_basedir, f'{molecule.GetTitle()} - complex.pdb') if not os.path.exists(output_filename): with oechem.oemolostream(output_filename) as ofs: oechem.OEClearResidues(docked_molecule) #oechem.OEWriteMolecule(ofs, docked_molecule) oechem.OETriposAtomNames(docked_molecule) oechem.OEWritePDBFile(ofs, docked_molecule, oechem.OEOFlavor_PDB_Default | oechem.OEOFlavor_PDB_BONDS) set_serial(receptor, 'X', docked_molecule.NumAtoms()+1) #oechem.OEWritePDBFile(ofs, receptor, oechem.OEOFlavor_PDB_Default | oechem.OEOFlavor_PDB_BONDS) oechem.OEWriteMolecule(ofs, receptor) # Write PDB of just ligand output_filename = os.path.join(docking_basedir, f'{molecule.GetTitle()} - ligand.pdb') if not os.path.exists(output_filename): with oechem.oemolostream(output_filename) as ofs: oechem.OEClearResidues(docked_molecule) #oechem.OEWriteMolecule(ofs, docked_molecule)
# Load molecule and create pdb object pdb = PDBFile(pdb_filename) # Load a SMIRNOFF force field forcefield = ForceField( get_data_file_path('test_forcefields/Frosst_AlkEthOH_parmAtFrosst.offxml')) # Load molecule using OpenEye tools mol = oechem.OEGraphMol() ifs = oechem.oemolistream(mol_filename) # LPW: I don't understand the meaning of these lines. # flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_MOL2_Default | oechem.OEIFlavor_MOL2_Forcefield # ifs.SetFlavor( oechem.OEFormat_MOL2, flavor) oechem.OEReadMolecule(ifs, mol) oechem.OETriposAtomNames(mol) # Create the OpenMM system system = forcefield.createSystem(pdb.topology, [mol], nonbondedMethod=PME, nonbondedCutoff=1.0 * unit.nanometers, rigidWater=True) # Set up an OpenMM simulation integrator = openmm.LangevinIntegrator(temperature, friction, time_step) platform = openmm.Platform.getPlatformByName('CUDA') simulation = Simulation(pdb.topology, system, integrator) simulation.context.setPositions(pdb.positions) simulation.context.setVelocitiesToTemperature(temperature) netcdf_reporter = NetCDFReporter('water_traj.nc', trj_freq) simulation.reporters.append(netcdf_reporter)
from openeye import oeiupac from openeye import oequacpac # Create molecules. for resname in molecules: name = molecules[resname] print name # Create molecule from IUPAC name. molecule = oechem.OEMol() oeiupac.OEParseIUPACName(molecule, name) molecule.SetTitle(name) # Normalize molecule. oechem.OEAddExplicitHydrogens(molecule) oechem.OETriposAtomNames(molecule) oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) # Create configuration. omega = oeomega.OEOmega() omega.SetStrictStereo(True) omega.SetIncludeInput(False) omega(molecule) # Create charges. oequacpac.OEAssignPartialCharges(molecule, oequacpac.OECharges_AM1BCCSym) # Write molecule. filename = '%s.tripos.mol2' % name print filename ofs = oechem.oemolostream()
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 build_mixture_prmtop(gaff_mol2_filenames, box_filename, out_top, out_gro, ffxml): """Analog of openmoltools.amber.build_mixture_prmtop which uses SMIRNOFF forcefield (from github.com/open-forcefield-group/smarty) to parameterize small molecules, rather than GAFF. Parameters ---------- mol2_filenames : list(str) Filenames of GAFF flavored mol2 files. Each must contain exactly ONE solute. box_filename : str Filename of PDB containing an arbitrary box of the mol2 molecules. out_top : str output GROMACS topology filename. Should have suffix .top out_gro : str output gro filename. Should have suffix .gro ffxml : str filename containing input SMIRNOFF FFXML file for use in parameterizing the system Returns ------- success : bool True or False as to success of operation Notes ----- This can be easily broken if there are missing, duplicated, or inconsistent ligand residue names in your box, mol2, and frcmod files. You can use mdtraj to edit the residue names with something like this: trj.top.residue(0).name = "L1" """ from openeye import oechem from openforcefield.typing.engines.smirnoff import ForceField, PME from openforcefield.utils import read_molecules, get_data_filename, generateTopologyFromOEMol # Read in molecules oemols = [] for mol2file in set(gaff_mol2_filenames): mol = oechem.OEGraphMol() ifs = oechem.oemolistream(mol2file) flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_MOL2_Default | oechem.OEIFlavor_MOL2_Forcefield ifs.SetFlavor(oechem.OEFormat_MOL2, flavor) oechem.OEReadMolecule(ifs, mol) oechem.OETriposAtomNames(mol) oemols.append(mol) # Read in PDB file to get topology pdb = app.PDBFile(box_filename) # Load forcefield ff = ForceField(ffxml) # Construct system; charging not needed as mol2 files already have charges here system = ff.createSystem(pdb.topology, oemols, nonbondedMethod=PME, nonbondedCutoff=CUTOFF) # Dump to AMBER format structure = parmed.openmm.topsystem.load_topology(pdb.topology, system, pdb.positions) structure.save(out_top, overwrite=True) structure.save(out_gro, overwrite=True) return True