Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a module for working with RMG reaction families #754

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f79d7fe
Minor: CI style modifications
alongd Jun 29, 2024
86456a5
Removed RMG-Py and RMG-database repo paths from common
alongd Jul 1, 2024
2cd8712
Relocated reaction into a sub module
alongd Jun 29, 2024
e2e1f05
Added RMG_DB_PATH to settings
alongd Jul 2, 2024
2203c75
Added clean_text() to common
alongd Jun 29, 2024
81703dc
Tests: common.clean_text()
alongd Jun 29, 2024
2df0a90
Added hydrolysis as an ARC reaction family
alongd Jul 2, 2024
07f068b
Added the reaction family module
alongd Jul 2, 2024
0181c57
Tests: Added reaction family tests
alongd Jul 2, 2024
c19e0bf
Removed rmgdb from reaction
alongd Jul 2, 2024
bafa5fb
Tests: Adaptations to reaction tests
alongd Jul 2, 2024
99db4b2
Corrected import in arkane test
alongd Jul 2, 2024
756d5a0
Don't consider additional TS conformers if there's just one
alongd Jul 3, 2024
1df3a5b
Removed the determine_family() function from the rmgdb module
alongd Jul 3, 2024
02fdea5
Don't use RMGDatabase to determine reaction family
alongd Jul 3, 2024
ec01997
Tests: Removed RMGDatabase from tests
alongd Jul 3, 2024
d4ee5ba
Modifications to how reaction family is used in ARC
alongd Jul 3, 2024
a13f1a6
Make family a property of reaction
alongd Jul 3, 2024
88f607a
Tests: Adaptations to ARC tests
alongd Jul 3, 2024
f36f76c
f! fam
alongd Jul 3, 2024
87ef2b5
f! fam test
alongd Jul 5, 2024
55abaa4
fam
alongd Jul 6, 2024
2df5d92
f! tst
alongd Jul 6, 2024
e7e3466
f tst
alongd Jul 7, 2024
2974141
f fam
alongd Jul 7, 2024
a01bd4a
TMP
alongd Jul 11, 2024
e6bd6af
Removed hard-coded no-mol-perception for triplet O2/S2
alongd Jul 29, 2024
9974059
Tests: Perceive triplet O2 properly
alongd Jul 29, 2024
6f7392e
f! fam resonance
alongd Jul 29, 2024
12d0085
f! fam tests
alongd Jul 29, 2024
ca05315
TMP
alongd Aug 8, 2024
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
3 changes: 2 additions & 1 deletion .github/workflows/cont_int.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ on:
schedule:
- cron: '0 0 * * *'


jobs:
build:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -60,6 +59,7 @@ jobs:
key: ${{ runner.os }}-rmgdb-main
restore-keys: |
${{ runner.os }}-rmgdb-

- name: Checkout RMG-database
if: steps.cache-rmg-db.outputs.cache-hit != 'true'
uses: actions/checkout@v3
Expand Down Expand Up @@ -129,6 +129,7 @@ jobs:
path: ~/conda_pkgs_dir
key:
${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('environment.yml') }}

- name: Setup ARC Env
uses: conda-incubator/setup-miniconda@v2
with:
Expand Down
2 changes: 1 addition & 1 deletion arc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import arc.processor
import arc.scheduler
import arc.utils

import arc.job
import arc.reaction
import arc.settings
import arc.species
import arc.statmech
17 changes: 4 additions & 13 deletions arc/checks/ts.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import numpy as np
from typing import TYPE_CHECKING, List, Optional, Tuple, Union

import arc.rmgdb as rmgdb
from arc import parser
from arc.common import (ARC_PATH,
convert_list_index_0_to_1,
Expand All @@ -20,9 +19,7 @@
)
from arc.imports import settings
from arc.species.converter import check_xyz_dict, displace_xyz, xyz_to_dmat
from arc.mapping.engine import (get_atom_indices_of_labeled_atoms_in_an_rmg_reaction,
get_rmg_reactions_from_arc_reaction,
)
from arc.mapping.engine import get_atom_indices_of_labeled_atoms_in_a_reaction
from arc.statmech.factory import statmech_factory

