Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
240 changes: 105 additions & 135 deletions arc/job/adapters/ts/heuristics_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1125,63 +1125,58 @@ def test_heuristics_for_h_abstraction_13(self):
heuristics_1.execute_incore()
self.assertEqual(len(rxn1.ts_species.ts_guesses), 12)

def test_heuristics_for_hydrolysis(self):
def test_heuristics_for_carbonyl_based_hydrolysis(self):
"""
Test that ARC can generate TS guesses based on heuristics for different hydrolysis families reactions.
Test heuristics for carbonyl-based hydrolysis: C2H4O2 + H2O <=> CH2O2 + CH4O.
"""
# Carbonyl-based hydrolysis
# C2H4O2 + H2O <=> CH2O2 + CH4O
methylformate = self.methylformate
formicacid = self.formicacid
methanol = self.methanol
water = self.water
rxn1 = ARCReaction(r_species=[methylformate, water], p_species=[formicacid, methanol],
family='carbonyl_based_hydrolysis')
heuristics_1 = HeuristicsAdapter(job_type='tsg',
reactions=[rxn1],
testing=True,
project='test',
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics')
)
heuristics_1.execute_incore()
self.assertEqual(rxn1.family, 'carbonyl_based_hydrolysis')
self.assertTrue(rxn1.ts_species.is_ts)
self.assertEqual(rxn1.ts_species.ts_guesses[0].initial_xyz['symbols'],
rxn = ARCReaction(r_species=[self.methylformate, self.water],
p_species=[self.formicacid, self.methanol],
family='carbonyl_based_hydrolysis')
adapter = HeuristicsAdapter(job_type='tsg',
reactions=[rxn],
testing=True,
project='test',
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics_carbonyl'))
adapter.execute_incore()
self.assertEqual(rxn.family, 'carbonyl_based_hydrolysis')
self.assertTrue(rxn.ts_species.is_ts)
self.assertEqual(rxn.ts_species.ts_guesses[0].initial_xyz['symbols'],
('C', 'O', 'C', 'O', 'H', 'H', 'H', 'H', 'O', 'H', 'H'))
self.assertEqual(len(rxn1.ts_species.ts_guesses), 6)
# Ether hydrolysis
# C3H8O + H2O <=> C2H6O + CH4O
allylmethylether = self.allylmethylether
allylalcohol = self.allylalcohol
methanol = self.methanol
rxn2 = ARCReaction(r_species=[allylmethylether, water], p_species=[allylalcohol, methanol])
heuristics_2 = HeuristicsAdapter(job_type='tsg',
reactions=[rxn2],
testing=True,
project='test',
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics')
)
heuristics_2.execute_incore()
self.assertEqual(rxn2.family, 'ether_hydrolysis')
self.assertTrue(rxn2.ts_species.is_ts)
self.assertEqual(rxn2.ts_species.ts_guesses[0].initial_xyz['symbols'],
self.assertEqual(len(rxn.ts_species.ts_guesses), 6)

def test_heuristics_for_ether_hydrolysis(self):
"""
Test heuristics for ether hydrolysis: C3H8O + H2O <=> C2H6O + CH4O.
"""
rxn = ARCReaction(r_species=[self.allylmethylether, self.water],
p_species=[self.allylalcohol, self.methanol])
adapter = HeuristicsAdapter(job_type='tsg',
reactions=[rxn],
testing=True,
project='test',
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics_ether'))
adapter.execute_incore()
self.assertEqual(rxn.family, 'ether_hydrolysis')
self.assertTrue(rxn.ts_species.is_ts)
self.assertEqual(rxn.ts_species.ts_guesses[0].initial_xyz['symbols'],
('C', 'C', 'C', 'O', 'C', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'O', 'H', 'H'))
self.assertEqual(len(rxn2.ts_species.ts_guesses), 4)
# Nitrile hydrolysis
# N#CC(C#N) + H2O <=> N=C(O)C(C#N)
malononitrile = self.malononitrile
iminopropanoic_acid = self.iminopropanoic_acid
rxn4 = ARCReaction(r_species=[malononitrile, water], p_species=[iminopropanoic_acid])
heuristics_4 = HeuristicsAdapter(job_type='tsg',
reactions=[rxn4],
testing=True,
project='test',
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics')
)
heuristics_4.execute_incore()
self.assertEqual(rxn4.family, 'nitrile_hydrolysis')
self.assertTrue(rxn4.ts_species.is_ts)
self.assertEqual(rxn4.ts_species.ts_guesses[0].initial_xyz['symbols'],
self.assertEqual(len(rxn.ts_species.ts_guesses), 4)

def test_heuristics_for_nitrile_hydrolysis(self):
"""
Test heuristics for nitrile hydrolysis: N#CC(C#N) + H2O <=> N=C(O)C(C#N).
"""
rxn = ARCReaction(r_species=[self.malononitrile, self.water],
p_species=[self.iminopropanoic_acid])
adapter = HeuristicsAdapter(job_type='tsg',
reactions=[rxn],
testing=True,
project='test',
project_directory=os.path.join(ARC_TESTING_PATH, 'heuristics_nitrile'))
adapter.execute_incore()
self.assertEqual(rxn.family, 'nitrile_hydrolysis')
self.assertTrue(rxn.ts_species.is_ts)
self.assertEqual(rxn.ts_species.ts_guesses[0].initial_xyz['symbols'],
('N', 'C', 'C', 'C', 'N', 'H', 'H', 'O', 'H', 'H'))

def test_keeping_atom_order_in_ts(self):
Expand Down Expand Up @@ -1958,90 +1953,65 @@ def test_find_distant_neighbor(self):
self.assertEqual(find_distant_neighbor(mol=mol_3, start=2), 4)
self.assertEqual(find_distant_neighbor(mol=mol_3, start=2), 4)

def test_are_h_abs_wells_reversed(self):
"""
Test the are_h_abs_wells_reversed() function.
The expected order is: R(*1)-H(*2) + R(*3)j <=> R(*1)j + R(*3)-H(*2)
"""
rxn_1 = ARCReaction(r_species=[ARCSpecies(label='C2H6', smiles='CC'), ARCSpecies(label='OH', smiles='[OH]')],
# none are reversed
p_species=[ARCSpecies(label='C2H5', smiles='[CH2]C'), ARCSpecies(label='H2O', smiles='O')])
rxn_2 = ARCReaction(r_species=[ARCSpecies(label='OH', smiles='[OH]'), ARCSpecies(label='C2H6', smiles='CC')],
# r reversed
p_species=[ARCSpecies(label='C2H5', smiles='[CH2]C'), ARCSpecies(label='H2O', smiles='O')])
rxn_3 = ARCReaction(r_species=[ARCSpecies(label='C2H6', smiles='CC'), ARCSpecies(label='OH', smiles='[OH]')],
# p reversed
p_species=[ARCSpecies(label='H2O', smiles='O'), ARCSpecies(label='C2H5', smiles='[CH2]C')])
rxn_4 = ARCReaction(r_species=[ARCSpecies(label='OH', smiles='[OH]'), ARCSpecies(label='C2H6', smiles='CC')],
# r and p reversed
p_species=[ARCSpecies(label='H2O', smiles='O'), ARCSpecies(label='C2H5', smiles='[CH2]C')])

product_dicts = get_reaction_family_products(rxn=rxn_1,
rmg_family_set=[rxn_1.family],
consider_rmg_families=True,
consider_arc_families=False,
discover_own_reverse_rxns_in_reverse=False,
)
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_1, product_dict=product_dicts[0])
self.assertFalse(r_reversed)
self.assertFalse(p_reversed)

product_dicts = get_reaction_family_products(rxn=rxn_2,
rmg_family_set=[rxn_2.family],
consider_rmg_families=True,
consider_arc_families=False,
discover_own_reverse_rxns_in_reverse=False,
)
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_2, product_dict=product_dicts[0])
self.assertTrue(r_reversed)
self.assertFalse(p_reversed)

product_dicts = get_reaction_family_products(rxn=rxn_3,
rmg_family_set=[rxn_3.family],
consider_rmg_families=True,
consider_arc_families=False,
discover_own_reverse_rxns_in_reverse=False,
)
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_3, product_dict=product_dicts[0])
self.assertFalse(r_reversed)
self.assertTrue(p_reversed)

product_dicts = get_reaction_family_products(rxn=rxn_4,
rmg_family_set=[rxn_4.family],
consider_rmg_families=True,
consider_arc_families=False,
discover_own_reverse_rxns_in_reverse=False,
)
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_4, product_dict=product_dicts[0])
self.assertTrue(r_reversed)
self.assertTrue(p_reversed)

rxn_5 = ARCReaction(r_species=[ARCSpecies(label='H', smiles='[H]'), ARCSpecies(label='H2O', smiles='O')],
# r and p reversed
p_species=[ARCSpecies(label='H2', smiles='[H][H]'), ARCSpecies(label='OH', smiles='[OH]')])
product_dicts = get_reaction_family_products(rxn=rxn_5,
rmg_family_set=[rxn_5.family],
consider_rmg_families=True,
consider_arc_families=False,
discover_own_reverse_rxns_in_reverse=False,
)
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_5, product_dict=product_dicts[0])
self.assertTrue(r_reversed)
self.assertTrue(p_reversed)

