def __init__(self, prmtopFname, inpcrdFname): # prmtopFname, inpcrdFname ): self.prmtop = AmberPrmtopFile(prmtopFname) self.inpcrd = AmberInpcrdFile(inpcrdFname) # number of atoms self.natoms = self.prmtop.topology._numAtoms # todo: set up ff and simulation object self.system = self.prmtop.createSystem( nonbondedMethod=openmmff.NoCutoff) # no cutoff self.integrator = VerletIntegrator(0.001 * picosecond) self.simulation = Simulation(self.prmtop.topology, self.system, self.integrator) # Another way of setting up potential using just pdb file ( no prmtop ) # pdb = PDBFile('coords.pdb') # forcefield = ForceField('amber99sb.xml', 'tip3p.xml') # system = forcefield.createSystem(pdb.topology, nonbondedMethod=ff.NoCutoff) # integrator = VerletIntegrator(0.001*picoseconds) # simulation = Simulation(pdb.topology, system, integrator) # simulation.context.setPositions(pdb.positions) # remove units self.localCoords = self.inpcrd.positions / angstrom self.kJtokCal = kilocalories_per_mole / kilojoules_per_mole
def export_frame_coordinates(topology, trajectory, nframe, output=None): """ Extract a single frame structure from a trajectory. """ if output is None: basename, ext = os.path.splitext(trajectory) output = '{}.frame{}.inpcrd'.format(basename, nframe) # ParmEd sometimes struggles with certain PRMTOP files if os.path.splitext(topology)[1] in ('.top', '.prmtop'): top = AmberPrmtopFile(topology) mdtop = mdtraj.Topology.from_openmm(top.topology) traj = mdtraj.load_frame(trajectory, int(nframe), top=mdtop) structure = parmed.openmm.load_topology(top.topology, system=top.createSystem()) structure.box_vectors = top.topology.getPeriodicBoxVectors() else: # standard protocol (the topology is loaded twice, though) traj = mdtraj.load_frame(trajectory, int(nframe), top=topology) structure = parmed.load_file(topology) structure.positions = traj.openmm_positions(0) if traj.unitcell_vectors is not None: # if frame provides box vectors, use those structure.box_vectors = traj.openmm_boxes(0) structure.save(output, overwrite=True)
def __init__(self, ff_type=None, system_file=None, **kwargs): """Two pathways can be used starting from FF-specific files or OpenMM XML system. Additional kwargs are variously used depending on the forcefield / pathway that was chosen. supported ff_type ----------------- amber :: give a prmtop and an inpcrd openmm :: give an XML file for the system supported kwargs ---------------- topology :: system-specific or not depending on FF coordinates :: source of coordinates for initial state """ assert (ff_type is None) or (system_file is None) # This dict will store the API calls # along with atom groups and force # parameters needed to generate all # the given restraints self._restraints = dict() self._topology = None topofile = kwargs.get("topology", None) coordfile = kwargs.get("coordinates", None) if ff_type is not None: if ff_type.lower() == "amber": prmtop = AmberPrmtopFile(topofile) inpcrd = AmberInpcrdFile(coordfile) self.system = prmtop.createSystem( nonbondedMethod=NoCutoff ) #CutoffNonPeriodic - according to Ada, this would be good bc its what amber does - preliminary tests show that this hurts small/medium proteins self._topology = Topology.from_openmm(prmtop.topology) self._positions = inpcrd elif system_file is not None: self.load_xml(system_file) if topofile: if topofile.endswith(".pdb"): # this line is a bit silly but Topology class # doesn't seem to directly load PDB so keeps # the imports clean self._topology = Topology.from_openmm( PDBFile(topofile).topology) else: # Inspect and set ff_type # TODO ff_type as instance attribute pass
def from_amber(cls, path, positions=None, strict=True, **kwargs): """ Loads Amber Parm7 parameters and topology file Parameters ---------- path : str Path to *.prmtop or *.top file positions : simtk.unit.Quantity Atomic positions Returns ------- prmtop : SystemHandler SystemHandler with topology """ if strict and positions is None: raise ValueError( 'Amber TOP/PRMTOP files require initial positions.') prmtop = AmberPrmtopFile(path) box = kwargs.pop('box', prmtop.topology.getPeriodicBoxVectors()) return cls(master=prmtop, topology=prmtop.topology, positions=positions, box=box, path=path, **kwargs)
def __init__(self, prmtopFname, inpcrdFname): # prmtopFname, inpcrdFname ): # reads coords.inpcrd , coords.prmtop , min.in and data # - fnames hard coded (todo) super(GMINAmberPotential, self).__init__(GMIN) # self.potentialLocal = gminpot.GMINPotential(GMIN) GMIN.initialize() self.prmtop = AmberPrmtopFile(prmtopFname) self.inpcrd = AmberInpcrdFile(inpcrdFname) # number of atoms self.natoms = self.prmtop.topology._numAtoms self.localCoords = self.inpcrd.positions / angstrom
def __init__(self, prmtopFname, inpcrdFname ): # prmtopFname, inpcrdFname ): self.prmtop = AmberPrmtopFile( prmtopFname ) self.inpcrd = AmberInpcrdFile( inpcrdFname ) # number of atoms self.natoms = self.prmtop.topology._numAtoms # todo: set up ff and simulation object self.system = self.prmtop.createSystem(nonbondedMethod=openmmff.NoCutoff ) # no cutoff self.integrator = VerletIntegrator(0.001*picosecond) self.simulation = Simulation(self.prmtop.topology, self.system , self.integrator) # Another way of setting up potential using just pdb file ( no prmtop ) #pdb = PDBFile('coords.pdb') #forcefield = ForceField('amber99sb.xml', 'tip3p.xml') #system = forcefield.createSystem(pdb.topology, nonbondedMethod=ff.NoCutoff) #integrator = VerletIntegrator(0.001*picoseconds) #simulation = Simulation(pdb.topology, system, integrator) #simulation.context.setPositions(pdb.positions) # remove units self.localCoords = self.inpcrd.positions/angstrom self.kJtokCal = kilocalories_per_mole/kilojoules_per_mole
import numpy as np from simtk.openmm.app import AmberPrmtopFile """ creates a sqlite database from min.data, ts.data, extractedmin, extractedts Input: coords.prmtop ( for number of atoms ) min.data, ts.data, extractedmin, extractedts Output: storage.sqlite """ # determine number of atoms from prmtop prmtop = AmberPrmtopFile( 'coords.prmtop' ) # TOSET natoms = prmtop.topology._numAtoms # open database db = Database(db="storage.sqlite") # TOSET def read_coords(filee): coords = np.zeros(3*natoms) for i in range(natoms): x = filee.readline().split() coords[i*3:i*3+3] = [float(y) for y in x] return coords # counter to keep track of added minima mini=1 minima={}
# check cis if deg < 180: # this condition was found by inspection of structures todo isL = False # print 'chiral state of CA atom ', i[0], ' is D' # print 'CA improper torsion (deg) ', i, ' = ', deg return isL if __name__ == "__main__": # create topology from prmtop file from simtk.openmm.app import AmberPrmtopFile prmtop = AmberPrmtopFile('../../examples/amber/coords.prmtop') scheck = sanity_check(prmtop.topology) # get coordinates from a pdb file from simtk.openmm.app import pdbfile as openmmpdbReader from simtk.unit import angstrom as openmm_angstrom pdb = openmmpdbReader.PDBFile( '../../examples/amber/coords.pdb') # todo: coords.pdb is hardcoded coords = pdb.getPositions() / openmm_angstrom coords = np.reshape(np.transpose(coords), 3 * len(coords), 1) # test if scheck.check_CAchirality(coords):
def get_molecule_engine(**kwargs): """ Parameters ---------- args : namespace Command line arguments from argparse Returns ------- Molecule Molecule object containing necessary optimization info Engine Engine object containing methods for calculating energy and gradient """ ### Set up based on which quantum chemistry code we're using (defaults to TeraChem). engine_str = kwargs.get('engine', None) customengine = kwargs.get('customengine', None) # Path to Molpro executable (used if molpro=True) molproexe = kwargs.get('molproexe', None) # PDB file will be read for residue IDs to make TRICs for fragments # and provide starting coordinates in the case of OpenMM pdb = kwargs.get('pdb', None) # if frag=True, do not add a bond between residues. frag = kwargs.get('frag', False) # Number of threads to use (engine-dependent) threads = kwargs.get('nt', None) # Name of the input file. inputf = kwargs.get('input') # Name of temporary directory for calculations, needed by some engines. dirname = kwargs.get('dirname', None) # Temporary directory generated by a previous Q-Chem calculation, may be used at the beginning of a geomeTRIC calculation qcdir = kwargs.get('qcdir', None) ## MECI calculations create a custom engine that contains two other engines. if kwargs.get('meci', None): if engine_str.lower() in [ 'psi4', 'gmx', 'molpro', 'qcengine', 'openmm', 'gaussian' ] or customengine: logger.warning( "MECI optimizations are not tested with engines: psi4, gmx, molpro, qcengine, openmm, gaussian, customengine. Be Careful!" ) ## If 'engine' is provided as the argument to 'meci', then we assume the engine is # directly returning the MECI objective function and gradient. if kwargs['meci'].lower() == 'engine': sub_kwargs = kwargs.copy() sub_kwargs['meci'] = None M, engine = get_molecule_engine(**sub_kwargs) else: meci_sigma = kwargs.get('meci_sigma', 3.5) meci_alpha = kwargs.get('meci_alpha', 0.025) sub_engines = {} for state in [1, 2]: sub_kwargs = kwargs.copy() if state == 2: sub_kwargs['input'] = kwargs['meci'] sub_kwargs['meci'] = None M, sub_engine = get_molecule_engine(**sub_kwargs) sub_engines[state] = sub_engine engine = ConicalIntersection(M, sub_engines[1], sub_engines[2], meci_sigma, meci_alpha) return M, engine ## Read radii from the command line. # Cations should have radii of zero. arg_radii = kwargs.get('radii', ["Na", "0.0", "K", "0.0"]) if (len(arg_radii) % 2) != 0: raise RuntimeError("Must have an even number of arguments for radii") nrad = int(len(arg_radii) / 2) radii = {} for i in range(nrad): radii[arg_radii[2 * i].capitalize()] = float(arg_radii[2 * i + 1]) using_qchem = False threads_enabled = False if engine_str: engine_str = engine_str.lower() if engine_str[:4] == 'tera': engine_str = 'tera' if engine_str not in [ 'tera', 'qchem', 'psi4', 'gmx', 'molpro', 'openmm', 'qcengine', "gaussian" ]: raise RuntimeError( "Valid values of engine are: tera, qchem, psi4, gmx, molpro, openmm, qcengine, gaussian" ) if customengine: raise RuntimeError( "engine and customengine cannot simultaneously be set") if engine_str == 'tera': logger.info( "TeraChem engine selected. Expecting TeraChem input for gradient calculation.\n" ) set_tcenv() tcin = load_tcin(inputf) # The QM-MM interface is designed on the following ideas: # 1) We are only optimizing the QM portion of the system # (until we implement fast inversion of G matrices and Hessians) # 2) The geomeTRIC optimizer only "sees" the part of the molecule being optimized. # 3) The TeraChem engine writes .rst7 files instead of .xyz files by inserting the # optimization coordinates into the correct locations. qmmm = 'qmindices' in tcin if qmmm: from simtk.openmm.app import AmberPrmtopFile # Need to build a molecule object for the portion of the system being optimized # We rely on OpenMM's AmberPrmtopFile class to read the .prmtop file if not os.path.exists(tcin['coordinates']): raise RuntimeError( "TeraChem QM/MM coordinate file does not exist") if not os.path.exists(tcin['prmtop']): raise RuntimeError( "TeraChem QM/MM prmtop file does not exist") if not os.path.exists(tcin['qmindices']): raise RuntimeError( "TeraChem QM/MM qmindices file does not exist") prmtop_name = tcin['prmtop'] prmtop = AmberPrmtopFile(prmtop_name) M_full = Molecule(tcin['coordinates'], ftype='inpcrd', build_topology=False) M_full.elem = [ a.element.symbol for a in list(prmtop.topology.atoms()) ] M_full.resid = [ a.residue.index for a in list(prmtop.topology.atoms()) ] qmindices_name = tcin['qmindices'] qmindices = [ int(i.split()[0]) for i in open(qmindices_name).readlines() ] M = M_full.atom_select(qmindices) M.top_settings['radii'] = radii M.top_settings['fragment'] = frag M.build_topology() elif pdb is not None: M = Molecule(pdb, radii=radii, fragment=frag) else: if not os.path.exists(tcin['coordinates']): raise RuntimeError( "TeraChem coordinate file does not exist") M = Molecule(tcin['coordinates'], radii=radii, fragment=frag) M.charge = tcin['charge'] M.mult = tcin.get('spinmult', 1) # The TeraChem engine needs to write rst7 files before calling TC # and also make sure the prmtop and qmindices.txt files are present. engine = TeraChem(M, tcin, dirname=dirname) elif engine_str == 'qchem': logger.info( "Q-Chem engine selected. Expecting Q-Chem input for gradient calculation.\n" ) # The file from which we make the Molecule object if pdb is not None: # If we pass the PDB, then read both the PDB and the Q-Chem input file, # then copy the Q-Chem rem variables over to the PDB M = Molecule(pdb, radii=radii, fragment=frag) M1 = Molecule(inputf, radii=radii) for i in [ 'qctemplate', 'qcrems', 'elem', 'qm_ghost', 'charge', 'mult' ]: if i in M1: M[i] = M1[i] else: M = Molecule(inputf, radii=radii) engine = QChem(M, dirname=dirname, qcdir=qcdir, threads=threads) using_qchem = True threads_enabled = True elif engine_str == 'gmx': logger.info( "Gromacs engine selected. Expecting conf.gro, topol.top and shot.mdp (exact names).\n" ) M = Molecule(inputf, radii=radii, fragment=frag) if pdb is not None: M = Molecule(pdb, radii=radii, fragment=frag) if 'boxes' in M.Data: del M.Data['boxes'] engine = Gromacs(M) elif engine_str == 'openmm': logger.info( "OpenMM engine selected. Expecting forcefield.xml or system.xml file, and PDB passed in via --pdb.\n" ) if pdb is None: raise RuntimeError( "Must pass a PDB with option --pdb to use OpenMM.") M = Molecule(pdb, radii=radii, fragment=frag) if 'boxes' in M.Data: del M.Data['boxes'] engine = OpenMM(M, pdb, inputf) elif engine_str == 'psi4': logger.info( "Psi4 engine selected. Expecting Psi4 input for gradient calculation.\n" ) engine = Psi4(threads=threads) engine.load_psi4_input(inputf) if pdb is not None: M = Molecule(pdb, radii=radii, fragment=frag) M1 = engine.M for i in ['elem']: if i in M1: M[i] = M1[i] else: M = engine.M M.top_settings['radii'] = radii threads_enabled = True elif engine_str == 'molpro': logger.info( "Molpro engine selected. Expecting Molpro input for gradient calculation.\n" ) engine = Molpro(threads=threads) engine.load_molpro_input(inputf) M = engine.M if molproexe is not None: engine.set_molproexe(molproexe) threads_enabled = True elif engine_str == "gaussian": logger.info( "Gaussian engine selected. Expecting Gaussian input for gradient calculation. \n" ) M = Molecule(inputf, radii=radii, fragment=frag) # now work out which gaussian version we have if shutil.which("g16") is not None: exe = "g16" elif shutil.which("g09") is not None: exe = "g09" else: raise ValueError( "Neither g16 or g09 was found, please check the environment." ) engine = Gaussian(molecule=M, exe=exe, threads=threads) threads_enabled = True logger.info("The gaussian engine exe is set as %s" % engine.gaussian_exe) # load the template into the engine engine.load_gaussian_input(inputf) elif engine_str == 'qcengine': logger.info("QCEngine selected.\n") schema = kwargs.get('qcschema', False) if schema is False: raise RuntimeError("QCEngineAPI option requires a QCSchema") program = kwargs.get('qce_program', False) if program is False: raise RuntimeError( "QCEngineAPI option requires a qce_program option") engine = QCEngineAPI(schema, program) M = engine.M else: raise RuntimeError( "Failed to create an engine object, this might be a bug in get_molecule_engine" ) elif customengine: logger.info("Custom engine selected.\n") engine = customengine M = engine.M else: raise RuntimeError( "Neither engine name nor customengine object was provided.\n") # If --coords is provided via command line, use final coordinate set in the provided file # to override all previously provided coordinates. arg_coords = kwargs.get('coords', None) if arg_coords is not None: M1 = Molecule(arg_coords) M1 = M1[-1] M.xyzs = M1.xyzs # Perform some sanity checks on arguments if not using_qchem and qcdir: raise EngineError( "qcdir keyword argument passed to get_molecule_engine but Q-Chem engine is not being used" ) if threads and not threads_enabled: raise RuntimeError( "Setting number of threads not configured to work with %s yet" % engine_str) return M, engine
def _parm_top_from_string(parm_string): with tempfile.NamedTemporaryFile(mode="w") as parm_file: parm_file.write(parm_string) parm_file.flush() prm_top = AmberPrmtopFile(parm_file.name) return prm_top
from simtk.unit import picosecond import simtk.openmm.app.forcefield as openmmff #from sys import stdout # energy from GMIN GMIN.initialize() # reads coords.inpcrd and coords.prmtop pot = gminpot.GMINPotential(GMIN) coords = pot.getCoords() enerGmin = pot.getEnergy(coords)*4.184 # ----- OpenMM # setup using inpcrd and prmtop prmtop = AmberPrmtopFile('coords.prmtop') inpcrd = AmberInpcrdFile('coords.inpcrd') system1 = prmtop.createSystem(nonbondedMethod=openmmff.NoCutoff ) integrator1 = VerletIntegrator(0.001*picosecond) simulation1 = Simulation(prmtop.topology, system1, integrator1) simulation1.context.setPositions(inpcrd.positions) # get energy ener1 = simulation1.context.getState(getEnergy=True).getPotentialEnergy() # setup using pdb and built-in amber ff pdb = openmmpdb.PDBFile('coords.pdb') forcefield = openmmff.ForceField('amber99sb.xml', 'tip3p.xml') system2 = forcefield.createSystem(pdb.topology, nonbondedMethod=openmmff.NoCutoff) integrator2 = VerletIntegrator(0.001*picosecond) simulation2 = Simulation(pdb.topology, system2, integrator2) simulation2.context.setPositions(pdb.positions)
23 Mar 2014 """ from __future__ import print_function # OpenMM from simtk.openmm.app import AmberPrmtopFile, AmberInpcrdFile, Simulation from simtk.openmm.app import pdbfile as openmmpdb from simtk.openmm import * from simtk.unit import picosecond import simtk.openmm.app.forcefield as openmmff #from sys import stdout # ----- OpenMM # setup using inpcrd and prmtop prmtop = AmberPrmtopFile('coords.prmtop') inpcrd = AmberInpcrdFile('coords.inpcrd') system1 = prmtop.createSystem(nonbondedMethod=openmmff.NoCutoff) integrator1 = VerletIntegrator(0.001 * picosecond) simulation1 = Simulation(prmtop.topology, system1, integrator1) simulation1.context.setPositions(inpcrd.positions) # get energy ener1 = simulation1.context.getState(getEnergy=True).getPotentialEnergy() # setup using pdb and built-in amber ff pdb = openmmpdb.PDBFile('coords.pdb') forcefield = openmmff.ForceField('amber99sb.xml', 'tip3p.xml') system2 = forcefield.createSystem(pdb.topology, nonbondedMethod=openmmff.NoCutoff) integrator2 = VerletIntegrator(0.001 * picosecond) simulation2 = Simulation(pdb.topology, system2, integrator2)
def relevant_indices(trj): atom_indxs = [] for ref in res_indxs: atom_indxs += [atom.index for atom in trj.top.atoms if atom.residue.resSeq == ref] ri = np.array(atom_indxs) wi = np.array([atom.index for atom in trj.topology.atoms if (atom.residue.is_water and (atom.element.symbol == 'O'))]) ki = np.array([i.index for i in trj.top.atoms_by_name('K+')]) all_i = np.concatenate((ri,wi,ki)) table, bonds = trj.topology.to_dataframe() data = table.T[all_i].T return data start_time = time.time() prmtop = AmberPrmtopFile(args.prmtop) platform = mm.Platform.getPlatformByName('CPU') system = prmtop.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=2.0*unit.nanometers, constraints=app.HBonds, rigidWater=True, ewaldErrorTolerance=0.0005) system.addForce(mm.MonteCarloBarostat(1*unit.atmospheres, 300*unit.kelvin)) integrator = mm.LangevinIntegrator(300*unit.kelvin, 1.0/unit.picoseconds, 2.0*unit.femtoseconds) integrator.setConstraintTolerance(0.00001) simulation = app.Simulation(prmtop.topology, system, integrator, platform) trj = mdtraj.load(args.trj, top=args.prmtop) datumz = [] for tndx, frame in enumerate(trj): if tndx == 0:
class OpenMMAmberPotential(BasePotential): """ OpenMM V(r) = Amber """ def __init__(self, prmtopFname, inpcrdFname): # prmtopFname, inpcrdFname ): self.prmtop = AmberPrmtopFile(prmtopFname) self.inpcrd = AmberInpcrdFile(inpcrdFname) # number of atoms self.natoms = self.prmtop.topology._numAtoms # todo: set up ff and simulation object self.system = self.prmtop.createSystem( nonbondedMethod=openmmff.NoCutoff) # no cutoff self.integrator = VerletIntegrator(0.001 * picosecond) self.simulation = Simulation(self.prmtop.topology, self.system, self.integrator) # Another way of setting up potential using just pdb file ( no prmtop ) # pdb = PDBFile('coords.pdb') # forcefield = ForceField('amber99sb.xml', 'tip3p.xml') # system = forcefield.createSystem(pdb.topology, nonbondedMethod=ff.NoCutoff) # integrator = VerletIntegrator(0.001*picoseconds) # simulation = Simulation(pdb.topology, system, integrator) # simulation.context.setPositions(pdb.positions) # remove units self.localCoords = self.inpcrd.positions / angstrom self.kJtokCal = kilocalories_per_mole / kilojoules_per_mole # ''' ------------------------------------------------------------------- ''' def copyToLocalCoords(self, coords): """ copy to local coords -- deprecated """ # copy to local coords for i in range(self.natoms): self.localCoords[i] = Vec3(coords[3 * i], coords[3 * i + 1], coords[3 * i + 2]) # ''' ------------------------------------------------------------------- ''' def getEnergy(self, coords): """ returns energy in kcal/mol """ # using unit.Quantity is 5 times faster than calling copyToLocalCoords! coordinates = unit.Quantity(coords.reshape(self.natoms, 3), angstrom) self.simulation.context.setPositions(coordinates) # attach units to coordinates before computing energy self.simulation.context.setPositions(coordinates) potE = self.simulation.context.getState( getEnergy=True).getPotentialEnergy() # remove units from potE and then convert to kcal/mol to be consistent with GMIN ee = potE / kilojoules_per_mole / self.kJtokCal return float(ee) # ''' ------------------------------------------------------------------- ''' def getEnergyGradient(self, coords): """ returns energy and gradient in kcal/mol and kcal/mol/angstrom""" coordinates = unit.Quantity(coords.reshape(self.natoms, 3), angstrom) self.simulation.context.setPositions(coordinates) # get pot energy potE = self.simulation.context.getState( getEnergy=True).getPotentialEnergy() E = potE / kilojoules_per_mole / self.kJtokCal # get forces forcee = self.simulation.context.getState(getForces=True).getForces( asNumpy=True) # xply to -1 to convert gradient ; divide by 10 to convert to kJ/mol/angstroms grad = -forcee / (kilojoules_per_mole / nanometer ) / 10 / self.kJtokCal # todo - 10 is hardcoded # remove units before returning grad = np.array(grad, dtype=float) return float(E), grad.reshape(-1)
class OpenMMAmberPotential(BasePotential): """ OpenMM V(r) = Amber """ def __init__(self, prmtopFname, inpcrdFname ): # prmtopFname, inpcrdFname ): self.prmtop = AmberPrmtopFile( prmtopFname ) self.inpcrd = AmberInpcrdFile( inpcrdFname ) # number of atoms self.natoms = self.prmtop.topology._numAtoms # todo: set up ff and simulation object self.system = self.prmtop.createSystem(nonbondedMethod=openmmff.NoCutoff ) # no cutoff self.integrator = VerletIntegrator(0.001*picosecond) self.simulation = Simulation(self.prmtop.topology, self.system , self.integrator) # Another way of setting up potential using just pdb file ( no prmtop ) #pdb = PDBFile('coords.pdb') #forcefield = ForceField('amber99sb.xml', 'tip3p.xml') #system = forcefield.createSystem(pdb.topology, nonbondedMethod=ff.NoCutoff) #integrator = VerletIntegrator(0.001*picoseconds) #simulation = Simulation(pdb.topology, system, integrator) #simulation.context.setPositions(pdb.positions) # remove units self.localCoords = self.inpcrd.positions/angstrom self.kJtokCal = kilocalories_per_mole/kilojoules_per_mole # ''' ------------------------------------------------------------------- ''' def copyToLocalCoords(self, coords): """ copy to local coords -- deprecated """ # copy to local coords for i in range(self.natoms): self.localCoords[i] = Vec3(coords[3*i], coords[3*i+1] , coords[3*i+2] ) # ''' ------------------------------------------------------------------- ''' def getEnergy(self, coords): """ returns energy in kcal/mol """ # using unit.Quantity is 5 times faster than calling copyToLocalCoords! coordinates = unit.Quantity( coords.reshape(self.natoms,3) , angstrom) self.simulation.context.setPositions( coordinates ) # attach units to coordinates before computing energy self.simulation.context.setPositions(coordinates) potE = self.simulation.context.getState(getEnergy=True).getPotentialEnergy() # remove units from potE and then convert to kcal/mol to be consistent with GMIN return potE / kilojoules_per_mole / self.kJtokCal #''' ------------------------------------------------------------------- ''' def getEnergyGradient(self, coords): """ returns energy and gradient in kcal/mol and kcal/mol/angstrom""" coordinates = unit.Quantity( coords.reshape(self.natoms,3) , angstrom) self.simulation.context.setPositions( coordinates ) # get pot energy potE = self.simulation.context.getState(getEnergy=True).getPotentialEnergy() E = potE / kilojoules_per_mole /self.kJtokCal # get forces forcee = self.simulation.context.getState(getForces=True).getForces(asNumpy=True) # xply to -1 to convert gradient ; divide by 10 to convert to kJ/mol/angstroms grad = -forcee / ( kilojoules_per_mole / nanometer ) / 10 / self.kJtokCal # todo - 10 is hardcoded # remove units before returning return E, grad.reshape(-1)
from simtk.openmm import unit, version, Context, MonteCarloBarostat, XmlSerializer from simtk.openmm.app import PDBFile, PME, Simulation, StateDataReporter, HBonds, AmberPrmtopFile, AmberInpcrdFile from mdtraj.reporters import NetCDFReporter # set up basic parameters experiment = 'p18_CDK6_hcyclinD_CRBN' receptor = 'CDK6' ligand = '03123' trial = 0 work_dir = f'/home/guoj1/data_projects/BSJ_inhibitors/fresh_simulations/{experiment}/h_{ligand}_long{trial}' temperature = 400.15 * unit.kelvin pressure = 1.0 * unit.atmospheres steps = 250000000 ## 1000 ns # load prm or crd files of the minimized and equilibrated protein prmtop = AmberPrmtopFile(f'../03123_long0/complex_prep/02.ante.tleap/{ligand}_{receptor}.com.wat.leap.prmtop') pdb = PDBFile(f'../03123_long0/{ligand}_{receptor}_holo_equi.pdb') print("OpenMM version:", version.version) # use heavy hydrogens and constrain all hygrogen atom-involved bonds system = prmtop.createSystem(nonbondedMethod=PME, rigidWater=True, nonbondedCutoff=1 * unit.nanometer, constraints = HBonds, removeCMMotion=False, hydrogenMass= 4 * unit.amu) system.addForce(MonteCarloBarostat(pressure, temperature)) # Set up the context for unbiased simulation integrator = mm.LangevinIntegrator(temperature, 1.0, 0.004) ## 4 fs time steps integrator.setRandomNumberSeed(trial) print(f"Random seed of this run is: {integrator.getRandomNumberSeed()}") platform = mm.Platform.getPlatformByName('OpenCL') print("Done specifying integrator and platform for simulation.") platform.setPropertyDefaultValue('Precision', 'mixed') print("Done setting the precision to mixed.")
import os import pandas as pd import matplotlib.pyplot as plt import simtk.unit as unit from MDAnalysis.coordinates.DCD import DCDFile from simtk.openmm.app import PDBFile from simtk.openmm import XmlSerializer from simtk.openmm.app import AmberPrmtopFile, Topology from simtk import openmm # Load system.xml with open("system.xml", "r") as f: system = XmlSerializer.deserialize(f.read()) prmtop = AmberPrmtopFile('MGLab8-MCH.prmtop') dt = 2.0 * unit.femtoseconds Temp = 298.15 * unit.kelvin Pres = 1.01325 * unit.bar integrator = openmm.LangevinIntegrator(Temp, 1.0 / unit.picoseconds, dt) barostat = openmm.MonteCarloBarostat(Pres, Temp, 100) system.addForce(barostat) # Create Simulation Object simulation = openmm.app.Simulation(prmtop.topology, system, integrator, openmm.Platform.getPlatformByName('CUDA')) # Extract Collective variables from trajectory colvars_list = [] with DCDFile("MD-Equil.dcd") as dcd: header = dcd.header for frame in dcd.readframes()[0]: