def solvate_models(msmseed): """ Calculate the number of waters needed to solvate the implicitly-refined model Parameters ---------- msmseed : MSMSeed object containing the unsolvated, implicitly refined model structure Returns ------- msmseed : MSMSeed object additionally containing the number of waters required to solvate the model """ import os import simtk.unit as unit import simtk.openmm.app as app forcefields_to_use = ['amber99sbildn.xml', 'tip3p.xml' ] # list of forcefields to use in parameterization nparticles_per_water = 3 padding = 10.0 * unit.angstroms forcefield = app.ForceField(*forcefields_to_use) topology = msmseed.implicit_refined_model.topology positions = msmseed.implicit_refined_model.positions natoms_initial = len(positions) modeller = app.Modeller(topology, positions) modeller.addSolvent(forcefield, model='tip3p', padding=padding) positions = modeller.getPositions() natoms_final = len(positions) nwaters = (natoms_final - natoms_initial) / nparticles_per_water msmseed.nwaters = nwaters return msmseed
def test_porin_membrane_system(): """Test the addition of a ligand to a solvated porin""" # pdb file corresponding to a solvated porin pdb = PDBFile( os.path.join(os.path.dirname(__file__), '../data/porin/solvated-porin.pdb')) modeller = app.Modeller(pdb.topology, pdb.positions) forcefield = ForceField('amber14-all.xml', 'amber14/tip3pfb.xml') platform = mm.Platform.getPlatformByName('CPU') modeller.addHydrogens(forcefield=forcefield) # rigidWater False is required for ParMed to access water paramters system_md = forcefield.createSystem(modeller.topology, nonbondedMethod=app.PME, rigidWater=False, nonbondedCutoff=1 * unit.nanometer) ligand_system = PorinMembraneSystem('comp7', system_md, modeller.topology, modeller.positions, platform, tolerance=1 * unit.kilojoule / unit.mole, max_iterations=200) integrator = mm.LangevinIntegrator(300 * unit.kelvin, 1.0 / unit.picoseconds, 2 * unit.femtosecond) simulation = app.Simulation(ligand_system.structure.topology, ligand_system.system, integrator, platform) simulation.context.setPositions(ligand_system.structure.positions) state = simulation.context.getState(getEnergy=True) pe = state.getPotentialEnergy()._value assert pe < 0.0
def openmm_system(self): """Initialise the OpenMM system we will use to evaluate the energies.""" # Load the initial coords into the system and initialise pdb = app.PDBFile(self.pdb) forcefield = app.ForceField(self.xml) modeller = app.Modeller(pdb.topology, pdb.positions) # set the initial positions from the pdb self.system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None) # Check what combination rule we should be using from the xml xmlstr = open(self.xml).read() # check if we have opls combination rules if the xml is present try: self.combination = ET.fromstring(xmlstr).find('NonbondedForce').attrib['combination'] except AttributeError: pass except KeyError: pass if self.combination == 'opls': print('OPLS combination rules found in xml file') self.opls_lj() temperature = constants.STP * unit.kelvin integrator = mm.LangevinIntegrator(temperature, 5 / unit.picoseconds, 0.001 * unit.picoseconds) self.simulation = app.Simulation(modeller.topology, self.system, integrator) self.simulation.context.setPositions(modeller.positions)
def addSolvent(self, boxSize=None, padding=None, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*unit.molar): """Add a solvent box surrounding the structure. Parameters ---------- boxSize : simtk.openmm.Vec3, optional, default=None The size of the box to fill with water. If specified, padding must not be specified. padding : simtk.unit.Quantity compatible with nanometers, optional, default=None Padding around macromolecule for filling box with water. If specified, boxSize must not be specified. positiveIon : str, optional, default='Na+' The type of positive ion to add. Allowed values are 'Cs+', 'K+', 'Li+', 'Na+', and 'Rb+'. negativeIon : str, optional, default='Cl-' The type of negative ion to add. Allowed values are 'Cl-', 'Br-', 'F-', and 'I-'. ionicStrength : simtk.unit.Quantity with units compatible with molar, optional, default=0*molar The total concentration of ions (both positive and negative) to add. This does not include ions that are added to neutralize the system. Examples -------- Add missing residues, heavy atoms, and hydrogens, and then solvate with 10 A padding. >>> fixer = PDBFixer(pdbid='1VII') >>> fixer.findMissingResidues() >>> fixer.findMissingAtoms() >>> fixer.addMissingAtoms() >>> fixer.addMissingHydrogens(pH=8.0) >>> fixer.addSolvent(padding=10*unit.angstrom, ionicStrength=0.050*unit.molar) """ modeller = app.Modeller(self.topology, self.positions) forcefield = self._createForceField(self.topology, True) modeller.addSolvent(forcefield, padding=padding, boxSize=boxSize, positiveIon=positiveIon, negativeIon=negativeIon, ionicStrength=ionicStrength) self.topology = modeller.topology self.positions = modeller.positions
def addMissingHydrogens(self, pH=7.0): """Add missing hydrogen atoms to the structure. Parameters ---------- pH : float, optional, default=7.0 The pH based on which to select hydrogens. Notes ----- No extensive electrostatic analysis is performed; only default residue pKas are used. Examples -------- Examples -------- Add missing hydrogens appropriate for pH 8. >>> fixer = PDBFixer(pdbid='1VII') >>> fixer.addMissingHydrogens(pH=8.0) """ modeller = app.Modeller(self.topology, self.positions) modeller.addHydrogens(pH=pH) self.topology = modeller.topology self.positions = modeller.positions
def removeHeterogens(self, keepWater=True): """Remove all heterogens from the structure. Parameters ---------- keepWater : bool, optional, default=True If True, water molecules will not be removed. Examples -------- Remove heterogens in Abl structure complexed with imatinib. >>> fixer = PDBFixer(pdbid='2F4J') >>> fixer.removeHeterogens(keepWater=False) """ keep = set(proteinResidues).union(dnaResidues).union(rnaResidues) keep.add('N') keep.add('UNK') if keepWater: keep.add('HOH') toDelete = [] for residue in self.topology.residues(): if residue.name not in keep: toDelete.append(residue) modeller = app.Modeller(self.topology, self.positions) modeller.delete(toDelete) self.topology = modeller.topology self.positions = modeller.positions
def test_mutate_quick(): """ Abbreviated version of test_mutate_all for travis. """ import perses.rjmc.topology_proposal as topology_proposal import perses.rjmc.geometry as geometry from perses.tests.utils import compute_potential_components from openmmtools import testsystems as ts geometry_engine = geometry.FFAllAngleGeometryEngine() aminos = ['ALA','VAL','GLY','PHE','PRO','TRP'] for aa in aminos: topology, positions = _get_capped_amino_acid(amino_acid=aa) modeller = app.Modeller(topology, positions) ff_filename = "amber99sbildn.xml" max_point_mutants = 1 ff = app.ForceField(ff_filename) system = ff.createSystem(modeller.topology) chain_id = '1' system_generator = topology_proposal.SystemGenerator([ff_filename]) pm_top_engine = topology_proposal.PointMutationEngine(modeller.topology, system_generator, chain_id, max_point_mutants=max_point_mutants) current_system = system current_topology = modeller.topology current_positions = modeller.positions minimize_integrator = openmm.VerletIntegrator(1.0*unit.femtosecond) platform = openmm.Platform.getPlatformByName("Reference") minimize_context = openmm.Context(current_system, minimize_integrator, platform) minimize_context.setPositions(current_positions) initial_state = minimize_context.getState(getEnergy=True) initial_potential = initial_state.getPotentialEnergy() openmm.LocalEnergyMinimizer.minimize(minimize_context) final_state = minimize_context.getState(getEnergy=True, getPositions=True) final_potential = final_state.getPotentialEnergy() current_positions = final_state.getPositions() print("Minimized initial structure from %s to %s" % (str(initial_potential), str(final_potential))) for k, proposed_amino in enumerate(aminos): pm_top_engine._allowed_mutations = [[('2',proposed_amino)]] pm_top_proposal = pm_top_engine.propose(current_system, current_topology) new_positions, logp = geometry_engine.propose(pm_top_proposal, current_positions, beta) new_system = pm_top_proposal.new_system if np.isnan(logp): raise Exception("NaN in the logp") integrator = openmm.VerletIntegrator(1*unit.femtoseconds) platform = openmm.Platform.getPlatformByName("Reference") context = openmm.Context(new_system, integrator, platform) context.setPositions(new_positions) state = context.getState(getEnergy=True) print(compute_potential_components(context)) potential = state.getPotentialEnergy() potential_without_units = potential / potential.unit print(str(potential)) if np.isnan(potential_without_units): raise Exception("Energy after proposal is NaN")
def test_run_point_mutation_propose(): """ Propose a random mutation in insulin """ import perses.rjmc.topology_proposal as topology_proposal pdbid = "2HIU" 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' system_generator = topology_proposal.SystemGenerator([ff_filename]) pm_top_engine = topology_proposal.PointMutationEngine( modeller.topology, system_generator, chain_id, max_point_mutants=max_point_mutants) pm_top_proposal = pm_top_engine.propose(system, modeller.topology)
def create_system(self): # set up the system using opls combo rules # Load the initial coords into the system and initialise forcefield = app.ForceField(self.xml_file) top = self.molecule.to_openmm_topology() positions = self.molecule.openmm_coordinates() # set the initial positions from the pdb modeller = app.Modeller(topology=top, positions=positions) # if there are virtual sites we need to add them here try: self.system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None) except ValueError: print("Virtual sites were found in the xml file") modeller.addExtraParticles(forcefield) self.system = forcefield.createSystem(modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None) # Use the opls combination rules. if self.molecule.combination == "opls": print("OPLS combination rules found in XML file") self.opls_lj() integrator = openmm.VerletIntegrator(1.0 * unit.femtoseconds) platform = openmm.Platform.getPlatformByName("Reference") self.simulation = app.Simulation(modeller.topology, self.system, integrator, platform) self.simulation.context.setPositions(modeller.positions)
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 create_modeller(self, atoms, keep_atoms=False): """ Makes a OpenMM modeller object based on given geometry Parameters ---------- atoms : list The subset of atom indices to either keep or delete keep_atoms : bool Whether to keep the atoms specified in the modeller or delete them. Default is false. Returns ------- A OpenMM modeller object Examples -------- >>> modeller = self.make_modeller() modeller = self.make_modeller(keep_qm=True) """ modeller = OM_app.Modeller(self.topology, self.pdb.getPositions()) if keep_atoms is False: OpenMMWrapper.delete_atoms(modeller, atoms) elif keep_atoms is True: OpenMMWrapper.keep_atoms(modeller, atoms) return modeller
def build_protein_system(host_pdbfile): host_ff = app.ForceField('amber99sbildn.xml', 'tip3p.xml') host_pdb = app.PDBFile(host_pdbfile) modeller = app.Modeller(host_pdb.topology, host_pdb.positions) host_coords = strip_units(host_pdb.positions) padding = 1.0 box_lengths = np.amax(host_coords, axis=0) - np.amin(host_coords, axis=0) box_lengths = box_lengths.value_in_unit_system(unit.md_unit_system) box_lengths = box_lengths+padding box = np.eye(3, dtype=np.float64)*box_lengths modeller.addSolvent(host_ff, boxSize=np.diag(box)*unit.nanometers, neutralize=False) solvated_host_coords = strip_units(modeller.positions) nha = host_coords.shape[0] nwa = solvated_host_coords.shape[0] - nha print(nha, "protein atoms", nwa, "water atoms") solvated_host_system = host_ff.createSystem( modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None, rigidWater=False ) return solvated_host_system, solvated_host_coords, nwa, nha, box, modeller.topology
def addHydrogens(self, output_prefix, structure_type, iteration): '''Protonate the complex and update the positions and topology Parameters ---------- output_prefix : string Path to output directory in which to save protonated structure structure_type : string 'WT' or 'Mutant' to be used in output file name iteration : int iteration number to use in the output file name ''' print("\tAdding hydrogens...") modeller = app.Modeller(self.complexTopology, self.complexPositions) modeller.addHydrogens(self.forcefield, pH=self._pH) # Save protonated PDB print( "\tWriting the protonated model to ", output_prefix + self._name + "_" + structure_type + "_" + str(iteration) + "_protonated.pdb") app.PDBFile.writeFile( modeller.topology, modeller.positions, open( output_prefix + self._name + "_" + structure_type + "_" + str(iteration) + "_protonated.pdb", 'w'), keepIds=True) self.complexTopology = modeller.topology self.complexPositions = modeller.positions
def test_limiting_allowed_residues(): """ Test example system with certain mutations allowed to mutate """ import perses.rjmc.topology_proposal as topology_proposal failed_mutants = 0 pdbid = "1G3F" topology, positions = load_pdbid_to_openmm(pdbid) modeller = app.Modeller(topology, positions) chain_id = 'B' to_delete = list() for chain in modeller.topology.chains(): if chain.id != chain_id: to_delete.append(chain) modeller.delete(to_delete) modeller.addHydrogens() ff_filename = "amber99sbildn.xml" ff = app.ForceField(ff_filename) system = ff.createSystem(modeller.topology) system_generator = topology_proposal.SystemGenerator([ff_filename]) max_point_mutants = 1 residues_allowed_to_mutate = ['903','904','905'] pl_top_library = topology_proposal.PointMutationEngine(modeller.topology, system_generator, chain_id, max_point_mutants=max_point_mutants, residues_allowed_to_mutate=residues_allowed_to_mutate) pl_top_proposal = pl_top_library.propose(system, modeller.topology)
def fix(pdbid, padding=PADDING): fixer = pdbfixer.PDBFixer(pdbid=pdbid) fixer.findMissingResidues() fixer.findNonstandardResidues() fixer.replaceNonstandardResidues() fixer.removeHeterogens(True) fixer.findMissingAtoms() fixer.addMissingAtoms() fixer.addMissingHydrogens(7.0) numChains = len(list(fixer.topology.chains())) fixer.removeChains(range(1, numChains)) file_handle = open("%s_fixed.pdb" % pdbid, 'wb') app.PDBFile.writeFile(fixer.topology, fixer.positions, file_handle) file_handle.close() ff_name = "amber99sbildn" water_name = 'tip3p' which_forcefield = "%s.xml" % ff_name which_water = '%s.xml' % water_name out_pdb_filename = "./equil/equil.pdb" ff = app.ForceField(which_forcefield, which_water) modeller = app.Modeller(fixer.topology, fixer.positions) modeller.addSolvent(ff, padding=padding) app.PDBFile.writeFile(modeller.topology, modeller.positions, open("./%s_box.pdb" % pdbid, 'w'))
def _build_system( self, molecule: Ligand, input_files: Optional[List[str]] = None ) -> System: """Serialise the input XML system using openmm.""" modeller = app.Modeller( molecule.to_openmm_topology(), molecule.openmm_coordinates() ) xml = None if input_files is not None: for file in input_files: if file.endswith(".xml"): xml = file break # if we did not find one guess the name xml = xml or f"{molecule.name}.xml" forcefield = app.ForceField(xml) # Check for virtual sites try: system = forcefield.createSystem( modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None ) except ValueError: print("Virtual sites were found in the xml file") modeller.addExtraParticles(forcefield) system = forcefield.createSystem( modeller.topology, nonbondedMethod=app.NoCutoff, constraints=None ) return system
def test_run_point_mutation_propose(): """ Propose a random mutation in insulin """ import perses.rjmc.topology_proposal as topology_proposal pdbid = "2HIU" topology, positions = load_pdbid_to_openmm(pdbid) modeller = app.Modeller(topology, positions) for chain in modeller.topology.chains(): pass modeller.delete([chain]) max_point_mutants = 1 chain_id = 'A' system_generator = create_simple_protein_system_generator() system = system_generator.create_system(modeller.topology) pm_top_engine = topology_proposal.PointMutationEngine( modeller.topology, system_generator, chain_id, max_point_mutants=max_point_mutants) pm_top_proposal = pm_top_engine.propose(system, modeller.topology)
def __setup_system_ex_mm(self): with self.logger("__setup_system_ex_mm") as logger: if "openmm_system_generator" not in self.__dict__: amber_forcefields = ['amber/protein.ff14SB.xml', 'amber/phosaa10', 'amber/tip3p_standard.xml'] small_molecule_forcefield = 'openff-1.1.0' # small_molecule_forcefield = 'gaff-2.11' self.openmm_system_generator = SystemGenerator(forcefields=amber_forcefields, forcefield_kwargs=self.params, molecules=[self.mol], small_molecule_forcefield=small_molecule_forcefield, ) else: self.openmm_system_generator.add_molecules([self.mol]) self.modeller = app.Modeller(self.topology, self.positions) self.modeller.addSolvent(self.openmm_system_generator.forcefield, model='tip3p', ionicStrength=100 * unit.millimolar, padding=1.0 * unit.nanometers) self.boxvec = self.modeller.getTopology().getPeriodicBoxVectors() self.topology, self.positions = self.modeller.getTopology(), self.modeller.getPositions() self.system = self.openmm_system_generator.create_system(self.topology) self.system.setDefaultPeriodicBoxVectors(*self.modeller.getTopology().getPeriodicBoxVectors()) with open("{}".format(self.config.pdb_file_name), 'w') as f: app.PDBFile.writeFile(self.topology, self.positions, file=f, keepIds=True) logger.log("wrote ", "{}".format(self.config.pdb_file_name)) with open("{}".format(self.config.pdb_file_name), 'r') as f: self.pdb = app.PDBFile(f) return self.system, self.topology, self.positions
def test_run_peptide_library_engine(): """ Test example system with peptide and library """ import perses.rjmc.topology_proposal as topology_proposal failed_mutants = 0 pdbid = "1G3F" topology, positions = load_pdbid_to_openmm(pdbid) modeller = app.Modeller(topology, positions) chain_id = 'B' to_delete = list() for chain in modeller.topology.chains(): if chain.id != chain_id: to_delete.append(chain) modeller.delete(to_delete) modeller.addHydrogens() ff_filename = "amber99sbildn.xml" ff = app.ForceField(ff_filename) ff.loadFile("tip3p.xml") modeller.addSolvent(ff) system = ff.createSystem(modeller.topology) system_generator = topology_proposal.SystemGenerator([ff_filename]) library = ['AVILMFYQP', 'RHKDESTNQ', 'STNQCFGPL'] pl_top_library = topology_proposal.PeptideLibraryEngine( system_generator, library, chain_id) pl_top_proposal = pl_top_library.propose(system, modeller.topology)
def test_run_point_mutation_propose(): """ Propose a random mutation in insulin """ import perses.rjmc.topology_proposal as topology_proposal pdbid = "2HIU" topology, positions = load_pdbid_to_openmm(pdbid) modeller = app.Modeller(topology, positions) for chain in modeller.topology.chains(): pass modeller.delete([chain]) max_point_mutants = 1 chain_id = 'A' # Pull the allowable mutatable residues.. _chain = [ chain for chain in modeller.topology.chains() if chain.id == chain_id ][0] residue_ids = [ residue.id for residue in _chain.residues() if residue.name != 'CYS' ][1:-1] system_generator = create_simple_protein_system_generator() system = system_generator.create_system(modeller.topology) pm_top_engine = topology_proposal.PointMutationEngine( modeller.topology, system_generator, chain_id, max_point_mutants=max_point_mutants, residues_allowed_to_mutate=residue_ids) pm_top_proposal = pm_top_engine.propose(system, modeller.topology)
def test_propose_self(): """ Propose a mutation to remain at WT in insulin """ import perses.rjmc.topology_proposal as topology_proposal pdbid = "2HIU" topology, positions = load_pdbid_to_openmm(pdbid) modeller = app.Modeller(topology, positions) for chain in modeller.topology.chains(): pass modeller.delete([chain]) system_generator = create_simple_protein_system_generator() system = system_generator.create_system(modeller.topology) chain_id = 'A' for chain in modeller.topology.chains(): if chain.id == chain_id: residues = chain._residues mutant_res = np.random.choice(residues[1:-1]) allowed_mutations = [(mutant_res.id, mutant_res.name)] pm_top_engine = topology_proposal.PointMutationEngine( modeller.topology, system_generator, chain_id, allowed_mutations=allowed_mutations) pm_top_proposal = pm_top_engine.propose(system, modeller.topology) assert pm_top_proposal.old_topology == pm_top_proposal.new_topology assert pm_top_proposal.old_system == pm_top_proposal.new_system assert pm_top_proposal.old_chemical_state_key == pm_top_proposal.new_chemical_state_key
def __init__(self, pdb_file=None, forcefield=None, pH=7.0, addHs=True, mpi_comm=None): self._units = _Units() self.pdb_file = None self.forcefield = None self.pH = None self.modeller = None self.topology = None self.positions = None self.n_atoms = None self._heavy_atoms_indices = None self._ca_atoms_indices = None self.__addHs_log = None if pdb_file: pdb_aux = app.PDBFile(pdb_file) self.modeller = app.Modeller(pdb_aux.topology, pdb_aux.positions) self.forcefield = app.ForceField(forcefield) self.pH = pH if addHs: self.__addHs_log = self.modeller.addHydrogens(self.forcefield, pH=self.pH) self.topology = self.modeller.getTopology() self.positions = self.modeller.getPositions() self.n_atoms = len(self.positions) self._heavy_atoms_indices = utils.heavy_atoms_indices(self.topology) self._ca_atoms_indices = utils.ca_atoms_indices(self.topology) if mpi_comm is not None: self.equal_positions_across_MPI_Universe(mpi_comm)
def test_propose_self(): """ Propose a mutation to remain at WT in insulin """ import perses.rjmc.topology_proposal as topology_proposal pdbid = "2HIU" 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" ff = app.ForceField(ff_filename) system = ff.createSystem(modeller.topology) chain_id = 'A' for chain in modeller.topology.chains(): if chain.id == chain_id: residues = chain._residues mutant_res = np.random.choice(residues) allowed_mutations = [[(mutant_res.id,mutant_res.name)]] system_generator = topology_proposal.SystemGenerator([ff_filename]) pm_top_engine = topology_proposal.PointMutationEngine(modeller.topology, system_generator, chain_id, allowed_mutations=allowed_mutations, verbose=True) print('Self mutation:') pm_top_proposal = pm_top_engine.propose(system, modeller.topology) assert pm_top_proposal.old_topology == pm_top_proposal.new_topology assert pm_top_proposal.old_system == pm_top_proposal.new_system assert pm_top_proposal.old_chemical_state_key == pm_top_proposal.new_chemical_state_key
def test_complex(self): """Test parameterizing a protein:ligand complex in vacuum""" from openmmforcefields.generators import SystemGenerator for name, testsystem in self.testsystems.items(): print(f'Testing parameterization of {name} in vacuum') molecules = testsystem['molecules'] # Select a complex from the set ligand_index = 0 complex_structure = testsystem['complex_structures'][ligand_index] molecule = molecules[ligand_index] openmm_topology = complex_structure.topology cache = os.path.join(get_data_filename(os.path.join('perses_jacs_systems', name)), 'cache.json') # Create a system in vacuum generator = SystemGenerator(forcefields=self.amber_forcefields, molecules=molecules, cache=cache) system = generator.create_system(openmm_topology) assert system.getNumParticles() == len(complex_structure.atoms) # Create solvated structure from simtk.openmm import app from simtk import unit modeller = app.Modeller(complex_structure.topology, complex_structure.positions) modeller.addSolvent(generator.forcefield, padding=0*unit.angstroms, ionicStrength=300*unit.millimolar) # Create a system with solvent and ions system = generator.create_system(modeller.topology) assert system.getNumParticles() == len(list(modeller.topology.atoms())) with open('test.pdb', 'w') as outfile: app.PDBFile.writeFile(modeller.topology, modeller.positions, outfile)
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 create_nacl_system(): # Read ion pair. pdbfile = app.PDBFile('nacl.pdb') # Load forcefield. forcefields_to_use = ['tip3p.xml', 'amber96.xml'] forcefield = app.ForceField(*forcefields_to_use) # Solvate. modeller = app.Modeller(pdbfile.topology, pdbfile.positions) modeller.addSolvent(forcefield, model='tip3p', padding=10.0 * units.angstroms) # Create System. cutoff = 9.0 * units.angstroms #nonbondedMethod = app.CutoffPeriodic nonbondedMethod = app.PME system = forcefield.createSystem(modeller.topology, nonbondedMethod=nonbondedMethod, nonbondedCutoff=cutoff, rigidWater=True) # Extract positions. positions = modeller.positions # Extract topology. topology = modeller.topology return [system, positions, topology]
def _solvate(self, topology, positions, water_model, phase, ionic_strength, box_dimensions=None): """ Generate a solvated topology, positions, and system for a given input topology and positions. For generating the system, the forcefield files provided in the constructor will be used. Parameters ---------- topology : app.Topology Topology of the system to solvate positions : [n, 3] ndarray of Quantity nm the positions of the unsolvated system forcefield : SystemGenerator.forcefield forcefield file of solvent to add water_model : str solvent model to use for solvation phase : str if phase == vacuum, then the complex will not be solvated with water; else, it will be solvated with tip3p ionic_strength : float * unit.molar the total concentration of ions (both positive and negative) to add using Modeller. This does not include ions that are added to neutralize the system. Note that only monovalent ions are currently supported. Returns ------- solvated_topology : app.Topology Topology of the system with added waters solvated_positions : [n + 3(n_waters), 3] ndarray of Quantity nm Solvated positions solvated_system : openmm.System The parameterized system, containing a barostat if one was specified. """ modeller = app.Modeller(topology, positions) # Now we have to add missing atoms if phase != 'vacuum': _logger.info(f"solvating at {ionic_strength} using {water_model}") if not box_dimensions: modeller.addSolvent(self.system_generator.forcefield, model=water_model, padding=0.9 * unit.nanometers, ionicStrength=ionic_strength) else: modeller.addSolvent(self.system_generator.forcefield, model=water_model, boxSize=box_dimensions, ionicStrength=ionic_strength) else: pass solvated_topology = modeller.getTopology() if box_dimensions: solvated_topology.setUnitCellDimensions(box_dimensions) solvated_positions = modeller.getPositions() # Canonicalize the solvated positions: turn tuples into np.array solvated_positions = unit.quantity.Quantity(value=np.array([list(atom_pos) for atom_pos in solvated_positions.value_in_unit_system(unit.md_unit_system)]), unit=unit.nanometers) solvated_system = self.system_generator.create_system(solvated_topology) return solvated_topology, solvated_positions, solvated_system
def generate_solvated_hybrid_test_topology(current_mol_name="naphthalene", proposed_mol_name="benzene"): """ Generate a test solvated topology proposal, current positions, and new positions triplet from two IUPAC molecule names. Parameters ---------- current_mol_name : str, optional name of the first molecule proposed_mol_name : str, optional name of the second molecule Returns ------- topology_proposal : perses.rjmc.topology_proposal The topology proposal representing the transformation current_positions : np.array, unit-bearing The positions of the initial system new_positions : np.array, unit-bearing The positions of the new system """ import simtk.openmm.app as app from openmoltools import forcefield_generators from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename current_mol, unsolv_old_system, pos_old, top_old = createSystemFromIUPAC(current_mol_name) proposed_mol = createOEMolFromIUPAC(proposed_mol_name) initial_smiles = oechem.OEMolToSmiles(current_mol) final_smiles = oechem.OEMolToSmiles(proposed_mol) gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) modeller = app.Modeller(top_old, pos_old) modeller.addSolvent(forcefield, model='tip3p', padding=9.0*unit.angstrom) solvated_topology = modeller.getTopology() solvated_positions = modeller.getPositions() solvated_system = forcefield.createSystem(solvated_topology, nonbondedMethod=app.PME, removeCMMotion=False) barostat = openmm.MonteCarloBarostat(1.0*unit.atmosphere, temperature, 50) solvated_system.addForce(barostat) gaff_filename = get_data_filename('data/gaff.xml') system_generator = SystemGenerator([gaff_filename, 'amber99sbildn.xml', 'tip3p.xml'], barostat=barostat, forcefield_kwargs={'removeCMMotion': False, 'nonbondedMethod': app.PME}) geometry_engine = geometry.FFAllAngleGeometryEngine() proposal_engine = SmallMoleculeSetProposalEngine( [initial_smiles, final_smiles], system_generator, residue_name=current_mol_name) #generate topology proposal topology_proposal = proposal_engine.propose(solvated_system, solvated_topology) #generate new positions with geometry engine new_positions, _ = geometry_engine.propose(topology_proposal, solvated_positions, beta) return topology_proposal, solvated_positions, new_positions
def generate_atp(phase='vacuum'): """ modify the AlanineDipeptideVacuum test system to be parametrized with amber14ffsb in vac or solvent (tip3p) """ import openmmtools.testsystems as ts atp = ts.AlanineDipeptideVacuum(constraints=app.HBonds, hydrogenMass=4 * unit.amus) forcefield_files = [ 'gaff.xml', 'amber14/protein.ff14SB.xml', 'amber14/tip3p.xml' ] if phase == 'vacuum': barostat = None system_generator = SystemGenerator(forcefield_files, barostat=barostat, forcefield_kwargs={ 'removeCMMotion': False, 'ewaldErrorTolerance': 1e-4, 'nonbondedMethod': app.NoCutoff, 'constraints': app.HBonds, 'hydrogenMass': 4 * unit.amus }) atp.system = system_generator.build_system( atp.topology) #update the parametrization scheme to amberff14sb elif phase == 'solvent': barostat = openmm.MonteCarloBarostat(1.0 * unit.atmosphere, 300 * unit.kelvin, 50) system_generator = SystemGenerator(forcefield_files, barostat=barostat, forcefield_kwargs={ 'removeCMMotion': False, 'ewaldErrorTolerance': 1e-4, 'nonbondedMethod': app.PME, 'constraints': app.HBonds, 'hydrogenMass': 4 * unit.amus }) if phase == 'solvent': modeller = app.Modeller(atp.topology, atp.positions) modeller.addSolvent(system_generator._forcefield, model='tip3p', padding=9 * unit.angstroms, ionicStrength=0.15 * unit.molar) solvated_topology = modeller.getTopology() solvated_positions = modeller.getPositions() # canonicalize the solvated positions: turn tuples into np.array atp.positions = unit.quantity.Quantity(value=np.array([ list(atom_pos) for atom_pos in solvated_positions.value_in_unit_system(unit.md_unit_system) ]), unit=unit.nanometers) atp.topology = solvated_topology atp.system = system_generator.build_system(atp.topology) return atp, system_generator
def copy_molcomplex(molcomplex): tmp_complex = deepcopy(molcomplex) tmp_complex.modeller = app.Modeller(molcomplex.topology, molcomplex.positions) tmp_complex.topology = tmp_complex.modeller.getTopology() return tmp_complex