rxn_6 = ARCReaction(
r_species=[ARCSpecies(label='CCCC(O)=O', smiles='CCCC(O)=O'), ARCSpecies(label='OH', smiles='[OH]')],
# none are reversed
p_species=[ARCSpecies(label='CCCC([O])=O', smiles='CCCC([O])=O'), ARCSpecies(label='H2O', smiles='O')])
product_dicts = get_reaction_family_products(rxn=rxn_6,
rmg_family_set=[rxn_6.family],
def _check_h_abs_wells_reversed(self, rxn: 'ARCReaction', expected_r_reversed: bool, expected_p_reversed: bool):
"""Helper: run are_h_abs_wells_reversed against the family products and assert the orientations."""
product_dicts = get_reaction_family_products(rxn=rxn,
rmg_family_set=[rxn.family],
consider_rmg_families=True,
consider_arc_families=False,
discover_own_reverse_rxns_in_reverse=False,
)
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn_6, product_dict=product_dicts[0])
self.assertFalse(r_reversed)
self.assertFalse(p_reversed)
r_reversed, p_reversed = are_h_abs_wells_reversed(rxn, product_dict=product_dicts[0])
self.assertEqual(r_reversed, expected_r_reversed)
self.assertEqual(p_reversed, expected_p_reversed)

