Skip to content

Commit 23bf4ae

Browse files
authored
Break down monolithic driver and heuristics tests (#881)
Splits the catch-all `test_map_abstractions` and heuristics tests into one test per reaction case, so failures point at a specific scenario instead of one giant test. Shared XYZ fixtures live on `setUpClass`. No production-code changes.
2 parents 42c0f2a + 0d22e94 commit 23bf4ae

2 files changed

Lines changed: 232 additions & 228 deletions

File tree

arc/job/adapters/ts/heuristics_test.py

Lines changed: 105 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,63 +1125,58 @@ def test_heuristics_for_h_abstraction_13(self):
11251125
heuristics_1.execute_incore()
11261126
self.assertEqual(len(rxn1.ts_species.ts_guesses), 12)
11271127

1128-
def test_heuristics_for_hydrolysis(self):
1128+
def test_heuristics_for_carbonyl_based_hydrolysis(self):
11291129
"""
1130-
Test that ARC can generate TS guesses based on heuristics for different hydrolysis families reactions.
1130+
Test heuristics for carbonyl-based hydrolysis: C2H4O2 + H2O <=> CH2O2 + CH4O.
11311131
"""
1132-
# Carbonyl-based hydrolysis
1133-
# C2H4O2 + H2O <=> CH2O2 + CH4O
1134-
methylformate = self.methylformate
1135-
formicacid = self.formicacid
1136-
methanol = self.methanol
1137-
water = self.water
1138-
rxn1 = ARCReaction(r_species=[methylformate, water], p_species=[formicacid, methanol],
1139-
family='carbonyl_based_hydrolysis')
1140-
heuristics_1 = HeuristicsAdapter(job_type='tsg',
1141-
reactions=[rxn1],
1142-
testing=True,
1143-
project='test',
1144-
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics')
1145-
)
1146-
heuristics_1.execute_incore()
1147-
self.assertEqual(rxn1.family, 'carbonyl_based_hydrolysis')
1148-
self.assertTrue(rxn1.ts_species.is_ts)
1149-
self.assertEqual(rxn1.ts_species.ts_guesses[0].initial_xyz['symbols'],
1132+
rxn = ARCReaction(r_species=[self.methylformate, self.water],
1133+
p_species=[self.formicacid, self.methanol],
1134+
family='carbonyl_based_hydrolysis')
1135+
adapter = HeuristicsAdapter(job_type='tsg',
1136+
reactions=[rxn],
1137+
testing=True,
1138+
project='test',
1139+
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics_carbonyl'))
1140+
adapter.execute_incore()
1141+
self.assertEqual(rxn.family, 'carbonyl_based_hydrolysis')
1142+
self.assertTrue(rxn.ts_species.is_ts)
1143+
self.assertEqual(rxn.ts_species.ts_guesses[0].initial_xyz['symbols'],
11501144
('C', 'O', 'C', 'O', 'H', 'H', 'H', 'H', 'O', 'H', 'H'))
1151-
self.assertEqual(len(rxn1.ts_species.ts_guesses), 6)
1152-
# Ether hydrolysis
1153-
# C3H8O + H2O <=> C2H6O + CH4O
1154-
allylmethylether = self.allylmethylether
1155-
allylalcohol = self.allylalcohol
1156-
methanol = self.methanol
1157-
rxn2 = ARCReaction(r_species=[allylmethylether, water], p_species=[allylalcohol, methanol])
1158-
heuristics_2 = HeuristicsAdapter(job_type='tsg',
1159-
reactions=[rxn2],
1160-
testing=True,
1161-
project='test',
1162-
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics')
1163-
)
1164-
heuristics_2.execute_incore()
1165-
self.assertEqual(rxn2.family, 'ether_hydrolysis')
1166-
self.assertTrue(rxn2.ts_species.is_ts)
1167-
self.assertEqual(rxn2.ts_species.ts_guesses[0].initial_xyz['symbols'],
1145+
self.assertEqual(len(rxn.ts_species.ts_guesses), 6)
1146+
1147+
def test_heuristics_for_ether_hydrolysis(self):
1148+
"""
1149+
Test heuristics for ether hydrolysis: C3H8O + H2O <=> C2H6O + CH4O.
1150+
"""
1151+
rxn = ARCReaction(r_species=[self.allylmethylether, self.water],
1152+
p_species=[self.allylalcohol, self.methanol])
1153+
adapter = HeuristicsAdapter(job_type='tsg',
1154+
reactions=[rxn],
1155+
testing=True,
1156+
project='test',
1157+
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics_ether'))
1158+
adapter.execute_incore()
1159+
self.assertEqual(rxn.family, 'ether_hydrolysis')
1160+
self.assertTrue(rxn.ts_species.is_ts)
1161+
self.assertEqual(rxn.ts_species.ts_guesses[0].initial_xyz['symbols'],
11681162
('C', 'C', 'C', 'O', 'C', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'O', 'H', 'H'))
1169-
self.assertEqual(len(rxn2.ts_species.ts_guesses), 4)
1170-
# Nitrile hydrolysis
1171-
# N#CC(C#N) + H2O <=> N=C(O)C(C#N)
1172-
malononitrile = self.malononitrile
1173-
iminopropanoic_acid = self.iminopropanoic_acid
1174-
rxn4 = ARCReaction(r_species=[malononitrile, water], p_species=[iminopropanoic_acid])
1175-
heuristics_4 = HeuristicsAdapter(job_type='tsg',
1176-
reactions=[rxn4],
1177-
testing=True,
1178-
project='test',
1179-
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics')
1180-
)
1181-
heuristics_4.execute_incore()
1182-
self.assertEqual(rxn4.family, 'nitrile_hydrolysis')
1183-
self.assertTrue(rxn4.ts_species.is_ts)
1184-
self.assertEqual(rxn4.ts_species.ts_guesses[0].initial_xyz['symbols'],
1163+
self.assertEqual(len(rxn.ts_species.ts_guesses), 4)
1164+
1165+
def test_heuristics_for_nitrile_hydrolysis(self):
1166+
"""
1167+
Test heuristics for nitrile hydrolysis: N#CC(C#N) + H2O <=> N=C(O)C(C#N).
1168+
"""
1169+
rxn = ARCReaction(r_species=[self.malononitrile, self.water],
1170+
p_species=[self.iminopropanoic_acid])
1171+
adapter = HeuristicsAdapter(job_type='tsg',
1172+
reactions=[rxn],
1173+
testing=True,
1174+
project='test',
1175+
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics_nitrile'))
1176+
adapter.execute_incore()
1177+
self.assertEqual(rxn.family, 'nitrile_hydrolysis')
1178+
self.assertTrue(rxn.ts_species.is_ts)
1179+
self.assertEqual(rxn.ts_species.ts_guesses[0].initial_xyz['symbols'],
11851180
('N', 'C', 'C', 'C', 'N', 'H', 'H', 'O', 'H', 'H'))
11861181

11871182
def test_keeping_atom_order_in_ts(self):
@@ -1958,90 +1953,65 @@ def test_find_distant_neighbor(self):
19581953
self.assertEqual(find_distant_neighbor(mol=mol_3, start=2), 4)
19591954
self.assertEqual(find_distant_neighbor(mol=mol_3, start=2), 4)
19601955

1961-
def test_are_h_abs_wells_reversed(self):
1962-
"""
1963-
Test the are_h_abs_wells_reversed() function.
1964-
The expected order is: R(*1)-H(*2) + R(*3)j <=> R(*1)j + R(*3)-H(*2)
1965-
"""
1966-
rxn_1 = ARCReaction(r_species=[ARCSpecies(label='C2H6', smiles='CC'), ARCSpecies(label='OH', smiles='[OH]')],
1967-
# none are reversed
1968-
p_species=[ARCSpecies(label='C2H5', smiles='[CH2]C'), ARCSpecies(label='H2O', smiles='O')])
1969-
rxn_2 = ARCReaction(r_species=[ARCSpecies(label='OH', smiles='[OH]'), ARCSpecies(label='C2H6', smiles='CC')],
1970-
# r reversed
1971-
p_species=[ARCSpecies(label='C2H5', smiles='[CH2]C'), ARCSpecies(label='H2O', smiles='O')])
1972-
rxn_3 = ARCReaction(r_species=[ARCSpecies(label='C2H6', smiles='CC'), ARCSpecies(label='OH', smiles='[OH]')],
1973-
# p reversed
1974-
p_species=[ARCSpecies(label='H2O', smiles='O'), ARCSpecies(label='C2H5', smiles='[CH2]C')])
1975-
rxn_4 = ARCReaction(r_species=[ARCSpecies(label='OH', smiles='[OH]'), ARCSpecies(label='C2H6', smiles='CC')],
1976-
# r and p reversed
1977-
p_species=[ARCSpecies(label='H2O', smiles='O'), ARCSpecies(label='C2H5', smiles='[CH2]C')])
1978-
1979-
product_dicts = get_reaction_family_products(rxn=rxn_1,
1980-
rmg_family_set=[rxn_1.family],
1981-
consider_rmg_families=True,
1982-
consider_arc_families=False,
1983-
discover_own_reverse_rxns_in_reverse=False,
1984-
)
1985-
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_1, product_dict=product_dicts[0])
1986-
self.assertFalse(r_reversed)
1987-
self.assertFalse(p_reversed)
1988-
1989-
product_dicts = get_reaction_family_products(rxn=rxn_2,
1990-
rmg_family_set=[rxn_2.family],
1991-
consider_rmg_families=True,
1992-
consider_arc_families=False,
1993-
discover_own_reverse_rxns_in_reverse=False,
1994-
)
1995-
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_2, product_dict=product_dicts[0])
1996-
self.assertTrue(r_reversed)
1997-
self.assertFalse(p_reversed)
1998-
1999-
product_dicts = get_reaction_family_products(rxn=rxn_3,
2000-
rmg_family_set=[rxn_3.family],
2001-
consider_rmg_families=True,
2002-
consider_arc_families=False,
2003-
discover_own_reverse_rxns_in_reverse=False,
2004-
)
2005-
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_3, product_dict=product_dicts[0])
2006-
self.assertFalse(r_reversed)
2007-
self.assertTrue(p_reversed)
2008-
2009-
product_dicts = get_reaction_family_products(rxn=rxn_4,
2010-
rmg_family_set=[rxn_4.family],
2011-
consider_rmg_families=True,
2012-
consider_arc_families=False,
2013-
discover_own_reverse_rxns_in_reverse=False,
2014-
)
2015-
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_4, product_dict=product_dicts[0])
2016-
self.assertTrue(r_reversed)
2017-
self.assertTrue(p_reversed)
2018-
2019-
rxn_5 = ARCReaction(r_species=[ARCSpecies(label='H', smiles='[H]'), ARCSpecies(label='H2O', smiles='O')],
2020-
# r and p reversed
2021-
p_species=[ARCSpecies(label='H2', smiles='[H][H]'), ARCSpecies(label='OH', smiles='[OH]')])
2022-
product_dicts = get_reaction_family_products(rxn=rxn_5,
2023-
rmg_family_set=[rxn_5.family],
2024-
consider_rmg_families=True,
2025-
consider_arc_families=False,
2026-
discover_own_reverse_rxns_in_reverse=False,
2027-
)
2028-
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_5, product_dict=product_dicts[0])
2029-
self.assertTrue(r_reversed)
2030-
self.assertTrue(p_reversed)
2031-
2032-
rxn_6 = ARCReaction(
2033-
r_species=[ARCSpecies(label='CCCC(O)=O', smiles='CCCC(O)=O'), ARCSpecies(label='OH', smiles='[OH]')],
2034-
# none are reversed
2035-
p_species=[ARCSpecies(label='CCCC([O])=O', smiles='CCCC([O])=O'), ARCSpecies(label='H2O', smiles='O')])
2036-
product_dicts = get_reaction_family_products(rxn=rxn_6,
2037-
rmg_family_set=[rxn_6.family],
1956+
def _check_h_abs_wells_reversed(self, rxn: 'ARCReaction', expected_r_reversed: bool, expected_p_reversed: bool):
1957+
"""Helper: run are_h_abs_wells_reversed against the family products and assert the orientations."""
1958+
product_dicts = get_reaction_family_products(rxn=rxn,
1959+
rmg_family_set=[rxn.family],
20381960
consider_rmg_families=True,
20391961
consider_arc_families=False,
20401962
discover_own_reverse_rxns_in_reverse=False,
20411963
)
2042-
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_6, product_dict=product_dicts[0])
2043-
self.assertFalse(r_reversed)
2044-
self.assertFalse(p_reversed)
1964+
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn, product_dict=product_dicts[0])
1965+
self.assertEqual(r_reversed, expected_r_reversed)
1966+
self.assertEqual(p_reversed, expected_p_reversed)
1967+
1968+
def test_are_h_abs_wells_reversed_neither_reversed(self):
1969+
"""C2H6 + OH <=> C2H5 + H2O — neither r nor p reversed."""
1970+
rxn = ARCReaction(r_species=[ARCSpecies(label='C2H6', smiles='CC'),
1971+
ARCSpecies(label='OH', smiles='[OH]')],
1972+
p_species=[ARCSpecies(label='C2H5', smiles='[CH2]C'),
1973+
ARCSpecies(label='H2O', smiles='O')])
1974+
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=False, expected_p_reversed=False)
1975+
1976+
def test_are_h_abs_wells_reversed_r_reversed(self):
1977+
"""OH + C2H6 <=> C2H5 + H2O — reactants reversed."""
1978+
rxn = ARCReaction(r_species=[ARCSpecies(label='OH', smiles='[OH]'),
1979+
ARCSpecies(label='C2H6', smiles='CC')],
1980+
p_species=[ARCSpecies(label='C2H5', smiles='[CH2]C'),
1981+
ARCSpecies(label='H2O', smiles='O')])
1982+
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=True, expected_p_reversed=False)
1983+
1984+
def test_are_h_abs_wells_reversed_p_reversed(self):
1985+
"""C2H6 + OH <=> H2O + C2H5 — products reversed."""
1986+
rxn = ARCReaction(r_species=[ARCSpecies(label='C2H6', smiles='CC'),
1987+
ARCSpecies(label='OH', smiles='[OH]')],
1988+
p_species=[ARCSpecies(label='H2O', smiles='O'),
1989+
ARCSpecies(label='C2H5', smiles='[CH2]C')])
1990+
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=False, expected_p_reversed=True)
1991+
1992+
def test_are_h_abs_wells_reversed_both_reversed(self):
1993+
"""OH + C2H6 <=> H2O + C2H5 — reactants and products reversed."""
1994+
rxn = ARCReaction(r_species=[ARCSpecies(label='OH', smiles='[OH]'),
1995+
ARCSpecies(label='C2H6', smiles='CC')],
1996+
p_species=[ARCSpecies(label='H2O', smiles='O'),
1997+
ARCSpecies(label='C2H5', smiles='[CH2]C')])
1998+
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=True, expected_p_reversed=True)
1999+
2000+
def test_are_h_abs_wells_reversed_h_plus_h2o(self):
2001+
"""H + H2O <=> H2 + OH — reactants and products reversed."""
2002+
rxn = ARCReaction(r_species=[ARCSpecies(label='H', smiles='[H]'),
2003+
ARCSpecies(label='H2O', smiles='O')],
2004+
p_species=[ARCSpecies(label='H2', smiles='[H][H]'),
2005+
ARCSpecies(label='OH', smiles='[OH]')])
2006+
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=True, expected_p_reversed=True)
2007+
2008+
def test_are_h_abs_wells_reversed_butyrate(self):
2009+
"""CCCC(O)=O + OH <=> CCCC([O])=O + H2O — neither r nor p reversed."""
2010+
rxn = ARCReaction(r_species=[ARCSpecies(label='CCCC(O)=O', smiles='CCCC(O)=O'),
2011+
ARCSpecies(label='OH', smiles='[OH]')],
2012+
p_species=[ARCSpecies(label='CCCC([O])=O', smiles='CCCC([O])=O'),
2013+
ARCSpecies(label='H2O', smiles='O')])
2014+
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=False, expected_p_reversed=False)
20452015

20462016
def test_process_hydrolysis_reaction(self):
20472017
"""Test the process_hydrolysis_reaction() function."""
@@ -2254,8 +2224,8 @@ def tearDownClass(cls):
22542224
A function that is run ONCE after all unit tests in this class.
22552225
Delete all project directories created during these unit tests.
22562226
"""
2257-
shutil.rmtree(os.path.join(ARC_TESTING_PATH, 'heuristics'), ignore_errors=True)
2258-
shutil.rmtree(os.path.join(ARC_TESTING_PATH, 'heuristics_1'), ignore_errors=True)
2227+
for sub in ('heuristics', 'heuristics_1', 'heuristics_carbonyl', 'heuristics_ether', 'heuristics_nitrile'):
2228+
shutil.rmtree(os.path.join(ARC_TESTING_PATH, sub), ignore_errors=True)
22592229

22602230

22612231
if __name__ == '__main__':

0 commit comments

Comments
 (0)