Skip to content

Commit 41f50fc

Browse files
committed
Add test for single topology end-states
1 parent 10d0045 commit 41f50fc

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

tests/test_single_topology.py

+46
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
setup_dummy_interactions_from_ff,
3737
)
3838
from timemachine.fe.system import minimize_scipy, simulate_system
39+
from timemachine.fe.topology import BaseTopology
3940
from timemachine.fe.utils import get_mol_name, get_romol_conf, read_sdf, read_sdf_mols_by_name, set_mol_name
4041
from timemachine.ff import Forcefield
4142
from timemachine.md import minimizer
@@ -1743,3 +1744,48 @@ def test_hif2a_end_state_symmetry_nightly_test():
17431744
print("testing", mol_a.GetProp("_Name"), "->", mol_b.GetProp("_Name"))
17441745
core = atom_mapping.get_cores(mol_a, mol_b, **DEFAULT_ATOM_MAPPING_KWARGS)[0]
17451746
assert_symmetric_interpolation(mol_a, mol_b, core)
1747+
1748+
1749+
def test_empty_core():
1750+
# test that an empty core results in an end-state with identical energies and forces to independent molecules
1751+
with path_to_internal_file("timemachine.testsystems.data", "ligands_40.sdf") as path_to_ligand:
1752+
mols = read_sdf(path_to_ligand)
1753+
1754+
mol_a = mols[0]
1755+
mol_b = mols[1]
1756+
1757+
x_a = get_romol_conf(mol_a)
1758+
x_b = get_romol_conf(mol_b)
1759+
core = np.zeros((0, 2))
1760+
1761+
ff = Forcefield.load_default()
1762+
st = SingleTopology(mol_a, mol_b, core, ff)
1763+
lhs = st.setup_intermediate_state(0.0)
1764+
rhs = st.setup_intermediate_state(1.0)
1765+
1766+
x_0 = st.combine_confs(x_a, x_b, 0.0)
1767+
x_1 = st.combine_confs(x_a, x_b, 1.0)
1768+
1769+
np.testing.assert_array_equal(x_0, x_1)
1770+
1771+
# lhs and rhs do not have identical total energies since dummy molecule is in a softened state
1772+
lhs_U_fn = lhs.get_U_fn()
1773+
rhs_U_fn = rhs.get_U_fn()
1774+
1775+
assert lhs_U_fn(x_0) != rhs_U_fn(x_0)
1776+
1777+
# however, the bond, angle, improper energies should be bitwise identical
1778+
assert lhs.bond(x_0, None) == rhs.bond(x_0, None)
1779+
assert lhs.angle(x_0, None) == rhs.angle(x_0, None)
1780+
assert lhs.improper(x_0, None) == rhs.improper(x_0, None)
1781+
1782+
# we should also be consistent with vanilla base topologies
1783+
bt_a = BaseTopology(mol_a, ff)
1784+
bt_b = BaseTopology(mol_b, ff)
1785+
1786+
ref_a = bt_a.setup_end_state()
1787+
ref_b = bt_b.setup_end_state()
1788+
1789+
np.testing.assert_almost_equal(lhs.bond(x_0, None), ref_a.bond(x_a, None) + ref_b.bond(x_b, None))
1790+
np.testing.assert_almost_equal(lhs.angle(x_0, None), ref_a.angle(x_a, None) + ref_b.angle(x_b, None))
1791+
np.testing.assert_almost_equal(lhs.improper(x_0, None), ref_a.improper(x_a, None) + ref_b.improper(x_b, None))

timemachine/fe/single_topology.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def setup_dummy_bond_and_chiral_interactions(
144144
root_anchor_atom: int,
145145
core_atoms: NDArray,
146146
):
147-
assert root_anchor_atom in core_atoms
147+
assert root_anchor_atom is None or root_anchor_atom in core_atoms
148148

149149
dummy_group_arr = np.array(list(dummy_group))
150150

@@ -286,7 +286,7 @@ def setup_dummy_interactions(
286286
(bonded_idxs, bonded_params)
287287
Returns bonds, angles, and improper idxs and parameters.
288288
"""
289-
assert root_anchor_atom in core_atoms
289+
assert root_anchor_atom is None or root_anchor_atom in core_atoms
290290

291291
dummy_angle_idxs = []
292292
dummy_angle_params = []
@@ -664,9 +664,8 @@ def concatenate(arrays, empty_shape, empty_dtype):
664664
)
665665

666666
num_atoms = mol_a.GetNumAtoms() + mol_b.GetNumAtoms() - len(core)
667-
assert get_num_connected_components(num_atoms, bond_potential.potential.idxs) == 1, (
668-
"hybrid molecule has multiple connected components"
669-
)
667+
if get_num_connected_components(num_atoms, bond_potential.potential.idxs) > 1:
668+
warnings.warn("Hybrid molecule has multiple connected components")
670669

671670
return GuestSystem(
672671
bond=bond_potential,

0 commit comments

Comments
 (0)