def minimise_energy_all_confs(mol, models = None, epsilon = 4, allow_undefined_stereo = True, **kwargs ): from simtk import unit from simtk.openmm import LangevinIntegrator from simtk.openmm.app import Simulation, HBonds, NoCutoff from rdkit import Chem from rdkit.Geometry import Point3D import mlddec import copy import tqdm mol = Chem.AddHs(mol, addCoords = True) if models is None: models = mlddec.load_models(epsilon) charges = mlddec.get_charges(mol, models) from openforcefield.utils.toolkits import RDKitToolkitWrapper, ToolkitRegistry from openforcefield.topology import Molecule, Topology from openforcefield.typing.engines.smirnoff import ForceField # from openforcefield.typing.engines.smirnoff.forcefield import PME import parmed import numpy as np forcefield = ForceField(get_data_filename("modified_smirnoff99Frosst.offxml")) #FIXME better way of identifying file location tmp = copy.deepcopy(mol) tmp.RemoveAllConformers() #XXX workround for speed beacuse seemingly openforcefield records all conformer informations, which takes a long time. but I think this is a ill-practice molecule = Molecule.from_rdkit(tmp, allow_undefined_stereo = allow_undefined_stereo) molecule.partial_charges = unit.Quantity(np.array(charges), unit.elementary_charge) topology = Topology.from_molecules(molecule) openmm_system = forcefield.create_openmm_system(topology, charge_from_molecules= [molecule]) structure = parmed.openmm.topsystem.load_topology(topology.to_openmm(), openmm_system) system = structure.createSystem(nonbondedMethod=NoCutoff, nonbondedCutoff=1*unit.nanometer, constraints=HBonds) integrator = LangevinIntegrator(273*unit.kelvin, 1/unit.picosecond, 0.002*unit.picoseconds) simulation = Simulation(structure.topology, system, integrator) out_mol = copy.deepcopy(mol) for i in tqdm.tqdm(range(out_mol.GetNumConformers())): conf = mol.GetConformer(i) structure.coordinates = unit.Quantity(np.array([np.array(conf.GetAtomPosition(i)) for i in range(mol.GetNumAtoms())]), unit.angstroms) simulation.context.setPositions(structure.positions) simulation.minimizeEnergy() # simulation.step(1) coords = simulation.context.getState(getPositions = True).getPositions(asNumpy = True).value_in_unit(unit.angstrom) conf = out_mol.GetConformer(i) for j in range(out_mol.GetNumAtoms()): conf.SetAtomPosition(j, Point3D(*coords[j])) return out_mol
def minimize_energy(pdb: PDBFile, simulation: Simulation, args: ListOfArgs): if args.MINIMIZE: print('Energy minimizing...') simulation.minimizeEnergy(tolerance=0.01 * simtk.unit.kilojoules_per_mole) if not args.MINIMIZED_FILE: base, _ = os.path.splitext(args.INITIAL_STRUCTURE_PATH) minimized_file_name = f'{base}_min.pdb' else: minimized_file_name = args.MINIMIZED_FILE # TODO: Nasty fix print(f' Saving minimized structure in {minimized_file_name}') state = simulation.context.getState(getPositions=True) PDBFile.writeFile(pdb.topology, state.getPositions(), open(minimized_file_name, 'w'))
def simulation_from_graph(self, g): """ Create simulation from moleucle """ # assign partial charge g.mol.assign_partial_charges("gasteiger") # faster # parameterize topology topology = g.mol.to_topology() # create openmm system system = self.forcefield.create_openmm_system( topology, # TODO: # figure out whether `sqm` should be so slow charge_from_molecules=[g.mol], ) # use langevin integrator integrator = openmm.LangevinIntegrator(self.temperature, self.collision_rate, self.step_size) # initialize simulation simulation = Simulation(topology=topology, system=system, integrator=integrator) import openforcefield # get conformer g.mol.generate_conformers( toolkit_registry=openforcefield.utils.RDKitToolkitWrapper(), ) # put conformer in simulation simulation.context.setPositions(g.mol.conformers[0]) # minimize energy simulation.minimizeEnergy() # set velocities simulation.context.setVelocitiesToTemperature(self.temperature) return simulation
def distributeLipids(boxsize, resnames, sigmas, cutoff, mass=39.9 * unit.amu, # argon epsilon=0.238 * unit.kilocalories_per_mole, # argon, switch_width=3.4 * unit.angstrom, # argon ): nparticles = len(resnames) # Determine Lennard-Jones cutoff. cutoff = cutoff * unit.angstrom cutoff_type = openmm.NonbondedForce.CutoffPeriodic # Create an empty system object. system = openmm.System() # Periodic box vectors. a = unit.Quantity((boxsize[0] * unit.angstrom, 0 * unit.angstrom, 0 * unit.angstrom)) b = unit.Quantity((0 * unit.angstrom, boxsize[1] * unit.angstrom, 0 * unit.angstrom)) c = unit.Quantity((0 * unit.angstrom, 0 * unit.angstrom, boxsize[2] * unit.angstrom)) system.setDefaultPeriodicBoxVectors(a, b, c) # Set up periodic nonbonded interactions with a cutoff. nb = openmm.NonbondedForce() nb.setNonbondedMethod(cutoff_type) nb.setCutoffDistance(cutoff) nb.setUseDispersionCorrection(True) nb.setUseSwitchingFunction(False) if (switch_width is not None): nb.setUseSwitchingFunction(True) nb.setSwitchingDistance(cutoff - switch_width) for s in sigmas: system.addParticle(mass) nb.addParticle(0.0 * unit.elementary_charge, s * unit.angstrom, epsilon) positions = subrandom_particle_positions(nparticles, system.getDefaultPeriodicBoxVectors(), 2) # Add the nonbonded force. system.addForce(nb) # Add a restraining potential to keep atoms in z=0 energy_expression = 'k * (z^2)' force = openmm.CustomExternalForce(energy_expression) force.addGlobalParameter('k', 10) for particle_index in range(nparticles): force.addParticle(particle_index, []) system.addForce(force) # Create topology. topology = app.Topology() chain = topology.addChain() elems = ['Ar', 'Cl', 'Na'] _, idx = np.unique(resnames, return_inverse=True) for i in idx: element = app.Element.getBySymbol(elems[i]) residue = topology.addResidue(elems[i], chain) topology.addAtom(elems[i], element, residue) topology.setUnitCellDimensions(unit.Quantity(boxsize, unit.angstrom)) # Simulate it from simtk.openmm import LangevinIntegrator, VerletIntegrator from simtk.openmm.app import Simulation, PDBReporter, StateDataReporter, PDBFile from simtk.unit import kelvin, picoseconds, picosecond, angstrom from sys import stdout from mdtraj.reporters import DCDReporter nsteps = 10000 freq = 1 integrator = VerletIntegrator(0.002 * picoseconds) simulation = Simulation(topology, system, integrator) simulation.context.setPositions(positions) simulation.minimizeEnergy() # simulation.reporters.append(DCDReporter('output.dcd', 1)) # simulation.reporters.append(StateDataReporter(stdout, 1000, potentialEnergy=True, totalEnergy=True, step=True, separator=' ')) simulation.step(nsteps) state = simulation.context.getState(getPositions=True, enforcePeriodicBox=True) allfinalpos = state.getPositions(asNumpy=True).value_in_unit(angstrom) # with open('topology.pdb', 'w') as f: # PDBFile.writeFile(topology, positions, f) # from htmd.molecule.molecule import Molecule # mol = Molecule('topology.pdb') # mol.read('output.dcd') return allfinalpos
# Loop extrusion force le_force = mm.HarmonicBondForce() le_force.addBond( 48, 50, 1 * u.angstrom, LE_FORCE_MATRIX[2][0] * 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, LE_FORCE_MATRIX[1][0] * 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('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(STEPS_PER_CYCLE) for i in range(2, 35): p1, p2 = 49 - i, 49 + i for j in range(0, STEPS_PER_CYCLE):
def test_improper_recover(): from simtk import openmm, unit from simtk.openmm.app import Simulation from simtk.unit import Quantity TEMPERATURE = 500 * unit.kelvin STEP_SIZE = 1 * unit.femtosecond COLLISION_RATE = 1 / unit.picosecond system, topology, g = _create_impropers_only_system() # use langevin integrator, although it's not super useful here integrator = openmm.LangevinIntegrator( TEMPERATURE, COLLISION_RATE, STEP_SIZE ) # initialize simulation simulation = Simulation( topology=topology, system=system, integrator=integrator ) import openff.toolkit # get conformer g.mol.generate_conformers( toolkit_registry=openff.toolkit.utils.RDKitToolkitWrapper(), ) # put conformer in simulation simulation.context.setPositions(g.mol.conformers[0]) # minimize energy simulation.minimizeEnergy() # set velocities simulation.context.setVelocitiesToTemperature(TEMPERATURE) samples = [] us = [] # loop through number of samples for _ in range(10): # run MD for `self.n_steps_per_sample` steps simulation.step(10) # append samples to `samples` samples.append( simulation.context.getState(getPositions=True) .getPositions(asNumpy=True) .value_in_unit(esp.units.DISTANCE_UNIT) ) us.append( simulation.context.getState(getEnergy=True) .getPotentialEnergy() .value_in_unit(esp.units.ENERGY_UNIT) ) # put samples into an array samples = np.array(samples) us = np.array(us) # put samples into tensor samples = torch.tensor(samples, dtype=torch.float32) us = torch.tensor(us, dtype=torch.float32)[None, :, None] g.heterograph.nodes["n1"].data["xyz"] = samples.permute(1, 0, 2) # require gradient for force matching g.heterograph.nodes["n1"].data["xyz"].requires_grad = True g.heterograph.nodes["g"].data["u_ref"] = us # parametrize layer = esp.nn.dgl_legacy.gn() net = torch.nn.Sequential( esp.nn.Sequential(layer, [32, "tanh", 32, "tanh", 32, "tanh"]), esp.nn.readout.janossy.JanossyPoolingImproper( in_features=32, config=[32, "tanh"], out_features={ "k": 6, }, ), esp.mm.geometry.GeometryInGraph(), esp.mm.energy.EnergyInGraph(terms=["n4_improper"]), ) optimizer = torch.optim.Adam(net.parameters(), 1e-3) for _ in range(1500): optimizer.zero_grad() net(g.heterograph) u_ref = g.nodes["g"].data["u"] u = g.nodes["g"].data["u_ref"] loss = torch.nn.MSELoss()(u_ref, u) loss.backward() print(loss) optimizer.step() assert loss.detach().numpy().item() < 0.1
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.") # start minimization tolerance = 0.1 * unit.kilojoules_per_mole / unit.angstroms print("Done setting tolerance.") minimize.minimizeEnergy(tolerance=tolerance, maxIterations=1000) print("Done setting energy minimization.") minimize.reporters.append( StateDataReporter('relax-hydrogens.log', 1000, step=True, temperature=True, potentialEnergy=True, totalEnergy=True, speed=True)) minimize.step(min_steps) print("Done 100000 steps of minimization.") print("Potential energy after minimization:") #print(minimize.context.getState(getEnergy=True).getPotentialEnergy()) positions = minimize.context.getState(getPositions=True).getPositions() print("Done updating positions.")
def simulate(self, header, content): """Main method that is "executed" by the receipt of the msg_type == 'simulate' message from the server. We run some OpenMM dynamics, and then send back the results. """ self.log.info('Setting up simulation...') state, topology = self.deserialize_input(content) # set the GPU platform platform = Platform.getPlatformByName(str(self.platform)) if self.platform == 'CUDA': properties = {'CudaPrecision': 'mixed', 'CudaDeviceIndex': str(self.device_index) } elif self.platform == 'OpenCL': properties = {'OpenCLPrecision': 'mixed', 'OpenCLDeviceIndex': str(self.device_index) } else: properties = None simulation = Simulation(topology, self.system, self.integrator, platform, properties) # do the setup self.set_state(state, simulation) self.sanity_check(simulation) if self.minimize: self.log.info('minimizing...') simulation.minimizeEnergy() if self.random_initial_velocities: try: temp = simulation.integrator.getTemperature() simulation.context.setVelocitiesToTemperature(temp) except AttributeError: print "I don't know what temperature to use!!" # TODO: look through the system's forces to find an andersen # thermostate? raise pass assert content.output.protocol == 'localfs', "I'm currently only equiped for localfs output" self.log.info('adding reporters...') self.add_reporters(simulation, content.output.path) # run dynamics! self.log.info('Starting dynamics') simulation.step(self.number_of_steps) for reporter in simulation.reporters: # explicitly delete the reporters so that any open file handles # are closed. del reporter # tell the master that I'm done self.send_recv(msg_type='simulation_done', content={ 'status': 'success', 'output': { 'protocol': 'localfs', 'path': content.output.path } })
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 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
print("Done specifying integrator.") platform = mm.Platform.getPlatformByName('CUDA') print("Done specifying platform.") platform.setPropertyDefaultValue('Precision', 'single') print("Done setting the precision to single.") simulation = Simulation(molecule.topology, system, integrator, platform) print("Done specifying simulation.") simulation.context.setPositions(molecule.positions) print("Done recording a context for positions.") simulation.context.setVelocitiesToTemperature(310.15 * unit.kelvin) print("Done assigning velocities.") # start minimization tolerance = 0.1 * unit.kilojoules_per_mole / unit.angstroms print("Done setting tolerance.") simulation.minimizeEnergy(tolerance=tolerance, maxIterations=1000) print("Done setting energy minimization.") simulation.reporters.append( StateDataReporter('relax-hydrogens.log', 1000, step=True, temperature=True, potentialEnergy=True, totalEnergy=True, speed=True)) simulation.step(10000) print("Done 10000 steps of simulation.") positions = simulation.context.getState(getPositions=True).getPositions() print("Done updating positions.") simulation.saveCheckpoint('state.chk') print("Done saving checkpoints.")
def main(): parser = argparse.ArgumentParser(description='Runs local minimization on \ the protein-ligand complex using OpenMM') parser.add_argument('-l', '--ligand', action='store', nargs=1, dest='ligand', help='The ligand .pdb file to generate \ parameters for') parser.add_argument('-x', '--xml_ligand', action='store', nargs=1, dest='xml', help='The xml file containing ligand \ parameters - use full path if not in directory where \ this script is being executed from') parser.add_argument('-p', '--protein', action='store', nargs=1, dest='protein', help='The protein complex .pdb file') 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 in ligand file and parameters ligand_pdbfile = PDBFile(args['input'][0] + '/' + args['ligand'][0]) ligand_system = parmed.load_file(args['xml'][0]) ligand_structure = load_topology(ligand_pdbfile.topology, ligand_system, xyz=ligand_pdbfile.positions) #Load in protein complex file and force field receptor_pdbfile = PDBFile(args['input'][0] + '/' + args['protein'][0]) receptor_pdbfile_name = args['protein'][0].split('.pdb')[-2] omm_forcefield = ForceField('amber14-all.xml') receptor_system = omm_forcefield.createSystem(receptor_pdbfile.topology) receptor_structure = load_topology(receptor_pdbfile.topology, receptor_system, xyz=receptor_pdbfile.positions) #Generate ligand-protein complex complex_structure = receptor_structure + ligand_structure complex_system = (complex_structure.createSystem(nonbondedMethod=NoCutoff, nonbondedCutoff=9.0 * angstrom, constraints=HBonds, removeCMMotion=False)) #Set up simulation parameters integrator = LangevinIntegrator(300 * kelvin, 1 / picosecond, 0.002 * picoseconds) simulation = Simulation(complex_structure.topology, complex_system, integrator) simulation.context.setPositions(complex_structure.positions) #Run local minimization simulation.minimizeEnergy() positions = simulation.context.getState(getPositions=True).getPositions() #Save minimized complex structure PDBFile.writeFile( simulation.topology, positions, open(args['output'][0] + '/' + receptor_pdbfile_name + '_min.pdb', 'w'))
def simulate(self, header, content): """Main method that is "executed" by the receipt of the msg_type == 'simulate' message from the server. We run some OpenMM dynamics, and then send back the results. """ self.log.info('Setting up simulation...') state, topology = self.deserialize_input(content) starting_state_path = content.starting_state.path # set the GPU platform platform = Platform.getPlatformByName(str(self.platform)) if self.platform == 'CUDA': properties = { 'CudaPrecision': 'mixed', 'CudaDeviceIndex': str(self.device_index) } elif self.platform == 'OpenCL': properties = { 'OpenCLPrecision': 'mixed', 'OpenCLDeviceIndex': str(self.device_index) } else: properties = None simulation = Simulation(topology, self.system, self.integrator, platform, properties) # do the setup self.set_state(state, simulation) self.sanity_check(simulation) if self.minimize: self.log.info('minimizing...') simulation.minimizeEnergy() if self.random_initial_velocities: try: temp = simulation.integrator.getTemperature() simulation.context.setVelocitiesToTemperature(temp) except AttributeError: print "I don't know what temperature to use!!" # TODO: look through the system's forces to find an andersen # thermostate? raise pass assert content.output.protocol == 'localfs', "I'm currently only equiped for localfs output" self.log.info('adding reporters...') self.add_reporters(simulation, content.output.path) # run dynamics! self.log.info('Starting dynamics') simulation.step(self.number_of_steps) for reporter in simulation.reporters: # explicitly delete the reporters so that any open file handles # are closed. del reporter # tell the master that I'm done self.send_recv(msg_type='simulation_done', content={ 'status': 'success', 'starting_state': { 'protocol': 'localfs', 'path': starting_state_path }, 'output': { 'protocol': 'localfs', 'path': content.output.path } })
def main(argdict): """ Main function for entry point checking. Expects a dictionary of command line arguments. """ # are we continuing from logfile or starting from fresh PDB? if argdict["log"] is None: # keep track of restart number: argdict["restart_number"] = int(0) # write arguments to a file to keep a record: with open(argdict["outname"] + "_parameters.log", 'w') as f: print(json.dumps(argdict, sort_keys=True, indent=4), file=f) else: # load configuration from logfile: logfile = argdict["log"] with open(argdict["log"], 'r') as f: argdict = json.load(f) # make sure log file has appropriate entry: argdict["log"] = logfile # increment restart number: argdict["restart_number"] += 1 # write unnumbered parameters file (for easy restarts): with open(argdict["outname"] + "_parameters.log", 'w') as f: print(json.dumps(argdict, sort_keys=True, indent=4), file=f) # write numbered parameters file (for record keeping): with open( argdict["outname"] + "_" + str(argdict["restart_number"]) + "_parameters.log", 'w') as f: print(json.dumps(argdict, sort_keys=True, indent=4), file=f) # load system initial configuration: pdb = pdb_file_nonstandard_bonds(argdict["pdb"]) print("--> input topology: ", end="") print(pdb.topology) # get XML file from absolute path: xmlfile = os.path.abspath(argdict["xml"]) # set box size in topology to values from XML file: box_vectors = periodic_box_vectors_from_xml(xmlfile) pdb.topology.setPeriodicBoxVectors(box_vectors) # 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 sim_num_steps = argdict["num_steps"] sim_traj_rep_steps = argdict["report_freq"] sim_state_rep_steps = argdict["report_freq"] sim_checkpoint_steps = argdict["report_freq"] # 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) sys = 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 = sys.getForce(9) print("--> using polarisation method " + str(argdict["polarisation"])) if argdict["polarisation"] == "mutual": multipole_force.setPolarizationType(multipole_force.Mutual) elif argdict["polarisation"] == "extrapolated": multipole_force.setPolarizationType(multipole_force.Extrapolated) elif argdict["polarisation"] == "direct": multipole_force.setPolarizationType(multipole_force.Direct) else: raise Exception("Polarisation method " + str(argdict["polarisation"]) + " not supported!") # 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)) sys.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) sys.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: sys.addForce(force) # make special group for nonbonded forces: for f in sys.getForces(): if (isinstance(f, AmoebaMultipoleForce) or isinstance(f, AmoebaVdwForce) or isinstance(f, AmoebaGeneralizedKirkwoodForce) or isinstance(f, AmoebaWcaDispersionForce)): f.setForceGroup(1) # read umbrella parameters from file: with open(argdict["umbrella_target"], "r") as f: umbrella_target = json.load(f) # obtain index from atom to be restrained: umbrella_index = umbrella_target["target_particle"]["index"] umbrella_fc = (umbrella_target["umbrella_params"]["fc"] * kilojoule_per_mole / nanometer**2) umbrella_cv = umbrella_target["umbrella_params"]["cv"] * nanometer # inform user: print("--> applying umbrella potential to " + str(list(pdb.topology.atoms())[umbrella_index]) + " at position " + str(pdb.positions[umbrella_index])) # additional restraining force applied to ion under umbrella restraints: umbrella_force = CustomExternalForce( "k*periodicdistance(0.0, 0.0, z, 0.0, 0.0, z0)^2") umbrella_force.addGlobalParameter("k", umbrella_fc) # z0 is set to value in JSON file rather than initial particle coordinate to # allow for a few steps of energy minimisation to avoid clashes between the # restrained umbrella target and surrounding atoms: umbrella_force.addGlobalParameter("z0", umbrella_cv) # 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)]) elif argdict["integrator"] == "verlet": # use Leapfrog Verlet integrator here: print("--> using Verlet integrator") integrator = VerletIntegrator(sim_timestep) else: # no other integrators supported: raise Exception("Integrator " + str(argdict["integrator"]) + " is not supported.") # select a platform: platform = Platform.getPlatformByName(argdict["platform"]) properties = { "CudaPrecision": argdict["precision"], "CudaDeviceIndex": "0" } # prepare a simulation from topology, system, and integrator and set initial # positions as in PDB file: sim = Simulation(pdb.topology, sys, integrator, platform, properties) # is this initial simulation or restart from checkpoint? if argdict["log"] is None: # load positions and velocities from XML file: print("--> loading simulation state from XML file...") sim.loadState(xmlfile) # find all particles bonded to ion (i.e. Drude particles): idx_bonded = atom_idx_from_bonds(sim.topology, umbrella_index) idx_shift = idx_bonded + [umbrella_index] # shift target particle into position: pos = (sim.context.getState(getPositions=True).getPositions( asNumpy=True)) pos[idx_shift, :] = (umbrella_target["target_particle"]["init_pos"] * nanometer) print("--> target particle now placed at " + str(pos[idx_shift, :])) # set new particle positions in context: sim.context.setPositions(pos) e_pot = sim.context.getState(getEnergy=True).getPotentialEnergy() print("--> potential energy after target placement is: " + str(e_pot)) # minimise energy to remove clashes: # (too many steps might ruin everythin!) print("--> running energy minimisation...") sim.minimizeEnergy(maxIterations=argdict["minimisation_steps"]) e_pot = sim.context.getState(getEnergy=True).getPotentialEnergy() print( "--> " + str(argdict["minimisation_steps"]) + " steps of energy minimisation reduced the potential energy to " + str(e_pot)) # reduce time step for equilibration period: print("--> running equilibration at reduced time step...") sim.integrator.setStepSize(0.1 * sim.integrator.getStepSize()) sim.context.setTime(0.0 * picosecond) # will write report about equilibration phase: sim.reporters.append( StateDataReporter(stdout, int(argdict["equilibration_steps"] / 10), step=True, time=True, speed=True, progress=True, remainingTime=True, totalSteps=argdict["equilibration_steps"], separator="\t")) # run equilibration steps: sim.step(argdict["equilibration_steps"]) # reset step size to proper value: sim.integrator.setStepSize(10.0 * sim.integrator.getStepSize()) sim.context.setTime(0.0 * picosecond) sim.reporters.clear() else: # load checkpoint file: checkpoint_file = (str(argdict["outname"]) + "_" + str(argdict["restart_number"] - 1) + ".chk") print("--> loading checkpoint file " + checkpoint_file) sim.loadCheckpoint(checkpoint_file) # write collective variable value to file: sample_outname = (argdict["outname"] + "_" + str(argdict["restart_number"]) + str(".dat")) sim.reporters.append( CollectiveVariableReporter(sample_outname, argdict["umbrella_freq"], umbrella_index)) # write simulation trajectory to DCD file: dcd_outname = (argdict["outname"] + "_" + str(argdict["restart_number"]) + str(".dcd")) sim.reporters.append(DCDReporter(dcd_outname, sim_traj_rep_steps)) # write state data to tab-separated CSV file: state_outname = (argdict["outname"] + "_" + str(argdict["restart_number"]) + str(".csv")) sim.reporters.append( StateDataReporter(state_outname, sim_state_rep_steps, step=True, time=True, progress=False, remainingTime=True, potentialEnergy=True, kineticEnergy=True, totalEnergy=True, temperature=True, volume=True, density=False, speed=True, totalSteps=sim_num_steps, separator="\t")) # write limited state information to standard out: sim.reporters.append( StateDataReporter(stdout, sim_state_rep_steps, step=True, time=True, speed=True, progress=True, remainingTime=True, totalSteps=sim_num_steps, separator="\t")) # write checkpoint files regularly: checkpoint_outname = (argdict["outname"] + "_" + str(argdict["restart_number"]) + ".chk") sim.reporters.append( CheckpointReporter(checkpoint_outname, sim_checkpoint_steps)) # run simulation: sim.step(argdict["num_steps"]) # save final simulation state: sim.saveState(argdict["outname"] + "_" + str(argdict["restart_number"]) + ".xml") positions = sim.context.getState(getPositions=True).getPositions() PDBFile.writeFile( sim.topology, positions, open( argdict["outname"] + "_" + str(argdict["restart_number"]) + ".pdb", "w"))
def distributeAtoms(boxsize=[34, 34, 34], nparticles=1000, reduced_density=0.05, mass=39.9 * unit.amu, # argon sigma=3.4 * unit.angstrom, # argon, epsilon=0.238 * unit.kilocalories_per_mole, # argon, cutoff=None, switch_width=3.4 * unit.angstrom, # argon dispersion_correction=True, lattice=False, charge=None, **kwargs): # Determine Lennard-Jones cutoff. if cutoff is None: cutoff = 3.0 * sigma charge = 0.0 * unit.elementary_charge cutoff_type = openmm.NonbondedForce.CutoffPeriodic # Create an empty system object. system = openmm.System() # Periodic box vectors. a = unit.Quantity((boxsize[0] * unit.angstrom, 0 * unit.angstrom, 0 * unit.angstrom)) b = unit.Quantity((0 * unit.angstrom, boxsize[1] * unit.angstrom, 0 * unit.angstrom)) c = unit.Quantity((0 * unit.angstrom, 0 * unit.angstrom, boxsize[2] * unit.angstrom)) system.setDefaultPeriodicBoxVectors(a, b, c) # Set up periodic nonbonded interactions with a cutoff. nb = openmm.NonbondedForce() nb.setNonbondedMethod(cutoff_type) nb.setCutoffDistance(cutoff) nb.setUseDispersionCorrection(dispersion_correction) nb.setUseSwitchingFunction(False) if (switch_width is not None): nb.setUseSwitchingFunction(True) nb.setSwitchingDistance(cutoff - switch_width) for particle_index in range(nparticles): system.addParticle(mass) nb.addParticle(charge, sigma, epsilon) positions = subrandom_particle_positions(nparticles, system.getDefaultPeriodicBoxVectors(), 2) # Add the nonbonded force. system.addForce(nb) # Add a restrining potential to keep atoms in z=0 energy_expression = 'k * (z^2)' force = openmm.CustomExternalForce(energy_expression) force.addGlobalParameter('k', 100) for particle_index in range(nparticles): force.addParticle(particle_index, []) system.addForce(force) # Create topology. topology = app.Topology() element = app.Element.getBySymbol('Ar') chain = topology.addChain() for particle in range(system.getNumParticles()): residue = topology.addResidue('Ar', chain) topology.addAtom('Ar', element, residue) topology.setUnitCellDimensions(unit.Quantity(boxsize, unit.angstrom)) # Simulate it from simtk.openmm import LangevinIntegrator, VerletIntegrator from simtk.openmm.app import Simulation, PDBReporter, StateDataReporter, PDBFile from simtk.unit import kelvin, picoseconds, picosecond, angstrom from sys import stdout from mdtraj.reporters import DCDReporter #from dcdreporter import DCDReporter nsteps = 10000 freq = 1 #integrator = LangevinIntegrator(300 * kelvin, 1 / picosecond, 0.002 * picoseconds) integrator = VerletIntegrator(0.002 * picoseconds) simulation = Simulation(topology, system, integrator) simulation.context.setPositions(positions) simulation.minimizeEnergy() simulation.reporters.append(DCDReporter('output.dcd', 1)) simulation.reporters.append(StateDataReporter(stdout, 1000, potentialEnergy=True, totalEnergy=True, step=True, separator=' ')) simulation.step(nsteps) state = simulation.context.getState(getPositions=True) finalpos = state.getPositions(asNumpy=True).value_in_unit(angstrom) with open('topology.pdb', 'w') as f: PDBFile.writeFile(topology, positions, f) from htmd.molecule.molecule import Molecule mol = Molecule('topology.pdb') mol.read('output.dcd') return finalpos, mol, system, simulation