def test_are_h_abs_wells_reversed_neither_reversed(self):
"""C2H6 + OH <=> C2H5 + H2O — neither r nor p reversed."""
rxn = ARCReaction(r_species=[ARCSpecies(label='C2H6', smiles='CC'),
ARCSpecies(label='OH', smiles='[OH]')],
p_species=[ARCSpecies(label='C2H5', smiles='[CH2]C'),
ARCSpecies(label='H2O', smiles='O')])
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=False, expected_p_reversed=False)

def test_are_h_abs_wells_reversed_r_reversed(self):
"""OH + C2H6 <=> C2H5 + H2O — reactants reversed."""
rxn = ARCReaction(r_species=[ARCSpecies(label='OH', smiles='[OH]'),
ARCSpecies(label='C2H6', smiles='CC')],
p_species=[ARCSpecies(label='C2H5', smiles='[CH2]C'),
ARCSpecies(label='H2O', smiles='O')])
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=True, expected_p_reversed=False)

def test_are_h_abs_wells_reversed_p_reversed(self):
"""C2H6 + OH <=> H2O + C2H5 — products reversed."""
rxn = ARCReaction(r_species=[ARCSpecies(label='C2H6', smiles='CC'),
ARCSpecies(label='OH', smiles='[OH]')],
p_species=[ARCSpecies(label='H2O', smiles='O'),
ARCSpecies(label='C2H5', smiles='[CH2]C')])
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=False, expected_p_reversed=True)

def test_are_h_abs_wells_reversed_both_reversed(self):
"""OH + C2H6 <=> H2O + C2H5 — reactants and products reversed."""
rxn = ARCReaction(r_species=[ARCSpecies(label='OH', smiles='[OH]'),
ARCSpecies(label='C2H6', smiles='CC')],
p_species=[ARCSpecies(label='H2O', smiles='O'),
ARCSpecies(label='C2H5', smiles='[CH2]C')])
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=True, expected_p_reversed=True)

def test_are_h_abs_wells_reversed_h_plus_h2o(self):
"""H + H2O <=> H2 + OH — reactants and products reversed."""
rxn = ARCReaction(r_species=[ARCSpecies(label='H', smiles='[H]'),
ARCSpecies(label='H2O', smiles='O')],
p_species=[ARCSpecies(label='H2', smiles='[H][H]'),
ARCSpecies(label='OH', smiles='[OH]')])
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=True, expected_p_reversed=True)

def test_are_h_abs_wells_reversed_butyrate(self):
"""CCCC(O)=O + OH <=> CCCC([O])=O + H2O — neither r nor p reversed."""
rxn = ARCReaction(r_species=[ARCSpecies(label='CCCC(O)=O', smiles='CCCC(O)=O'),
ARCSpecies(label='OH', smiles='[OH]')],
p_species=[ARCSpecies(label='CCCC([O])=O', smiles='CCCC([O])=O'),
ARCSpecies(label='H2O', smiles='O')])
self._check_h_abs_wells_reversed(rxn, expected_r_reversed=False, expected_p_reversed=False)

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


if __name__ == '__main__':
Expand Down
Loading
Loading