if TYPE_CHECKING:
Expand Down Expand Up @@ -302,8 +299,6 @@ def check_normal_mode_displacement(reaction: 'ARCReaction',
"""
if job is None:
return
if reaction.family is None:
rmgdb.determine_family(reaction)
amplitudes = amplitudes or [0.1, 0.2, 0.4, 0.6, 0.8, 1]
amplitudes = [amplitudes] if isinstance(amplitudes, float) else amplitudes
reaction.ts_species.ts_checks['NMD'] = False
Expand Down Expand Up @@ -333,8 +328,7 @@ def check_normal_mode_displacement(reaction: 'ARCReaction',
bond_lone_hydrogens=bond_lone_hs)
got_expected_changing_bonds = False
for i, rmg_reaction in enumerate(rmg_reactions):
r_label_dict = get_atom_indices_of_labeled_atoms_in_an_rmg_reaction(arc_reaction=reaction,
rmg_reaction=rmg_reaction)[0]
r_label_dict = get_atom_indices_of_labeled_atoms_in_a_reaction(arc_reaction=reaction)[0]
if r_label_dict is None:
continue
expected_breaking_bonds, expected_forming_bonds = reaction.get_expected_changing_bonds(r_label_dict=r_label_dict)
Expand Down Expand Up @@ -539,14 +533,11 @@ def get_rxn_normal_mode_disp_atom_number(rxn_family: Optional[str] = None,
if rms_list is not None \
and (not isinstance(rms_list, list) or not all(isinstance(entry, float) for entry in rms_list)):
raise TypeError(f'rms_list must be a non empty list, got {rms_list} of type {type(rms_list)}.')
family = rxn_family
if family is None and reaction is not None and reaction.family is not None:
family = reaction.family.label
if family is None:
if reaction.family is None:
logger.warning(f'Cannot deduce a reaction family for {reaction}, assuming {default} atoms in the reaction zone.')
return default
content = read_yaml_file(os.path.join(ARC_PATH, 'data', 'rxn_normal_mode_disp.yml'))
number_by_family = content.get(rxn_family, default)
number_by_family = content.get(rxn_family or reaction.family, default)
if rms_list is None or not len(rms_list):
return number_by_family
entry = None
Expand Down
13 changes: 0 additions & 13 deletions arc/checks/ts_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from arc.level import Level
from arc.parser import parse_normal_mode_displacement, parse_xyz_from_file
from arc.reaction import ARCReaction
from arc.rmgdb import load_families_only, make_rmg_database_object
from arc.species.species import ARCSpecies, TSGuess
from arc.utils.wip import work_in_progress

Expand All @@ -32,8 +31,6 @@ def setUpClass(cls):
A method that is run before all unit tests in this class.
"""
cls.maxDiff = None
cls.rmgdb = make_rmg_database_object()
load_families_only(cls.rmgdb)

cls.rms_list_1 = [0.01414213562373095, 0.05, 0.04, 0.5632938842203065, 0.7993122043357026, 0.08944271909999159,
0.10677078252031312, 0.09000000000000001, 0.05, 0.09433981132056604]
Expand Down Expand Up @@ -185,15 +182,6 @@ def setUpClass(cls):
xyz=os.path.join(ts.ARC_PATH, 'arc', 'testing', 'freq', 'TS_nC3H7-iC3H7.out'))
cls.rxn_8.ts_label = cls.rxn_8.ts_species.label

cls.rxn_2a.determine_family(rmg_database=cls.rmgdb, save_order=True)
cls.rxn_2b.determine_family(rmg_database=cls.rmgdb, save_order=True)
cls.rxn_3.determine_family(rmg_database=cls.rmgdb, save_order=True)
cls.rxn_4.determine_family(rmg_database=cls.rmgdb, save_order=True)
cls.rxn_5.determine_family(rmg_database=cls.rmgdb, save_order=True)
cls.rxn_6.determine_family(rmg_database=cls.rmgdb, save_order=True)
cls.rxn_7.determine_family(rmg_database=cls.rmgdb, save_order=True)
cls.rxn_8.determine_family(rmg_database=cls.rmgdb, save_order=True)

