def test_packmol_simulation_ternary(): smiles_list = ["Cc1ccccc1", "c1ccccc1", "CC"] pdb_filenames = [] ligand_trajectories, ffxml = utils.smiles_to_mdtraj_ffxml(smiles_list) for k, ligand_traj in enumerate(ligand_trajectories): pdb_filename = tempfile.mktemp(suffix=".pdb") ligand_traj.save(pdb_filename) pdb_filenames.append(pdb_filename) pdb_filenames = pdb_filenames[0:2] + [ligand_traj] # Test passing BOTH pdb filenames and trajectories as input. trj = packmol.pack_box(pdb_filenames, [6, 11, 23]) xyz = trj.openmm_positions(0) top = trj.top.to_openmm() top.setUnitCellDimensions(mm.Vec3(*trj.unitcell_lengths[0])*u.nanometer) forcefield = app.ForceField(ffxml) temperature = 300 * u.kelvin friction = 0.1 / u.picosecond timestep = 0.1 * u.femtosecond system = forcefield.createSystem(top, nonbondedMethod=app.PME, nonbondedCutoff=1.0 * u.nanometers, constraints=None) integrator = mm.LangevinIntegrator(temperature, friction, timestep) simulation = app.Simulation(top, system, integrator) simulation.context.setPositions(xyz) simulation.step(25)
def test_amber_binary_mixture(): sustiva_filename = utils.get_data_filename("chemicals/etoh/etoh.mol2") etoh_filename = utils.get_data_filename("chemicals/etoh/etoh_renamed.mol2") trj0, trj1 = md.load(sustiva_filename), md.load(etoh_filename) # Hack to assign unique residue names that are consistent with contents of mol2 files trj0.top.residue(0).name = "LIG" trj1.top.residue(0).name = "LI2" trj_list = [trj0, trj1] with utils.enter_temp_directory( ): # Prevents creating tons of GAFF files everywhere. box_filename = "./box.pdb" box_trj = packmol.pack_box(trj_list, [25, 50]) box_trj.save(box_filename) gaff_mol2_filename0, frcmod_filename0 = amber.run_antechamber( "sustiva", sustiva_filename, charge_method=None) gaff_mol2_filename1, frcmod_filename1 = amber.run_antechamber( "etoh", etoh_filename, charge_method=None) mol2_filenames = [gaff_mol2_filename0, gaff_mol2_filename1] frcmod_filenames = [frcmod_filename0, frcmod_filename1] prmtop_filename = "./out.prmtop" inpcrd_filename = "./out.inpcrd" tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename, prmtop_filename, inpcrd_filename) print(tleap_cmd)
def _via_helper_other_solvent(cls, density, num_solvent, **kwargs): from openmoltools import packmol density = density.value_in_unit(unit.gram / unit.milliliter) if cls.backend == "openeye": box_size = packmol.approximate_volume_by_density( [cls.smiles, cls.solvent_smiles], [1, num_solvent], density=density, box_scaleup_factor=cls.box_scaleup_factor, box_buffer=cls.default_padding) else: box_size = approximate_volume_by_density( [cls.smiles, cls.solvent_smiles], [1, num_solvent], density=density, box_scaleup_factor=cls.box_scaleup_factor, box_buffer=cls.default_padding) packmol_out = packmol.pack_box( [cls.pdb_filename, cls.solvent_pdb_filename], [1, num_solvent], box_size=box_size) import mdtraj as md cls.system_pmd = cls.ligand_pmd + (cls.solvent_pmd * num_solvent) cls.system_pmd.positions = packmol_out.openmm_positions(0) cls.system_pmd.box_vectors = packmol_out.openmm_boxes(0) try: # TODO should maybe delete the higher parent level? i.e. -2? shutil.rmtree("/".join(cls.pdb_filename.split("/")[:-1])) shutil.rmtree("/".join(cls.solvent_pdb_filename.split("/")[:-1])) del cls.ligand_pmd, cls.solvent_pmd except Exception as e: print("Error due to : {}".format(e)) cls.system_pmd.title = cls.smiles return cls.system_pmd
def test_amber_box(): etoh_filename = utils.get_data_filename("chemicals/etoh/etoh.mol2") trj_list = [md.load(etoh_filename)] with utils.enter_temp_directory( ): # Prevents creating tons of GAFF files everywhere. box_filename = "./box.pdb" box_trj = packmol.pack_box(trj_list, [50]) box_trj.save(box_filename) gaff_mol2_filename1, frcmod_filename1 = amber.run_antechamber( "etoh", etoh_filename, charge_method=None) mol2_filenames = [gaff_mol2_filename1] frcmod_filenames = [frcmod_filename1] prmtop_filename = "./out.prmtop" inpcrd_filename = "./out.inpcrd" tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename, prmtop_filename, inpcrd_filename) print(tleap_cmd)
def test_amber_binary_mixture(): sustiva_filename = utils.get_data_filename("chemicals/etoh/etoh.mol2") etoh_filename = utils.get_data_filename("chemicals/etoh/etoh_renamed.mol2") trj0, trj1 = md.load(sustiva_filename), md.load(etoh_filename) # Hack to assign unique residue names that are consistent with contents of mol2 files trj0.top.residue(0).name = "LIG" trj1.top.residue(0).name = "LI2" trj_list = [trj0, trj1] with utils.enter_temp_directory(): # Prevents creating tons of GAFF files everywhere. box_filename = "./box.pdb" box_trj = packmol.pack_box(trj_list, [25, 50]) box_trj.save(box_filename) gaff_mol2_filename0, frcmod_filename0 = amber.run_antechamber("sustiva", sustiva_filename, charge_method=None) gaff_mol2_filename1, frcmod_filename1 = amber.run_antechamber("etoh", etoh_filename, charge_method=None) mol2_filenames = [gaff_mol2_filename0, gaff_mol2_filename1] frcmod_filenames = [frcmod_filename0, frcmod_filename1] prmtop_filename = "./out.prmtop" inpcrd_filename = "./out.inpcrd" tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename, prmtop_filename, inpcrd_filename) print(tleap_cmd)
def mixture_setup(molfiles,resnames,nmols,boxsize,solvate=True): """ Function that generalises the function 'nanopipeline' for general mixtures. Starting with the mol2 files of drug and dye, the molecules are parametrised, assembled uniformly in cubic box, and AMBER prmtop and inpcrd files are created for the system. Parameters ---------- molfiles : list of str the mol2 file name of the compounds, with or without hydrogens resnames : list of str the residue names you want for the molecules residue name and output file naming schemes nmols : list of int the number of molecules you want in the box, excluding water and ions boxsize: int the length of the cubic box in Angstroms Returns ------- out.inpcrd and out.out.prmtop are created in the working directory, as well gaff output files """ # Parmetrizing with antechamber via openeye: for i in range(len(molfiles)): parametrize_mol(molfiles[i],resnames[i]) # Creating box of drugs and dye. Packmol requires PDB files for i in range(len(molfiles)): mol2pdb(resnames[i]+'_gaff.mol2') molfiles_pdb = [mol + '_gaff.pdb' for mol in resnames] box = packmol.pack_box(molfiles_pdb, nmols, tolerance=2.0, box_size=boxsize) box.save('box.pdb') # Running tleap to create out.prmtop out.inpcrd for use with openmm tleap_input = tleap_mixture(resnames,'box',solvate=solvate,run=True)
def solvate(ase_mol, mol_id, ase_solvent_mol, solvent_id, n_solvent=100): """Build solvent sphere around molecule""" from openmoltools import packmol # needs to be here rather than global because we sometimes pickle this function and send it to the server to run # because on importing packmol sets various paths (e.g. where temporary files are kept) # so we don't want to import those from the local session to the cluster ##File paths mol_xyz_path = mol_id + '.xyz' mol_pdb_path = mol_id + '.pdb' solvent_xyz_path = solvent_id + '.xyz' solvent_pdb_path = solvent_id + '.pdb' ##File construction of xyz and pdb files ase_mol.write(mol_xyz_path) pybel_mol = readfile("xyz", mol_xyz_path).next() pybel_mol.write('pdb', mol_pdb_path, overwrite=True) ##File construction of solvent pdb files if not os.path.isfile(solvent_xyz_path): ase_solvent_mol.write(solvent_xyz_path) if not os.path.isfile(solvent_pdb_path): pybel_mol = readfile("xyz", solvent_xyz_path).next() pybel_mol.write('pdb', solvent_pdb_path) solute_traj = md.load(mol_pdb_path) solvent_traj = md.load(solvent_pdb_path) #currently only works for solvent composed of Hydrogens and Carbons! #size returns length of box as measured in Angstrom size = packmol.approximate_volume([mol_pdb_path, solvent_pdb_path], [1,n_solvent]) if ase_mol != ase_solvent_mol: solvated_traj = packmol.pack_box([solute_traj,solvent_traj],[1,n_solvent], fix=True, shape='sphere', size=size*0.75, seed= np.random.randint(2**16), ) else: solvated_traj = packmol.pack_box([solvent_traj],[n_solvent+1], fix=True, shape='sphere', size=size*0.75, seed= np.random.randint(2**16), ) return to_ase_frames(solvated_traj)[0]
def nanopipeline(drugmol2,dyemol2,drugname='LIG',dyename='DYE',ndrugs=10,ndye=20,boxsize=50,neutralize=True,implicit=False): """ Starting with the mol2 files of drug and dye, the molecules are parametrised, assembled uniformly in cubic box, and AMBER prmtop and inpcrd files are created for the system. Parameters ---------- drugmol2, dyemol2 : str, str the mol2 file name of the drug/dye, with or without hydrogens drugname, dyename : str, str the residue name you want for the drug/dye residue name and output file naming schemes ndrugs/ndye: int the number of drug/dye molecules you want in the box boxsize: int the length of the cubic box in Angstroms Returns ------- out.inpcrd and out.out.prmtop are created in the working directory, as well gaff output files """ # Parmetrizing with antechamber via openeye: parametrize_mol(drugmol2,drugname) parametrize_mol(dyemol2,dyename) # Creating box of drugs and dye. Packmol requires PDB files mol2pdb(drugname+'_gaff.mol2') mol2pdb(dyename+'_gaff.mol2') if neutralize == True: box = packmol.pack_box([drugname+'_gaff.pdb',dyename+'_gaff.pdb','Na.pdb'],[ndrugs,ndye,ndye], tolerance=2.0, box_size=boxsize) else: box = packmol.pack_box([drugname+'_gaff.pdb',dyename+'_gaff.pdb'],[ndrugs,ndye], tolerance=2.0, box_size=boxsize) box.save('box.pdb') #os.remove(drugname+'_gaff.pdb') #os.remove(dyename+'_gaff.pdb') # Running tleap to create out.prmtop out.inpcrd for use with openmm #tleap_nanosim(drugname,dyename,'box') if implicit == False: tleap_mixture([drugname,dyename],'box',solvate=True,implicit=False,run=True) else: tleap_mixture([drugname,dyename],'box',solvate=False,implicit=True,run=True)
def _via_helper(cls, density, num_lig, **kwargs): # TODO !!!!!!!!!!!! approximating volume by density if not possible via rdkit at the moment. """ Helper function for via_rdkit or via_openeye Parameters ---------------- density : simtk.unit Density of liquid box num_lig : int Number of replicates of the molecule Returns ------------------ system_pmd : parmed.structure The parameterised system as parmed object """ import mdtraj as md # TODO packmol can accept file name as input too, no need for this really from openmoltools import packmol density = density.value_in_unit(unit.gram / unit.milliliter) ligand_mdtraj = md.load(cls.pdb_filename)[0] try: # TODO better error handling if openeye is not detected #box_size = packmol.approximate_volume_by_density([smiles], [num_lig], density=density, box_scaleup_factor=1.1, box_buffer=2.0) box_size = packmol.approximate_volume_by_density( [cls.smiles], [num_lig], density=density, box_scaleup_factor=cls.box_scaleup_factor, box_buffer=2.0) except: box_size = approximate_volume_by_density( [cls.smiles], [num_lig], density=density, box_scaleup_factor=box_scaleup_factor, box_buffer=2.0) packmol_out = packmol.pack_box([ligand_mdtraj], [num_lig], box_size=box_size) cls.system_pmd = cls.ligand_pmd * num_lig cls.system_pmd.positions = packmol_out.openmm_positions(0) cls.system_pmd.box_vectors = packmol_out.openmm_boxes(0) try: shutil.rmtree("/".join(cls.pdb_filename.split("/")[:-1])) del cls.ligand_pmd except Exception as e: print("Error due to : {}".format(e)) cls.system_pmd.title = cls.smiles return cls.system_pmd
def test_binary_mixture_rename(): smiles_string0 = "CCCCCC" smiles_string1 = "CCCCCCCCC" with utils.enter_temp_directory( ): # Prevents creating tons of GAFF files everywhere. mol2_filename0 = "./A.mol2" frcmod_filename0 = "./A.frcmod" mol2_filename1 = "./B.mol2" frcmod_filename1 = "./B.frcmod" gaff_mol2_filenames = [mol2_filename0, mol2_filename1] frcmod_filenames = [frcmod_filename0, frcmod_filename1] prmtop_filename = "./box.prmtop" inpcrd_filename = "./box.inpcrd" openmoltools.openeye.smiles_to_antechamber(smiles_string0, mol2_filename0, frcmod_filename0) openmoltools.openeye.smiles_to_antechamber(smiles_string1, mol2_filename1, frcmod_filename1) openmoltools.utils.randomize_mol2_residue_names(gaff_mol2_filenames) box_pdb_filename = "./box.pdb" gaff_mol2_filenames = [mol2_filename0, mol2_filename1] n_monomers = [10, 20] packed_trj = packmol.pack_box( [md.load(mol2) for mol2 in gaff_mol2_filenames], n_monomers) packed_trj.save(box_pdb_filename) tleap_cmd = openmoltools.amber.build_mixture_prmtop( gaff_mol2_filenames, frcmod_filenames, box_pdb_filename, prmtop_filename, inpcrd_filename) prmtop = app.AmberPrmtopFile(prmtop_filename) inpcrd = app.AmberInpcrdFile(inpcrd_filename) system = prmtop.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=1.0 * u.nanometers, constraints=app.HBonds)
def test_amber_water_mixture(): water_filename = utils.get_data_filename("chemicals/water/water.mol2") etoh_filename = utils.get_data_filename("chemicals/etoh/etoh.mol2") sustiva_filename = utils.get_data_filename("chemicals/sustiva/sustiva.mol2") with utils.enter_temp_directory(): # Prevents creating tons of GAFF files everywhere. shutil.copy( water_filename, 'c1.mol2' ) shutil.copy( etoh_filename, 'c2.mol2' ) shutil.copy( sustiva_filename, 'c3.mol2') water_filename = 'c1.mol2' etoh_filename = 'c2.mol2' sustiva_filename = 'c3.mol2' #Randomize residue names to avoid clashes utils.randomize_mol2_residue_names( [ water_filename, etoh_filename, sustiva_filename] ) trj0, trj1, trj2 = md.load(water_filename), md.load(etoh_filename), md.load(sustiva_filename) trj_list = [trj0, trj1, trj2] box_filename = "./box.pdb" box_trj = packmol.pack_box(trj_list, [300, 25, 3]) box_trj.save(box_filename) gaff_mol2_filename0, frcmod_filename0 = amber.run_antechamber("water", water_filename, charge_method=None) gaff_mol2_filename1, frcmod_filename1 = amber.run_antechamber("etoh", etoh_filename, charge_method=None) gaff_mol2_filename2, frcmod_filename2 = amber.run_antechamber("sustiva", sustiva_filename, charge_method=None) mol2_filenames = [gaff_mol2_filename0, gaff_mol2_filename1, gaff_mol2_filename2] frcmod_filenames = [frcmod_filename0, frcmod_filename1, frcmod_filename2] prmtop_filename = "./out.prmtop" inpcrd_filename = "./out.inpcrd" shutil.copy(box_filename, 'renamed.pdb') tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, 'renamed.pdb', prmtop_filename, inpcrd_filename) print(tleap_cmd) #Also do here for case of GAFF water tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename, prmtop_filename, inpcrd_filename, water_model = None) print(tleap_cmd) #Also do here for case of SPC tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, 'renamed.pdb', prmtop_filename, inpcrd_filename, water_model = 'SPC') print(tleap_cmd)
def test_packmol_simulation_ternary_bydensity(): smiles_list = ["Cc1ccccc1", "c1ccccc1", "CC"] pdb_filenames = [] ligand_trajectories, ffxml = utils.smiles_to_mdtraj_ffxml(smiles_list) for k, ligand_traj in enumerate(ligand_trajectories): pdb_filename = tempfile.mktemp(suffix=".pdb") ligand_traj.save(pdb_filename) pdb_filenames.append(pdb_filename) pdb_filenames = pdb_filenames[0:2] + [ ligand_traj ] # Test passing BOTH pdb filenames and trajectories as input. size = packmol.approximate_volume_by_density(smiles_list, [12, 22, 46]) trj = packmol.pack_box(pdb_filenames, [12, 22, 46], box_size=size) # The box size should be set as expected (in nanometers). assert all( trj.unitcell_lengths[0] == [size / 10.0, size / 10.0, size / 10.0]) xyz = trj.openmm_positions(0) top = trj.top.to_openmm() top.setUnitCellDimensions(mm.Vec3(*trj.unitcell_lengths[0]) * u.nanometer) forcefield = app.ForceField(ffxml) temperature = 300 * u.kelvin friction = 91.0 / u.picosecond timestep = 0.1 * u.femtosecond system = forcefield.createSystem(top, nonbondedMethod=app.PME, nonbondedCutoff=1.0 * u.nanometers, constraints=None) integrator = mm.LangevinIntegrator(temperature, friction, timestep) simulation = app.Simulation(top, system, integrator) simulation.context.setPositions(xyz) simulation.minimizeEnergy() simulation.step(25)
def test_amber_box(): etoh_filename = utils.get_data_filename("chemicals/etoh/etoh.mol2") trj_list = [md.load(etoh_filename)] with utils.enter_temp_directory(): # Prevents creating tons of GAFF files everywhere. box_filename = "./box.pdb" box_trj = packmol.pack_box(trj_list, [50]) box_trj.save(box_filename) gaff_mol2_filename1, frcmod_filename1 = amber.run_antechamber("etoh", etoh_filename, charge_method=None) mol2_filenames = [gaff_mol2_filename1] frcmod_filenames = [frcmod_filename1] prmtop_filename = "./out.prmtop" inpcrd_filename = "./out.inpcrd" tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename, prmtop_filename, inpcrd_filename) print(tleap_cmd)
def create_pdb_files(molecule_smiles, molecule_mol2_filepath, water_mol2_filepath, vacuum_pdb_filepath, solvated_pdb_filepath): """Create vacuum and solvated molecule box and save in PDB format. The function uses packmol to solvate the molecule in 1309 waters. Parameters ---------- molecule_smiles : str SMILES string for the molecule. molecule_mol2_filepath : str Path to the mol2 file describing the molecule to solvate. water_mol2_filepath : str Path to the mol2 file describing the water molecule geometry. vacuum_pdb_filepath : str Output path for the PDB file describing the molecule in vacuum. solvated_pdb_filepath : str Output path for the PDB file of the solvated molecule. """ n_monomers = [1, 1309] # molecule, waters mol_traj = md.load(molecule_mol2_filepath) water_traj = md.load(water_mol2_filepath) # Export molecule in PDB format for vacuum calculation. mol_traj.save_pdb(vacuum_pdb_filepath) # Estimate box size based on water density. box_size = packmol.approximate_volume_by_density([molecule_smiles, 'O'], n_monomers) # Solvate molecule and export PDB. packed_traj = packmol.pack_box([mol_traj, water_traj], n_molecules_list=[1, 1309], box_size=box_size) packed_traj.save_pdb(solvated_pdb_filepath)
def test_packmol_simulation_ternary(): smiles_list = ["Cc1ccccc1", "c1ccccc1", "CC"] pdb_filenames = [] ligand_trajectories, ffxml = utils.smiles_to_mdtraj_ffxml(smiles_list) for k, ligand_traj in enumerate(ligand_trajectories): pdb_filename = tempfile.mktemp(suffix=".pdb") ligand_traj.save(pdb_filename) pdb_filenames.append(pdb_filename) pdb_filenames = pdb_filenames[0:2] + [ ligand_traj ] # Test passing BOTH pdb filenames and trajectories as input. trj = packmol.pack_box(pdb_filenames, [6, 11, 23]) xyz = trj.openmm_positions(0) top = trj.top.to_openmm() top.setUnitCellDimensions(mm.Vec3(*trj.unitcell_lengths[0]) * u.nanometer) forcefield = app.ForceField(ffxml) temperature = 300 * u.kelvin friction = 0.1 / u.picosecond timestep = 0.1 * u.femtosecond system = forcefield.createSystem(top, nonbondedMethod=app.PME, nonbondedCutoff=1.0 * u.nanometers, constraints=None) integrator = mm.LangevinIntegrator(temperature, friction, timestep) simulation = app.Simulation(top, system, integrator) simulation.context.setPositions(xyz) simulation.step(25)
def test_packmol_simulation_ternary_bydensity(): smiles_list = ["Cc1ccccc1", "c1ccccc1", "CC"] pdb_filenames = [] ligand_trajectories, ffxml = utils.smiles_to_mdtraj_ffxml(smiles_list) for k, ligand_traj in enumerate(ligand_trajectories): pdb_filename = tempfile.mktemp(suffix=".pdb") ligand_traj.save(pdb_filename) pdb_filenames.append(pdb_filename) pdb_filenames = pdb_filenames[0:2] + [ligand_traj] # Test passing BOTH pdb filenames and trajectories as input. size = packmol.approximate_volume_by_density( smiles_list, [12, 22, 46] ) trj = packmol.pack_box(pdb_filenames, [12, 22, 46], box_size = size) # The box size should be set as expected (in nanometers). assert all(trj.unitcell_lengths[0] == [size/10.0, size/10.0, size/10.0]) xyz = trj.openmm_positions(0) top = trj.top.to_openmm() top.setUnitCellDimensions(mm.Vec3(*trj.unitcell_lengths[0])*u.nanometer) forcefield = app.ForceField(ffxml) temperature = 300 * u.kelvin friction = 91.0 / u.picosecond timestep = 0.1 * u.femtosecond system = forcefield.createSystem(top, nonbondedMethod=app.PME, nonbondedCutoff=1.0 * u.nanometers, constraints=None) integrator = mm.LangevinIntegrator(temperature, friction, timestep) simulation = app.Simulation(top, system, integrator) simulation.context.setPositions(xyz) simulation.minimizeEnergy() simulation.step(25)
def test_binary_mixture_rename(): smiles_string0 = "CCCCCC" smiles_string1 = "CCCCCCCCC" with utils.enter_temp_directory(): # Prevents creating tons of GAFF files everywhere. mol2_filename0 = "./A.mol2" frcmod_filename0 = "./A.frcmod" mol2_filename1 = "./B.mol2" frcmod_filename1 = "./B.frcmod" gaff_mol2_filenames = [mol2_filename0, mol2_filename1] frcmod_filenames = [frcmod_filename0, frcmod_filename1] prmtop_filename = "./box.prmtop" inpcrd_filename = "./box.inpcrd" openmoltools.openeye.smiles_to_antechamber(smiles_string0, mol2_filename0, frcmod_filename0) openmoltools.openeye.smiles_to_antechamber(smiles_string1, mol2_filename1, frcmod_filename1) openmoltools.utils.randomize_mol2_residue_names(gaff_mol2_filenames) box_pdb_filename = "./box.pdb" gaff_mol2_filenames = [mol2_filename0, mol2_filename1] n_monomers = [10, 20] packed_trj = packmol.pack_box([md.load(mol2) for mol2 in gaff_mol2_filenames], n_monomers) packed_trj.save(box_pdb_filename) tleap_cmd = openmoltools.amber.build_mixture_prmtop(gaff_mol2_filenames, frcmod_filenames, box_pdb_filename, prmtop_filename, inpcrd_filename) prmtop = app.AmberPrmtopFile(prmtop_filename) inpcrd = app.AmberInpcrdFile(inpcrd_filename) system = prmtop.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=1.0*u.nanometers, constraints=app.HBonds)
def test_amber_water_mixture(): water_filename = utils.get_data_filename("chemicals/water/water.mol2") etoh_filename = utils.get_data_filename("chemicals/etoh/etoh.mol2") sustiva_filename = utils.get_data_filename( "chemicals/sustiva/sustiva.mol2") with utils.enter_temp_directory( ): # Prevents creating tons of GAFF files everywhere. shutil.copy(water_filename, 'c1.mol2') shutil.copy(etoh_filename, 'c2.mol2') shutil.copy(sustiva_filename, 'c3.mol2') water_filename = 'c1.mol2' etoh_filename = 'c2.mol2' sustiva_filename = 'c3.mol2' #Randomize residue names to avoid clashes utils.randomize_mol2_residue_names( [water_filename, etoh_filename, sustiva_filename]) trj0, trj1, trj2 = md.load(water_filename), md.load( etoh_filename), md.load(sustiva_filename) trj_list = [trj0, trj1, trj2] box_filename = "./box.pdb" box_trj = packmol.pack_box(trj_list, [300, 25, 3]) box_trj.save(box_filename) gaff_mol2_filename0, frcmod_filename0 = amber.run_antechamber( "water", water_filename, charge_method=None) gaff_mol2_filename1, frcmod_filename1 = amber.run_antechamber( "etoh", etoh_filename, charge_method=None) gaff_mol2_filename2, frcmod_filename2 = amber.run_antechamber( "sustiva", sustiva_filename, charge_method=None) mol2_filenames = [ gaff_mol2_filename0, gaff_mol2_filename1, gaff_mol2_filename2 ] frcmod_filenames = [ frcmod_filename0, frcmod_filename1, frcmod_filename2 ] prmtop_filename = "./out.prmtop" inpcrd_filename = "./out.inpcrd" shutil.copy(box_filename, 'renamed.pdb') tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, 'renamed.pdb', prmtop_filename, inpcrd_filename) print(tleap_cmd) #Also do here for case of GAFF water tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename, prmtop_filename, inpcrd_filename, water_model=None) print(tleap_cmd) #Also do here for case of SPC tleap_cmd = amber.build_mixture_prmtop(mol2_filenames, frcmod_filenames, 'renamed.pdb', prmtop_filename, inpcrd_filename, water_model='SPC') print(tleap_cmd)
def run_md(molecule, solvent_name="chloroform", confId=0): """ Uses the PARSLEY forcefield to compute molecule ``molecule`` in a cubic box of solvent at STP. Details: - Particle mesh Ewald summation is used (1 nm cutoff) - Periodic boundary conditions are employed - Langevin thermostat is employed to regulate temperature - Box size is automatically scaled to the desired number of solvent molecules Args: molecule (openforcefield.topology.Molecule): desired molecule solvent_name (str): either ``chloroform`` or ``benzene``, for now confId (int): conformer ID for autogenerated molecular conformers, 0 seems fine by default Returns: Nothing, but ``.csv``, ``.hdf5``, and ``.pdb`` files are generated in the current directory. """ #### Load in the appropriate Molecule object off_solute = molecule.to_topology() omm_solute = off_solute.to_openmm() mdt_solute = mdt.Topology.from_openmm(omm_solute) #### Build solvent Molecule object solvent, density, mw = None, None, None if solvent_name == "chloroform": solvent = Molecule.from_smiles("C(Cl)(Cl)Cl") density = 1.49 mw = 119.38 elif solvent_name == "benzene": solvent = Molecule.from_smiles("c1ccccc1") density = 0.879 mw = 78.11 else: raise ValueError(f"Unknown solvent {solvent_name}!") solvent.generate_conformers() off_solvent = solvent.to_topology() omm_solvent = off_solvent.to_openmm() mdt_solvent = mdt.Topology.from_openmm(omm_solvent) #### Calculate box side length num, length = None, None if "num" in config: num = config["num"] assert isinstance(num, int), "Need an integer number of solvent molecules." assert num > 0, "Need a positive number of solvent molecules." length = (1.6606 * num * mw / density)**( 1 / 3) # 1.6606 = 10^24 (Å**3 per mL) divided by Avogadro's number elif "length" in config: length = config["length"] assert isinstance(length, (int, float)), "Need a numeric side length." assert length > 0, "Need a positive length." num = (length**3) * density / (mw * 1.6606) num = int(num) else: raise ValueError("Need ``length`` or ``num`` in config file!") logger.info( f"{num} solvent molecules in a cube with {length:.2f} Å sides.") #### Write solvent and solute to ``.pdb`` files for PACKMOL solute_pdb = "solute.pdb" with open(solute_pdb, "w+") as f: openmm.app.pdbfile.PDBFile.writeFile(omm_solute, molecule.conformers[confId], f) solvent_pdb = "solvent.pdb" with open(solvent_pdb, "w+") as f: openmm.app.pdbfile.PDBFile.writeFile(omm_solvent, solvent.conformers[0], f) #### Use ``openmoltools`` Python wrapper for PACKMOL to fill the box appropriately mdt_trajectory = pack_box([solute_pdb, solvent_pdb], [1, num], box_size=length) #### Convert back to ``openforcefield`` omm_topology = mdt_trajectory.top.to_openmm() length = length / 10 # OpenMM uses nanometers for some stupid reason omm_topology.setPeriodicBoxVectors( ((length, 0, 0), (0, length, 0), (0, 0, length))) off_topology = Topology.from_openmm(omm_topology, [ Molecule.from_topology(off_solute), Molecule.from_topology(off_solvent) ]) logger.info(f"BOX VECTORS: {off_topology.box_vectors}") #### Set up the OpenMM system forcefield.get_parameter_handler('Electrostatics').method = 'PME' system = forcefield.create_openmm_system(off_topology) time_step = config["time_step"] * unit.femtoseconds temperature = config["temperature"] * unit.kelvin friction = 1 / unit.picosecond integrator = openmm.LangevinIntegrator(temperature, friction, time_step) #### Set up the simulation simulation = openmm.app.Simulation(omm_topology, system, integrator) logger.info(f"Simulation object created.") simulation.context.setPositions(mdt_trajectory.openmm_positions(0)) logger.info(f"Positions loaded.") # pdb_reporter = openmm.app.PDBReporter('trj.pdb', config["pdb_freq"]) hdf5_reporter = mdt.reporters.HDF5Reporter('trj.hdf5', config["hdf5_freq"]) state_data_reporter = openmm.app.StateDataReporter("data.csv", config["data_freq"], step=True, potentialEnergy=True, temperature=True, density=True) # simulation.reporters.append(pdb_reporter) simulation.reporters.append(hdf5_reporter) simulation.reporters.append(state_data_reporter) logger.info("Using Platform: " + simulation.context.getPlatform().getName()) #### Clean up ``.pdb`` files os.remove(solute_pdb) os.remove(solvent_pdb) logger.info("Minimizing...") simulation.minimizeEnergy(maxIterations=25) logger.info("Running...") w_start = time.time() p_start = time.process_time() simulation.step(config["num_steps"]) w_end = time.time() p_end = time.process_time() logger.info( f"Elapsed time {w_end-w_start:.2f} s (CPU: {p_end-p_start:.2f} s)") logger.info("Done")