def test_rb_energy_round_trip(tmpdir): """ Make sure that no parameters are lost when reading in RBterms. """ with tmpdir.as_cwd(): # load the molecule and parameterise mol = Ligand.from_file(file_name=get_data("cyclohexane.sdf")) XML().run(molecule=mol, input_files=[get_data("cyclohexane.xml")]) # load the serialised system we extract the parameters from as our reference ref_system = XmlSerializer.deserializeSystem( open("serialised.xml").read()) parm_top = load_topology(mol.to_openmm_topology(), system=ref_system, xyz=mol.openmm_coordinates()) ref_energy = energy_decomposition_system(parm_top, ref_system, platform="Reference") # now we need to build the system from our stored parameters mol.write_parameters(file_name="test.xml") ff = app.ForceField("test.xml") qube_system = ff.createSystem(mol.to_openmm_topology()) with open("qube.xml", "w") as xml_out: xml_out.write(XmlSerializer.serialize(qube_system)) qube_struc = load_topology(mol.to_openmm_topology(), system=qube_system, xyz=mol.openmm_coordinates()) qube_energy = energy_decomposition_system(qube_struc, qube_system, platform="Reference") # compare the decomposed energies of the groups for force_group, energy in ref_energy: for qube_force, qube_e in qube_energy: if force_group == qube_force: assert energy == pytest.approx(qube_e, abs=2e-3)
def serialize(self): """Return the System and positions in serialized XML form. Returns ------- system_xml : str Serialized XML form of System object. state_xml : str Serialized XML form of State object containing particle positions. """ from simtk.openmm import XmlSerializer # Serialize System. system_xml = XmlSerializer.serialize(self._system) # Serialize positions via State. if self._system.getNumParticles() == 0: # Cannot serialize the State of a system with no particles. state_xml = None else: platform = openmm.Platform.getPlatformByName('Reference') integrator = openmm.VerletIntegrator(1.0 * unit.femtoseconds) context = openmm.Context(self._system, integrator, platform) context.setPositions(self._positions) state = context.getState(getPositions=True) del context, integrator state_xml = XmlSerializer.serialize(state) return (system_xml, state_xml)
def serialize_simulation(self) -> str: ROOT_TAG = 'OpenMMSimulation' """ Generate an XML string from a simulation. :param simulation: The simulation to serialize. :return: A string with the content of an XML file describing the simulation. """ implementation = getDOMImplementation() document = implementation.createDocument(None, ROOT_TAG, None) # Extract the PDB positions = self.context.getState(getPositions=True).getPositions() pdb_content = StringIO() app.PDBFile.writeFile(self.topology, positions, pdb_content) pdb_node = document.createElement('pdb') pdb_node.appendChild(document.createTextNode(pdb_content.getvalue())) # Extract the system system_xml_str = XmlSerializer.serialize(self.system) system_document = parseString(system_xml_str) # Extract the integrator integrator_xml_str = XmlSerializer.serialize(self.integrator) integrator_document = parseString(integrator_xml_str) # Combine the element in a single root = document.documentElement root.appendChild(pdb_node) root.appendChild(system_document.documentElement) root.appendChild(integrator_document.documentElement) return root.toprettyxml()
def serialize(item, filename): """ Serialize an OpenMM System, State, or Integrator. Parameters ---------- item : System, State, or Integrator The thing to be serialized filename : str The filename to serialize to """ from simtk.openmm import XmlSerializer if filename[-2:] == 'gz': import gzip with gzip.open(filename, 'wb') as outfile: serialized_thing = XmlSerializer.serialize(item) outfile.write(serialized_thing.encode()) if filename[-3:] == 'bz2': import bz2 with bz2.open(filename, 'wb') as outfile: serialized_thing = XmlSerializer.serialize(item) outfile.write(serialized_thing.encode()) else: with open(filename, 'w') as outfile: serialized_thing = XmlSerializer.serialize(item) outfile.write(serialized_thing)
def fix_system(system_xml_filename): """ Set the PME parameters explicitly in a specified system XML file if they are not already set. The file is renamed with '.old' appended, and a corrected file written in its place. Parameters ---------- system_xml_filename : str The name of the serialized system XML file to be modified """ system = XmlSerializer.deserialize(read_file(system_xml_filename)) forces = { system.getForce(force_index).__class__.__name__: system.getForce(force_index) for force_index in range(system.getNumForces()) } force = forces['NonbondedForce'] (alpha, nx, ny, nz) = force.getPMEParameters() if alpha == 0.0 / unit.nanometers: (alpha, nx, ny, nz) = calc_pme_parameters(system) force.setPMEParameters(alpha, nx, ny, nz) serialized_system = XmlSerializer.serialize(system) os.rename(system_xml_filename, system_xml_filename + '.old') write_file(system_xml_filename, serialized_system) return
def dump_xml(system=None, integrator=None, state=None): """ Dump system, integrator, and state to XML for debugging. """ from simtk.openmm import XmlSerializer def write_file(filename, contents): outfile = open(filename, 'w') outfile.write(contents) outfile.close() if system: write_file('system.xml', XmlSerializer.serialize(system)) if integrator: write_file('integrator.xml', XmlSerializer.serialize(integrator)) if state: write_file('state.xml', XmlSerializer.serialize(state)) return
def from_xml(cls, path): with open(path) as f: xml = XmlSerializer.deserialize(f.read()) positions = xml.getPositions() velocities = xml.getVelocities() box = xml.getPeriodicBoxVectors() return cls(positions=positions, velocities=velocities, box=box)
def __init__(self, **kwargs): Calculator.__init__(self, **kwargs) input = self.parameters.input fileType = self.parameters.fileType if fileType == "xyz": print("Generating OpenMM system") self.system,self.topology = self.setUpMM3(self.parameters.ASEmol, self.parameters.atomTypes) positions = [x for x in self.parameters.ASEmol.get_positions()] if fileType == "xml": print("Generating OpenMM system") f = open('OpenMM.xml','r') sys = f.read() #self.system = forcefield.createSystem(topology, nonbondedMethod=self.parameters.nonbondedMethod,nonbondedCutoff=self.parameters.nonbondedCutoff) self.system = XmlSerializer.deserialize(sys) #box_vec = self.system.getDefaultPeriodicBoxVectors() #self.parameters.ASEmol.set_cell([box_vec[0]._value[0]*10,box_vec[1]._value[1]*10,box_vec[2]._value[2]*10]) #self.parameters.ASEmol.pbc = (True,True,True) #self.parameters.ASEmol.wrap() positions = [x for x in self.parameters.ASEmol.get_positions()] # Create a dummy integrator, this doesn't really matter. self.integrator = VerletIntegrator(0.001 * picosecond) self.platform = Platform.getPlatformByName("CPU") self.context = openmm.Context(self.system, self.integrator) self.context.setPositions(positions * angstrom) state = self.context.getState(getEnergy=True) print("Energy: ", state.getPotentialEnergy(), len(positions)) self.n_atoms = len(positions)
def __init__(self, system, integrator=None): # if strings are passed in, assume that they are paths to # xml files on disk if isinstance(system, basestring): with open(system) as f: system = XmlSerializer.deserialize(f.read()) if isinstance(integrator, basestring): with open(integrator) as f: integrator = XmlSerializer.deserialize(f.read()) if integrator is None: # this integrator isn't really necessary, but it has to be something # for the openmm API to let us serialize the state integrator = VerletIntegrator(2*femtoseconds) self.context = Context(system, integrator, Platform.getPlatformByName('Reference'))
def deserialize_input(self, content): """Retreive the state and topology from the message content The message protocol tries not to pass 'data' around within the messages, but instead pass paths to data. So far we're only sending paths on the local filesystem, but we might could generalize this to HTTP or S3 or something later. The assumption that data can be passed around on the local filesystem shouldn't be built deep into the code at all """ # todo: better name for this function? if content.starting_state.protocol == 'localfs': with open(content.starting_state.path) as f: self.log.info('Opening state file: %s', content.starting_state.path) state = XmlSerializer.deserialize(f.read()) else: raise ValueError('Unknown protocol') if content.topology_pdb.protocol == 'localfs': topology = PDBFile(content.topology_pdb.path).topology else: raise ValueError('Unknown protocol') return state, topology
def serialise_system(self): """Create the OpenMM system; parametrise using frost; serialise the system.""" # Load the molecule using openforcefield pdb_file = app.PDBFile(f'{self.molecule.name}.pdb') # Now we need the connection info try using smiles string from rdkit rdkit = RDKit() molecule = Molecule.from_smiles( rdkit.get_smiles(f'{self.molecule.name}.pdb')) # Make the openMM system omm_topology = pdb_file.topology off_topology = Topology.from_openmm(omm_topology, unique_molecules=[molecule]) # Load the smirnoff99Frosst force field. forcefield = ForceField('test_forcefields/smirnoff99Frosst.offxml') # Parametrize the topology and create an OpenMM System. system = forcefield.create_openmm_system(off_topology) # Serialise the OpenMM system into the xml file with open('serialised.xml', 'w+') as out: out.write(XmlSerializer.serializeSystem(system))
def _extract_charges(self): """Extracts all of the charges from a system object. Returns ------- list of float """ from simtk import unit as simtk_unit charge_list = [] with open(self._system_path, 'r') as file: system = XmlSerializer.deserialize(file.read()) for force_index in range(system.getNumForces()): force = system.getForce(force_index) if not isinstance(force, openmm.NonbondedForce): continue for atom_index in range(force.getNumParticles()): charge = force.getParticleParameters(atom_index)[0] charge = charge.value_in_unit(simtk_unit.elementary_charge) charge_list.append(charge) return charge_list
def check_system(system): """ Check OpenMM System object for pathologies, like duplicate atoms in torsions. Parameters ---------- system : simtk.openmm.System """ forces = { system.getForce(index).__class__.__name__: system.getForce(index) for index in range(system.getNumForces()) } force = forces['PeriodicTorsionForce'] for index in range(force.getNumTorsions()): [i, j, k, l, periodicity, phase, barrier] = force.getTorsionParameters(index) if len(set([i, j, k, l])) < 4: # TODO: Serialize system.xml on exceptions. msg = 'Torsion index %d of self._topology_proposal.new_system has duplicate atoms: %d %d %d %d\n' % ( index, i, j, k, l) msg += 'Serialzed system to system.xml for inspection.\n' from simtk.openmm import XmlSerializer serialized_system = XmlSerializer.serialize(system) outfile = open('system.xml', 'w') outfile.write(serialized_system) outfile.close() raise Exception(msg)
def minimization(): # Load OpenMM System file = open(xml_filename, 'r') serialized_system = file.read() system = XmlSerializer.deserialize(serialized_system) # Select Integrator integrator = mm.LangevinIntegrator(TEMPERATURE, MIN_FRICTION, MIN_TIME_STEP) # Set Simulation simulation = app.Simulation(prmtop.topology, system, integrator, MIN_PLATFORM) # Set Position simulation.context.setPositions(inpcrd.positions) state = simulation.context.getState(getEnergy=True) if np.isnan(state.getPotentialEnergy() / kilojoule_per_mole): raise ValueError("The Potential Energy before minimization is NaN") # Minimization print('Minimizing...\n') simulation.minimizeEnergy(tolerance=MIN_TOLERANCE, maxIterations=MIN_STEPS) state = simulation.context.getState(getPositions=True, getEnergy=True) if np.isnan(state.getPotentialEnergy() / kilojoule_per_mole): raise ValueError("The Potential Energy after minimization is NaN") coords = state.getPositions() return coords
def write_system_xml(self, file_name): """ Method that writes the OpenMM system stored in the `system` attribute to an XML file. Parameters ---------- file_name : str Name of the XML file to be written. Returns ------- `True` if file was closed successfully. `False` otherwise. """ from simtk.openmm import XmlSerializer logging.info( "Writing serialized system to XML file {}.".format(file_name)) serialized_system = XmlSerializer.serializeSystem(self.system) outfile = open(file_name, 'w') outfile.write(serialized_system) outfile.close() return outfile.close()
def build(self, trajectory): """Create a serialized XML state from the first frame in a trajectory Parameteters ------------ trajectory : mdtraj.trajectory.Trajectory The trajectory to take the frame from. We'll use both the the positions and the box vectors (if you're using periodic boundary conditions) """ periodic = False if trajectory.unitcell_vectors is not None: a, b, c = trajectory.unitcell_lengths[0] np.testing.assert_array_almost_equal(trajectory.unitcell_angles[0], np.ones(3) * 90) self.context.setPeriodicBoxVectors([a, 0, 0] * nanometers, [0, b, 0] * nanometers, [0, 0, c] * nanometers) periodic = True self.context.setPositions(trajectory.openmm_positions(0)) state = self.context.getState(getPositions=True, getVelocities=True, getForces=True, getEnergy=True, getParameters=True, enforcePeriodicBox=periodic) return XmlSerializer.serialize(state)
def serialise_system(self): """Serialise the amber style files into an openmm object.""" prmtop = app.AmberPrmtopFile(self.prmtop) system = prmtop.createSystem(nonbondedMethod=app.NoCutoff, constraints=None) with open('serialised.xml', 'w+') as out: out.write(XmlSerializer.serializeSystem(system))
def __init__(self, system, integrator=None): # if strings are passed in, assume that they are paths to # xml files on disk if isinstance(system, basestring): with open(system) as f: system = XmlSerializer.deserialize(f.read()) if isinstance(integrator, basestring): with open(integrator) as f: integrator = XmlSerializer.deserialize(f.read()) if integrator is None: # this integrator isn't really necessary, but it has to be something # for the openmm API to let us serialize the state integrator = VerletIntegrator(2 * femtoseconds) self.context = Context(system, integrator, Platform.getPlatformByName('Reference'))
def start(self): # load up the system and integrator files with open(self.system_xml) as f: self.system = XmlSerializer.deserialize(f.read()) # reset the random number seed for any random # forces (andersen thermostat, montecarlo barostat) for i in range(self.system.getNumForces()): force = self.system.getForce(i) if hasattr(force, 'setRandomNumberSeed'): force.setRandomNumberSeed(random_seed()) with open(self.integrator_xml) as f: self.integrator = XmlSerializer.deserialize(f.read()) # reset the random number seed for a stochastic integrator if hasattr(self.integrator, 'setRandomNumberSeed'): self.integrator.setRandomNumberSeed(random_seed()) super(OpenMMSimulator, self).start()
def _execute(self, directory, available_resources): from paprika.restraints.openmm import ( apply_dat_restraint, apply_positional_restraints, ) from simtk.openmm import XmlSerializer # Load in the system to add the restraints to. system = self.input_system.system # Define a custom force group per type of restraint to help # with debugging / analysis. force_groups = { "static": 10, "conformational": 11, "guest": 12, "symmetry": 13, "wall": 14, } # Apply the serialized restraints. restraints = self.load_restraints(self.restraints_path) for restraint_type in force_groups: if restraint_type not in restraints: continue for restraint in restraints[restraint_type]: apply_dat_restraint( system, restraint, self.phase, self.window_index, flat_bottom=restraint_type in ["symmetry", "wall"], force_group=force_groups[restraint_type], ) # Apply the positional restraints to the dummy atoms. apply_positional_restraints( self.input_system.topology_path, system, force_group=15 ) output_system_path = os.path.join(directory, "output.xml") with open(output_system_path, "w") as file: file.write(XmlSerializer.serialize(system)) self.output_system = ParameterizedSystem( substance=self.input_system.substance, force_field=self.input_system.force_field, topology_path=self.input_system.topology_path, system_path=output_system_path, )
def nvt(coords): # Load OpenMM System file = open(xml_filename, 'r') serialized_system = file.read() system = XmlSerializer.deserialize(serialized_system) # Select Integrator integrator = mm.LangevinIntegrator(TEMPERATURE, NVT_FRICTION, NVT_TIME_STEP) # Set Simulation simulation = app.Simulation(pdb.topology, system, integrator, NVT_PLATFORM, NVT_PROPERTIES) #DEBUG STUFF properties = NVT_PLATFORM.getPropertyValue(simulation.context, 'DeviceIndex') print(properties) print(NVT_PLATFORM.getPropertyNames()) print(NVT_PLATFORM.getSpeed()) #DEBUG STUFF # Set Position and velocities simulation.context.setPositions(coords) simulation.context.setVelocitiesToTemperature(TEMPERATURE) # Set Reporter simulation.reporters.append( app.DCDReporter(nvt_dcd_filename, NVT_OUTPUT_FREQ)) simulation.reporters.append( app.StateDataReporter(nvt_data_filename, NVT_DATA_FREQ, step=True, potentialEnergy=True, temperature=True, density=True)) state = simulation.context.getState(getEnergy=True) if np.isnan(state.getPotentialEnergy() / kilojoule_per_mole): raise ValueError("The Potential Energy before NVT is NaN") print('NVT...\n') simulation.step(NVT_STEPS) state = simulation.context.getState(getPositions=True, getVelocities=True, getEnergy=True) if np.isnan(state.getPotentialEnergy() / kilojoule_per_mole): raise ValueError("The Potential Energy after NVT is NaN") coords = state.getPositions() velocities = state.getVelocities() return coords, velocities
def _serialise_system(self, system: System) -> None: """ Serialise a openMM system to file so that the parameters can be gathered. Args: system: A parameterised OpenMM system. """ xml = XmlSerializer.serializeSystem(system) with open("serialised.xml", "w+") as out: out.write(xml)
def test_round_trip_energy(tmpdir, molecule, method, openff, antechamber): """ Make sure that no terms are missing when storing parameters from source by comparing energies. Note we relax the comparison to abs=2e-3 due to differences in nonbonded cutoffs, phase rounding and the ordering improper torsions are applied. """ if method == "openff": engine = openff else: engine = antechamber with tmpdir.as_cwd(): mol = Ligand.from_file(get_data(molecule)) # parametrise the system engine.run(mol) # this will make a serialised system in the folder so get the reference energy ref_system = XmlSerializer.deserializeSystem( open("serialised.xml").read()) parm_top = load_topology(mol.to_openmm_topology(), system=ref_system, xyz=mol.openmm_coordinates()) ref_energy = energy_decomposition_system(parm_top, ref_system, platform="Reference") # now we need to build the system from our stored parameters mol.write_parameters(file_name="test.xml") ff = app.ForceField("test.xml") qube_system = ff.createSystem(mol.to_openmm_topology()) with open("qube.xml", "w") as xml_out: xml_out.write(XmlSerializer.serialize(qube_system)) qube_struc = load_topology(mol.to_openmm_topology(), system=qube_system, xyz=mol.openmm_coordinates()) qube_energy = energy_decomposition_system(qube_struc, qube_system, platform="Reference") # compare the decomposed energies of the groups for force_group, energy in ref_energy: for qube_force, qube_e in qube_energy: if force_group == qube_force: assert energy == pytest.approx(qube_e, abs=2e-3)
def test_offxml_round_trip(tmpdir, openff, molecule): """ Test round tripping offxml parameters through qubekit """ with tmpdir.as_cwd(): mol = Ligand.from_file(get_data(molecule)) offmol = Molecule.from_file(get_data(molecule)) openff.run(mol) mol.to_offxml("test.offxml") # build another openmm system and serialise to compare with deepdiff offxml = ForceField("test.offxml") assert offxml.author == f"QUBEKit_version_{qubekit.__version__}" qubekit_system = offxml.create_openmm_system( topology=offmol.to_topology()) qubekit_xml = xmltodict.parse( openmm.XmlSerializer.serialize(qubekit_system)) with open("qubekit_xml", "w") as output: output.write(openmm.XmlSerializer.serialize(qubekit_system)) openff_system = xmltodict.parse(open("serialised.xml").read()) offxml_diff = DeepDiff( qubekit_xml, openff_system, ignore_order=True, significant_digits=6, ) # the only difference should be in torsions with a 0 barrier height which are excluded from an offxml for item in offxml_diff["iterable_item_removed"].values(): assert item["@k"] == "0" # load both systems and compute the energy qubekit_top = load_topology( mol.to_openmm_topology(), system=qubekit_system, xyz=mol.openmm_coordinates(), ) qubekit_energy = energy_decomposition_system(qubekit_top, qubekit_system, platform="Reference") ref_system = XmlSerializer.deserializeSystem( open("serialised.xml").read()) parm_top = load_topology(mol.to_openmm_topology(), system=ref_system, xyz=mol.openmm_coordinates()) ref_energy = energy_decomposition_system(parm_top, ref_system, platform="Reference") # compare the decomposed energies of the groups for force_group, energy in ref_energy: for qube_force, qube_e in qubekit_energy: if force_group == qube_force: assert energy == pytest.approx(qube_e, abs=2e-3)
def npt(coords, velocities): # Create OpenMM System file = open(xml_filename, 'r') serialized_system = file.read() system = XmlSerializer.deserialize(serialized_system) # Select Integrator integrator = mm.LangevinIntegrator(TEMPERATURE, NPT_FRICTION, NPT_TIME_STEP) # Set Barostat system.addForce( mm.MonteCarloBarostat(PRESSURE, TEMPERATURE, BAROSTAT_FREQUENCY)) # Set Simulation simulation = app.Simulation(prmtop.topology, system, integrator, NPT_PLATFORM, NPT_PROPERTIES) # Set Position and velocities simulation.context.setPositions(coords) simulation.context.setVelocities(velocities) # Set Reporter simulation.reporters.append( app.DCDReporter(npt_dcd_filename, NPT_OUTPUT_FREQ)) simulation.reporters.append( app.StateDataReporter(npt_data_filename, NPT_DATA_FREQ, step=True, potentialEnergy=True, temperature=True, density=True)) state = simulation.context.getState(getEnergy=True) if np.isnan(state.getPotentialEnergy() / kilojoule_per_mole): raise ValueError("The Potential Energy before NPT is NaN") print('NPT...\n') simulation.step(NPT_STEPS) state = simulation.context.getState(getPositions=True, getVelocities=True, getEnergy=True) if np.isnan(state.getPotentialEnergy() / kilojoule_per_mole): raise ValueError("The Potential Energy after NPT is NaN") coords = state.getPositions() velocities = state.getVelocities() box = state.getPeriodicBoxVectors() return coords, velocities, box
def serialise_system(self): """Serialise the input XML system using openmm.""" pdb = app.PDBFile(f'{self.molecule.name}.pdb') modeller = app.Modeller(pdb.topology, pdb.positions) forcefield = app.ForceField(self.xml) system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None) xml = XmlSerializer.serializeSystem(system) with open('serialised.xml', 'w+') as out: out.write(xml)
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 get_xml(xml_file): # TODO file access control attempt = 0 retries = 500 if not xml_file.endswith('.xml'): raise IOError("{} must end in '.xml' for reading as XML file".format(xml_file)) while True: try: with open(xml_file) as f: xml = f.read() cereal = XmlSerializer.deserialize(xml) return xml, cereal except ValueError as e: if attempt < retries: attempt += 1 time.sleep(5*random.random()) else: raise e
def serialise_system(self): """Serialise the input XML system using openmm.""" pdb = app.PDBFile(f"{self.molecule.name}.pdb") modeller = app.Modeller(pdb.topology, pdb.positions) # if the user want the general qube forcefield make it here. if self.xml == "QUBE_general_pi.xml": qube_general() forcefield = app.ForceField(self.xml) system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None) xml = XmlSerializer.serializeSystem(system) with open("serialised.xml", "w+") as out: out.write(xml)
def main(): parser = argparse.ArgumentParser(description='Parameterizes a small \ molecule ligand for use with OpenMM \ using OpenFF') parser.add_argument('-l', '--ligand', action='store', nargs=1, dest='ligand', help='The ligand .sdf file to generate \ parameters for') parser.add_argument('-i', '--input_directory', action='store', nargs=1, dest='input', default=['./'], help='Directory where \ input pdb files are stored') parser.add_argument('-o', '--output_directory', action='store', nargs=1, dest='output', default=['./'], help='Directory where \ output log should be written') args = vars(parser.parse_args()) #Load SDF file from minimize_lig.py lig_sdf = args['input'][0] + '/' + args['ligand'][0] lig_name = lig_sdf.split('.sdf')[-2] lig_off_molecule = Molecule(args['output'][0] + '/' + lig_sdf) force_field = ForceField('test_forcefields/smirnoff99Frosst.offxml') start = time.time() ligand_system = force_field.create_openmm_system( lig_off_molecule.to_topology()) end = time.time() print(end - start) with open(lig_name + '.xml', 'w') as f: f.write(XmlSerializer.serialize(ligand_system))
def serialise_system(self): """Serialise the input XML system using openmm.""" pdb = app.PDBFile(f'{self.molecule.name}.pdb') modeller = app.Modeller(pdb.topology, pdb.positions) if self.input_file: forcefield = app.ForceField(self.input_file) else: try: forcefield = app.ForceField(self.molecule.name + '.xml') except FileNotFoundError: raise FileNotFoundError('No .xml type file found.') system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None) xml = XmlSerializer.serializeSystem(system) with open('serialised.xml', 'w+') as out: out.write(xml)
def check_system(system): """ Check OpenMM System object for pathologies, like duplicate atoms in torsions. Parameters ---------- system : simtk.openmm.System """ forces = { system.getForce(index).__class__.__name__ : system.getForce(index) for index in range(system.getNumForces()) } force = forces['PeriodicTorsionForce'] for index in range(force.getNumTorsions()): [i, j, k, l, periodicity, phase, barrier] = force.getTorsionParameters(index) if len(set([i,j,k,l])) < 4: msg = 'Torsion index %d of self._topology_proposal.new_system has duplicate atoms: %d %d %d %d\n' % (index,i,j,k,l) msg += 'Serialzed system to system.xml for inspection.\n' from simtk.openmm import XmlSerializer serialized_system = XmlSerializer.serialize(system) outfile = open('system.xml', 'w') outfile.write(serialized_system) outfile.close() raise Exception(msg)
def build(self, trajectory): """Create a serialized XML state from the first frame in a trajectory Parameteters ------------ trajectory : mdtraj.trajectory.Trajectory The trajectory to take the frame from. We'll use both the the positions and the box vectors (if you're using periodic boundary conditions) """ periodic = False if trajectory.unitcell_vectors is not None: a, b, c = trajectory.unitcell_lengths[0] np.testing.assert_array_almost_equal(trajectory.unitcell_angles[0], np.ones(3)*90) self.context.setPeriodicBoxVectors([a, 0, 0] * nanometers, [0, b, 0] * nanometers, [0, 0, c] * nanometers) periodic = True self.context.setPositions(trajectory.openmm_positions(0)) state = self.context.getState(getPositions=True, getVelocities=True, getForces=True, getEnergy=True, getParameters=True, enforcePeriodicBox=periodic) return XmlSerializer.serialize(state)
def serialise_system(self): """Serialise the input XML system using openmm.""" pdb = app.PDBFile(f'{self.molecule.name}.pdb') modeller = app.Modeller(pdb.topology, pdb.positions) forcefield = app.ForceField(self.xml) # Check for virtual sites try: system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None) except ValueError: print('Virtual sites were found in the xml file') modeller.addExtraParticles(forcefield) system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None) xml = XmlSerializer.serializeSystem(system) with open('serialised.xml', 'w+') as out: out.write(xml)
def to_dict(self): system_xml = XmlSerializer.serialize(self.system) return {'system_xml': system_xml}
timestep = 1.0 * units.femtoseconds integrator = openmm.VerletIntegrator(timestep) context = openmm.Context(system, integrator) # Set positions context.setPositions(positions) # Evaluate the potential energy. state = context.getState(getEnergy=True, getForces=True, getPositions=True) initial_potential = state.getPotentialEnergy() initial_force = state.getForces(asNumpy=True) # Clean up del context, integrator from simtk.openmm import XmlSerializer # Serialize. system_xml = XmlSerializer.serialize(system) state_xml = XmlSerializer.serialize(state) # Deserialize. system = XmlSerializer.deserialize(system_xml) state = XmlSerializer.deserialize(state_xml) # Compute final potential and force. # Create a Context. timestep = 1.0 * units.femtoseconds integrator = openmm.VerletIntegrator(timestep) context = openmm.Context(system, integrator) # Set positions context.setPositions(positions) # Evaluate the potential energy. state = context.getState(getEnergy=True, getForces=True, getPositions=True)
# Set initial conditions. print "Setting initial positions..." context.setPositions(initial_positions) print "Setting initial velocities appropriate for temperature..." context.setVelocitiesToTemperature(temperature) # DEBUG: Write out initial conditions. print "Serializing..." def write_file(filename, contents): file = open(filename, 'w') file.write(contents) file.close() from simtk.openmm import XmlSerializer state = context.getState(getPositions=True, getVelocities=True, getEnergy=True, getForces=True) write_file(os.path.join(data_directory, '%05d.system.xml' % replicate), XmlSerializer.serialize(system)) write_file(os.path.join(data_directory, '%05d.state.xml' % replicate), XmlSerializer.serialize(state)) write_file(os.path.join(data_directory, '%05d.integrator.xml' % replicate), XmlSerializer.serialize(integrator)) # Record initial data. state = context.getState(getEnergy=True) reduced_volume = state.getPeriodicBoxVolume() / (nparticles * sigma**3) reduced_density = 1.0 / reduced_volume reduced_potential = state.getPotentialEnergy() / kT print "replicate %5d / %5d : initial : density %8.3f | potential %8.3f" % (replicate, nreplicates, reduced_density, reduced_potential) outfile.write('%8d %12.6f %12.6f\n' % (0, reduced_density, reduced_potential)) # Run simulation. for iteration in range(niterations): # Integrate the simulation. integrator.step(nsteps_per_iteration)
def main(): import doctest import argparse parser = argparse.ArgumentParser(description="Check OpenMM computed energies and forces across all platforms for a suite of test systems.") parser.add_argument('-o', '--outfile', dest='logfile', action='store', type=str, default=None) parser.add_argument('-v', dest='verbose', action='store_true') parser.add_argument('-i', '--input', dest="input_data_path", action="store", type=str) parser.add_argument('-t', '--tuneplatform', dest="tune_pme_platform", action="store", type=str, default=None) parser.add_argument('-p', '--precision', dest="precision", action="store", type=str, default='single') args = parser.parse_args() verbose = args.verbose # Don't display extra debug information. config_root_logger(verbose, log_file_path=args.logfile) # Print version. logger.info("OpenMM version: %s" % openmm.version.version) logger.info("") # List all available platforms logger.info("Available platforms:") for platform_index in range(openmm.Platform.getNumPlatforms()): platform = openmm.Platform.getPlatform(platform_index) logger.info("%5d %s" % (platform_index, platform.getName())) logger.info("") # Test all systems on Reference platform. platform = openmm.Platform.getPlatformByName("Reference") print('Testing Reference platform...') doctest.testmod() # Compute energy error made on all test systems for other platforms. # Make a count of how often set tolerance is exceeded. tests_failed = 0 # number of times tolerance is exceeded tests_passed = 0 # number of times tolerance is not exceeded logger.info("%16s%16s %16s %16s %16s %16s" % ("platform", "precision", "potential", "error", "force mag", "rms error")) reference_platform = openmm.Platform.getPlatformByName("Reference") n_runs=get_num_runs(args.input_data_path) for run in range(n_runs): print("Deserializing XML files for RUN%d" % run) state = XmlSerializer.deserialize(read_file(os.path.join(args.input_data_path,"RUN%d" % run, "state0.xml"))) integrator = XmlSerializer.deserialize(read_file(os.path.join(args.input_data_path,"RUN%d" % run, "integrator.xml"))) system = XmlSerializer.deserialize(read_file(os.path.join(args.input_data_path,"RUN%d" % run, "system.xml"))) # Update system periodic box vectors based on state. system.setDefaultPeriodicBoxVectors(*state.getPeriodicBoxVectors()) # Create test system instance. positions = state.getPositions() # Get PME parameters forces = [ system.getForce(force_index) for force_index in range(system.getNumForces()) ] force_dict = { force.__class__.__name__ : force for force in forces } print("PME parameters:") force = force_dict['NonbondedForce'] print(force.getPMEParameters()) (alpha, nx, ny, nz) = force.getPMEParameters() if alpha == 0.0 / unit.nanometers: # Set PME parameters explicitly. print("Setting PME parameters explicitly...") (alpha, nx, ny, nz) = calc_pme_parameters(system) print (alpha, nx, ny, nz) print(type(nx)) force.setPMEParameters(alpha, int(nx), int(ny), int(nz)) print(force.getPMEParameters()) if args.tune_pme_platform: # Tune PME parameters for specified platform. from optimizepme import optimizePME properties = dict() platform = openmm.Platform.getPlatformByName(args.tune_pme_platform) print("Tuning PME parameters for platform '%s' precision model '%s'..." % (platform.getName(), args.precision)) if (platform.getName() == 'OpenCL'): properties['OpenCLPrecision'] = args.precision elif (platform.getName() == 'CUDA'): properties['CudaPrecision'] = args.precision minCutoff = 0.8 * unit.nanometers maxCutoff = 1.2 * unit.nanometers optimizePME(system, integrator, positions, platform, properties, minCutoff, maxCutoff) class_name = 'RUN%d' % run logger.info("%s (%d atoms)" % (class_name, system.getNumParticles())) # Compute reference potential and force [reference_potential, reference_force] = compute_potential_and_force(system, positions, reference_platform) # Test all platforms. test_success = True for platform_index in range(openmm.Platform.getNumPlatforms()): try: platform = openmm.Platform.getPlatform(platform_index) platform_name = platform.getName() # Define precision models to test. if platform_name == 'Reference': precision_models = ['double'] else: precision_models = ['single'] if platform.supportsDoublePrecision(): precision_models.append('double') for precision_model in precision_models: # Set precision. if platform_name == 'CUDA': platform.setPropertyDefaultValue('CudaPrecision', precision_model) if platform_name == 'OpenCL': platform.setPropertyDefaultValue('OpenCLPrecision', precision_model) # Compute potential and force. [platform_potential, platform_force] = compute_potential_and_force(system, positions, platform) # Compute error in potential. potential_error = platform_potential - reference_potential # Compute per-atom RMS (magnitude) and RMS error in force. force_unit = unit.kilocalories_per_mole / unit.nanometers natoms = system.getNumParticles() force_mse = (((reference_force - platform_force) / force_unit)**2).sum() / natoms * force_unit**2 force_rmse = unit.sqrt(force_mse) force_ms = ((platform_force / force_unit)**2).sum() / natoms * force_unit**2 force_rms = unit.sqrt(force_ms) logger.info("%16s%16s %16.6f kcal/mol %16.6f kcal/mol %16.6f kcal/mol/nm %16.6f kcal/mol/nm" % (platform_name, precision_model, platform_potential / unit.kilocalories_per_mole, potential_error / unit.kilocalories_per_mole, force_rms / force_unit, force_rmse / force_unit)) # Mark whether tolerance is exceeded or not. if abs(potential_error) > ENERGY_TOLERANCE: test_success = False logger.info("%32s WARNING: Potential energy error (%.6f kcal/mol) exceeds tolerance (%.6f kcal/mol). Test failed." % ("", potential_error/unit.kilocalories_per_mole, ENERGY_TOLERANCE/unit.kilocalories_per_mole)) if abs(force_rmse) > FORCE_RMSE_TOLERANCE: test_success = False logger.info("%32s WARNING: Force RMS error (%.6f kcal/mol/nm) exceeds tolerance (%.6f kcal/mol/nm). Test failed." % ("", force_rmse/force_unit, FORCE_RMSE_TOLERANCE/force_unit)) if verbose: for atom_index in range(natoms): for k in range(3): logger.info("%12.6f" % (reference_force[atom_index,k]/force_unit), end="") logger.info(" : ", end="") for k in range(3): logger.info("%12.6f" % (platform_force[atom_index,k]/force_unit), end="") except Exception as e: logger.info(e) if test_success: tests_passed += 1 else: tests_failed += 1 if (test_success is False): # Write XML files of failed tests to aid in debugging. # Place forces into different force groups. forces = [ system.getForce(force_index) for force_index in range(system.getNumForces()) ] force_group_names = dict() group_index = 0 for force_index in range(system.getNumForces()): force_name = forces[force_index].__class__.__name__ if force_name == 'NonbondedForce': forces[force_index].setForceGroup(group_index+1) force_group_names[group_index] = 'NonbondedForce (direct)' group_index += 1 forces[force_index].setReciprocalSpaceForceGroup(group_index+1) force_group_names[group_index] = 'NonbondedForce (reciprocal)' group_index += 1 else: forces[force_index].setForceGroup(group_index+1) force_group_names[group_index] = force_name group_index += 1 ngroups = len(force_group_names) # Test by force group. logger.info("Breakdown of discrepancies by Force component:") nforces = system.getNumForces() for force_group in range(ngroups): force_name = force_group_names[force_group] logger.info(force_name) [reference_potential, reference_force] = compute_potential_and_force_by_force_group(system, positions, reference_platform, force_group) logger.info("%16s%16s %16s %16s %16s %16s" % ("platform", "precision", "potential", "error", "force mag", "rms error")) for platform_index in range(openmm.Platform.getNumPlatforms()): try: platform = openmm.Platform.getPlatform(platform_index) platform_name = platform.getName() # Define precision models to test. if platform_name == 'Reference': precision_models = ['double'] else: precision_models = ['single'] if platform.supportsDoublePrecision(): precision_models.append('double') for precision_model in precision_models: # Set precision. if platform_name == 'CUDA': platform.setPropertyDefaultValue('CudaPrecision', precision_model) if platform_name == 'OpenCL': platform.setPropertyDefaultValue('OpenCLPrecision', precision_model) # Compute potential and force. [platform_potential, platform_force] = compute_potential_and_force_by_force_group(system, positions, platform, force_group) # Compute error in potential. potential_error = platform_potential - reference_potential # Compute per-atom RMS (magnitude) and RMS error in force. force_unit = unit.kilocalories_per_mole / unit.nanometers natoms = system.getNumParticles() force_mse = (((reference_force - platform_force) / force_unit)**2).sum() / natoms * force_unit**2 force_rmse = unit.sqrt(force_mse) force_ms = ((platform_force / force_unit)**2).sum() / natoms * force_unit**2 force_rms = unit.sqrt(force_ms) logger.info("%16s%16s %16.6f kcal/mol %16.6f kcal/mol %16.6f kcal/mol/nm %16.6f kcal/mol/nm" % (platform_name, precision_model, platform_potential / unit.kilocalories_per_mole, potential_error / unit.kilocalories_per_mole, force_rms / force_unit, force_rmse / force_unit)) except Exception as e: logger.info(e) pass logger.info("") logger.info("%d tests failed" % tests_failed) logger.info("%d tests passed" % tests_passed) if (tests_failed > 0): # Signal failure of test. sys.exit(1) else: sys.exit(0)
def from_dict(cls, dct): system_xml = dct["system_xml"] subsets = dct["subsets"] return cls(XmlSerializer.deserialize(system_xml), subsets)
app.Topology.loadBondDefinitions('../residues-nle.xml') pdb = app.PDBFile(NATIVE) forcefield = app.ForceField('amber99sbildn.xml', 'tip3p.xml', '../amber99sbildn-nle.xml') system = forcefield.createSystem(pdb.topology, nonbondedMethod=app.PME, nonbondedCutoff=9.5 * unit.angstroms, constraints=app.HBonds, rigidWater=True, ewaldErrorTolerance=0.0005) # system.addForce(mm.MonteCarloBarostat(1 * unit.atmosphere, TEMPERATURE, 25)) print("Writing system.xml") with open('system.xml', 'w') as f: f.write(XmlSerializer.serialize(system)) # Create Integrator integrator = mm.LangevinIntegrator(TEMPERATURE, 1.0 / unit.picoseconds, TIMESTEP) integrator.setConstraintTolerance(0.00001) print("Writing integrator.xml") with open('integrator.xml', 'w') as f: f.write(XmlSerializer.serialize(integrator)) # platform = mm.Platform.getPlatformByName('CUDA') # properties = {'CudaPrecision': 'mixed'} # simulation = app.Simulation(modeller.topology, system, integrator, platform, # properties)
def from_dict(cls, dct): system_xml = dct['system_xml'] return cls(XmlSerializer.deserialize(system_xml))
def to_dict(self): system_xml = XmlSerializer.serialize(self.system) return {"system_xml": system_xml, "subsets": self.subsets}