cls.ccooj_xyz = {'symbols': ('C', 'C', 'O', 'O', 'H', 'H', 'H', 'H', 'H'),
'isotopes': (12, 12, 16, 16, 1, 1, 1, 1, 1),
'coords': ((-1.0558210286905791, -0.033295741345331475, -0.10080257427276477),
Expand Down Expand Up @@ -380,7 +368,6 @@ def test_check_normal_mode_displacement(self):
self.assertFalse(self.rxn_2a.ts_species.ts_checks['NMD'])
self.job1.local_path_to_output_file = os.path.join(ts.ARC_PATH, 'arc', 'testing', 'composite',
'TS_intra_H_migration_CBS-QB3.out')
self.rxn_2a.determine_family(rmg_database=self.rmgdb)
ts.check_normal_mode_displacement(reaction=self.rxn_2a, job=self.job1)
self.assertTrue(self.rxn_2a.ts_species.ts_checks['NMD'])
self.rxn_2a.ts_species.populate_ts_checks()
Expand Down
24 changes: 19 additions & 5 deletions arc/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@

# Absolute path to the ARC folder.
ARC_PATH = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
# Absolute path to RMG-Py folder.
RMG_PATH = os.path.abspath(os.path.dirname(os.path.dirname(rmgpy.__file__)))
# Absolute path to RMG-database folder.
RMG_DATABASE_PATH = os.path.abspath(os.path.dirname(rmgpy.settings['database.directory']))

VERSION = '1.1.0'

Expand Down Expand Up @@ -278,7 +274,7 @@ def log_header(project: str,
logger.log(level, '###############################################################')
logger.log(level, '')

paths_dict = {'ARC': ARC_PATH, 'RMG-Py': RMG_PATH, 'RMG-database': RMG_DATABASE_PATH}
paths_dict = {'ARC': ARC_PATH}
for repo, path in paths_dict.items():
# Extract HEAD git commit.
head, date = get_git_commit(path)
Expand Down Expand Up @@ -1064,6 +1060,24 @@ def is_str_int(value: Optional[str]) -> bool:
return False


def clean_text(text: str) -> str:
"""
Clean a text string from leading and trailing whitespaces, newline characters, and double quotes.

Args:
text (str): The text to clean.

Returns:
str: The cleaned text.
"""
text = text.strip()
text = text.lstrip('\n').rstrip('\n')
text = text.replace('"', '')
text = text.rstrip(',')
text = text.lstrip('\n').rstrip('\n')
return text


def time_lapse(t0) -> str:
"""
A helper function returning the elapsed time since t0.
Expand Down
18 changes: 14 additions & 4 deletions arc/common_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import arc.common as common
from arc.exceptions import InputError, SettingsError
from arc.imports import settings
from arc.rmgdb import make_rmg_database_object, load_families_only
from arc.mapping.engine import get_rmg_reactions_from_arc_reaction
import arc.species.converter as converter
from arc.reaction import ARCReaction
Expand All @@ -41,8 +40,6 @@ def setUpClass(cls):
A method that is run before all unit tests in this class.
"""
cls.maxDiff = None
cls.rmgdb = make_rmg_database_object()
load_families_only(cls.rmgdb)
cls.default_job_types = {'conformers': True,
'opt': True,
'fine': True,
Expand Down Expand Up @@ -587,6 +584,19 @@ def test_is_str_int(self):
self.assertFalse(common.is_str_int('125.84'))
self.assertFalse(common.is_str_int('0.0'))

def test_clean_text(self):
"""Test the clean_text() function"""
self.assertEqual(common.clean_text('R1'), 'R1')
self.assertEqual(common.clean_text(' D_3_5_7_4"\n'), 'D_3_5_7_4')
self.assertEqual(common.clean_text('"OR{Cd_Cdd, Cdd_Cd, Cd_Cd, Sd_Cd, N1dc_N5ddc, N3d_Cd}",\n '),
'OR{Cd_Cdd, Cdd_Cd, Cd_Cd, Sd_Cd, N1dc_N5ddc, N3d_Cd}')
self.assertEqual(common.clean_text('\n"""\n1 *1 Cd u0 {2,D} {3,S} {4,S}\n2 *2 Cdd u0 {1,D} {5,D}\n3 H u0 {1,S}\n4 H u0 {1,S}\n5 [O2d,S2d] u0 {2,D}\n""",\n '),
"""1 *1 Cd u0 {2,D} {3,S} {4,S}
2 *2 Cdd u0 {1,D} {5,D}
3 H u0 {1,S}
4 H u0 {1,S}
5 [O2d,S2d] u0 {2,D}""")

def test_get_atom_radius(self):
"""Test determining the covalent radius of an atom"""
self.assertEqual(common.get_atom_radius('C'), 0.76)
Expand Down Expand Up @@ -1261,7 +1271,7 @@ def test_check_r_n_p_symbols_between_rmg_and_arc_rxns(self):
"""Test the _check_r_n_p_symbols_between_rmg_and_arc_rxns() function"""
arc_rxn = ARCReaction(r_species=[ARCSpecies(label='CH4', smiles='C'), ARCSpecies(label='OH', smiles='[OH]')],
p_species=[ARCSpecies(label='CH3', smiles='[CH3]'), ARCSpecies(label='H2O', smiles='O')])
rmg_reactions = get_rmg_reactions_from_arc_reaction(arc_reaction=arc_rxn, db=self.rmgdb)
rmg_reactions = get_rmg_reactions_from_arc_reaction(arc_reaction=arc_rxn)
self.assertTrue(common._check_r_n_p_symbols_between_rmg_and_arc_rxns(arc_rxn, rmg_reactions))

def test_almost_equal_coords(self):
Expand Down
18 changes: 5 additions & 13 deletions arc/job/adapters/ts/autotst_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from arc.common import ARC_PATH
from arc.job.adapters.ts.autotst_ts import AutoTSTAdapter, HAS_AUTOTST
from arc.reaction import ARCReaction
from arc.rmgdb import make_rmg_database_object, load_families_only


class TestAutoTSTAdapter(unittest.TestCase):
Expand All @@ -29,8 +28,6 @@ def setUpClass(cls):
A method that is run before all unit tests in this class.
"""
cls.maxDiff = None
cls.rmgdb = make_rmg_database_object()
load_families_only(cls.rmgdb)

def test_has_autotst(self):
"""Test that AutoTST was successfully imported"""
Expand All @@ -43,8 +40,7 @@ def test_autotst_h_abstraction(self):
Species(label='HO2', smiles='O[O]')],
products=[Species(label='C3H7', smiles='[CH2]CC'),
Species(label='H2O2', smiles='OO')]))
rxn1.determine_family(rmg_database=self.rmgdb)
self.assertEqual(rxn1.family.label, 'H_Abstraction')
self.assertEqual(rxn1.family, 'H_Abstraction')
atst1 = AutoTSTAdapter(job_type='tsg',
reactions=[rxn1],
testing=True,
Expand All @@ -71,8 +67,7 @@ def test_autotst_h_abstraction(self):
Species().from_smiles('[OH]')],
products=[Species().from_smiles('CCC[O]'),
Species().from_smiles('O')]))
rxn2.determine_family(rmg_database=self.rmgdb)
self.assertEqual(rxn2.family.label, 'H_Abstraction')
self.assertEqual(rxn2.family, 'H_Abstraction')
atst2 = AutoTSTAdapter(job_type='tsg',
reactions=[rxn2],
testing=True,
Expand All @@ -93,8 +88,7 @@ def test_autotst_h_abstraction(self):
Species().from_smiles('[H]')],
products=[Species().from_smiles('C=C[O]'),
Species().from_smiles('[H][H]')]))
rxn3.determine_family(rmg_database=self.rmgdb)
self.assertEqual(rxn3.family.label, 'H_Abstraction')
self.assertEqual(rxn3.family, 'H_Abstraction')
atst3 = AutoTSTAdapter(job_type='tsg',
reactions=[rxn3],
testing=True,
Expand All @@ -117,8 +111,7 @@ def test_autotst_intra_h_migration(self):
rxn1 = ARCReaction(reactants=['[CH2]CO'], products=['CC[O]'],
rmg_reaction=Reaction(reactants=[Species().from_smiles('[CH2]CO')],
products=[Species().from_smiles('CC[O]')]))
rxn1.determine_family(rmg_database=self.rmgdb)
self.assertEqual(rxn1.family.label, 'intra_H_migration')
self.assertEqual(rxn1.family, 'intra_H_migration')
atst1 = AutoTSTAdapter(job_type='tsg',
reactions=[rxn1],
testing=True,
Expand Down Expand Up @@ -157,8 +150,7 @@ def test_autotst_r_addition_multiple_bond(self):
rmg_reaction=Reaction(reactants=[Species().from_smiles('C#C'),
Species().from_smiles('[OH]')],
products=[Species().from_smiles('[CH]=CO')]))
rxn1.determine_family(rmg_database=self.rmgdb)
self.assertEqual(rxn1.family.label, 'R_Addition_MultipleBond')
self.assertEqual(rxn1.family, 'R_Addition_MultipleBond')
atst1 = AutoTSTAdapter(job_type='tsg',
reactions=[rxn1],
testing=True,
Expand Down
2 changes: 1 addition & 1 deletion arc/job/adapters/ts/autotst_ts.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def execute_incore(self):

self.reactions = [self.reactions] if not isinstance(self.reactions, list) else self.reactions
for rxn in self.reactions:
if rxn.family.label in self.supported_families:
if rxn.family in self.supported_families:
if rxn.ts_species is None:
# Mainly used for testing, in an ARC run the TS species should already exist.
rxn.ts_species = ARCSpecies(label='TS',
Expand Down
3 changes: 0 additions & 3 deletions arc/job/adapters/ts/gcn_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from arc.common import ARC_PATH
import arc.job.adapters.ts.gcn_ts as ts_gcn
from arc.reaction import ARCReaction
from arc.rmgdb import load_families_only, make_rmg_database_object
from arc.species.converter import str_to_xyz
from arc.species.species import ARCSpecies, TSGuess

Expand All @@ -28,8 +27,6 @@ def setUpClass(cls):
A method that is run before all unit tests in this class.
"""
cls.maxDiff = None
cls.rmgdb = make_rmg_database_object()
load_families_only(cls.rmgdb)
cls.output_dir = os.path.join(ARC_PATH, 'arc', 'testing', 'GCN')
if not os.path.isdir(cls.output_dir):
os.makedirs(cls.output_dir)
Expand Down
13 changes: 6 additions & 7 deletions arc/job/adapters/ts/heuristics.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from arc.job.factory import register_job_adapter
from arc.plotter import save_geo
from arc.species.converter import compare_zmats, relocate_zmat_dummy_atoms_to_the_end, zmat_from_xyz, zmat_to_xyz
from arc.mapping.engine import map_arc_rmg_species, map_two_species
from arc.mapping.engine import map_two_species
from arc.species.species import ARCSpecies, TSGuess, colliding_atoms
from arc.species.zmat import get_parameter_from_atom_indices, remove_1st_atom, up_param

Expand Down Expand Up @@ -239,9 +239,8 @@ def execute_incore(self):

self.reactions = [self.reactions] if not isinstance(self.reactions, list) else self.reactions
for rxn in self.reactions:
family_label = rxn.family.label
if family_label not in supported_families:
logger.warning(f'The heuristics TS search adapter does not support the {family_label} reaction family.')
if rxn.family not in supported_families:
logger.warning(f'The heuristics TS search adapter does not support the {rxn.family} reaction family.')
continue
if any(spc.get_xyz() is None for spc in rxn.r_species + rxn.p_species):
logger.warning(f'The heuristics TS search adapter cannot process a reaction if 3D coordinates of '
Expand Down Expand Up @@ -272,7 +271,7 @@ def execute_incore(self):

xyzs = list()
tsg = None
if family_label == 'H_Abstraction':
if rxn.family == 'H_Abstraction':
# Todo: train guess params
# r1_stretch_, r2_stretch_, a2_ = get_training_params(
# family='H_Abstraction',
Expand Down Expand Up @@ -303,15 +302,15 @@ def execute_incore(self):
t0=tsg.t0,
execution_time=tsg.execution_time,
success=True,
family=family_label,
family=rxn.family,
xyz=xyz,
)
rxn.ts_species.ts_guesses.append(ts_guess)
save_geo(xyz=xyz,
path=self.local_path,
filename=f'Heuristics_{method_index}',
format_='xyz',
comment=f'Heuristics {method_index}, family: {family_label}',
comment=f'Heuristics {method_index}, family: {rxn.family}',
)

if len(self.reactions) < 5:
Expand Down
Loading
Loading