def _topology_from_residue(res): """Converts a openmm.app.Topology.Residue to openmm.app.Topology. Parameters ---------- res : openmm.app.Topology.Residue An individual residue in an openmm.app.Topology Returns ------- topology : openmm.app.Topology The generated topology """ topology = app.Topology() chain = topology.addChain() new_res = topology.addResidue(res.name, chain) atoms = dict() # { omm.Atom in res : omm.Atom in *new* topology } for res_atom in res.atoms(): topology_atom = topology.addAtom(name=res_atom.name, element=res_atom.element, residue=new_res) atoms[res_atom] = topology_atom topology_atom.bond_partners = [] for bond in res.bonds(): atom1 = atoms[bond.atom1] atom2 = atoms[bond.atom2] topology.addBond(atom1, atom2) atom1.bond_partners.append(atom2) atom2.bond_partners.append(atom1) return topology
def build_water_system(box_width): ff = app.ForceField('tip3p.xml') # Create empty topology and coordinates. top = app.Topology() pos = unit.Quantity((), unit.angstroms) m = app.Modeller(top, pos) boxSize = Vec3(box_width, box_width, box_width)*unit.nanometers m.addSolvent(ff, boxSize=boxSize, model='tip3p') system = ff.createSystem( m.getTopology(), nonbondedMethod=app.NoCutoff, constraints=None, rigidWater=False ) positions = m.getPositions() positions = unit.Quantity(np.array(positions / positions.unit), positions.unit) assert m.getTopology().getNumAtoms() == positions.shape[0] # TODO: minimize the water box (BFGS or scipy.optimize) return system, positions, np.eye(3)*box_width, m.getTopology()
def _build_new_topology(current_receptor_topology, oemol_proposed): """ Construct a new topology Parameters ---------- oemol_proposed : oechem.OEMol object the proposed OEMol object current_receptor_topology : app.Topology object The current topology without the small molecule Returns ------- new_topology : app.Topology object A topology with the receptor and the proposed oemol mol_start_index : int The first index of the small molecule """ oemol_proposed.SetTitle("MOL") mol_topology = forcefield_generators.generateTopologyFromOEMol( oemol_proposed) new_topology = app.Topology() append_topology(new_topology, current_receptor_topology) append_topology(new_topology, mol_topology) # Copy periodic box vectors. if current_receptor_topology._periodicBoxVectors != None: new_topology._periodicBoxVectors = copy.deepcopy( current_receptor_topology._periodicBoxVectors) return new_topology
def _topology_from_parmed(structure, non_element_types): """Convert a ParmEd Structure to an OpenMM Topology. """ topology = app.Topology() chain = topology.addChain() residue = topology.addResidue(structure.title, chain) atoms = dict() # pmd.Atom: omm.Atom for pmd_atom in structure.atoms: name = pmd_atom.name if pmd_atom.element in non_element_types: element = non_element_types[pmd_atom.element] else: if (isinstance(pmd_atom.atomic_number, int) and pmd_atom.atomic_number != 0): element = elem.Element.getByAtomicNumber(pmd_atom.atomic_number) else: element = elem.Element.getBySymbol(pmd_atom.name) omm_atom = topology.addAtom(name, element, residue) atoms[pmd_atom] = omm_atom omm_atom.bond_partners = [] for bond in structure.bonds: atom1 = atoms[bond.atom1] atom2 = atoms[bond.atom2] topology.addBond(atom1, atom2) atom1.bond_partners.append(atom2) atom2.bond_partners.append(atom1) if structure.box_vectors and np.any([x._value for x in structure.box_vectors]): topology.setPeriodicBoxVectors(structure.box_vectors) positions = structure.positions return topology, positions
def mol_to_topology(mol): """ Create an openmm topology object from an MDT molecule Args: mol (moldesign.Molecule): molecule to copy topology from Returns: simtk.openmm.app.Topology: topology of the molecule """ from simtk.openmm import app top = app.Topology() chainmap = {chain: top.addChain(chain.name) for chain in mol.chains} resmap = { res: top.addResidue(res.resname, chainmap[res.chain], str(res.pdbindex)) for res in mol.residues } atommap = { atom: top.addAtom(atom.name, app.Element.getBySymbol(atom.element), resmap[atom.residue], id=str(atom.pdbindex)) for atom in mol.atoms } for bond in mol.bonds: top.addBond(atommap[bond.a1], atommap[bond.a2]) return top
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 to_omm_topology(self): ''' Generate OpenMM topology from this topology Returns ------- omm_topology : mm.app.Topology ''' try: from simtk.openmm import app as omm_app from simtk.openmm.app.element import Element as omm_Element except ImportError: raise Exception('cannot import openmm') omm_top = omm_app.Topology() omm_chain = omm_top.addChain() for mol in self._molecules: omm_residue = omm_top.addResidue(mol.name, omm_chain) for atom in mol.atoms: try: omm_element = omm_Element.getBySymbol(atom.symbol) except: omm_element = None omm_top.addAtom(atom.name, omm_element, omm_residue) if self.cell.volume != 0: omm_top.setPeriodicBoxVectors(self.cell.vectors) omm_atoms = list(omm_top.atoms()) for bond in self.bonds: omm_top.addBond(omm_atoms[bond.atom1.id], omm_atoms[bond.atom2.id]) return omm_top
def _create_torsion_sim(periodicity: int = 2, phase=0 * omm_angle_unit, k=10.0 * omm_energy_unit) -> app.Simulation: """Create a 4-particle OpenMM Simulation containing only a PeriodicTorsionForce""" system = mm.System() # add 4 particles of unit mass for _ in range(4): system.addParticle(1) # add torsion force to system force = mm.PeriodicTorsionForce() force.addTorsion(0, 1, 2, 3, periodicity, phase, k) system.addForce(force) # create openmm Simulation, which requires a Topology and Integrator topology = app.Topology() chain = topology.addChain() residue = topology.addResidue("torsion", chain) for name in ["a", "b", "c", "d"]: topology.addAtom(name, "C", residue) integrator = mm.VerletIntegrator(1.0) sim = app.Simulation(topology, system, integrator) return sim
def create_omm_topology(self): topology = app.Topology() for molecule_name, number_of_molecule_copies in self.molecules: for _ in range(number_of_molecule_copies): self.add_moltype_to_omm_topology( self.molecule_types[molecule_name], topology, ) return topology
def write_solvent_pdb(sigma_slv, packing_fraction, box_edge, starting_pdb, dummypdb="dum.pdb"): """Create solvent in box""" # generate solvent n_slv = int(round(packing_fraction * ((box_edge / sigma_slv)**3))) xyz_slv = np.random.uniform(high=box_edge / unit.angstroms, size=[n_slv, 3]) overlap_radius = sigma_slv / unit.angstrom box_ang = box_edge / unit.angstrom new_xyz_slv = [] for i in range(len(xyz_slv)): not_overlapping = True if i < (len(xyz_slv) - 1): for n in range(i + 1, len(xyz_slv)): sep = periodic_distance(xyz_slv[i], xyz_slv[n], box_ang) if sep < overlap_radius: # remove solvent that is overlapping itself not_overlapping = False break if not_overlapping: new_xyz_slv.append(xyz_slv[i]) xyz_slv = np.array(new_xyz_slv) n_slv = len(xyz_slv) # create topology topology = app.Topology() chain = topology.addChain() for i in range(n_slv): res = topology.addResidue("SLV", chain) topology.addAtom("SV", app.element.get_by_symbol("Sv"), res) positions = unit.Quantity(xyz_slv, unit.angstrom) topology.setUnitCellDimensions( (box_edge / unit.nanometer) * omm.Vec3(1, 1, 1)) pdb = app.PDBFile(dummypdb) with open(starting_pdb, "w") as fout: pdb.writeFile(topology, positions, file=fout)
def chimera_molecule_to_openmm_topology(*molecules): """ Convert a Chimera Molecule object to OpenMM structure, providing topology and coordinates. Parameters ---------- molecule : chimera.Molecule Returns ------- topology : simtk.openmm.app.topology.Topology coordinates : simtk.unit.Quantity """ # Create topology atoms, residues, chains = {}, {}, {} topology = openmm_app.Topology() for i, mol in enumerate(molecules): for a in mol.atoms: chain_id = (i, a.residue.id.chainId) try: chain = chains[chain_id] except KeyError: chain = chains[chain_id] = topology.addChain() r = a.residue try: residue = residues[r] except KeyError: residue = residues[r] = topology.addResidue(r.type, chain) name = a.name element = openmm_app.Element.getByAtomicNumber( a.element.number) serial = a.serialNumber atoms[a] = topology.addAtom(name, element, residue, serial) for b in mol.bonds: topology.addBond(atoms[b.atoms[0]], atoms[b.atoms[1]]) return topology
def save_coords(saveas, xyz_ply, box_edge_nm): # create polymer topology topology = app.Topology() chain = topology.addChain() for i in range(len(xyz_ply)): res = topology.addResidue("PLY", chain) atm = topology.addAtom("PL", app.element.get_by_symbol("Pl"), res) if i == 0: prev_atm = atm else: topology.addBond(prev_atm, atm) prev_atm = atm positions = unit.Quantity(xyz_ply, unit.nanometer) topology.setUnitCellDimensions(box_edge_nm * omm.Vec3(1, 1, 1)) pdb = app.PDBFile("dum.pdb") with open(saveas, "w") as fout: pdb.writeFile(topology, positions, file=fout)
def test_mutate_from_every_amino_to_every_other(): """ Make sure mutations are successful between every possible pair of before-and-after residues Mutate Ecoli F-ATPase alpha subunit to all 20 amino acids (test going FROM all possibilities) Mutate each residue to all 19 alternatives """ import perses.rjmc.topology_proposal as topology_proposal aminos = [ 'ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'GLN', 'GLU', 'GLY', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL' ] failed_mutants = 0 pdbid = "2A7U" topology, positions = load_pdbid_to_openmm(pdbid) modeller = app.Modeller(topology, positions) for chain in modeller.topology.chains(): pass modeller.delete([chain]) ff_filename = "amber99sbildn.xml" max_point_mutants = 1 ff = app.ForceField(ff_filename) system = ff.createSystem(modeller.topology) chain_id = 'A' metadata = dict() system_generator = topology_proposal.SystemGenerator([ff_filename]) pm_top_engine = topology_proposal.PointMutationEngine( modeller.topology, system_generator, chain_id, proposal_metadata=metadata, max_point_mutants=max_point_mutants, always_change=True) current_system = system current_topology = modeller.topology current_positions = modeller.positions pm_top_engine._allowed_mutations = list() for k, proposed_amino in enumerate(aminos): pm_top_engine._allowed_mutations.append((str(k + 2), proposed_amino)) pm_top_proposal = pm_top_engine.propose(current_system, current_topology) current_system = pm_top_proposal.new_system current_topology = pm_top_proposal.new_topology for chain in current_topology.chains(): if chain.id == chain_id: # num_residues : int num_residues = len(chain._residues) break new_sequence = list() for residue in current_topology.residues(): if residue.index == 0: continue if residue.index == (num_residues - 1): continue if residue.name in ['HID', 'HIE']: residue.name = 'HIS' new_sequence.append(residue.name) for i in range(len(aminos)): assert new_sequence[i] == aminos[i] pm_top_engine = topology_proposal.PointMutationEngine( current_topology, system_generator, chain_id, proposal_metadata=metadata, max_point_mutants=max_point_mutants) from perses.rjmc.topology_proposal import append_topology old_topology = app.Topology() append_topology(old_topology, current_topology) new_topology = app.Topology() append_topology(new_topology, current_topology) old_chemical_state_key = pm_top_engine.compute_state_key(old_topology) for chain in new_topology.chains(): if chain.id == chain_id: # num_residues : int num_residues = len(chain._residues) break for proposed_location in range(1, num_residues - 1): print('Making mutations at residue %s' % proposed_location) original_residue_name = chain._residues[proposed_location].name matching_amino_found = 0 for proposed_amino in aminos: pm_top_engine._allowed_mutations = [(str(proposed_location + 1), proposed_amino)] new_topology = app.Topology() append_topology(new_topology, current_topology) old_system = current_system old_topology_natoms = sum([1 for atom in old_topology.atoms()]) old_system_natoms = old_system.getNumParticles() if old_topology_natoms != old_system_natoms: msg = 'PolymerProposalEngine: old_topology has %d atoms, while old_system has %d atoms' % ( old_topology_natoms, old_system_natoms) raise Exception(msg) metadata = dict() for atom in new_topology.atoms(): atom.old_index = atom.index index_to_new_residues, metadata = pm_top_engine._choose_mutant( new_topology, metadata) if len(index_to_new_residues) == 0: matching_amino_found += 1 continue print('Mutating %s to %s' % (original_residue_name, proposed_amino)) residue_map = pm_top_engine._generate_residue_map( new_topology, index_to_new_residues) for res_pair in residue_map: residue = res_pair[0] name = res_pair[1] assert residue.index in index_to_new_residues.keys() assert index_to_new_residues[residue.index] == name assert residue.name + '-' + str( residue.id) + '-' + name in metadata['mutations'] new_topology, missing_atoms = pm_top_engine._delete_excess_atoms( new_topology, residue_map) new_topology = pm_top_engine._add_new_atoms( new_topology, missing_atoms, residue_map) for res_pair in residue_map: residue = res_pair[0] name = res_pair[1] assert residue.name == name atom_map = pm_top_engine._construct_atom_map( residue_map, old_topology, index_to_new_residues, new_topology) templates = pm_top_engine._ff.getMatchingTemplates(new_topology) assert [ templates[index].name == residue.name for index, (residue, name) in enumerate(residue_map) ] new_chemical_state_key = pm_top_engine.compute_state_key( new_topology) new_system = pm_top_engine._system_generator.build_system( new_topology) pm_top_proposal = topology_proposal.TopologyProposal( new_topology=new_topology, new_system=new_system, old_topology=old_topology, old_system=old_system, old_chemical_state_key=old_chemical_state_key, new_chemical_state_key=new_chemical_state_key, logp_proposal=0.0, new_to_old_atom_map=atom_map) assert matching_amino_found == 1
def hydrate(system, opt): """ This function solvates the system by using PDBFixer Parameters: ----------- system: OEMol molecule The system to solvate opt: python dictionary The parameters used to solvate the system Return: ------- oe_mol: OEMol The solvated system """ def BoundingBox(molecule): """ This function calculates the Bounding Box of the passed molecule molecule: OEMol return: bb (numpy array) the calculated bounding box is returned as numpy array: [(xmin,ymin,zmin), (xmax,ymax,zmax)] """ coords = [v for k, v in molecule.GetCoords().items()] np_coords = np.array(coords) min_coord = np_coords.min(axis=0) max_coord = np_coords.max(axis=0) bb = np.array([min_coord, max_coord]) return bb # Create a system copy sol_system = system.CreateCopy() # Calculate system BoundingBox (Angstrom units) BB = BoundingBox(sol_system) # Estimation of the box cube length in A box_edge = 2.0 * opt['solvent_padding'] + np.max(BB[1] - BB[0]) # BB center xc = (BB[0][0]+BB[1][0])/2. yc = (BB[0][1]+BB[1][1])/2. zc = (BB[0][2]+BB[1][2])/2. delta = np.array([box_edge/2., box_edge/2., box_edge/2.]) - np.array([xc, yc, zc]) sys_coord_dic = {k: (v+delta) for k, v in sol_system.GetCoords().items()} sol_system.SetCoords(sys_coord_dic) # Load a fake system to initialize PDBfixer filename = resource_filename('pdbfixer', 'tests/data/test.pdb') fixer = PDBFixer(filename=filename) # Convert between OE and OpenMM topology omm_top, omm_pos = oeommutils.oemol_to_openmmTop(sol_system) chain_names = [] for chain in omm_top.chains(): chain_names.append(chain.id) # Set the correct topology to the fake system fixer.topology = omm_top fixer.positions = omm_pos # Solvate the system fixer.addSolvent(padding=unit.Quantity(opt['solvent_padding'], unit.angstroms), ionicStrength=unit.Quantity(opt['salt_concentration'], unit.millimolar)) # The OpenMM topology produced by the solvation fixer has missing bond # orders and aromaticity. The following section is creating a new openmm # topology made of just water molecules and ions. The new topology is then # converted in an OEMol and added to the passed molecule to produce the # solvated system wat_ion_top = app.Topology() # Atom dictionary between the the PDBfixer topology and the water_ion topology fixer_atom_to_wat_ion_atom = {} for chain in fixer.topology.chains(): if chain.id not in chain_names: n_chain = wat_ion_top.addChain(chain.id) for res in chain.residues(): n_res = wat_ion_top.addResidue(res.name, n_chain) for at in res.atoms(): n_at = wat_ion_top.addAtom(at.name, at.element, n_res) fixer_atom_to_wat_ion_atom[at] = n_at for bond in fixer.topology.bonds(): at0 = bond[0] at1 = bond[1] try: wat_ion_top.addBond(fixer_atom_to_wat_ion_atom[at0], fixer_atom_to_wat_ion_atom[at1], type=None, order=1) except: pass wat_ion_pos = fixer.positions[len(omm_pos):] oe_mol = oeommutils.openmmTop_to_oemol(wat_ion_top, wat_ion_pos) # Setting the box vectors omm_box_vectors = fixer.topology.getPeriodicBoxVectors() box_vectors = utils.PackageOEMol.encodePyObj(omm_box_vectors) oe_mol.SetData(oechem.OEGetTag('box_vectors'), box_vectors) oechem.OEAddMols(oe_mol, sol_system) return oe_mol
def __init__(self, n_particles=1, mass=100 * unit.amu, Eo=3.0 * unit.kilocalories_per_mole, a=0.5 * unit.nanometers, b=0.5 * unit.kilocalories_per_mole, k=1.0 * unit.kilocalories_per_mole / unit.angstroms**2, coordinates=None): """Creating a new instance of DoubleWell A new test system is returned with the openmm system of particles in an external double well potential. Parameters ---------- n_particles: int Number of particles in the system mass: unit.Quantity Mass of the particles (in units of mass). Eo: unit.Quantity Parameter of the external potential with units of energy. a: unit.Quantity Parameter of the external potential with units of length. b: unit.Quantity Parameter of the external potential with units of energy. k: unit.Quantity Parameter of the external potential with units of energy/length^2. Examples -------- >>> from uibcdf_test_systems import DoubleWell >>> from simtk import unit >>> double_well = DoubleWell(n_particles = 1, mass = 64 * unit.amu, Eo=4.0 * unit.kilocalories_per_mole, a=1.0 * unit.nanometers, b=0.0 * unit.kilocalories_per_mole, k=1.0 * unit.kilocalories_per_mole/unit.angstroms**2)) Notes ----- See `corresponding documentation in the user guide regarding this class <../../systems/double_well_potential.html>`_. """ super().__init__() # Parameters self.parameters = {} self.parameters['n_particles'] = n_particles self.parameters['mass'] = mass self.parameters['Eo'] = Eo self.parameters['a'] = a self.parameters['b'] = b self.parameters['k'] = k # OpenMM topology self.topology = app.Topology() try: dummy_element = app.element.get_by_symbol('DUM') except: dummy_element = app.Element(0, 'DUM', 'DUM', 0.0 * unit.amu) dummy_element.mass._value = mass.value_in_unit(unit.amu) chain = self.topology.addChain('A') for _ in range(n_particles): residue = self.topology.addResidue('DUM', chain) atom = self.topology.addAtom(name='DUM', element=dummy_element, residue=residue) # OpenMM system self.system = mm.System() for _ in range(n_particles): self.system.addParticle(dummy_element.mass) A = Eo / (a**4) B = -2.0 * Eo / (a**2) C = -b / a D = k / 2.0 force = mm.CustomExternalForce('A*x^4+B*x^2+C*x + D*(y^2+z^2)') force.addGlobalParameter('A', A) force.addGlobalParameter('B', B) force.addGlobalParameter('C', C) force.addGlobalParameter('D', D) for ii in range(n_particles): force.addParticle(ii, []) _ = self.system.addForce(force) # Coordinates if coordinates is None: coordinates = np.zeros([self.parameters['n_particles'], 3], np.float32) * unit.nanometers self.set_coordinates(coordinates) # Potential expresion and constants x, y, z, Eo, a, b, k = sy.symbols('x y z Eo a b k') self.potential_expression = Eo * ( (x / a)**4 - 2.0 * (x / a)**2) - (b / a) * x + 0.5 * k * (y**2 + z**2) del (x, y, z, Eo, a, b, k)
def generate_topology(non_omm_topology, non_element_types=None): if non_element_types is None: non_element_types = set() topology = app.Topology() chain = topology.addChain() if isinstance(non_omm_topology, pmd.Structure): residue = topology.addResidue(non_omm_topology.title, chain) atoms = dict() # pmd.Atom: omm.Atom # Create atoms in the residue. for pmd_atom in non_omm_topology.atoms: name = pmd_atom.name if pmd_atom.element in non_element_types: element = non_element_types[pmd_atom.element] else: if pmd_atom.atomic_number != 0: element = elem.Element.getByAtomicNumber( pmd_atom.atomic_number) else: # TODO: more robust element detection or enforcement of symbols element = elem.Element.getBySymbol(pmd_atom.name) omm_atom = topology.addAtom(name, element, residue) atoms[pmd_atom] = omm_atom omm_atom.bond_partners = [] # Create bonds. for bond in non_omm_topology.bonds: atom1 = atoms[bond.atom1] atom2 = atoms[bond.atom2] topology.addBond(atom1, atom2) atom1.bond_partners.append(atom2) atom2.bond_partners.append(atom1) if non_omm_topology.box_vectors and np.any( [x._value for x in non_omm_topology.box_vectors]): topology.setPeriodicBoxVectors(non_omm_topology.box_vectors) elif isinstance(non_omm_topology, mb.Compound): residue = topology.addResidue(non_omm_topology.name, chain) atoms = dict() # mb.Particle: omm.Atom # Create atoms in the residue. for mb_particle in non_omm_topology.particles(): name = mb_particle.name if mb_particle.name in non_element_types: element = non_element_types[mb_particle.name] else: element = elem.Element.getBySymbol(mb_particle.name) omm_atom = topology.addAtom(name, element, residue) atoms[mb_particle] = omm_atom omm_atom.bond_partners = [] # Create bonds. for bond in non_omm_topology.bonds(): atom1 = atoms[bond[0]] atom2 = atoms[bond[1]] topology.addBond(atom1, atom2) atom1.bond_partners.append(atom2) atom2.bond_partners.append(atom1) bounding_box = non_omm_topology.boundingbox box_vectors = np.zeros(shape=(3, 3)) box_vectors[0, 0] = non_omm_topology.periodicity[0] or bounding_box[0] box_vectors[1, 1] = non_omm_topology.periodicity[1] or bounding_box[1] box_vectors[2, 2] = non_omm_topology.periodicity[2] or bounding_box[2] topology.setPeriodicBoxVectors(box_vectors) else: raise FoyerError('Unknown topology format: {}\n' 'Supported formats are: ' '"parmed.Structure", ' '"mbuild.Compound", ' '"openmm.app.Topology"'.format(topology)) return topology
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
def prep_system(box_width): # if model not in supported_models: # raise Exception("Specified water model '%s' is not in list of supported models: %s" % (model, str(supported_models))) # Load forcefield for solvent model and ions. # force_fields = ['tip3p.xml'] # if ionic_strength != 0.0*unit.molar: # force_fields.append('amber99sb.xml') # For the ions. ff = app.ForceField('tip3p.xml') # Create empty topology and coordinates. top = app.Topology() pos = unit.Quantity((), unit.angstroms) # Create new Modeller instance. m = app.Modeller(top, pos) boxSize = Vec3(box_width, box_width, box_width) * unit.nanometers # boxSize = unit.Quantity(numpy.ones([3]) * box_edge / box_edge.unit, box_edge.unit) m.addSolvent(ff, boxSize=boxSize, model='tip3p') system = ff.createSystem(m.getTopology(), nonbondedMethod=app.NoCutoff, constraints=None, rigidWater=False) positions = m.getPositions() positions = unit.Quantity(np.array(positions / positions.unit), positions.unit) # pdb_str = io.StringIO() fname = "debug.pdb" fhandle = open(fname, "w") PDBFile.writeHeader(m.getTopology(), fhandle) PDBFile.writeModel(m.getTopology(), positions, fhandle, 0) PDBFile.writeFooter(m.getTopology(), fhandle) return system, positions, np.eye(3) * box_width, fname assert 0 # , positiveIon=positive_ion, # negativeIon=negative_ion, ionicStrength=ionic_strength) # Get new topology and coordinates. newtop = m.getTopology() newpos = m.getPositions() # Convert positions to numpy. positions = unit.Quantity(numpy.array(newpos / newpos.unit), newpos.unit) # Create OpenMM System. system = ff.createSystem(newtop, nonbondedMethod=nonbondedMethod, nonbondedCutoff=cutoff, constraints=None, rigidWater=constrained, removeCMMotion=False) # Set switching function and dispersion correction. forces = { system.getForce(index).__class__.__name__: system.getForce(index) for index in range(system.getNumForces()) } forces['NonbondedForce'].setUseSwitchingFunction(False) if switch_width is not None: forces['NonbondedForce'].setUseSwitchingFunction(True) forces['NonbondedForce'].setSwitchingDistance(cutoff - switch_width) forces['NonbondedForce'].setUseDispersionCorrection(dispersion_correction) forces['NonbondedForce'].setEwaldErrorTolerance(ewaldErrorTolerance) n_atoms = system.getNumParticles() self.ndof = 3 * n_atoms - (constrained * n_atoms) self.topology = m.getTopology() self.system = system self.positions = positions
def __init__(self, nx=3, ny=3, nz=3, K=100.0, b=2.0, mass=39.948 * unit.amu, well_radius=1.0, grid_spacing=1.0 * unit.angstrom, coupling_strength=100.0 * unit.kilocalories_per_mole / unit.angstrom, **kwargs): """Initialize particles on a 3D grid of specified size. Parameters ---------- nx, ny, nz : ints number of particles in x, y, z directions, respectively K : float well depth b : float exponent mass : simtk.unit.Quantity particle mass grid_spacing : simtk.unit.Quantity increment between grid points coupling_strength : simtk.unit.quantity strength of HarmonicBond force between each neighboring pair of particles Attributes ---------- topology, positions, system """ # 1. Initialize # 2. Set particles on a 3D grid, use a CustomExternalForce to place each particle in a well # 3. Add a HarmonicBondForce to each neighboring pair of particles. ### 1. Initialize TestSystem.__init__(self, **kwargs) # Set unit of well-depth appropriately #K *= unit.kilocalories_per_mole / unit.angstroms ** b # Determine total number of atoms. natoms = nx * ny * nz # Create an empty system object. system = openmm.System() ### 2. Put particles on a 3D grid positions = unit.Quantity(np.zeros([natoms, 3], np.float32), unit.angstrom) atom_index = 0 # Store the atom indices in a 3-way array # so that we can conveniently determine nearest neighbors atom_indices = np.zeros((nx, ny, nz), dtype=int) energy_expression = "{K} * (sqrt((x - x0)^2 + (y - y0)^2 + (z - z0)^2) / {r})^{b};".format( b=b, K=K, r=well_radius) force = openmm.CustomExternalForce(energy_expression) force.addPerParticleParameter("x0") force.addPerParticleParameter("y0") force.addPerParticleParameter("z0") for i in range(nx): for j in range(ny): for k in range(nz): system.addParticle(mass) xyz = (grid_spacing.value_in_unit(unit.angstrom)) * np.array([i, j, k], dtype=float) positions[atom_index] = (xyz + np.random.randn(3)*0.01) * unit.angstrom atom_indices[i, j, k] = atom_index # Add this particle's well force.addParticle(atom_index, xyz) atom_index += 1 system.addForce(force) ### 3. Couple each pair of neighbors # Find each pair of neighbors in this grid. # Connect each particle (i,j,k), to its "forward" neighbors, # (i+1, j, k), (i, j+1, k), (i, j, k+1), # (if they exist) bonds = [] for i in range(nx): for j in range(ny): for k in range(nz): if (i + 1) < nx: bonds.append((atom_indices[i, j, k], atom_indices[i + 1, j, k])) if (j + 1) < ny: bonds.append((atom_indices[i, j, k], atom_indices[i, j + 1, k])) if (k + 1) < nz: bonds.append((atom_indices[i, j, k], atom_indices[i, j, k + 1])) # Add these HarmonicBondForces to the system force = openmm.HarmonicBondForce() for bond in bonds: force.addBond(int(bond[0]), int(bond[1]), grid_spacing, coupling_strength) 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) # Set topology, positions, system as instance attributes self.topology = topology self.positions = positions self.system = system
def _addAtomsToTopology(self, heavyAtomsOnly, omitUnknownMolecules): """Create a new Topology in which missing atoms have been added.""" newTopology = app.Topology() newPositions = []*unit.nanometer newAtoms = [] existingAtomMap = {} addedAtomMap = {} addedOXT = [] for chain in self.topology.chains(): if omitUnknownMolecules and not any(residue.name in self.templates for residue in chain.residues()): continue chainResidues = list(chain.residues()) newChain = newTopology.addChain() for indexInChain, residue in enumerate(chain.residues()): # Insert missing residues here. if (chain.index, indexInChain) in self.missingResidues: insertHere = self.missingResidues[(chain.index, indexInChain)] endPosition = self._computeResidueCenter(residue) if indexInChain > 0: startPosition = self._computeResidueCenter(chainResidues[indexInChain-1]) else: outward = endPosition-self.centroid norm = unit.norm(outward) if norm > 0*unit.nanometer: outward *= len(insertHere)*0.5*unit.nanometer/norm startPosition = endPosition+outward self._addMissingResiduesToChain(newChain, insertHere, startPosition, endPosition, residue, newAtoms, newPositions) # Create the new residue and add existing heavy atoms. newResidue = newTopology.addResidue(residue.name, newChain) addResiduesAfter = (residue == chainResidues[-1] and (chain.index, indexInChain+1) in self.missingResidues) for atom in residue.atoms(): if not heavyAtomsOnly or (atom.element is not None and atom.element != hydrogen): if atom.name == 'OXT' and (chain.index, indexInChain+1) in self.missingResidues: continue # Remove terminal oxygen, since we'll add more residues after this one newAtom = newTopology.addAtom(atom.name, atom.element, newResidue) existingAtomMap[atom] = newAtom newPositions.append(self.positions[atom.index]) if residue in self.missingAtoms: # Find corresponding atoms in the residue and the template. template = self.templates[residue.name] atomPositions = dict((atom.name, self.positions[atom.index]) for atom in residue.atoms()) points1 = [] points2 = [] for atom in template.topology.atoms(): if atom.name in atomPositions: points1.append(atomPositions[atom.name].value_in_unit(unit.nanometer)) points2.append(template.positions[atom.index].value_in_unit(unit.nanometer)) # Compute the optimal transform to overlay them. (translate2, rotate, translate1) = _overlayPoints(points1, points2) # Add the missing atoms. addedAtomMap[residue] = {} for atom in self.missingAtoms[residue]: newAtom = newTopology.addAtom(atom.name, atom.element, newResidue) newAtoms.append(newAtom) addedAtomMap[residue][atom] = newAtom templatePosition = template.positions[atom.index].value_in_unit(unit.nanometer) newPositions.append((mm.Vec3(*np.dot(rotate, templatePosition+translate2))+translate1)*unit.nanometer) if residue in self.missingTerminals: terminalsToAdd = self.missingTerminals[residue] else: terminalsToAdd = None # If this is the end of the chain, add any missing residues that come after it. if residue == chainResidues[-1] and (chain.index, indexInChain+1) in self.missingResidues: insertHere = self.missingResidues[(chain.index, indexInChain+1)] if len(insertHere) > 0: startPosition = self._computeResidueCenter(residue) outward = startPosition-self.centroid norm = unit.norm(outward) if norm > 0*unit.nanometer: outward *= len(insertHere)*0.5*unit.nanometer/norm endPosition = startPosition+outward self._addMissingResiduesToChain(newChain, insertHere, startPosition, endPosition, residue, newAtoms, newPositions) newResidue = list(newChain.residues())[-1] if newResidue.name in proteinResidues: terminalsToAdd = ['OXT'] else: terminalsToAdd = None # If a terminal OXT is missing, add it. if terminalsToAdd is not None: atomPositions = dict((atom.name, newPositions[atom.index].value_in_unit(unit.nanometer)) for atom in newResidue.atoms()) if 'OXT' in terminalsToAdd: newAtom = newTopology.addAtom('OXT', oxygen, newResidue) newAtoms.append(newAtom) addedOXT.append(newAtom) d_ca_o = atomPositions['O']-atomPositions['CA'] d_ca_c = atomPositions['C']-atomPositions['CA'] d_ca_c /= unit.sqrt(unit.dot(d_ca_c, d_ca_c)) v = d_ca_o - d_ca_c*unit.dot(d_ca_c, d_ca_o) newPositions.append((atomPositions['O']+2*v)*unit.nanometer) newTopology.setUnitCellDimensions(self.topology.getUnitCellDimensions()) newTopology.createStandardBonds() newTopology.createDisulfideBonds(newPositions) # Return the results. return (newTopology, newPositions, newAtoms, existingAtomMap)
def __init__(self, atom_1='Ar', atom_2='Xe', mass_1=None, sigma_1=None, epsilon_1=None, mass_2=None, sigma_2=None, epsilon_2=None, cutoff_distance=None, switching_distance=None, box=None, coordinates=None): super().__init__() # Parameters if (mass_1 is not None) or (sigma_1 is not None) or (epsilon_1 is not None): if mass_1 is None: raise ValueError( 'A value for the input argument "mass_1" is needed.') if sigma_1 is None: raise ValueError( 'A value for the input argument "sigma_1" is needed.') if epsilon_1 is None: raise ValueError( 'A value for the input argument "epsilon_1" is needed.') elif atom_1 is not None: mass_1 = atoms_LJ[atom_1]['mass'] sigma_1 = atoms_LJ[atom_1]['sigma'] epsilon_1 = atoms_LJ[atom_1]['epsilon'] if (mass_2 is not None) or (sigma_2 is not None) or (epsilon_2 is not None): if mass_2 is None: raise ValueError( 'A value for the input argument "mass_2" is needed.') if sigma_2 is None: raise ValueError( 'A value for the input argument "sigma_2" is needed.') if epsilon_2 is None: raise ValueError( 'A value for the input argument "epsilon_2" is needed.') elif atom_2 is not None: mass_2 = atoms_LJ[atom_2]['mass'] sigma_2 = atoms_LJ[atom_2]['sigma'] epsilon_2 = atoms_LJ[atom_2]['epsilon'] self.parameters['mass_1'] = mass_1 self.parameters['sigma_1'] = sigma_1 self.parameters['epsilon_1'] = epsilon_1 self.parameters['mass_2'] = mass_2 self.parameters['sigma_2'] = sigma_2 self.parameters['epsilon_2'] = epsilon_2 if box is not None: reduced_sigma = self.get_reduced_sigma() if cutoff_distance is None: cutoff_distance = 4.0 * reduced_sigma if switching_distance is None: switching_distance = 3.0 * reduced_sigma self.parameters['box'] = box self.parameters['cutoff_distance'] = cutoff_distance self.parameters['switching_distance'] = switching_distance # OpenMM topology self.topology = app.Topology() try: dummy_element = app.element.get_by_symbol('DUM') except: dummy_element = app.Element(0, 'DUM', 'DUM', 0.0 * unit.amu) chain = self.topology.addChain('A') residue = self.topology.addResidue('DUM_0', chain) atom = self.topology.addAtom(name='DUM_0', element=dummy_element, residue=residue) residue = self.topology.addResidue('DUM_1', chain) atom = self.topology.addAtom(name='DUM_1', element=dummy_element, residue=residue) # OpenMM system self.system = mm.System() non_bonded_force = mm.NonbondedForce() if box is not None: non_bonded_force.setNonbondedMethod( mm.NonbondedForce.CutoffPeriodic) non_bonded_force.setUseSwitchingFunction(True) non_bonded_force.setCutoffDistance(cutoff_distance) non_bonded_force.setSwitchingDistance(switching_distance) else: non_bonded_force.setNonbondedMethod(mm.NonbondedForce.NoCutoff) self.system.addParticle(mass_1) charge_1 = 0.0 * unit.elementary_charge non_bonded_force.addParticle(charge_1, sigma_1, epsilon_1) self.system.addParticle(mass_2) charge_2 = 0.0 * unit.elementary_charge non_bonded_force.addParticle(charge_2, sigma_2, epsilon_2) _ = self.system.addForce(non_bonded_force) # Coordinates if coordinates is not None: self.set_coordinates(coordinates) # Box if box is not None: self.set_box(box) # Potential expresion d, eps_r, sigma_r = symbols('d eps_r sigma_r') self.potential_expression = 4.0 * eps_r * ((sigma_r / d)**12 - (sigma_r / d)**6) del (d, eps_r, sigma_r)
def empty_topology(): """Empty topology.""" return app.Topology()
def build_two_residues(): alanine_topology = app.Topology() alanine_positions = unit.Quantity(np.zeros((22, 3)), unit.nanometer) leucine_topology = app.Topology() leucine_positions = unit.Quantity(np.zeros((31, 3)), unit.nanometer) ala_chain = alanine_topology.addChain(id='A') leu_chain = leucine_topology.addChain(id='A') ala_ace = alanine_topology.addResidue('ACE', ala_chain) ala_res = alanine_topology.addResidue('ALA', ala_chain) ala_nme = alanine_topology.addResidue('NME', ala_chain) leu_ace = leucine_topology.addResidue('ACE', leu_chain) leu_res = leucine_topology.addResidue('LEU', leu_chain) leu_nme = leucine_topology.addResidue('NME', leu_chain) ala_atoms = dict() leu_atoms = dict() atom_map = dict() for core_atom_name, [element, position] in ace.items(): position = np.asarray(position) alanine_positions[len(ala_atoms.keys())] = position * unit.angstrom leucine_positions[len(leu_atoms.keys())] = position * unit.angstrom ala_atom = alanine_topology.addAtom(core_atom_name, element, ala_ace) leu_atom = leucine_topology.addAtom(core_atom_name, element, leu_ace) ala_atoms['ace-' + core_atom_name] = ala_atom leu_atoms['ace-' + core_atom_name] = leu_atom atom_map[ala_atom.index] = leu_atom.index for core_atom_name, [element, position] in core.items(): position = np.asarray(position) alanine_positions[len(ala_atoms.keys())] = position * unit.angstrom leucine_positions[len(leu_atoms.keys())] = position * unit.angstrom ala_atom = alanine_topology.addAtom(core_atom_name, element, ala_res) leu_atom = leucine_topology.addAtom(core_atom_name, element, leu_res) ala_atoms[core_atom_name] = ala_atom leu_atoms[core_atom_name] = leu_atom atom_map[ala_atom.index] = leu_atom.index for ala_atom_name, [element, position] in ala_unique.items(): position = np.asarray(position) alanine_positions[len(ala_atoms.keys())] = position * unit.angstrom ala_atom = alanine_topology.addAtom(ala_atom_name, element, ala_res) ala_atoms[ala_atom_name] = ala_atom for leu_atom_name, [element, position] in leu_unique.items(): position = np.asarray(position) leucine_positions[len(leu_atoms.keys())] = position * unit.angstrom leu_atom = leucine_topology.addAtom(leu_atom_name, element, leu_res) leu_atoms[leu_atom_name] = leu_atom for core_atom_name, [element, position] in nme.items(): position = np.asarray(position) alanine_positions[len(ala_atoms.keys())] = position * unit.angstrom leucine_positions[len(leu_atoms.keys())] = position * unit.angstrom ala_atom = alanine_topology.addAtom(core_atom_name, element, ala_nme) leu_atom = leucine_topology.addAtom(core_atom_name, element, leu_nme) ala_atoms['nme-' + core_atom_name] = ala_atom leu_atoms['nme-' + core_atom_name] = leu_atom atom_map[ala_atom.index] = leu_atom.index for bond in core_bonds: alanine_topology.addBond(ala_atoms[bond[0]], ala_atoms[bond[1]]) leucine_topology.addBond(leu_atoms[bond[0]], leu_atoms[bond[1]]) for bond in ala_bonds: alanine_topology.addBond(ala_atoms[bond[0]], ala_atoms[bond[1]]) for bond in leu_bonds: leucine_topology.addBond(leu_atoms[bond[0]], leu_atoms[bond[1]]) return alanine_topology, alanine_positions, leucine_topology, leucine_positions, atom_map
def run(opts): system_xml_file = opts.system integrator_xml_file = opts.integrator coords_f = opts.coords platform_name = opts.platform deviceid = opts.device write_freq = opts.write_freq output = opts.output nsteps = opts.nsteps platform_properties = { 'OpenCLPrecision': 'mixed', 'OpenCLPlatformIndex': '0', 'OpenCLDeviceIndex': '0', 'CudaPrecision': 'mixed', 'CudaDeviceIndex': '0', 'CpuThreads': '1' } platform_properties['CudaDeviceIndex'] = deviceid platform_properties['OpenCLDeviceIndex'] = deviceid with open(system_xml_file, 'r') as f: system = openmm.XmlSerializer.deserialize(f.read()) with open(integrator_xml_file, 'r') as f: integrator = openmm.XmlSerializer.deserialize(f.read()) integrator.setRandomNumberSeed(random.randint(0, 2**16)) platform = openmm.Platform.getPlatformByName(platform_name) properties = { key: platform_properties[key] for key in platform_properties if key.lower().startswith(platform_name.lower()) } if platform_name == 'CPU': properties = {'CpuThreads': '1'} print properties # Create dummy topology to satisfy Simulation object topology = app.Topology() volume = wcadimer.natoms / wcadimer.density length = volume**(1.0 / 3.0) L = length.value_in_unit(units.nanometer) topology.setUnitCellDimensions(Vec3(L, L, L) * units.nanometer) simulation = app.Simulation(topology, system, integrator, platform, properties) init_data = np.load(coords_f) coords = units.Quantity(init_data['coord'], units.nanometer) simulation.context.setPositions(coords) if 'veloc' in init_data: velocs = units.Quantity(init_data['veloc'], units.nanometer / units.picosecond) simulation.context.setVelocities(velocs) else: simulation.context.setVelocitiesToTemperature(wcadimer.temperature) # Attach reporters simulation.reporters.append( HDF5Reporter(output + '.h5', write_freq, atomSubset=[0, 1])) simulation.reporters.append( app.StateDataReporter(stdout, 20 * write_freq, step=True, potentialEnergy=True, temperature=True, progress=True, remainingTime=True, speed=True, totalSteps=nsteps, separator='\t')) # Run segment simulation.step(nsteps) # Write restart data state = simulation.context.getState(getPositions=True, getVelocities=True) coords = state.getPositions(asNumpy=True) velocs = state.getVelocities(asNumpy=True) np.savez_compressed(output + '_restart.npz', coords, coord=coords, veloc=velocs)
def extract(self, chains_to_keep, extract_protein): '''Extract the protein or ligand from the complex and return its energy. Parameters ---------- chains_to_keep : list of strings Chain id(s) to keep extract_protein : boolean If true, extract protein. Otherwise, extract ligand. Returns ------- float Final energy in kcal/mol ''' try: self.minimizedState.getPositions() except Exception: print( "The System has not been minimized -- you must minimize before extracting." ) if not isinstance(extract_protein, bool): raise TypeError( "extract_protein should be boolean indicating whether to extract the protein (True) or ligand (False)" ) ## Extract topology if extract_protein: print("\tExtracting P from PL...") else: print("\tExtracting L from PL...") # Create new topology new_topology = app.Topology() # Copy residues and atoms to new topology for chains_to_keep d_old_to_new = { } # Key: atom in old topology, Value: atom in new topology for chain in self.complexTopology.chains(): if chain.id in chains_to_keep: new_chain = new_topology.addChain(id=chain.id) for res in chain.residues(): # Copy residues and atoms new_res = new_topology.addResidue(res.name, new_chain, id=res.id) for atom in res.atoms(): new_atom = new_topology.addAtom( atom.name, atom.element, new_res) d_old_to_new[atom] = new_atom # Make list of atoms to delete atoms_to_delete = [] for res in self.complexTopology.residues(): if res.chain.id not in chains_to_keep: for atom in res.atoms(): atoms_to_delete.append(atom) # Copy bonds to new topology, except bonds involving atoms to delete for bond in self.complexTopology.bonds(): atom_1 = bond[0] atom_2 = bond[1] if (atom_1 in atoms_to_delete) or (atom_2 in atoms_to_delete): continue atom_1_new = d_old_to_new[atom_1] atom_2_new = d_old_to_new[atom_2] new_topology.addBond(atom_1_new, atom_2_new) ## Extract the positions atoms = [ atom.index for atom in self.complexTopology.atoms() if atom.residue.chain.id in chains_to_keep ] positions = [ position for i, position in enumerate(self.minimizedState.getPositions()) if i in atoms ] ## Extract the energy # Set up system system = self.forcefield.createSystem( new_topology, nonbondedMethod=app.CutoffNonPeriodic, nonbondedCutoff=1.2 * unit.nanometer, constraints=app.HBonds, hydrogenMass=4 * unit.amu, soluteDielectric=1, solventDielectric=1) # Set up integrator integrator = openmmtools.integrators.LangevinIntegrator( 300 * unit.kelvin, 1 / unit.picosecond, 4 * unit.femtosecond) # Set up simulation simulation = app.Simulation(new_topology, system, integrator, self.platform) simulation.context.setPositions(positions) # Get the initial energy initial_state = simulation.context.getState(getEnergy=True, getPositions=True) initial_energy = initial_state.getPotentialEnergy( ) / unit.kilocalories_per_mole # before conversion: kJ/mol print('\t Energy : %8.3f kcal/mol' % (initial_energy)) if extract_protein: self.proteinEnergy = initial_energy else: self.ligandEnergy = initial_energy
import pandas as pd import simtk.openmm.app as app import simtk.openmm as mm import simtk.unit as u import mdtraj as md # 0.2 * 1000 / 18.015 temperature = 300.0 * u.kelvin pressure = 1.0 * u.atmospheres stderr_tolerance = 0.0001 ionicStrength = 2.0 * u.molar ff = app.ForceField("tip3p.xml", "amber10.xml") mmtop = app.Topology() positions = [] modeller = app.Modeller(mmtop, positions) modeller.addSolvent(ff, boxSize=mm.Vec3(2.2, 2.2, 2.2) * u.nanometers, ionicStrength=ionicStrength) system = ff.createSystem(modeller.topology, nonbondedMethod=app.CutoffPeriodic) output_frequency = 125 friction = 1.0 / u.picoseconds timestep = 2.0 * u.femtoseconds barostat_frequency = 25 n_steps = 100000 csv_filename = "density_%d_%0.1f.csv" % (temperature / temperature.unit,
import atomsmm from simtk import openmm from simtk import unit from simtk.openmm import app from sys import stdout temp = 300 * unit.kelvin rigid_water = False simulation_platform = 'CUDA' pressure_computer_platform = 'CUDA' modeller = app.Modeller(app.Topology(), []) force_field = app.ForceField('tip3p.xml') modeller.addSolvent(force_field, numAdded=500) topology = modeller.getTopology() system = force_field.createSystem(topology, nonbondedMethod=app.PME, rigidWater=rigid_water) def platform(name): return [ openmm.Platform.getPlatformByName(name), dict(Precision='mixed') if name == 'CUDA' else dict() ] integrator = openmm.LangevinIntegrator(temp, 0.1 / unit.femtoseconds, 1.0 * unit.femtosecond) system.addForce(openmm.MonteCarloBarostat(1 * unit.atmospheres, temp, 20)) simulation = app.Simulation(topology, system, integrator,
def oemol_to_openmmTop(mol): """ This function converts an OEMol to an openmm topology The OEMol coordinates are assumed to be in Angstrom unit Parameters: ----------- mol: OEMol molecule The molecule to convert Return: ------- topology : OpenMM Topology The generated OpenMM topology positions : OpenMM Quantity The molecule atom positions associated with the generated topology in Angstrom units """ # OE Hierarchical molecule view hv = oechem.OEHierView( mol, oechem.OEAssumption_BondedResidue + oechem.OEAssumption_ResPerceived + oechem.OEAssumption_PDBOrder) # Create empty OpenMM Topology topology = app.Topology() # Dictionary used to map oe atoms to openmm atoms oe_atom_to_openmm_at = {} for chain in hv.GetChains(): # Create empty OpenMM Chain openmm_chain = topology.addChain(chain.GetChainID()) for frag in chain.GetFragments(): for hres in frag.GetResidues(): # Get OE residue oe_res = hres.GetOEResidue() # Create OpenMM residue openmm_res = topology.addResidue(oe_res.GetName(), openmm_chain) for oe_at in hres.GetAtoms(): # Select atom element based on the atomic number element = app.element.Element.getByAtomicNumber( oe_at.GetAtomicNum()) # Add atom OpenMM atom to the topology openmm_at = topology.addAtom(oe_at.GetName(), element, openmm_res) openmm_at.index = oe_at.GetIdx() # Add atom to the mapping dictionary oe_atom_to_openmm_at[oe_at] = openmm_at if topology.getNumAtoms() != mol.NumAtoms(): raise ValueError( "OpenMM topology and OEMol number of atoms mismatching: " "OpenMM = {} vs OEMol = {}".format(topology.getNumAtoms(), mol.NumAtoms())) # Count the number of bonds in the openmm topology omm_bond_count = 0 def IsAmideBond(oe_bond): # This supporting function checks if the passed bond is an amide bond or not. # Our definition of amide bond C-N between a Carbon and a Nitrogen atom is: # O # ║ # CA or O-C-N- # | # The amide bond C-N is a single bond if oe_bond.GetOrder() != 1: return False atomB = oe_bond.GetBgn() atomE = oe_bond.GetEnd() # The amide bond is made by Carbon and Nitrogen atoms if not (atomB.IsCarbon() and atomE.IsNitrogen() or (atomB.IsNitrogen() and atomE.IsCarbon())): return False # Select Carbon and Nitrogen atoms if atomB.IsCarbon(): C_atom = atomB N_atom = atomE else: C_atom = atomE N_atom = atomB # Carbon and Nitrogen atoms must have 3 neighbour atoms if not (C_atom.GetDegree() == 3 and N_atom.GetDegree() == 3): return False double_bonds = 0 single_bonds = 0 for bond in C_atom.GetBonds(): # The C-O bond can be single or double. if (bond.GetBgn() == C_atom and bond.GetEnd().IsOxygen()) or \ (bond.GetBgn().IsOxygen() and bond.GetEnd() == C_atom): if bond.GetOrder() == 2: double_bonds += 1 if bond.GetOrder() == 1: single_bonds += 1 # The CA-C bond is single if (bond.GetBgn() == C_atom and bond.GetEnd().IsCarbon()) or \ (bond.GetBgn().IsCarbon() and bond.GetEnd() == C_atom): if bond.GetOrder() == 1: single_bonds += 1 # Just one double and one single bonds are connected to C # In this case the bond is an amide bond if double_bonds == 1 and single_bonds == 1: return True else: return False # Creating bonds for oe_bond in mol.GetBonds(): omm_bond_count += 1 # Set the bond type if oe_bond.GetType() is not "": if oe_bond.GetType() in [ 'Single', 'Double', 'Triple', 'Aromatic', 'Amide' ]: omm_bond_type = oe_bond.GetType() else: omm_bond_type = None else: if oe_bond.IsAromatic(): oe_bond.SetType("Aromatic") omm_bond_type = "Aromatic" elif oe_bond.GetOrder() == 2: oe_bond.SetType("Double") omm_bond_type = "Double" elif oe_bond.GetOrder() == 3: oe_bond.SetType("Triple") omm_bond_type = "Triple" elif IsAmideBond(oe_bond): oe_bond.SetType("Amide") omm_bond_type = "Amide" elif oe_bond.GetOrder() == 1: oe_bond.SetType("Single") omm_bond_type = "Single" else: omm_bond_type = None topology.addBond(oe_atom_to_openmm_at[oe_bond.GetBgn()], oe_atom_to_openmm_at[oe_bond.GetEnd()], type=omm_bond_type, order=oe_bond.GetOrder()) if omm_bond_count != mol.NumBonds(): raise ValueError( "OpenMM topology and OEMol number of bonds mismatching: " "OpenMM = {} vs OEMol = {}".format(omm_bond_count, mol.NumBonds())) dic = mol.GetCoords() positions = [Vec3(v[0], v[1], v[2]) for k, v in dic.items()] * unit.angstrom return topology, positions
def __init__(self, box_edge=25.0 * unit.angstroms, cutoff=9 * unit.angstroms, model='tip3p', switch_width=1.5 * unit.angstroms, constrained=True, dispersion_correction=True, nonbondedMethod=app.PME, ewaldErrorTolerance=5E-4, **kwargs): """ Create a water box test system. Parameters ---------- box_edge : simtk.unit.Quantity with units compatible with nanometers, optional, default = 2.5 nm Edge length for cubic box [should be greater than 2*cutoff] cutoff : simtk.unit.Quantity with units compatible with nanometers, optional, default = 0.9 nm Nonbonded cutoff model : str, optional, default = 'tip3p' The name of the water model to use ['tip3p', 'tip4p', 'tip4pew', 'tip5p', 'spce'] switch_width : simtk.unit.Quantity with units compatible with nanometers, optional, default = 0.5 A Sets the width of the switch function for Lennard-Jones. constrained : bool, optional, default=True Sets whether water geometry should be constrained (rigid water implemented via SETTLE) or flexible. dispersion_correction : bool, optional, default=True Sets whether the long-range dispersion correction should be used. nonbondedMethod : simtk.openmm.app nonbonded method, optional, default=app.PME Sets the nonbonded method to use for the water box (one of app.CutoffPeriodic, app.Ewald, app.PME). ewaldErrorTolerance : float, optional, default=5E-4 The Ewald or PME tolerance. Used only if nonbondedMethod is Ewald or PME. Examples -------- Create a default waterbox. >>> waterbox = WaterBox() >>> [system, positions] = [waterbox.system, waterbox.positions] Use reaction-field electrostatics instead. >>> waterbox = WaterBox(nonbondedMethod=app.CutoffPeriodic) Control the cutoff. >>> waterbox = WaterBox(box_edge=3.0*unit.nanometers, cutoff=1.0*unit.nanometers) Use a different water model. >>> waterbox = WaterBox(model='spce') Use a five-site water model. >>> waterbox = WaterBox(model='tip5p') Turn off the switch function. >>> waterbox = WaterBox(switch_width=None) Set the switch width. >>> waterbox = WaterBox(switch_width=0.8*unit.angstroms) Turn of long-range dispersion correction. >>> waterbox = WaterBox(dispersion_correction=False) """ TestSystem.__init__(self, **kwargs) supported_models = ['tip3p', 'tip4pew', 'tip5p', 'spce'] if model not in supported_models: raise Exception( "Specified water model '%s' is not in list of supported models: %s" % (model, str(supported_models))) # Load forcefield for solvent model. ff = app.ForceField('gcmc.xml') # Create empty topology and coordinates. top = app.Topology() pos = unit.Quantity((), unit.angstroms) # Create new Modeller instance. m = app.Modeller(top, pos) # Add solvent to specified box dimensions. boxSize = unit.Quantity( np.ones([3]) * box_edge / box_edge.unit, box_edge.unit) m.addSolvent(ff, boxSize=boxSize, model=model, neutralize=False, positiveIon='Na+', negativeIon='Cl-', **kwargs) # Get new topology and coordinates. newtop = m.getTopology() newpos = m.getPositions() # Convert positions to np. positions = unit.Quantity(np.array(newpos / newpos.unit), newpos.unit) # Create OpenMM System. self.forcefieldOptions = { 'nonbondedMethod': nonbondedMethod, 'nonbondedCutoff': cutoff, 'constraints': None, 'rigidWater': constrained, 'removeCMMotion': False } system = ff.createSystem(newtop, **(self.forcefieldOptions)) # Set switching function and dispersion correction. forces = { system.getForce(index).__class__.__name__: system.getForce(index) for index in range(system.getNumForces()) } forces['NonbondedForce'].setUseSwitchingFunction(False) if switch_width is not None: forces['NonbondedForce'].setUseSwitchingFunction(True) forces['NonbondedForce'].setSwitchingDistance(cutoff - switch_width) forces['NonbondedForce'].setUseDispersionCorrection( dispersion_correction) forces['NonbondedForce'].setEwaldErrorTolerance(ewaldErrorTolerance) self.ndof = 3 * system.getNumParticles() - 3 * constrained self.topology = newtop self.system = system self.positions = positions self.forcefield = ff
import numpy as np import argparse import subprocess # Read filename parser = argparse.ArgumentParser(description='correct equilibrated.pdb') parser.add_argument('name', type=str, help='name of file for which to correct') args = parser.parse_args() pdb = app.PDBFile(args.name) # Get old topology and positions old_topology = pdb.getTopology() old_positions = pdb.positions # Create new topology and positions new_topology = app.Topology() new_topology.setPeriodicBoxVectors(old_topology.getPeriodicBoxVectors()) positions_R, positions_X, positions_C, positions_D, positions_E, positions_Y = list( ), list(), list(), list(), list(), list() # Create new chains new_chain_R = new_topology.addChain(id="R") new_chain_X = new_topology.addChain(id="X") new_chain_C = new_topology.addChain(id="C") new_chain_D = new_topology.addChain(id="D") new_chain_E = new_topology.addChain(id="E") new_chain_Y = new_topology.addChain(id="Y") # Specify the starting residue ids for each chain d_current_start = {"C": 18, "E": 1, "R": 332, "X": 1, "D": 1}