def run_rj_proposals(top_prop, configuration_traj, use_sterics, ncmc_nsteps, n_replicates, bond_softening_constant=1.0, angle_softening_constant=1.0): ncmc_engine = NCMCEngine(nsteps=ncmc_nsteps, pressure=1.0*unit.atmosphere, bond_softening_constant=bond_softening_constant, angle_softening_constant=angle_softening_constant) geometry_engine = FFAllAngleGeometryEngine(use_sterics=use_sterics, bond_softening_constant=bond_softening_constant, angle_softening_constant=angle_softening_constant) initial_thermodynamic_state = states.ThermodynamicState(top_prop.old_system, temperature=temperature, pressure=1.0*unit.atmosphere) final_thermodynamic_state = states.ThermodynamicState(top_prop.new_system, temperature=temperature, pressure=1.0*unit.atmosphere) traj_indices = np.arange(0, configuration_traj.n_frames) results = np.zeros([n_replicates, 4]) for i in tqdm.trange(n_replicates): frame_index = np.random.choice(traj_indices) initial_sampler_state = traj_frame_to_sampler_state(configuration_traj, frame_index) initial_logP = - compute_reduced_potential(initial_thermodynamic_state, initial_sampler_state) proposed_geometry, logP_geometry_forward = geometry_engine.propose(top_prop, initial_sampler_state.positions, beta) proposed_sampler_state = states.SamplerState(proposed_geometry, box_vectors=initial_sampler_state.box_vectors) final_old_sampler_state, final_sampler_state, logP_work, initial_hybrid_logP, final_hybrid_logP = ncmc_engine.integrate(top_prop, initial_sampler_state, proposed_sampler_state) final_logP = - compute_reduced_potential(final_thermodynamic_state, final_sampler_state) logP_reverse = geometry_engine.logp_reverse(top_prop, final_sampler_state.positions, final_old_sampler_state.positions, beta) results[i, 0] = initial_hybrid_logP - initial_logP results[i, 1] = logP_reverse - logP_geometry_forward results[i, 2] = final_logP - final_hybrid_logP results[i, 3] = logP_work return results
def setup_class(cls): """Shared test cases for the suite.""" temperature = 300 * unit.kelvin # Default protocols for tests. cls.protocol = dict(lambda_electrostatics=[1.0, 0.5, 0.0, 0.0, 0.0], lambda_sterics=[1.0, 1.0, 1.0, 0.5, 0.0]) cls.restrained_protocol = dict( lambda_electrostatics=[1.0, 1.0, 0.0, 0.0], lambda_sterics=[1.0, 1.0, 1.0, 0.0], lambda_restraints=[0.0, 1.0, 1.0, 1.0]) # Ligand-receptor in implicit solvent. test_system = testsystems.HostGuestImplicit() thermodynamic_state = states.ThermodynamicState( test_system.system, temperature=temperature) sampler_state = states.SamplerState( positions=test_system.positions, box_vectors=test_system.system.getDefaultPeriodicBoxVectors()) topography = Topography(test_system.topology, ligand_atoms='resname B2') cls.host_guest_implicit = ('Host-guest implicit', thermodynamic_state, sampler_state, topography) # Ligand-receptor in explicit solvent. test_system = testsystems.HostGuestExplicit() thermodynamic_state = states.ThermodynamicState( test_system.system, temperature=temperature) positions = test_system.positions box_vectors = test_system.system.getDefaultPeriodicBoxVectors() sampler_state = states.SamplerState(positions=positions, box_vectors=box_vectors) topography = Topography(test_system.topology, ligand_atoms='resname B2') cls.host_guest_explicit = ('Host-guest explicit', thermodynamic_state, sampler_state, topography) # Peptide solvated in explicit solvent. test_system = testsystems.AlanineDipeptideExplicit() thermodynamic_state = states.ThermodynamicState( test_system.system, temperature=temperature) positions = test_system.positions box_vectors = test_system.system.getDefaultPeriodicBoxVectors() sampler_state = states.SamplerState(positions=positions, box_vectors=box_vectors) topography = Topography(test_system.topology) cls.alanine_explicit = ('Alanine dipeptide explicit', thermodynamic_state, sampler_state, topography) # All test cases cls.all_test_cases = [ cls.host_guest_implicit, cls.host_guest_explicit, cls.alanine_explicit ]
def generate_endpoint_thermodynamic_states( system: openmm.System, topology_proposal: TopologyProposal): """ Generate endpoint thermodynamic states for the system Parameters ---------- system : openmm.System System object corresponding to thermodynamic state topology_proposal : perses.rjmc.topology_proposal.TopologyProposal TopologyProposal representing transformation Returns ------- nonalchemical_zero_thermodynamic_state : ThermodynamicState Nonalchemical thermodynamic state for lambda zero endpoint nonalchemical_one_thermodynamic_state : ThermodynamicState Nonalchemical thermodynamic state for lambda one endpoint lambda_zero_thermodynamic_state : ThermodynamicState Alchemical (hybrid) thermodynamic state for lambda zero lambda_one_thermodynamic_State : ThermodynamicState Alchemical (hybrid) thermodynamic state for lambda one """ #create the thermodynamic state from perses.annihilation.lambda_protocol import RelativeAlchemicalState lambda_zero_alchemical_state = RelativeAlchemicalState.from_system(system) lambda_one_alchemical_state = copy.deepcopy(lambda_zero_alchemical_state) #ensure their states are set appropriately lambda_zero_alchemical_state.set_alchemical_parameters(0.0) lambda_one_alchemical_state.set_alchemical_parameters(1.0) check_system(system) #create the base thermodynamic state with the hybrid system thermodynamic_state = states.ThermodynamicState(system, temperature=temperature) #Create thermodynamic states for the nonalchemical endpoints nonalchemical_zero_thermodynamic_state = states.ThermodynamicState( topology_proposal.old_system, temperature=temperature) nonalchemical_one_thermodynamic_state = states.ThermodynamicState( topology_proposal.new_system, temperature=temperature) #Now create the compound states with different alchemical states lambda_zero_thermodynamic_state = states.CompoundThermodynamicState( thermodynamic_state, composable_states=[lambda_zero_alchemical_state]) lambda_one_thermodynamic_state = states.CompoundThermodynamicState( thermodynamic_state, composable_states=[lambda_one_alchemical_state]) return nonalchemical_zero_thermodynamic_state, nonalchemical_one_thermodynamic_state, lambda_zero_thermodynamic_state, lambda_one_thermodynamic_state
def generate_example_waterbox_states(temperature=300.0 * unit.kelvin, pressure=1.0 * unit.atmosphere): """ This is a convenience function to generate a CompoundThermodynamicState and SamplerState to use in other tests. Here, we generate an alchemical water box """ #get the water box testsystem water_ts = testsystems.AlchemicalWaterBox() system = water_ts.system positions = water_ts.positions #construct the openmmtools objects for it sampler_state = states.SamplerState( positions, box_vectors=system.getDefaultPeriodicBoxVectors()) thermodynamic_state = states.ThermodynamicState(system, temperature=temperature, pressure=pressure) #make an alchemical state alchemical_state = alchemy.AlchemicalState.from_system(system) alchemical_state.set_alchemical_parameters(0.0) #make a compound thermodynamic state cpd_thermodynamic_state = states.CompoundThermodynamicState( thermodynamic_state, [alchemical_state]) return cpd_thermodynamic_state, sampler_state, water_ts.topology
def test_harmonic_standard_state(): """ Test that the expected harmonic standard state correction is close to our approximation Also ensures that PBC bonds are being computed and disabled correctly as expected """ LJ_fluid = testsystems.LennardJonesFluid() # Create Harmonic restraint. restraint = yank.restraints.create_restraint('Harmonic', restrained_receptor_atoms=1) # Determine other parameters. ligand_atoms = [3, 4, 5] topography = Topography(LJ_fluid.topology, ligand_atoms=ligand_atoms) sampler_state = states.SamplerState(positions=LJ_fluid.positions) thermodynamic_state = states.ThermodynamicState(system=LJ_fluid.system, temperature=300.0 * unit.kelvin) restraint.determine_missing_parameters(thermodynamic_state, sampler_state, topography) spring_constant = restraint.spring_constant # Compute standard-state volume for a single molecule in a box of size (1 L) / (avogadros number) liter = 1000.0 * unit.centimeters**3 # one liter box_volume = liter / (unit.AVOGADRO_CONSTANT_NA * unit.mole ) # standard state volume analytical_shell_volume = ( 2 * math.pi / (spring_constant * thermodynamic_state.beta))**(3.0 / 2) analytical_standard_state_G = -math.log( box_volume / analytical_shell_volume) restraint_standard_state_G = restraint.get_standard_state_correction( thermodynamic_state) np.testing.assert_allclose(analytical_standard_state_G, restraint_standard_state_G)
def setup_class(cls): lysozyme = testsystems.LysozymeImplicit() system, positions = lysozyme.system, lysozyme.positions thermodynamic_state = states.ThermodynamicState(system, 300*unit.kelvin) sampler_state = states.SamplerState(positions) topography = Topography(lysozyme.topology, ligand_atoms='resname TMP') cls.lysozyme_test_case = (thermodynamic_state, sampler_state, topography)
def restraint_selection_template(topography_ligand_atoms=None, restrained_receptor_atoms=None, restrained_ligand_atoms=None, topography_regions=None): """The DSL atom selection works as expected.""" test_system = testsystems.HostGuestVacuum() topography = Topography(test_system.topology, ligand_atoms=topography_ligand_atoms) if topography_regions is not None: for region, selection in topography_regions.items(): topography.add_region(region, selection) sampler_state = states.SamplerState(positions=test_system.positions) thermodynamic_state = states.ThermodynamicState(test_system.system, temperature=300.0 * unit.kelvin) # Initialize with DSL and without processing the string raises an error. restraint = yank.restraints.Harmonic(spring_constant=2.0 * unit.kilojoule_per_mole / unit.nanometer ** 2, restrained_receptor_atoms=restrained_receptor_atoms, restrained_ligand_atoms=restrained_ligand_atoms) with nose.tools.assert_raises(yank.restraints.RestraintParameterError): restraint.restrain_state(thermodynamic_state) # After parameter determination, the indices of the restrained atoms are correct. restraint.determine_missing_parameters(thermodynamic_state, sampler_state, topography) assert len(restraint.restrained_receptor_atoms) == 14 assert len(restraint.restrained_ligand_atoms) == 30 # The bond force is configured correctly. restraint.restrain_state(thermodynamic_state) system = thermodynamic_state.system for force in system.getForces(): if isinstance(force, openmm.CustomCentroidBondForce): assert force.getBondParameters(0)[0] == (0, 1) assert len(force.getGroupParameters(0)[0]) == 14 assert len(force.getGroupParameters(1)[0]) == 30 assert isinstance(force, openmm.CustomCentroidBondForce) # We have found a force.
def test_BoreschLike_standard_state_analytical(): """ Perform some analytical tests of the Boresch standard state correction. Also ensures that PBC is being handled correctly """ LJ_fluid = testsystems.LennardJonesFluid() # Define receptor and ligand atoms receptor_atoms = [0, 1, 2] ligand_atoms = [3, 4, 5] # Create restraint K_r = 1.0 * unit.kilocalories_per_mole / unit.angstrom**2 r_0 = 0.0 * unit.angstrom K_theta = 0.0 * unit.kilocalories_per_mole / unit.degrees**2 theta_0 = 30.0 * unit.degrees topography = Topography(LJ_fluid.topology, ligand_atoms=ligand_atoms) sampler_state = states.SamplerState(positions=LJ_fluid.positions) thermodynamic_state = states.ThermodynamicState(system=LJ_fluid.system, temperature=300.0 * unit.kelvin) for restraint_name in ['Boresch', 'PeriodicTorsionBoresch']: restraint = yank.restraints.create_restraint( 'Boresch', restrained_receptor_atoms=receptor_atoms, restrained_ligand_atoms=ligand_atoms, K_r=K_r, r_aA0=r_0, K_thetaA=K_theta, theta_A0=theta_0, K_thetaB=K_theta, theta_B0=theta_0, K_phiA=K_theta, phi_A0=theta_0, K_phiB=K_theta, phi_B0=theta_0, K_phiC=K_theta, phi_C0=theta_0) # Determine other parameters restraint.determine_missing_parameters(thermodynamic_state, sampler_state, topography) # Compute standard-state volume for a single molecule in a box of size (1 L) / (avogadros number) liter = 1000.0 * unit.centimeters**3 # one liter box_volume = liter / (unit.AVOGADRO_CONSTANT_NA * unit.mole ) # standard state volume analytical_shell_volume = (2 * math.pi / (K_r * thermodynamic_state.beta))**(3.0 / 2) analytical_standard_state_G = -math.log( box_volume / analytical_shell_volume) restraint_standard_state_G = restraint.get_standard_state_correction( thermodynamic_state) msg = 'Failed test for restraint {}'.format(restraint_name) np.testing.assert_allclose(analytical_standard_state_G, restraint_standard_state_G, err_msg=msg)
def setup_class(cls): """Create the thermodynamic states used in the test suite.""" water_test = testsystems.WaterBox(box_edge=2.0*unit.nanometer) cls.water_300k = states.ThermodynamicState(water_test.system, 300*unit.kelvin) cls.water_310k = states.ThermodynamicState(water_test.system, 310*unit.kelvin) cls.water_310k_1atm = states.ThermodynamicState(water_test.system, 310*unit.kelvin, 1*unit.atmosphere) cls.verlet_2fs = openmm.VerletIntegrator(2.0*unit.femtosecond) cls.verlet_3fs = openmm.VerletIntegrator(3.0*unit.femtosecond) cls.langevin_2fs_310k = openmm.LangevinIntegrator(310*unit.kelvin, 5.0/unit.picosecond, 2.0*unit.femtosecond) cls.compatible_states = [cls.water_300k, cls.water_310k] cls.compatible_integrators = [cls.verlet_2fs, cls.verlet_3fs] cls.incompatible_states = [cls.water_310k, cls.water_310k_1atm] cls.incompatible_integrators = [cls.verlet_2fs, cls.langevin_2fs_310k]
def test_compute_restraint_volume(self): """Test the calculation of the restraint volume.""" testsystem = testsystems.TolueneVacuum() thermodynamic_state = states.ThermodynamicState( testsystem.system, 300 * unit.kelvin) energy_cutoffs = np.linspace(0.0, 10.0, num=3) radius_cutoffs = np.linspace(0.0, 5.0, num=3) * unit.nanometers def assert_integrated_analytical_equal(restraint, square_well, radius_cutoff, energy_cutoff): args = [ thermodynamic_state, square_well, radius_cutoff, energy_cutoff ] # For flat-bottom, the calculation is only partially analytical. analytical_volume = restraint._compute_restraint_volume(*args) # Make sure there's no analytical component (from _determine_integral_limits) # in the numerical integration calculation. copied_restraint = copy.deepcopy(restraint) for parent_cls in [ RadiallySymmetricCentroidRestraintForce, RadiallySymmetricBondRestraintForce ]: if isinstance(copied_restraint, parent_cls): copied_restraint.__class__ = parent_cls integrated_volume = copied_restraint._integrate_restraint_volume( *args) err_msg = '{}: square_well={}, radius_cutoff={}, energy_cutoff={}\n'.format( restraint.__class__.__name__, square_well, radius_cutoff, energy_cutoff) err_msg += 'integrated_volume={}, analytical_volume={}'.format( integrated_volume, analytical_volume) assert utils.is_quantity_close(integrated_volume, analytical_volume, rtol=1e-2), err_msg for restraint in self.restraints: # Test integrated and analytical agree with no cutoffs. yield assert_integrated_analytical_equal, restraint, False, None, None for square_well in [True, False]: # Try energies and distances singly and together. for energy_cutoff in energy_cutoffs: yield assert_integrated_analytical_equal, restraint, square_well, None, energy_cutoff for radius_cutoff in radius_cutoffs: yield assert_integrated_analytical_equal, restraint, square_well, radius_cutoff, None for energy_cutoff, radius_cutoff in zip( energy_cutoffs, radius_cutoffs): yield assert_integrated_analytical_equal, restraint, square_well, radius_cutoff, energy_cutoff for energy_cutoff, radius_cutoff in zip( energy_cutoffs, reversed(radius_cutoffs)): yield assert_integrated_analytical_equal, restraint, square_well, radius_cutoff, energy_cutoff
def test_partial_parametrization(): """The automatic restraint parametrization doesn't overwrite user values.""" # Create states and identify ligand/receptor. test_system = testsystems.HostGuestVacuum() topography = Topography(test_system.topology, ligand_atoms='resname B2') sampler_state = states.SamplerState(positions=test_system.positions) thermodynamic_state = states.ThermodynamicState(test_system.system, temperature=300.0*unit.kelvin) # Test case: (restraint_type, constructor_kwargs) boresch = dict(restrained_ligand_atoms=[130, 131, 136], K_r=1.0*unit.kilojoule_per_mole/unit.angstroms**2) test_cases = [ ('Harmonic', dict(spring_constant=2.0*unit.kilojoule_per_mole/unit.nanometer**2, restrained_receptor_atoms=[5])), ('FlatBottom', dict(well_radius=1.0*unit.angstrom, restrained_ligand_atoms=[130])), ('Boresch', boresch), ('PeriodicTorsionBoresch', boresch), ] if OpenMM73.dev_validate: test_cases.append(('RMSD', dict(restrained_ligand_atoms=[130, 131, 136], K_RMSD=1.0 * unit.kilojoule_per_mole / unit.angstroms ** 2))) for restraint_type, kwargs in test_cases: state = copy.deepcopy(thermodynamic_state) restraint = yank.restraints.create_restraint(restraint_type, **kwargs) # Test-precondition: The restraint has undefined parameters. with nose.tools.assert_raises(yank.restraints.RestraintParameterError): restraint.restrain_state(state) # The automatic parametrization maintains user values. restraint.determine_missing_parameters(state, sampler_state, topography) for parameter_name, parameter_value in kwargs.items(): assert getattr(restraint, parameter_name) == parameter_value # The rest of the parameters has been determined. restraint.get_standard_state_correction(state) # The force has been configured correctly. restraint.restrain_state(state) system = state.system for force in system.getForces(): # RadiallySymmetricRestraint between two single atoms. if isinstance(force, openmm.CustomBondForce): particle1, particle2, _ = force.getBondParameters(0) assert particle1 == restraint.restrained_receptor_atoms[0] assert particle2 == restraint.restrained_ligand_atoms[0] # Boresch restraint. elif isinstance(force, openmm.CustomCompoundBondForce): particles, _ = force.getBondParameters(0) assert particles == tuple(restraint.restrained_receptor_atoms + restraint.restrained_ligand_atoms) # RMSD restraint. elif OpenMM73.dev_validate and isinstance(force, openmm.CustomCVForce): rmsd_cv = force.getCollectiveVariable(0) particles = rmsd_cv.getParticles() assert particles == tuple(restraint.restrained_receptor_atoms + restraint.restrained_ligand_atoms)
def build_test_case(): """Create a new ThermodynamicState, SamplerState and Topography.""" # Create a test system t = HostGuestNoninteracting() # Create states and topography encoding the info to determine the parameters. topography = Topography(t.topology, ligand_atoms='resname B2') sampler_state = states.SamplerState(positions=t.positions) thermodynamic_state = states.ThermodynamicState(system=t.system, temperature=300.0*unit.kelvin) return thermodynamic_state, sampler_state, topography
def _anneal_ligand(self): """Anneal ligand interactions to clean up clashes. """ alchemical_system = self._alchemically_modify_ligand(self.system) from openmmtools.alchemy import AlchemicalState alchemical_state = AlchemicalState.from_system(alchemical_system) thermodynamic_state = states.ThermodynamicState( system=alchemical_system, temperature=self.temperature, pressure=self.pressure) alchemical_thermodynamic_state = states.CompoundThermodynamicState( thermodynamic_state=thermodynamic_state, composable_states=[alchemical_state]) # Initial softened minimization print('Minimizing softened ligand...') alchemical_thermodynamic_state.lambda_sterics = 0.01 alchemical_thermodynamic_state.lambda_electrostatics = 0.0 self.sampler_state = self._minimize_sampler_state( alchemical_thermodynamic_state, self.sampler_state) # Anneal n_annealing_steps = 1000 integrator = openmm.LangevinIntegrator(self.temperature, 90.0 / unit.picoseconds, 1.0 * unit.femtoseconds) context, integrator = openmmtools.cache.global_context_cache.get_context( alchemical_thermodynamic_state, integrator) self.sampler_state.apply_to_context(context) print('Annealing sterics...') for step in progressbar.progressbar(range(n_annealing_steps)): alchemical_state.lambda_sterics = float(step) / float( n_annealing_steps) alchemical_state.lambda_electrostatics = 0.0 alchemical_state.apply_to_context(context) integrator.step(1) print('Annealing electrostatics...') for step in progressbar.progressbar(range(n_annealing_steps)): alchemical_state.lambda_sterics = 1.0 alchemical_state.lambda_electrostatics = float(step) / float( n_annealing_steps) alchemical_state.apply_to_context(context) integrator.step(1) self.sampler_state.update_from_context(context) # Compute the final energy of the system for logging. final_energy = thermodynamic_state.reduced_potential(context) logger.debug('final alchemical energy {:8.3f}kT'.format(final_energy)) # Initial softened minimization print('Minimizing real ligand...') self.sampler_state = self._minimize_sampler_state( self.reference_thermodynamic_state, self.sampler_state)
def test_minimize(self): """Test AlchemicalPhase minimization of positions in reference state.""" # Ligand-receptor in implicit solvent. test_system = testsystems.AlanineDipeptideVacuum() thermodynamic_state = states.ThermodynamicState(test_system.system, temperature=300 * unit.kelvin) topography = Topography(test_system.topology) # We create 3 different sampler states that will be distributed over # replicas in a round-robin fashion. displacement_vector = np.ones(3) * unit.nanometer positions2 = test_system.positions + displacement_vector positions3 = positions2 + displacement_vector box_vectors = test_system.system.getDefaultPeriodicBoxVectors() sampler_state1 = states.SamplerState(positions=test_system.positions, box_vectors=box_vectors) sampler_state2 = states.SamplerState(positions=positions2, box_vectors=box_vectors) sampler_state3 = states.SamplerState(positions=positions3, box_vectors=box_vectors) sampler_states = [sampler_state1, sampler_state2, sampler_state3] with self.temporary_storage_path() as storage_path: # Create alchemical phase. alchemical_phase = AlchemicalPhase(ReplicaExchangeSampler()) alchemical_phase.create(thermodynamic_state, sampler_states, topography, self.protocol, storage_path) # Measure the average distance between positions. This should be # maintained after minimization. sampler_states = alchemical_phase._sampler.sampler_states original_diffs = [ np.average(sampler_states[i].positions - sampler_states[i + 1].positions) for i in range(len(sampler_states) - 1) ] # Minimize. alchemical_phase.minimize() # The minimized positions should be still more or less # one displacement vector from each other. sampler_states = alchemical_phase._sampler.sampler_states new_diffs = [ np.average(sampler_states[i].positions - sampler_states[i + 1].positions) for i in range(len(sampler_states) - 1) ] assert np.allclose( original_diffs, new_diffs, rtol=0.1 ), "original_diffs {} are not close to new_diffs {}".format( original_diffs, new_diffs)
def test_restrain_atoms(): """Check that the restrained molecule's centroid is in the origin.""" host_guest = testsystems.HostGuestExplicit() topology = mdtraj.Topology.from_openmm(host_guest.topology) sampler_state = states.SamplerState(positions=host_guest.positions) thermodynamic_state = states.ThermodynamicState( host_guest.system, temperature=300 * unit.kelvin, pressure=1.0 * unit.atmosphere) # Restrain all the host carbon atoms. restrained_atoms = [ atom.index for atom in topology.atoms if atom.element.symbol is 'C' and atom.index <= 125 ] restrain_atoms(thermodynamic_state, sampler_state, restrained_atoms) # Compute host center_of_geometry. centroid = np.mean(sampler_state.positions[:126], axis=0) assert np.allclose(centroid, np.zeros(3))
def _anneal_ligand(self, structure, index): """ Anneal ligand interactions to clean up clashes. Returns ------- positions : unit.Quantity Positions of all atoms after annealing the ligand """ reference_system = copy.deepcopy(self.phases[index].system) protein = self.phases[index].mdtraj_top.select( f'protein and backbone and type CA').tolist() rmsd = openmm.RMSDForce( self.phases[index].structure.positions, protein + self.phases[index].lg1_idx + self.phases[index].lg2_idx) energy_expression = 'step(dRMSD) * (K_RMSD/2)*dRMSD^2; dRMSD = (RMSD-RMSD0);' restraint_force = openmm.CustomCVForce(energy_expression) restraint_force.addCollectiveVariable('RMSD', rmsd) restraint_force.addGlobalParameter( 'K_RMSD', 2 * unit.kilocalories_per_mole / (unit.angstroms**2)) restraint_force.addGlobalParameter('RMSD0', 2 * unit.angstroms) reference_system.addForce(restraint_force) alchemical_system = self._alchemically_modify_ligand( reference_system, index) from openmmtools.alchemy import AlchemicalState alchemical_state_zero = mmtools.alchemy.AlchemicalState.from_system( alchemical_system, parameters_name_suffix='zero') alchemical_state_one = mmtools.alchemy.AlchemicalState.from_system( alchemical_system, parameters_name_suffix='one') thermodynamic_state = states.ThermodynamicState( system=alchemical_system, temperature=300 * unit.kelvin) composable_states = [alchemical_state_zero, alchemical_state_one] compound_states = states.CompoundThermodynamicState( thermodynamic_state, composable_states=composable_states) sampler_state = states.SamplerState( positions=structure.positions, box_vectors=structure.topology.getPeriodicBoxVectors()) # Anneal n_annealing_steps = 1000 integrator = openmm.LangevinIntegrator(300 * unit.kelvin, 90.0 / unit.picoseconds, 1.0 * unit.femtoseconds) context, integrator = mmtools.cache.global_context_cache.get_context( compound_states, integrator) sampler_state.apply_to_context(context) compound_states.lambda_sterics_one = 0.0 compound_states.lambda_electrostatics_one = 0.0 compound_states.apply_to_context(context) print('Annealing sterics of ligand 1...') for step in progressbar.progressbar(range(n_annealing_steps)): compound_states.lambda_sterics_zero = float(step) / float( n_annealing_steps) compound_states.lambda_electrostatics_zero = 0.0 compound_states.apply_to_context(context) integrator.step(1) print('Annealing electrostatics of ligand 1...') for step in progressbar.progressbar(range(n_annealing_steps)): compound_states.lambda_sterics_zero = 1.0 compound_states.lambda_electrostatics_zero = float(step) / float( n_annealing_steps) compound_states.apply_to_context(context) integrator.step(1) compound_states.lambda_sterics_zero = 1.0 compound_states.lambda_electrostatics_zero = 1.0 compound_states.apply_to_context(context) print('Annealing sterics of ligand 2...') for step in progressbar.progressbar(range(n_annealing_steps)): compound_states.lambda_sterics_one = float(step) / float( n_annealing_steps) compound_states.lambda_electrostatics_one = 0.0 compound_states.apply_to_context(context) integrator.step(1) print('Annealing electrostatics of ligand 2...') for step in progressbar.progressbar(range(n_annealing_steps)): compound_states.lambda_sterics_one = 1.0 compound_states.lambda_electrostatics_one = float(step) / float( n_annealing_steps) compound_states.apply_to_context(context) integrator.step(1) compound_states.apply_to_context(context) sampler_state.update_from_context(context) # Compute the final energy of the system. final_energy = thermodynamic_state.reduced_potential(context) print('final alchemical energy {:8.3f}kT'.format(final_energy)) return sampler_state.positions
def main(): parser = argparse.ArgumentParser( description= 'Compute a potential of mean force (PMF) for porin permeation.') parser.add_argument('--index', dest='index', action='store', type=int, help='Index of ') parser.add_argument('--output', dest='output_filename', action='store', default='output.nc', help='output netcdf filename (default: output.nc)') args = parser.parse_args() index = args.index output_filename = args.output_filename logger = logging.getLogger(__name__) logging.root.setLevel(logging.DEBUG) logging.basicConfig(level=logging.DEBUG) yank.utils.config_root_logger(verbose=True, log_file_path=None) # Configure ContextCache, platform and precision from yank.experiment import ExperimentBuilder platform = ExperimentBuilder._configure_platform('CUDA', 'mixed') try: openmmtools.cache.global_context_cache.platform = platform except RuntimeError: # The cache has been already used. Empty it before switching platform. openmmtools.cache.global_context_cache.empty() openmmtools.cache.global_context_cache.platform = platform # Topology pdbx = app.PDBxFile('mem_prot_md_system.pdbx') # This system contains the CVforce with parameters different than zero with open('openmm_system.xml', 'r') as infile: openmm_system = XmlSerializer.deserialize(infile.read()) ####### Indexes of configurations in trajectory ############################ configs = [ 39, 141, 276, 406, 562, 668, 833, 1109, 1272, 1417, 1456, 1471, 1537, 1645, 1777, 1882 ] ####### Indexes of states for series of replica exchange simulations ####### limits = [(0, 9), (10, 19), (20, 29), (30, 39), (40, 49), (50, 59), (60, 69), (70, 79), (80, 89), (90, 99), (100, 109), (110, 119), (120, 129), (130, 139), (140, 149), (150, 159)] ####### Reading positions from mdtraj trajectory ########################### topology = md.Topology.from_openmm(pdbx.topology) t = md.load('../../steered_md/comp7/forward/seed_0/steered_forward.nc', top=topology) positions = t.openmm_positions(configs[index]) thermodynamic_state_deserialized = states.ThermodynamicState( system=openmm_system, temperature=310 * unit.kelvin, pressure=1.0 * unit.atmospheres) sampler_state = states.SamplerState( positions=positions, box_vectors=t.unitcell_vectors[configs[index], :, :] * unit.nanometer) logger.debug(type(sampler_state)) move = mcmc.LangevinDynamicsMove(timestep=2 * unit.femtosecond, collision_rate=1.0 / unit.picoseconds, n_steps=500, reassign_velocities=False) simulation = ReplicaExchangeSampler(mcmc_moves=move, number_of_iterations=1) analysis_particle_indices = topology.select( '(protein and mass > 3.0) or (resname MER and mass > 3.0)') reporter = MultiStateReporter( output_filename, checkpoint_interval=2000, analysis_particle_indices=analysis_particle_indices) first, last = limits[index] # Initialize compound thermodynamic states protocol = { 'lambda_restraints': [i / 159 for i in range(first, last + 1)], 'K_parallel': [ 1250 * unit.kilojoules_per_mole / unit.nanometer**2 for i in range(first, last + 1) ], 'Kmax': [ 500 * unit.kilojoules_per_mole / unit.nanometer**2 for i in range(first, last + 1) ], 'Kmin': [ 500 * unit.kilojoules_per_mole / unit.nanometer**2 for i in range(first, last + 1) ] } my_composable_state = MyComposableState.from_system(openmm_system) compound_states = states.create_thermodynamic_state_protocol( thermodynamic_state_deserialized, protocol=protocol, composable_states=[my_composable_state]) simulation.create(thermodynamic_states=compound_states, sampler_states=[sampler_state], storage=reporter) simulation.equilibrate(50, mcmc_moves=move) simulation.run() ts = simulation._thermodynamic_states[0] context, _ = openmmtools.cache.global_context_cache.get_context(ts) files_names = [ 'state_{}_{}.log'.format(index, i) for i in range(first, last + 1) ] files = [] for i, file in enumerate(files_names): files.append(open(file, 'w')) mpi.distribute(write_cv, range(simulation.n_replicas), context, simulation, files, send_results_to=None) for i in range(10000): simulation.extend(n_iterations=2) mpi.distribute(write_cv, range(simulation.n_replicas), context, simulation, files, send_results_to=None)
def _setup(self, topology, positions, box): """ Set up calculation. """ # Signal that system has now been set up if self._setup_complete: raise Exception( "System has already been set up---cannot run again.") self._setup_complete = True # Compute thermal energy and inverse temperature self.kT = kB * self.temperature self.beta = 1.0 / self.kT # Add a barostat # TODO: Is this necessary, since ThermodynamicState handles this automatically? It may not correctly handle MonteCarloAnisotropicBarostat. self._add_barostat() # Create SamplerState for initial conditions self.sampler_state = states.SamplerState(positions=positions, box_vectors=self.box) # Create reference thermodynamic state self.reference_thermodynamic_state = states.ThermodynamicState( system=self.system, temperature=self.temperature, pressure=self.pressure) # Anneal ligand into binding site if self.anneal_ligand: self._anneal_ligand() positions = self.sampler_state.positions structure = pmd.openmm.load_topology(topology, system=self.system, xyz=positions) # Create ThermodynamicStates for umbrella sampling along pore self.thermodynamic_states = self._auto_create_thermodynamic_states( structure, topology, self.reference_thermodynamic_state) # Minimize initial thermodynamic state # TODO: Select initial thermodynamic state based on which state has minimum energy initial_state_index = 0 #self.sampler_state = self._minimize_sampler_state(self.thermodynamic_states[initial_state_index], self.sampler_state) #pickle.dump(self.sampler_state, open('sampler_state.obj', 'wb')) #pickle.dump(self.reference_thermodynamic_state, open('reference_thermodynamic_state.obj', 'wb')) #pickle.dump(self.thermodynamic_states, open('thermodynamic_states.obj', 'wb')) #pickle.dump(self.system, open('system.obj', 'wb')) # Set up simulation from yank.multistate import SAMSSampler, MultiStateReporter # TODO: Change this to LangevinSplittingDynamicsMove move = mcmc.LangevinDynamicsMove(timestep=self.timestep, collision_rate=self.collision_rate, n_steps=self.n_steps_per_iteration, reassign_velocities=False) self.simulation = SAMSSampler( mcmc_moves=move, number_of_iterations=self.n_iterations, online_analysis_interval=None, gamma0=self.gamma0, flatness_threshold=self.flatness_threshold) self.reporter = MultiStateReporter( self.output_filename, checkpoint_interval=self.checkpoint_interval, analysis_particle_indices=self.analysis_particle_indices) self.simulation.create( thermodynamic_states=self.thermodynamic_states, unsampled_thermodynamic_states=[ self.reference_thermodynamic_state ], sampler_states=[self.sampler_state], initial_thermodynamic_states=[initial_state_index], storage=self.reporter)
def _setup(self): """ Set up calculation. """ # Signal that system has now been set up if self._setup_complete: raise Exception( "System has already been set up---cannot run again.") self._setup_complete = True # Compute thermal energy and inverse temperature self.kT = kB * self.temperature self.beta = 1.0 / self.kT # Create the system self.system = self._create_system() # Add a barostat # TODO: Is this necessary, sicne ThermodynamicState handles this automatically? It may not correctly handle MonteCarloAnisotropicBarostat. self._add_barostat() # Restrain protein atoms in space # TODO: Allow protein atom selection to be configured selection = '((residue 342 and resname GLY) or (residue 97 and resname ASP) or (residue 184 and resname SER)) and (name CA)' protein_atoms_to_restrain = self.mdtraj_topology.select(selection) #self._restrain_protein(protein_atoms_to_restrain) # Create SamplerState for initial conditions self.sampler_state = states.SamplerState( positions=self.grofile.positions, box_vectors=self.grofile.getPeriodicBoxVectors()) # Create reference thermodynamic state self.reference_thermodynamic_state = states.ThermodynamicState( system=self.system, temperature=self.temperature, pressure=self.pressure) # Anneal ligand into binding site if self.anneal_ligand: self._anneal_ligand() # Create ThermodynamicStates for umbrella sampling along pore self.thermodynamic_states = self._create_thermodynamic_states( self.reference_thermodynamic_state) # Minimize initial thermodynamic state # TODO: Select initial thermodynamic state based on which state has minimum energy initial_state_index = 0 self.sampler_state = self._minimize_sampler_state( self.thermodynamic_states[initial_state_index], self.sampler_state) # Set up simulation from yank.multistate import SAMSSampler, MultiStateReporter # TODO: Change this to LangevinSplittingDynamicsMove move = mcmc.LangevinDynamicsMove(timestep=self.timestep, collision_rate=self.collision_rate, n_steps=self.n_steps_per_iteration, reassign_velocities=False) self.simulation = SAMSSampler( mcmc_moves=move, number_of_iterations=self.n_iterations, online_analysis_interval=None, gamma0=self.gamma0, flatness_threshold=self.flatness_threshold) self.reporter = MultiStateReporter( self.output_filename, checkpoint_interval=self.checkpoint_interval, analysis_particle_indices=self.analysis_particle_indices) self.simulation.create( thermodynamic_states=self.thermodynamic_states, unsampled_thermodynamic_states=[ self.reference_thermodynamic_state ], sampler_states=[self.sampler_state], initial_thermodynamic_states=[initial_state_index], storage=self.reporter)
pdb = app.PDBFile('../../../smd/porin-ligand.pdb') with open('../../../smd/openmm_system_alch.xml', 'r') as infile: openmm_system = XmlSerializer.deserialize(infile.read()) topology = md.Topology.from_openmm(pdb.topology) ligand_atoms = topology.select('(resname CM7)') factory = AbsoluteAlchemicalFactory( consistent_exceptions=False, disable_alchemical_dispersion_correction=True) alchemical_region = AlchemicalRegion(alchemical_atoms=ligand_atoms) alchemical_system = factory.create_alchemical_system(openmm_system, alchemical_region) thermodynamic_state_ref = states.ThermodynamicState( system=alchemical_system, temperature=310 * unit.kelvin, pressure=1.0 * unit.atmospheres) sampler_state = states.SamplerState( positions=pdb.positions, box_vectors=pdb.topology.getPeriodicBoxVectors()) nstates = 160 #lambda_sterics= [1.00, 0.95, 0.90, 0.85, 0.80, 0.75, 0.70, 0.65, 0.59, 0.54, 0.47, 0.41, 0.36, 0.31, 0.27, 0.25, 0.225, 0.20, 0.18, 0.15, 0.13, #0.11, 0.06, 0.03, 0.00] #lambda_sterics =[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.00, 0.95, 0.90, 0.85, 0.80, 0.75, 0.70, 0.65, 0.59, 0.54, 0.47, #0.41, 0.36, 0.31, 0.27, 0.25, 0.225, 0.20, 0.18, 0.15, 0.13, 0.11, 0.06, 0.03, 0.00] #lambda_electrostatics=[1.0, 0.9, 0.79, 0.69, 0.58, 0.46, 0.32, 0.18, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, #0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] lambda_electrostatics = [1.0, 0.95, 0.9, 0.85, 0.8] lambda_sterics = [1.0, 1.0, 1.0, 1.0, 1.0] lambda_restraints = [i / nstates for i in range(12, 112)]
def __init__(self, molecules: List[str], output_filename: str, ncmc_switching_times: Dict[str, int], equilibrium_steps: Dict[str, int], timestep: unit.Quantity, initial_molecule: str=None, geometry_options: Dict=None): self._molecules = [SmallMoleculeSetProposalEngine.canonicalize_smiles(molecule) for molecule in molecules] environments = ['explicit', 'vacuum'] temperature = 298.15 * unit.kelvin pressure = 1.0 * unit.atmospheres constraints = app.HBonds self._storage = NetCDFStorage(output_filename) self._ncmc_switching_times = ncmc_switching_times self._n_equilibrium_steps = equilibrium_steps self._geometry_options = geometry_options # Create a system generator for our desired forcefields. from perses.rjmc.topology_proposal import SystemGenerator system_generators = dict() from pkg_resources import resource_filename gaff_xml_filename = resource_filename('perses', 'data/gaff.xml') barostat = openmm.MonteCarloBarostat(pressure, temperature) system_generators['explicit'] = SystemGenerator([gaff_xml_filename, 'tip3p.xml'], forcefield_kwargs={'nonbondedCutoff': 9.0 * unit.angstrom, 'implicitSolvent': None, 'constraints': constraints, 'ewaldErrorTolerance': 1e-5, 'hydrogenMass': 3.0*unit.amu}, periodic_forcefield_kwargs = {'nonbondedMethod': app.PME} barostat=barostat) system_generators['vacuum'] = SystemGenerator([gaff_xml_filename], forcefield_kwargs={'implicitSolvent': None, 'constraints': constraints, 'hydrogenMass': 3.0*unit.amu}, nonperiodic_forcefield_kwargs = {'nonbondedMethod': app.NoCutoff}) # # Create topologies and positions # topologies = dict() positions = dict() from openmoltools import forcefield_generators forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) # Create molecule in vacuum. from perses.utils.openeye import extractPositionsFromOEMol from openmoltools.openeye import smiles_to_oemol, generate_conformers if initial_molecule: smiles = initial_molecule else: smiles = np.random.choice(molecules) molecule = smiles_to_oemol(smiles) molecule = generate_conformers(molecule, max_confs=1) topologies['vacuum'] = forcefield_generators.generateTopologyFromOEMol(molecule) positions['vacuum'] = extractPositionsFromOEMol(molecule) # Create molecule in solvent. modeller = app.Modeller(topologies['vacuum'], positions['vacuum']) modeller.addSolvent(forcefield, model='tip3p', padding=9.0 * unit.angstrom) topologies['explicit'] = modeller.getTopology() positions['explicit'] = modeller.getPositions() # Set up the proposal engines. proposal_metadata = {} proposal_engines = dict() for environment in environments: proposal_engines[environment] = SmallMoleculeSetProposalEngine(self._molecules, system_generators[environment]) # Generate systems systems = dict() for environment in environments: systems[environment] = system_generators[environment].build_system(topologies[environment]) # Define thermodynamic state of interest. thermodynamic_states = dict() thermodynamic_states['explicit'] = states.ThermodynamicState(system=systems['explicit'], temperature=temperature, pressure=pressure) thermodynamic_states['vacuum'] = states.ThermodynamicState(system=systems['vacuum'], temperature=temperature) # Create SAMS samplers from perses.samplers.samplers import ExpandedEnsembleSampler, SAMSSampler mcmc_samplers = dict() exen_samplers = dict() sams_samplers = dict() for environment in environments: storage = NetCDFStorageView(self._storage, envname=environment) if self._geometry_options: n_torsion_divisions = self._geometry_options['n_torsion_divsions'][environment] use_sterics = self._geometry_options['use_sterics'][environment] else: n_torsion_divisions = 180 use_sterics = False geometry_engine = geometry.FFAllAngleGeometryEngine(storage=storage, n_torsion_divisions=n_torsion_divisions, use_sterics=use_sterics) move = mcmc.LangevinSplittingDynamicsMove(timestep=timestep, splitting="V R O R V", n_restart_attempts=10) chemical_state_key = proposal_engines[environment].compute_state_key(topologies[environment]) if environment == 'explicit': sampler_state = states.SamplerState(positions=positions[environment], box_vectors=systems[environment].getDefaultPeriodicBoxVectors()) else: sampler_state = states.SamplerState(positions=positions[environment]) mcmc_samplers[environment] = mcmc.MCMCSampler(thermodynamic_states[environment], sampler_state, move) exen_samplers[environment] = ExpandedEnsembleSampler(mcmc_samplers[environment], topologies[environment], chemical_state_key, proposal_engines[environment], geometry_engine, options={'nsteps': self._ncmc_switching_times[environment]}, storage=storage, ncmc_write_interval=self._ncmc_switching_times[environment]) exen_samplers[environment].verbose = True sams_samplers[environment] = SAMSSampler(exen_samplers[environment], storage=storage) sams_samplers[environment].verbose = True # Create test MultiTargetDesign sampler. from perses.samplers.samplers import MultiTargetDesign target_samplers = {sams_samplers['explicit']: 1.0, sams_samplers['vacuum']: -1.0} designer = MultiTargetDesign(target_samplers, storage=self._storage) # Store things. self.molecules = molecules self.environments = environments self.topologies = topologies self.positions = positions self.system_generators = system_generators self.proposal_engines = proposal_engines self.thermodynamic_states = thermodynamic_states self.mcmc_samplers = mcmc_samplers self.exen_samplers = exen_samplers self.sams_samplers = sams_samplers self.designer = designer
def test_compute_standard_state_correction(self): """Test standard state correction works correctly in all ensembles.""" toluene = testsystems.TolueneVacuum() alanine = testsystems.AlanineDipeptideExplicit() big_radius = 200.0 * unit.nanometers temperature = 300.0 * unit.kelvin # Limit the maximum volume to 1nm^3. distance_unit = unit.nanometers state_volume = 1.0 * distance_unit**3 box_vectors = np.identity(3) * np.cbrt( state_volume / distance_unit**3) * distance_unit alanine.system.setDefaultPeriodicBoxVectors(*box_vectors) toluene.system.setDefaultPeriodicBoxVectors(*box_vectors) # Create systems in various ensembles (NVT, NPT and non-periodic). nvt_state = states.ThermodynamicState(alanine.system, temperature) npt_state = states.ThermodynamicState(alanine.system, temperature, 1.0 * unit.atmosphere) nonperiodic_state = states.ThermodynamicState(toluene.system, temperature) def assert_equal_ssc(expected_restraint_volume, restraint, thermodynamic_state, square_well=False, radius_cutoff=None, energy_cutoff=None, max_volume=None): expected_ssc = -math.log( STANDARD_STATE_VOLUME / expected_restraint_volume) ssc = restraint.compute_standard_state_correction( thermodynamic_state, square_well, radius_cutoff, energy_cutoff, max_volume) err_msg = '{} computed SSC != expected SSC'.format( restraint.__class__.__name__) nose.tools.assert_equal(ssc, expected_ssc, msg=err_msg) for restraint in self.restraints: # In NPT ensemble, an exception is thrown if max_volume is not provided. with nose.tools.assert_raises_regexp( TypeError, "max_volume must be provided"): restraint.compute_standard_state_correction(npt_state) # With non-periodic systems and reweighting to square-well # potential, a cutoff must be given. with nose.tools.assert_raises_regexp(TypeError, "One between radius_cutoff"): restraint.compute_standard_state_correction(nonperiodic_state, square_well=True) # While there are no problems if we don't reweight to a square-well potential. restraint.compute_standard_state_correction(nonperiodic_state, square_well=False) # SSC is limited by max_volume (in NVT and NPT). assert_equal_ssc(state_volume, restraint, nvt_state, radius_cutoff=big_radius) assert_equal_ssc(state_volume, restraint, npt_state, radius_cutoff=big_radius, max_volume='system') # SSC is not limited by max_volume with non periodic systems. expected_ssc = -math.log(STANDARD_STATE_VOLUME / state_volume) ssc = restraint.compute_standard_state_correction( nonperiodic_state, radius_cutoff=big_radius) assert expected_ssc < ssc, (restraint, expected_ssc, ssc) # Check reweighting to square-well potential. expected_volume = _compute_sphere_volume(big_radius) assert_equal_ssc(expected_volume, restraint, nonperiodic_state, square_well=True, radius_cutoff=big_radius) energy_cutoff = 10 * nonperiodic_state.kT radius_cutoff = _compute_harmonic_radius(self.spring_constant, energy_cutoff) if isinstance(restraint, FlatBottomRestraintForceMixIn): radius_cutoff += self.well_radius expected_volume = _compute_sphere_volume(radius_cutoff) assert_equal_ssc(expected_volume, restraint, nonperiodic_state, square_well=True, radius_cutoff=radius_cutoff) max_volume = 3.0 * unit.nanometers**3 assert_equal_ssc(max_volume, restraint, nonperiodic_state, square_well=True, max_volume=max_volume)
# testsystem = testsystems.HostGuestVacuum() # save topology as .pdb top = mdtraj.Topology.from_openmm(testsystem.topology) trj = mdtraj.Trajectory([testsystem.positions / unit.nanometers], top) trj.save(stem + '.pdb') # save system as .xml serialized_system = mm.openmm.XmlSerializer.serialize(testsystem.system) with open(stem + '.xml', 'w') as fp: print(serialized_system, file=fp) n_replicas = 3 # Number of temperature replicas. T_min = 298.0 * unit.kelvin # Minimum temperature. T_max = 600.0 * unit.kelvin # Maximum temperature. reference_state = states.ThermodynamicState(system=testsystem.system, temperature=T_min) move = mcmc.GHMCMove(timestep=2.0 * unit.femtoseconds, n_steps=50) sampler = ParallelTemperingSampler(mcmc_moves=move, number_of_iterations=float('inf'), online_analysis_interval=None) storage_path = stem + '.nc' reporter = MultiStateReporter(storage_path, checkpoint_interval=1) sampler.create(reference_state, states.SamplerState(testsystem.positions), reporter, min_temperature=T_min, max_temperature=T_max, n_temperatures=n_replicas)