def get_base(positions_old, positions): pos = positions vec_a = (positions[len(positions_old)+11]-positions[len(positions_old)+9]) x, y, z = vec_a.value_in_unit(unit.angstroms) x, y, z = np.array([x,y,z])/np.linalg.norm(np.array([x,y,z])) shift_forward = mm.Vec3(0,0,0)*unit.angstroms-positions[len(positions_old)+11] phi_2 = np.random.uniform(-np.math.pi/2,np.math.pi/2) s = np.math.sin(phi_2) c = np.math.cos(phi_2) rot = np.array([[2*(np.power(x,2)-1)*np.power(s,2)+1, 2*x*y*np.power(s,2)-2*z*c*s, 2*x*z*np.power(s,2)+2*y*c*s], [2*x*y*np.power(s,2)+2*z*c*s, 2*(np.power(y,2)-1)*np.power(s,2)+1, 2*z*y*np.power(s,2)-2*x*c*s], [2*x*z*np.power(s,2)-2*y*c*s, 2*z*y*np.power(s,2)+2*x*c*s, 2*(np.power(z,2)-1)*np.power(s,2)+1]]) end = 0 #print(len(positions)-len(positions_old)) if len(positions)-len(positions_old) == 30: end = len(positions_old)+24 elif len(positions)-len(positions_old) == 32: end = len(positions_old)+26 elif len(positions)-len(positions_old) == 33: end = len(positions_old)+27 for j in range(len(positions_old)+11,end-1): pos[j] += shift_forward for j in range(len(positions_old)+11,end-1): #pos[j] += drift roted = np.dot(np.array(pos[j].value_in_unit(unit.angstrom)),rot) pos[j] = mm.Vec3(roted[0],roted[1],roted[2])*unit.angstrom pos[j] -= shift_forward positions_new = pos return positions_new
def __init__(self, force_field='amber03', water=None, box_length=25*unit.angstroms): pdb = app.PDBFile(os.path.join(ufedmm.__path__[0], 'data', 'alanine-dipeptide.pdb')) if water is None: force_field = app.ForceField(f'{force_field}.xml') self.topology = pdb.topology self.positions = pdb.positions L = box_length.value_in_unit(unit.nanometers) vectors = [openmm.Vec3(L, 0, 0), openmm.Vec3(0, L, 0), openmm.Vec3(0, 0, L)] self.topology.setPeriodicBoxVectors(vectors) else: force_field = app.ForceField(f'{force_field}.xml', f'{water}.xml') modeller = app.Modeller(pdb.topology, pdb.positions) modeller.addSolvent(force_field, model=water, boxSize=box_length*openmm.Vec3(1, 1, 1)) self.topology = modeller.topology self.positions = modeller.positions self.system = force_field.createSystem( self.topology, nonbondedMethod=app.NoCutoff if water is None else app.PME, constraints=app.HBonds, rigidWater=True, removeCMMotion=False, ) atoms = [(a.name, a.residue.name) for a in self.topology.atoms()] phi_atoms = [('C', 'ACE'), ('N', 'ALA'), ('CA', 'ALA'), ('C', 'ALA')] self.phi = openmm.CustomTorsionForce('theta') self.phi.addTorsion(*[atoms.index(i) for i in phi_atoms], []) psi_atoms = [('N', 'ALA'), ('CA', 'ALA'), ('C', 'ALA'), ('N', 'NME')] self.psi = openmm.CustomTorsionForce('theta') self.psi.addTorsion(*[atoms.index(i) for i in psi_atoms], [])
def setPeriodicBoxVectors(self, a, b, c): """ Set the vectors defining the axes of the periodic box. .. warning:: Only orthorhombic boxes are allowed. Parameters ---------- a : openmm.Vec3 The vector defining the first edge of the periodic box. b : openmm.Vec3 The vector defining the second edge of the periodic box. c : openmm.Vec3 The vector defining the third edge of the periodic box. """ a = openmm.Vec3(*map(_standardized, a)) b = openmm.Vec3(*map(_standardized, b)) c = openmm.Vec3(*map(_standardized, c)) if not (a.y == a.z == b.x == b.z == c.x == c.y == 0.0): raise ValueError('Only orthorhombic boxes are allowed') self.setParameter('Lx', a.x) super().setPeriodicBoxVectors(a, b, c) system = self.getSystem() ntotal = system.getNumParticles() nvars = len(self.variables) for i, v in enumerate(self.variables): system.setParticleMass(ntotal - nvars + i, v._particle_mass(a.x)) self.reinitialize(preserveState=True)
def _createTopology(self): """Build the topology of the system """ top = Topology() positions = [] velocities = [] boxVectors = [] for x, y, z in self._conn.execute('SELECT x, y, z FROM global_cell'): boxVectors.append(mm.Vec3(x, y, z)) unitCellDimensions = [boxVectors[0][0], boxVectors[1][1], boxVectors[2][2]] top.setUnitCellDimensions(unitCellDimensions*angstrom) atoms = {} lastChain = None lastResId = None c = top.addChain() q = """SELECT id, name, anum, resname, resid, chain, x, y, z, vx, vy, vz FROM particle ORDER BY id""" for (atomId, atomName, atomNumber, resName, resId, chain, x, y, z, vx, vy, vz) in self._conn.execute(q): newChain = False if chain != lastChain: lastChain = chain c = top.addChain() newChain = True if resId != lastResId or newChain: lastResId = resId if resName in PDBFile._residueNameReplacements: resName = PDBFile._residueNameReplacements[resName] r = top.addResidue(resName, c) if resName in PDBFile._atomNameReplacements: atomReplacements = PDBFile._atomNameReplacements[resName] else: atomReplacements = {} if atomNumber == 0 and atomName.startswith('Vrt'): elem = None else: elem = Element.getByAtomicNumber(atomNumber) if atomName in atomReplacements: atomName = atomReplacements[atomName] atoms[atomId] = top.addAtom(atomName, elem, r) positions.append(mm.Vec3(x, y, z)) velocities.append(mm.Vec3(vx, vy, vz)) for p0, p1 in self._conn.execute('SELECT p0, p1 FROM bond'): top.addBond(atoms[p0], atoms[p1]) positions = positions*angstrom velocities = velocities*angstrom/femtosecond return top, positions, velocities
def make_harmonic_system(n_particles, force_constant): """System with one harmonic oscillator.""" system = mm.System() harmonic = mm.CustomExternalForce("0.5 * force_constant * (x-0.5)^2") harmonic.addGlobalParameter("force_constant", force_constant) system.setDefaultPeriodicBoxVectors(mm.Vec3(1, 0, 0), mm.Vec3(0, 1, 0), mm.Vec3(0, 0, 1)) for i in range(n_particles): system.addParticle(1.0) harmonic.addParticle(i) system.addForce(harmonic) return system
def stratified_sample(topology, coordinates, variances, Nsteps, index, box=50, rang=[0,400]): aptamer_top = topology aptamer_crd = coordinates en = [] xyz = [] cnt = 0 for i in range(Nsteps): pos = aptamer_crd.positions pos0 = aptamer_crd.positions[(rang[1]-rang[0])/2] shift = [0,0,0] shift[0], shift[1], shift[2], x, y, z, phi_2 = uniform_strat(variances[0],variances[1],variances[2],variances[3],variances[4],variances[5],variances[6],[-box,box],[-np.math.pi,np.math.pi]) x, y, z = np.array([x,y,z])*1/(np.linalg.norm(np.array([x,y,z]))) xyz.append([shift[0], shift[1], shift[2], x, y, z, phi_2]) shift = mm.Vec3(*shift)*unit.angstroms s = np.math.sin(phi_2) c = np.math.cos(phi_2) rot = np.array([[2*(np.power(x,2)-1)*np.power(s,2)+1, 2*x*y*np.power(s,2)-2*z*c*s, 2*x*z*np.power(s,2)+2*y*c*s], [2*x*y*np.power(s,2)+2*z*c*s, 2*(np.power(y,2)-1)*np.power(s,2)+1, 2*z*y*np.power(s,2)-2*x*c*s], [2*x*z*np.power(s,2)-2*y*c*s, 2*z*y*np.power(s,2)+2*x*c*s, 2*(np.power(z,2)-1)*np.power(s,2)+1]]) #print(rot) drift = get_aptamer(get_ligand_range(aptamer_top.topology), aptamer_crd.positions)[10] for j in range(get_ligand_range(aptamer_top.topology)[1],len(pos)): pos[j] -= drift for j in range(0,get_ligand_range(aptamer_top.topology)[1]): pos[j] -= pos0 #pos[126] += drift for j in range(get_ligand_range(aptamer_top.topology)[1],len(pos)): #pos[j] += drift roted = np.dot(np.array(pos[j].value_in_unit(unit.angstrom)),rot) pos[j] = mm.Vec3(roted[0],roted[1],roted[2])*unit.angstrom pos[j] += shift simulation.context.setPositions(pos) #print("minimizing ...") #simulation.minimizeEnergy() state = simulation.context.getState(getPositions=True,getEnergy=True,groups=1) #print("getting positions ...") #fil = open("montetest%s.pdb"%i,"w") #app.PDBFile.writeModel(aptamer_top.topology,pos,file=fil,modelIndex=i) #fil.close() #del fil #simulation.step(1) free_E = state.getPotentialEnergy().value_in_unit(unit.kilojoules_per_mole) en.append(free_E) #monte_pos.append(shift) if free_E < free_E_old: free_E_old = free_E cnt += 1 positions = pos return en, pos, xyz, free_E, index
def step(self, nstep): niter = int(nstep / self.barofreq) for i in range(niter): self.simeq.step(self.barofreq) self.ntrials += 1 statebak = self.simeq.context.getState(getEnergy=True, getPositions=True) oldE = statebak.getPotentialEnergy() oldpos = statebak.getPositions() newpos0 = np.asarray(oldpos.value_in_unit(unit.nanometer)) newpos = np.asarray(oldpos.value_in_unit(unit.nanometer)) boxvec = statebak.getPeriodicBoxVectors() oldboxlen = boxvec[2][2] deltalen = self.lenscale * (random.uniform(0, 1) * 2. - 1) newboxlen = oldboxlen + deltalen for i in range(self.numres): fidx = self.resFirstAtomIdxs[i] lidx = self.resFirstAtomIdxs[i] + self.resNumAtoms[i] if self.resmass[i] == 0 * unit.dalton: newpos[fidx:lidx, 2] += 0.5 * deltalen / unit.nanometer else: newpos[fidx, 2] *= newboxlen / oldboxlen posdel = newpos[fidx, 2] - newpos0[fidx, 2] newpos[fidx + 1:lidx, 2] += posdel self.simeq.context.setPositions(newpos) self.simeq.context.setPeriodicBoxVectors( boxvec[0], boxvec[1], mm.Vec3(0, 0, newboxlen / unit.nanometer) * unit.nanometer) statenew = self.simeq.context.getState(getEnergy=True, getPositions=True) newE = statenew.getPotentialEnergy() w = newE - oldE + self.pressure * deltalen - self.numRealRes * self.RT * np.log( newboxlen / oldboxlen) if self.metropolis(w): self.naccept += 1 print('newE: ' + str(newE) + 'oldE: ' + str(oldE)) else: self.simeq.context.setPositions(oldpos) self.simeq.context.setPeriodicBoxVectors( boxvec[0], boxvec[1], mm.Vec3(0, 0, oldboxlen / unit.nanometer) * unit.nanometer) if self.ntrials >= 10: if (self.naccept < 0.25 * self.ntrials): self.lenscale /= 1.1 self.ntrials = 0 self.naccept = 0 elif self.naccept > 0.75 * self.ntrials: self.lenscale = min(self.lenscale * 1.1, newboxlen * 0.3) self.ntrials = 0 self.naccept = 0
def volumnmove(self,test_reporter): self.ntrials += 1 statebak = self.simeq.context.getState(getEnergy=True, getPositions=True) oldE = statebak.getPotentialEnergy() oldpos = statebak.getPositions() newpos0 = np.asarray(oldpos.value_in_unit(unit.nanometer)) newpos = np.asarray(oldpos.value_in_unit(unit.nanometer)) boxvec = statebak.getPeriodicBoxVectors() oldboxlen = boxvec[2][2] deltalen = self.lenscale*(random.uniform(0, 1) * 2 - 1) newboxlen = oldboxlen + deltalen newpos[self.firstidx:self.secondidx, 2] += 0.5 * deltalen / unit.nanometer newpos[self.secondidx:, 2] *= newboxlen / oldboxlen self.simeq.context.setPositions(newpos) self.simeq.context.setPeriodicBoxVectors(boxvec[0], boxvec[1], mm.Vec3(0, 0, newboxlen / unit.nanometer) * unit.nanometer) statenew = self.simeq.context.getState(getEnergy=True,getPositions=True) newE = statenew.getPotentialEnergy() w = newE-oldE + self.pressure*deltalen - self.numres * self.RT*np.log(newboxlen/oldboxlen) # for i in range(100): # try: # f = self.simeq.system.getForce(i) # print(type(f), str(self.simeq.context.getState(getEnergy=True, groups=2**i).getPotentialEnergy())) # print() # except: # pass test_reporter.report(self.simeq, statenew) print("Accept ratio for volumnmove", self.getAcceptRatio()) if self.metropolis(w): self.naccept += 1 # print('newE:', str(newE), 'oldE:', str(oldE)) else: self.simeq.context.setPositions(oldpos) self.simeq.context.setPeriodicBoxVectors(boxvec[0], boxvec[1], mm.Vec3(0, 0, oldboxlen / unit.nanometer) * unit.nanometer) if self.ntrials >= 10: if (self.naccept < 0.25*self.ntrials) : self.lenscale /= 1.1 self.ntrials = 0 self.naccept = 0 elif self.naccept > 0.75*self.ntrials : self.lenscale = min(self.lenscale*1.1, newboxlen*0.3) self.ntrials = 0 self.naccept = 0
def rotate_global(self, element, axis, angle, reverse=False, glob=True): if self.positions: x, y, z = np.asarray(nostrom(axis)) / (np.linalg.norm( np.asarray(nostrom(axis)))) phi_2 = angle / 2. pos = self.positions[:] starting_index = 1 if glob: starting_index = 0 ##print(element) if reverse: shift_forward = mm.Vec3(0, 0, 0) * unit.angstroms - pos[element[2]] else: shift_forward = mm.Vec3( 0, 0, 0) * unit.angstroms - pos[element[starting_index]] s = np.math.sin(phi_2) c = np.math.cos(phi_2) rot = np.array([[ 2 * (np.power(x, 2) - 1) * np.power(s, 2) + 1, 2 * x * y * np.power(s, 2) - 2 * z * c * s, 2 * x * z * np.power(s, 2) + 2 * y * c * s ], [ 2 * x * y * np.power(s, 2) + 2 * z * c * s, 2 * (np.power(y, 2) - 1) * np.power(s, 2) + 1, 2 * z * y * np.power(s, 2) - 2 * x * c * s ], [ 2 * x * z * np.power(s, 2) - 2 * y * c * s, 2 * z * y * np.power(s, 2) + 2 * x * c * s, 2 * (np.power(z, 2) - 1) * np.power(s, 2) + 1 ]]) for j in range(element[starting_index], element[2]): pos[j] += shift_forward for j in range(element[starting_index], element[2]): roted = np.dot(np.array(pos[j].value_in_unit(unit.angstrom)), rot) pos[j] = mm.Vec3(roted[0], roted[1], roted[2]) * unit.angstrom pos[j] -= shift_forward positions_new = pos self.positions = positions_new[:] else: raise ValueError( 'This Complex contains no positions! You CANNOT rotate!')
def test_radius_of_gyration(): model = ufedmm.AlanineDipeptideModel() R = model.positions._value N = len(R) Rmean = sum(R, openmm.Vec3(0, 0, 0)) / N RgSqVal = 0.0 for r in R: dr = r - Rmean RgSqVal += dr.x**2 + dr.y**2 + dr.z**2 RgSqVal /= N RgSq = cvlib.SquareRadiusOfGyration(range(model.topology._numAtoms)) RgSq.setForceGroup(1) model.system.addForce(RgSq) Rg = cvlib.RadiusOfGyration(range(model.topology._numAtoms)) Rg.setForceGroup(2) model.system.addForce(Rg) integrator = openmm.CustomIntegrator(0) platform = openmm.Platform.getPlatformByName('Reference') context = openmm.Context(model.system, integrator, platform) context.setPositions(model.positions) RgSq = context.getState(getEnergy=True, groups={1}).getPotentialEnergy()._value assert RgSq == pytest.approx(RgSqVal) Rg = context.getState(getEnergy=True, groups={2}).getPotentialEnergy()._value assert Rg * Rg == pytest.approx(RgSqVal)
def _compute_forces(self, ufed, dataframe): collective_variables = [ colvar.id for v in ufed.variables for colvar in v.colvars ] extended_variables = [v.id for v in ufed.variables] all_variables = collective_variables + extended_variables force = openmm.CustomCVForce(_get_energy_function(ufed.variables)) for key, value in _get_parameters(ufed.variables).items(): force.addGlobalParameter(key, value) for variable in all_variables: force.addGlobalParameter(variable, 0) for xv in extended_variables: force.addEnergyParameterDerivative(xv) system = openmm.System() system.addForce(force) system.addParticle(0) platform = openmm.Platform.getPlatformByName('Reference') context = openmm.Context(system, openmm.CustomIntegrator(0), platform) context.setPositions([openmm.Vec3(0, 0, 0)]) n = len(dataframe.index) forces = [np.empty(n) for xv in extended_variables] for j, row in dataframe.iterrows(): for variable in all_variables: context.setParameter(variable, row[variable]) state = context.getState(getParameterDerivatives=True) derivatives = state.getEnergyParameterDerivatives() for i, xv in enumerate(extended_variables): forces[i][j] = -derivatives[xv] return forces
def solvate(system, forcefield, box_size=9.0, boxtype='cubic', padding=None, ionicStrength=0*molar): """ Generation of box parameters and solvation. Parameters ---------- system : TYPE DESCRIPTION. boxtype : str, optional Box type, either 'cubic' or 'rectangular'. The default is 'cubic'. box_padding : float, optional Box padding. The default is 1.0. Returns ------- None. """ # add box vectors and solvate #TODO: Allow other box definitions. Use method padding to get prot sized+padding distance system.addSolvent(forcefield, model='tip4pew', neutralize=True, ionicStrength=ionicStrength, #0.1 M for SETD2 padding=None, boxSize=omm.Vec3(box_size, box_size, box_size)) return system
def _addMissingResiduesToChain(self, chain, residueNames, startPosition, endPosition, orientTo, newAtoms, newPositions): """Add a series of residues to a chain.""" orientToPositions = dict((atom.name, self.positions[atom.index]) for atom in orientTo.atoms()) for i, residueName in enumerate(residueNames): template = self.templates[residueName] # Find a translation that best matches the adjacent residue. points1 = [] points2 = [] for atom in template.topology.atoms(): if atom.name in orientToPositions: points1.append(orientToPositions[atom.name].value_in_unit(unit.nanometer)) points2.append(template.positions[atom.index].value_in_unit(unit.nanometer)) (translate2, rotate, translate1) = _overlayPoints(points1, points2) # Create the new residue. newResidue = chain.topology.addResidue(residueName, chain) translate = startPosition+(endPosition-startPosition)*(i+1.0)/(len(residueNames)+1.0) templateAtoms = list(template.topology.atoms()) if newResidue == next(chain.residues()): templateAtoms = [atom for atom in templateAtoms if atom.name not in ('P', 'OP1', 'OP2')] for atom in templateAtoms: newAtom = chain.topology.addAtom(atom.name, atom.element, newResidue) newAtoms.append(newAtom) templatePosition = template.positions[atom.index].value_in_unit(unit.nanometer) newPositions.append(mm.Vec3(*np.dot(rotate, templatePosition))*unit.nanometer+translate)
def convert_spce_to_cs(file, saveas="newpdb.pdb"): """Extract and rename oxygens from all-atom water structure""" import os import numpy as np import simtk.unit as unit import simtk.openmm as omm import simtk.openmm.app as app file = "equil_spc.pdb" saveas = "justO_spc.pdb" app.element.solvent = app.element.Element(201, "Solvent", "Sv", 18 * unit.amu) pdb = app.PDBFile(file) O_idxs = np.array( [atm.index for atm in pdb.topology.atoms() if atm.name == "O"]) xyz = np.array(pdb.positions / unit.angstrom)[O_idxs] positions = unit.Quantity(xyz, unit.angstrom) n_slv = len(O_idxs) topology = app.Topology() chain = topology.addChain() for i in range(n_slv): res = topology.addResidue("SLV", chain) topology.addAtom("CS", app.element.get_by_symbol("Sv"), res) box_edge = 5.96256971 * unit.nanometer topology.setUnitCellDimensions(box_edge * omm.Vec3(1, 1, 1)) with open(saveas, "w") as fout: pdb.writeFile(topology, positions, file=fout)
def update_temperatures(self, system_temperature, extended_space_temperatures): super().update_temperatures(system_temperature, extended_space_temperatures) kT_vectors = self.getPerDofVariableByName('kT') tauSq = _standardized(self._tau)**2 Q = [tauSq*kT for kT in kT_vectors] invQ = [openmm.Vec3(*map(lambda x: 1/x if x > 0.0 else 0.0, q)) for q in Q] self.setPerDofVariableByName('invQ', invQ)
def _add_dummy_to_PDB(self, input_pdb, output_pdb, offset_coordinates, dummy_atom_tuples): input_pdb_file = openmm.app.PDBFile(input_pdb) positions = input_pdb_file.positions # When we pass in a guest, we have multiple coordinates and the function expects to address the first guest # atom coordinates. # When we pass in the center of mass of the host, we'll only have one set of coordinates. if len(np.shape(offset_coordinates)) < 2: offset_coordinates = [ offset_coordinates, ] for index, dummy_atom_tuple in enumerate(dummy_atom_tuples): positions.append( openmm.Vec3( offset_coordinates[0][0] + dummy_atom_tuple[0], offset_coordinates[0][1] + dummy_atom_tuple[1], offset_coordinates[0][2] + dummy_atom_tuple[2], ) * unit.angstrom) topology = input_pdb_file.topology for dummy_index in range(len(dummy_atom_tuples)): dummy_chain = topology.addChain(None) dummy_residue = topology.addResidue(f"DM{dummy_index + 1}", dummy_chain) topology.addAtom(f"DUM", None, dummy_residue) with open(output_pdb, "w") as file: openmm.app.PDBFile.writeFile(topology, positions, file)
def loadPosFile(path, systemName): filename = path + systemName + '.pos' while (not os.path.exists(filename)) and '_' in systemName: systemName = systemName[:systemName.rfind('_')] filename = path + systemName + '.pos' fpos = open(filename) # The first line of the .pos file should contain the number of positions. Sometimes # the word 'Positions' is first and the number is second, sometimes the number is first # and the word 'Positions' is second. firstLine = fpos.readline() firstLineList = firstLine.split() if firstLineList[1] != 'Positions' and firstLineList[0] != 'Positions': print "Error; the first line of the .pos file should contain the number of particles." sys.exit(1) if firstLineList[1] == 'Positions': numParticles = int(firstLineList[0]) else: numParticles = int(firstLineList[1]) # read the remaining lines from the .pos file and parse the positions into the correct # data structure positions = [None] * numParticles remainingLines = fpos.readlines() for line in remainingLines: lineSplit = line.split() index = int(lineSplit[0]) pos1 = float(lineSplit[1]) pos2 = float(lineSplit[2]) pos3 = float(lineSplit[3]) positions[index] = mm.Vec3(pos1, pos2, pos3) * unit.nanometer return positions
def setPositions(self, positions, extended_positions=None): """ Sets the positions of all particles and extended-space variables in this context. If the latter are not provided, then suitable values are automatically determined from the particle positions. Parameters ---------- positions : list of openmm.Vec3 The positions of physical particles. Keyword Args ------------ extended_positions : list of float or unit.Quantity The positions of extended-space particles. """ a, b, _ = self.getState().getPeriodicBoxVectors() nvars = len(self.variables) particle_positions = _standardized(positions) if extended_positions is None: extra_positions = [openmm.Vec3(0, b.y*(i + 1)/(nvars + 2), 0) for i in range(nvars)] minisystem = openmm.System() expression = _get_energy_function(self.variables) for i, v in enumerate(self.variables): expression += f'; {v.id}={v._get_energy_function(index=i+1)}' force = openmm.CustomCompoundBondForce(nvars, expression) force.addBond(range(nvars), []) for name, value in _get_parameters(self.variables).items(): force.addGlobalParameter(name, value) force.addGlobalParameter('Lx', a.x) for v in self.variables: minisystem.addParticle(v._particle_mass(a.x)) for cv in v.colvars: value = cv.evaluate(self.getSystem(), particle_positions + extra_positions) force.addGlobalParameter(cv.id, value) minisystem.addForce(force) minicontext = openmm.Context(minisystem, openmm.CustomIntegrator(0), openmm.Platform.getPlatformByName('Reference')) minicontext.setPositions(extra_positions) openmm.LocalEnergyMinimizer.minimize(minicontext, 1*unit.kilojoules_per_mole, 0) ministate = minicontext.getState(getPositions=True) extra_positions = ministate.getPositions().value_in_unit(unit.nanometers) else: extra_positions = [openmm.Vec3(x, b.y*(i + 1)/(nvars + 2), 0) for i, x in enumerate(extended_positions)] super().setPositions(particle_positions + extra_positions)
def _overlayPoints(points1, points2): """Given two sets of points, determine the translation and rotation that matches them as closely as possible. Parameters ---------- points1 (numpy array of simtk.unit.Quantity with units compatible with distance) - reference set of coordinates points2 (numpy array of simtk.unit.Quantity with units compatible with distance) - set of coordinates to be rotated Returns ------- translate2 - vector to translate points2 by in order to center it rotate - rotation matrix to apply to centered points2 to map it on to points1 center1 - center of points1 Notes ----- This is based on W. Kabsch, Acta Cryst., A34, pp. 828-829 (1978). """ if len(points1) == 0: return (mm.Vec3(0, 0, 0), np.identity(3), mm.Vec3(0, 0, 0)) if len(points1) == 1: return (points1[0], np.identity(3), -1*points2[0]) # Compute centroids. center1 = unit.sum(points1)/float(len(points1)) center2 = unit.sum(points2)/float(len(points2)) # Compute R matrix. R = np.zeros((3, 3)) for p1, p2 in zip(points1, points2): x = p1-center1 y = p2-center2 for i in range(3): for j in range(3): R[i][j] += y[i]*x[j] # Use an SVD to compute the rotation matrix. (u, s, v) = lin.svd(R) return (-1*center2, np.dot(u, v).transpose(), center1)
def test_dcd(self): """ Test the DCD file """ fname = tempfile.mktemp(suffix='.dcd') pdbfile = app.PDBFile('systems/alanine-dipeptide-implicit.pdb') natom = len(list(pdbfile.topology.atoms())) with open(fname, 'wb') as f: dcd = app.DCDFile(f, pdbfile.topology, 0.001) for i in range(5): dcd.writeModel([mm.Vec3(random(), random(), random()) for j in range(natom)]*unit.angstroms) os.remove(fname)
def testLongTrajectory(self): """Test writing a trajectory that has more than 2^31 steps.""" fname = tempfile.mktemp(suffix='.dcd') pdbfile = app.PDBFile('systems/alanine-dipeptide-implicit.pdb') natom = len(list(pdbfile.topology.atoms())) with open(fname, 'wb') as f: dcd = app.DCDFile(f, pdbfile.topology, 0.001, interval=1000000000) for i in range(5): dcd.writeModel([mm.Vec3(random(), random(), random()) for j in range(natom)]*unit.angstroms) os.remove(fname)
def CustomLangevinIntegrator(temperature=298.0*u.kelvin, collision_rate=91.0/u.picoseconds, timestep=1.0*u.femtoseconds): # Compute constants. kT = kB * temperature gamma = collision_rate # Create a new custom integrator. integrator = mm.CustomIntegrator(timestep) # # If dimensions == 2, set up a dummy variable to remove z-axial velocities # if dimensions == 2: integrator.addPerDofVariable("dumv", 1.0) integrator.setPerDofVariableByName("dumv", [mm.Vec3(x=1.0, y=1.0, z=0.0)]) # # Integrator initialization. # integrator.addComputePerDof("sigma", "sqrt(kT/m)") integrator.addGlobalVariable("kT", kT) # thermal energy integrator.addGlobalVariable("T", temperature) # temperature integrator.addGlobalVariable("b", np.exp(-gamma*timestep)) # velocity mixing parameter integrator.addPerDofVariable("sigma", 0) integrator.addPerDofVariable("x1", 0) # position before application of constraints # # Allow context updating here. # integrator.addUpdateContextState(); # # Velocity perturbation. # integrator.addComputePerDof("v", "sqrt(b)*v + sqrt(1-b)*sigma*gaussian") integrator.addConstrainVelocities(); # # Metropolized symplectic step. # integrator.addComputePerDof("v", "v + 0.5*dt*f/m") if dimensions == 2: # To get a 2D system, make z-velocities zero when moving x integrator.addComputePerDof("x", "x + v*dumv*dt") else: integrator.addComputePerDof("x", "x + v*dt") integrator.addComputePerDof("x1", "x") integrator.addComputePerDof("v", "v + 0.5*dt*f/m + (x-x1)/dt") # # Velocity randomization # integrator.addComputePerDof("v", "sqrt(b)*v + sqrt(1-b)*sigma*gaussian") if dimensions == 2: # Remove the resulting z-velocities to get the correct Kinetic Energy integrator.addComputePerDof("v", "v*dumv") return integrator
def step(self, steps): if self._uninitialized: ndof = self.getPerDofVariableByName('ndof') self._ndof = NDOF = 3 * len(ndof) self.setGlobalVariableByName('NDOF', NDOF) for i in range(len(ndof)): ndof[i] = openmm.Vec3(NDOF, NDOF, NDOF) self.setPerDofVariableByName('ndof', ndof) self.initialize() self._uninitialized = False return super().step(steps)
def setContextFromRst(simulation, inpcrd): """ Restore the simulation's context from all the information present in an AMBER rst7 file. """ simulation.context.setPositions(inpcrd.positions) simulation.context.setVelocities(inpcrd.velocities) x = mm.Vec3(inpcrd.getBoxVectors()[0][0].value_in_unit(u.nanometers), inpcrd.getBoxVectors()[0][1].value_in_unit(u.nanometers), inpcrd.getBoxVectors()[0][2].value_in_unit(u.nanometers)) y = mm.Vec3(inpcrd.getBoxVectors()[1][0].value_in_unit(u.nanometers), inpcrd.getBoxVectors()[1][1].value_in_unit(u.nanometers), inpcrd.getBoxVectors()[1][2].value_in_unit(u.nanometers)) z = mm.Vec3(inpcrd.getBoxVectors()[2][0].value_in_unit(u.nanometers), inpcrd.getBoxVectors()[2][1].value_in_unit(u.nanometers), inpcrd.getBoxVectors()[2][2].value_in_unit(u.nanometers)) simulation.context.setPeriodicBoxVectors(x,y,z)
def translate_global(self, element, shift): if self.positions: vec_shift = mm.Vec3(*shift)*unit.angstroms pos = self.positions[:] for j in range(element[0],element[2]): pos[j] += vec_shift positions_new = pos self.positions = positions_new[:] else: raise ValueError('This Complex contains no positions! You CANNOT translate!')
def make_xml_explicit_imidazole( pdb_filename="protons/examples/Ligand example/imidazole.pdb", ffxml_filename="protons/examples/Ligand example/imidazole.xml", outfile="imidazole-explicit", ): """Solvate an imidazole pdb file and minimize the system""" temperature = 300.0 * unit.kelvin pressure = 1.0 * unit.atmospheres outfile1 = open("{}.sys.xml".format(outfile), "w") outfile2 = open("{}.state.xml".format(outfile), "w") gaff = get_data("gaff.xml", "forcefields") pdb = app.PDBFile(pdb_filename) forcefield = app.ForceField(gaff, ffxml_filename, "amber99sbildn.xml", "tip3p.xml") integrator = openmm.LangevinIntegrator(300 * unit.kelvin, 1.0 / unit.picoseconds, 2.0 * unit.femtoseconds) integrator.setConstraintTolerance(0.00001) modeller = app.Modeller(pdb.topology, pdb.positions) modeller.addSolvent( forcefield, boxSize=openmm.Vec3(3.5, 3.5, 3.5) * unit.nanometers, model="tip3p", ionicStrength=0.1 * unit.molar, positiveIon="Na+", negativeIon="Cl-", ) system = forcefield.createSystem( modeller.topology, nonbondedMethod=app.PME, nonbondedCutoff=1.0 * unit.nanometers, constraints=app.HBonds, rigidWater=True, ewaldErrorTolerance=0.0005, ) system.addForce(openmm.MonteCarloBarostat(pressure, temperature)) simulation = app.Simulation(modeller.topology, system, integrator) simulation.context.setPositions(modeller.positions) simulation.minimizeEnergy() outfile1.write(openmm.XmlSerializer.serialize(simulation.system)) positions = simulation.context.getState(getPositions=True) outfile2.write(openmm.XmlSerializer.serialize(positions)) app.PDBFile.writeFile( simulation.topology, modeller.positions, open("imidazole-solvated-minimized.pdb", "w"), )
def testFreezeGraph(self): graph = tf.Graph() with graph.as_default(): positions = tf.placeholder(tf.float32, [None, 3], 'positions') scale = tf.Variable(5.0) energy = tf.multiply(scale, tf.reduce_sum(positions**2), name='energy') forces = tf.identity(tf.gradients(-energy, positions), name='forces') session = tf.Session() session.run(tf.global_variables_initializer()) force = nn.NeuralNetworkForce(graph, session) system = mm.System() for i in range(3): system.addParticle(1.0) system.addForce(force) integrator = mm.VerletIntegrator(0.001) context = mm.Context(system, integrator) positions = [mm.Vec3(3, 0, 0), mm.Vec3(0, 4, 0), mm.Vec3(3, 4, 0)] context.setPositions(positions) assert context.getState(getEnergy=True).getPotentialEnergy( ) == 250.0 * unit.kilojoules_per_mole
def report(self, simulation, state): """Generate a report. Parameters ---------- simulation : Simulation The Simulation to generate a report for state : State The current state of the simulation """ if self._dcd is None: self._dcd = DCDFile(self._out, simulation.topology, simulation.integrator.getStepSize(), 0, self._reportInterval) a,b,c = state.getPeriodicBoxVectors() self._dcd.writeModel(state.getPositions(), mm.Vec3(a[0].value_in_unit(nanometer), b[1].value_in_unit(nanometer), c[2].value_in_unit(nanometer))*nanometer)
def __init__(self, forceField='amber14-all', water=None, boxLength=25*unit.angstroms, bareSystem=False): pdb = app.PDBFile(os.path.join(afed.__path__[0], 'data', 'alanine-dipeptide.pdb')) if water is None: force_field = app.ForceField(f'{forceField}.xml') self._topology = pdb.topology self._positions = pdb.positions else: force_field = app.ForceField(f'{forceField}.xml', f'{water}.xml') modeller = app.Modeller(pdb.topology, pdb.positions) modeller.addSolvent(force_field, model=water, boxSize=boxLength*openmm.Vec3(1, 1, 1)) self._topology = modeller.topology self._positions = modeller.positions self._system = force_field.createSystem( self._topology, nonbondedMethod=app.NoCutoff if water is None else app.PME, constraints=None, rigidWater=False, removeCMMotion=False, ) if bareSystem: return atoms = [(a.name, a.residue.name) for a in self._topology.atoms()] psi_atoms = [('N', 'ALA'), ('CA', 'ALA'), ('C', 'ALA'), ('N', 'NME')] self._psi_angle = openmm.CustomTorsionForce('theta') self._psi_angle.addTorsion(*[atoms.index(i) for i in psi_atoms], []) phi_atoms = [('C', 'ACE'), ('N', 'ALA'), ('CA', 'ALA'), ('C', 'ALA')] self._phi_angle = openmm.CustomTorsionForce('theta') self._phi_angle.addTorsion(*[atoms.index(i) for i in phi_atoms], []) period = 360*unit.degrees self._psi = afed.DrivenCollectiveVariable('psi', self._psi_angle, unit.radians, period) self._phi = afed.DrivenCollectiveVariable('phi', self._phi_angle, unit.radians, period) value = 180*unit.degrees minval = -value maxval = value T = 1500*unit.kelvin mass = 168.0*unit.dalton*(unit.angstroms/unit.radian)**2 velocity_scale = unit.sqrt(unit.BOLTZMANN_CONSTANT_kB*unit.AVOGADRO_CONSTANT_NA*T/mass) self._psi_driver = afed.DriverParameter('psi_s', unit.radians, value, T, velocity_scale, minval, maxval, periodic=True) self._phi_driver = afed.DriverParameter('phi_s', unit.radians, value, T, velocity_scale, minval, maxval, periodic=True) self._driving_force = afed.HarmonicDrivingForce() K = 2.78E3*unit.kilocalories_per_mole/unit.radians**2 self._driving_force.addPair(self._psi, self._psi_driver, K) self._driving_force.addPair(self._phi, self._phi_driver, K) self._system.addForce(self._driving_force)
def get_backbone_restraint_force(topology, positions, explicit, K=5.0): if explicit: energy_expression = '(k_restr/2)*periodicdistance(x, y, z, x0, y0, z0)^2' # periodic distance else: energy_expression = '(k_restr/2)*((x-x0)^2 + (y-y0)^2 + (z-z0)^2)' # non-periodic distance force = mm.CustomExternalForce(energy_expression) force.addGlobalParameter("k_restr", K) force.addPerParticleParameter("x0") force.addPerParticleParameter("y0") force.addPerParticleParameter("z0") positions_ = positions.value_in_unit(unit.nanometer) for i, atom_id in enumerate(get_backbone_ids(topology)): pos = positions_[atom_id] pops = mm.Vec3(pos[0], pos[1], pos[2]) _ = force.addParticle(int(atom_id), pops) return force