Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
5d0b683
Towards ABFE protocol
IAlibay Dec 11, 2024
22fbc37
Add base code for settings
IAlibay Dec 11, 2024
e1ef18c
Fix up the units a bit
IAlibay Dec 11, 2024
158ce40
Deal with the restraint addition
IAlibay Dec 11, 2024
deac61d
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Dec 14, 2024
2dd883a
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Dec 16, 2024
67abff1
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Feb 19, 2025
06f84c5
Add various fixes
IAlibay Feb 20, 2025
8506db2
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Feb 25, 2025
6ecec87
some QoL updates
IAlibay Feb 26, 2025
f5369c6
Fix a few things with the restraint addition
IAlibay Feb 27, 2025
0e93e00
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Feb 27, 2025
6f5a4e0
fix regex match test
IAlibay Feb 27, 2025
9f1cc46
Fix the case where we don't have a restraint parameter
IAlibay Feb 27, 2025
0d32568
Enforce the periodic box when getting state to avoid NaNs
IAlibay Feb 27, 2025
4aa6151
Fix up some protocol results things
IAlibay Feb 28, 2025
c0d3d58
Add some tests and validation
IAlibay Mar 2, 2025
7db8ac6
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Mar 2, 2025
a856403
Some reformatting
IAlibay Mar 2, 2025
a28cc59
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Mar 2, 2025
6d0a51d
fix return type hint
IAlibay Mar 2, 2025
ecad789
Add test for complex equil output indices
IAlibay Mar 2, 2025
d901204
Allow generation of results for ABFEs
IAlibay Mar 4, 2025
86fc509
add settings_cls
IAlibay Mar 4, 2025
f976de0
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Mar 4, 2025
84a932b
Update openfe/protocols/restraint_utils/settings.py
IAlibay Mar 5, 2025
5a59f08
Bad things
IAlibay Mar 6, 2025
617b8fe
Fix the restraints to be the right way around
IAlibay Mar 11, 2025
3abe329
lint file, add restraint_geom return
IAlibay Mar 11, 2025
b4b0f33
Add rest geom return
IAlibay Mar 11, 2025
56045c9
Fix up things
IAlibay Mar 11, 2025
f219492
Add protocol results for testing and also add geometry to results object
IAlibay Mar 13, 2025
d5ac4e0
Add tokenization tests
IAlibay Mar 13, 2025
8258f66
add protocol results tests
IAlibay Mar 13, 2025
e1a5645
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Mar 13, 2025
22038f4
Remove None guard
IAlibay Mar 13, 2025
d24605f
revert random guard
IAlibay Mar 13, 2025
8012625
fixing pbc handling and the solvent unit
IAlibay Mar 14, 2025
befb5d7
Add a comment
IAlibay Mar 14, 2025
b626f53
fix
IAlibay Mar 14, 2025
be2de12
separate solvation settings for complex and solvent
hannahbaumann Mar 27, 2025
302eb2b
Update openfe/protocols/openmm_afe/equil_binding_afe_method.py
hannahbaumann Apr 1, 2025
984a501
Merge branch 'main' into abfe_protocol
hannahbaumann Apr 1, 2025
d17fa4f
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Apr 15, 2025
52076d0
max on frc_const check
IAlibay Apr 15, 2025
2fab254
try sanitizing molecules
IAlibay Apr 15, 2025
eba3d43
Add missing return
IAlibay Apr 15, 2025
81823c0
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Apr 15, 2025
814f468
min not max
IAlibay Apr 16, 2025
b051600
Merge branch 'omm-restraints' into abfe_protocol
IAlibay May 1, 2025
e113e7c
Make the reporter write the last frame
IAlibay May 4, 2025
08b28dc
fix benzene solvent test
IAlibay May 5, 2025
5ee7c73
Update tests
IAlibay May 22, 2025
2533cef
Merge branch 'main' into abfe_protocol
IAlibay May 23, 2025
614edc1
Merge branch 'abfe_protocol' of github.com:OpenFreeEnergy/openfe into…
IAlibay Jun 3, 2025
8ed6084
update lambdas to list[float]
IAlibay Jun 3, 2025
6982106
Merge branch 'omm-restraints' into abfe_protocol
IAlibay Jul 1, 2025
f84d72a
Fix the get states call
IAlibay Jul 1, 2025
96e9325
fix units
IAlibay Jul 2, 2025
3557ffe
black after isort
IAlibay Jul 2, 2025
3c7de18
fix tests
IAlibay Jul 2, 2025
cc6d112
fix mypy
IAlibay Jul 2, 2025
f69daf9
backport Mike's fix
IAlibay Jul 2, 2025
9f09b85
Merge branch 'main' into abfe_protocol
IAlibay Jul 15, 2025
780671c
Merge branch 'main' into abfe_protocol
hannahbaumann Aug 1, 2025
626c9d0
Merge branch 'main' into abfe_protocol
IAlibay Aug 12, 2025
274c258
Enable anchor finding strategy in abfe protocol
IAlibay Aug 12, 2025
cb11dc5
Merge branch 'main' into abfe_protocol
IAlibay Aug 14, 2025
4c72787
Merge branch 'main' into abfe_protocol
hannahbaumann Aug 22, 2025
864f10c
Merge branch 'main' into abfe_protocol
hannahbaumann Sep 8, 2025
a157b57
Add ABFE protocol docs (#1507)
hannahbaumann Sep 23, 2025
301b381
Merge branch 'main' into abfe_protocol
IAlibay Sep 23, 2025
919f125
Merge branch 'main' into abfe_protocol
hannahbaumann Sep 29, 2025
57f694d
Merge branch 'main' into abfe_protocol
hannahbaumann Oct 6, 2025
42b87aa
Merge branch 'main' into abfe_protocol
IAlibay Oct 9, 2025
127468a
Some formatting, duecredit tests
IAlibay Oct 9, 2025
15bdfbc
some fixes
IAlibay Oct 9, 2025
9b1507a
some prep for net charge checks
IAlibay Oct 12, 2025
9df87d5
Merge branch 'main' into abfe_protocol
IAlibay Oct 13, 2025
16f2b63
some validation stuff
IAlibay Oct 13, 2025
a867d39
Fix up settings and validation things
IAlibay Oct 13, 2025
6088267
format settings
IAlibay Oct 13, 2025
d30b574
format the lambda schedules
IAlibay Oct 13, 2025
47ab5a7
Merge branch 'main' into abfe_protocol
IAlibay Oct 13, 2025
8335198
Deal with some validation stuff
IAlibay Oct 14, 2025
97ffb2e
Merge branch 'abfe_protocol' of github.com:OpenFreeEnergy/openfe into…
IAlibay Oct 14, 2025
2119ce5
fix up protocol results tests
IAlibay Oct 14, 2025
07e0aa7
Merge branch 'main' into abfe_protocol
IAlibay Oct 14, 2025
849365b
typing thing
IAlibay Oct 14, 2025
03757e9
Add more returns to the debug dictionary
IAlibay Oct 14, 2025
3fca3c1
Add gather test
IAlibay Oct 15, 2025
139411b
Add tagging test
IAlibay Oct 15, 2025
8765e60
stop duplicating execute everywhere
IAlibay Oct 15, 2025
45b3a99
Add check for virtual sites & fail if no reassign
IAlibay Oct 15, 2025
b5eefa7
move timestep validation up to validate
IAlibay Oct 15, 2025
8669e27
Merge branch 'main' into abfe_protocol
IAlibay Oct 15, 2025
0580dd1
Add unit tagging tests
IAlibay Oct 15, 2025
1c8386a
Add base dry run test
IAlibay Oct 16, 2025
07577fe
Add energy checks
IAlibay Oct 16, 2025
c133006
reformat a few things
IAlibay Oct 16, 2025
3032da3
Merge branch 'main' into abfe_protocol
IAlibay Oct 16, 2025
e199baa
Add slow extra dry run test
IAlibay Oct 16, 2025
5b1a65e
Add energy tests
IAlibay Oct 16, 2025
a394fa9
Apply suggestion from @hannahbaumann
IAlibay Oct 16, 2025
77e35cb
typo
IAlibay Oct 16, 2025
8d7cd64
remove extra prints
IAlibay Oct 16, 2025
5bf0144
deal with typo
IAlibay Oct 16, 2025
07d922c
fix septop test with renamed fixture
IAlibay Oct 16, 2025
156e73f
Various fixes and some slow tests
IAlibay Oct 17, 2025
df219c6
Merge branch 'main' into abfe_protocol
IAlibay Oct 17, 2025
a68f062
Add news item
IAlibay Oct 17, 2025
ba1c807
remove debug shim
IAlibay Oct 17, 2025
d935551
reverse the restraint lambda windows
IAlibay Oct 17, 2025
7fe2712
Update openfe/protocols/openmm_afe/equil_binding_afe_method.py
IAlibay Oct 17, 2025
d20fffd
Update openfe/protocols/openmm_afe/equil_binding_afe_method.py
IAlibay Oct 17, 2025
4be91e0
Update openfe/tests/protocols/openmm_abfe/test_abfe_energies.py
IAlibay Oct 17, 2025
b9d37d2
Change how we combine corrections
IAlibay Oct 17, 2025
2bdb6a9
Merge branch 'abfe_protocol' of github.com:OpenFreeEnergy/openfe into…
IAlibay Oct 17, 2025
9f802d1
Address some review comments
IAlibay Oct 17, 2025
c2bff25
Add an extra note for the solvent lambda settings
IAlibay Oct 17, 2025
d7e0da9
Merge branch 'main' into abfe_protocol
IAlibay Oct 17, 2025
3fb1036
try to make myppy happy
IAlibay Oct 17, 2025
a29dbc0
you happy now mypy?
IAlibay Oct 17, 2025
acd1f6b
And again...
IAlibay Oct 17, 2025
b25f86e
Add net charge check test
IAlibay Oct 17, 2025
ec04f3a
remove early termination
IAlibay Oct 17, 2025
23ed15e
Merge branch 'main' into abfe_protocol
IAlibay Oct 20, 2025
6b87bab
Merge branch 'main' into abfe_protocol
IAlibay Oct 20, 2025
fa02671
fix tests
IAlibay Oct 20, 2025
a174ef2
fix restraints
IAlibay Oct 20, 2025
5fff298
fix settings validation for lambdas
IAlibay Oct 20, 2025
9d22909
update results
IAlibay Oct 20, 2025
ef634a0
Merge branch 'main' into abfe_protocol
IAlibay Oct 20, 2025
7cec9e2
Update for new settings
IAlibay Oct 20, 2025
ec5ecd2
Merge branch 'main' into abfe_protocol
IAlibay Oct 20, 2025
9765bf1
Merge branch 'main' into abfe_protocol
IAlibay Oct 21, 2025
8e1b2ee
Update openfe/protocols/openmm_afe/equil_afe_settings.py
IAlibay Oct 21, 2025
5c8ef53
Merge branch 'main' into abfe_protocol
IAlibay Oct 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 97 additions & 52 deletions openfe/protocols/openmm_afe/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from openmmtools import multistate
from openmmtools.states import (SamplerState,
ThermodynamicState,
GlobalParameterState,
create_thermodynamic_state_protocol,)
from openmmtools.alchemy import (AlchemicalRegion, AbsoluteAlchemicalFactory,
AlchemicalState,)
Expand Down Expand Up @@ -469,45 +470,70 @@ def _get_modeller(

def _get_omm_objects(
self,
system_modeller: app.Modeller,
system_generator: SystemGenerator,
smc_components: list[OFFMolecule],
) -> tuple[app.Topology, openmm.unit.Quantity, openmm.System]:
settings: dict[str, SettingsBaseModel],
protein_component: Optional[ProteinComponent],
solvent_component: Optional[SolventComponent],
smc_components: dict[SmallMoleculeComponent, OFFMolecule],
) -> tuple[
app.Topology,
openmm.System,
openmm.unit.Quantity,
dict[str, npt.NDArray],
]:
"""
Get the OpenMM Topology, Positions and System of the
parameterised system.

Parameters
----------
system_modeller : app.Modeller
OpenMM Modeller object representing the system to be
parametrized.
system_generator : SystemGenerator
SystemGenerator object to create a System with.
smc_components : list[openff.toolkit.Molecule]
A list of openff Molecules to add to the system.
settings : dict[str, SettingsBaseModel]
Protocol settings
protein_component : Optional[ProteinComponent]
Protein component for the system.
solvent_component : Optional[SolventComponent]
Solvent component for the system.
smc_components : dict[str, OFFMolecule]
SmallMoleculeComponents defining ligands to be added to the system

Returns
-------
topology : app.Topology
Topology object describing the parameterized system
OpenMM Topology object describing the parameterized system.
system : openmm.System
An OpenMM System of the alchemical system.
positionns : openmm.unit.Quantity
An non-alchemical OpenMM System of the simulated system.
positions : openmm.unit.Quantity
Positions of the system.
comp_resids : dict[str, npt.NDArray]
A dictionary of residues for each component in the System.
"""
topology = system_modeller.getTopology()
if self.verbose:
self.logger.info("Parameterizing system")

system_generator = self._get_system_generator(
settings, solvent_component
)

modeller, comp_resids = self._get_modeller(
protein_component,
solvent_component,
smc_components,
system_generator,
settings['charge_settings'],
settings['solvation_settings']
)

topology = modeller.getTopology()
# roundtrip positions to remove vec3 issues
positions = to_openmm(from_openmm(system_modeller.getPositions()))
positions = to_openmm(from_openmm(modeller.getPositions()))

# Block out oechem backend to avoid any issues with
# smiles roundtripping between rdkit and oechem
with without_oechem_backend():
system = system_generator.create_system(
system_modeller.topology,
modeller.topology,
molecules=smc_components,
)
return topology, system, positions
return topology, system, positions, comp_resids

def _get_lambda_schedule(
self, settings: dict[str, SettingsBaseModel]
Expand All @@ -533,21 +559,24 @@ def _get_lambda_schedule(

lambda_elec = settings['lambda_settings'].lambda_elec
lambda_vdw = settings['lambda_settings'].lambda_vdw
lambda_rest = settings['lambda_settings'].lambda_restraints

# Reverse lambda schedule since in AbsoluteAlchemicalFactory 1
# means fully interacting, not stateB
lambda_elec = [1-x for x in lambda_elec]
lambda_vdw = [1-x for x in lambda_vdw]
lambdas['lambda_electrostatics'] = lambda_elec
lambdas['lambda_sterics'] = lambda_vdw
for name, schedule in [
('lambda_electrostatics', lambda_elec),
('lambda_sterics', lambda_vdw),
('lambda_restraints', lambda_rest),
]:
lambdas[name] = [1-x for x in schedule]

return lambdas

def _add_restraints(self, system, topology, settings):
"""
Placeholder method to add restraints if necessary
"""
return
return None, None, system

def _get_alchemical_system(
self,
Expand Down Expand Up @@ -607,6 +636,7 @@ def _get_states(
settings: dict[str, SettingsBaseModel],
lambdas: dict[str, npt.NDArray],
solvent_comp: Optional[SolventComponent],
restraint_state: Optional[GlobalParameterState],
) -> tuple[list[SamplerState], list[ThermodynamicState]]:
"""
Get a list of sampler and thermodynmic states from an
Expand All @@ -624,6 +654,8 @@ def _get_states(
A dictionary of lambda scales.
solvent_comp : Optional[SolventComponent]
The solvent component of the system, if there is one.
restraint_state : Optional[GlobalParameterState]
The restraint parameter control state, if there is one.

Returns
-------
Expand All @@ -641,9 +673,14 @@ def _get_states(
if solvent_comp is not None:
constants['pressure'] = ensure_quantity(pressure, 'openmm')

if restraint_state is not None:
composable_states = [alchemical_state, restraint_state]
else:
composable_states = [alchemical_state,]

cmp_states = create_thermodynamic_state_protocol(
alchemical_system, protocol=lambdas,
constants=constants, composable_states=[alchemical_state],
constants=constants, composable_states=composable_states,
)

sampler_state = SamplerState(positions=positions)
Expand Down Expand Up @@ -873,6 +910,7 @@ def _run_simulation(
sampler: multistate.MultiStateSampler,
reporter: multistate.MultiStateReporter,
settings: dict[str, SettingsBaseModel],
standard_state_corr: Optional[unit.Quantity]
dry: bool
):
"""
Expand All @@ -886,6 +924,8 @@ def _run_simulation(
The reporter associated with the sampler.
settings : dict[str, SettingsBaseModel]
The dictionary of settings for the protocol.
standard_state_corr : Optional[unit.Quantity]
The standard state correction, if available.
dry : bool
Whether or not to dry run the simulation

Expand Down Expand Up @@ -944,7 +984,12 @@ def _run_simulation(
analyzer.plot(filepath=self.shared_basepath, filename_prefix="")
analyzer.close()

return analyzer.unit_results_dict
return_dict = analyzer.unit_results_dict

if standard_state_corr is not None:
return_dict['standard_state_correction'] = standard_state_corr

return return_dict

else:
# close reporter when you're done, prevent file handle clashes
Expand Down Expand Up @@ -991,44 +1036,40 @@ def run(self, dry=False, verbose=True,
# 2. Get settings
settings = self._handle_settings()

# 3. Get system generator
system_generator = self._get_system_generator(settings, solv_comp)

# 4. Get modeller
system_modeller, comp_resids = self._get_modeller(
prot_comp, solv_comp, smc_comps, system_generator,
settings['charge_settings'],
settings['solvation_settings'],
# 3. Get OpenMM topology, positions, and system
omm_topology, omm_system, position, comp_resids = self._get_omm_objects(
settings, prot_comps, solv_comps, smc_comps,
)

# 5. Get OpenMM topology, positions and system
omm_topology, omm_system, positions = self._get_omm_objects(
system_modeller, system_generator, list(smc_comps.values())
)

# 6. Pre-equilbrate System (Test + Avoid NaNs + get stable system)
# 4. Pre-equilbrate System (Test + Avoid NaNs + get stable system)
positions = self._pre_equilibrate(
omm_system, omm_topology, positions, settings, dry
)

# 7. Get lambdas
# 5. Get lambdas
lambdas = self._get_lambda_schedule(settings)

# 8. Add restraints
self._add_restraints(omm_system, omm_topology, settings)
# 6. Add restraints
restraint_parameter_state, standard_state_corr, omm_system = self._add_restraints(
omm_system, omm_topology, settings
)

# 9. Get alchemical system
# 7. Get alchemical system
alchem_factory, alchem_system, alchem_indices = self._get_alchemical_system(
omm_topology, omm_system, comp_resids, alchem_comps
)

# 10. Get compound and sampler states
# 7. Get compound and sampler states
sampler_states, cmp_states = self._get_states(
alchem_system, positions, settings,
lambdas, solv_comp
alchem_system,
positions,
settings,
lambdas,
solv_comp,
restraint_parameter_state,
)

# 11. Create the multistate reporter & create PDB
# 9. Create the multistate reporter & create PDB
reporter = self._get_reporter(
omm_topology, positions,
settings['simulation_settings'],
Expand All @@ -1037,29 +1078,33 @@ def run(self, dry=False, verbose=True,

# Wrap in try/finally to avoid memory leak issues
try:
# 12. Get context caches
# 10. Get context caches
energy_ctx_cache, sampler_ctx_cache = self._get_ctx_caches(
settings['forcefield_settings'],
settings['engine_settings']
)

# 13. Get integrator
# 11. Get integrator
integrator = self._get_integrator(
settings['integrator_settings'],
settings['simulation_settings'],
)

# 14. Get sampler
# 12. Get sampler
sampler = self._get_sampler(
integrator, reporter, settings['simulation_settings'],
settings['thermo_settings'],
cmp_states, sampler_states,
energy_ctx_cache, sampler_ctx_cache
)

# 15. Run simulation
# 13. Run simulation
unit_result_dict = self._run_simulation(
sampler, reporter, settings, dry
sampler,
reporter,
settings,
standard_state_corr,
dry
)

finally:
Expand Down
Loading
Loading