def test_debug_ffxml(self): """Test that debug ffxml file is created when requested""" with tempfile.TemporaryDirectory() as tmpdirname: debug_ffxml_filename = os.path.join(tmpdirname, 'molecule.ffxml') cache = os.path.join(tmpdirname, 'db.json') # Create a generator that only knows about one molecule molecule = self.molecules[0] generator = self.TEMPLATE_GENERATOR(molecules=molecule, cache=cache) # Create a ForceField from simtk.openmm.app import ForceField forcefield = ForceField() # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Ensure no file is created from simtk.openmm.app import NoCutoff openmm_topology = molecule.to_topology().to_openmm() system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) assert not os.path.exists(debug_ffxml_filename) # Enable debug file output creation forcefield = ForceField() forcefield.registerTemplateGenerator(generator.generator) generator.debug_ffxml_filename = debug_ffxml_filename # Ensure that an ffxml file is created system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) assert os.path.exists(debug_ffxml_filename) # Ensure we can use that file to create a new force field forcefield_from_ffxml = ForceField() if hasattr(generator, 'gaff_xml_filename'): forcefield_from_ffxml.loadFile(generator.gaff_xml_filename) forcefield_from_ffxml.loadFile(debug_ffxml_filename) system2 = forcefield_from_ffxml.createSystem(openmm_topology, nonbondedMethod=NoCutoff) # TODO: Test that systems are equivalent assert system.getNumParticles() == system2.getNumParticles()
def test_parameterize(self): """Test parameterizing molecules with template generator for all supported force fields""" # Test all supported small molecule force fields for small_molecule_forcefield in self.TEMPLATE_GENERATOR.INSTALLED_FORCEFIELDS: print(f'Testing {small_molecule_forcefield}') # Create a generator that knows about a few molecules # TODO: Should the generator also load the appropriate force field files into the ForceField object? generator = self.TEMPLATE_GENERATOR(molecules=self.molecules, forcefield=small_molecule_forcefield) # Check that we have loaded the right force field assert generator.forcefield == small_molecule_forcefield # Create a ForceField with the appropriate small molecule force field from simtk.openmm.app import ForceField forcefield = ForceField() # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Parameterize some molecules from simtk.openmm.app import NoCutoff from openmmforcefields.utils import Timer for molecule in self.molecules: openmm_topology = molecule.to_topology().to_openmm() with Timer() as t1: system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) assert system.getNumParticles() == molecule.n_atoms # Molecule should now be cached with Timer() as t2: system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) assert system.getNumParticles() == molecule.n_atoms assert (t2.interval() < t1.interval())
def test_cache(self): """Test template generator cache capability""" from simtk.openmm.app import ForceField, NoCutoff with tempfile.TemporaryDirectory() as tmpdirname: # Create a generator that also has a database cache cache = os.path.join(tmpdirname, 'db.json') generator = self.TEMPLATE_GENERATOR(molecules=self.molecules, cache=cache) # Create a ForceField forcefield = ForceField() # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Parameterize the molecules for molecule in self.molecules: openmm_topology = molecule.to_topology().to_openmm() forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) # Check database contents def check_cache(generator, n_expected): """ Check database contains number of expected records Parameters ---------- generator : SmallMoleculeTemplateGenerator The generator whose cache should be examined n_expected : int Number of expected records """ from tinydb import TinyDB db = TinyDB(generator._cache) table = db.table(generator._database_table_name) db_entries = table.all() db.close() n_entries = len(db_entries) assert (n_entries == n_expected), \ "Expected {} entries but database has {}\n db contents: {}".format(n_expected, n_entries, db_entries) check_cache(generator, len(self.molecules)) # Clean up, forcing closure of database del forcefield, generator # Create a generator that also uses the database cache but has no molecules print('Creating new generator with just cache...') generator = self.TEMPLATE_GENERATOR(cache=cache) # Check database still contains the molecules we expect check_cache(generator, len(self.molecules)) # Create a ForceField forcefield = ForceField() # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Parameterize the molecules; this should succeed for molecule in self.molecules: openmm_topology = molecule.to_topology().to_openmm() forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff)
def _prep_sim(self, coords, external_forces=[]): try: from simtk.openmm import Platform, LangevinIntegrator, Vec3 from simtk.openmm.app import Modeller, ForceField, \ CutoffNonPeriodic, PME, Simulation, HBonds from simtk.unit import angstrom, nanometers, picosecond, \ kelvin, Quantity, molar except ImportError: raise ImportError( 'Please install PDBFixer and OpenMM in order to use ClustENM.') positions = Quantity([Vec3(*xyz) for xyz in coords], angstrom) modeller = Modeller(self._topology, positions) if self._sol == 'imp': forcefield = ForceField(*self._force_field) system = forcefield.createSystem(modeller.topology, nonbondedMethod=CutoffNonPeriodic, nonbondedCutoff=1.0 * nanometers, constraints=HBonds) if self._sol == 'exp': forcefield = ForceField(*self._force_field) modeller.addSolvent(forcefield, padding=self._padding * nanometers, ionicStrength=self._ionicStrength * molar) system = forcefield.createSystem(modeller.topology, nonbondedMethod=PME, nonbondedCutoff=1.0 * nanometers, constraints=HBonds) for force in external_forces: system.addForce(force) integrator = LangevinIntegrator(self._temp * kelvin, 1 / picosecond, 0.002 * picosecond) # precision could be mixed, but single is okay. platform = self._platform if self._platform is None else Platform.getPlatformByName( self._platform) properties = None if self._platform is None: properties = {'Precision': 'single'} elif self._platform in ['CUDA', 'OpenCL']: properties = {'Precision': 'single'} simulation = Simulation(modeller.topology, system, integrator, platform, properties) simulation.context.setPositions(modeller.positions) return simulation
def test_jacs_ligands(self): """Use template generator to parameterize the Schrodinger JACS set of ligands""" from simtk.openmm.app import ForceField, NoCutoff jacs_systems = { #'bace' : { 'prefix' : 'Bace' }, #'cdk2' : { 'prefix' : 'CDK2' }, 'jnk1' : { 'prefix' : 'Jnk1' }, 'mcl1' : { 'prefix' : 'MCL1' }, #'p38' : { 'prefix' : 'p38' }, 'ptp1b' : { 'prefix' : 'PTP1B' }, 'thrombin' : { 'prefix' : 'Thrombin' }, #'tyk2' : { 'prefix' : 'Tyk2' }, } for system_name in jacs_systems: prefix = jacs_systems[system_name]['prefix'] # Load molecules ligand_sdf_filename = get_data_filename(os.path.join('perses_jacs_systems', system_name, prefix + '_ligands.sdf')) print(f'Reading molecules from {ligand_sdf_filename} ...') from openforcefield.topology import Molecule molecules = Molecule.from_file(ligand_sdf_filename, allow_undefined_stereo=True) # Ensure this is a list try: nmolecules = len(molecules) except TypeError: molecules = [molecules] print(f'Read {len(molecules)} molecules from {ligand_sdf_filename}') #molecules = self.filter_molecules(molecules) MAX_MOLECULES = len(molecules) if 'TRAVIS' in os.environ: MAX_MOLECULES = 3 molecules = molecules[:MAX_MOLECULES] print(f'{len(molecules)} molecules remain after filtering') # Create template generator with local cache cache = os.path.join(get_data_filename(os.path.join('perses_jacs_systems', system_name)), 'cache.json') generator = self.TEMPLATE_GENERATOR(molecules=molecules, cache=cache) # Create a ForceField forcefield = ForceField() # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Parameterize all molecules print(f'Caching all molecules for {system_name} at {cache} ...') n_success = 0 n_failure = 0 for molecule in molecules: openmm_topology = molecule.to_topology().to_openmm() try: forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) n_success += 1 except Exception as e: n_failure += 1 print(e) print(f'{n_failure}/{n_success+n_failure} ligands failed to parameterize for {system_name}')
def test_gaffResidueTemplateGenerator(): """ Test the GAFF residue template generator. """ # # Test where we generate parameters for only a ligand. # # Load the PDB file. from simtk.openmm.app import PDBFile pdb_filename = utils.get_data_filename("chemicals/imatinib/imatinib.pdb") pdb = PDBFile(pdb_filename) # Create a ForceField object. gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") forcefield = ForceField(gaff_xml_filename) # Add the residue template generator. from openmoltools.forcefield_generators import gaffTemplateGenerator forcefield.registerTemplateGenerator(gaffTemplateGenerator) # Parameterize system. system = forcefield.createSystem(pdb.topology, nonbondedMethod=NoCutoff) # Check potential is finite. check_potential_is_finite(system, pdb.positions) # Check energy matches prmtop route. check_energy_components_vs_prmtop( prmtop=utils.get_data_filename("chemicals/imatinib/imatinib.prmtop"), inpcrd=utils.get_data_filename("chemicals/imatinib/imatinib.inpcrd"), system=system, ) # # Test where we generate parameters for only a ligand in a protein. # # Load the PDB file. from simtk.openmm.app import PDBFile pdb_filename = utils.get_data_filename("chemicals/proteins/T4-lysozyme-L99A-p-xylene-implicit.pdb") pdb = PDBFile(pdb_filename) # Create a ForceField object. gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") forcefield = ForceField("amber99sb.xml", gaff_xml_filename) # Add the residue template generator. from openmoltools.forcefield_generators import gaffTemplateGenerator forcefield.registerTemplateGenerator(gaffTemplateGenerator) # Parameterize system. system = forcefield.createSystem(pdb.topology, nonbondedMethod=NoCutoff) # Check potential is finite. check_potential_is_finite(system, pdb.positions)
def test_generateResidueTemplate(): """ Test GAFF residue template generation from OEMol molecules. """ from openeye import oechem, oeiupac from pkg_resources import resource_filename gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") # Test independent ForceField instances. for molecule_name in IUPAC_molecule_names: mol = createOEMolFromIUPAC(molecule_name) # Generate an ffxml residue template. from openmoltools.forcefield_generators import generateResidueTemplate [template, ffxml] = generateResidueTemplate(mol) # Create a ForceField object. forcefield = ForceField(gaff_xml_filename) # Add the additional parameters and template to the forcefield. forcefield.registerResidueTemplate(template) forcefield.loadFile(StringIO(ffxml)) # Create a Topology from the molecule. from openmoltools.forcefield_generators import generateTopologyFromOEMol topology = generateTopologyFromOEMol(mol) # Parameterize system. system = forcefield.createSystem(topology, nonbondedMethod=NoCutoff) # Check potential is finite. positions = extractPositionsFromOEMOL(mol) check_potential_is_finite(system, positions) # Test adding multiple molecules to a single ForceField instance. forcefield = ForceField(gaff_xml_filename) for molecule_name in IUPAC_molecule_names: mol = createOEMolFromIUPAC(molecule_name) # Generate an ffxml residue template. from openmoltools.forcefield_generators import generateResidueTemplate [template, ffxml] = generateResidueTemplate(mol) # Add the additional parameters and template to the forcefield. forcefield.registerResidueTemplate(template) forcefield.loadFile(StringIO(ffxml)) # Create a Topology from the molecule. from openmoltools.forcefield_generators import generateTopologyFromOEMol topology = generateTopologyFromOEMol(mol) # Parameterize system. system = forcefield.createSystem(topology, nonbondedMethod=NoCutoff) # Check potential is finite. positions = extractPositionsFromOEMOL(mol) check_potential_is_finite(system, positions)
def test_xtc_reporter_append(tmpdir, get_fn): pdb = PDBFile(get_fn('native.pdb')) forcefield = ForceField('amber99sbildn.xml', 'amber99_obc.xml') # NO PERIODIC BOUNDARY CONDITIONS system = forcefield.createSystem(pdb.topology, nonbondedMethod=CutoffNonPeriodic, nonbondedCutoff=1.0 * nanometers, constraints=HBonds, rigidWater=True) integrator = LangevinIntegrator(300 * kelvin, 1.0 / picoseconds, 2.0 * femtoseconds) integrator.setConstraintTolerance(0.00001) platform = Platform.getPlatformByName('Reference') simulation = Simulation(pdb.topology, system, integrator, platform) simulation.context.setPositions(pdb.positions) simulation.context.setVelocitiesToTemperature(300 * kelvin) tmpdir = str(tmpdir) xtcfile = os.path.join(tmpdir, 'traj.xtc') xtcfile_cp = os.path.join(tmpdir, 'traj_cp.xtc') checkpoint = os.path.join(tmpdir, 'checkpoint.chk') reporter = XTCReporter(xtcfile, 2) simulation.reporters.append(reporter) simulation.reporters.append(CheckpointReporter(checkpoint, 10)) simulation.step(10) reporter.close() shutil.copyfile(xtcfile, xtcfile_cp) system = forcefield.createSystem(pdb.topology, nonbondedMethod=CutoffNonPeriodic, nonbondedCutoff=1.0 * nanometers, constraints=HBonds, rigidWater=True) integrator = LangevinIntegrator(300 * kelvin, 1.0 / picoseconds, 2.0 * femtoseconds) integrator.setConstraintTolerance(0.00001) platform = Platform.getPlatformByName('Reference') simulation = Simulation(pdb.topology, system, integrator, platform) simulation.loadCheckpoint(checkpoint) reporter = XTCReporter(xtcfile, 2, append=True) simulation.reporters.append(reporter) simulation.step(10) reporter.close() xtc_traj = md.load(xtcfile, top=get_fn('native.pdb')) xtc_traj_cp = md.load(xtcfile_cp, top=get_fn('native.pdb')) eq(xtc_traj.xyz[:5], xtc_traj_cp.xyz) eq(xtc_traj.n_frames, 10) eq(xtc_traj_cp.n_frames, 5) eq(xtc_traj.time[:5], xtc_traj_cp.time)
def test_gaffResidueTemplateGenerator(): """ Test the GAFF residue template generator. """ # # Test where we generate parameters for only a ligand. # # Load the PDB file. from simtk.openmm.app import PDBFile pdb_filename = utils.get_data_filename("chemicals/imatinib/imatinib.pdb") pdb = PDBFile(pdb_filename) # Create a ForceField object. gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") forcefield = ForceField(gaff_xml_filename) # Add the residue template generator. from openmoltools.forcefield_generators import gaffTemplateGenerator forcefield.registerTemplateGenerator(gaffTemplateGenerator) # Parameterize system. system = forcefield.createSystem(pdb.topology, nonbondedMethod=NoCutoff) # Check potential is finite. check_potential_is_finite(system, pdb.positions) # Check energy matches prmtop route. check_energy_components_vs_prmtop( prmtop=utils.get_data_filename('chemicals/imatinib/imatinib.prmtop'), inpcrd=utils.get_data_filename('chemicals/imatinib/imatinib.inpcrd'), system=system) # # Test where we generate parameters for only a ligand in a protein. # # Load the PDB file. from simtk.openmm.app import PDBFile pdb_filename = utils.get_data_filename( "chemicals/proteins/T4-lysozyme-L99A-p-xylene-implicit.pdb") pdb = PDBFile(pdb_filename) # Create a ForceField object. gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") forcefield = ForceField('amber99sb.xml', gaff_xml_filename) # Add the residue template generator. from openmoltools.forcefield_generators import gaffTemplateGenerator forcefield.registerTemplateGenerator(gaffTemplateGenerator) # Parameterize system. system = forcefield.createSystem(pdb.topology, nonbondedMethod=NoCutoff) # Check potential is finite. check_potential_is_finite(system, pdb.positions)
def test_charge(self): """Test that charges are nonzero after charging if the molecule does not contain user charges""" # Create a generator that does not know about any molecules generator = self.TEMPLATE_GENERATOR() # Create a ForceField from simtk.openmm.app import ForceField forcefield = ForceField() # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Check that parameterizing a molecule using user-provided charges produces expected charges import numpy as np from simtk import unit molecule = self.molecules[0] # Ensure partial charges are initially zero assert np.all(molecule.partial_charges / unit.elementary_charge == 0) # Add the molecule generator.add_molecules(molecule) # Create the System from simtk.openmm.app import NoCutoff openmm_topology = molecule.to_topology().to_openmm() system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) # Ensure charges are no longer zero assert not np.all( self.charges_from_system(system) == 0), "System has zero charges despite molecule not being charged"
def test_porin_membrane_system(): """Test the addition of a ligand to a solvated porin""" # pdb file corresponding to a solvated porin pdb = PDBFile( os.path.join(os.path.dirname(__file__), '../data/porin/solvated-porin.pdb')) modeller = app.Modeller(pdb.topology, pdb.positions) forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') platform = mm.Platform.getPlatformByName('CPU') modeller.addHydrogens(forcefield=forcefield) # rigidWater False is required for ParMed to access water paramters system_md = forcefield.createSystem(modeller.topology, nonbondedMethod=app.PME, rigidWater=False, nonbondedCutoff=1 * unit.nanometer) ligand_system = PorinMembraneSystem('comp7', system_md, modeller.topology, modeller.positions, platform, tolerance=1 * unit.kilojoule / unit.mole, max_iterations=200) integrator = mm.LangevinIntegrator(300 * unit.kelvin, 1.0 / unit.picoseconds, 2 * unit.femtosecond) simulation = app.Simulation(ligand_system.structure.topology, ligand_system.system, integrator, platform) simulation.context.setPositions(ligand_system.structure.positions) state = simulation.context.getState(getEnergy=True) pe = state.getPotentialEnergy()._value assert pe < 0.0
def test_membraneModeller(): # pdb file containing a solvated single lipid molecule pdb = PDBFile('solvated-lipid.pdb') modeller = Modeller(pdb.topology,pdb.positions) modeller.modifyTopology() forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') modeller.addHydrogens(forcefield=forcefield) system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.PME, rigidWater=True, nonbondedCutoff=1*unit.nanometer) integrator = mm.VerletIntegrator(0.5*unit.femtoseconds) platform = mm.Platform.getPlatformByName('Reference') simulation = app.Simulation(modeller.topology, system, integrator, platform) simulation.context.setPositions(modeller.positions) simulation.context.setVelocitiesToTemperature(300*unit.kelvin) # Minimize the system after adding hydrogens tolerance = 0.1*unit.kilojoules_per_mole/unit.angstroms simulation.minimizeEnergy(tolerance=tolerance,maxIterations=200) simulation.reporters.append(app.StateDataReporter('relax-hydrogens.log', 1000, step=True, potentialEnergy=True)) simulation.step(1000)
def imatinib_timing(): print("Loading imatinib...") # Load the PDB file. from simtk.openmm.app import PDBFile pdb_filename = utils.get_data_filename("chemicals/imatinib/imatinib.pdb") pdb = PDBFile(pdb_filename) # Create a ForceField object. gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") forcefield = ForceField(gaff_xml_filename) # Add the residue template generator. from openmoltools.forcefield_generators import gaffTemplateGenerator forcefield.registerTemplateGenerator(gaffTemplateGenerator) # Parameterize system. system = forcefield.createSystem(pdb.topology, nonbondedMethod=NoCutoff) integrator = openmm.LangevinIntegrator(300 * unit.kelvin, 5.0 / unit.picoseconds, 1.0 * unit.femtoseconds) # Create Context context = openmm.Context(system, integrator) context.setPositions(pdb.positions) integrator.step(100) import time nsteps = 10000000 initial_time = time.time() integrator.step(nsteps) state = context.getState().getPeriodicBoxVectors() # force dynamics final_time = time.time() elapsed_time = final_time / initial_time time_per_step = elapsed_time / float(nsteps) print('time per force evaluation is %.3f us' % (time_per_step * 1e6))
def test_generate_ffxml_from_molecules(): """ Test generation of single ffxml file from a list of molecules """ # Create a test set of molecules. molecules = [createOEMolFromIUPAC(name) for name in IUPAC_molecule_names] # Create an ffxml file. from openmoltools.forcefield_generators import generateForceFieldFromMolecules ffxml = generateForceFieldFromMolecules(molecules) # Create a ForceField. gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") forcefield = ForceField(gaff_xml_filename) try: forcefield.loadFile(StringIO(ffxml)) except Exception as e: msg = str(e) msg += "ffxml contents:\n" for (index, line) in enumerate(ffxml.split("\n")): msg += "line %8d : %s\n" % (index, line) raise Exception(msg) # Parameterize the molecules. from openmoltools.forcefield_generators import generateTopologyFromOEMol for molecule in molecules: # Create topology from molecule. topology = generateTopologyFromOEMol(molecule) # Create system with forcefield. system = forcefield.createSystem(topology) # Check potential is finite. positions = extractPositionsFromOEMOL(molecule) check_potential_is_finite(system, positions)
def test_charge_from_molecules(self): """Test that user-specified partial charges are used if requested""" # Create a generator that does not know about any molecules generator = self.TEMPLATE_GENERATOR() # Create a ForceField from simtk.openmm.app import ForceField forcefield = ForceField() # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Check that parameterizing a molecule using user-provided charges produces expected charges import numpy as np from simtk import unit molecule = self.molecules[0] charges = np.random.random([molecule.n_particles]) charges += (molecule.total_charge - charges.sum()) / molecule.n_particles molecule.partial_charges = unit.Quantity(charges, unit.elementary_charge) assert not np.all(molecule.partial_charges / unit.elementary_charge == 0) # Add the molecule generator.add_molecules(molecule) # Create the System from simtk.openmm.app import NoCutoff openmm_topology = molecule.to_topology().to_openmm() system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) assert self.charges_are_equal(system, molecule)
def imatinib_timing(): print("Loading imatinib...") # Load the PDB file. from simtk.openmm.app import PDBFile pdb_filename = utils.get_data_filename("chemicals/imatinib/imatinib.pdb") pdb = PDBFile(pdb_filename) # Create a ForceField object. gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") forcefield = ForceField(gaff_xml_filename) # Add the residue template generator. from openmoltools.forcefield_generators import gaffTemplateGenerator forcefield.registerTemplateGenerator(gaffTemplateGenerator) # Parameterize system. system = forcefield.createSystem(pdb.topology, nonbondedMethod=NoCutoff) integrator = openmm.LangevinIntegrator(300 * unit.kelvin, 5.0 / unit.picoseconds, 1.0 * unit.femtoseconds) # Create Context context = openmm.Context(system, integrator) context.setPositions(pdb.positions) integrator.step(100) import time nsteps = 10000000 initial_time = time.time() integrator.step(nsteps) state = context.getState().getPeriodicBoxVectors() # force dynamics final_time = time.time() elapsed_time = final_time / initial_time time_per_step = elapsed_time / float(nsteps) print('time per force evaluation is %.3f us' % (time_per_step*1e6))
def test_membrane_modeller(): """Test the addition of hydrogens to a solvated DPPC molecule""" # pdb file corresponding to a solvated lipid molecule pdb = PDBFile(os.path.join(os.path.dirname(__file__), '../data/dppc/solvated-dppc.pdb')) modeller = MembraneModeller(pdb.topology,pdb.positions) modeller.modify_topology() forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') modeller.addHydrogens(forcefield=forcefield) system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.PME, rigidWater=True, nonbondedCutoff=1*unit.nanometer) integrator = mm.VerletIntegrator(0.5*unit.femtoseconds) platform = mm.Platform.getPlatformByName('Reference') simulation = app.Simulation(modeller.topology, system, integrator, platform) simulation.context.setPositions(modeller.positions) simulation.context.setVelocitiesToTemperature(300*unit.kelvin) # Minimize the system after adding hydrogens simulation.minimizeEnergy(maxIterations=200) # Run a few MD steps to check the system has no overlaps simulation.step(1000) state = simulation.context.getState(getEnergy=True) pe = state.getPotentialEnergy()._value assert pe < 0.0
def test_generate_ffxml_from_molecules(): """ Test generation of single ffxml file from a list of molecules """ # Create a test set of molecules. molecules = [createOEMolFromIUPAC(name) for name in IUPAC_molecule_names] # Create an ffxml file. from openmoltools.forcefield_generators import generateForceFieldFromMolecules ffxml = generateForceFieldFromMolecules(molecules) # Create a ForceField. gaff_xml_filename = utils.get_data_filename("parameters/gaff.xml") forcefield = ForceField(gaff_xml_filename) try: forcefield.loadFile(StringIO(ffxml)) except Exception as e: msg = str(e) msg += "ffxml contents:\n" for (index, line) in enumerate(ffxml.split('\n')): msg += 'line %8d : %s\n' % (index, line) raise Exception(msg) # Parameterize the molecules. from openmoltools.forcefield_generators import generateTopologyFromOEMol for molecule in molecules: # Create topology from molecule. topology = generateTopologyFromOEMol(molecule) # Create system with forcefield. system = forcefield.createSystem(topology) # Check potential is finite. positions = extractPositionsFromOEMOL(molecule) check_potential_is_finite(system, positions)
def test_add_molecules(self): """Test that molecules can be added to template generator after its creation""" # Create a generator that does not know about any molecules generator = self.TEMPLATE_GENERATOR() # Create a ForceField from simtk.openmm.app import ForceField forcefield = ForceField() # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Check that parameterizing a molecule fails molecule = self.molecules[0] from simtk.openmm.app import NoCutoff try: # This should fail with an exception openmm_topology = molecule.to_topology().to_openmm() system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) except ValueError as e: # Exception 'No template found...' is expected assert str(e).startswith('No template found') # Now add the molecule to the generator and ensure parameterization passes generator.add_molecules(molecule) openmm_topology = molecule.to_topology().to_openmm() try: system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) except Exception as e: print(forcefield._atomTypes.keys()) from simtk.openmm.app import PDBFile PDBFile.writeFile(openmm_topology, molecule.conformers[0]) raise e assert system.getNumParticles() == molecule.n_atoms # Add multiple molecules, including repeats generator.add_molecules(self.molecules) # Ensure all molecules can be parameterized for molecule in self.molecules: openmm_topology = molecule.to_topology().to_openmm() system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) assert system.getNumParticles() == molecule.n_atoms
def createSystemFromIUPAC(iupac_name): """ Create an openmm system out of an oemol Parameters ---------- iupac_name : str IUPAC name Returns ------- molecule : openeye.OEMol OEMol molecule system : openmm.System object OpenMM system positions : [n,3] np.array of floats Positions topology : openmm.app.Topology object Topology """ from perses.utils.data import get_data_filename from perses.utils.openeye import extractPositionsFromOEMol # Create OEMol molecule = iupac_to_oemol(iupac_name) # Generate a topology. from openmoltools.forcefield_generators import generateTopologyFromOEMol topology = generateTopologyFromOEMol(molecule) # Initialize a forcefield with GAFF. # TODO: Fix path for `gaff.xml` since it is not yet distributed with OpenMM from simtk.openmm.app import ForceField gaff_xml_filename = get_data_filename('data/gaff.xml') forcefield = ForceField(gaff_xml_filename) # Generate template and parameters. from openmoltools.forcefield_generators import generateResidueTemplate [template, ffxml] = generateResidueTemplate(molecule) # Register the template. forcefield.registerResidueTemplate(template) # Add the parameters. forcefield.loadFile(StringIO(ffxml)) # Create the system. system = forcefield.createSystem(topology, removeCMMotion=False) # Extract positions positions = extractPositionsFromOEMol(molecule) return (molecule, system, positions, topology)
def createSystemFromIUPAC(iupac_name): """ Create an openmm system out of an oemol Parameters ---------- iupac_name : str IUPAC name Returns ------- molecule : openeye.OEMol OEMol molecule system : openmm.System object OpenMM system positions : [n,3] np.array of floats Positions topology : openmm.app.Topology object Topology """ # Create OEMol molecule = createOEMolFromIUPAC(iupac_name) # Generate a topology. from openmoltools.forcefield_generators import generateTopologyFromOEMol topology = generateTopologyFromOEMol(molecule) # Initialize a forcefield with GAFF. # TODO: Fix path for `gaff.xml` since it is not yet distributed with OpenMM from simtk.openmm.app import ForceField gaff_xml_filename = get_data_filename('data/gaff.xml') forcefield = ForceField(gaff_xml_filename) # Generate template and parameters. from openmoltools.forcefield_generators import generateResidueTemplate [template, ffxml] = generateResidueTemplate(molecule) # Register the template. forcefield.registerResidueTemplate(template) # Add the parameters. forcefield.loadFile(StringIO(ffxml)) # Create the system. system = forcefield.createSystem(topology) # Extract positions positions = extractPositionsFromOEMOL(molecule) return (molecule, system, positions, topology)
def calculate_fragment_energetics(frag_no=1): """ * Create an OpenMM system with a fragment. * Calculate the energy of the system and print. :param frag_no: The number of the fragment being analysed (used to access files). """ os.chdir(f'group2/frag{frag_no}') # Necessary due to size of calculation sys.setrecursionlimit(15000) pdb = PDBFile(f'QUBE_pro_frag{frag_no}.pdb') forcefield = ForceField(f'QUBE_pro_frag{frag_no}_plus.xml') system = forcefield.createSystem( pdb.topology, nonbondedMethod=NoCutoff, ) system = apply_opls_combo(system) with open(f'QUBE_pro_frag{frag_no}_out.xml', 'w') as outfile: serialized_system = XmlSerializer.serialize(system) outfile.write(serialized_system) # Create the integrator to do Langevin dynamics integrator = LangevinIntegrator( 298.15 * unit.kelvin, # Temperature of heat bath 1.0 / unit.picoseconds, # Friction coefficient 2.0 * unit.femtoseconds, # Time step ) platform = Platform.getPlatformByName('CPU') simulation = Simulation(pdb.topology, system, integrator, platform) simulation.context.setPositions(pdb.positions) print('energy from openmm library') print(simulation.context.getState(getEnergy=True).getPotentialEnergy()) structure = parmed.load_file(f'QUBE_pro_frag{frag_no}.pdb') energy_comps = parmed.openmm.energy_decomposition_system(structure, system) total_energy = 0.0 for comp in energy_comps: total_energy += comp[1] print(*comp) print(f'Total energy {total_energy: 6.6f}')
def test_multiple_registration(self): """Test registering the template generator with multiple force fields""" generator = self.TEMPLATE_GENERATOR(molecules=self.molecules) from simtk.openmm.app import ForceField NUM_FORCEFIELDS = 2 # number of force fields to test forcefields = list() for index in range(NUM_FORCEFIELDS): forcefield = ForceField() forcefield.registerTemplateGenerator(generator.generator) forcefields.append(forcefield) # Parameterize a molecule in each force field instance molecule = self.molecules[0] openmm_topology = molecule.to_topology().to_openmm() from simtk.openmm.app import NoCutoff for forcefield in forcefields: system = forcefield.createSystem(openmm_topology, nonbondedMethod=NoCutoff) assert system.getNumParticles() == molecule.n_atoms
def setup(args: ListOfArgs) -> Tuple[PDBFile, int, Simulation]: print("Initialization...") if args.SIM_RANDOM_SEED == 0: random_seed = np.random.randint(2147483647) else: random_seed = args.SIM_RANDOM_SEED print(f" Loading initial structure: {args.INITIAL_STRUCTURE_PATH}") pdb = PDBFile(args.INITIAL_STRUCTURE_PATH) print(f" Loading forcefield file: {args.FORCEFIELD_PATH}") forcefield = ForceField(args.FORCEFIELD_PATH) print(" Building system...") system = forcefield.createSystem(pdb.topology) add_forces_to_system(system, args) integrator = get_integrator(random_seed, args) print(" Setting up simulation...") simulation = Simulation(pdb.topology, system, integrator) simulation.context.setPositions(pdb.positions) return pdb, random_seed, simulation
model='tip3p', positiveIon='Na+', negativeIon='Cl-', ionicStrength=0 * unit.molar) print("Done adding solvent.") PDBxFile.writeFile(molecule.topology, molecule.positions, open(f'{pdbid}_chain{chain}.pdbx', 'w'), keepIds=True) PDBFile.writeFile(molecule.topology, molecule.positions, open(f'{pdbid}_chain{chain}_solvated.pdb', 'w'), keepIds=True) print("Done outputing pdbx and solvated pdb.") system = forcefield.createSystem(molecule.topology, nonbondedMethod=PME, rigidWater=True, nonbondedCutoff=1 * unit.nanometer) # specify the rest of the context for minimization integrator = mm.VerletIntegrator(0.5 * unit.femtoseconds) print("Done specifying integrator.") platform = mm.Platform.getPlatformByName('CUDA') print("Done specifying platform.") platform.setPropertyDefaultValue('Precision', 'mixed') print("Done setting the precision to mixed.") minimize = Simulation(molecule.topology, system, integrator, platform) print("Done specifying simulation.") minimize.context.setPositions(molecule.positions) print("Done recording a context for positions.") minimize.context.setVelocitiesToTemperature(310.15 * unit.kelvin) print("Done assigning velocities.")
2.91151942, 2.917109761, 2.922520161, 2.927750286, 2.932799813, 2.937668432, 2.942355841, 2.946861752, 2.951185887, 2.955327978, 2.959287772, 2.963065022, 2.966659496, 2.970070973, 2.973299242, 2.976344104, 2.979205371, 2.981882866, 2.984376425, 2.986685894, 2.988811129, 2.990752001, 2.992508389, 2.994080185, 2.995467292, 2.996669625, 2.997687109, 2.998519681, 2.999167291, 2.999629897, 2.999907473, 3 ]]) pdb = PDBFile('initial_structure.pdb') forcefield = ForceField('polymer_ff.xml') system = forcefield.createSystem(pdb.topology, nonbondedCutoff=1 * u.nanometer) integrator = mm.LangevinIntegrator(100 * u.kelvin, 0.2, 1 * u.femtoseconds) # Distance constraint for i in range(system.getNumParticles() - 1): system.addConstraint(i, i + 1, 0.1 * u.nanometer) # Pinning ends with rubber pin_force = mm.CustomExternalForce("k*((x-x0)^2+(y-y0)^2+(z-z0)^2)") pin_force.addGlobalParameter("k", 50 * u.kilocalories_per_mole / u.angstroms**2) pin_force.addPerParticleParameter("x0") pin_force.addPerParticleParameter("y0") pin_force.addPerParticleParameter("z0") pin_force.addParticle(0, [15 * u.angstrom, 0 * u.angstrom, 0 * u.angstrom]) pin_force.addParticle(system.getNumParticles() - 1,
def test_reporter(tmpdir, get_fn): pdb = PDBFile(get_fn('native.pdb')) forcefield = ForceField('amber99sbildn.xml', 'amber99_obc.xml') # NO PERIODIC BOUNDARY CONDITIONS system = forcefield.createSystem(pdb.topology, nonbondedMethod=CutoffNonPeriodic, nonbondedCutoff=1.0 * nanometers, constraints=HBonds, rigidWater=True) integrator = LangevinIntegrator(300 * kelvin, 1.0 / picoseconds, 2.0 * femtoseconds) integrator.setConstraintTolerance(0.00001) platform = Platform.getPlatformByName('Reference') simulation = Simulation(pdb.topology, system, integrator, platform) simulation.context.setPositions(pdb.positions) simulation.context.setVelocitiesToTemperature(300 * kelvin) tmpdir = str(tmpdir) hdf5file = os.path.join(tmpdir, 'traj.h5') ncfile = os.path.join(tmpdir, 'traj.nc') dcdfile = os.path.join(tmpdir, 'traj.dcd') xtcfile = os.path.join(tmpdir, 'traj.xtc') reporter = HDF5Reporter(hdf5file, 2, coordinates=True, time=True, cell=True, potentialEnergy=True, kineticEnergy=True, temperature=True, velocities=True) reporter2 = NetCDFReporter(ncfile, 2, coordinates=True, time=True, cell=True) reporter3 = DCDReporter(dcdfile, 2) reporter4 = XTCReporter(xtcfile, 2) simulation.reporters.append(reporter) simulation.reporters.append(reporter2) simulation.reporters.append(reporter3) simulation.reporters.append(reporter4) simulation.step(100) reporter.close() reporter2.close() reporter3.close() reporter4.close() with HDF5TrajectoryFile(hdf5file) as f: got = f.read() eq(got.temperature.shape, (50,)) eq(got.potentialEnergy.shape, (50,)) eq(got.kineticEnergy.shape, (50,)) eq(got.coordinates.shape, (50, 22, 3)) eq(got.velocities.shape, (50, 22, 3)) eq(got.cell_lengths, None) eq(got.cell_angles, None) eq(got.time, 0.002 * 2 * (1 + np.arange(50))) assert f.topology == md.load(get_fn('native.pdb')).top with NetCDFTrajectoryFile(ncfile) as f: xyz, time, cell_lengths, cell_angles = f.read() eq(cell_lengths, None) eq(cell_angles, None) eq(time, 0.002 * 2 * (1 + np.arange(50))) hdf5_traj = md.load(hdf5file) dcd_traj = md.load(dcdfile, top=get_fn('native.pdb')) netcdf_traj = md.load(ncfile, top=get_fn('native.pdb')) xtc_traj = md.load(xtcfile, top=get_fn('native.pdb')) # we don't have to convert units here, because md.load already # handles that assert hdf5_traj.unitcell_vectors is None eq(hdf5_traj.xyz, netcdf_traj.xyz) eq(hdf5_traj.unitcell_vectors, netcdf_traj.unitcell_vectors) eq(hdf5_traj.time, netcdf_traj.time) eq(xtc_traj.time, netcdf_traj.time) eq(dcd_traj.xyz, hdf5_traj.xyz) eq(xtc_traj.xyz, dcd_traj.xyz, decimal=3)
def main(argdict): """ Main function for entry point checking. Expects a dictionary of command line arguments. """ # load configuration from logfile: with open(argdict["log"], 'r') as f: argdict = json.load(f) # load system initial configuration: pdb = pdb_file_nonstandard_bonds(argdict["pdb"]) print("--> input topology: ", end="") print(pdb.topology) # physical parameters of simulation: sim_temperature = argdict["temperature"] * kelvin sim_andersen_coupling = 1 / picosecond sim_pressure = ( (argdict["pressure"], argdict["pressure"], argdict["pressure"]) * bar) sim_scale_x = True sim_scale_y = True sim_scale_z = True # simulation control parameters: sim_timestep = argdict["timestep"] * femtoseconds # restraints parameters: sim_restr_fc = argdict["restr_fc"] * kilojoule_per_mole / nanometer**2 # create force field object: ff = ForceField(*argdict["ff"]) # build a simulation system from topology and force field: # (note that AMOEBA is intended to be run without constraints) # (note that mutualInducedtargetEpsilon defaults to 0.01 unlike what is # specified in the documentation which claims 0.00001) system = ff.createSystem( pdb.topology, nonbondedMethod=PME, nonbondedCutoff=argdict["nonbonded_cutoff"] * nanometer, vdwCutoff=argdict["vdw_cutoff"] * nanometer, ewaldErrorTolerance=argdict["ewald_error_tolerance"], polarisation=argdict["polarisation"], mutualInducedTargetEpsilon=argdict["mutual_induced_target_epsilon"], constraints=None, rigidWater=False, removeCMMotion=True # removes centre of mass motion ) # overwrite the polarisation method set at system creation; this is # necessary as openMM always sets polarisation method to "mutual" of the # target epsilon is specified at system creation; this way, target epsilon # is ignored for all but the mutual method multipole_force = [ f for f in system.getForces() if isinstance(f, AmoebaMultipoleForce) ][0] print("--> using polarisation method " + str(argdict["polarisation"])) if argdict["polarisation"] == "mutual": multipole_force.setPolarizationType(multipole_force.Mutual) if argdict["polarisation"] == "extrapolated": multipole_force.setPolarizationType(multipole_force.Extrapolated) if argdict["polarisation"] == "direct": multipole_force.setPolarizationType(multipole_force.Direct) # will use Andersen thermostat here: # (Inhibits particle dynamics somewhat, but little or no ergodicity # issues (from Gromacs documenation). However, only alternative is full # Langevin dynamics, which is even worse wrt dynamics. Bussi/v-rescale is # not available at the moment, it seems (it is available in tinker, but # without GPU acceleration)) system.addForce(AndersenThermostat(sim_temperature, sim_andersen_coupling)) # use anisotropic barostat: # (note that this corresponds to semiisotropic pressure coupling in Gromacs # if the pressure is identical for the x- and y/axes) # (note that by default this attempts an update every 25 steps) system.addForce( MonteCarloAnisotropicBarostat(sim_pressure, sim_temperature, sim_scale_x, sim_scale_y, sim_scale_z)) # prepare harmonic restraining potential: # (note that periodic distance is absolutely necessary here to prevent # system from blowing up, as otherwise periodic image position may be used # resulting in arbitrarily large forces) force = CustomExternalForce("k*periodicdistance(x, y, z, x0, y0, z0)^2") force.addGlobalParameter("k", sim_restr_fc) force.addPerParticleParameter("x0") force.addPerParticleParameter("y0") force.addPerParticleParameter("z0") # apply harmonic restraints to C-alphas: if argdict["restr"] == "capr": print("--> applying harmonic positional restraints to CA atoms") for atm in pdb.topology.atoms(): if atm.name == "CA": force.addParticle(atm.index, pdb.positions[atm.index]) elif argdict["restr"] == "hapr": sys.exit("Restraints mode " + str(argdict["restr"]) + "is not implemented.") elif argdict["restr"] == "none": print("--> applying no harmonic positional restraints to any atom") else: sys.exit("Restraints mode " + str(argdict["restr"]) + "is not implemented.") # add restraining force to system: system.addForce(force) # make special group for nonbonded forces: for f in system.getForces(): if (isinstance(f, AmoebaMultipoleForce) or isinstance(f, AmoebaVdwForce) or isinstance(f, AmoebaGeneralizedKirkwoodForce) or isinstance(f, AmoebaWcaDispersionForce)): f.setForceGroup(1) # select integrator: if argdict["integrator"] == "mts": # use multiple timestep RESPA integrator: print("--> using RESPA/MTS integrator") integrator = MTSIntegrator(sim_timestep, [(0, argdict["inner_ts_frac"]), (1, 1)]) if argdict["integrator"] == "verlet": # use Leapfrog Verlet integrator here: print("--> using Verlet integrator") integrator = VerletIntegrator(sim_timestep) # select a platform (should be CUDA, otherwise VERY slow): platform = Platform.getPlatformByName(argdict["platform"]) properties = { "CudaPrecision": argdict["precision"], "CudaDeviceIndex": "0" } # create simulation system: sim = Simulation(pdb.topology, system, integrator, platform, properties) # unit conversion factors: ang2nm = 0.1 # create MDA universe: u = mda.Universe(args.s, args.f) # selection for overall system will be needed to set OpenMM positions # accordingt to trajectory: allsystem = u.select_atoms("all") # get parameters to define cylinder around protein center of geometry: # (the cylinder spans the entire box in the z-direction) protein = u.select_atoms("protein") radius = str(args.r) z_margin = args.z_margin z_min = str(protein.bbox()[0, 2] - protein.center_of_geometry()[2] - z_margin) z_max = str(protein.bbox()[1, 2] - protein.center_of_geometry()[2] + z_margin) # select all solvent atoms, note that AMOEBA residue name is HOH: # (these must be updating, as water may move in and out of pore!) solvent = u.select_atoms("byres (resname HOH SOL) and cyzone " + radius + " " + z_max + " " + z_min + " protein", updating=True) solvent_ow = solvent.select_atoms("name O OW", updating=True) # lambda function for converting atomic dipoles to molecular dipoles: # (this only works on 1D arrays, hence use apply_along_axis if quantity is # vector-valued, e.g. positions and dipoles) def atomic2molecular_sum(arr): return np.bincount(allsystem.resindices, arr) def atomic2molecular_avg(arr): return np.bincount(allsystem.resindices, arr) / np.bincount( allsystem.resindices) # create lambda function for obtaining charges in vectorisable way: # (units are elementary_charge) get_atomic_charges = np.vectorize( lambda index: multipole_force.getMultipoleParameters(int(index))[ 0].value_in_unit(elementary_charge)) # obtain atomic charges: # (charges are static, so need this only once; units are elementary charge) atomic_charges = get_atomic_charges(allsystem.ix) # obtain start and end time as will as time step: dt = float(args.dt) t_start = float(args.b) t_end = float(args.e) # prepare results dictionary: res = { "t": [], "x": [], "y": [], "z": [], "indu_rho": [], "indu_costheta": [], "indu_cosphi": [], "perm_rho": [], "perm_costheta": [], "perm_cosphi": [], "mono_rho": [], "mono_costheta": [], "mono_cosphi": [], "total_rho": [], "total_costheta": [], "total_cosphi": [] } # loop over trajectory: for ts in u.trajectory: # skip all frames before starting frame: if ts.time < t_start: continue # only analyse relevant time frames: if round(ts.time, 4) % dt == 0: # inform user: print("analysing frame: " + str(ts.frame) + " at time: " + str(ts.time)) print("number of selected solvent molecules in this frame: " + str(solvent.n_residues)) # convert mda positions to OpenMM positions and set context: omm_positions = Quantity( [tuple(pos) for pos in list(allsystem.positions)], unit=angstrom) sim.context.setPositions(omm_positions) # calculate molecular positions (or molecular centre of geometry) by # averaging over all atomic positions within a residue: # (units are Angstrom in MDAnalysis!) molecular_positions = np.apply_along_axis( atomic2molecular_avg, 0, allsystem.positions) * ang2nm # calculate charge-weighted positions by multiplying the relative # atomic positions with the atomic charges (relative positions are # necessary to account for charged residues/molecules, where the # dipole moment is calculated relative to the center of geometry of # the residue): # (units are elementary charge * nanometer) atomic_charge_weighted_positions = ( allsystem.positions - molecular_positions[allsystem.resindices]) atomic_charge_weighted_positions *= (atomic_charges[np.newaxis].T * ang2nm) # obtain induced and permanent atomic dipoles from OpenMM: # (units are elementary charge * nm) atomic_dipoles_indu = np.array( multipole_force.getInducedDipoles(sim.context)) atomic_dipoles_perm = np.array( multipole_force.getLabFramePermanentDipoles(sim.context)) # convert atomic to molecular quantities and calculate total dipole: molecular_dipoles_indu = np.apply_along_axis( atomic2molecular_sum, 0, atomic_dipoles_indu) molecular_dipoles_perm = np.apply_along_axis( atomic2molecular_sum, 0, atomic_dipoles_perm) molecular_dipoles_mono = np.apply_along_axis( atomic2molecular_sum, 0, atomic_charge_weighted_positions) molecular_dipoles_total = (molecular_dipoles_indu + molecular_dipoles_perm + molecular_dipoles_mono) # convert to spherical coordinates: molecular_dipoles_indu = cartesian2spherical( molecular_dipoles_indu) molecular_dipoles_perm = cartesian2spherical( molecular_dipoles_perm) molecular_dipoles_mono = cartesian2spherical( molecular_dipoles_mono) molecular_dipoles_total = cartesian2spherical( molecular_dipoles_total) # insert into results dictionary: res["t"].append(np.repeat(ts.time, solvent.n_residues)) res["x"].append(molecular_positions[solvent_ow.resindices, 0]) res["y"].append(molecular_positions[solvent_ow.resindices, 1]) res["z"].append(molecular_positions[solvent_ow.resindices, 2]) res["indu_rho"].append( molecular_dipoles_indu[solvent_ow.resindices, 0]) res["indu_costheta"].append( molecular_dipoles_indu[solvent_ow.resindices, 1]) res["indu_cosphi"].append( molecular_dipoles_indu[solvent_ow.resindices, 2]) res["perm_rho"].append( molecular_dipoles_perm[solvent_ow.resindices, 0]) res["perm_costheta"].append( molecular_dipoles_perm[solvent_ow.resindices, 1]) res["perm_cosphi"].append( molecular_dipoles_perm[solvent_ow.resindices, 2]) res["mono_rho"].append( molecular_dipoles_mono[solvent_ow.resindices, 0]) res["mono_costheta"].append( molecular_dipoles_mono[solvent_ow.resindices, 1]) res["mono_cosphi"].append( molecular_dipoles_mono[solvent_ow.resindices, 2]) res["total_rho"].append( molecular_dipoles_total[solvent_ow.resindices, 0]) res["total_costheta"].append( molecular_dipoles_total[solvent_ow.resindices, 1]) res["total_cosphi"].append( molecular_dipoles_total[solvent_ow.resindices, 2]) # stop iterating through trajectory after end time: if ts.time > t_end: break # convert lists of arrays to arrays: for k in res.keys(): res[k] = np.concatenate(res[k]) # convert units of dipole magnitude to Debye: eNm2debye = 48.03205 res["indu_rho"] = eNm2debye * res["indu_rho"] res["perm_rho"] = eNm2debye * res["perm_rho"] res["mono_rho"] = eNm2debye * res["mono_rho"] res["total_rho"] = eNm2debye * res["total_rho"] # load spline curve data: with open(args.j, "r") as f: chap_data = json.load(f) # create spline curve from CHAP data: spline_curve = BSplineCurve(chap_data) # calculate s-coordinate from z-coordinate: res["s"] = spline_curve.z2s(res["z"]) # convert results to data frame: df_res = pd.DataFrame(res) # loop over various numbers of bins: df = [] for nbins in args.nbins: # create a temporary data frame: tmp = df_res # drop positional coordinates: tmp = tmp.drop(["x", "y", "z", "t"], axis=1) # bin by value of s-coordinate: tmp = tmp.groupby(pd.cut(tmp.s, nbins)) # aggregate variables: tmp = tmp.agg([np.mean, np.std, sem, np.size, np.median, qlo, qhi]).reset_index() # rename columns (combines variable name with aggregation method): tmp.columns = ["_".join(x) for x in tmp.columns.ravel()] # remove grouping key: tmp = tmp.drop("s_", axis=1) # add column wit number of bins: tmp["nbins"] = nbins # append to list of data frames: df.append(tmp) # combine list of data frames into single data frame: df = pd.concat(df) # write to JSON file: df.to_json(args.o, orient="records") # need to add newline for POSIX compliance: with open(args.o, "a") as f: f.write("\n")
class MoleculeUtil(object): """ A class for managing a molecule defined by a PDB file """ np.random.seed(20) def __init__(self, pdb_path, offset_size=2): # OpenMM init self.pdb_path = pdb_path self.pdb = PDBFile(self.pdb_path) self.forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') self.modeller = Modeller(self.pdb.topology, self.pdb.positions) # Remove any water that might be present in the PDB file self.modeller.deleteWater() # Add any hydrogens not present self.modeller.addHydrogens(self.forcefield) self.system = self.forcefield.createSystem(self.modeller.topology, nonbondedMethod=PME, nonbondedCutoff=1 * u.nanometer, constraints=HBonds) self.integrator = LangevinIntegrator(300 * u.kelvin, 1 / u.picosecond, 0.002 * u.picoseconds) self.simulation = Simulation(self.modeller.topology, self.system, self.integrator) self.pdb_positions = self.modeller.getPositions() # Initialize bond dictionary and positions for chemcoord self.cc_bonds = {} self.offset_size = offset_size self._init_pdb_bonds() self.set_cc_positions(self.pdb_positions) # Perform initial minimization, which updates self.pdb_positions min_energy, min_positions = self.run_simulation() # Reset the positions after the minimization self.set_cc_positions(self.pdb_positions) self.torsion_indices = self._get_torsion_indices() self.starting_positions = min_positions self.starting_torsions = np.array([ self.zmat.loc[self.torsion_indices[:, 0], 'dihedral'], self.zmat.loc[self.torsion_indices[:, 1], 'dihedral'] ]).T self.seed_offsets() def _add_backbone_restraint(self): # https://github.com/ParmEd/ParmEd/wiki/OpenMM-Tricks-and-Recipes#positional-restraints positions = self.modeller.getPositions() force = CustomExternalForce('k*((x-x0)^2+(y-y0)^2+(z-z0)^2)') force.addGlobalParameter( 'k', 5.0 * u.kilocalories_per_mole / u.angstroms**2) force.addPerParticleParameter('x0') force.addPerParticleParameter('y0') force.addPerParticleParameter('z0') for index, atom in enumerate(self.modeller.topology.atoms()): if atom.name in ('CA', 'C', 'N'): coord = positions[index] force.addParticle(index, coord.value_in_unit(u.nanometers)) self.restraint_force_id = self.system.addForce(force) def _remove_backbone_restraint(self): self.system.removeForce(self.restraint_force_id) def _fix_backbone(self): for index, atom in enumerate(self.modeller.topology.atoms()): if atom.name in ('CA', 'C', 'N'): self.system.setParticleMass(index, 0) def seed_offsets(self): self.offsets = np.random.choice([0, 0, -1, 1], self.starting_torsions.shape) def get_torsions(self): return np.array([ self.zmat.loc[self.torsion_indices[:, 0], 'dihedral'], self.zmat.loc[self.torsion_indices[:, 1], 'dihedral'] ]).T def set_torsions(self, new_torsions): self.zmat.safe_loc[self.torsion_indices[:, 0], 'dihedral'] = new_torsions[:, 0] self.zmat.safe_loc[self.torsion_indices[:, 1], 'dihedral'] = new_torsions[:, 1] def get_offset_torsions(self, scale_factor): """ Calculates and returns new torsion angles based on randomly generated offsets. Args: scale_factor: the relative scale of the offset relative to self.offset_size Returns: The new torsion angles """ total_offset = self.offset_size * scale_factor new_torsions = np.zeros(shape=self.starting_torsions.shape) new_torsions[:, 0] = self.starting_torsions[:, 0] + \ (self.offsets[:, 0] * total_offset) new_torsions[:, 1] = self.starting_torsions[:, 1] + \ (self.offsets[:, 1] * total_offset) return new_torsions def run_simulation(self): """ Run a simulation to calculate the current configuration's energy level. Note that the atoms will likely move somewhat during the calculation, since energy minimization is used. Returns: A tuple of the form (potential_energy, updated_positions) """ # Delete solvent that's based on previous positions cartesian = self.zmat.get_cartesian().sort_index() self.simulation.context.setPositions([ Vec3(x, y, z) for x, y, z in zip(cartesian['x'], cartesian['y'], cartesian['z']) ]) # self._add_backbone_restraint() # self._fix_backbone() self.modeller.addSolvent(self.forcefield, padding=1.0 * u.nanometer) self.simulation.minimizeEnergy(maxIterations=200) state = self.simulation.context.getState(getEnergy=True, getPositions=True) p_energy = state.getPotentialEnergy() positions = state.getPositions(asNumpy=True) # Clean up - remove solvent and backbone restraint (for next iteration) self.modeller.deleteWater() # self._remove_backbone_restraint() return p_energy, positions def _init_pdb_bonds(self): """Construct a dictionary describing the PDB's bonds for chemcoord use""" for index in range(self.modeller.topology.getNumAtoms()): self.cc_bonds[index] = set() for bond in self.modeller.topology.bonds(): self.cc_bonds[bond[0].index].add(bond[1].index) self.cc_bonds[bond[1].index].add(bond[0].index) def set_cc_positions(self, positions): """ Calculates the zmat from an OpenMM modeller Args: positions (list): A list """ cc_df = self._get_cartesian_df(positions) self.cartesian = cc.Cartesian(cc_df) self.cartesian.set_bonds(self.cc_bonds) self.cartesian._give_val_sorted_bond_dict(use_lookup=True) self.zmat = self.cartesian.get_zmat(use_lookup=True) def _get_cartesian_df(self, positions): cc_positions = np.zeros((3, self.modeller.topology.getNumAtoms())) atom_names = [] for index, atom in enumerate(self.modeller.topology.atoms()): pos = positions[index] / u.nanometer atom_names.append(atom.name) cc_positions[:, index] = pos cc_df = pd.DataFrame({ 'atom': atom_names, 'x': cc_positions[0, :], 'y': cc_positions[1, :], 'z': cc_positions[2, :] }) return cc_df def _get_torsion_indices(self): """ Calculates indices into the zmatrix which correspond to phi and psi angles. Args: zmat: the zmatrix specifying the molecule Returns: a numpy.array, with first column as phi_indices, second column as psi_indices """ phi_indices = [] psi_indices = [] for i in range(len(self.zmat.index)): b_index = self.zmat.loc[i, 'b'] a_index = self.zmat.loc[i, 'a'] d_index = self.zmat.loc[i, 'd'] # If this molecule references a magic string (origin, e_x, e_y, e_z, etc) if isinstance(b_index, str) or isinstance( a_index, str) or isinstance(d_index, str): continue # Psi angles if (self.zmat.loc[i, 'atom'] == 'N') & \ (self.zmat.loc[b_index, 'atom'] == 'CA') & \ (self.zmat.loc[a_index, 'atom'] == 'C') & \ (self.zmat.loc[d_index, 'atom'] == 'N'): psi_indices.append(i) elif (self.zmat.loc[i, 'atom'] == 'N') & \ (self.zmat.loc[b_index, 'atom'] == 'C') & \ (self.zmat.loc[a_index, 'atom'] == 'CA') & \ (self.zmat.loc[d_index, 'atom'] == 'N'): psi_indices.append(i) elif (self.zmat.loc[i, 'atom'] == 'C') & \ (self.zmat.loc[b_index, 'atom'] == 'N') & \ (self.zmat.loc[a_index, 'atom'] == 'CA') & \ (self.zmat.loc[d_index, 'atom'] == 'C'): phi_indices.append(i) elif (self.zmat.loc[i, 'atom'] == 'C') & \ (self.zmat.loc[b_index, 'atom'] == 'CA') & \ (self.zmat.loc[a_index, 'atom'] == 'N') & \ (self.zmat.loc[d_index, 'atom'] == 'C'): phi_indices.append(i) return np.array([phi_indices, psi_indices]).T
def test_reporter_subset(tmpdir, get_fn): pdb = PDBFile(get_fn('native2.pdb')) pdb.topology.setUnitCellDimensions([2, 2, 2]) forcefield = ForceField('amber99sbildn.xml', 'amber99_obc.xml') system = forcefield.createSystem(pdb.topology, nonbondedMethod=CutoffPeriodic, nonbondedCutoff=1 * nanometers, constraints=HBonds, rigidWater=True) integrator = LangevinIntegrator(300 * kelvin, 1.0 / picoseconds, 2.0 * femtoseconds) integrator.setConstraintTolerance(0.00001) platform = Platform.getPlatformByName('Reference') simulation = Simulation(pdb.topology, system, integrator, platform) simulation.context.setPositions(pdb.positions) simulation.context.setVelocitiesToTemperature(300 * kelvin) tmpdir = str(tmpdir) hdf5file = os.path.join(tmpdir, 'traj.h5') ncfile = os.path.join(tmpdir, 'traj.nc') dcdfile = os.path.join(tmpdir, 'traj.dcd') xtcfile = os.path.join(tmpdir, 'traj.xtc') atomSubset = [0, 1, 2, 4, 5] reporter = HDF5Reporter(hdf5file, 2, coordinates=True, time=True, cell=True, potentialEnergy=True, kineticEnergy=True, temperature=True, velocities=True, atomSubset=atomSubset) reporter2 = NetCDFReporter(ncfile, 2, coordinates=True, time=True, cell=True, atomSubset=atomSubset) reporter3 = DCDReporter(dcdfile, 2, atomSubset=atomSubset) reporter4 = XTCReporter(xtcfile, 2, atomSubset=atomSubset) simulation.reporters.append(reporter) simulation.reporters.append(reporter2) simulation.reporters.append(reporter3) simulation.reporters.append(reporter4) simulation.step(100) reporter.close() reporter2.close() reporter3.close() reporter4.close() t = md.load(get_fn('native.pdb')) t.restrict_atoms(atomSubset) with HDF5TrajectoryFile(hdf5file) as f: got = f.read() eq(got.temperature.shape, (50,)) eq(got.potentialEnergy.shape, (50,)) eq(got.kineticEnergy.shape, (50,)) eq(got.coordinates.shape, (50, len(atomSubset), 3)) eq(got.velocities.shape, (50, len(atomSubset), 3)) eq(got.cell_lengths, 2 * np.ones((50, 3))) eq(got.cell_angles, 90 * np.ones((50, 3))) eq(got.time, 0.002 * 2 * (1 + np.arange(50))) assert f.topology == md.load(get_fn('native.pdb'), atom_indices=atomSubset).topology with NetCDFTrajectoryFile(ncfile) as f: xyz, time, cell_lengths, cell_angles = f.read() eq(cell_lengths, 20 * np.ones((50, 3))) eq(cell_angles, 90 * np.ones((50, 3))) eq(time, 0.002 * 2 * (1 + np.arange(50))) eq(xyz.shape, (50, len(atomSubset), 3)) hdf5_traj = md.load(hdf5file) dcd_traj = md.load(dcdfile, top=hdf5_traj) netcdf_traj = md.load(ncfile, top=hdf5_traj) xtc_traj = md.load(xtcfile, top=hdf5_traj) # we don't have to convert units here, because md.load already handles that eq(hdf5_traj.xyz, netcdf_traj.xyz) eq(hdf5_traj.unitcell_vectors, netcdf_traj.unitcell_vectors) eq(hdf5_traj.time, netcdf_traj.time) eq(xtc_traj.time, netcdf_traj.time) eq(dcd_traj.xyz, hdf5_traj.xyz) eq(xtc_traj.xyz, hdf5_traj.xyz) eq(dcd_traj.unitcell_vectors, hdf5_traj.unitcell_vectors)
logging.root.setLevel(logging.DEBUG) logging.basicConfig(level=logging.DEBUG) yank.utils.config_root_logger(verbose=True, log_file_path=None) # File from MemProt Data Base pdb = PDBFile('atomistic-system.pdb') modeller = Modeller(pdb.topology, pdb.positions) modeller.changeAtomNames() forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') modeller.addHydrogens(forcefield=forcefield) PDBxFile.writeFile(modeller.topology, modeller.positions, open("atomistic-system-with-hydrogens.pdbx", 'w')) system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.PME, rigidWater=True, nonbondedCutoff=1 * unit.nanometer) integrator = mm.VerletIntegrator(0.5 * unit.femtoseconds) platform = mm.Platform.getPlatformByName('CUDA') simulation = app.Simulation(modeller.topology, system, integrator, platform) simulation.context.setPositions(modeller.positions) simulation.context.setVelocitiesToTemperature(300 * unit.kelvin) # Minimize the system after adding hydrogens to the membrane tolerance = 0.1 * unit.kilojoules_per_mole / unit.angstroms simulation.minimizeEnergy(tolerance=tolerance, maxIterations=0) simulation.reporters.append( app.StateDataReporter('relax-hydrogens.log', 1000, step=True, temperature=True, potentialEnergy=True,
def test_jacs_complexes(self): """Use template generator to parameterize the Schrodinger JACS set of complexes""" # TODO: Uncomment working systems when we have cleaned up the input files jacs_systems = { #'bace' : { 'prefix' : 'Bace' }, #'cdk2' : { 'prefix' : 'CDK2' }, #'jnk1' : { 'prefix' : 'Jnk1' }, 'mcl1' : { 'prefix' : 'MCL1' }, #'p38' : { 'prefix' : 'p38' }, #'ptp1b' : { 'prefix' : 'PTP1B' }, #'thrombin' : { 'prefix' : 'Thrombin' }, #'tyk2' : { 'prefix' : 'Tyk2' }, } for system_name in jacs_systems: prefix = jacs_systems[system_name]['prefix'] # Read molecules ligand_sdf_filename = get_data_filename(os.path.join('perses_jacs_systems', system_name, prefix + '_ligands.sdf')) print(f'Reading molecules from {ligand_sdf_filename} ...') from openforcefield.topology import Molecule molecules = Molecule.from_file(ligand_sdf_filename, allow_undefined_stereo=True) try: nmolecules = len(molecules) except TypeError: molecules = [molecules] print(f'Read {len(molecules)} molecules from {ligand_sdf_filename}') # Read ParmEd Structures import parmed from simtk import unit protein_pdb_filename = get_data_filename(os.path.join('perses_jacs_systems', system_name, prefix + '_protein.pdb')) from simtk.openmm.app import PDBFile print(f'Reading protein from {protein_pdb_filename} ...') #protein_structure = parmed.load_file(protein_pdb_filename) # NOTE: This mis-interprets distorted geometry and sequentially-numbered residues that span chain breaks pdbfile = PDBFile(protein_pdb_filename) protein_structure = parmed.openmm.load_topology(pdbfile.topology, xyz=pdbfile.positions.value_in_unit(unit.angstroms)) ligand_structures = parmed.load_file(ligand_sdf_filename) try: nmolecules = len(ligand_structures) except TypeError: ligand_structures = [ligand_structures] assert len(ligand_structures) == len(molecules) # Filter molecules if 'TRAVIS' in os.environ: MAX_MOLECULES = 3 else: MAX_MOLECULES = 6 molecules = molecules[:MAX_MOLECULES] ligand_structures = ligand_structures[:MAX_MOLECULES] print(f'{len(molecules)} molecules remain after filtering') # Create complexes complex_structures = [ (protein_structure + ligand_structure) for ligand_structure in ligand_structures ] # Create template generator with local cache cache = os.path.join(get_data_filename(os.path.join('perses_jacs_systems', system_name)), 'cache.json') generator = self.TEMPLATE_GENERATOR(molecules=molecules, cache=cache) # Create a ForceField from simtk.openmm.app import ForceField forcefield = ForceField(*self.amber_forcefields) # Register the template generator forcefield.registerTemplateGenerator(generator.generator) # Parameterize all complexes print(f'Caching all molecules for {system_name} at {cache} ...') for ligand_index, complex_structure in enumerate(complex_structures): openmm_topology = complex_structure.topology molecule = molecules[ligand_index] # Delete hydrogens from terminal protein residues # TODO: Fix the input files so we don't need to do this from simtk.openmm import app modeller = app.Modeller(complex_structure.topology, complex_structure.positions) residues = [residue for residue in modeller.topology.residues() if residue.name != 'UNL'] termini_ids = [residues[0].id, residues[-1].id] #hs = [atom for atom in modeller.topology.atoms() if atom.element.symbol in ['H'] and atom.residue.name != 'UNL'] hs = [atom for atom in modeller.topology.atoms() if atom.element.symbol in ['H'] and atom.residue.id in termini_ids] modeller.delete(hs) from simtk.openmm.app import PDBFile modeller.addHydrogens(forcefield) # Parameterize protein:ligand complex in vacuum print(f' Parameterizing {system_name} : {molecule.to_smiles()} in vacuum...') from simtk.openmm.app import NoCutoff forcefield.createSystem(modeller.topology, nonbondedMethod=NoCutoff) # Parameterize protein:ligand complex in solvent print(f' Parameterizing {system_name} : {molecule.to_smiles()} in explicit solvent...') from simtk.openmm.app import PME modeller.addSolvent(forcefield, padding=0*unit.angstroms, ionicStrength=300*unit.millimolar) forcefield.createSystem(modeller.topology, nonbondedMethod=PME)
def loop_extrusion(STEPS, LE_FORCE_SCALE, MATRIX_LENGTH, STEPS_PER_CYCLE, STEPS_PER_IT): STATE_FNAME = '2sided-state.csv' #STEPS = 10000 #LE_FORCE_SCALE = 3 #MATRIX_LENGTH = 200 #STEPS_PER_CYCLE = 10 #STEPS_PER_IT = 1 #Macierz z parametrami sił wiązań #Dodano funkcje generacji macierzy o wartościach sinusoidalnych. Funkcja ta przyjmuje dwa argumenty. Pierwszy oznacza liczbę kroków które ma posiadać macierz a drugi #stanowi regulacje maksymalnej siły (tzn jeśli wstawimy 3 to maksymalna siła bedzie tyle wynosić) LE_FORCE_MATRIX = gen_sin_array(MATRIX_LENGTH,LE_FORCE_SCALE) LE_FORCE_MATRIX[1][0] = 0 LE_FORCE_MATRIX[2][-1] = 0 #print(LE_FORCE_MATRIX) pdb = PDBFile('initial_structure.pdb') forcefield = ForceField('polymer_ff.xml') system = forcefield.createSystem(pdb.topology, nonbondedCutoff=1 * u.nanometer) integrator = mm.LangevinIntegrator(100 * u.kelvin, 0.2, 1 * u.femtoseconds) # Distance constraint for i in range(system.getNumParticles() - 1): system.addConstraint(i, i + 1, 0.1 * u.nanometer) # Pinning ends with rubber pin_force = mm.CustomExternalForce("k*((x-x0)^2+(y-y0)^2+(z-z0)^2)") pin_force.addGlobalParameter("k", 50 * u.kilocalories_per_mole / u.angstroms ** 2) pin_force.addPerParticleParameter("x0") pin_force.addPerParticleParameter("y0") pin_force.addPerParticleParameter("z0") pin_force.addParticle(0, [15 * u.angstrom, 0 * u.angstrom, 0 * u.angstrom]) pin_force.addParticle(system.getNumParticles() - 1, [-15 * u.angstrom, 0 * u.angstrom, 0 * u.angstrom]) system.addForce(pin_force) # Loop extrusion force le_force = mm.HarmonicBondForce() le_force.addBond(48, 50, 1 * u.angstrom, LE_FORCE_SCALE * u.kilocalories_per_mole / u.angstroms ** 2) for i in range(2, 35): p1, p2 = 49 - i, 49 + i le_force.addBond(p1, p2, 1 * u.angstrom, 0.000001 * u.kilocalories_per_mole / u.angstroms ** 2) system.addForce(le_force) simulation = Simulation(pdb.topology, system, integrator) simulation.context.setPositions(pdb.positions) simulation.minimizeEnergy() simulation.reporters.append(DCDReporter('wyniki/2sided-trj.dcd', 1)) simulation.reporters.append(StateDataReporter(stdout, 1000, step=True, potentialEnergy=True, temperature=True)) simulation.reporters.append(StateDataReporter(STATE_FNAME, 10, step=True, potentialEnergy=True)) simulation.step(1) for i in range(2, 35): p1, p2 = 49 - i, 49 + i for j in range(MATRIX_LENGTH): le_force_one = LE_FORCE_MATRIX[1][j] * u.kilocalories_per_mole / u.angstroms ** 2 #ROSNĄCA le_force_two = LE_FORCE_MATRIX[2][j] * u.kilocalories_per_mole / u.angstroms ** 2 #MALEJĄCA le_force.setBondParameters(i - 2, p1 + 1, p2 - 1, 1 * u.angstrom, le_force_two) le_force.setBondParameters(i - 1, p1, p2, 1 * u.angstrom, le_force_one) le_force.updateParametersInContext(simulation.context) #print(le_force_one) #print(le_force_two) #simulation.minimizeEnergy() simulation.step(STEPS_PER_IT) # for i in range(STEPS_PER_CYCLE): # simulation.step(1) simulation.step(200) plot_data(STATE_FNAME, '2sided-energy.png') print('#1: repr stick; color white; color red :1,100; repr sphere :1,100; vdwdefine 0.5') print('#1: color green :49,51; repr sphere :49,51; color #ffffa2e8a2e8 :50;') for i in range(1, 35): p1, p2 = 50 - i - 1, 50 + i + 1 print( f'#{i*STEPS_PER_CYCLE+1}: color green :{p1},{p2}; repr sphere :{p1},{p2}; repr stick :{p1+1},{p2-1}; color #ffffa2e8a2e8 :{p1+1}-{p2-1};') print("Done")
class SystemGenerator(object): """ Utility factory to generate OpenMM Systems from Topology objects. Parameters ---------- forcefields_to_use : list of string List of the names of ffxml files that will be used in system creation. forcefield_kwargs : dict of arguments to createSystem, optional Allows specification of various aspects of system creation. use_gaff : bool, optional, default=True If True, will add the GAFF residue template generator. Examples -------- >>> from simtk.openmm import app >>> forcefield_kwargs={ 'nonbondedMethod' : app.NoCutoff, 'implicitSolvent' : None, 'constraints' : None } >>> system_generator = SystemGenerator(['amber99sbildn.xml'], forcefield_kwargs=forcefield_kwargs) >>> from openmmtools.testsystems import AlanineDipeptideVacuum >>> testsystem = AlanineDipeptideVacuum() >>> system = system_generator.createSystem(testsystem.topology) """ def __init__(self, forcefields_to_use, forcefield_kwargs=None, use_gaff=True): self._forcefield_xmls = forcefields_to_use self._forcefield_kwargs = forcefield_kwargs if forcefield_kwargs is not None else {} from simtk.openmm.app import ForceField self._forcefield = ForceField(*self._forcefield_xmls) if use_gaff: self._forcefield.registerTemplateGenerator(gaffTemplateGenerator) def getForceField(self): """ Return the associated ForceField object. Returns ------- forcefield : simtk.openmm.app.ForceField The current ForceField object. """ return self._forcefield def createSystem(self, topology): """ Build a system from specified topology object. Parameters ---------- topology : simtk.openmm.app.Topology object The topology of the system to construct. Returns ------- system : openmm.System A system object generated from the topology """ system = self._forcefield.createSystem(topology, **self._forcefield_kwargs) return system @property def ffxmls(self): return self._forcefield_xmls @property def forcefield(self): return self._forcefield
import porinMembraneSystem from porinMembraneSystem import PorinMembraneSystem logger = logging.getLogger(__name__) # Setup general logging logging.root.setLevel(logging.DEBUG) logging.basicConfig(level=logging.DEBUG) yank.utils.config_root_logger(verbose=True, log_file_path=None) forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') pdbx = PDBxFile('atomistic-system-with-hydrogens.pdbx') system = forcefield.createSystem(pdbx.topology, nonbondedMethod=app.PME, rigidWater=False, nonbondedCutoff=1 * unit.nanometer) integrator = mm.VerletIntegrator(0.5 * unit.femtosecond) platform = mm.Platform.getPlatformByName('CUDA') simulation = app.Simulation(pdbx.topology, system, integrator, platform) simulation.loadCheckpoint('state.chk') positions = simulation.context.getState(getPositions=True).getPositions() #rigidWater = False is necessary because water parameters are required by Parmed #when loading the ligand ligand_atomistic_system = PorinMembraneSystem('comp7', system, pdbx.topology, positions, platform,
def test_reporter(tmpdir, get_fn): pdb = PDBFile(get_fn('native.pdb')) forcefield = ForceField('amber99sbildn.xml', 'amber99_obc.xml') # NO PERIODIC BOUNDARY CONDITIONS system = forcefield.createSystem(pdb.topology, nonbondedMethod=CutoffNonPeriodic, nonbondedCutoff=1.0 * nanometers, constraints=HBonds, rigidWater=True) integrator = LangevinIntegrator(300 * kelvin, 1.0 / picoseconds, 2.0 * femtoseconds) integrator.setConstraintTolerance(0.00001) platform = Platform.getPlatformByName('Reference') simulation = Simulation(pdb.topology, system, integrator, platform) simulation.context.setPositions(pdb.positions) simulation.context.setVelocitiesToTemperature(300 * kelvin) tmpdir = str(tmpdir) hdf5file = os.path.join(tmpdir, 'traj.h5') ncfile = os.path.join(tmpdir, 'traj.nc') dcdfile = os.path.join(tmpdir, 'traj.dcd') reporter = HDF5Reporter(hdf5file, 2, coordinates=True, time=True, cell=True, potentialEnergy=True, kineticEnergy=True, temperature=True, velocities=True) reporter2 = NetCDFReporter(ncfile, 2, coordinates=True, time=True, cell=True) reporter3 = DCDReporter(dcdfile, 2) simulation.reporters.append(reporter) simulation.reporters.append(reporter2) simulation.reporters.append(reporter3) simulation.step(100) reporter.close() reporter2.close() reporter3.close() with HDF5TrajectoryFile(hdf5file) as f: got = f.read() eq(got.temperature.shape, (50, )) eq(got.potentialEnergy.shape, (50, )) eq(got.kineticEnergy.shape, (50, )) eq(got.coordinates.shape, (50, 22, 3)) eq(got.velocities.shape, (50, 22, 3)) eq(got.cell_lengths, None) eq(got.cell_angles, None) eq(got.time, 0.002 * 2 * (1 + np.arange(50))) assert f.topology == md.load(get_fn('native.pdb')).top with NetCDFTrajectoryFile(ncfile) as f: xyz, time, cell_lengths, cell_angles = f.read() eq(cell_lengths, None) eq(cell_angles, None) eq(time, 0.002 * 2 * (1 + np.arange(50))) hdf5_traj = md.load(hdf5file) dcd_traj = md.load(dcdfile, top=get_fn('native.pdb')) netcdf_traj = md.load(ncfile, top=get_fn('native.pdb')) # we don't have to convert units here, because md.load already # handles that assert hdf5_traj.unitcell_vectors is None eq(hdf5_traj.xyz, netcdf_traj.xyz) eq(hdf5_traj.unitcell_vectors, netcdf_traj.unitcell_vectors) eq(hdf5_traj.time, netcdf_traj.time) eq(dcd_traj.xyz, hdf5_traj.xyz)