updates for new Settings

currently every (non-slow) tests passes except the reloading old files tests (to be expected)

still to do: regenerated example results files & update fixtures for these
This commit is contained in:
richard gowers
2024-02-02 13:10:15 +00:00
parent 990667c330
commit 4a73dff83b
19 changed files with 302 additions and 268 deletions

View File

@@ -52,8 +52,9 @@ from openfe.protocols.openmm_utils.omm_settings import (
)
from openfe.protocols.openmm_afe.equil_afe_settings import (
SolvationSettings,
AlchemicalSamplerSettings, OpenMMEngineSettings,
IntegratorSettings, SimulationSettings, LambdaSettings, OutputSettings,
MultiStateSimulationSettings, OpenMMEngineSettings,
IntegratorSettings, LambdaSettings, OutputSettings,
ThermoSettings,
)
from openfe.protocols.openmm_rfe._rfe_utils import compute
from ..openmm_utils import (
@@ -234,7 +235,7 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
* solvation_settings : SolvationSettings
* alchemical_settings : AlchemicalSettings
* lambda_settings : LambdaSettings
* sampler_settings : AlchemicalSamplerSettings
* sampler_settings : MultiStateSimulationSettings
* engine_settings : OpenMMEngineSettings
* integrator_settings : IntegratorSettings
* simulation_settings : SimulationSettings
@@ -279,8 +280,6 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
forcefield_settings=settings['forcefield_settings'],
integrator_settings=settings['integrator_settings'],
thermo_settings=settings['thermo_settings'],
integrator_settings=settings['integrator_settings'],
system_settings=settings['system_settings'],
cache=ffcache,
has_solvent=solvent_comp is not None,
)
@@ -616,10 +615,10 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
return energy_context_cache, sampler_context_cache
@staticmethod
def _get_integrator(
self,
integrator_settings: IntegratorSettings,
alchemsampler_settings: AlchemicalSamplerSettings
simulation_settings: MultiStateSimulationSettings
) -> openmmtools.mcmc.LangevinDynamicsMove:
"""
Return a LangevinDynamicsMove integrator
@@ -627,16 +626,22 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
Parameters
----------
integrator_settings : IntegratorSettings
simulation_settings : MultiStateSimulationSettings
Returns
-------
integrator : openmmtools.mcmc.LangevinDynamicsMove
A configured integrator object.
"""
# TODO: Check this is correct
tpi_fs = simulation_settings.time_per_iteration.to(unit.femtosecond).m
ts_fs = integrator_settings.timestep.to(unit.femtosecond).m
steps_per_iteration = int(round(tpi_fs / ts_fs))
integrator = openmmtools.mcmc.LangevinDynamicsMove(
timestep=to_openmm(integrator_settings.timestep),
collision_rate=to_openmm(integrator_settings.langevin_collision_rate),
n_steps=alchemsampler_settings.steps_per_iteration.m,
n_steps=steps_per_iteration,
reassign_velocities=integrator_settings.reassign_velocities,
n_restart_attempts=integrator_settings.n_restart_attempts,
constraint_tolerance=integrator_settings.constraint_tolerance,
@@ -644,11 +649,12 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
return integrator
@staticmethod
def _get_sampler(
self,
integrator: openmmtools.mcmc.LangevinDynamicsMove,
reporter: openmmtools.multistate.MultiStateReporter,
sampler_settings: AlchemicalSamplerSettings,
simulation_settings: MultiStateSimulationSettings,
thermo_settings: ThermoSettings,
cmp_states: list[ThermodynamicState],
sampler_states: list[SamplerState],
energy_context_cache: openmmtools.cache.ContextCache,
@@ -663,8 +669,10 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
The simulation integrator.
reporter : openmmtools.multistate.MultiStateReporter
The reporter to hook up to the sampler.
sampler_settings : AlchemicalSamplerSettings
simulation_settings : MultiStateSimulationSettings
Settings for the alchemical sampler.
thermo_settings : ThermoSettings
Thermodynamic settings
cmp_states : list[ThermodynamicState]
A list of thermodynamic states to sample.
sampler_states : list[SamplerState]
@@ -679,30 +687,37 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
sampler : multistate.MultistateSampler
A sampler configured for the chosen sampling method.
"""
rta_its, rta_min_its = settings_validation.convert_real_time_analysis_iterations(
simulation_settings=simulation_settings,
)
et_target_err = settings_validation.convert_target_error(
thermo_settings=thermo_settings,
simulation_settings=simulation_settings,
)
# Select the right sampler
# Note: doesn't need else, settings already validates choices
if sampler_settings.sampler_method.lower() == "repex":
if simulation_settings.sampler_method.lower() == "repex":
sampler = multistate.ReplicaExchangeSampler(
mcmc_moves=integrator,
online_analysis_interval=sampler_settings.real_time_analysis_interval,
online_analysis_target_error=sampler_settings.early_termination_target_error.m,
online_analysis_minimum_iterations=sampler_settings.real_time_analysis_minimum_iterations
online_analysis_interval=rta_its,
online_analysis_target_error=et_target_err,
online_analysis_minimum_iterations=rta_min_its
)
elif sampler_settings.sampler_method.lower() == "sams":
elif simulation_settings.sampler_method.lower() == "sams":
sampler = multistate.SAMSSampler(
mcmc_moves=integrator,
online_analysis_interval=sampler_settings.real_time_analysis_interval,
online_analysis_minimum_iterations=sampler_settings.real_time_analysis_minimum_iterations,
flatness_criteria=sampler_settings.sams_flatness_criteria,
gamma0=sampler_settings.sams_gamma0,
online_analysis_interval=rta_its,
online_analysis_minimum_iterations=rta_min_its,
flatness_criteria=simulation_settings.sams_flatness_criteria,
gamma0=simulation_settings.sams_gamma0,
)
elif sampler_settings.sampler_method.lower() == 'independent':
elif simulation_settings.sampler_method.lower() == 'independent':
sampler = multistate.MultiStateSampler(
mcmc_moves=integrator,
online_analysis_interval=sampler_settings.real_time_analysis_interval,
online_analysis_target_error=sampler_settings.early_termination_target_error.m,
online_analysis_minimum_iterations=sampler_settings.real_time_analysis_minimum_iterations
online_analysis_interval=rta_its,
online_analysis_target_error=et_target_err,
online_analysis_minimum_iterations=rta_min_its,
)
sampler.create(
@@ -744,7 +759,10 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
if not a dry run.
"""
# Get the relevant simulation steps
mc_steps = settings['sampler_settings'].steps_per_iteration.m
mc_steps = settings_validation.convert_steps_per_iteration(
simulation_settings=settings['simulation_settings'],
integrator_settings=settings['integrator_settings'],
)
equil_steps = settings_validation.get_simsteps(
sim_length=settings['simulation_settings'].equilibration_length,
@@ -894,12 +912,13 @@ class BaseAbsoluteUnit(gufe.ProtocolUnit):
# 13. Get integrator
integrator = self._get_integrator(
settings['integrator_settings'],
settings['sampler_settings'],
settings['simulation_settings'],
)
# 14. Get sampler
sampler = self._get_sampler(
integrator, reporter, settings['sampler_settings'],
integrator, reporter, settings['simulation_settings'],
settings['thermo_settings'],
cmp_states, sampler_states,
energy_ctx_cache, sampler_ctx_cache
)

View File

@@ -16,21 +16,24 @@ TODO
"""
from gufe.settings import (
Settings,
SettingsBaseModel,
OpenMMSystemGeneratorFFSettings,
ThermoSettings,
)
from openfe.protocols.openmm_utils.omm_settings import (
SystemSettings,
MultiStateSimulationSettings,
SolvationSettings,
AlchemicalSamplerSettings,
OpenMMEngineSettings,
IntegratorSettings,
SimulationSettings,
OutputSettings,
)
import numpy as np
from openff.models.types import FloatQuantity
from openff.units import unit
from typing import (
Literal,
Optional,
)
try:
@@ -109,7 +112,9 @@ class LambdaSettings(SettingsBaseModel):
return v
class AbsoluteSolvationSettings(Settings):
# This subclasses from SettingsBaseModel as it has vacuum_forcefield and
# solvent_forcefield fields, not just a single forcefield_settings field
class AbsoluteSolvationSettings(SettingsBaseModel):
"""
Configuration object for ``AbsoluteSolvationProtocol``.
@@ -117,9 +122,6 @@ class AbsoluteSolvationSettings(Settings):
--------
openfe.protocols.openmm_afe.AbsoluteSolvationProtocol
"""
class Config:
arbitrary_types_allowed = True
protocol_repeats: int
"""
The number of completely independent repeats of the entire sampling
@@ -135,22 +137,12 @@ class AbsoluteSolvationSettings(Settings):
return v
# Inherited things
forcefield_settings: OpenMMSystemGeneratorFFSettings
solvent_forcefield_settings: OpenMMSystemGeneratorFFSettings
vacuum_forcefield_settings: OpenMMSystemGeneratorFFSettings
"""Parameters to set up the force field with OpenMM Force Fields"""
thermo_settings: ThermoSettings
"""Settings for thermodynamic parameters"""
# Things for creating the systems
vacuum_system_settings: SystemSettings
"""
Simulation system settings including the
long-range non-bonded methods for the vacuum transformation.
"""
solvent_system_settings: SystemSettings
"""
Simulation system settings including the
long-range non-bonded methods for the solvent transformation.
"""
solvation_settings: SolvationSettings
"""Settings for solvating the system."""
@@ -164,10 +156,6 @@ class AbsoluteSolvationSettings(Settings):
Settings for controlling the lambda schedule for the different components
(vdw, elec, restraints).
"""
alchemsampler_settings: AlchemicalSamplerSettings
"""
Settings for controlling how we sample alchemical space.
"""
# MD Engine things
vacuum_engine_settings: OpenMMEngineSettings
@@ -189,12 +177,12 @@ class AbsoluteSolvationSettings(Settings):
"""
# Simulation run settings
vacuum_simulation_settings: SimulationSettings
vacuum_simulation_settings: MultiStateSimulationSettings
"""
Simulation control settings, including simulation lengths
for the vacuum transformation.
"""
solvent_simulation_settings: SimulationSettings
solvent_simulation_settings: MultiStateSimulationSettings
"""
Simulation control settings, including simulation lengths
for the solvent transformation.

View File

@@ -34,7 +34,6 @@ import warnings
from collections import defaultdict
import gufe
from gufe.components import Component
from openff.toolkit.topology import Molecule as OFFMolecule
import itertools
import numpy as np
import numpy.typing as npt
@@ -50,10 +49,10 @@ from gufe import (
ProteinComponent, SolventComponent
)
from openfe.protocols.openmm_afe.equil_afe_settings import (
AbsoluteSolvationSettings, SystemSettings,
AbsoluteSolvationSettings,
SolvationSettings, AlchemicalSettings, LambdaSettings,
AlchemicalSamplerSettings, OpenMMEngineSettings,
IntegratorSettings, SimulationSettings, OutputSettings,
MultiStateSimulationSettings, OpenMMEngineSettings,
IntegratorSettings, OutputSettings,
SettingsBaseModel,
)
from ..openmm_utils import system_validation, settings_validation
@@ -398,13 +397,14 @@ class AbsoluteSolvationProtocol(gufe.Protocol):
"""
return AbsoluteSolvationSettings(
protocol_repeats=3,
forcefield_settings=settings.OpenMMSystemGeneratorFFSettings(),
solvent_forcefield_settings=settings.OpenMMSystemGeneratorFFSettings(),
vacuum_forcefield_settings=settings.OpenMMSystemGeneratorFFSettings(
nonbonded_method='nocutoff',
),
thermo_settings=settings.ThermoSettings(
temperature=298.15 * unit.kelvin,
pressure=1 * unit.bar,
),
solvent_system_settings=SystemSettings(),
vacuum_system_settings=SystemSettings(nonbonded_method='nocutoff'),
alchemical_settings=AlchemicalSettings(),
lambda_settings=LambdaSettings(
lambda_elec=[
@@ -415,14 +415,12 @@ class AbsoluteSolvationProtocol(gufe.Protocol):
0.0, 0.0, 0.0, 0.0, 0.0, 0.12, 0.24,
0.36, 0.48, 0.6, 0.7, 0.77, 0.85, 1.0],
),
alchemsampler_settings=AlchemicalSamplerSettings(
n_replicas=14,
),
solvation_settings=SolvationSettings(),
vacuum_engine_settings=OpenMMEngineSettings(),
solvent_engine_settings=OpenMMEngineSettings(),
integrator_settings=IntegratorSettings(),
solvent_simulation_settings=SimulationSettings(
solvent_simulation_settings=MultiStateSimulationSettings(
n_replicas=14,
equilibration_length=1.0 * unit.nanosecond,
production_length=10.0 * unit.nanosecond,
),
@@ -430,7 +428,8 @@ class AbsoluteSolvationProtocol(gufe.Protocol):
output_filename='solvent.nc',
checkpoint_storage_filename='solvent_checkpoint.nc',
),
vacuum_simulation_settings=SimulationSettings(
vacuum_simulation_settings=MultiStateSimulationSettings(
n_replicas=14,
equilibration_length=0.5 * unit.nanosecond,
production_length=2.0 * unit.nanosecond,
),
@@ -535,15 +534,17 @@ class AbsoluteSolvationProtocol(gufe.Protocol):
@staticmethod
def _validate_lambda_schedule(
lambda_settings: LambdaSettings,
alchemsampler_settings: AlchemicalSamplerSettings,
simulation_settings: MultiStateSimulationSettings,
) -> None:
"""
Checks that the lambda schedule is set up correctly.
Parameters
----------
settings : AbsoluteSolvationSettings
Settings object.
lambda_settings : LambdaSettings
the lambda schedule Settings
simulation_settings : MultiStateSimulationSettings
the settings for either the vacuum or solvent phase
Raises
------
@@ -558,7 +559,7 @@ class AbsoluteSolvationProtocol(gufe.Protocol):
lambda_elec = lambda_settings.lambda_elec
lambda_vdw = lambda_settings.lambda_vdw
lambda_restraints = lambda_settings.lambda_restraints
n_replicas = alchemsampler_settings.n_replicas
n_replicas = simulation_settings.n_replicas
# Ensure that all lambda components have equal amount of windows
lambda_components = [lambda_vdw, lambda_elec]
@@ -601,7 +602,7 @@ class AbsoluteSolvationProtocol(gufe.Protocol):
self,
stateA: ChemicalSystem,
stateB: ChemicalSystem,
mapping: Optional[Dict[str, gufe.ComponentMapping]] = None,
mapping: Optional[dict[str, gufe.ComponentMapping]] = None,
extends: Optional[gufe.ProtocolDAGResult] = None,
) -> list[gufe.ProtocolUnit]:
# TODO: extensions
@@ -617,11 +618,13 @@ class AbsoluteSolvationProtocol(gufe.Protocol):
# Validate the lambda schedule
self._validate_lambda_schedule(self.settings.lambda_settings,
self.settings.alchemsampler_settings)
self.settings.solvent_simulation_settings)
self._validate_lambda_schedule(self.settings.lambda_settings,
self.settings.vacuum_simulation_settings)
# Check nonbond & solvent compatibility
solv_nonbonded_method = self.settings.solvent_system_settings.nonbonded_method
vac_nonbonded_method = self.settings.vacuum_system_settings.nonbonded_method
solv_nonbonded_method = self.settings.solvent_forcefield_settings.nonbonded_method
vac_nonbonded_method = self.settings.vacuum_forcefield_settings.nonbonded_method
# Use the more complete system validation solvent checks
system_validation.validate_solvent(stateA, solv_nonbonded_method)
# Gas phase is always gas phase
@@ -736,11 +739,9 @@ class AbsoluteSolvationVacuumUnit(BaseAbsoluteUnit):
A dictionary with the following entries:
* forcefield_settings : OpenMMSystemGeneratorFFSettings
* thermo_settings : ThermoSettings
* system_settings : SystemSettings
* solvation_settings : SolvationSettings
* alchemical_settings : AlchemicalSettings
* lambda_settings : LambdaSettings
* sampler_settings : AlchemicalSamplerSettings
* engine_settings : OpenMMEngineSettings
* integrator_settings : IntegratorSettings
* simulation_settings : SimulationSettings
@@ -749,13 +750,11 @@ class AbsoluteSolvationVacuumUnit(BaseAbsoluteUnit):
prot_settings = self._inputs['settings']
settings = {}
settings['forcefield_settings'] = prot_settings.forcefield_settings
settings['forcefield_settings'] = prot_settings.vacuum_forcefield_settings
settings['thermo_settings'] = prot_settings.thermo_settings
settings['system_settings'] = prot_settings.vacuum_system_settings
settings['solvation_settings'] = prot_settings.solvation_settings
settings['alchemical_settings'] = prot_settings.alchemical_settings
settings['lambda_settings'] = prot_settings.lambda_settings
settings['sampler_settings'] = prot_settings.alchemsampler_settings
settings['engine_settings'] = prot_settings.vacuum_engine_settings
settings['integrator_settings'] = prot_settings.integrator_settings
settings['simulation_settings'] = prot_settings.vacuum_simulation_settings
@@ -828,7 +827,6 @@ class AbsoluteSolvationSolventUnit(BaseAbsoluteUnit):
* solvation_settings : SolvationSettings
* alchemical_settings : AlchemicalSettings
* lambda_settings : LambdaSettings
* sampler_settings : AlchemicalSamplerSettings
* engine_settings : OpenMMEngineSettings
* integrator_settings : IntegratorSettings
* simulation_settings : SimulationSettings
@@ -837,13 +835,11 @@ class AbsoluteSolvationSolventUnit(BaseAbsoluteUnit):
prot_settings = self._inputs['settings']
settings = {}
settings['forcefield_settings'] = prot_settings.forcefield_settings
settings['forcefield_settings'] = prot_settings.solvent_forcefield_settings
settings['thermo_settings'] = prot_settings.thermo_settings
settings['system_settings'] = prot_settings.solvent_system_settings
settings['solvation_settings'] = prot_settings.solvation_settings
settings['alchemical_settings'] = prot_settings.alchemical_settings
settings['lambda_settings'] = prot_settings.lambda_settings
settings['sampler_settings'] = prot_settings.alchemsampler_settings
settings['engine_settings'] = prot_settings.solvent_engine_settings
settings['integrator_settings'] = prot_settings.integrator_settings
settings['simulation_settings'] = prot_settings.solvent_simulation_settings

View File

@@ -33,9 +33,9 @@ from gufe import (
ProteinComponent, SolventComponent
)
from openfe.protocols.openmm_md.plain_md_settings import (
PlainMDProtocolSettings, SystemSettings,
PlainMDProtocolSettings,
SolvationSettings, OpenMMEngineSettings,
IntegratorSettings, SimulationSettingsMD, OutputSettingsMD,
IntegratorSettings, MDSimulationSettings, MDOutputSettings,
)
from openff.toolkit.topology import Molecule as OFFMolecule
@@ -121,16 +121,15 @@ class PlainMDProtocol(gufe.Protocol):
temperature=298.15 * unit.kelvin,
pressure=1 * unit.bar,
),
system_settings=SystemSettings(),
solvation_settings=SolvationSettings(),
engine_settings=OpenMMEngineSettings(),
integrator_settings=IntegratorSettings(),
simulation_settings=SimulationSettingsMD(
simulation_settings=MDSimulationSettings(
equilibration_length_nvt=0.1 * unit.nanosecond,
equilibration_length=1.0 * unit.nanosecond,
production_length=5.0 * unit.nanosecond,
),
output_settings=OutputSettingsMD(),
output_settings=MDOutputSettings(),
protocol_repeats=1,
)
@@ -146,7 +145,7 @@ class PlainMDProtocol(gufe.Protocol):
raise NotImplementedError("Can't extend simulations yet")
# Validate solvent component
nonbond = self.settings.system_settings.nonbonded_method
nonbond = self.settings.forcefield_settings.nonbonded_method
system_validation.validate_solvent(stateA, nonbond)
# Validate protein component
@@ -246,8 +245,8 @@ class PlainMDProtocolUnit(gufe.ProtocolUnit):
@staticmethod
def _run_MD(simulation: openmm.app.Simulation,
positions: omm_unit.Quantity,
simulation_settings: SimulationSettingsMD,
output_settings: OutputSettingsMD,
simulation_settings: MDSimulationSettings,
output_settings: MDOutputSettings,
temperature: settings.ThermoSettings.temperature,
barostat_frequency: IntegratorSettings.barostat_frequency,
equil_steps_nvt: int,
@@ -466,11 +465,10 @@ class PlainMDProtocolUnit(gufe.ProtocolUnit):
protocol_settings.forcefield_settings
thermo_settings: settings.ThermoSettings = \
protocol_settings.thermo_settings
system_settings: SystemSettings = protocol_settings.system_settings
solvation_settings: SolvationSettings = \
protocol_settings.solvation_settings
sim_settings: SimulationSettingsMD = protocol_settings.simulation_settings
output_settings: OutputSettingsMD = protocol_settings.output_settings
sim_settings: MDSimulationSettings = protocol_settings.simulation_settings
output_settings: MDOutputSettings = protocol_settings.output_settings
timestep = protocol_settings.integrator_settings.timestep
integrator_settings = protocol_settings.integrator_settings
@@ -505,8 +503,6 @@ class PlainMDProtocolUnit(gufe.ProtocolUnit):
forcefield_settings=forcefield_settings,
integrator_settings=integrator_settings,
thermo_settings=thermo_settings,
integrator_settings=integrator_settings,
system_settings=system_settings,
cache=ffcache,
has_solvent=solvent_comp is not None,
)

View File

@@ -8,9 +8,9 @@ This module implements the settings necessary to run MD simulations using
"""
from openfe.protocols.openmm_utils.omm_settings import (
Settings, SystemSettings,
SolvationSettings, OpenMMEngineSettings, SimulationSettingsMD,
IntegratorSettings, OutputSettingsMD,
Settings,
SolvationSettings, OpenMMEngineSettings, MDSimulationSettings,
IntegratorSettings, MDOutputSettings,
)
from gufe.settings import SettingsBaseModel
try:
@@ -19,7 +19,6 @@ except ImportError:
from pydantic import validator # type: ignore[assignment]
class PlainMDProtocolSettings(Settings):
class Config:
arbitrary_types_allowed = True
@@ -37,7 +36,6 @@ class PlainMDProtocolSettings(Settings):
return v
# Things for creating the systems
system_settings: SystemSettings
solvation_settings: SolvationSettings
# MD Engine things
@@ -47,7 +45,7 @@ class PlainMDProtocolSettings(Settings):
integrator_settings: IntegratorSettings
# Simulation run settings
simulation_settings: SimulationSettingsMD
simulation_settings: MDSimulationSettings
#Simulations output settings
output_settings: OutputSettingsMD
# Simulations output settings
output_settings: MDOutputSettings

View File

@@ -9,7 +9,7 @@ from openmmtools.alchemy import AlchemicalState
class LambdaProtocol(object):
"""Protocols for perturbing each of the compent energy terms in alchemical
"""Protocols for perturbing each of the component energy terms in alchemical
free energy simulations.
TODO

View File

@@ -52,10 +52,10 @@ from gufe import (
)
from .equil_rfe_settings import (
RelativeHybridTopologyProtocolSettings, SystemSettings,
RelativeHybridTopologyProtocolSettings,
SolvationSettings, AlchemicalSettings, LambdaSettings,
AlchemicalSamplerSettings, OpenMMEngineSettings,
IntegratorSettings, SimulationSettings, OutputSettings,
MultiStateSimulationSettings, OpenMMEngineSettings,
IntegratorSettings, OutputSettings,
)
from ..openmm_utils import (
system_validation, settings_validation, system_creation,
@@ -454,17 +454,15 @@ class RelativeHybridTopologyProtocol(gufe.Protocol):
temperature=298.15 * unit.kelvin,
pressure=1 * unit.bar,
),
system_settings=SystemSettings(),
solvation_settings=SolvationSettings(),
alchemical_settings=AlchemicalSettings(softcore_LJ='gapsys'),
lambda_settings=LambdaSettings(),
alchemical_sampler_settings=AlchemicalSamplerSettings(),
engine_settings=OpenMMEngineSettings(),
integrator_settings=IntegratorSettings(),
simulation_settings=SimulationSettings(
simulation_settings=MultiStateSimulationSettings(
equilibration_length=1.0 * unit.nanosecond,
production_length=5.0 * unit.nanosecond,
),
engine_settings=OpenMMEngineSettings(),
integrator_settings=IntegratorSettings(),
output_settings=OutputSettings(),
)
@@ -489,7 +487,7 @@ class RelativeHybridTopologyProtocol(gufe.Protocol):
ligandmapping = list(mapping.values())[0] # type: ignore
# Validate solvent component
nonbond = self.settings.system_settings.nonbonded_method
nonbond = self.settings.forcefield_settings.nonbonded_method
system_validation.validate_solvent(stateA, nonbond)
# Validate protein component
@@ -629,12 +627,9 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
forcefield_settings: settings.OpenMMSystemGeneratorFFSettings = protocol_settings.forcefield_settings
thermo_settings: settings.ThermoSettings = protocol_settings.thermo_settings
alchem_settings: AlchemicalSettings = protocol_settings.alchemical_settings
alchem_sampler_settings: AlchemicalSamplerSettings = protocol_settings.alchemical_sampler_settings
lambda_settings: LambdaSettings = protocol_settings.lambda_settings
system_settings: SystemSettings = protocol_settings.system_settings
solvation_settings: SolvationSettings = protocol_settings.solvation_settings
sampler_settings: AlchemicalSamplerSettings = protocol_settings.alchemical_sampler_settings
sim_settings: SimulationSettings = protocol_settings.simulation_settings
sampler_settings: MultiStateSimulationSettings = protocol_settings.simulation_settings
output_settings: OutputSettings = protocol_settings.output_settings
integrator_settings: IntegratorSettings = protocol_settings.integrator_settings
@@ -643,15 +638,22 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
forcefield_settings.hydrogen_mass,
integrator_settings.timestep
)
# TODO: Also validate various conversions?
# Convert various time based inputs to steps/iterations
steps_per_iteration = settings_validation.convert_steps_per_iteration(
simulation_settings=sampler_settings,
integrator_settings=integrator_settings,
)
equil_steps = settings_validation.get_simsteps(
sim_length=sim_settings.equilibration_length,
sim_length=sampler_settings.equilibration_length,
timestep=integrator_settings.timestep,
mc_steps=integrator_settings.n_steps.m,
mc_steps=steps_per_iteration,
)
prod_steps = settings_validation.get_simsteps(
sim_length=sim_settings.production_length,
sim_length=sampler_settings.production_length,
timestep=integrator_settings.timestep,
mc_steps=integrator_settings.n_steps.m,
mc_steps=steps_per_iteration,
)
solvent_comp, protein_comp, small_mols = system_validation.get_components(stateA)
@@ -660,7 +662,7 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
# and check if the charge correction used is appropriate
charge_difference = _get_alchemical_charge_difference(
mapping,
system_settings.nonbonded_method,
forcefield_settings.nonbonded_method,
alchem_settings.explicit_charge_correction,
solvent_comp,
)
@@ -676,8 +678,6 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
forcefield_settings=forcefield_settings,
integrator_settings=integrator_settings,
thermo_settings=thermo_settings,
integrator_settings=integrator_settings,
system_settings=system_settings,
cache=ffcache,
has_solvent=solvent_comp is not None,
)
@@ -827,12 +827,16 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
)
# a. Create the multistate reporter
# convert checkpoint_interval from time to steps
checkpoint_fs = output_settings.checkpoint_interval.to(unit.femtosecond).m
ts_fs = integrator_settings.timestep.to(unit.femtosecond).m
checkpoint_int = int(round(checkpoint_fs / ts_fs))
nc = shared_basepath / output_settings.output_filename
chk = output_settings.checkpoint_storage_filename
reporter = multistate.MultiStateReporter(
storage=nc,
analysis_particle_indices=selection_indices,
checkpoint_interval=output_settings.checkpoint_interval.m,
checkpoint_interval=checkpoint_int,
checkpoint_storage=chk,
)
@@ -871,7 +875,7 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
integrator = openmmtools.mcmc.LangevinDynamicsMove(
timestep=to_openmm(integrator_settings.timestep),
collision_rate=to_openmm(integrator_settings.langevin_collision_rate),
n_steps=alchem_sampler_settings.steps_per_iteration.m,
n_steps=steps_per_iteration,
reassign_velocities=integrator_settings.reassign_velocities,
n_restart_attempts=integrator_settings.n_restart_attempts,
constraint_tolerance=integrator_settings.constraint_tolerance,
@@ -879,26 +883,28 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
# 12. Create sampler
self.logger.info("Creating and setting up the sampler")
rta_its, rta_min_its = settings_validation.convert_real_time_analysis_iterations(
simulation_settings=sampler_settings,
)
# convert early_termination_target_error from kcal/mol to kT
temp = thermo_settings.temperature
kB = 0.001987204 * unit.kilocalorie_per_mole / unit.kelvin
kT = temp * kB
early_termination_target_error = kT / sampler_settings.early_termination_target_error
early_termination_target_error = settings_validation.convert_target_error(
thermo_settings=thermo_settings, simulation_settings=sampler_settings
)
if sampler_settings.sampler_method.lower() == "repex":
sampler = _rfe_utils.multistate.HybridRepexSampler(
mcmc_moves=integrator,
hybrid_factory=hybrid_factory,
online_analysis_interval=sampler_settings.real_time_analysis_interval,
online_analysis_interval=rta_its,
online_analysis_target_error=early_termination_target_error,
online_analysis_minimum_iterations=sampler_settings.real_time_analysis_minimum_iterations
online_analysis_minimum_iterations=rta_min_its,
)
elif sampler_settings.sampler_method.lower() == "sams":
sampler = _rfe_utils.multistate.HybridSAMSSampler(
mcmc_moves=integrator,
hybrid_factory=hybrid_factory,
online_analysis_interval=sampler_settings.real_time_analysis_interval,
online_analysis_minimum_iterations=sampler_settings.real_time_analysis_minimum_iterations,
online_analysis_interval=rta_its,
online_analysis_minimum_iterations=rta_min_its,
flatness_criteria=sampler_settings.sams_flatness_criteria,
gamma0=sampler_settings.sams_gamma0,
)
@@ -906,9 +912,9 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
sampler = _rfe_utils.multistate.HybridMultiStateSampler(
mcmc_moves=integrator,
hybrid_factory=hybrid_factory,
online_analysis_interval=sampler_settings.real_time_analysis_interval,
online_analysis_interval=rta_its,
online_analysis_target_error=early_termination_target_error,
online_analysis_minimum_iterations=sampler_settings.real_time_analysis_minimum_iterations
online_analysis_minimum_iterations=rta_min_its,
)
else:
@@ -941,7 +947,7 @@ class RelativeHybridTopologyProtocolUnit(gufe.ProtocolUnit):
if verbose:
self.logger.info("Running minimization")
sampler.minimize(max_iterations=sim_settings.minimization_steps)
sampler.minimize(max_iterations=sampler_settings.minimization_steps)
# equilibrate
if verbose:

View File

@@ -11,7 +11,6 @@ from __future__ import annotations
from typing import Optional, Literal
from openff.units import unit
from openff.models.types import FloatQuantity
import os
from gufe.settings import (
Settings,
@@ -20,8 +19,8 @@ from gufe.settings import (
ThermoSettings,
)
from openfe.protocols.openmm_utils.omm_settings import (
SystemSettings, SolvationSettings, AlchemicalSamplerSettings,
OpenMMEngineSettings, IntegratorSettings, SimulationSettings,
SolvationSettings, MultiStateSimulationSettings,
OpenMMEngineSettings, IntegratorSettings,
OutputSettings,
)
@@ -107,9 +106,6 @@ class AlchemicalSettings(SettingsBaseModel):
class RelativeHybridTopologyProtocolSettings(Settings):
class Config:
arbitrary_types_allowed = True
protocol_repeats: int
"""
The number of completely independent repeats of the entire sampling
@@ -132,8 +128,6 @@ class RelativeHybridTopologyProtocolSettings(Settings):
"""Settings for thermodynamic parameters."""
# Things for creating the systems
system_settings: SystemSettings
"""Simulation system settings including the long-range non-bonded method."""
solvation_settings: SolvationSettings
"""Settings for solvating the system."""
@@ -146,7 +140,7 @@ class RelativeHybridTopologyProtocolSettings(Settings):
"""
Alchemical protocol settings including soft core scaling.
"""
alchemical_sampler_settings: AlchemicalSamplerSettings
simulation_settings: MultiStateSimulationSettings
"""
Settings for alchemical sampler.
"""
@@ -159,11 +153,6 @@ class RelativeHybridTopologyProtocolSettings(Settings):
integrator_settings: IntegratorSettings
"""Settings for the integrator such as timestep and barostat settings."""
# Simulation run settings
simulation_settings: SimulationSettings
"""
Simulation control settings, including simulation lengths.
"""
output_settings: OutputSettings
"""
Simulation output control settings.

View File

@@ -28,42 +28,6 @@ except ImportError:
from pydantic import validator # type: ignore[assignment]
# class SystemSettings(SettingsBaseModel):
# """Settings describing the simulation system settings."""
#
# class Config:
# arbitrary_types_allowed = True
#
# nonbonded_method = 'PME'
# """
# Method for treating nonbonded interactions, currently only PME and
# NoCutoff are allowed. Default PME.
# """
# nonbonded_cutoff: FloatQuantity['nanometer'] = 1.0 * unit.nanometer
# """
# Cutoff value for short range nonbonded interactions.
# Default 1.0 * unit.nanometer.
# """
#
# @validator('nonbonded_method')
# def allowed_nonbonded(cls, v):
# if v.lower() not in ['pme', 'nocutoff']:
# errmsg = ("Only PME and NoCutoff are allowed nonbonded_methods")
# raise ValueError(errmsg)
# return v
#
# @validator('nonbonded_cutoff')
# def is_positive_distance(cls, v):
# # these are time units, not simulation steps
# if not v.is_compatible_with(unit.nanometer):
# raise ValueError("nonbonded_cutoff must be in distance units "
# "(i.e. nanometers)")
# if v < 0:
# errmsg = "nonbonded_cutoff must be a positive value"
# raise ValueError(errmsg)
# return v
class SolvationSettings(SettingsBaseModel):
"""Settings for solvating the system
@@ -338,8 +302,7 @@ class OutputSettings(SettingsBaseModel):
Selection string for which part of the system to write coordinates for.
Default 'not water'.
"""
checkpoint_interval = FloatQuantity['picosecond'] = 1 * unit.picosecond
# todo: convert back to unit.timestep in protocol
checkpoint_interval: FloatQuantity['picosecond'] = 1 * unit.picosecond
"""
Frequency to write the checkpoint file. Default 1 * unit.picosecond.
"""
@@ -434,13 +397,11 @@ class MultiStateSimulationSettings(SimulationSettings):
Default `repex`.
"""
time_per_iteration: FloatQuantity['picosecond'] = 1 * unit.picosecond
# TODO: convert back in protocol
# todo: Add validators in the protocol
"""
Simulation time between each MCMC move attempt. Default 1 * unit.picosecond.
"""
real_time_analysis_interval: Optional[FloatQuantity['picosecond']] = 250 * unit.picosecond
# TODO: convert back in protocol
# todo: Add validators in the protocol
"""
Time interval at which to perform an analysis of the free energies.
@@ -471,8 +432,7 @@ class MultiStateSimulationSettings(SimulationSettings):
shown to be effective in both hydration and binding free energy benchmarks.
Default ``None``, i.e. no early termination will occur.
"""
real_time_analysis_minimum_time = FloatQuantity['picosecond'] = 500 * unit.picosecond
# todo: convert back to unit.timestep in protocol
real_time_analysis_minimum_time: FloatQuantity['picosecond'] = 500 * unit.picosecond
# todo: Add validators in the protocol
"""
Simulation time which must pass before real time analysis is
@@ -513,7 +473,7 @@ class MultiStateSimulationSettings(SimulationSettings):
raise ValueError(errmsg)
return v
@validator('n_replicas', 'steps_per_iteration')
@validator('n_replicas', 'time_per_iteration')
def must_be_positive(cls, v):
if v <= 0:
errmsg = "n_replicas and steps_per_iteration must be positive " \
@@ -522,7 +482,7 @@ class MultiStateSimulationSettings(SimulationSettings):
return v
@validator('early_termination_target_error',
'real_time_analysis_minimum_iterations', 'sams_gamma0',
'real_time_analysis_minimum_time', 'sams_gamma0',
'n_replicas')
def must_be_zero_or_positive(cls, v):
if v < 0:

View File

@@ -71,3 +71,95 @@ def get_simsteps(sim_length: unit.Quantity,
raise ValueError(errmsg)
return sim_steps
def convert_steps_per_iteration(
simulation_settings,
integrator_settings,
):
"""Convert time per iteration to steps
Parameters
----------
simulation_settings: MultiStateSimulationSettings
integrator_settings: IntegratorSettings
Returns
-------
steps_per_iteration : int
suitable for input to Integrator
"""
# TODO: Check this is correct
tpi_fs = simulation_settings.time_per_iteration.to(unit.femtosecond).m
ts_fs = integrator_settings.timestep.to(unit.femtosecond).m
steps_per_iteration = int(round(tpi_fs / ts_fs))
return steps_per_iteration
def convert_real_time_analysis_iterations(
simulation_settings,
):
"""Convert time units in Settings to various other units
Interally openmmtools uses various quantities with units of time,
steps, and iterations.
Our Settings objects instead have things defined in time (fs or ps).
This function generates suitable inputs for the openmmtools objects
Parameters
----------
simulation_settings: MultiStateSimulationSettings
Returns
-------
real_time_analysis_iterations : int
suitable for input to online_analysis_interval
real_time_analysis_minimum_iterations : int
suitable for input to real_time_analysis_minimum_iterations
"""
# TODO: Check this is correct
tpi_fs = simulation_settings.time_per_iteration.to(unit.femtosecond).m
# convert real_time_analysis time to interval
# rta_its must be number of MCMC iterations
# i.e. rta_fs / tpi_fs -> number of iterations
rta_fs = simulation_settings.real_time_analysis_interval.to(unit.femtosecond).m
rta_its = round(int(rta_fs / tpi_fs))
# convert RTA_minimum_time to iterations
rta_min_fs = simulation_settings.real_time_analysis_minimum_time.to(unit.femtosecond).m
rta_min_its = round(int(rta_min_fs / tpi_fs))
return rta_its, rta_min_its
def convert_target_error(
thermo_settings,
simulation_settings,
):
"""Convert kcal/mol target error to kT units
Parameters
----------
thermo_settings: ThermoSettings
simulation_settings: MultiStateSimulationSettings
Returns
-------
early_termination_target_error : float
in units of kT, suitable for input as "online_analysis_target_error" in a
Sampler
"""
temp = thermo_settings.temperature
if simulation_settings.early_termination_target_error:
# TODO: Check conversions here
kB = 0.001987204 * unit.kilocalorie_per_mole / unit.kelvin
kT = temp * kB
early_termination_target_error = kT / simulation_settings.early_termination_target_error
else:
early_termination_target_error = 0.0
return early_termination_target_error

View File

@@ -18,7 +18,7 @@ from gufe import (
Component, ProteinComponent, SolventComponent, SmallMoleculeComponent
)
from ..openmm_rfe.equil_rfe_settings import (
SystemSettings, SimulationSettings, SolvationSettings, IntegratorSettings,
SolvationSettings, IntegratorSettings,
)
@@ -26,7 +26,6 @@ def get_system_generator(
forcefield_settings: OpenMMSystemGeneratorFFSettings,
thermo_settings: ThermoSettings,
integrator_settings: IntegratorSettings,
system_settings: SystemSettings,
cache: Optional[Path],
has_solvent: bool,
) -> SystemGenerator:
@@ -46,9 +45,6 @@ def get_system_generator(
for defining the ensemble conditions.
integrator_settings : IntegratorSettings
Integrator settings, including barostat control variables.
system_settings : SystemSettings
System settings including all necessary information for
the nonbonded methods.
cache : Optional[pathlib.Path]
Path to openff force field cache.
has_solvent : bool
@@ -88,10 +84,11 @@ def get_system_generator(
'cutoffnonperiodic': app.CutoffNonPeriodic,
'cutoffperiodic': app.CutoffPeriodic,
'ewald': app.Ewald
}[system_settings.nonbonded_method.lower()]
}[forcefield_settings.nonbonded_method.lower()]
nonbonded_cutoff = to_openmm(
system_settings.nonbonded_cutoff
nonbonded_cutoff = ensure_quantity(
forcefield_settings.nonbonded_cutoff, # type: ignore
'openmm',
)
# create the periodic_kwarg entry

View File

@@ -209,7 +209,7 @@ class RelativeAlchemicalNetworkPlanner(
# Todo: Another dirty hack! - START
protocol_settings = transformation_protocol.settings.unfrozen_copy()
if "vacuum" in transformation_name:
protocol_settings.system_settings.nonbonded_method = "nocutoff"
protocol_settings.forcefield_settings.nonbonded_method = "nocutoff"
transformation_protocol = transformation_protocol.__class__(
settings=protocol_settings

View File

@@ -70,11 +70,17 @@ def test_validate_lambda_schedule_naked_charge(val, default_settings):
default_settings.lambda_settings.lambda_elec = val['elec']
default_settings.lambda_settings.lambda_vdw = val['vdw']
default_settings.lambda_settings.lambda_restraints = val['restraints']
default_settings.alchemsampler_settings.n_replicas = 2
default_settings.vacuum_simulation_settings.n_replicas = 2
default_settings.solvent_simulation_settings.n_replicas = 2
with pytest.raises(ValueError, match=errmsg):
AbsoluteSolvationProtocol._validate_lambda_schedule(
default_settings.lambda_settings,
default_settings.alchemsampler_settings,
default_settings.vacuum_simulation_settings,
)
with pytest.raises(ValueError, match=errmsg):
AbsoluteSolvationProtocol._validate_lambda_schedule(
default_settings.lambda_settings,
default_settings.solvent_simulation_settings,
)
@@ -86,13 +92,13 @@ def test_validate_lambda_schedule_nreplicas(val, default_settings):
default_settings.lambda_settings.lambda_vdw = val['vdw']
default_settings.lambda_settings.lambda_restraints = val['restraints']
n_replicas = 3
default_settings.alchemsampler_settings.n_replicas = n_replicas
default_settings.vacuum_simulation_settings.n_replicas = n_replicas
errmsg = (f"Number of replicas {n_replicas} does not equal the"
f" number of lambda windows {len(val['vdw'])}")
with pytest.raises(ValueError, match=errmsg):
AbsoluteSolvationProtocol._validate_lambda_schedule(
default_settings.lambda_settings,
default_settings.alchemsampler_settings,
default_settings.vacuum_simulation_settings,
)
@@ -104,7 +110,7 @@ def test_validate_lambda_schedule_nwindows(val, default_settings):
default_settings.lambda_settings.lambda_vdw = val['vdw']
default_settings.lambda_settings.lambda_restraints = val['restraints']
n_replicas = 3
default_settings.alchemsampler_settings.n_replicas = n_replicas
default_settings.vacuum_simulation_settings.n_replicas = n_replicas
errmsg = (
"Components elec and vdw must have equal amount"
f" of lambda windows. Got {len(val['elec'])} elec lambda"
@@ -112,7 +118,7 @@ def test_validate_lambda_schedule_nwindows(val, default_settings):
with pytest.raises(ValueError, match=errmsg):
AbsoluteSolvationProtocol._validate_lambda_schedule(
default_settings.lambda_settings,
default_settings.alchemsampler_settings,
default_settings.vacuum_simulation_settings,
)
@@ -126,11 +132,11 @@ def test_validate_lambda_schedule_nonzero_restraints(val, default_settings):
default_settings.lambda_settings.lambda_elec = val['elec']
default_settings.lambda_settings.lambda_vdw = val['vdw']
default_settings.lambda_settings.lambda_restraints = val['restraints']
default_settings.alchemsampler_settings.n_replicas = 2
default_settings.vacuum_simulation_settings.n_replicas = 2
with pytest.warns(UserWarning, match=wmsg):
AbsoluteSolvationProtocol._validate_lambda_schedule(
default_settings.lambda_settings,
default_settings.alchemsampler_settings,
default_settings.vacuum_simulation_settings,
)
@@ -262,7 +268,7 @@ def test_validate_alchem_nonsmc(benzene_modifications):
def test_vac_bad_nonbonded(benzene_modifications):
settings = openmm_afe.AbsoluteSolvationProtocol.default_settings()
settings.vacuum_system_settings.nonbonded_method = 'pme'
settings.vacuum_forcefield_settings.nonbonded_method = 'pme'
protocol = openmm_afe.AbsoluteSolvationProtocol(settings=settings)
stateA = ChemicalSystem({
@@ -285,7 +291,7 @@ def test_dry_run_vac_benzene(benzene_modifications,
method, tmpdir):
s = openmm_afe.AbsoluteSolvationProtocol.default_settings()
s.protocol_repeats = 1
s.alchemsampler_settings.sampler_method = method
s.vacuum_simulation_settings.sampler_method = method
protocol = openmm_afe.AbsoluteSolvationProtocol(
settings=s,
@@ -408,7 +414,12 @@ def test_dry_run_solv_benzene(benzene_modifications, tmpdir):
def test_dry_run_solv_benzene_tip4p(benzene_modifications, tmpdir):
s = AbsoluteSolvationProtocol.default_settings()
s.protocol_repeats = 1
s.forcefield_settings.forcefields = [
s.vacuum_forcefield_settings.forcefields = [
"amber/ff14SB.xml", # ff14SB protein force field
"amber/tip4pew_standard.xml", # FF we are testsing with the fun VS
"amber/phosaa10.xml", # Handles THE TPO
]
s.solvent_forcefield_settings.forcefields = [
"amber/ff14SB.xml", # ff14SB protein force field
"amber/tip4pew_standard.xml", # FF we are testsing with the fun VS
"amber/phosaa10.xml", # Handles THE TPO
@@ -535,7 +546,8 @@ def test_dry_run_solv_user_charges_benzene(benzene_modifications, tmpdir):
def test_high_timestep(benzene_modifications, tmpdir):
s = AbsoluteSolvationProtocol.default_settings()
s.protocol_repeats = 1
s.forcefield_settings.hydrogen_mass = 1.0
s.solvent_forcefield_settings.hydrogen_mass = 1.0
s.vacuum_forcefield_settings.hydrogen_mass = 1.0
protocol = AbsoluteSolvationProtocol(
settings=s,

View File

@@ -181,8 +181,8 @@ def test_dry_run_default_vacuum(benzene_vacuum_system, toluene_vacuum_system,
benzene_to_toluene_mapping, method, tmpdir):
vac_settings = openmm_rfe.RelativeHybridTopologyProtocol.default_settings()
vac_settings.system_settings.nonbonded_method = 'nocutoff'
vac_settings.alchemical_sampler_settings.sampler_method = method
vac_settings.forcefield_settings.nonbonded_method = 'nocutoff'
vac_settings.simulation_settings.sampler_method = method
vac_settings.protocol_repeats = 1
protocol = openmm_rfe.RelativeHybridTopologyProtocol(
@@ -226,7 +226,7 @@ def test_dry_run_default_vacuum(benzene_vacuum_system, toluene_vacuum_system,
def test_dry_run_gaff_vacuum(benzene_vacuum_system, toluene_vacuum_system,
benzene_to_toluene_mapping, tmpdir):
vac_settings = openmm_rfe.RelativeHybridTopologyProtocol.default_settings()
vac_settings.system_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.small_molecule_forcefield = 'gaff-2.11'
protocol = openmm_rfe.RelativeHybridTopologyProtocol(
@@ -348,7 +348,7 @@ def test_dry_core_element_change(tmpdir):
)
settings = openmm_rfe.RelativeHybridTopologyProtocol.default_settings()
settings.system_settings.nonbonded_method = 'nocutoff'
settings.forcefield_settings.nonbonded_method = 'nocutoff'
protocol = openmm_rfe.RelativeHybridTopologyProtocol(
settings=settings,
@@ -383,7 +383,7 @@ def test_dry_run_ligand(benzene_system, toluene_system,
benzene_to_toluene_mapping, method, tmpdir):
# this might be a bit time consuming
settings = openmm_rfe.RelativeHybridTopologyProtocol.default_settings()
settings.alchemical_sampler_settings.sampler_method = method
settings.simulation_settings.sampler_method = method
settings.protocol_repeats = 1
settings.output_settings.output_indices = 'resname UNK'
@@ -446,7 +446,7 @@ def tip4p_hybrid_factory(
"amber/phosaa10.xml", # Handles THE TPO
]
settings.solvation_settings.solvent_padding = 1.0 * unit.nanometer
settings.system_settings.nonbonded_cutoff = 0.9 * unit.nanometer
settings.forcefield_settings.nonbonded_cutoff = 0.9 * unit.nanometer
settings.solvation_settings.solvent_model = 'tip4pew'
settings.integrator_settings.reassign_velocities = True
@@ -594,7 +594,7 @@ def test_dry_run_user_charges(benzene_modifications, tmpdir):
hybrid topology.
"""
vac_settings = openmm_rfe.RelativeHybridTopologyProtocol.default_settings()
vac_settings.system_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.nonbonded_method = 'nocutoff'
vac_settings.protocol_repeats = 1
protocol = openmm_rfe.RelativeHybridTopologyProtocol(
@@ -727,7 +727,7 @@ def test_virtual_sites_no_reassign(benzene_system, toluene_system,
"amber/phosaa10.xml", # Handles THE TPO
]
settings.solvation_settings.solvent_padding = 1.0 * unit.nanometer
settings.system_settings.nonbonded_cutoff = 0.9 * unit.nanometer
settings.forcefield_settings.nonbonded_cutoff = 0.9 * unit.nanometer
settings.solvation_settings.solvent_model = 'tip4pew'
settings.integrator_settings.reassign_velocities = False
@@ -797,7 +797,7 @@ def test_hightimestep(benzene_vacuum_system,
benzene_to_toluene_mapping, tmpdir):
settings = openmm_rfe.RelativeHybridTopologyProtocol.default_settings()
settings.forcefield_settings.hydrogen_mass = 1.0
settings.system_settings.nonbonded_method = 'nocutoff'
settings.forcefield_settings.nonbonded_method = 'nocutoff'
p = openmm_rfe.RelativeHybridTopologyProtocol(
settings=settings,
@@ -823,8 +823,8 @@ def test_n_replicas_not_n_windows(benzene_vacuum_system,
# equals the numbers of replicas used - TODO: remove limitation
settings = openmm_rfe.RelativeHybridTopologyProtocol.default_settings()
# default lambda windows is 11
settings.alchemical_sampler_settings.n_replicas = 13
settings.system_settings.nonbonded_method = 'nocutoff'
settings.simulation_settings.n_replicas = 13
settings.forcefield_settings.nonbonded_method = 'nocutoff'
errmsg = ("Number of replicas 13 does not equal the number of "
"lambda windows 11")
@@ -1022,7 +1022,7 @@ def test_element_change_warning(atom_mapping_basic_test_files):
def test_ligand_overlap_warning(benzene_vacuum_system, toluene_vacuum_system,
benzene_to_toluene_mapping, tmpdir):
vac_settings = openmm_rfe.RelativeHybridTopologyProtocol.default_settings()
vac_settings.system_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.nonbonded_method = 'nocutoff'
protocol = openmm_rfe.RelativeHybridTopologyProtocol(
settings=vac_settings,
@@ -1552,8 +1552,6 @@ def benzene_solvent_openmm_system(benzene_modifications):
forcefield_settings=settings.forcefield_settings,
integrator_settings=settings.integrator_settings,
thermo_settings=settings.thermo_settings,
integrator_settings=settings.integrator_settings,
system_settings=settings.system_settings,
cache=None,
has_solvent=True,
)
@@ -1595,8 +1593,6 @@ def benzene_tip4p_solvent_openmm_system(benzene_modifications):
forcefield_settings=settings.forcefield_settings,
integrator_settings=settings.integrator_settings,
thermo_settings=settings.thermo_settings,
integrator_settings=settings.integrator_settings,
system_settings=settings.system_settings,
cache=None,
has_solvent=True,
)

View File

@@ -79,7 +79,7 @@ def test_create_independent_repeat_ids(benzene_system):
def test_dry_run_default_vacuum(benzene_vacuum_system, tmpdir):
vac_settings = PlainMDProtocol.default_settings()
vac_settings.system_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.nonbonded_method = 'nocutoff'
protocol = PlainMDProtocol(
settings=vac_settings,
@@ -104,7 +104,7 @@ def test_dry_run_default_vacuum(benzene_vacuum_system, tmpdir):
def test_dry_run_logger_output(benzene_vacuum_system, tmpdir, caplog):
vac_settings = PlainMDProtocol.default_settings()
vac_settings.system_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.nonbonded_method = 'nocutoff'
vac_settings.simulation_settings.equilibration_length_nvt = 1 * unit.picosecond
vac_settings.simulation_settings.equilibration_length = 1 * unit.picosecond
vac_settings.simulation_settings.production_length = 1 * unit.picosecond
@@ -135,7 +135,7 @@ def test_dry_run_logger_output(benzene_vacuum_system, tmpdir, caplog):
def test_dry_run_ffcache_none_vacuum(benzene_vacuum_system, tmpdir):
vac_settings = PlainMDProtocol.default_settings()
vac_settings.system_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.nonbonded_method = 'nocutoff'
vac_settings.output_settings.forcefield_cache = None
protocol = PlainMDProtocol(
@@ -157,7 +157,7 @@ def test_dry_run_ffcache_none_vacuum(benzene_vacuum_system, tmpdir):
def test_dry_run_gaff_vacuum(benzene_vacuum_system, tmpdir):
vac_settings = PlainMDProtocol.default_settings()
vac_settings.system_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.nonbonded_method = 'nocutoff'
vac_settings.forcefield_settings.small_molecule_forcefield = 'gaff-2.11'
protocol = PlainMDProtocol(
@@ -278,7 +278,7 @@ def test_dry_run_ligand_tip4p(benzene_system, tmpdir):
"amber/phosaa10.xml", # Handles THE TPO
]
settings.solvation_settings.solvent_padding = 1.0 * unit.nanometer
settings.system_settings.nonbonded_cutoff = 0.9 * unit.nanometer
settings.forcefield_settings.nonbonded_cutoff = 0.9 * unit.nanometer
settings.solvation_settings.solvent_model = 'tip4pew'
settings.integrator_settings.reassign_velocities = True
@@ -326,7 +326,7 @@ def test_dry_run_complex(benzene_complex_system, tmpdir):
def test_hightimestep(benzene_vacuum_system, tmpdir):
settings = PlainMDProtocol.default_settings()
settings.forcefield_settings.hydrogen_mass = 1.0
settings.system_settings.nonbonded_method = 'nocutoff'
settings.forcefield_settings.nonbonded_method = 'nocutoff'
p = PlainMDProtocol(
settings=settings,

View File

@@ -12,7 +12,7 @@ from openfe.protocols.openmm_utils import omm_settings
class TestOMMSettingsFromStrings:
# checks that we can set Settings fields via strings
def test_system_settings(self):
s = omm_settings.SystemSettings()
s = omm_settings.OpenMMSystemGeneratorFFSettings()
s.nonbonded_cutoff = '1.1 nm'
@@ -59,7 +59,7 @@ class TestOMMSettingsFromStrings:
class TestEquilRFESettingsFromString:
def test_alchemical_settings(self):
s = equil_rfe_settings.AlchemicalSettings()
s = equil_rfe_settings.AlchemicalSettings(softcore_LJ='gapsys')
s.explicit_charge_correction_cutoff = '0.85 nm'

View File

@@ -18,7 +18,7 @@ from openfe.protocols.openmm_utils import (
multistate_analysis
)
from openfe.protocols.openmm_rfe.equil_rfe_settings import (
SystemSettings, SolvationSettings, IntegratorSettings,
SolvationSettings, IntegratorSettings,
)
@@ -165,16 +165,13 @@ def test_components_complex(T4_protein_component, benzene_modifications):
@pytest.fixture(scope='module')
def get_settings():
forcefield_settings = OpenMMSystemGeneratorFFSettings()
integrator_settings = IntegratorSettings
integrator_settings = IntegratorSettings()
thermo_settings = ThermoSettings(
temperature=298.15 * unit.kelvin,
pressure=1 * unit.bar,
)
system_settings = SystemSettings()
integrator_settings = IntegratorSettings()
return (forcefield_settings, integrator_settings, thermo_settings, system_settings,
integrator_settings)
return forcefield_settings, integrator_settings, thermo_settings
class TestFEAnalysis:
@@ -269,22 +266,10 @@ class TestFEAnalysis:
class TestSystemCreation:
@staticmethod
def get_settings():
forcefield_settings = OpenMMSystemGeneratorFFSettings()
integrator_settings = IntegratorSettings()
thermo_settings = ThermoSettings(
temperature=298.15 * unit.kelvin,
pressure=1 * unit.bar,
)
system_settings = SystemSettings()
return forcefield_settings, integrator_settings, thermo_settings, system_settings
def test_system_generator_nosolv_nocache(self, get_settings):
ffsets, intsets, thermosets, systemsets, intsets = get_settings
ffsets, intsets, thermosets = get_settings
generator = system_creation.get_system_generator(
ffsets, intsets, thermosets, intsets, systemsets, None, False
ffsets, thermosets, intsets, None, False
)
assert generator.barostat is None
assert generator.template_generator._cache is None
@@ -306,13 +291,13 @@ class TestSystemCreation:
assert generator.periodic_forcefield_kwargs == periodic_kwargs
def test_system_generator_solv_cache(self, get_settings):
ffsets, intsets, thermosets, systemsets, intsets = get_settings
ffsets, intsets, thermosets = get_settings
thermosets.temperature = 320 * unit.kelvin
thermosets.pressure = 1.25 * unit.bar
intsets.barostat_frequency = 200 * unit.timestep
generator = system_creation.get_system_generator(
ffsets, intsets, thermosets, intsets, systemsets, Path('./db.json'), True
ffsets, thermosets, intsets, Path('./db.json'), True
)
# Check barostat conditions
@@ -336,9 +321,9 @@ class TestSystemCreation:
def test_get_omm_modeller_complex(self, T4_protein_component,
benzene_modifications,
get_settings):
ffsets, intsets, thermosets, systemsets, intsets = get_settings
ffsets, intsets, thermosets = get_settings
generator = system_creation.get_system_generator(
ffsets, intsets, thermosets, intsets, systemsets, None, True
ffsets, thermosets, intsets, None, True
)
smc = benzene_modifications['toluene']
@@ -362,9 +347,9 @@ class TestSystemCreation:
np.linspace(165, len(resids)-1, len(resids)-165))
def test_get_omm_modeller_ligand_no_neutralize(self, get_settings):
ffsets, intsets, thermosets, systemsets, intsets = get_settings
ffsets, intsets, thermosets = get_settings
generator = system_creation.get_system_generator(
ffsets, intsets, thermosets, intsets, systemsets, None, True
ffsets, thermosets, intsets, None, True
)
offmol = OFFMol.from_smiles('[O-]C=O')

View File

@@ -39,7 +39,7 @@ class TestRelativeHybridTopologyProtocolResult(GufeTokenizableTestsMixin):
class TestRelativeHybridTopologyProtocol(GufeTokenizableTestsMixin):
cls = openmm_rfe.RelativeHybridTopologyProtocol
key = "RelativeHybridTopologyProtocol-02ad30e0e0332ab6a8ce97bcdf3f287c"
key = "RelativeHybridTopologyProtocol-a7946099ab9756c22f3a79fe9082585a"
repr = f"<{key}>"
@pytest.fixture()

View File

@@ -49,7 +49,7 @@ def protocol_result(afe_solv_transformation_json):
class TestAbsoluteSolvationProtocol(GufeTokenizableTestsMixin):
cls = openmm_afe.AbsoluteSolvationProtocol
key = "AbsoluteSolvationProtocol-045abf8f41dbb14db338c2c8583da308"
key = "AbsoluteSolvationProtocol-9a18332b06a721da1b0fcaf5cc86dd25"
repr = f"<{key}>"
@pytest.fixture()