def test_label_molecules(verbose=False): """Test labeling/getting stats on labeling molecules""" molecules = read_molecules( get_data_filename('molecules/AlkEthOH-tripos.mol2.gz'), verbose=verbose) ffxml = get_data_filename('forcefield/Frosst_AlkEthOH.ffxml') get_molecule_parameterIDs(molecules, ffxml)
def test_smirnoff_energies_vs_parmatfrosst(verbose=False): """Test evaluation of energies from parm@frosst ffxml files versus energies of equivalent systems.""" from openeye import oechem prefix = 'AlkEthOH_' molecules = ['r118', 'r12', 'c1161', 'r0', 'c100', 'c38', 'c1266'] # Loop over molecules, load OEMols and prep for comparison/do comparison for molnm in molecules: f_prefix = os.path.join('molecules', prefix + molnm) mol2file = get_data_filename(f_prefix + '.mol2') prmtop = get_data_filename(f_prefix + '.top') crd = get_data_filename(f_prefix + '.crd') # Load special parm@frosst with parm99/parm@frosst bugs re-added for testing forcefield = ForceField( get_data_filename('forcefield/Frosst_AlkEthOH_parmAtFrosst.ffxml')) # Load OEMol 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) # Do comparison results = compare_molecule_energies(prmtop, crd, forcefield, mol, verbose=verbose)
def test_improper(verbose=False): """Test implement of impropers on benzene.""" from openeye import oechem # Load benzene ifs = oechem.oemolistream(get_data_filename('molecules/benzene.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) ifs.close() # Load forcefield ffxml = get_data_filename('forcefield/benzene_minimal.ffxml') ff = ForceField(ffxml) # Load AMBER files and compare crd = get_data_filename('molecules/benzene.crd') top = get_data_filename('molecules/benzene.top') g0, g1, e0, e1 = compare_molecule_energies(top, crd, ff, mol, skip_assert=True) # Check that torsional energies the same to 1 in 10^6 rel_error = np.abs((g0['torsion'] - g1['torsion']) / g0['torsion']) if rel_error > 2e-5: #Note that this will not be tiny because we use six-fold impropers and they use a single improper raise Exception( "Improper torsion energy for benzene differs too much (relative error %.4g) between AMBER and SMIRNOFF." % rel_error)
def test_merge_system(): """Test merging of a system created from AMBER and another created from SMIRNOFF.""" #Create System from AMBER prefix = os.path.join('systems', 'amber', 'cyclohexane_ethanol_0.4_0.6') prmtop = get_data_filename(prefix + '.prmtop') incrd = get_data_filename(prefix + '.inpcrd') from openforcefield.typing.engines.smirnoff import create_system_from_amber topology0, system0, positions0 = create_system_from_amber(prmtop, incrd) 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 forcefield = ForceField( get_data_filename('forcefield/Frosst_AlkEthOH.ffxml')) topology1, system1, positions1 = create_system_from_molecule( forcefield, mol) merge_system(topology0, topology1, system0, system1, positions0, positions1, verbose=True)
def test_gromacs_roundtrip(): """Save a System (a mixture) to GROMACS, read back in, verify yields same energy and force terms.""" 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) # Create ParmEd structure, save to AMBER a, topfile = tempfile.mkstemp(suffix='.top') a, grofile = tempfile.mkstemp(suffix='.gro') save_system_to_gromacs(pdbfile.topology, system, pdbfile.positions, topfile, grofile) # Read back in and cross-check energies top = parmed.load_file(topfile) gro = parmed.load_file(grofile) gromacssys = top.createSystem(nonbondedMethod=app.NoCutoff, constraints=None, implicitSolvent=None) groups0, groups1, energy0, energy1 = compare_system_energies( pdbfile.topology, pdbfile.topology, gromacssys, system, pdbfile.positions, verbose=False) # Remove temp files os.remove(topfile) os.remove(grofile)
def test_create_system_molecules_parmatfrosst_gbsa(verbose=False): """Test creation of a System object from small molecules to test parm@frosst forcefield with GBSA support. """ forcefield = ForceField( get_data_filename('forcefield/Frosst_AlkEthOH_GBSA.ffxml')) for f in check_AlkEthOH(forcefield, "to test Parm@Frosst parameters", verbose=verbose): yield f
def test_create_system_boxes_smirnoff99Frosst(verbose=False): """Test creation of a System object from some boxes of mixed solvents to test parm@frosst forcefield. """ forcefield = ForceField( get_data_filename('forcefield/smirnoff99Frosst.ffxml')) for f in check_boxes(forcefield, description="to test Parm@frosst parameters", verbose=verbose): yield f
def create_yank_input_files(): """Creates XML, PDB and YAML script files to run YANK calculations. Starting from mol2 files, the script uses packmol to solvate the molecules in TIP3P waters and produces PDB files of the vacuum and solvated boxes together with OpenMM XML System files parametrized with smirnoff99Frosst. A YANK script is generated for each system following the unified FreeSolv protocol. """ database_filepath = os.path.join('..', 'database.json') smirnoff_openmm_dir = os.path.join('..', 'openmmfiles') pdb_dir = os.path.join('..', 'pdbfiles') water_mol2_filepath = get_data_filename( os.path.join('systems', 'monomers', 'tip3p_water.mol2')) # Create directories that don't exist. for directory_path in [smirnoff_openmm_dir, pdb_dir]: if not os.path.exists(directory_path): os.makedirs(directory_path) # Read in database. with open(database_filepath, 'r') as f: database = json.load(f) # Find all molecules. mol2_files_pattern = os.path.join('..', 'mol2files_sybyl', '*.mol2') tripos_filenames = list(glob.glob(mol2_files_pattern)) # Create YANK input files. for i, tripos_filename in enumerate(tripos_filenames): molecule_id, _ = os.path.splitext( os.path.basename(tripos_filename)) # Remove path and extension. print('\rSetting up {} ({}/{}) '.format(molecule_id, i + 1, len(tripos_filenames))) # Output file paths. vacuum_filename = molecule_id + '_vacuum' solvated_filename = molecule_id + '_solvated' vacuum_pdb_filepath = os.path.join(pdb_dir, vacuum_filename + '.pdb') solvated_pdb_filepath = os.path.join(pdb_dir, solvated_filename + '.pdb') vacuum_smirnoff_openmm_filepath = os.path.join( smirnoff_openmm_dir, vacuum_filename + '.xml') solvated_smirnoff_openmm_filepath = os.path.join( smirnoff_openmm_dir, solvated_filename + '.xml') # Export solvated and vacuum molecule in PDB format. create_pdb_files(database[molecule_id]['smiles'], tripos_filename, water_mol2_filepath, vacuum_pdb_filepath, solvated_pdb_filepath) # Create OpenMM XML file parametrized with SMIRNOFF. create_xml_system_files(tripos_filename, water_mol2_filepath, vacuum_pdb_filepath, solvated_pdb_filepath, vacuum_smirnoff_openmm_filepath, solvated_smirnoff_openmm_filepath)
def test_parameter_completeness_check(self): """Test that proper exceptions are raised if a force field fails to assign parameters to valence terms in a molecule.""" from openeye import oechem mol = oechem.OEMol() oechem.OEParseSmiles(mol, 'CCC') oechem.OEAddExplicitHydrogens(mol) oechem.OETriposAtomNames(mol) ff = ForceField(get_data_filename('forcefield/Frosst_AlkEthOH.ffxml')) topology = generateTopologyFromOEMol(mol) # Test nonbonded error checking by wiping out required LJ parameter params = ff.getParameter(paramID='n0001') params['smirks'] = '[#136:1]' ff.setParameter(paramID='n0001', params=params) ff.setParameter(paramID='n0002', params=params) with self.assertRaises(Exception): system = ff.createSystem(topology, [mol]) ff = ForceField(get_data_filename('forcefield/Frosst_AlkEthOH.ffxml')) # Test bond error checking by wiping out a required bond parameter params = ff.getParameter(paramID='b0001') params['smirks'] = '[#136:1]~[*:2]' ff.setParameter(paramID='b0001', params=params) with self.assertRaises(Exception): system = ff.createSystem(topology, [mol]) ff = ForceField(get_data_filename('forcefield/Frosst_AlkEthOH.ffxml')) # Test angle error checking by wiping out a required angle parameter params = ff.getParameter(paramID='a0001') params['smirks'] = '[#136:1]~[*:2]~[*:3]' ff.setParameter(paramID='a0001', params=params) with self.assertRaises(Exception): system = ff.createSystem(topology, [mol]) ff = ForceField(get_data_filename('forcefield/Frosst_AlkEthOH.ffxml')) # Test torsion error checking by wiping out a required torsion parameter params = ff.getParameter(paramID='t0001') params['smirks'] = '[#136:1]~[*:2]~[*:3]~[*:4]' ff.setParameter(paramID='t0001', params=params) ff.setParameter(paramID='t0004', params=params) with self.assertRaises(Exception): system = ff.createSystem(topology, [mol]) ff = ForceField(get_data_filename('forcefield/Frosst_AlkEthOH.ffxml'))
def initialize_system(dt=0.001, temperature=100, forcefield_file='forcefield/smirnoff99Frosst.offxml', smiles="C1CCCCC1"): mol = OEMol() # OEParseSmiles(mol, 'CCOCCSCC') # OEParseSmiles(mol, 'c1ccccc1') OEParseSmiles(mol, smiles) # OEParseSmiles(mol, 'C([C@@H]1[C@H]([C@@H]([C@H](C(O1)O)O)O)O)O') OEAddExplicitHydrogens(mol) masses = get_masses(mol) num_atoms = mol.NumAtoms() topology = generateTopologyFromOEMol(mol) ff = ForceField(get_data_filename(forcefield_file)) nrgs, total_params, offsets = system_builder.construct_energies( ff, mol, False) # dt = 0.0025 # friction = 10.0 # temperature = 300 # gradient descent dt = dt friction = 10.0 temperature = temperature a, b, c = get_abc_coefficents(masses, dt, friction, temperature) buf_size = estimate_buffer_size(1e-10, a) print("BUFFER SIZE", buf_size) omegaOpts = oeomega.OEOmegaOptions() omegaOpts.SetMaxConfs(1) omega = oeomega.OEOmega(omegaOpts) omega.SetStrictStereo(False) if not omega(mol): assert 0 x0 = mol_coords_to_numpy_array(mol) / 10 intg = custom_ops.Integrator_double(dt, buf_size, num_atoms, total_params, a, b, c) context = custom_ops.Context_double(nrgs, intg) x0 = minimizer.minimize_newton_cg(nrgs, x0, total_params) return nrgs, offsets, intg, context, x0, total_params
def check_boxes(forcefield, description="", chargeMethod=None, verbose=False): """Test creation of System from boxes of mixed solvents. """ # Read monomers mols = list() monomers = [ 'water', '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 = [ 'ethanol_water.pdb', 'cyclohexane_water.pdb', '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 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_AlkEthOH.ffxml') ff = ForceField(ffxml) 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 check_AlkEthOH(forcefield, description="", chargeMethod=None, verbose=False): """Test creation of System from AlkEthOH small molecules. """ from openeye import oechem ifs = oechem.oemolistream( get_data_filename('molecules/AlkEthOH-tripos.mol2.gz')) mol = oechem.OEGraphMol() while oechem.OEReadMolecule(ifs, mol): args = {'verbose': verbose, 'chargeMethod': chargeMethod} f = partial(check_system_creation_from_molecule, forcefield, mol, **args) f.description = 'Testing creation of system object from small molecules (%s) %s' % ( mol.GetTitle(), description) yield f
def test_molecule_labeling(verbose=False): """Test using labelMolecules to see which parameters applied to an oemol.""" from openeye import oechem mol = oechem.OEMol() oechem.OEParseSmiles(mol, 'CCC') oechem.OEAddExplicitHydrogens(mol) ff = ForceField(get_data_filename('forcefield/Frosst_AlkEthOH.ffxml')) labels = ff.labelMolecules([mol], verbose=verbose) # Check that force terms aren't empty print(labels[0].keys()) if not 'HarmonicBondGenerator' in labels[0].keys(): raise Exception("No force term assigned for harmonic bonds.") if not 'HarmonicAngleGenerator' in labels[0].keys(): raise Exception("No force term assigned for harmonic angles.") if not 'PeriodicTorsionGenerator' in labels[0].keys(): raise Exception("No force term assigned for periodic torsions.") if not 'NonbondedGenerator' in labels[0].keys(): raise Exception("No nonbonded force term assigned.")
def initialize(input_smiles, gp): train_reference_args = [] train_args = [] train_offset_idxs = [] train_charge_idxs = [] for smi_idx, smiles in enumerate(input_smiles): print("processing", smiles, smi_idx, "/", len(input_smiles)) mol = OEMol() OEParseSmiles(mol, smiles) OEAddExplicitHydrogens(mol) masses = get_masses(mol) num_atoms = mol.NumAtoms() omegaOpts = oeomega.OEOmegaOptions() omegaOpts.SetMaxConfs(1) omega = oeomega.OEOmega(omegaOpts) omega.SetStrictStereo(False) if not omega(mol): assert 0 topology = generateTopologyFromOEMol(mol) reference_forcefield_file = 'forcefield/smirnoff99Frosst_perturbed.offxml' ff = ForceField(get_data_filename(reference_forcefield_file)) params = system_builder.construct_energies(ff, mol, True) train_reference_args.append((params[0], params[1], masses, mol)) params = system_builder.construct_energies(ff, mol, False) # global_params = args[0] # nrg_params = args[1] # total_params = args[2] # masses = args[3] # mol = args[4] # charge_idxs = args[5] train_args.append((gp, params[0], params[1], masses, mol, params[3])) train_offset_idxs.append(params[2]) train_charge_idxs.append(params[3]) label_confs = [generate_conformations(a) for a in train_reference_args] return train_args, train_offset_idxs, train_charge_idxs, label_confs
def test_tip3p_constraints(): """Test that TIP3P distance costraints are correctly applied.""" # TIP3P constrained distances. tip3p_oh_distance = 0.9572 # angstrom tip3p_hoh_angle = 104.52 # angle tip3p_hh_distance = tip3p_oh_distance * np.sin( np.radians(tip3p_hoh_angle / 2)) * 2 expected_distances = [ tip3p_oh_distance, tip3p_oh_distance, tip3p_hh_distance ] # Load tip3p molecule as OEMol. tip3p_mol2_filepath = get_data_filename( os.path.join('systems', 'monomers', 'tip3p_water.mol2')) tip3p_oemol = read_molecules(tip3p_mol2_filepath, verbose=False)[0] # Extract topology and positions. tip3p_topology = generateTopologyFromOEMol(tip3p_oemol) tip3p_positions = positions_from_oemol(tip3p_oemol) # Create tip3p water system. ff = ForceField('forcefield/tip3p.ffxml') system = ff.createSystem(tip3p_topology, [tip3p_oemol]) # Run dynamics. integrator = openmm.VerletIntegrator(2.0 * unit.femtoseconds) context = openmm.Context(system, integrator) context.setPositions(tip3p_positions) integrator.step(50) # Constrained distances are correct. state = context.getState(getPositions=True) new_positions = state.getPositions(asNumpy=True) / unit.angstroms distances = [] for atom_1, atom_2 in [(0, 1), (0, 2), (1, 2)]: # pair of atoms O-H1, O-H2, H1-H2 distances.append( np.linalg.norm(new_positions[atom_1] - new_positions[atom_2])) err_msg = 'expected distances [O-H1, O-H2, H1-H2]: {} A, new distances: {} A' assert np.allclose(expected_distances, distances), err_msg.format(expected_distances, distances)
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)) name = sys.argv[1]+'_'+sys.argv[3] filename = 'packmol_boxes/'+name+'.pdb' pdb = PDBFile(filename) forcefield = ForceField(get_data_filename('forcefield/smirnoff99Frosst.ffxml')) params = forcefield.getParameter(smirks='[#1:1]-[#8]') params['rmin_half']='0.01' params['epsilon']='0.01' forcefield.setParameter(params, smirks='[#1:1]-[#8]') smirkseries = sys.argv[4] eps = sys.argv[5] rmin = sys.argv[6] epsval = sys.argv[7] rminval = sys.argv[8] param = forcefield.getParameter(smirks=smirkseries) param[eps] = epsval param[rmin] = rminval
def test_read_ffxml(): """Test reading of ffxml files. """ forcefield = ForceField( get_data_filename('forcefield/Frosst_AlkEthOH.ffxml'))
def create_yank_input_files(): """Creates XML, PDB and YAML script files to run YANK calculations on a subset of the FreeSolv set. Starting from mol2 files, the script uses packmol to solvate the molecules in TIP3P waters and produces PDB files of the vacuum and solvated boxes together with OpenMM XML System files parametrized with smirnoff99Frosst. A YANK script is generated for each system following the unified FreeSolv protocol. """ database_filepath = os.path.join('..', 'database.json') smirnoff_openmm_dir = os.path.join('..', 'openmmfiles') pdb_dir = os.path.join('..', 'pdbfiles') water_mol2_filepath = get_data_filename( os.path.join('systems', 'monomers', 'tip3p_water.mol2')) # Create directories that don't exist. for directory_path in [smirnoff_openmm_dir, pdb_dir]: if not os.path.exists(directory_path): os.makedirs(directory_path) # Read in database. with open(database_filepath, 'r') as f: database = json.load(f) # Find all molecules. mol2_files_pattern = os.path.join('..', 'mol2files_sybyl', '*.mol2') tripos_filenames = list(glob.glob(mol2_files_pattern)) # Remove everything with names which are NOT in the list of those we need to repeat. file = open( '../../modification_validation/filtered_data/FreeSolv/database_filtered.txt', 'r') database_text = file.readlines() file.close() retain_mols = [] for line in database_text: #If it's not a comment, parse it and add to list if line[0] != '#': retain_mols.append(line.split(';')[0]) fnm = [] for filename in tripos_filenames: molid = os.path.basename(filename).replace('.mol2', '') if molid in retain_mols: fnm.append(filename) tripos_filenames = fnm # Create YANK input files. for i, tripos_filename in enumerate(tripos_filenames): molecule_id, _ = os.path.splitext( os.path.basename(tripos_filename)) # Remove path and extension. print('\rSetting up {} ({}/{}) '.format(molecule_id, i + 1, len(tripos_filenames))) # Output file paths. vacuum_filename = molecule_id + '_vacuum' solvated_filename = molecule_id + '_solvated' vacuum_pdb_filepath = os.path.join(pdb_dir, vacuum_filename + '.pdb') solvated_pdb_filepath = os.path.join(pdb_dir, solvated_filename + '.pdb') vacuum_smirnoff_openmm_filepath = os.path.join( smirnoff_openmm_dir, vacuum_filename + '.xml') solvated_smirnoff_openmm_filepath = os.path.join( smirnoff_openmm_dir, solvated_filename + '.xml') # Export solvated and vacuum molecule in PDB format. create_pdb_files(database[molecule_id]['smiles'], tripos_filename, water_mol2_filepath, vacuum_pdb_filepath, solvated_pdb_filepath) # Create OpenMM XML file parametrized with SMIRNOFF. create_xml_system_files(tripos_filename, water_mol2_filepath, vacuum_pdb_filepath, solvated_pdb_filepath, vacuum_smirnoff_openmm_filepath, solvated_smirnoff_openmm_filepath)
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)) name = sys.argv[1]+'_'+sys.argv[3] filename = 'packmol_boxes/'+name+'.pdb' pdb = PDBFile(filename) FF_filename = get_data_filename('forcefield/smirnoff99Frosst.ffxml') #FF_filename = 'smirnoff99Frosst_with_AllConstraints.ffxml' forcefield = ForceField(FF_filename) params = forcefield.getParameter(smirks='[#1:1]-[#8]') params['rmin_half']='0.01' params['epsilon']='0.01' forcefield.setParameter(params, smirks='[#1:1]-[#8]') smirkseries1 = sys.argv[4] eps = sys.argv[5] rmin = sys.argv[6] epsval1 = sys.argv[7] rminval1 = sys.argv[8] smirkseries2 = sys.argv[9]
def new_param_energy(coords, params, topology, vecs, P=1.01, T=293.15,NPT=False,V=None,P_conv=1.e5,V_conv=1.e-6,Ener_conv=1.e-3,N_part=250.): """ Return potential energies associated with specified parameter perturbations. Parameters ---------- coords: coordinates from the simulation(s) ran on the given molecule params: arbitrary length dictionary of changes in parameter across arbitrary number of states. Highest level key is the molecule AlkEthOH_ID, second level of keys are the new state, the values of each of these subkeys are a arbitrary length list of length 3 lists where the length 3 lists contain information on a parameter to change in the form: [SMIRKS, parameter type, parameter value]. I.e. : params = {'AlkEthOH_c1143':{'State 1':[['[6X4:1]-[#1:2]','k','620'],['[6X4:1]-[#6X4:2]','length','1.53'],...],'State 2':[...],...}} P: Pressure of the system. By default set to 1.01 bar. T: Temperature of the system. By default set to 300 K. Returns ------- E_kn: a kxN matrix of the dimensional energies associated with the forcfield parameters used as input u_kn: a kxN matrix of the dimensionless energies associated with the forcfield parameters used as input """ #------------------- # CONSTANTS #------------------- kB = 0.0083145 #Boltzmann constant (Gas constant) in kJ/(mol*K) beta = 1/(kB*T) #------------------- # PARAMETERS #------------------- params = params mol2files = [] for i in params: mol2files.append('monomers/'+i.rsplit(' ',1)[0]+'.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)) K = len(params['cyclohexane'].keys()) # Load forcefield file #ffxml = 'smirnoff99Frosst_with_AllConstraints.ffxml'# #print('The forcefield being used is smirnoff99Frosst_with_AllConstraints.ffxml') ffxml = get_data_filename('forcefield/smirnoff99Frosst.ffxml') print('The forcefield being used is smirnoff99Frosst.ffxml') ff = ForceField(ffxml) # Generate a topology top = topology#generateTopologyFromOEMol(mol) #----------------- # MAIN #----------------- # Calculate energies E_kn = np.zeros([K,len(coords)],np.float64) u_kn = np.zeros([K,len(coords)],np.float64) for i,j in enumerate(params): AlkEthOH_id = j for k,l in enumerate(params[AlkEthOH_id]): print("Anotha one") for m,n in enumerate(params[AlkEthOH_id][l]): newparams = ff.getParameter(smirks=n[0]) newparams[n[1]]=n[2] ff.setParameter(newparams,smirks=n[0]) system = ff.createSystem(top,mols,nonbondedMethod=PME,nonbondedCutoff=1.125*nanometers,ewaldErrorTolerance=1.e-5) barostat = MonteCarloBarostat(P*bar, T*kelvin, 10) system.addForce(barostat) for o,p in enumerate(coords): e = get_energy(system,p,vecs[o]) if not NPT: E_kn[k,o] = e._value u_kn[k,o] = e._value*beta else: E_kn[k,o] = e._value + P*P_conv*V[o]*V_conv*Ener_conv*N_part u_kn[k,o] = (e._value + P*P_conv*V[o]*V_conv*Ener_conv*N_part)*beta return E_kn,u_kn
# Cross-check energies of molecules from AlkEthOH set using SMIRNOFF xml file # versus energies from AMBER .prmtop and .crd files (parm@frosst params) datapath = './AlkEthOH_inputfiles/AlkEthOH_rings_filt1' #molname = 'AlkEthOH_r0' #That fails, but it's complicated. Try cyclobutane molname = 'AlkEthOH_r51' mol_filename = os.path.join( datapath, molname+'.mol2') # Check if we have this data file; if not we have to extract the archive if not os.path.isfile( mol_filename): print "Extracting archived molecule files." tarfile = 'AlkEthOH_inputfiles.tar.gz' os.system('tar -xf AlkEthOH_inputfiles.tar.gz') # Load OEMol mol = oechem.OEGraphMol() ifs = oechem.oemolistream(mol_filename) 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 forcefield = ForceField(get_data_filename('forcefield/Frosst_AlkEthOH_parmAtFrosst.offxml')) # Compare energies prmtop = os.path.join( datapath, molname+'.top') crd = os.path.join( datapath, molname+'.crd') results = compare_molecule_energies( prmtop, crd, forcefield, mol)
def new_param_energy(coords, params, topology, vecs, P=1.01, T=300.): """ Return potential energies associated with specified parameter perturbations. Parameters ---------- coords: coordinates from the simulation(s) ran on the given molecule params: arbitrary length dictionary of changes in parameter across arbitrary number of states. Highest level key is the molecule AlkEthOH_ID, second level of keys are the new state, the values of each of these subkeys are a arbitrary length list of length 3 lists where the length 3 lists contain information on a parameter to change in the form: [SMIRKS, parameter type, parameter value]. I.e. : params = {'AlkEthOH_c1143':{'State 1':[['[6X4:1]-[#1:2]','k','620'],['[6X4:1]-[#6X4:2]','length','1.53'],...],'State 2':[...],...}} P: Pressure of the system. By default set to 1.01 bar. T: Temperature of the system. By default set to 300 K. Returns ------- E_kn: a kxN matrix of the dimensional energies associated with the forcfield parameters used as input u_kn: a kxN matrix of the dimensionless energies associated with the forcfield parameters used as input """ #------------------- # CONSTANTS #------------------- kB = 0.0083145 #Boltzmann constant (Gas constant) in kcal/(mol*K) beta = 1 / (kB * T) #------------------- # PARAMETERS #------------------- params = params # Determine number of states we wish to estimate potential energies for mol2files = [] for i in params: mol2files.append('monomers/' + i.rsplit(' ', 1)[0] + '.mol2') # mol2files.append('monomers/'+i.rsplit(' ',1)[1]+'.mol2') #print mol2files #mol = 'Mol2_files/'+mols[0]+'.mol2' #K = len(params[mols[0]].keys()) #if np.shape(params) != np.shape(N_k): raise "K_k and N_k must have same dimensions" # Determine max number of samples to be drawn from any state #mol2files = ['monomers/'+sys.argv[1]+'.mol2','monomers/'+sys.argv[4]+'.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)) K = len(params['cyclohexane'].keys()) # Load forcefield file ffxml = get_data_filename('forcefield/smirnoff99Frosst.ffxml') ff = ForceField(ffxml) # Generate a topology #from smarty.forcefield import generateTopologyFromOEMol top = topology #generateTopologyFromOEMol(mol) #----------------- # MAIN #----------------- # Calculate energies E_kn = np.zeros([K, len(coords)], np.float64) u_kn = np.zeros([K, len(coords)], np.float64) for i, j in enumerate(params): AlkEthOH_id = j for k, l in enumerate(params[AlkEthOH_id]): for m, n in enumerate(params[AlkEthOH_id][l]): newparams = ff.getParameter(smirks=n[0]) newparams[n[1]] = n[2] ff.setParameter(newparams, smirks=n[0]) system = ff.createSystem(top, mols, nonbondedMethod=PME, nonbondedCutoff=12. * angstroms) barostat = MonteCarloBarostat(P * bar, T * kelvin, 25) system.addForce(barostat) #print system for o, p in enumerate(coords): e = get_energy(system, p, vecs[o]) print o, e E_kn[k, o] = e._value u_kn[k, o] = e._value * beta return E_kn, u_kn
def new_param_energy_vac(coords, params, T=293.15): """ Return potential energies associated with specified parameter perturbations. Parameters ---------- coords: coordinates from the simulation(s) ran on the given molecule params: arbitrary length dictionary of changes in parameter across arbitrary number of states. Highest level key is the molecule AlkEthOH_ID, second level of keys are the new state, the values of each of these subkeys are a arbitrary length list of length 3 lists where the length 3 lists contain information on a parameter to change in the form: [SMIRKS, parameter type, parameter value]. I.e. : params = {'AlkEthOH_c1143':{'State 1':[['[6X4:1]-[#1:2]','k','620'],['[6X4:1]-[#6X4:2]','length','1.53'],...],'State 2':[...],...}} T: Temperature of the system. By default set to 300 K. Returns ------- E_kn: a kxN matrix of the dimensional energies associated with the forcfield parameters used as input u_kn: a kxN matrix of the dimensionless energies associated with the forcfield parameters used as input """ #------------------- # CONSTANTS #------------------- kB = 0.0083145 #Boltzmann constant (Gas constant) in kJ/(mol*K) beta = 1/(kB*T) #------------------- # PARAMETERS #------------------- params = params # Determine number of states we wish to estimate potential energies for mols = [] for i in params: mols.append(i) mol = 'monomers/'+mols[0]+'.mol2' K = len(params[mols[0]].keys()) #------------- # SYSTEM SETUP #------------- verbose = False # suppress echos from OEtoolkit functions ifs = oechem.oemolistream(mol) mol = oechem.OEMol() # This uses parm@frosst atom types, so make sure to use the forcefield-flavor reader flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_MOL2_Default | oechem.OEIFlavor_MOL2_Forcefield ifs.SetFlavor( oechem.OEFormat_MOL2, flavor) oechem.OEReadMolecule(ifs, mol ) # Perceive tripos types oechem.OETriposAtomNames(mol) # Load forcefield file #ffxml = 'smirnoff99Frosst_with_AllConstraints.ffxml'# #print('The forcefield being used is smirnoff99Frosst_with_AllConstraints.ffxml') ffxml = get_data_filename('forcefield/smirnoff99Frosst.ffxml') print('The forcefield being used is smirnoff99Frosst.ffxml') ff = ForceField(ffxml) # Generate a topology topology = generateTopologyFromOEMol(mol) #----------------- # MAIN #----------------- # Calculate energies E_kn = np.zeros([K,len(coords)],np.float64) u_kn = np.zeros([K,len(coords)],np.float64) for i,j in enumerate(params): AlkEthOH_id = j for k,l in enumerate(params[AlkEthOH_id]): print("Anotha one") for m,n in enumerate(params[AlkEthOH_id][l]): newparams = ff.getParameter(smirks=n[0]) newparams[n[1]]=n[2] ff.setParameter(newparams,smirks=n[0]) system = ff.createSystem(topology, [mol]) #print(newparams) for o,p in enumerate(coords): e = get_energy_vac(system,p) E_kn[k,o] = e._value u_kn[k,o] = e._value*beta return E_kn,u_kn
def test_protein_structure(self): from simtk.openmm import app pdbfile = utils.get_data_filename('proteins/T4-protein.pdb') proteinpdb = app.PDBFile(pdbfile) protein_structure = utils.generateProteinStructure(proteinpdb) self.assertIsInstance(protein_structure, parmed.structure.Structure)
# Cross-check energies of molecules from AlkEthOH set using SMIRNOFF xml file # versus energies from AMBER .prmtop and .crd files (parm@frosst params) datapath = './AlkEthOH_inputfiles/AlkEthOH_rings_filt1' #molname = 'AlkEthOH_r0' #That fails, but it's complicated. Try cyclobutane molname = 'AlkEthOH_r51' mol_filename = os.path.join(datapath, molname + '.mol2') # Check if we have this data file; if not we have to extract the archive if not os.path.isfile(mol_filename): print "Extracting archived molecule files." tarfile = 'AlkEthOH_inputfiles.tar.gz' os.system('tar -xf AlkEthOH_inputfiles.tar.gz') # Load OEMol mol = oechem.OEGraphMol() ifs = oechem.oemolistream(mol_filename) 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 forcefield = ForceField( get_data_filename('forcefield/Frosst_AlkEthOH_parmAtFrosst.ffxml')) # Compare energies prmtop = os.path.join(datapath, molname + '.top') crd = os.path.join(datapath, molname + '.crd') results = compare_molecule_energies(prmtop, crd, forcefield, mol)
def test_tip3p_solvated_molecule_energy(): """Check the energy of a TIP3P solvated molecule is the same with SMIRNOFF and OpenMM. This test makes also use of defining the force field with multiple FFXML files, and test the energy of mixture systems (i.e. molecule plus water). """ # TODO remove this function when ParmEd#868 is fixed def add_water_bonds(system): """Hack to make tip3p waters work with ParmEd Structure.createSystem. Bond parameters need to be specified even when constrained. """ k_tip3p = 462750.4 * unit.kilojoule_per_mole / unit.nanometers**2 length_tip3p = 0.09572 * unit.nanometers for force in system.getForces(): if isinstance(force, openmm.HarmonicBondForce): force.addBond(particle1=0, particle2=1, length=length_tip3p, k=k_tip3p) force.addBond(particle1=0, particle2=2, length=length_tip3p, k=k_tip3p) monomers_dir = get_data_filename(os.path.join('systems', 'monomers')) # Load tip3p molecule as OEMol. tip3p_mol2_filepath = os.path.join(monomers_dir, 'tip3p_water.mol2') tip3p_oemol = read_molecules(tip3p_mol2_filepath, verbose=False)[0] # Create OpenMM-parametrized water ParmEd Structure. tip3p_openmm_ff = openmm.app.ForceField('tip3p.xml') tip3p_topology = generateTopologyFromOEMol(tip3p_oemol) tip3p_positions = positions_from_oemol(tip3p_oemol) tip3p_openmm_system = tip3p_openmm_ff.createSystem(tip3p_topology) # TODO remove this line when ParmEd#868 is fixed # Hack to make tip3p waters work with ParmEd Structure.createSystem. add_water_bonds(tip3p_openmm_system) tip3p_openmm_structure = parmed.openmm.topsystem.load_topology( tip3p_topology, tip3p_openmm_system, tip3p_positions) # Test case: monomer_filename test_cases = [('smirnoff99Frosst.ffxml', 'ethanol.mol2'), ('smirnoff99Frosst.ffxml', 'methane.mol2')] for ff_name, molecule_filename in test_cases: # Load molecule as OEMol. molecule_filepath = os.path.join(monomers_dir, molecule_filename) molecule_oemol = read_molecules(molecule_filepath, verbose=False)[0] # Create molecule parametrized ParmEd args. molecule_ff = ForceField('forcefield/' + ff_name) molecule_args = forcefield_utils.create_system_from_molecule( molecule_ff, molecule_oemol) molecule_structure = parmed.openmm.topsystem.load_topology( *molecule_args) _, _, molecule_positions = molecule_args # Merge molecule and OpenMM TIP3P water. structure = tip3p_openmm_structure + molecule_structure structure.positions = np.append(tip3p_positions, molecule_positions, axis=0) system = structure.createSystem() energy_openmm = get_energy(system, structure.positions) # Test the creation of system with multiple force field files. ff = ForceField('forcefield/' + ff_name, 'forcefield/tip3p.ffxml') system = ff.createSystem(structure.topology, [tip3p_oemol, molecule_oemol]) # TODO remove this line when ParmEd#868 is fixed # Add bonds to match ParmEd hack above. add_water_bonds(system) energy_smirnoff = get_energy(system, structure.positions) # The energies of the systems must be the same. assert np.isclose(energy_openmm, energy_smirnoff), 'OpenMM: {}, SMIRNOFF: {}'.format( energy_openmm, energy_smirnoff)
#!/bin/env python from simtk.openmm import app import openforcefield.utils as utils from openeye import oechem molecule = oechem.OEMol() molpdb = utils.get_data_filename('molecules/toluene.pdb') with oechem.oemolistream(molpdb) as ifs: oechem.OEReadMolecule(ifs, molecule) molecule_structure = utils.generateSMIRNOFFStructure(molecule) print('Molecule:', molecule_structure) pdbfile = utils.get_data_filename('proteins/T4-protein.pdb') proteinpdb = app.PDBFile(pdbfile) protein_structure = utils.generateProteinStructure(proteinpdb) print('Protein:', protein_structure) structure = utils.mergeStructure(protein_structure, molecule_structure) print('Complex:', structure)
def test_read_ffxml_gbsa(): """Test reading of ffxml files with GBSA support. """ forcefield = ForceField( get_data_filename('forcefield/Frosst_AlkEthOH_GBSA.ffxml'))
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)
mol_filename = 'mol1.mol2' # Define a few simulation parameters time_step = 2*unit.femtoseconds # simulation timestep temperature = 300*unit.kelvin # simulation temperature friction = 1/unit.picosecond # collision rate num_steps = 1000000 # number of steps to run trj_freq = 1000 # number of steps per written trajectory frame data_freq = 1000 # number of steps per written simulation statistics # Load molecule and create pdb object pdb = PDBFile(pdb_filename) # Load a SMIRNOFF forcefield #forcefield = ForceField(get_data_filename('forcefield/Frosst_AlkEthOH_parmAtFrosst.offxml')) forcefield = ForceField(get_data_filename('forcefield/smirnoff99Frosst.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) pdbatoms = list(pdb.topology.atoms()) labels = forcefield.labelMolecules([mol])[0] for key, val in labels.items(): print(key)