Skip to content

Commit

Permalink
Merge pull request #448 from ReactionMechanismGenerator/minor
Browse files Browse the repository at this point in the history
Minor modifications
  • Loading branch information
kfir4444 committed Mar 9, 2021
2 parents 79563b1 + 01892d0 commit 60eb6eb
Show file tree
Hide file tree
Showing 23 changed files with 186 additions and 150 deletions.
6 changes: 3 additions & 3 deletions arc/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,8 +734,8 @@ def key_by_val(dictionary: dict,
raise ValueError(f'Could not find value {value} in the dictionary\n{dictionary}')


def almost_equal_lists(iter1: list or tuple or np.ndarray,
iter2: list or tuple or np.ndarray,
def almost_equal_lists(iter1: Union[list, tuple, np.ndarray],
iter2: Union[list, tuple, np.ndarray],
rtol: float = 1e-05,
atol: float = 1e-08,
) -> bool:
Expand Down Expand Up @@ -958,7 +958,7 @@ def check_torsion_change(torsions: pd.DataFrame,
differences are equal to the scan resolution.
Returns: pd.DataFrame
a DataFrame consisting of ``True``/``False``, indicating
A DataFrame consisting of ``True``/``False``, indicating
which torsions changed significantly. ``True`` for significant change.
"""
# First iteration without 180/-180 adjustment
Expand Down
2 changes: 1 addition & 1 deletion arc/job/jobTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ def tearDownClass(cls):
for project in projects:
project_directory = os.path.join(arc_path, 'Projects', project)
if os.path.isdir(project_directory):
shutil.rmtree(project_directory)
shutil.rmtree(project_directory, ignore_errors=True)


if __name__ == '__main__':
Expand Down
4 changes: 2 additions & 2 deletions arc/job/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ def execute_command(command, shell=True, no_fail=False):
return False
else:
_output_command_error_message(command, e, logger.error)
logger.error(f'ARC is sleeping for {sleep_time * i} seconds before re-trying,'
f' please check if this is a server issue by executing the command manually on server.')
logger.error(f'ARC is sleeping for {sleep_time * i} seconds before retrying.\nPlease check whether '
f'this is a server issue by executing the command manually on the server.')
logger.info('ZZZZZ..... ZZZZZ.....')
time.sleep(sleep_time * i) # in seconds
i += 1
Expand Down
2 changes: 1 addition & 1 deletion arc/job/localTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def test_rename_output(self):
local.rename_output(local_file_path=path2, software='gaussian')
self.assertFalse(os.path.isfile(path1))
self.assertTrue(os.path.isfile(path2))
shutil.rmtree(os.path.join(arc_path, 'scratch'))
shutil.rmtree(os.path.join(arc_path, 'scratch'), ignore_errors=True)


if __name__ == '__main__':
Expand Down
2 changes: 1 addition & 1 deletion arc/level.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def as_dict(self) -> dict:
original_dict = self.__dict__
clean_dict = {}
for key, val in original_dict.items():
if val is not None and key != 'args' or key =='args' and all([v for v in self.args.values()]):
if val is not None and key != 'args' or key == 'args' and all([v for v in self.args.values()]):
clean_dict[key] = val
return clean_dict

Expand Down
30 changes: 13 additions & 17 deletions arc/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,9 @@
from arc.species.species import ARCSpecies
from arc.utils.scale import determine_scaling_factors

try:
from arc.settings import default_job_settings, global_ess_settings
except ImportError:
default_job_settings, global_ess_settings = dict(), None


logger = get_logger()


default_levels_of_theory, servers, valid_chars, default_job_types, default_job_settings, global_ess_settings = \
settings['default_levels_of_theory'], settings['servers'], settings['valid_chars'], settings['default_job_types'], \
settings['default_job_settings'], settings['global_ess_settings']
Expand Down Expand Up @@ -243,11 +237,11 @@ def __init__(self,
output: Optional[dict] = None,
project: Optional[str] = None,
project_directory: Optional[str] = None,
reactions: Optional[List[ARCReaction]] = None,
reactions: Optional[List[Union[ARCReaction, Reaction]]] = None,
running_jobs: Optional[dict] = None,
scan_level: Optional[Union[str, dict, Level]] = None,
sp_level: Optional[Union[str, dict, Level]] = None,
species: Optional[List[ARCSpecies]] = None,
species: Optional[List[Union[ARCSpecies, Species]]] = None,
specific_job_type: str = '',
T_min: Optional[Tuple[float, str]] = None,
T_max: Optional[Tuple[float, str]] = None,
Expand Down Expand Up @@ -380,7 +374,7 @@ def __init__(self,
self.species.append(ARCSpecies(is_ts=False, rmg_species=spc))
self.unique_species_labels.append(spc.label)
elif isinstance(rxn, dict):
# dict representation for ARCReaction
# dict representation for ARCReaction as in a YAML input file
indices_to_pop.append(i)
converted_reactions.append(ARCReaction(reaction_dict=rxn))
elif not isinstance(rxn, ARCReaction):
Expand Down Expand Up @@ -519,8 +513,8 @@ def execute(self) -> dict:
"""
Execute ARC.
Returns:
dict: Status dictionary indicating which species converged successfully.
Returns: dict
Status dictionary indicating which species converged successfully.
"""
logger.info('\n')
for species in self.species:
Expand Down Expand Up @@ -650,8 +644,8 @@ def summary(self) -> dict:
"""
Report status and data of all species / reactions.
Returns:
dict: Status dictionary indicating which species converged successfully.
Returns: dict
Status dictionary indicating which species converged successfully.
"""
status_dict = {}
logger.info(f'\n\n\nAll jobs terminated. Summary for project {self.project}:\n')
Expand Down Expand Up @@ -932,7 +926,8 @@ def set_levels_of_theory(self):
else:
logger.warning("Not performing rotor scans, since it was not requested by the user. This might "
"compromise finding the best conformer, as dihedral angles won't be corrected. "
"Also, the calculated entropy and heat capacity won't be accurate.")
"Also, the calculated thermodynamic properties and rate coefficients "
"will be less accurate.")

if self.job_types['irc']:
if not self.irc_level:
Expand Down Expand Up @@ -1006,7 +1001,8 @@ def set_levels_of_theory(self):
else:
logger.warning("Not performing rotor scans, since it was not requested by the user. This might "
"compromise finding the best conformer, as dihedral angles won't be corrected. "
"Also, the calculated entropy and heat capacity won't be accurate.")
"Also, the calculated thermodynamic properties and rate coefficients "
"will be less accurate.")

if self.job_types['irc']:
if not self.irc_level:
Expand Down Expand Up @@ -1131,8 +1127,8 @@ def process_adaptive_levels(adaptive_levels: Optional[dict]) -> Optional[dict]:
Args:
adaptive_levels (dict): The adaptive levels dictionary.
Returns:
dict: The processed adaptive levels dictionary.
Returns: dict
The processed adaptive levels dictionary.
"""
if adaptive_levels is None:
return None
Expand Down
4 changes: 2 additions & 2 deletions arc/mainTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_as_dict(self):
'software': 'gaussian'},
'e_confs': 5.0,
'ess_settings': {'gaussian': ['local', 'server2'],
'molpro': ['server2'],
'molpro': ['local', 'server2'],
'onedmin': ['server1'],
'orca': ['local'],
'qchem': ['server1'],
Expand Down Expand Up @@ -428,7 +428,7 @@ def tearDownClass(cls):
'arc_model_chemistry_test', 'arc_test', 'test', 'unit_test_specific_job', 'wrong']
for project in projects:
project_directory = os.path.join(arc_path, 'Projects', project)
shutil.rmtree(project_directory)
shutil.rmtree(project_directory, ignore_errors=True)


if __name__ == '__main__':
Expand Down
2 changes: 1 addition & 1 deletion arc/plotterTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def tearDownClass(cls):
"""A function that is run ONCE after all unit tests in this class."""
project = 'arc_project_for_testing_delete_after_usage'
project_directory = os.path.join(arc_path, 'Projects', project)
shutil.rmtree(project_directory)
shutil.rmtree(project_directory, ignore_errors=True)
os.remove(os.path.join(arc_path, 'arc', 'testing', 'bde_report_test.txt'))


Expand Down
22 changes: 11 additions & 11 deletions arc/reaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,43 +491,43 @@ def check_attributes(self):
for reactant in reactants:
if reactant not in self.reactants:
raise ReactionError(f'Reactant {reactant} from the reaction label {self.label} '
f'not in self.reactants ({self.reactants})')
f'is not in self.reactants ({self.reactants})')
for reactant in self.reactants:
if reactant not in reactants:
raise ReactionError(f'Reactant {reactant} not in the reaction label ({self.label})')
raise ReactionError(f'Reactant {reactant} is not in the reaction label ({self.label})')
if self.products is not None:
for product in products:
if product not in self.products:
raise ReactionError(f'Product {product} from the reaction label {self.label} '
f'not in self.products ({self.products})')
raise ReactionError(f'Product {product} from the reaction {self.label} '
f'is not in self.products ({self.products})')
for product in self.products:
if product not in products:
raise ReactionError(f'Product {product} not in the reaction label ({self.label})')
raise ReactionError(f'Product {product} is not in the reaction label ({self.label})')
if self.r_species is not None:
for reactant in self.r_species:
if reactant.label not in self.reactants:
raise ReactionError(f'Reactant {reactant.label} from {self.label} '
f'not in self.reactants ({self.reactants})')
f'is not in self.reactants ({self.reactants})')
for reactant in reactants:
if reactant not in [r.label for r in self.r_species]:
raise ReactionError(f'Reactant {reactant} from the reaction label {self.label} '
f'not in self.r_species ({[r.label for r in self.r_species]})')
f'is not in self.r_species ({[r.label for r in self.r_species]})')
for reactant in self.reactants:
if reactant not in [r.label for r in self.r_species]:
raise ReactionError(f'Reactant {reactant} not in '
raise ReactionError(f'Reactant {reactant} is not in '
f'self.r_species ({[r.label for r in self.r_species]})')
if self.p_species is not None:
for product in self.p_species:
if product.label not in self.products:
raise ReactionError(f'Product {product.label} from {self.label} '
f'not in self.products ({self.reactants})')
f'is not in self.products ({self.reactants})')
for product in products:
if product not in [p.label for p in self.p_species]:
raise ReactionError(f'Product {product} from the reaction label {self.label} '
f'not in self.p_species ({[p.label for p in self.p_species]})')
f'is not in self.p_species ({[p.label for p in self.p_species]})')
for product in self.products:
if product not in [p.label for p in self.p_species]:
raise ReactionError(f'Product {product} not in '
raise ReactionError(f'Product {product} is not in '
f'self.p_species ({[p.label for p in self.p_species]})')

def check_atom_balance(self,
Expand Down
2 changes: 1 addition & 1 deletion arc/restartTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def tearDownClass(cls):
]
for project in projects:
project_directory = os.path.join(arc_path, 'Projects', project)
shutil.rmtree(project_directory)
shutil.rmtree(project_directory, ignore_errors=True)

for file_name in ['arc.log', 'restart_paths_globalized.yml']:
os.remove(os.path.join(arc_path, 'arc', 'testing', 'restart', '4_globalized_paths', file_name))
Expand Down
64 changes: 43 additions & 21 deletions arc/rmgdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

import os
from typing import TYPE_CHECKING, List, Optional, Tuple, Union

from rmgpy import settings as rmg_settings
from rmgpy.data.kinetics.common import find_degenerate_reactions
Expand All @@ -13,13 +14,16 @@
from arc.common import get_logger
from arc.exceptions import InputError

if TYPE_CHECKING:
from rmgpy.data.kinetics.family import KineticsFamily


logger = get_logger()

db_path = rmg_settings['database.directory']


def make_rmg_database_object():
def make_rmg_database_object() -> RMGDatabase:
"""
Make a clean RMGDatabase object.
Expand All @@ -30,18 +34,19 @@ def make_rmg_database_object():
return rmgdb


def load_families_only(rmgdb, kinetics_families='default'):
def load_families_only(rmgdb: RMGDatabase,
kinetics_families: Union[str, list] = 'default'):
"""
A helper function for loading kinetic families from RMG's database.
Args:
rmgdb (RMGDatabase): The RMG database instance.
kinetics_families (str, optional): Specific kinetics families to load.
kinetics_families (str, list, optional): Specific kinetics families to load.
"""
if kinetics_families not in ('default', 'all', 'none'):
if not isinstance(kinetics_families, list):
raise InputError("kinetics families should be either 'default', 'all', 'none', or a list of names, e.g.,"
" ['H_Abstraction','R_Recombination'] or ['!Intra_Disproportionation'].")
if kinetics_families not in ('default', 'all', 'none') and not isinstance(kinetics_families, list):
raise InputError(f"kinetics families should be either 'default', 'all', 'none', or a list of names, e.g.,"
f" ['H_Abstraction','R_Recombination'] or ['!Intra_Disproportionation']. "
f"Got:\n{kinetics_families}")
logger.debug('\n\nLoading only kinetic families from the RMG database...')
rmgdb.load(
path=db_path,
Expand All @@ -55,8 +60,14 @@ def load_families_only(rmgdb, kinetics_families='default'):
)


def load_rmg_database(rmgdb, thermo_libraries=None, reaction_libraries=None, kinetics_families='default',
load_thermo_libs=True, load_kinetic_libs=True, include_nist=False):
def load_rmg_database(rmgdb: RMGDatabase,
thermo_libraries: list = None,
reaction_libraries: list = None,
kinetics_families: Union[str, list] = 'default',
load_thermo_libs: bool = True,
load_kinetic_libs: bool = True,
include_nist: bool = False,
) -> None:
"""
A helper function for loading the RMG database.
Expand Down Expand Up @@ -150,7 +161,9 @@ def load_rmg_database(rmgdb, thermo_libraries=None, reaction_libraries=None, kin
logger.info('\n\n')


def determine_reaction_family(rmgdb, reaction):
def determine_reaction_family(rmgdb: RMGDatabase,
reaction:Reaction,
) -> Tuple[Optional['KineticsFamily'], bool]:
"""
Determine the RMG kinetic family for a given ARCReaction object.
Returns None if no family found or more than one family found.
Expand All @@ -159,9 +172,9 @@ def determine_reaction_family(rmgdb, reaction):
rmgdb (RMGDatabase): The RMG database instance.
reaction (Reaction): The RMG Reaction object.
Returns: Tuple[str, bool]
- The corresponding RMG reaction's family. None if no family was found or more than one family were found.
- Whether the family is its own reverse.
Returns: Tuple[Optional[KineticsFamily], bool]
- The corresponding RMG reaction's family. ``None`` if no family was found or more than one family were found.
- Whether the family is its own reverse. ``True`` if it is.
"""
fam_list = loop_families(rmgdb=rmgdb, reaction=reaction)
families = [fam_l[0] for fam_l in fam_list]
Expand All @@ -171,7 +184,9 @@ def determine_reaction_family(rmgdb, reaction):
return None, False


def loop_families(rmgdb, reaction):
def loop_families(rmgdb: RMGDatabase,
reaction: Reaction,
) -> List['KineticsFamily']:
"""
Loop through kinetic families and return a list of tuples of (family, degenerate_reactions)
`reaction` is an RMG Reaction object.
Expand All @@ -181,8 +196,8 @@ def loop_families(rmgdb, reaction):
rmgdb (RMGDatabase): The RMG database instance.
reaction (Reaction): The RMG Reaction object.
Returns: list
Entries are corresponding RMG reaction families.
Returns: List[KineticsFamily]
Entries are corresponding RMG KineticsFamily instances.
"""
reaction = reaction.copy() # use a copy to avoid changing atom order in the molecules by RMG
fam_list = list()
Expand Down Expand Up @@ -245,14 +260,21 @@ def loop_families(rmgdb, reaction):
return fam_list


def determine_rmg_kinetics(rmgdb, reaction, dh_rxn298):
def determine_rmg_kinetics(rmgdb: RMGDatabase,
reaction: Reaction,
dh_rxn298: float,
) -> List[Reaction]:
"""
Determine kinetics for `reaction` (an RMG Reaction object) from RMG's database, if possible.
Assigns a list of all matching entries from both libraries and families.
Returns a list of all matching RMG reactions (both libraries and families) with a populated .kinetics attribute
`rmgdb` is the RMG database instance
`reaction` is an RMG Reaction object
`dh_rxn298` is the heat of reaction at 298 K in J / mol
Args:
rmgdb (RMGDatabase): The RMG database instance.
reaction (Reaction): The RMG Reaction object.
dh_rxn298 (float): The heat of reaction at 298 K in J/mol.
Returns: List[Reaction]
All matching RMG reactions (both libraries and families) with a populated ``.kinetics`` attribute.
"""
reaction = reaction.copy() # use a copy to avoid changing atom order in the molecules by RMG
rmg_reactions = list()
Expand Down

0 comments on commit 60eb6eb

Please sign in to comment.