From be64abc783b5997ee7cca80a4097a9e5f2b708d2 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Sat, 27 Jun 2026 14:11:32 -0600 Subject: [PATCH 001/176] Add reaction progression and detector stubs Introduces scaffold code for upcoming reaction workflow features: a new `ReactionProgression` processor module with a configurable `MAX_LOOP` constant and placeholder `reaction_progression` method, plus an `index_based_functional_groups_detector` placeholder in `FunctionalGroupsDetector`. These changes establish integration points without altering current behavior yet. --- AutoREACTER/detectors/functional_groups_detector.py | 5 +++++ .../reaction_processor/reaction_progression.py | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index c9bed736..5aceca44 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -364,6 +364,11 @@ def functional_groups_detector( session.monomer_roles = monomer_roles return None # Return session with updated monomer_roles; visualization handled separately. + def index_based_functional_groups_detector( + self, session: "Session", + ) -> None: + pass + def _functional_groups_detector_for_visualization( self, session: Session diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py new file mode 100644 index 00000000..80422273 --- /dev/null +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -0,0 +1,11 @@ +MAX_LOOP = 5 # Maximum number of iterations for the reaction progression loop. Users should be able to adjust this value based on their specific needs and the complexity of the reactions being analyzed. +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from AutoREACTER.session import Session + + + + +class ReactionProgression: + def reaction_progression(self, session: "Session", max_loop: int = MAX_LOOP) -> None: + pass # Placeholder for the reaction progression logic. This method will be implemented to handle the progression of reactions based on the session data and the specified maximum loop iterations. \ No newline at end of file From 65d16df342a3789e7891719cf15bfd8dd55392d8 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Sun, 28 Jun 2026 12:07:59 -0600 Subject: [PATCH 002/176] Add PoolSpecies model and mol population helper Introduce a new `species_pool.py` module with a `PoolSpecies` dataclass to represent reaction pool entries, including monomer flags, SMILES, RDKit molecule objects, and template atom indices. Add `_populate_mols(pool)` to build RDKit molecules from monomer SMILES and initialize `template_idxes` from atom indices, centralizing species preparation logic for downstream reaction processing. --- .../reaction_processor/species_pool.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 AutoREACTER/reaction_preparation/reaction_processor/species_pool.py diff --git a/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py b/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py new file mode 100644 index 00000000..623be991 --- /dev/null +++ b/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from dataclasses import dataclass, field +from rdkit import Chem +from typing import Optional + +@dataclass(slots=True) +class PoolSpecies: + """ + Represents a species in the reaction pool. + """ + species_id: str + is_monomer: bool + smiles: Optional[str] = None + mol: Optional[Chem.Mol] = None + template_idxes: Optional[list[int]] = None + + +def _populate_mols(pool: list[PoolSpecies]) -> list[PoolSpecies]: + """ + Populate the `mol` attribute of each monomer species in the pool based on its SMILES string. + Args: + pool (list[PoolSpecies]): The list of species in the pool. + + Returns: + list[PoolSpecies]: The updated list of species with populated `mol` attributes. + """ + for species in pool: + if species.smiles and species.mol is None and species.is_monomer: + species.mol = Chem.MolFromSmiles(species.smiles) + atoms = [] + for atom in species.mol.GetAtoms(): + atoms.append(atom.GetIdx()) + species.template_idxes = atoms + + + + return pool From a087fd226c7bd70650f6f38520346eaaa83957bc Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 1 Jul 2026 21:26:40 -0600 Subject: [PATCH 003/176] Document PoolSpecies fields and mol population Expand `PoolSpecies` docstring to list its key attributes, and clarify `_populate_mols` documentation to note that it fills both `mol` and `template_idxes` for monomer species derived from SMILES. --- .../reaction_processor/species_pool.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py b/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py index 623be991..11768f29 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py @@ -8,6 +8,12 @@ class PoolSpecies: """ Represents a species in the reaction pool. + Attributes: + species_id (str): The unique identifier of the species. + is_monomer (bool): Indicates whether the species is a monomer. + smiles (Optional[str]): The SMILES representation of the species. + mol (Optional[Chem.Mol]): The RDKit Mol object of the species. + template_idxes (Optional[list[int]]): The list of atom indices used as a template. """ species_id: str is_monomer: bool @@ -18,12 +24,12 @@ class PoolSpecies: def _populate_mols(pool: list[PoolSpecies]) -> list[PoolSpecies]: """ - Populate the `mol` attribute of each monomer species in the pool based on its SMILES string. + Populate the `mol` and `template_idxes` attributes of each monomer species in the pool based on its SMILES string. Args: pool (list[PoolSpecies]): The list of species in the pool. Returns: - list[PoolSpecies]: The updated list of species with populated `mol` attributes. + list[PoolSpecies]: The updated list of species with populated `mol` and `template_idxes` attributes. """ for species in pool: if species.smiles and species.mol is None and species.is_monomer: @@ -32,7 +38,4 @@ def _populate_mols(pool: list[PoolSpecies]) -> list[PoolSpecies]: for atom in species.mol.GetAtoms(): atoms.append(atom.GetIdx()) species.template_idxes = atoms - - - return pool From 2f6d8423eaf295945cd7a8633b7838b2475265bf Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:01:23 -0400 Subject: [PATCH 004/176] Add index-based functional group detector helper --- .../detectors/functional_groups_detector.py | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index 5aceca44..f738039c 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -1,5 +1,7 @@ from __future__ import annotations from typing import TYPE_CHECKING + +from numpy import indices """ * Monomer Functionality Detection Module -------------------------------------- @@ -364,11 +366,6 @@ def functional_groups_detector( session.monomer_roles = monomer_roles return None # Return session with updated monomer_roles; visualization handled separately. - def index_based_functional_groups_detector( - self, session: "Session", - ) -> None: - pass - def _functional_groups_detector_for_visualization( self, session: Session @@ -406,6 +403,32 @@ def _functional_groups_detector_for_visualization( ) ) return monomer_roles_visualization + + def _detect_functional_groups_by_index(self, mol: Chem.Mol, smarts: str, indices: list[int]) -> bool: + """ + mol: RDKit Mol object + smarts: SMARTS pattern string + indices: iterable of atom indices you care about + + Returns: bool + True if any of the specified indices match the SMARTS pattern, False otherwise + """ + target_indices = set(indices) + results = {} + + patt = Chem.MolFromSmarts(smarts) + if patt is None: + # invalid SMARTS + results["present"] = False + results["error"] = "invalid SMARTS" + return results + + matches = mol.GetSubstructMatches(patt, uniquify=True) # tuple of tuples of atom idx + + # check if ANY match shares AT LEAST ONE atom with your target indices + matching_hits = [m for m in matches if target_indices.intersection(m)] + + return bool(matching_hits) def functional_group_highlighted_molecules_image_grid(self, session: Session) -> Image: """Convert monomer roles with detected functionalities into visualizations. From df45b60c21f3cb5f38df07023a6f30f3c62a1028 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:50:08 -0400 Subject: [PATCH 005/176] Add index-based functional groups detector --- .../detectors/functional_groups_detector.py | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index f738039c..0f6fc57a 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -429,6 +429,97 @@ def _detect_functional_groups_by_index(self, mol: Chem.Mol, smarts: str, indices matching_hits = [m for m in matches if target_indices.intersection(m)] return bool(matching_hits) + + def index_based_functional_groups_detector( + self, session: "Session" + ) -> None: + """ + Detect functional groups across a list of monomers and categorize them into roles. + + Iterates over predefined monomer_types, matches each against the monomer's SMILES, + and collects valid detections. Prints matches for debugging/user feedback. + + Args: + session (Session): Validated Session object containing monomers. + + Returns: + None (results stored in session.monomer_roles for downstream use). + + Notes: + - Matches criteria: 'vinyl'/'mono' (>=1 primary), 'di_identical' (>=2 primary), + 'di_different' (>=1 each pattern). + """ + + monomers = session.inputs.monomers + monomer_roles = [] + + for monomer in monomers: + smiles = monomer.smiles + detected_functionalities = [] + all_matches = [] + + # Check against each predefined functional group type. + for functional_group in self.monomer_types.values(): + ftype = functional_group["functionality_type"] + smarts_1 = functional_group["smarts_1"] + smarts_2 = functional_group.get("smarts_2") + + functionality_count, count_1, count_2, functional_matches = ( + self.detect_monomer_functionality( + monomer.rdkit_mol, + ftype, + smarts_1, + smarts_2, + ) + ) + + # Determine if this functionality matches criteria. + if functionality_count > 0: + all_matches.extend(functional_matches) + + # Log detected functionality for debugging/user feedback. + print(f"{smiles} has functionality: {functional_group['group_name']}") + + if functional_group.get("comments"): + print(f"Note: {smiles} - {functional_group['comments']}") + + detected_functionalities.append( + FunctionalGroupInfo( + functionality_type=ftype, + fg_name=functional_group["group_name"], + fg_smarts_1=smarts_1, + fg_count_1=count_1, + fg_smarts_2=smarts_2, + fg_count_2=count_2, + ) + ) + # Debug print for match details. + # print( + # f"Monomer {monomer.name} (SMILES: {smiles}) matches {ftype} " + # f"with {functional_group['group_name']} (Count 1: {count_1}, Count 2: {count_2})" + # ) + + # Add to roles if any functionalities detected. + if detected_functionalities: + monomer_roles.append( + MonomerRole( + smiles=smiles, + name=monomer.name, + functionalities=tuple(detected_functionalities), + ) + ) + + # Store results in session for potential downstream use. + if not monomer_roles: + raise RuntimeError( + "No functional groups were detected in any input monomer. " + "Either the input molecules are not valid polymerizable monomers, " + "or AutoREACTER does not yet support these monomer types. " + "Please open a feature request or issue if you think support should be added: " + "https://github.com/NanoCIPHER-Lab/AutoREACTER/issues" + ) + session.monomer_roles = monomer_roles + return None # Return session with updated monomer_roles; visualization handled separately. def functional_group_highlighted_molecules_image_grid(self, session: Session) -> Image: """Convert monomer roles with detected functionalities into visualizations. From b537e59cd739188c8addb586504581414e826c22 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:53:36 -0400 Subject: [PATCH 006/176] Add DetectedChemistryFilter to collect chemistries --- .../detected_chemistry_filter.py | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py diff --git a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py new file mode 100644 index 00000000..aaeacdc6 --- /dev/null +++ b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py @@ -0,0 +1,87 @@ +from __future__ import annotations # 1. Must be the first line + +from dataclasses import dataclass +from typing import TYPE_CHECKING, Optional + +if TYPE_CHECKING: + from AutoREACTER.session import Session + + +@dataclass(slots=True) +class DetectedChemistries: + functional_groups: list[str] # Unique functional group SMARTS detected in available reactions + reactions: dict[str, str] # reaction_name -> reaction_smarts + + +class DetectedChemistryFilter: + """ + Collects available detected chemistry from reaction instances. + + This class extracts: + - unique functional group SMARTS used by detected reactions + - unique reaction names and their reaction SMARTS + """ + + def __init__(self, session: Session): + self.reaction_instances = session.reaction_instances or [] + + def _add_to_the_list(self, list_to_add: list[str], item: Optional[str]) -> None: + """ + Adds an item to the list if it is not None and not already present. + """ + if item is not None and item not in list_to_add: + list_to_add.append(item) + + def _add_to_the_dict(self, dict_to_add: dict[str, str], key: str, value: str) -> None: + """ + Adds a key-value pair to the dictionary if the key is not already present. + """ + if key not in dict_to_add: + dict_to_add[key] = value + + def filter(self) -> DetectedChemistries: + """ + Extracts available functional group SMARTS and reaction SMARTS + from detected reaction instances. + + Returns: + DetectedChemistries: Available functional groups and reactions. + """ + available_functional_groups: list[str] = [] + available_reactions: dict[str, str] = {} + + for reaction_instance in self.reaction_instances: + reaction_name = reaction_instance.reaction_name + reaction_smarts = reaction_instance.reaction_smarts + + self._add_to_the_dict( + available_reactions, + reaction_name, + reaction_smarts, + ) + + functional_group_1 = reaction_instance.functional_group_1 + self._add_to_the_list( + available_functional_groups, + functional_group_1.fg_smarts_1, + ) + self._add_to_the_list( + available_functional_groups, + functional_group_1.fg_smarts_2, + ) + + functional_group_2 = reaction_instance.functional_group_2 + if functional_group_2 is not None: + self._add_to_the_list( + available_functional_groups, + functional_group_2.fg_smarts_1, + ) + self._add_to_the_list( + available_functional_groups, + functional_group_2.fg_smarts_2, + ) + + return DetectedChemistries( + functional_groups=available_functional_groups, + reactions=available_reactions, + ) \ No newline at end of file From 986977e05d5f0ea61ecef62c6e01aa01b9f46924 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 6 Jul 2026 15:18:59 -0400 Subject: [PATCH 007/176] Add epoxy/amine reaction rules and progression --- .../detectors/functional_groups_library.py | 8 ++++++++ .../detectors/functional_groups_rules.json | 0 AutoREACTER/detectors/reaction_rules.json | 11 +++++++++++ AutoREACTER/detectors/reactions_library.py | 14 +++++++++++++- .../reaction_processor/reaction_progression.py | 15 ++++++++++++++- 5 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 AutoREACTER/detectors/functional_groups_rules.json create mode 100644 AutoREACTER/detectors/reaction_rules.json diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index 1408d624..09389dd0 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -120,6 +120,14 @@ def __init__(self): "comments": None, }, + + "diepoxy_monomer": { + "functionality_type": "di_identical", + "smarts_1": "[OX2r3:1]1[#6r3][#6r3]1", + "group_name": "di_epoxide", + "comments": None, + } + # ============================================================ # Commented functional groups # ============================================================ diff --git a/AutoREACTER/detectors/functional_groups_rules.json b/AutoREACTER/detectors/functional_groups_rules.json new file mode 100644 index 00000000..e69de29b diff --git a/AutoREACTER/detectors/reaction_rules.json b/AutoREACTER/detectors/reaction_rules.json new file mode 100644 index 00000000..6b694887 --- /dev/null +++ b/AutoREACTER/detectors/reaction_rules.json @@ -0,0 +1,11 @@ +{ + "multi_step_reactions": [ + { + "name": "epoxy_polymerization", + "required_reactions": [ + "first_step_reaction", + "second_step_reaction" + ] + } + ] +} \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py index c4ed8486..7d7b7118 100644 --- a/AutoREACTER/detectors/reactions_library.py +++ b/AutoREACTER/detectors/reactions_library.py @@ -339,6 +339,18 @@ def __init__(self): }, "comments": None }, + "Amine Epoxy Addition First Stage": { + "same_reactants": False, + "reactant_1": "amine", + "reactant_2": "epoxide", + "product": "beta_hydroxy_secondary_amine", + "delete_atom": False, + "reaction": "[NX3;H2,H1:1].[OX2r3:2]1[CX4r3:3][CX4r3:4]1>>[NX3:1]-[CX4:3]-[CX4:4]-[OX2H1:2]", + "reference": { + "reaction_and_mechanism": [] + } + } + } # ============================================================ # Commented reactions @@ -473,4 +485,4 @@ def __init__(self): # "delete_atom": False, # "reaction": "[NX2:3]=[CX2:4]=[OX1,SX1:5].[OX2,SX2;H1;!$([O,S]C=*):6]>>[NX3:3][CX3:4](=[OX1,SX1:5])[OX2,SX2;!$([O,S]C=*):6]" # }, - } \ No newline at end of file + #} \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 80422273..d5301139 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -1,11 +1,24 @@ MAX_LOOP = 5 # Maximum number of iterations for the reaction progression loop. Users should be able to adjust this value based on their specific needs and the complexity of the reactions being analyzed. from typing import TYPE_CHECKING +from dataclasses import dataclass if TYPE_CHECKING: from AutoREACTER.session import Session +from AutoREACTER.reaction_preparation.reaction_processor.detected_chemistry_filter import DetectedChemistryFilter, DetectedChemistries +@dataclass(slots=True) +class ReactionProgressionSession: + """ + Holds the state of the reaction progression process, including detected chemistries and the current iteration count. + """ + iteration: int = 0 # Current iteration count of the reaction progression loop. + detected_chemistries: DetectedChemistries + class ReactionProgression: + + def __init__(self, session: "Session"): + self.detected_chemistry_filter = DetectedChemistryFilter(session) def reaction_progression(self, session: "Session", max_loop: int = MAX_LOOP) -> None: - pass # Placeholder for the reaction progression logic. This method will be implemented to handle the progression of reactions based on the session data and the specified maximum loop iterations. \ No newline at end of file + pass \ No newline at end of file From 2489ddf4143f7034f08351135e7d5e63bb318ea2 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:11:30 -0400 Subject: [PATCH 008/176] Add epoxy-amine FGs, atom indexes, and warning util - Add fg_1_indexes and fg_2_indexes fields to FunctionalGroupInfo for storing matched atom indices - Expand functional group library with epoxy-amine polymerization entries (diepoxy, primary amine, secondary amine) with improved SMARTS and documentation - Update reaction_rules.json with required_fgs field for epoxy_polymerization - Add _add_progessive_chemistries stub in detected_chemistry_filter.py - Add warning_asci.py with ASCII warning banner for reaction progression beta loop --- .../detectors/functional_groups_detector.py | 4 ++ .../detectors/functional_groups_library.py | 64 ++++++++++++++++--- AutoREACTER/detectors/reaction_rules.json | 1 + .../detected_chemistry_filter.py | 14 +++- .../reaction_processor/warning_asci.py | 21 ++++++ 5 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index 0f6fc57a..a5b9dba1 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -129,16 +129,20 @@ class FunctionalGroupInfo: functionality_type (str): Type of functionality (e.g., 'vinyl', 'mono', 'di_identical', 'di_different'). fg_name (str): Name of the functional group (e.g., 'acrylate'). fg_smarts_1 (str): Primary SMARTS pattern for matching. + fg_1_indexes (Optional[Tuple[int, ...]]): Atom indices for matches of fg_smarts_1. fg_count_1 (int): Number of matches for fg_smarts_1. fg_smarts_2 (Optional[str]): Secondary SMARTS pattern (for 'di_different' types). + fg_2_indexes (Optional[Tuple[int, ...]]): Atom indices for matches of fg_smarts_2. fg_count_2 (Optional[int]): Number of matches for fg_smarts_2. """ functionality_type: str fg_name: str fg_smarts_1: str fg_count_1: int + fg_1_indexes: Optional[Tuple[int, ...]] = None fg_smarts_2: Optional[str] = None fg_count_2: Optional[int] = None + fg_2_indexes: Optional[Tuple[int, ...]] = None @dataclass(slots=True, frozen=True) diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index 09389dd0..047d5d24 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -1,12 +1,29 @@ """ -This module defines a library of functional groups relevant to polymer chemistry, -particularly for the detection of monomers in reaction simulations. Each functional group is characterized by -its functionality type (e.g., 'vinyl', 'mono', 'di_different', 'di_identical'), -SMARTS patterns for substructure matching, and group names for identification. This library serves as a reference -for the FunctionalGroupsDetector to identify and classify monomers based on their chemical structure. +Functional group library for epoxy polymerization chemistry. + +This library focuses on monomers and curing-agent functional groups relevant to +epoxy polymerization / epoxy curing systems. It includes epoxides and common +epoxy-reactive groups such as primary amines, secondary amines, thiols, alcohols, +carboxylic acids, and cyclic anhydrides. + +Each entry defines: + - functionality_type: + "mono" : one reactive functional group + "di_identical" : two identical reactive functional groups + "di_different" : two different reactive functional groups + + - smarts_1 / smarts_2: + SMARTS patterns used for substructure matching + + - group_name: + functional group label used by the detector + + - comments: + optional chemistry notes """ + class FunctionalGroupsLibrary: def __init__(self): self.monomer_types = { @@ -120,13 +137,44 @@ def __init__(self): "comments": None, }, + # ============================================================ + # Epoxy / Amine Functional Monomers + # Relevant for epoxy-amine polymerization + # + # Polymer-forming epoxy monomer: + # must contain two epoxide groups, i.e. diepoxy + # + # Primary monoamine: + # one -NH2 group has two active hydrogens + # can react with two epoxide groups in two stages + # + # Stage 1: + # primary amine + epoxide -> secondary amine + # + # Stage 2: + # secondary amine + epoxide -> tertiary amine + # ============================================================ "diepoxy_monomer": { "functionality_type": "di_identical", - "smarts_1": "[OX2r3:1]1[#6r3][#6r3]1", + "smarts_1": "[OX2r3:1]1[#6r3:2][#6r3:3]1", "group_name": "di_epoxide", - "comments": None, - } + "comments": "Difunctional epoxide monomer. Required on the epoxy side for epoxy-amine polymerization.", + }, + + "primary_amine_monomer": { + "functionality_type": "mono", + "smarts_1": "[NX3;H2;!$([N][C,S]=*):1]", + "group_name": "primary_amine", + "comments": "Mono primary amine. One -NH2 group has two active hydrogens and can react with two epoxide groups.", + }, + + "secondary_amine_monomer": { + "functionality_type": "mono", + "smarts_1": "[NX3;H1;!$([N][C,S]=*):1]", + "group_name": "secondary_amine", + "comments": "Mono secondary amine. Represents the second-stage reactive amine after primary amine reacts once with epoxide. By itself, a mono secondary amine reacts only once with epoxide and is not a true polymer-forming monomer.", + }, # ============================================================ # Commented functional groups diff --git a/AutoREACTER/detectors/reaction_rules.json b/AutoREACTER/detectors/reaction_rules.json index 6b694887..fb020f2f 100644 --- a/AutoREACTER/detectors/reaction_rules.json +++ b/AutoREACTER/detectors/reaction_rules.json @@ -2,6 +2,7 @@ "multi_step_reactions": [ { "name": "epoxy_polymerization", + "required_fgs": [] , "required_reactions": [ "first_step_reaction", "second_step_reaction" diff --git a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py index aaeacdc6..447fb198 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py @@ -2,6 +2,8 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Optional +import json +from pathlib import Path if TYPE_CHECKING: from AutoREACTER.session import Session @@ -13,6 +15,7 @@ class DetectedChemistries: reactions: dict[str, str] # reaction_name -> reaction_smarts + class DetectedChemistryFilter: """ Collects available detected chemistry from reaction instances. @@ -26,7 +29,7 @@ def __init__(self, session: Session): self.reaction_instances = session.reaction_instances or [] def _add_to_the_list(self, list_to_add: list[str], item: Optional[str]) -> None: - """ + """ Adds an item to the list if it is not None and not already present. """ if item is not None and item not in list_to_add: @@ -84,4 +87,11 @@ def filter(self) -> DetectedChemistries: return DetectedChemistries( functional_groups=available_functional_groups, reactions=available_reactions, - ) \ No newline at end of file + ) + +def _add_progessive_chemistries(): + rules_location = "AutoREACTER/detectors" + reactions_rules_location = Path(rules_location) / "reaction_rules.json" + with open(reactions_rules_location, "r") as file: + reaction_rules = json.load(file) + \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py new file mode 100644 index 00000000..629be0c7 --- /dev/null +++ b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py @@ -0,0 +1,21 @@ + +def ascii_art(message: str) -> None: + message = message.upper() + print(f"WARNING: {message}") + """ _ _ _ _ +| | | | (_) | | | | +| | | | __ _ _ __ _ __ _ _ __ __ _| | | | +| |/\| |/ _` | '__| '_ \| | '_ \ / _` | | | | +\ /\ / (_| | | | | | | | | | | (_| |_|_|_| + \/ \/ \__,_|_| |_| |_|_|_| |_|\__, (_|_|_) + __/ | + |___/ +""" + + +def print_warning() -> None: + message = "Warning " \ + "Entering to the reaction progression Loop still in the Beta phase" \ + "Caution: Can be chemically inaccurate" + ascii_art(message) + From a01caea99363feaa75c214acb80076f141a5d170 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 7 Jul 2026 15:08:54 -0400 Subject: [PATCH 009/176] Add staged amine-epoxy reaction rules --- .../detectors/functional_groups_library.py | 2 +- AutoREACTER/detectors/reaction_rules.json | 9 ++++++--- AutoREACTER/detectors/reactions_library.py | 20 +++++++++++++++---- .../detected_chemistry_filter.py | 18 ++++++++++------- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index 047d5d24..e540ce00 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -155,7 +155,7 @@ def __init__(self): # secondary amine + epoxide -> tertiary amine # ============================================================ - "diepoxy_monomer": { + "di_epoxy_monomer": { "functionality_type": "di_identical", "smarts_1": "[OX2r3:1]1[#6r3:2][#6r3:3]1", "group_name": "di_epoxide", diff --git a/AutoREACTER/detectors/reaction_rules.json b/AutoREACTER/detectors/reaction_rules.json index fb020f2f..14931501 100644 --- a/AutoREACTER/detectors/reaction_rules.json +++ b/AutoREACTER/detectors/reaction_rules.json @@ -2,11 +2,14 @@ "multi_step_reactions": [ { "name": "epoxy_polymerization", - "required_fgs": [] , + "if_reactions": "Amine Epoxy Addition First Stage", "required_reactions": [ - "first_step_reaction", - "second_step_reaction" + "Amine Epoxy Addition Second Stage" ] + , + "fg_additon": { + "primary_amine": "secondary_amine" + } } ] } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py index 7d7b7118..7d97bb5e 100644 --- a/AutoREACTER/detectors/reactions_library.py +++ b/AutoREACTER/detectors/reactions_library.py @@ -341,16 +341,27 @@ def __init__(self): }, "Amine Epoxy Addition First Stage": { "same_reactants": False, - "reactant_1": "amine", + "reactant_1": "primary_amine", "reactant_2": "epoxide", "product": "beta_hydroxy_secondary_amine", "delete_atom": False, - "reaction": "[NX3;H2,H1:1].[OX2r3:2]1[CX4r3:3][CX4r3:4]1>>[NX3:1]-[CX4:3]-[CX4:4]-[OX2H1:2]", + "reaction": "[NX3;H2:1].[OX2r3:2]1[CX4r3:3][CX4r3:4]1>>[NX3;H1:1]-[CX4:3]-[CX4:4]-[OX2H1:2]", "reference": { "reaction_and_mechanism": [] } + }, + + "Amine Epoxy Addition Second Stage": { + "same_reactants": False, + "reactant_1": "secondary_amine", + "reactant_2": "epoxide", + "product": "beta_hydroxy_tertiary_amine", + "delete_atom": False, + "reaction": "[NX3;H1:1].[OX2r3:2]1[CX4r3:3][CX4r3:4]1>>[NX3;H0:1]-[CX4:3]-[CX4:4]-[OX2H1:2]", + "reference": { + "reaction_and_mechanism": [] } - } + }, # ============================================================ # Commented reactions @@ -485,4 +496,5 @@ def __init__(self): # "delete_atom": False, # "reaction": "[NX2:3]=[CX2:4]=[OX1,SX1:5].[OX2,SX2;H1;!$([O,S]C=*):6]>>[NX3:3][CX3:4](=[OX1,SX1:5])[OX2,SX2;!$([O,S]C=*):6]" # }, - #} \ No newline at end of file + #} + } \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py index 447fb198..c324fb8d 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Optional import json -from pathlib import Path +from importlib.resources import files if TYPE_CHECKING: from AutoREACTER.session import Session @@ -89,9 +89,13 @@ def filter(self) -> DetectedChemistries: reactions=available_reactions, ) -def _add_progessive_chemistries(): - rules_location = "AutoREACTER/detectors" - reactions_rules_location = Path(rules_location) / "reaction_rules.json" - with open(reactions_rules_location, "r") as file: - reaction_rules = json.load(file) - \ No newline at end of file + + + + def _add_progessive_chemistries(self): + rules_file = files("AutoREACTER.detectors").joinpath("reaction_rules.json") + + with rules_file.open("r", encoding="utf-8") as file: + reaction_rules = json.load(file) + + return reaction_rules \ No newline at end of file From c2a93bc96bc63e8fdef6539e7ac86a4dc5986d05 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 7 Jul 2026 15:21:58 -0400 Subject: [PATCH 010/176] WIP: add progressive chemistry rules skeleton --- .../detected_chemistry_filter.py | 14 ++-- test.ipynb | 66 +++++++++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 test.ipynb diff --git a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py index c324fb8d..64700420 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py @@ -83,7 +83,13 @@ def filter(self) -> DetectedChemistries: available_functional_groups, functional_group_2.fg_smarts_2, ) - + rules = self._add_progessive_chemistries() + for reaction in available_reactions: + for rule in rules: + print(f"yet to implement for reaction: {reaction}, rule: {rule}" + in here we need to add functional groups with meta data + and then add to the set. + ) return DetectedChemistries( functional_groups=available_functional_groups, reactions=available_reactions, @@ -92,10 +98,10 @@ def filter(self) -> DetectedChemistries: - def _add_progessive_chemistries(self): + def _add_progessive_chemistries(): rules_file = files("AutoREACTER.detectors").joinpath("reaction_rules.json") with rules_file.open("r", encoding="utf-8") as file: reaction_rules = json.load(file) - - return reaction_rules \ No newline at end of file + rules = reaction_rules["multi_step_reactions"] + return rules \ No newline at end of file diff --git a/test.ipynb b/test.ipynb new file mode 100644 index 00000000..56f21e44 --- /dev/null +++ b/test.ipynb @@ -0,0 +1,66 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "7642e888", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "import json\n", + "from importlib.resources import files\n", + "\n", + "\n", + "def _add_progessive_chemistries():\n", + " rules_file = files(\"AutoREACTER.detectors\").joinpath(\"reaction_rules.json\")\n", + "\n", + " with rules_file.open(\"r\", encoding=\"utf-8\") as file:\n", + " reaction_rules = json.load(file)\n", + " rules = reaction_rules[\"multi_step_reactions\"]\n", + " print(rules)\n", + "\n", + " return reaction_rules" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8af2ad56", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'multi_step_reactions': [{'name': 'epoxy_polymerization', 'if_reactions': 'Amine Epoxy Addition First Stage', 'required_reactions': ['Amine Epoxy Addition Second Stage'], 'fg_additon': {'primary_amine': 'secondary_amine'}}]}\n" + ] + } + ], + "source": [ + "action = _add_progessive_chemistries()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 7df0749a0af1bd94de54022f8de66e127ed26f7f Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 9 Jul 2026 09:51:53 -0400 Subject: [PATCH 011/176] Add epoxy simulation example config --- examples/test_epoxy.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 examples/test_epoxy.json diff --git a/examples/test_epoxy.json b/examples/test_epoxy.json new file mode 100644 index 00000000..00fb094f --- /dev/null +++ b/examples/test_epoxy.json @@ -0,0 +1,24 @@ +{ + "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "simulations": [ + { + "tag": "epoxy_test", + "temperature": 300, + "density": 1.0, + "monomer_counts": { + "di_epoxy": 200, + "primary_diamine": 100 + } + } + ], + "monomers": [ + { + "name": "di_epoxy", + "smiles": "C1OC1COCCOCC1CO1" + }, + { + "name": "primary_diamine", + "smiles": "NCCN" + } + ] +} \ No newline at end of file From 8ab6dd8ed473239c8f053d0751f1f94f8f736a32 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 9 Jul 2026 16:10:05 -0400 Subject: [PATCH 012/176] Implement index-based functional group detection --- .../detectors/functional_groups_detector.py | 129 +++++++----- .../detectors/functional_groups_library.py | 6 +- AutoREACTER/detectors/reactions_library.py | 30 +-- .../reaction_processor/prepare_reactions.py | 4 +- .../reaction_progression.py | 190 +++++++++++++++++- 5 files changed, 285 insertions(+), 74 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index a5b9dba1..d14395f3 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, List from numpy import indices """ @@ -118,6 +118,7 @@ logger = logging.getLogger(__name__) # Module-level logger for future diagnostics. if TYPE_CHECKING: from AutoREACTER.session import Session + from AutoREACTER.detectors.functional_groups_detector import MonomerRoleforIndexBasedFGDetection @dataclass(slots=True) @@ -145,7 +146,7 @@ class FunctionalGroupInfo: fg_2_indexes: Optional[Tuple[int, ...]] = None -@dataclass(slots=True, frozen=True) +@dataclass(slots=True) class MonomerRole: """ Immutable dataclass representing a monomer with its detected functional groups. @@ -158,6 +159,10 @@ class MonomerRole: smiles: str name: str functionalities: Tuple[FunctionalGroupInfo, ...] # Tuple of detected functionalities for the monomer + rdkit_mol: Optional[rdchem.Mol] = None # Optional RDKit molecule object for the monomer + indexes_in_template: List[int] = None # Optional list of atom indices in the template + is_monomer: bool = False # Flag indicating if the monomer is eligible for polymerization + is_looped: bool = False @dataclass(slots=True) class FunctionalGroupVisualization: @@ -355,6 +360,7 @@ def functional_groups_detector( smiles=smiles, name=monomer.name, functionalities=tuple(detected_functionalities), + is_monomer=True ) ) @@ -435,57 +441,90 @@ def _detect_functional_groups_by_index(self, mol: Chem.Mol, smarts: str, indices return bool(matching_hits) def index_based_functional_groups_detector( - self, session: "Session" + self, monomer_roles_in: list[MonomerRoleforIndexBasedFGDetection] ) -> None: """ - Detect functional groups across a list of monomers and categorize them into roles. + Detect functional groups across a list of monomers and categorize them into roles, + restricted to a given set of atom indices per monomer. - Iterates over predefined monomer_types, matches each against the monomer's SMILES, - and collects valid detections. Prints matches for debugging/user feedback. + Iterates over predefined monomer_types, matches each against the monomer's + rdkit_mol, and keeps only matches that overlap with the monomer's + `indexes_in_template`. Prints matches for debugging/user feedback. Args: - session (Session): Validated Session object containing monomers. + monomer_roles_in (list[MonomerRoleforIndexBasedFGDetection]): List of monomer + roles to process, each carrying the atom indices of interest. Returns: - None (results stored in session.monomer_roles for downstream use). + list[MonomerRole] | bool: List of MonomerRole objects with index-filtered + functionalities, or False if none detected. Notes: - - Matches criteria: 'vinyl'/'mono' (>=1 primary), 'di_identical' (>=2 primary), - 'di_different' (>=1 each pattern). + - Index-based rule: at least ONE match overlapping the given indices is + enough to qualify, regardless of functionality_type. This intentionally + breaks the whole-molecule 'di_identical' (>=2 matches) rule, since here + we only care whether the given index sits inside a valid functional group, + not how many total sites exist on the monomer. """ - - monomers = session.inputs.monomers - monomer_roles = [] - for monomer in monomers: - smiles = monomer.smiles + monomer_roles_out = [] + + for monomer in monomer_roles_in: + if monomer.is_looped: + continue # Skip already processed monomers + + mol = monomer.rdkit_mol + print(f"Processing monomer: {monomer.name} with SMILES: {monomer.smiles}") + + target_indices = set(monomer.indexes_in_template or []) detected_functionalities = [] all_matches = [] - + # Check against each predefined functional group type. for functional_group in self.monomer_types.values(): ftype = functional_group["functionality_type"] smarts_1 = functional_group["smarts_1"] smarts_2 = functional_group.get("smarts_2") - functionality_count, count_1, count_2, functional_matches = ( - self.detect_monomer_functionality( - monomer.rdkit_mol, - ftype, - smarts_1, - smarts_2, - ) - ) + patt1 = Chem.MolFromSmarts(smarts_1) + if patt1 is None: + logger.warning(f"Invalid primary SMARTS: {smarts_1}") + continue + + matches1 = mol.GetSubstructMatches(patt1, uniquify=True) + # Index-based filter: keep only matches touching at least one target index. + matches1_hit = [m for m in matches1 if target_indices.intersection(m)] + count_1 = len(matches1_hit) + + count_2 = None + matches2_hit = [] + + if smarts_2: + patt2 = Chem.MolFromSmarts(smarts_2) + if patt2 is None: + logger.warning(f"Invalid secondary SMARTS: {smarts_2}") + continue + + matches2 = mol.GetSubstructMatches(patt2, uniquify=True) + matches2_hit = [m for m in matches2 if target_indices.intersection(m)] + count_2 = len(matches2_hit) + + # di_different: still need one overlapping hit on EACH pattern. + functionality_count = 2 if (count_1 >= 1 and count_2 >= 1) else 0 + else: + # vinyl / mono / di_identical: ONE overlapping match is enough. + # (Breaks the normal di_identical >=2 rule on purpose for index-based detection.) + functionality_count = 1 if count_1 >= 1 else 0 - # Determine if this functionality matches criteria. if functionality_count > 0: + functional_matches = tuple(matches1_hit) + tuple(matches2_hit) all_matches.extend(functional_matches) - + # Log detected functionality for debugging/user feedback. - print(f"{smiles} has functionality: {functional_group['group_name']}") + print(f"{monomer.smiles} has functionality: {functional_group['group_name']}") if functional_group.get("comments"): - print(f"Note: {smiles} - {functional_group['comments']}") + print(f"Note: {monomer.smiles} - {functional_group['comments']}") detected_functionalities.append( FunctionalGroupInfo( @@ -493,37 +532,33 @@ def index_based_functional_groups_detector( fg_name=functional_group["group_name"], fg_smarts_1=smarts_1, fg_count_1=count_1, + fg_1_indexes=tuple(matches1_hit) if matches1_hit else None, fg_smarts_2=smarts_2, fg_count_2=count_2, + fg_2_indexes=tuple(matches2_hit) if matches2_hit else None, ) ) - # Debug print for match details. - # print( - # f"Monomer {monomer.name} (SMILES: {smiles}) matches {ftype} " - # f"with {functional_group['group_name']} (Count 1: {count_1}, Count 2: {count_2})" - # ) # Add to roles if any functionalities detected. if detected_functionalities: - monomer_roles.append( + monomer_roles_out.append( MonomerRole( - smiles=smiles, + smiles=monomer.smiles, name=monomer.name, + rdkit_mol=monomer.rdkit_mol, functionalities=tuple(detected_functionalities), + is_monomer=False, # This is a product, not an input monomer + is_looped=False, # Yet to be processed in the loop + indexes_in_template=monomer.indexes_in_template, ) ) - - # Store results in session for potential downstream use. - if not monomer_roles: - raise RuntimeError( - "No functional groups were detected in any input monomer. " - "Either the input molecules are not valid polymerizable monomers, " - "or AutoREACTER does not yet support these monomer types. " - "Please open a feature request or issue if you think support should be added: " - "https://github.com/NanoCIPHER-Lab/AutoREACTER/issues" - ) - session.monomer_roles = monomer_roles - return None # Return session with updated monomer_roles; visualization handled separately. + + # Store results for potential downstream use. + if not monomer_roles_out: + return False # No functional groups detected; handle as needed + # first break condition: if no monomer roles are detected, return False to indicate no further processing is needed. + + return monomer_roles_out # Return list of MonomerRole; visualization not considered here. def functional_group_highlighted_molecules_image_grid(self, session: Session) -> Image: """Convert monomer roles with detected functionalities into visualizations. diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index e540ce00..3f38c5c5 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -157,21 +157,21 @@ def __init__(self): "di_epoxy_monomer": { "functionality_type": "di_identical", - "smarts_1": "[OX2r3:1]1[#6r3:2][#6r3:3]1", + "smarts_1": "[CX4;R1]1[OX2;R1][CX4;R1]1", "group_name": "di_epoxide", "comments": "Difunctional epoxide monomer. Required on the epoxy side for epoxy-amine polymerization.", }, "primary_amine_monomer": { "functionality_type": "mono", - "smarts_1": "[NX3;H2;!$([N][C,S]=*):1]", + "smarts_1": "[NX3H2;!$(NC=O);!$(NC=[N,O,S])]", "group_name": "primary_amine", "comments": "Mono primary amine. One -NH2 group has two active hydrogens and can react with two epoxide groups.", }, "secondary_amine_monomer": { "functionality_type": "mono", - "smarts_1": "[NX3;H1;!$([N][C,S]=*):1]", + "smarts_1": "[NX3H1;!$(NC=O);!$(NC=[N,O,S])]", "group_name": "secondary_amine", "comments": "Mono secondary amine. Represents the second-stage reactive amine after primary amine reacts once with epoxide. By itself, a mono secondary amine reacts only once with epoxide and is not a true polymer-forming monomer.", }, diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py index 7d97bb5e..4dd9a14d 100644 --- a/AutoREACTER/detectors/reactions_library.py +++ b/AutoREACTER/detectors/reactions_library.py @@ -339,28 +339,32 @@ def __init__(self): }, "comments": None }, - "Amine Epoxy Addition First Stage": { + "Primary Amine and Epoxide Polyaddition (Epoxy-Amine, First Addition)": { "same_reactants": False, "reactant_1": "primary_amine", - "reactant_2": "epoxide", - "product": "beta_hydroxy_secondary_amine", + "reactant_2": "di_epoxide", + "product": "secondary_amine_hydroxyl_product", "delete_atom": False, - "reaction": "[NX3;H2:1].[OX2r3:2]1[CX4r3:3][CX4r3:4]1>>[NX3;H1:1]-[CX4:3]-[CX4:4]-[OX2H1:2]", + "reaction": "[NX3H2:1]-[H:6].[CX4:2]1[OX2:5][CX4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]", "reference": { - "reaction_and_mechanism": [] - } + "smarts": None, + "reaction_and_mechanism": None + }, + "comments": "Primary amine (-NH2) opens one epoxide ring. One N-H is consumed and transferred to the epoxide oxygen as -OH; nitrogen becomes a secondary amine with one remaining N-H, still reactive toward a second epoxide." }, - "Amine Epoxy Addition Second Stage": { + "Secondary Amine and Epoxide Polyaddition (Epoxy-Amine, Second Addition / Crosslink)": { "same_reactants": False, - "reactant_1": "secondary_amine", - "reactant_2": "epoxide", - "product": "beta_hydroxy_tertiary_amine", + "reactant_1": "secondary_amine_monomer", + "reactant_2": "di_epoxy_monomer", + "product": "tertiary_amine_crosslink_product", "delete_atom": False, - "reaction": "[NX3;H1:1].[OX2r3:2]1[CX4r3:3][CX4r3:4]1>>[NX3;H0:1]-[CX4:3]-[CX4:4]-[OX2H1:2]", + "reaction": "[NX3H1:1]-[H:6].[CX4:2]1[OX2:5][CX4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]", "reference": { - "reaction_and_mechanism": [] - } + "smarts": None, + "reaction_and_mechanism": None + }, + "comments": "Secondary amine's remaining N-H opens a second epoxide ring. Nitrogen becomes a fully substituted tertiary amine (network crosslink point); no reactive N-H remains on this nitrogen." }, # ============================================================ diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 9c2d9510..eeea4bd0 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -29,7 +29,7 @@ # Use TYPE_CHECKING to prevent circular imports with session.py if TYPE_CHECKING: from AutoREACTER.session import Session - +from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ReactionProgression class MappingError(Exception): """Custom exception raised when atom mapping between reactants and products fails or is inconsistent.""" @@ -163,6 +163,8 @@ def prepare_reactions(self, session: "Session") -> list[ReactionMetadata]: # Store the finalized metadata inside the session session.reaction_metadata = unique_reaction_metadata + reaction_progression = ReactionProgression(session) + return unique_reaction_metadata # --- PIPELINE STEPS (PRIVATE) --- diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index d5301139..3bfbf2ee 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -1,24 +1,194 @@ -MAX_LOOP = 5 # Maximum number of iterations for the reaction progression loop. Users should be able to adjust this value based on their specific needs and the complexity of the reactions being analyzed. +MAX_LOOP = 5 # Maximum number of iterations for the reaction progression loop. + from typing import TYPE_CHECKING -from dataclasses import dataclass +from dataclasses import dataclass, field + +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import FunctionalGroupsDetector + if TYPE_CHECKING: from AutoREACTER.session import Session + from AutoREACTER.detectors.functional_groups_detector import MonomerRole + -from AutoREACTER.reaction_preparation.reaction_processor.detected_chemistry_filter import DetectedChemistryFilter, DetectedChemistries +@dataclass(slots=True) +class MonomerRoleforIndexBasedFGDetection: + """ + Represents a monomer role with its associated properties for + index-based functional group detection. + """ + smiles: str + name: str + indexes_in_template: list[int] + is_monomer: bool = False + is_looped: bool = False + rdkit_mol: Chem.Mol | None = None @dataclass(slots=True) class ReactionProgressionSession: """ - Holds the state of the reaction progression process, including detected chemistries and the current iteration count. + Placeholder for future reaction progression state. """ - iteration: int = 0 # Current iteration count of the reaction progression loop. - detected_chemistries: DetectedChemistries + monomer_roles: list["MonomerRole"] = field(default_factory=list) + iteration: int = 0 class ReactionProgression: - def __init__(self, session: "Session"): - self.detected_chemistry_filter = DetectedChemistryFilter(session) - def reaction_progression(self, session: "Session", max_loop: int = MAX_LOOP) -> None: - pass \ No newline at end of file + self.session = session + self.session.reaction_progression_session = ReactionProgressionSession() + + self.fg_detector = FunctionalGroupsDetector() + self.reaction_progression() + + def reaction_progression(self, max_loop: int = MAX_LOOP) -> None: + """ + Progresses the reaction by iteratively applying detected chemistries + to the session's molecules. + + Args: + max_loop (int): Maximum number of iterations for the reaction progression loop. + """ + iteration = 0 + + while iteration < max_loop: + iteration += 1 + self.session.reaction_progression_session.iteration = iteration + + if iteration == 1: + self._populate_monomer_roles() + + if iteration > 1: + print( + f"Starting iteration {iteration} " + f"of the reaction progression loop." + ) + + size_of_pool = self._set_is_monomer_flag() + + print(self.session.monomer_roles) # Debug print + monomer_roles_for_idx_based_fg_detection = self._prepare_products_for_idx_based_fg_detection() + fg_detection_results = self.fg_detector.index_based_functional_groups_detector( + monomer_roles_for_idx_based_fg_detection + ) + # self.fg_detector._detect_functional_groups_by_index(self.session) + + if self._loop_break_condition(size_of_pool): + break + + def _prepare_products_for_idx_based_fg_detection( + self, + ) -> list[MonomerRoleforIndexBasedFGDetection]: + """ + Prepares generated reaction products for index-based functional group detection. + """ + monomer_roles_for_idx_based_fg_detection = [] + reaction_metadata = self.session.reaction_metadata + + for reaction in reaction_metadata: + monomer_roles_for_idx_based_fg_detection.append( + MonomerRoleforIndexBasedFGDetection( + smiles=self._get_product_smiles(reaction.product_combined_RDmol), + name=f"new_{reaction.reaction_id}", + indexes_in_template=self._get_product_index( + reaction.template_reactant_to_product_mapping + ), + is_monomer=False, + is_looped=False, + rdkit_mol=self._sanitize_molecule(reaction.product_combined_RDmol), + + ) + ) + + return monomer_roles_for_idx_based_fg_detection + + def _sanitize_molecule(self, mol: Chem.Mol) -> Chem.Mol | None: + """ + Sanitizes an RDKit molecule object to ensure it is chemically valid. + + Args: + mol (Chem.Mol): The RDKit molecule object to sanitize. + + Returns: + Chem.Mol | None: The sanitized RDKit molecule object, or None if sanitization fails. + """ + try: + Chem.SanitizeMol(mol) + return mol + except Exception: + return None + + def _get_product_smiles(self, mol: Chem.Mol) -> str: + """ + Converts an RDKit molecule object to its corresponding SMILES string. + """ + try: + return Chem.MolToSmiles(mol) + except Exception: + return "" + + def _get_product_index( + self, + template_reactant_to_product_mapping: dict, + ) -> list[int]: + """ + Retrieves product indexes from the reactant-to-product mapping. + + Args: + template_reactant_to_product_mapping (dict): Mapping from reactant + indices to product indices. + + Returns: + list[int]: Corresponding product indexes. + """ + product_indexes = [] + + for product_idx in template_reactant_to_product_mapping.values(): + product_indexes.append(product_idx) + print(f"Product indexes: {product_indexes}") # Debug print + return product_indexes + + def _set_is_monomer_flag(self) -> int: + """ + Sets the is_looped flag for each monomer role in the session. + + Returns: + int: Number of monomer roles before functional group detection. + """ + for monomer_role in self.session.monomer_roles: + monomer_role.is_looped = True + + return len(self.session.monomer_roles) + + def _populate_monomer_roles(self) -> None: + """ + Populates RDKit molecule objects for monomers marked as monomers. + """ + for monomer in self.session.monomer_roles: + if monomer.is_monomer: + monomer.rdkit_mol = self._smiles_to_rdkit_mol(monomer.smiles) + + def _smiles_to_rdkit_mol(self, smiles: str) -> Chem.Mol | None: + """ + Converts a SMILES string to an RDKit molecule object. + + Args: + smiles (str): The SMILES string to convert. + + Returns: + Chem.Mol | None: The corresponding RDKit molecule object. + """ + return Chem.MolFromSmiles(smiles) + + def _loop_break_condition(self, size_of_pool: int) -> bool: + if size_of_pool <= len(self.session.monomer_roles): + print( + f"Breaking the loop as the size of the pool ({size_of_pool}) " + f"is less than or equal to the number of monomer roles " + f"({len(self.session.monomer_roles)})." + ) + return True + + return False \ No newline at end of file From 4b02a381ac4fe7c23fb5a4b6e84c52b629e6cd3a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 9 Jul 2026 16:21:23 -0400 Subject: [PATCH 013/176] Clean reaction products in progression Copy loop monomer roles before extending them, and strip atom maps/isotopes from product molecules before sanitizing or generating SMILES. --- .../reaction_processor/reaction_progression.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 3bfbf2ee..2d288fc6 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -52,11 +52,11 @@ def reaction_progression(self, max_loop: int = MAX_LOOP) -> None: max_loop (int): Maximum number of iterations for the reaction progression loop. """ iteration = 0 + monomer_roles_in_loop = self.session.monomer_roles.copy() # Create a copy to avoid modifying the original list during iteration while iteration < max_loop: iteration += 1 - self.session.reaction_progression_session.iteration = iteration - + if iteration == 1: self._populate_monomer_roles() @@ -73,8 +73,8 @@ def reaction_progression(self, max_loop: int = MAX_LOOP) -> None: fg_detection_results = self.fg_detector.index_based_functional_groups_detector( monomer_roles_for_idx_based_fg_detection ) - # self.fg_detector._detect_functional_groups_by_index(self.session) - + monomer_roles_in_loop.extend(fg_detection_results) + print(monomer_roles_in_loop) # Debug print if self._loop_break_condition(size_of_pool): break @@ -114,16 +114,23 @@ def _sanitize_molecule(self, mol: Chem.Mol) -> Chem.Mol | None: Returns: Chem.Mol | None: The sanitized RDKit molecule object, or None if sanitization fails. """ + self._clean_product(mol) # Clean the product before sanitization try: Chem.SanitizeMol(mol) return mol except Exception: return None + + def _clean_product(self, products: Chem.Mol) -> Chem.Mol | None: + for atom in products.GetAtoms(): + atom.SetAtomMapNum(0) + atom.SetIsotope(0) def _get_product_smiles(self, mol: Chem.Mol) -> str: """ Converts an RDKit molecule object to its corresponding SMILES string. """ + self._clean_product(mol) # Clean the product before converting to SMILES try: return Chem.MolToSmiles(mol) except Exception: From e6516ad6f80a07f0c294eb3a7ed29f2cec669f1e Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 9 Jul 2026 16:36:05 -0400 Subject: [PATCH 014/176] Add index-based reaction detection in progression --- AutoREACTER/detectors/reaction_detector.py | 134 ++++++++++++++++++ .../reaction_progression.py | 81 ++++++++--- 2 files changed, 193 insertions(+), 22 deletions(-) diff --git a/AutoREACTER/detectors/reaction_detector.py b/AutoREACTER/detectors/reaction_detector.py index 5d7b68e3..73b6911a 100644 --- a/AutoREACTER/detectors/reaction_detector.py +++ b/AutoREACTER/detectors/reaction_detector.py @@ -241,6 +241,140 @@ def reaction_detector(self, session: "Session") -> None: ) session.reaction_instances = reaction_instances + + def index_based_reaction_detector( + self, monomer_roles: List[MonomerRole] + ) -> List[ReactionInstance]: + """ + Scans a list of index-based monomer roles to find all possible polymerization + reactions, same logic as reaction_detector but operating on a direct list of + MonomerRole objects (as produced by index_based_functional_groups_detector) + instead of session.monomer_roles. + + Looping rule: + - Homo-polymerization (single monomer role): skip if that monomer role + is already looped (is_looped=True). + - Co-polymerization / same-reactant-two-FG (two monomer roles involved): + skip ONLY if BOTH monomer roles are already looped. If either one is + still fresh (is_looped=False), the pair is still looked up/processed. + + Args: + monomer_roles: List of MonomerRole objects to analyze. + + Returns: + List[ReactionInstance]: All detected reaction instances for this pass. + """ + reaction_instances = [] + seen_pairs: Set[Tuple] = set() + + for reaction_name, reaction_info in self.reactions.items(): + reactant_1_name = reaction_info.get("reactant_1") + reactant_2_name = reaction_info.get("reactant_2") + same_reactants = reaction_info.get("same_reactants", False) + + # CASE 1: HOMO-POLYMERIZATION (e.g., A + A) + if same_reactants and reactant_2_name is None: + for monomer_role in monomer_roles: + # Single-monomer case: skip only if this monomer is already looped. + if monomer_role.is_looped: + continue + + fg_hits = self._matching_fgs(monomer_role, reactant_1_name) + for fg in fg_hits: + pair_key = self._seen_pair_key(reaction_name, monomer_role, fg) + if pair_key not in seen_pairs: + seen_pairs.add(pair_key) + reaction_instances.append( + ReactionInstance( + reaction_name=reaction_name, + reaction_smarts=reaction_info["reaction"], + delete_atom=reaction_info["delete_atom"], + references=reaction_info["reference"], + same_reactants=same_reactants, + monomer_1=monomer_role, + functional_group_1=fg + ) + ) + + # CASE 2: CO-POLYMERIZATION (e.g., A + B) + else: + for monomer_role_i in monomer_roles: + fg_hits_i = self._matching_fgs(monomer_role_i, reactant_1_name) + if not fg_hits_i: + continue + + for fg_i in fg_hits_i: + for monomer_role_j in monomer_roles: + # Prevent a monomer reacting with itself in a co-monomer definition + if monomer_role_i == monomer_role_j: + continue + + # Pairwise rule: skip only if BOTH are already looped. + if monomer_role_i.is_looped and monomer_role_j.is_looped: + continue + + fg_hits_j = self._matching_fgs(monomer_role_j, reactant_2_name) + for fg_j in fg_hits_j: + pair_key = self._seen_pair_key( + reaction_name, monomer_role_i, fg_i, monomer_role_j, fg_j + ) + if pair_key not in seen_pairs: + seen_pairs.add(pair_key) + reaction_instances.append( + ReactionInstance( + reaction_name=reaction_name, + reaction_smarts=reaction_info["reaction"], + delete_atom=reaction_info["delete_atom"], + references=reaction_info["reference"], + same_reactants=same_reactants, + monomer_1=monomer_role_i, + functional_group_1=fg_i, + monomer_2=monomer_role_j, + functional_group_2=fg_j + ) + ) + + # CASE 1.1: Same reactant has two functional groups (e.g., A + A with FG1 and FG2) + if not same_reactants and reactant_2_name is not None: + for monomer_role in monomer_roles: + # Both "slots" are the same monomer role here, so the pairwise + # both-looped rule collapses to a single-monomer check. + if monomer_role.is_looped: + continue + + fg_hits_1 = self._matching_fgs(monomer_role, reactant_1_name) + fg_hits_2 = self._matching_fgs(monomer_role, reactant_2_name) + + for fg_1 in fg_hits_1: + for fg_2 in fg_hits_2: + + # Skip identical FG objects + if fg_1 == fg_2: + continue + + pair_key = self._seen_pair_key( + reaction_name, monomer_role, fg_1, monomer_role, fg_2 + ) + + if pair_key not in seen_pairs: + seen_pairs.add(pair_key) + + reaction_instances.append( + ReactionInstance( + reaction_name=reaction_name, + reaction_smarts=reaction_info["reaction"], + delete_atom=reaction_info["delete_atom"], + references=reaction_info["reference"], + same_reactants=same_reactants, + monomer_1=monomer_role, + functional_group_1=fg_1, + monomer_2=monomer_role, + functional_group_2=fg_2 + ) + ) + + return reaction_instances + def create_reaction_image(self, reactant_a_smiles: str, reactant_b_smiles: str, reaction_smarts: str, reaction_name: str) -> Image.Image: """ diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 2d288fc6..5b52789c 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -1,11 +1,12 @@ MAX_LOOP = 5 # Maximum number of iterations for the reaction progression loop. -from typing import TYPE_CHECKING from dataclasses import dataclass, field +from typing import TYPE_CHECKING from rdkit import Chem from AutoREACTER.detectors.functional_groups_detector import FunctionalGroupsDetector +from AutoREACTER.detectors.reaction_detector import ReactionDetector if TYPE_CHECKING: from AutoREACTER.session import Session @@ -20,7 +21,7 @@ class MonomerRoleforIndexBasedFGDetection: """ smiles: str name: str - indexes_in_template: list[int] + indexes_in_template: list[int] is_monomer: bool = False is_looped: bool = False rdkit_mol: Chem.Mol | None = None @@ -41,6 +42,8 @@ def __init__(self, session: "Session"): self.session.reaction_progression_session = ReactionProgressionSession() self.fg_detector = FunctionalGroupsDetector() + self.rxn_detector = ReactionDetector() + self.reaction_progression() def reaction_progression(self, max_loop: int = MAX_LOOP) -> None: @@ -52,11 +55,13 @@ def reaction_progression(self, max_loop: int = MAX_LOOP) -> None: max_loop (int): Maximum number of iterations for the reaction progression loop. """ iteration = 0 - monomer_roles_in_loop = self.session.monomer_roles.copy() # Create a copy to avoid modifying the original list during iteration + monomer_roles_in_loop = self.session.monomer_roles.copy() + reaction_instances = self.session.reaction_instances.copy() while iteration < max_loop: iteration += 1 - + self.session.reaction_progression_session.iteration = iteration + if iteration == 1: self._populate_monomer_roles() @@ -69,12 +74,34 @@ def reaction_progression(self, max_loop: int = MAX_LOOP) -> None: size_of_pool = self._set_is_monomer_flag() print(self.session.monomer_roles) # Debug print - monomer_roles_for_idx_based_fg_detection = self._prepare_products_for_idx_based_fg_detection() - fg_detection_results = self.fg_detector.index_based_functional_groups_detector( - monomer_roles_for_idx_based_fg_detection + + monomer_roles_for_idx_based_fg_detection = ( + self._prepare_products_for_idx_based_fg_detection() + ) + + fg_detection_results = ( + self.fg_detector.index_based_functional_groups_detector( + monomer_roles_for_idx_based_fg_detection ) + ) + + if not fg_detection_results: + print( + f"No new functional groups detected in iteration {iteration}. " + f"Ending the reaction progression loop." + ) + break + monomer_roles_in_loop.extend(fg_detection_results) + + rxns = self.rxn_detector.index_based_reaction_detector( + monomer_roles_in_loop + ) + reaction_instances.extend(rxns) + + print(len(reaction_instances)) # Debug print print(monomer_roles_in_loop) # Debug print + if self._loop_break_condition(size_of_pool): break @@ -88,49 +115,57 @@ def _prepare_products_for_idx_based_fg_detection( reaction_metadata = self.session.reaction_metadata for reaction in reaction_metadata: + product_mol = reaction.product_combined_RDmol + monomer_roles_for_idx_based_fg_detection.append( MonomerRoleforIndexBasedFGDetection( - smiles=self._get_product_smiles(reaction.product_combined_RDmol), + smiles=self._get_product_smiles(product_mol), name=f"new_{reaction.reaction_id}", indexes_in_template=self._get_product_index( reaction.template_reactant_to_product_mapping - ), + ), is_monomer=False, is_looped=False, - rdkit_mol=self._sanitize_molecule(reaction.product_combined_RDmol), - + rdkit_mol=self._sanitize_molecule(product_mol), ) ) return monomer_roles_for_idx_based_fg_detection - + def _sanitize_molecule(self, mol: Chem.Mol) -> Chem.Mol | None: """ - Sanitizes an RDKit molecule object to ensure it is chemically valid. + Sanitizes an RDKit molecule object. Args: - mol (Chem.Mol): The RDKit molecule object to sanitize. + mol (Chem.Mol): RDKit molecule object. Returns: - Chem.Mol | None: The sanitized RDKit molecule object, or None if sanitization fails. + Chem.Mol | None: Sanitized molecule, or None if sanitization fails. """ - self._clean_product(mol) # Clean the product before sanitization + self._clean_product(mol) + try: Chem.SanitizeMol(mol) return mol except Exception: return None - - def _clean_product(self, products: Chem.Mol) -> Chem.Mol | None: - for atom in products.GetAtoms(): + + def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: + """ + Removes atom map numbers and isotope labels from a product molecule. + """ + for atom in mol.GetAtoms(): atom.SetAtomMapNum(0) atom.SetIsotope(0) + return mol + def _get_product_smiles(self, mol: Chem.Mol) -> str: """ Converts an RDKit molecule object to its corresponding SMILES string. """ - self._clean_product(mol) # Clean the product before converting to SMILES + self._clean_product(mol) + try: return Chem.MolToSmiles(mol) except Exception: @@ -154,7 +189,9 @@ def _get_product_index( for product_idx in template_reactant_to_product_mapping.values(): product_indexes.append(product_idx) + print(f"Product indexes: {product_indexes}") # Debug print + return product_indexes def _set_is_monomer_flag(self) -> int: @@ -182,10 +219,10 @@ def _smiles_to_rdkit_mol(self, smiles: str) -> Chem.Mol | None: Converts a SMILES string to an RDKit molecule object. Args: - smiles (str): The SMILES string to convert. + smiles (str): SMILES string. Returns: - Chem.Mol | None: The corresponding RDKit molecule object. + Chem.Mol | None: RDKit molecule object. """ return Chem.MolFromSmiles(smiles) From 5d86d4e9d233a1345cce4a107d67c372d6305cd1 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:34:01 -0400 Subject: [PATCH 015/176] Add index-constrained reaction progression prep --- AutoREACTER/detectors/reactions_library.py | 4 +- .../ff_wrapper/ff_wrapper.py | 3 +- .../reaction_processor/prepare_reactions.py | 199 +++++++++++++----- .../reaction_progression.py | 39 ++-- 4 files changed, 174 insertions(+), 71 deletions(-) diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py index 4dd9a14d..25f7fb9d 100644 --- a/AutoREACTER/detectors/reactions_library.py +++ b/AutoREACTER/detectors/reactions_library.py @@ -355,8 +355,8 @@ def __init__(self): "Secondary Amine and Epoxide Polyaddition (Epoxy-Amine, Second Addition / Crosslink)": { "same_reactants": False, - "reactant_1": "secondary_amine_monomer", - "reactant_2": "di_epoxy_monomer", + "reactant_1": "secondary_amine", + "reactant_2": "di_epoxide", "product": "tertiary_amine_crosslink_product", "delete_atom": False, "reaction": "[NX3H1:1]-[H:6].[CX4:2]1[OX2:5][CX4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]", diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/ff_wrapper.py b/AutoREACTER/reaction_preparation/ff_wrapper/ff_wrapper.py index b8e69d7b..6fef10a1 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/ff_wrapper.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/ff_wrapper.py @@ -1,8 +1,7 @@ from pathlib import Path from dataclasses import dataclass from typing import Optional, TYPE_CHECKING -from AutoREACTER.input_parser import SimulationSetup -from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ReactionMetadata + if TYPE_CHECKING: from AutoREACTER.session import Session diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index eeea4bd0..9a032451 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -15,12 +15,13 @@ from pathlib import Path from typing import Dict, List, Optional, TYPE_CHECKING +from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import logger from rdkit import Chem from rdkit.Chem import AllChem, Draw, rdmolops from PIL.Image import Image import pandas as pd -from AutoREACTER.detectors.reaction_detector import ReactionInstance +from AutoREACTER.detectors.reaction_detector import FunctionalGroupInfo, ReactionInstance from AutoREACTER.reaction_preparation.reaction_processor.utils import ( add_dict_as_new_columns, add_column_safe, compare_set, prepare_paths ) @@ -29,6 +30,7 @@ # Use TYPE_CHECKING to prevent circular imports with session.py if TYPE_CHECKING: from AutoREACTER.session import Session + from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ReactionProgression class MappingError(Exception): @@ -101,21 +103,35 @@ def __init__(self, session: "Session"): self.csv_cache = prepare_paths(self.cache, "csv_cache") # --- PUBLIC --- + def prepare_reactions(self, session): + prepared_reactions = self._prepare_reactions_stage(session) + session.reaction_metadata = prepared_reactions # set BEFORE progression needs it + + reaction_progression = ReactionProgression(session) + added_reaction_progression = reaction_progression.reaction_progression() - def prepare_reactions(self, session: "Session") -> list[ReactionMetadata]: + prepared_reactions.extend(added_reaction_progression) + session.reaction_metadata = prepared_reactions # update with full final list + return session + + def _prepare_reactions_stage(self, session: "Session", loop: bool = False) -> list[ReactionMetadata]: """ Main pipeline: processes reaction instances, detects duplicates, and enriches metadata with template mappings. Args: session: The main Session object containing reaction instances to process + loop: Boolean indicating whether this is a looped call (default: False) Returns: List of processed ReactionMetadata objects with template mappings and edge atoms """ - reaction_instances = session.reaction_instances - + try: + reaction_instances = session.reaction_instances + except AttributeError: + reaction_instances = session + # Process and filter reactions - reactions_metadata = self._process_reaction_instances(reaction_instances) + reactions_metadata = self._process_reaction_instances(reaction_instances, loop=loop) unique_reaction_metadata = self._detect_duplicates(reactions_metadata) for reaction in unique_reaction_metadata: @@ -162,14 +178,13 @@ def prepare_reactions(self, session: "Session") -> list[ReactionMetadata]: reaction.template_reactant_to_product_mapping = template_mapped_dict # Store the finalized metadata inside the session - session.reaction_metadata = unique_reaction_metadata - reaction_progression = ReactionProgression(session) - return unique_reaction_metadata # --- PIPELINE STEPS (PRIVATE) --- - def _process_reaction_instances(self, detected_reactions: list[ReactionInstance]) -> list[ReactionMetadata]: + def _process_reaction_instances( + self, detected_reactions: list[ReactionInstance], loop: bool = False + ) -> list[ReactionMetadata]: """ Converts ReactionInstance objects into ReactionMetadata by building molecules and running reactions. @@ -179,40 +194,89 @@ def _process_reaction_instances(self, detected_reactions: list[ReactionInstance] Returns: List of ReactionMetadata objects with atom mappings """ + + csv_cache = self.csv_cache reaction_metadata = [] for reaction in detected_reactions: + # SMARTS template associated with this detected reaction. rxn_smarts = reaction.reaction_smarts - reactant_smiles_1 = reaction.monomer_1.smiles - same_reactants = reaction.same_reactants - - # Handle case where both reactants are identical - if same_reactants: - reactant_smiles_2 = reactant_smiles_1 - else: - reactant_smiles_2 = reaction.monomer_2.smiles + if loop and (reaction.monomer_1.rdkit_mol is None or + (reaction.monomer_2 is not None and reaction.monomer_2.rdkit_mol is None)): + logger.warning( + f"Skipping reaction {reaction.reaction_name}: monomer rdkit_mol is None " + f"(likely failed sanitization upstream)." + ) + continue + same_reactants = reaction.same_reactants delete_atoms = reaction.delete_atom - # Build reaction and reactant molecules + forced_indexes_1 = None + forced_indexes_2 = None + + if loop: + # FORCED-REACTION MODE: use the actual index-scoped rdkit_mol (not a + # fresh SMILES reparse) so atom indices line up with fg_*_indexes. + # AddHs only appends new explicit H atoms at the end, so heavy-atom + # indices — the ones that matter for the FG match indices — are preserved. + mol_reactant_1 = Chem.AddHs(Chem.Mol(reaction.monomer_1.rdkit_mol)) + forced_indexes_1 = self._flatten_fg_indexes(reaction.functional_group_1) + + # Handle case where both reactants are identical + if same_reactants: + mol_reactant_2 = Chem.AddHs(Chem.Mol(reaction.monomer_1.rdkit_mol)) + else: + mol_reactant_2 = Chem.AddHs(Chem.Mol(reaction.monomer_2.rdkit_mol)) + + if reaction.functional_group_2 is not None: + forced_indexes_2 = self._flatten_fg_indexes(reaction.functional_group_2) + + # Direction is already known from the ReactionInstance (monomer_1 -> + # reactant slot 1, monomer_2 -> reactant slot 2), so unlike the normal + # path we do NOT also try the swapped ordering. + reaction_tuple = [[mol_reactant_1, mol_reactant_2]] + else: + reactant_smiles_1 = reaction.monomer_1.smiles + reactant_smiles_2 = reactant_smiles_1 if same_reactants else reaction.monomer_2.smiles + mol_reactant_1, mol_reactant_2 = self._build_reactants(reactant_smiles_1, reactant_smiles_2) + reaction_tuple = self._build_reaction_tuple(same_reactants, mol_reactant_1, mol_reactant_2) + rxn = self._build_reaction(rxn_smarts) - # This function also runs the reaction and builds metadata for each product set, including atom mappings and byproduct detection - mol_reactant_1, mol_reactant_2 = self._build_reactants(reactant_smiles_1, reactant_smiles_2) - # Build reaction tuple based on whether reactants are the same or different. If same, only one ordering is needed. If different, both orderings are processed to account for reaction directionality. - reaction_tuple = self._build_reaction_tuple(same_reactants, mol_reactant_1, mol_reactant_2) - # Process products and build metadata reaction_metadata = self._process_reaction_products( rxn, csv_cache, reaction_tuple, delete_atoms, - reaction_metadata + reaction_metadata, + forced_indexes_1=forced_indexes_1, + forced_indexes_2=forced_indexes_2, ) - + return reaction_metadata + def _flatten_fg_indexes(self, fg: Optional["FunctionalGroupInfo"]) -> Optional[set]: + """ + Flattens a FunctionalGroupInfo's recorded match indexes (fg_1_indexes and, + if present, fg_2_indexes for di_different groups) into a single allowed + atom-index set for forced-reaction checking. + + Returns None only if the FG has no recorded indexes at all (no forcing applied). + """ + if fg is None: + return None + + combined = set() + if fg.fg_1_indexes: + combined.update(atom_idx for match in fg.fg_1_indexes for atom_idx in match) + if fg.fg_2_indexes: + combined.update(atom_idx for match in fg.fg_2_indexes for atom_idx in match) + + return combined or None + + def _detect_duplicates(self, reaction_metadata_list: list[ReactionMetadata]) -> list[ReactionMetadata]: """ Filters duplicate reactions based on reactant and product molecules. @@ -238,13 +302,15 @@ def _detect_duplicates(self, reaction_metadata_list: list[ReactionMetadata]) -> return unique_metadata - def _process_reaction_products(self, - rxn: Chem.rdChemReactions.ChemicalReaction, - csv_cache: Path, - reaction_tuple: list, - delete_atoms: bool = True, - reaction_metadata: Optional[list[ReactionMetadata]] = None - ) -> list[ReactionMetadata]: + def _process_reaction_products(self, + rxn: Chem.rdChemReactions.ChemicalReaction, + csv_cache: Path, + reaction_tuple: list, + delete_atoms: bool = True, + reaction_metadata: Optional[list[ReactionMetadata]] = None, + forced_indexes_1: Optional[set] = None, + forced_indexes_2: Optional[set] = None, + ) -> list[ReactionMetadata]: """ Runs reactions on reactant pairs and builds metadata for each product set. @@ -260,16 +326,17 @@ def _process_reaction_products(self, """ if reaction_metadata is None: reaction_metadata = [] - + for pair in reaction_tuple: r1, r2 = Chem.Mol(pair[0]), Chem.Mol(pair[1]) - - # Assign unique map numbers and isotopes to track atoms through reaction + + # Assign atom map numbers and isotopes to reactants for tracking through the reaction self._assign_atom_map_numbers_and_set_isotopes(r1, r2) - # Run the reaction to get products + + # Run the reaction and get product sets products = rxn.RunReactants((r1, r2)) - - # If no products are generated, skip to the next reactant pair + + # Skip if no products were generated if not products: continue @@ -277,21 +344,18 @@ def _process_reaction_products(self, for product_set in products: df = pd.DataFrame(columns=["reactant_idx", "product_idx"]) - # Combine molecules for mapping reactant_combined = Chem.CombineMols(r1, r2) if len(product_set) == 1: product_combined = product_set[0] else: product_combined = reduce(Chem.CombineMols, product_set) - # Restore atom map numbers from isotopes (which survive the reaction) + # Reassign atom map numbers based on isotopes to recover original reactant identities self._reassign_atom_map_numbers_by_isotope(product_combined) - - # Build bidirectional atom index mappings mapping_dict, df = self._build_atom_index_mapping(reactant_combined, product_combined) reverse_mapping = {v: k for k, v in mapping_dict.items()} - # Restore map numbers for visualization + # Reveal original template map numbers for visualization and validation self._reveal_template_map_numbers(product_combined) # Validate mapping consistency @@ -299,15 +363,19 @@ def _process_reaction_products(self, # Identify atoms involved in reaction center and initiators first_shell, initiator_idxs = self._assign_first_shell_and_initiators( - reactant_combined, - product_combined, - reverse_mapping + reactant_combined, product_combined, reverse_mapping ) - # Detect byproducts (smallest fragments) + # FORCED-INDEX CHECK: discard this product if the atom that actually + # reacted isn't inside the given index set for its side. + if forced_indexes_1 is not None or forced_indexes_2 is not None: + if not self._initiators_within_forced_indexes( + initiator_idxs, r1.GetNumAtoms(), forced_indexes_1, forced_indexes_2 + ): + continue + byproduct_reactant_idxs = self._detect_byproducts(product_combined, reverse_mapping, delete_atoms) - # Combine all mapping data into single dataframe df_combined = pd.concat([ df, pd.Series(first_shell, name="first_shell"), @@ -316,14 +384,9 @@ def _process_reaction_products(self, ], axis=1).astype(pd.Int64Dtype()) total_products = len(reaction_metadata) + 1 - - # Clear isotopes before saving to restore normal chemistry self._clear_isotopes(reactant_combined, product_combined) - - # Save mapping dataframe to CSV df_combined.to_csv(csv_cache / f"reaction_{total_products}.csv", index=False) - # Create and store metadata object reaction_metadata.append( ReactionMetadata( reaction_id=total_products, @@ -345,6 +408,36 @@ def _process_reaction_products(self, return reaction_metadata # --- CORE REACTION LOGIC --- + + def _initiators_within_forced_indexes( + self, + initiator_idxs: list[int], + r1_atom_count: int, + forced_indexes_1: Optional[set], + forced_indexes_2: Optional[set], + ) -> bool: + """ + Checks whether the atoms that actually reacted (the two 'initiators') fall + within the forced index constraint for their respective side. + + Combined-mol index ranges follow Chem.CombineMols(r1, r2) ordering: + [0, r1_atom_count) belongs to r1, [r1_atom_count, ...) belongs to r2. + """ + for idx in initiator_idxs: + if idx < r1_atom_count: + if forced_indexes_1 is not None and idx not in forced_indexes_1: + return False + else: + local_idx = idx - r1_atom_count + if forced_indexes_2 is not None and local_idx not in forced_indexes_2: + return False + return True + + def _index_based_reaction_preparation(self, reaction_instances): + from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions + prepare_reactions = PrepareReactions(self.session) + prepared_reactions = prepare_reactions._prepare_reactions_stage(reaction_instances, loop=True) + return prepared_reactions def _assign_first_shell_and_initiators(self, reactant_combined: Chem.Mol, diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 5b52789c..75ac270b 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -11,6 +11,7 @@ if TYPE_CHECKING: from AutoREACTER.session import Session from AutoREACTER.detectors.functional_groups_detector import MonomerRole + from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ReactionInstance, ReactionMetadata @dataclass(slots=True) @@ -40,13 +41,10 @@ class ReactionProgression: def __init__(self, session: "Session"): self.session = session self.session.reaction_progression_session = ReactionProgressionSession() - self.fg_detector = FunctionalGroupsDetector() self.rxn_detector = ReactionDetector() - self.reaction_progression() - - def reaction_progression(self, max_loop: int = MAX_LOOP) -> None: + def reaction_progression(self, max_loop: int = MAX_LOOP) -> list["ReactionMetadata"]: """ Progresses the reaction by iteratively applying detected chemistries to the session's molecules. @@ -101,10 +99,25 @@ def reaction_progression(self, max_loop: int = MAX_LOOP) -> None: print(len(reaction_instances)) # Debug print print(monomer_roles_in_loop) # Debug print - - if self._loop_break_condition(size_of_pool): - break - + prepared_reactions = self._index_based_reaction_preparation( + reaction_instances=reaction_instances + ) + print(prepared_reactions) # Debug print + if self._loop_break_condition( + size_before=size_of_pool, size_after=len(monomer_roles_in_loop) + ): + return prepared_reactions + return prepared_reactions + + def _index_based_reaction_preparation( + self, reaction_instances: list["ReactionInstance"] + ) -> list["ReactionMetadata"]: + from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions + + prepare_reactions = PrepareReactions(self.session) + prepared_reactions = prepare_reactions._prepare_reactions_stage(reaction_instances) + return prepared_reactions + def _prepare_products_for_idx_based_fg_detection( self, ) -> list[MonomerRoleforIndexBasedFGDetection]: @@ -226,13 +239,11 @@ def _smiles_to_rdkit_mol(self, smiles: str) -> Chem.Mol | None: """ return Chem.MolFromSmiles(smiles) - def _loop_break_condition(self, size_of_pool: int) -> bool: - if size_of_pool <= len(self.session.monomer_roles): + def _loop_break_condition(self, size_before: int, size_after: int) -> bool: + if size_after <= size_before: print( - f"Breaking the loop as the size of the pool ({size_of_pool}) " - f"is less than or equal to the number of monomer roles " - f"({len(self.session.monomer_roles)})." + f"Breaking the loop as the pool did not grow " + f"(before={size_before}, after={size_after})." ) return True - return False \ No newline at end of file From 5004246d6458c0eac31bf8b961e0d8fda742e793 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:39:54 -0400 Subject: [PATCH 016/176] Refactor prepare_reactions.py code style Clean up whitespace, trailing spaces, and newlines throughout the file. Reorganize section comments for better clarity (e.g., rename '--- PUBLIC ---' and '--- PIPELINE STEPS (PRIVATE) ---' to more descriptive headers). Reorder `_detect_duplicates` and `_flatten_fg_indexes` methods. Add missing newline at end of file. --- .../reaction_processor/prepare_reactions.py | 249 +++++++++--------- 1 file changed, 131 insertions(+), 118 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 9a032451..bce72c85 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -3,7 +3,7 @@ reaction metadata extraction, and visualization utilities using RDKit. This module processes reaction SMARTS, applies atom mappings, identifies key reaction features (e.g., first shell, -initiators, byproducts), and generates metadata and visualizations for downstream analysis. It also includes validation checks to ensure mapping +initiators, byproducts), and generates metadata and visualizations for downstream analysis. It also includes validation checks to ensure mapping consistency and completeness. """ @@ -44,7 +44,7 @@ class SMARTSParsingError(Exception): @dataclass(slots=True) class ReactionMetadata: """ - Stores comprehensive metadata for a single reaction including molecular structures, + Stores comprehensive metadata for a single reaction including molecular structures, atom mappings, and analysis results. reaction_id: Unique identifier for the reaction instance reactant_combined_mol: RDKit molecule object representing combined reactants @@ -92,6 +92,8 @@ class ReactionMetadata: class PrepareReactions: """Processes chemical reactions: builds atom mappings, identifies reaction centers, and detects byproducts.""" + # --- INITIALIZATION AND PUBLIC WORKFLOW --- + def __init__(self, session: "Session"): """Initialize using the shared AutoREACTER session object.""" self.session = session @@ -102,7 +104,6 @@ def __init__(self, session: "Session"): self.cache = self.staging_dir self.csv_cache = prepare_paths(self.cache, "csv_cache") - # --- PUBLIC --- def prepare_reactions(self, session): prepared_reactions = self._prepare_reactions_stage(session) session.reaction_metadata = prepared_reactions # set BEFORE progression needs it @@ -117,11 +118,11 @@ def prepare_reactions(self, session): def _prepare_reactions_stage(self, session: "Session", loop: bool = False) -> list[ReactionMetadata]: """ Main pipeline: processes reaction instances, detects duplicates, and enriches metadata with template mappings. - + Args: session: The main Session object containing reaction instances to process loop: Boolean indicating whether this is a looped call (default: False) - + Returns: List of processed ReactionMetadata objects with template mappings and edge atoms """ @@ -133,27 +134,27 @@ def _prepare_reactions_stage(self, session: "Session", loop: bool = False) -> li # Process and filter reactions reactions_metadata = self._process_reaction_instances(reaction_instances, loop=loop) unique_reaction_metadata = self._detect_duplicates(reactions_metadata) - + for reaction in unique_reaction_metadata: # Skip reactions marked as duplicates if not reaction.activity_stats: continue - + combined_reactant_molecule_object = reaction.reactant_combined_RDmol reaction_dataframe = reaction.reaction_dataframe csv_save_path = reaction.csv_path - + # Build full atom mapping dictionary from dataframe fully_mapped_dict = reaction_dataframe.set_index("reactant_idx")["product_idx"].to_dict() first_shell = reaction_dataframe["first_shell"].dropna().tolist() - + # Generate template mapping by walking reaction graph template_mapped_dict, edge_atoms = reaction_atom_walker( combined_reactant_molecule_object, first_shell, fully_mapped_dict ) - + # Add template mapping and edge atoms to dataframe reaction_dataframe = add_dict_as_new_columns( reaction_dataframe, @@ -167,7 +168,7 @@ def _prepare_reactions_stage(self, session: "Session", loop: bool = False) -> li edge_atoms, "edge_atoms" ) - + # Save updated dataframe back to CSV and update metadata reaction.reaction_dataframe = reaction_dataframe.copy() # Save the updated dataframe with template mappings and edge atoms to CSV @@ -179,23 +180,24 @@ def _prepare_reactions_stage(self, session: "Session", loop: bool = False) -> li # Store the finalized metadata inside the session return unique_reaction_metadata - - # --- PIPELINE STEPS (PRIVATE) --- - + + + # --- REACTION INSTANCE AND PRODUCT PROCESSING --- + def _process_reaction_instances( self, detected_reactions: list[ReactionInstance], loop: bool = False ) -> list[ReactionMetadata]: """ Converts ReactionInstance objects into ReactionMetadata by building molecules and running reactions. - + Args: detected_reactions: List of detected reaction instances - + Returns: List of ReactionMetadata objects with atom mappings """ - + csv_cache = self.csv_cache reaction_metadata = [] @@ -257,51 +259,6 @@ def _process_reaction_instances( return reaction_metadata - def _flatten_fg_indexes(self, fg: Optional["FunctionalGroupInfo"]) -> Optional[set]: - """ - Flattens a FunctionalGroupInfo's recorded match indexes (fg_1_indexes and, - if present, fg_2_indexes for di_different groups) into a single allowed - atom-index set for forced-reaction checking. - - Returns None only if the FG has no recorded indexes at all (no forcing applied). - """ - if fg is None: - return None - - combined = set() - if fg.fg_1_indexes: - combined.update(atom_idx for match in fg.fg_1_indexes for atom_idx in match) - if fg.fg_2_indexes: - combined.update(atom_idx for match in fg.fg_2_indexes for atom_idx in match) - - return combined or None - - - def _detect_duplicates(self, reaction_metadata_list: list[ReactionMetadata]) -> list[ReactionMetadata]: - """ - Filters duplicate reactions based on reactant and product molecules. - - Args: - reaction_metadata_list: List of reaction metadata to filter - - Returns: - List of unique reactions; duplicates marked with activity_stats=False - """ - unique_metadata: list[ReactionMetadata] = [] - - for reaction in reaction_metadata_list: - # Compare current reaction's reactants and products against unique reactions collected so far - reactants = reaction.reactant_combined_RDmol - products = reaction.product_combined_RDmol - - # Keep reaction if it's unique, otherwise mark as duplicate - if compare_set(unique_metadata, reactants, products): - unique_metadata.append(reaction) - else: - reaction.activity_stats = False - - return unique_metadata - def _process_reaction_products(self, rxn: Chem.rdChemReactions.ChemicalReaction, csv_cache: Path, @@ -313,14 +270,14 @@ def _process_reaction_products(self, ) -> list[ReactionMetadata]: """ Runs reactions on reactant pairs and builds metadata for each product set. - + Args: rxn: RDKit ChemicalReaction object csv_cache: Path to cache directory for saving CSVs reaction_tuple: List of reactant pairs to process delete_atoms: Whether to detect and track byproducts reaction_metadata: Accumulator list for metadata objects - + Returns: Updated list of ReactionMetadata objects """ @@ -339,7 +296,7 @@ def _process_reaction_products(self, # Skip if no products were generated if not products: continue - + # Process each product set generated by the reaction for product_set in products: df = pd.DataFrame(columns=["reactant_idx", "product_idx"]) @@ -406,8 +363,54 @@ def _process_reaction_products(self, ) return reaction_metadata - - # --- CORE REACTION LOGIC --- + + + def _detect_duplicates(self, reaction_metadata_list: list[ReactionMetadata]) -> list[ReactionMetadata]: + """ + Filters duplicate reactions based on reactant and product molecules. + + Args: + reaction_metadata_list: List of reaction metadata to filter + + Returns: + List of unique reactions; duplicates marked with activity_stats=False + """ + unique_metadata: list[ReactionMetadata] = [] + + for reaction in reaction_metadata_list: + # Compare current reaction's reactants and products against unique reactions collected so far + reactants = reaction.reactant_combined_RDmol + products = reaction.product_combined_RDmol + + # Keep reaction if it's unique, otherwise mark as duplicate + if compare_set(unique_metadata, reactants, products): + unique_metadata.append(reaction) + else: + reaction.activity_stats = False + + return unique_metadata + + + # --- PROGRESSION AND FORCED-INDEX HANDLING --- + + def _flatten_fg_indexes(self, fg: Optional["FunctionalGroupInfo"]) -> Optional[set]: + """ + Flattens a FunctionalGroupInfo's recorded match indexes (fg_1_indexes and, + if present, fg_2_indexes for di_different groups) into a single allowed + atom-index set for forced-reaction checking. + + Returns None only if the FG has no recorded indexes at all (no forcing applied). + """ + if fg is None: + return None + + combined = set() + if fg.fg_1_indexes: + combined.update(atom_idx for match in fg.fg_1_indexes for atom_idx in match) + if fg.fg_2_indexes: + combined.update(atom_idx for match in fg.fg_2_indexes for atom_idx in match) + + return combined or None def _initiators_within_forced_indexes( self, @@ -432,29 +435,33 @@ def _initiators_within_forced_indexes( if forced_indexes_2 is not None and local_idx not in forced_indexes_2: return False return True - + + def _index_based_reaction_preparation(self, reaction_instances): from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions prepare_reactions = PrepareReactions(self.session) prepared_reactions = prepare_reactions._prepare_reactions_stage(reaction_instances, loop=True) return prepared_reactions - - def _assign_first_shell_and_initiators(self, - reactant_combined: Chem.Mol, - product_combined: Chem.Mol, + + + # --- REACTION-CENTER ANALYSIS AND VALIDATION --- + + def _assign_first_shell_and_initiators(self, + reactant_combined: Chem.Mol, + product_combined: Chem.Mol, reversed_mapping_dict: dict[int, int]) -> tuple[list[int], list[int]]: """ Identifies atoms in the first coordination shell (atoms with map numbers < 999) and initiator atoms. Initiators are atoms with map numbers 1 or 2 (typically the reactive centers). - + Args: reactant_combined: Combined reactant molecule product_combined: Combined product molecule reversed_mapping_dict: Product idx -> Reactant idx mapping - + Returns: Tuple of (first_shell atom indices, initiator atom indices) - + Raises: ValueError: If exactly 2 initiators are not found """ @@ -478,24 +485,25 @@ def _assign_first_shell_and_initiators(self, # Initiators are atoms with map numbers 1 or 2 if p_atom.GetAtomMapNum() in [1, 2]: initiator_idxs.append(r_idx) - + if len(initiator_idxs) != 2: raise ValueError(f"Expected 2 initiators, got {len(initiator_idxs)}: {initiator_idxs}") return first_shell, initiator_idxs - - def _detect_byproducts(self, - product_combined: Chem.Mol, - reversed_mapping_dict: dict[int, int], + + + def _detect_byproducts(self, + product_combined: Chem.Mol, + reversed_mapping_dict: dict[int, int], delete_atoms: bool) -> list[int]: """ Identifies byproduct atoms (smallest molecular fragment) and maps them back to reactant space. - + Args: product_combined: Combined product molecule reversed_mapping_dict: Product idx -> Reactant idx mapping delete_atoms: Whether to perform byproduct detection - + Returns: List of reactant indices corresponding to byproduct atoms """ @@ -504,7 +512,7 @@ def _detect_byproducts(self, # Get tuples of original atom indices for each fragment frags_indices = rdmolops.GetMolFrags(product_combined) - + # Find the tuple with the smallest number of atoms smallest_frag_indices = min(frags_indices, key=len) @@ -516,16 +524,17 @@ def _detect_byproducts(self, byproduct_reactant_indices.append(reversed_mapping_dict[p_idx]) return byproduct_reactant_indices - + + def _validate_mapping(self, df: pd.DataFrame, reactant: Chem.Mol, product: Chem.Mol) -> None: """ Validates atom mapping consistency: checks for required columns, duplicates, bounds, and completeness. - + Args: df: Dataframe containing reactant_idx and product_idx columns reactant: Reactant molecule product: Product molecule - + Raises: MappingError: If any validation check fails """ @@ -565,12 +574,12 @@ def _validate_mapping(self, df: pd.DataFrame, reactant: Chem.Mol, product: Chem. raise MappingError(f"Mapping validation error: incomplete mapping for product.") # --- ATOM MAPPING --- - + def _assign_atom_map_numbers_and_set_isotopes(self, r1: Chem.Mol, r2: Chem.Mol) -> None: """ Assigns unique map numbers and isotopes to reactant atoms for tracking through reaction. Isotopes survive RDKit's reaction engine, allowing atom identity recovery post-reaction. - + Args: r1: First reactant molecule r2: Second reactant molecule @@ -586,12 +595,13 @@ def _assign_atom_map_numbers_and_set_isotopes(self, r1: Chem.Mol, r2: Chem.Mol) idx = 2001 + atom.GetIdx() atom.SetAtomMapNum(idx) atom.SetIsotope(idx) # Isotope survives the reaction - + + def _reassign_atom_map_numbers_by_isotope(self, mol: Chem.Mol) -> None: """ Restores atom map numbers from isotope values after reaction. RDKit's reaction engine preserves isotopes, allowing recovery of original atom identities. - + Args: mol: Product molecule with isotope information """ @@ -601,28 +611,28 @@ def _reassign_atom_map_numbers_by_isotope(self, mol: Chem.Mol) -> None: atom.SetAtomMapNum(surviving_idx) # Restore original map number atom.SetIsotope(0) # Clear isotope to restore normal chemistry - def _build_atom_index_mapping(self, - reactant_combined: Chem.Mol, + def _build_atom_index_mapping(self, + reactant_combined: Chem.Mol, product_combined: Chem.Mol) -> tuple[dict[int, int], pd.DataFrame]: """ Builds bidirectional atom index mapping between reactants and products using map numbers. - + Args: reactant_combined: Combined reactant molecule product_combined: Combined product molecule - + Returns: Tuple of (mapping dict: reactant_idx -> product_idx, dataframe with mapping) """ mapping_dict = {} - + # Pre-index product atoms by map number for O(1) lookup product_map = { atom.GetAtomMapNum(): atom.GetIdx() for atom in product_combined.GetAtoms() if atom.GetAtomMapNum() != 0 } - + rows = [] for r_atom in reactant_combined.GetAtoms(): r_map_num = r_atom.GetAtomMapNum() @@ -645,7 +655,7 @@ def _reveal_template_map_numbers(self, mol: Chem.Mol) -> None: """ Restores map numbers from RDKit's internal 'old_mapno' property for visualization. RDKit stores original map numbers in this property after reaction execution. - + Args: mol: Product molecule """ @@ -657,7 +667,7 @@ def _reveal_template_map_numbers(self, mol: Chem.Mol) -> None: def _clear_isotopes(self, mol_1: Chem.Mol, mol_2: Chem.Mol) -> None: """ Clears isotope values from molecules to restore normal chemistry after using isotopes for atom tracking. - + Args: mol_1: First molecule to clear mol_2: Second molecule to clear @@ -667,20 +677,21 @@ def _clear_isotopes(self, mol_1: Chem.Mol, mol_2: Chem.Mol) -> None: for atom in mol_2.GetAtoms(): atom.SetIsotope(0) - # --- BUILDERS --- - + # --- REACTION AND REACTANT BUILDERS --- + def _build_reaction(self, rxn_smarts: str) -> Chem.rdChemReactions.ChemicalReaction: """Builds RDKit ChemicalReaction object from SMARTS string.""" return AllChem.ReactionFromSmarts(rxn_smarts) - + + def _build_reactants(self, reactant_smiles_1: str, reactant_smiles_2: str) -> tuple[Chem.Mol, Chem.Mol]: """ Builds reactant molecules from SMILES strings with explicit hydrogens added. - + Args: reactant_smiles_1: SMILES string for first reactant reactant_smiles_2: SMILES string for second reactant - + Returns: Tuple of (reactant1 molecule, reactant2 molecule) with explicit hydrogens """ @@ -688,24 +699,25 @@ def _build_reactants(self, reactant_smiles_1: str, reactant_smiles_2: str) -> tu if mol_reactant_1 is None: raise SMARTSParsingError(f"Failed to parse first reactant SMILES: {reactant_smiles_1!r}") mol_reactant_1 = Chem.AddHs(mol_reactant_1) - + mol_reactant_2 = Chem.MolFromSmiles(reactant_smiles_2) if mol_reactant_2 is None: raise SMARTSParsingError(f"Failed to parse second reactant SMILES: {reactant_smiles_2!r}") mol_reactant_2 = Chem.AddHs(mol_reactant_2) - + return mol_reactant_1, mol_reactant_2 - + + def _build_reaction_tuple(self, same_reactants: bool, mol_reactant_1: Chem.Mol, mol_reactant_2: Chem.Mol) -> list: """ Builds list of reactant pairs to process. If reactants are identical, returns single pair. Otherwise returns both orderings to account for reaction directionality. - + Args: same_reactants: Whether both reactants are identical mol_reactant_1: First reactant molecule mol_reactant_2: Second reactant molecule - + Returns: List of reactant pairs [[r1, r2], ...] to process """ @@ -713,16 +725,17 @@ def _build_reaction_tuple(self, same_reactants: bool, mol_reactant_1: Chem.Mol, return [[mol_reactant_1, mol_reactant_1]] return [[mol_reactant_1, mol_reactant_2], [mol_reactant_2, mol_reactant_1]] - - # --- HELPERS --- - + + + # --- GENERAL HELPERS --- + def _is_consecutive(self, num_list: list[int]) -> bool: """ Checks if list contains consecutive integers with no duplicates. - + Args: num_list: List of integers to check - + Returns: True if list is consecutive and has no duplicates, False otherwise """ @@ -735,7 +748,7 @@ def _is_consecutive(self, num_list: list[int]) -> bool: ) # --- VISUALIZATION --- - + def reaction_templates_highlighted_image_grid( self, session: "Session", @@ -743,11 +756,11 @@ def reaction_templates_highlighted_image_grid( ) -> Image: """ Generates grid image of reactions with highlighted atoms based on type. - + Args: session: The Session object containing reaction metadata to visualize highlight_type: Type of atoms to highlight - "template", "edge", "initiators", or "delete" - + Returns: PIL Image containing 2-column grid of reactant-product pairs with highlighted atoms """ @@ -798,7 +811,7 @@ def reaction_templates_highlighted_image_grid( color_map[a] = (1.0, 0.0, 0.0) # red mols.extend([reactant, product]) - + # Build atom mappings for highlighting forward_map = metadata.reactant_to_product_mapping reactant_atoms = atoms @@ -828,4 +841,4 @@ def reaction_templates_highlighted_image_grid( subImgSize=(400, 400), useSVG=False, ) - return img \ No newline at end of file + return img From 1fa9111e45e0625213a624ccefc9f7ee47f4a505 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:09:19 -0400 Subject: [PATCH 017/176] Fix product idx remapping for multi-fragment products Refactors _get_product_index into _get_product_idxs, which now also returns the (possibly trimmed) product molecule. When a reaction produces multiple disconnected fragments, only the largest heavy-atom fragment is kept and product atom indices are remapped accordingly. Also fixes _clean_product to operate on a copy so the original molecule is not mutated, and updates _get_product_smiles to use the cleaned copy. Adds a glycine test example JSON. --- .../reaction_processor/prepare_reactions.py | 5 +- .../reaction_progression.py | 123 ++++++++++++++---- examples/test_glycine.json | 19 +++ 3 files changed, 121 insertions(+), 26 deletions(-) create mode 100644 examples/test_glycine.json diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index bce72c85..69eeed6c 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -8,7 +8,7 @@ """ # WARNING: -# When modifying this file for dataframe or any other indexing variables use idx and idxs, do not use index or indices or similar. +# When modifying this file for dataframe or any other indexing variables use idx and idxs, do not use index or indices or similar. Mapping validation error from dataclasses import dataclass from functools import reduce @@ -570,9 +570,10 @@ def _validate_mapping(self, df: pd.DataFrame, reactant: Chem.Mol, product: Chem. # All atoms must be mapped (complete mapping) if len(r_idxs) != reactant.GetNumAtoms(): raise MappingError(f"Mapping validation error: incomplete mapping for reactant.") + # pass if len(p_idxs) != product.GetNumAtoms(): raise MappingError(f"Mapping validation error: incomplete mapping for product.") - + # pass # --- ATOM MAPPING --- def _assign_atom_map_numbers_and_set_isotopes(self, r1: Chem.Mol, r2: Chem.Mol) -> None: diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 75ac270b..fc832b5c 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -129,14 +129,15 @@ def _prepare_products_for_idx_based_fg_detection( for reaction in reaction_metadata: product_mol = reaction.product_combined_RDmol - + indexes_in_template, product_mol = self._get_product_idxs( + reaction.template_reactant_to_product_mapping, + product_mol + ) monomer_roles_for_idx_based_fg_detection.append( MonomerRoleforIndexBasedFGDetection( smiles=self._get_product_smiles(product_mol), name=f"new_{reaction.reaction_id}", - indexes_in_template=self._get_product_index( - reaction.template_reactant_to_product_mapping - ), + indexes_in_template=indexes_in_template, is_monomer=False, is_looped=False, rdkit_mol=self._sanitize_molecule(product_mol), @@ -165,47 +166,121 @@ def _sanitize_molecule(self, mol: Chem.Mol) -> Chem.Mol | None: def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: """ - Removes atom map numbers and isotope labels from a product molecule. + Return a copy of the molecule with atom-map numbers and isotope + labels removed. + + The input molecule is not modified. """ - for atom in mol.GetAtoms(): + cleaned_mol = Chem.Mol(mol) + + for atom in cleaned_mol.GetAtoms(): atom.SetAtomMapNum(0) atom.SetIsotope(0) - return mol + return cleaned_mol + def _get_product_smiles(self, mol: Chem.Mol) -> str: """ - Converts an RDKit molecule object to its corresponding SMILES string. + Convert a product molecule to SMILES without modifying the + original RDKit molecule. """ - self._clean_product(mol) + cleaned_mol = self._clean_product(mol) try: - return Chem.MolToSmiles(mol) + return Chem.MolToSmiles(cleaned_mol) except Exception: return "" - def _get_product_index( + + def _get_product_idxs( self, - template_reactant_to_product_mapping: dict, - ) -> list[int]: + template_reactant_to_product_mapping: dict[int, int], + mol: Chem.Mol, + ) -> tuple[list[int], Chem.Mol]: """ - Retrieves product indexes from the reactant-to-product mapping. - - Args: - template_reactant_to_product_mapping (dict): Mapping from reactant - indices to product indices. + Retrieve mapped product atom idxs and keep only the largest + molecular fragment when the product contains multiple fragments. Returns: - list[int]: Corresponding product indexes. + A tuple containing: + - Product atom idxs relative to the returned molecule. + - The complete product or its largest fragment. """ - product_indexes = [] + product = Chem.Mol(mol) - for product_idx in template_reactant_to_product_mapping.values(): - product_indexes.append(product_idx) + product_idxs = list( + template_reactant_to_product_mapping.values() + ) + + if len(Chem.GetMolFrags(product)) > 1: + product, product_idxs = self._keep_largest_fragment( + product, + product_idxs, + ) - print(f"Product indexes: {product_indexes}") # Debug print + print(f"Product idxs: {product_idxs}") - return product_indexes + return product_idxs, product + + + def _keep_largest_fragment( + self, + mol: Chem.Mol, + product_idxs: list[int], + ) -> tuple[Chem.Mol, list[int]]: + """ + Keep the fragment with the largest number of heavy atoms and + remap product atom idxs to the retained fragment. + + Args: + mol: + Molecule containing one or more disconnected fragments. + product_idxs: + Product atom idxs referring to the original molecule. + + Returns: + A tuple containing: + - The largest fragment. + - Product atom idxs remapped to the largest fragment. + """ + fragment_atom_mappings: list[tuple[int, ...]] = [] + + fragments = Chem.GetMolFrags( + mol, + asMols=True, + sanitizeFrags=True, + fragsMolAtomMapping=fragment_atom_mappings, + ) + + if not fragments: + raise ValueError("No fragments found in the product molecule.") + + largest_fragment_position = max( + range(len(fragments)), + key=lambda position: fragments[position].GetNumHeavyAtoms(), + ) + + largest_fragment = fragments[largest_fragment_position] + + # The atom mapping stores: + # new fragment idx -> original molecule idx. + original_atom_idxs = fragment_atom_mappings[ + largest_fragment_position + ] + + original_to_new_idx = { + original_idx: new_idx + for new_idx, original_idx in enumerate(original_atom_idxs) + } + + remapped_product_idxs = [ + original_to_new_idx[product_idx] + for product_idx in product_idxs + if product_idx in original_to_new_idx + ] + + return largest_fragment, remapped_product_idxs def _set_is_monomer_flag(self) -> int: """ diff --git a/examples/test_glycine.json b/examples/test_glycine.json new file mode 100644 index 00000000..33c5da9f --- /dev/null +++ b/examples/test_glycine.json @@ -0,0 +1,19 @@ +{ + "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "simulations": [ + { + "tag": "epoxy_test", + "temperature": 300, + "density": 1.0, + "monomer_counts": { + "di_epoxy": 200 + } + } + ], + "monomers": [ + { + "name": "di_epoxy", + "smiles": "NCC(=O)O" + } + ] +} \ No newline at end of file From 7f77e7e8f2b61c9b11786522ee14e66da13c6a35 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:16:58 -0400 Subject: [PATCH 018/176] Remove unused detectors and processor files Delete placeholder/incomplete files: empty functional_groups_rules.json, reaction_rules.json, detected_chemistry_filter.py (contained unfinished logic with syntax errors), and species_pool.py. --- .../detectors/functional_groups_rules.json | 0 AutoREACTER/detectors/reaction_rules.json | 15 --- .../detected_chemistry_filter.py | 107 ------------------ .../reaction_processor/species_pool.py | 41 ------- 4 files changed, 163 deletions(-) delete mode 100644 AutoREACTER/detectors/functional_groups_rules.json delete mode 100644 AutoREACTER/detectors/reaction_rules.json delete mode 100644 AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py delete mode 100644 AutoREACTER/reaction_preparation/reaction_processor/species_pool.py diff --git a/AutoREACTER/detectors/functional_groups_rules.json b/AutoREACTER/detectors/functional_groups_rules.json deleted file mode 100644 index e69de29b..00000000 diff --git a/AutoREACTER/detectors/reaction_rules.json b/AutoREACTER/detectors/reaction_rules.json deleted file mode 100644 index 14931501..00000000 --- a/AutoREACTER/detectors/reaction_rules.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "multi_step_reactions": [ - { - "name": "epoxy_polymerization", - "if_reactions": "Amine Epoxy Addition First Stage", - "required_reactions": [ - "Amine Epoxy Addition Second Stage" - ] - , - "fg_additon": { - "primary_amine": "secondary_amine" - } - } - ] -} \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py b/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py deleted file mode 100644 index 64700420..00000000 --- a/AutoREACTER/reaction_preparation/reaction_processor/detected_chemistry_filter.py +++ /dev/null @@ -1,107 +0,0 @@ -from __future__ import annotations # 1. Must be the first line - -from dataclasses import dataclass -from typing import TYPE_CHECKING, Optional -import json -from importlib.resources import files - -if TYPE_CHECKING: - from AutoREACTER.session import Session - - -@dataclass(slots=True) -class DetectedChemistries: - functional_groups: list[str] # Unique functional group SMARTS detected in available reactions - reactions: dict[str, str] # reaction_name -> reaction_smarts - - - -class DetectedChemistryFilter: - """ - Collects available detected chemistry from reaction instances. - - This class extracts: - - unique functional group SMARTS used by detected reactions - - unique reaction names and their reaction SMARTS - """ - - def __init__(self, session: Session): - self.reaction_instances = session.reaction_instances or [] - - def _add_to_the_list(self, list_to_add: list[str], item: Optional[str]) -> None: - """ - Adds an item to the list if it is not None and not already present. - """ - if item is not None and item not in list_to_add: - list_to_add.append(item) - - def _add_to_the_dict(self, dict_to_add: dict[str, str], key: str, value: str) -> None: - """ - Adds a key-value pair to the dictionary if the key is not already present. - """ - if key not in dict_to_add: - dict_to_add[key] = value - - def filter(self) -> DetectedChemistries: - """ - Extracts available functional group SMARTS and reaction SMARTS - from detected reaction instances. - - Returns: - DetectedChemistries: Available functional groups and reactions. - """ - available_functional_groups: list[str] = [] - available_reactions: dict[str, str] = {} - - for reaction_instance in self.reaction_instances: - reaction_name = reaction_instance.reaction_name - reaction_smarts = reaction_instance.reaction_smarts - - self._add_to_the_dict( - available_reactions, - reaction_name, - reaction_smarts, - ) - - functional_group_1 = reaction_instance.functional_group_1 - self._add_to_the_list( - available_functional_groups, - functional_group_1.fg_smarts_1, - ) - self._add_to_the_list( - available_functional_groups, - functional_group_1.fg_smarts_2, - ) - - functional_group_2 = reaction_instance.functional_group_2 - if functional_group_2 is not None: - self._add_to_the_list( - available_functional_groups, - functional_group_2.fg_smarts_1, - ) - self._add_to_the_list( - available_functional_groups, - functional_group_2.fg_smarts_2, - ) - rules = self._add_progessive_chemistries() - for reaction in available_reactions: - for rule in rules: - print(f"yet to implement for reaction: {reaction}, rule: {rule}" - in here we need to add functional groups with meta data - and then add to the set. - ) - return DetectedChemistries( - functional_groups=available_functional_groups, - reactions=available_reactions, - ) - - - - - def _add_progessive_chemistries(): - rules_file = files("AutoREACTER.detectors").joinpath("reaction_rules.json") - - with rules_file.open("r", encoding="utf-8") as file: - reaction_rules = json.load(file) - rules = reaction_rules["multi_step_reactions"] - return rules \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py b/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py deleted file mode 100644 index 11768f29..00000000 --- a/AutoREACTER/reaction_preparation/reaction_processor/species_pool.py +++ /dev/null @@ -1,41 +0,0 @@ -from __future__ import annotations - -from dataclasses import dataclass, field -from rdkit import Chem -from typing import Optional - -@dataclass(slots=True) -class PoolSpecies: - """ - Represents a species in the reaction pool. - Attributes: - species_id (str): The unique identifier of the species. - is_monomer (bool): Indicates whether the species is a monomer. - smiles (Optional[str]): The SMILES representation of the species. - mol (Optional[Chem.Mol]): The RDKit Mol object of the species. - template_idxes (Optional[list[int]]): The list of atom indices used as a template. - """ - species_id: str - is_monomer: bool - smiles: Optional[str] = None - mol: Optional[Chem.Mol] = None - template_idxes: Optional[list[int]] = None - - -def _populate_mols(pool: list[PoolSpecies]) -> list[PoolSpecies]: - """ - Populate the `mol` and `template_idxes` attributes of each monomer species in the pool based on its SMILES string. - Args: - pool (list[PoolSpecies]): The list of species in the pool. - - Returns: - list[PoolSpecies]: The updated list of species with populated `mol` and `template_idxes` attributes. - """ - for species in pool: - if species.smiles and species.mol is None and species.is_monomer: - species.mol = Chem.MolFromSmiles(species.smiles) - atoms = [] - for atom in species.mol.GetAtoms(): - atoms.append(atom.GetIdx()) - species.template_idxes = atoms - return pool From fcfe4a0ebf0cbd45293b613d41bf4a116cb9ff41 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 10 Jul 2026 16:25:05 -0400 Subject: [PATCH 019/176] Add DeduplicationDetector for reactions Introduces DeduplicationDetector, which converts LAMMPS molecule-template files to NetworkX graphs and uses graph isomorphism (matching atom and bond types) to identify duplicate pre/post reaction pairs. --- .../deduplication_detector.py | 309 ++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 AutoREACTER/reaction_preparation/deduplication_detector.py diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py new file mode 100644 index 00000000..6d73eb24 --- /dev/null +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -0,0 +1,309 @@ +import os +from pathlib import Path + +import networkx as nx + + +class DeduplicationDetector: + def __init__(self): + # Graphs are not hashable, so store reaction graph pairs in a list. + self.seen_reactions: list[tuple[nx.Graph, nx.Graph]] = [] + + def is_duplicate( + self, + pre_template_graph: nx.Graph, + post_template_graph: nx.Graph, + ) -> bool: + """ + Check whether a pre/post reaction graph pair has already been seen. + + Atom types and bond types are included in the graph comparison. + Coordinates are intentionally ignored because the same molecular + topology can have different coordinates. + """ + node_match = nx.algorithms.isomorphism.categorical_node_match( + "atom_type", + None, + ) + edge_match = nx.algorithms.isomorphism.categorical_edge_match( + "bond_type", + None, + ) + + for seen_pre_graph, seen_post_graph in self.seen_reactions: + pre_matches = nx.is_isomorphic( + pre_template_graph, + seen_pre_graph, + node_match=node_match, + edge_match=edge_match, + ) + + if not pre_matches: + continue + + post_matches = nx.is_isomorphic( + post_template_graph, + seen_post_graph, + node_match=node_match, + edge_match=edge_match, + ) + + if post_matches: + return True + + self.seen_reactions.append( + ( + pre_template_graph.copy(), + post_template_graph.copy(), + ) + ) + + return False + + def lammps_molecule_to_networkx( + self, + file_path: str | Path, + ) -> nx.Graph: + """ + Convert a LAMMPS molecule-template file into a NetworkX graph. + + Supported sections: + Types + Coords + Bonds + """ + file_path = Path(file_path) + + if not file_path.exists(): + raise FileNotFoundError( + f"Molecule file does not exist: {file_path}" + ) + + sections = self._read_sections(file_path) + + atom_mapping: dict[int, str] = {} + coord_mapping: dict[int, tuple[float, float, float]] = {} + bond_mapping: dict[int, tuple[str, int, int]] = {} + + for line in sections.get("Types", []): + atom_data = line.split() + + if len(atom_data) < 2: + raise ValueError( + f"Invalid Types line in {file_path}: {line!r}" + ) + + atom_id = int(atom_data[0]) + atom_type = atom_data[1] + atom_mapping[atom_id] = atom_type + + for line in sections.get("Coords", []): + coord_data = line.split() + + if len(coord_data) < 4: + raise ValueError( + f"Invalid Coords line in {file_path}: {line!r}" + ) + + atom_id = int(coord_data[0]) + x = float(coord_data[1]) + y = float(coord_data[2]) + z = float(coord_data[3]) + + coord_mapping[atom_id] = (x, y, z) + + for line in sections.get("Bonds", []): + bond_data = line.split() + + if len(bond_data) < 4: + raise ValueError( + f"Invalid Bonds line in {file_path}: {line!r}" + ) + + bond_id = int(bond_data[0]) + bond_type = bond_data[1] + atom1_id = int(bond_data[2]) + atom2_id = int(bond_data[3]) + + bond_mapping[bond_id] = ( + bond_type, + atom1_id, + atom2_id, + ) + + graph = nx.Graph() + + for atom_id, atom_type in atom_mapping.items(): + if atom_id not in coord_mapping: + raise ValueError( + f"Atom {atom_id} has a type but no coordinates " + f"in {file_path}." + ) + + graph.add_node( + atom_id, + atom_type=atom_type, + coords=coord_mapping[atom_id], + ) + + for bond_id, bond_data in bond_mapping.items(): + bond_type, atom1_id, atom2_id = bond_data + + if atom1_id not in graph or atom2_id not in graph: + raise ValueError( + f"Bond {bond_id} references an undefined atom " + f"in {file_path}." + ) + + graph.add_edge( + atom1_id, + atom2_id, + bond_id=bond_id, + bond_type=bond_type, + ) + + print( + f"Graph created from {file_path} with " + f"{graph.number_of_nodes()} nodes and " + f"{graph.number_of_edges()} edges." + ) + + return graph + + def _read_sections( + self, + file_path: Path, + ) -> dict[str, list[str]]: + """ + Read relevant sections from a LAMMPS molecule-template file. + """ + supported_sections = { + "Types", + "Coords", + "Bonds", + "Charges", + "Molecules", + "Angles", + "Dihedrals", + "Impropers", + "Special Bond Counts", + "Special Bonds", + } + + sections: dict[str, list[str]] = {} + current_section: str | None = None + + with file_path.open("r", encoding="utf-8") as file: + for raw_line in file: + # Remove comments but preserve the actual data. + line = raw_line.split("#", maxsplit=1)[0].strip() + + if not line: + continue + + if line in supported_sections: + current_section = line + sections.setdefault(current_section, []) + continue + + if current_section is not None: + # Stop collecting when another unsupported header/count + # line is encountered only through recognized sections. + sections[current_section].append(line) + + return sections + + def _couple_graphs( + self, + pre_template_graph: nx.Graph, + post_template_graph: nx.Graph, + ) -> dict[str, nx.Graph]: + """ + Store the pre- and post-template graphs together. + """ + return { + "pre_template_graph": pre_template_graph, + "post_template_graph": post_template_graph, + } + + def _compare_graphs( + self, + mol_file_paths: list[str | Path], + ) -> dict[str, bool]: + """ + Process pre-template files and report whether each reaction is + a duplicate of a previously processed pre/post pair. + + Returns: + Mapping from the pre-template file path to duplicate status. + """ + results: dict[str, bool] = {} + + for file_path_value in mol_file_paths: + file_path = Path(file_path_value) + + if "pre" not in file_path.name: + continue + + post_file_name = file_path.name.replace("pre", "post", 1) + post_file_path = file_path.with_name(post_file_name) + + if not post_file_path.exists(): + print( + f"Post-template file does not exist for " + f"{file_path}." + ) + continue + + pre_template_graph = self.lammps_molecule_to_networkx( + file_path + ) + post_template_graph = self.lammps_molecule_to_networkx( + post_file_path + ) + + is_duplicate = self.is_duplicate( + pre_template_graph, + post_template_graph, + ) + + results[str(file_path)] = is_duplicate + + if is_duplicate: + print( + f"Duplicate reaction: {file_path.name} and " + f"{post_file_path.name}" + ) + else: + print( + f"Unique reaction: {file_path.name} and " + f"{post_file_path.name}" + ) + + return results + + +if __name__ == "__main__": + deduplication_detector = DeduplicationDetector() + + folder_path = Path( + "/mnt/c/Users/Janitha/Documents/AutoREACTER/examples/" + "AutoREACTER_outputs/" + "Epoxy_Test_Primary_Diamine_Diepoxy" + ) + + pre_template_files = sorted( + file_path + for file_path in folder_path.glob("*.molecule") + if "pre" in file_path.name + ) + + results = deduplication_detector._compare_graphs( + pre_template_files + ) + + print("\nDeduplication results:") + + for file_path, is_duplicate in results.items(): + status = "duplicate" if is_duplicate else "unique" + print(f"{Path(file_path).name}: {status}") \ No newline at end of file From 33adcd3e203fa428e4578dbdf0aee9b0f6560ba7 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:15:02 -0400 Subject: [PATCH 020/176] Add RDKit reaction dedup across progression Reworks deduplication to compare coupled pre/post graphs using normalized atom/bond labels, adds separate LAMMPS and RDKit comparison caches, and introduces RDKit molecule graph conversion for in-memory reaction metadata. Reaction progression now accumulates reactions across iterations, disables duplicates via dedup checks, skips inactive reactions downstream, and uses a session-level monotonic reaction ID counter so generated reaction CSV IDs remain globally unique across loop passes. Also updates LUNAR config to a concrete local root path and refreshes notebook debug output. --- .../deduplication_detector.py | 675 ++++++++++++++---- .../ff_wrapper/lunar_client/config.py | 2 +- .../reaction_processor/prepare_reactions.py | 24 +- .../reaction_progression.py | 52 +- test.ipynb | 11 +- 5 files changed, 585 insertions(+), 179 deletions(-) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 6d73eb24..e510aeef 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -1,188 +1,409 @@ -import os +from __future__ import annotations + from pathlib import Path +from typing import TYPE_CHECKING import networkx as nx +from rdkit import Chem + +if TYPE_CHECKING: + from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ( + ReactionMetadata, + ) class DeduplicationDetector: - def __init__(self): - # Graphs are not hashable, so store reaction graph pairs in a list. - self.seen_reactions: list[tuple[nx.Graph, nx.Graph]] = [] + """ + Detect duplicate pre/post reaction graph pairs. + + Coordinates, atom IDs, and bond IDs are ignored during graph + isomorphism comparison. + + A coupled graph is created for every reaction pair so that the same + atom mapping must be valid for both the reactant and product graphs. + """ + + NODE_ATTRIBUTE = "atom_label" + EDGE_ATTRIBUTE = "bond_label" + + LAMMPS_COMPARISON_GROUP = "lammps" + RDKIT_COMPARISON_GROUP = "rdkit" + + def __init__(self) -> None: + """ + Initialize independent deduplication caches. + """ + self.seen_reactions: dict[str, list[nx.Graph]] = { + self.LAMMPS_COMPARISON_GROUP: [], + self.RDKIT_COMPARISON_GROUP: [], + } def is_duplicate( self, pre_template_graph: nx.Graph, post_template_graph: nx.Graph, + comparison_group: str, ) -> bool: """ - Check whether a pre/post reaction graph pair has already been seen. + Check whether an equivalent pre/post reaction pair has been seen. + + Args: + pre_template_graph: + Graph representing the reactant state. + + post_template_graph: + Graph representing the product state. - Atom types and bond types are included in the graph comparison. - Coordinates are intentionally ignored because the same molecular - topology can have different coordinates. + comparison_group: + Cache group used for the comparison, such as ``lammps`` + or ``rdkit``. + + Returns: + True if an equivalent reaction pair has already been seen. + Otherwise, stores the reaction pair and returns False. """ + coupled_graph = self._couple_graphs( + pre_template_graph=pre_template_graph, + post_template_graph=post_template_graph, + ) + node_match = nx.algorithms.isomorphism.categorical_node_match( - "atom_type", - None, + ["phase", self.NODE_ATTRIBUTE], + [None, None], ) + edge_match = nx.algorithms.isomorphism.categorical_edge_match( - "bond_type", - None, + ["relationship", self.EDGE_ATTRIBUTE], + [None, None], ) - for seen_pre_graph, seen_post_graph in self.seen_reactions: - pre_matches = nx.is_isomorphic( - pre_template_graph, - seen_pre_graph, - node_match=node_match, - edge_match=edge_match, - ) + seen_graphs = self.seen_reactions.setdefault( + comparison_group, + [], + ) - if not pre_matches: + for seen_graph in seen_graphs: + # Cheap checks before running graph isomorphism. + if coupled_graph.number_of_nodes() != seen_graph.number_of_nodes(): continue - post_matches = nx.is_isomorphic( - post_template_graph, - seen_post_graph, + if coupled_graph.number_of_edges() != seen_graph.number_of_edges(): + continue + + if nx.is_isomorphic( + coupled_graph, + seen_graph, node_match=node_match, edge_match=edge_match, - ) - - if post_matches: + ): return True - self.seen_reactions.append( - ( - pre_template_graph.copy(), - post_template_graph.copy(), - ) - ) + seen_graphs.append(coupled_graph.copy()) return False - def lammps_molecule_to_networkx( + def _couple_graphs( self, - file_path: str | Path, + pre_template_graph: nx.Graph, + post_template_graph: nx.Graph, ) -> nx.Graph: """ - Convert a LAMMPS molecule-template file into a NetworkX graph. + Combine the reactant and product graphs into one graph. - Supported sections: - Types - Coords - Bonds + Every atom is represented twice: + + ("pre", atom_id) + ("post", atom_id) + + A correspondence edge connects the same atom ID in the pre- and + post-reaction graphs. This requires one consistent atom mapping + across both reaction states. """ - file_path = Path(file_path) + pre_atom_ids = set(pre_template_graph.nodes) + post_atom_ids = set(post_template_graph.nodes) - if not file_path.exists(): - raise FileNotFoundError( - f"Molecule file does not exist: {file_path}" + if pre_atom_ids != post_atom_ids: + missing_from_post = sorted( + pre_atom_ids - post_atom_ids + ) + missing_from_pre = sorted( + post_atom_ids - pre_atom_ids ) - sections = self._read_sections(file_path) + raise ValueError( + "Pre- and post-reaction graphs must contain matching " + "atom IDs. " + f"Missing from post graph: {missing_from_post}. " + f"Missing from pre graph: {missing_from_pre}." + ) + + coupled_graph = nx.Graph() + + self._add_phase_to_coupled_graph( + source_graph=pre_template_graph, + coupled_graph=coupled_graph, + phase="pre", + ) + + self._add_phase_to_coupled_graph( + source_graph=post_template_graph, + coupled_graph=coupled_graph, + phase="post", + ) - atom_mapping: dict[int, str] = {} - coord_mapping: dict[int, tuple[float, float, float]] = {} - bond_mapping: dict[int, tuple[str, int, int]] = {} + for atom_id in pre_atom_ids: + coupled_graph.add_edge( + ("pre", atom_id), + ("post", atom_id), + relationship="atom_correspondence", + **{self.EDGE_ATTRIBUTE: None}, + ) + + return coupled_graph - for line in sections.get("Types", []): - atom_data = line.split() + def _add_phase_to_coupled_graph( + self, + source_graph: nx.Graph, + coupled_graph: nx.Graph, + phase: str, + ) -> None: + """ + Add one reaction phase to a coupled pre/post graph. + """ + for atom_id, attributes in source_graph.nodes(data=True): + atom_label = attributes.get(self.NODE_ATTRIBUTE) - if len(atom_data) < 2: + if atom_label is None: raise ValueError( - f"Invalid Types line in {file_path}: {line!r}" + f"Node {atom_id} is missing the required " + f"{self.NODE_ATTRIBUTE!r} attribute." ) - atom_id = int(atom_data[0]) - atom_type = atom_data[1] - atom_mapping[atom_id] = atom_type + coupled_graph.add_node( + (phase, atom_id), + phase=phase, + **{self.NODE_ATTRIBUTE: atom_label}, + ) - for line in sections.get("Coords", []): - coord_data = line.split() + for atom1_id, atom2_id, attributes in source_graph.edges( + data=True + ): + bond_label = attributes.get(self.EDGE_ATTRIBUTE) - if len(coord_data) < 4: + if bond_label is None: raise ValueError( - f"Invalid Coords line in {file_path}: {line!r}" + f"Edge {atom1_id}-{atom2_id} is missing the required " + f"{self.EDGE_ATTRIBUTE!r} attribute." ) - atom_id = int(coord_data[0]) - x = float(coord_data[1]) - y = float(coord_data[2]) - z = float(coord_data[3]) + coupled_graph.add_edge( + (phase, atom1_id), + (phase, atom2_id), + relationship="bond", + **{self.EDGE_ATTRIBUTE: bond_label}, + ) - coord_mapping[atom_id] = (x, y, z) + def rdkit_mol_to_networkx( + self, + molecule: Chem.Mol, + ) -> nx.Graph: + """ + Convert an in-memory RDKit molecule into a NetworkX graph. - for line in sections.get("Bonds", []): - bond_data = line.split() + Coordinates are not read or stored. - if len(bond_data) < 4: - raise ValueError( - f"Invalid Bonds line in {file_path}: {line!r}" - ) + Node attribute: + atom_label: + Chemical element symbol. - bond_id = int(bond_data[0]) - bond_type = bond_data[1] - atom1_id = int(bond_data[2]) - atom2_id = int(bond_data[3]) + Edge attribute: + bond_label: + RDKit bond type. + """ + if molecule is None: + raise ValueError( + "Cannot create a graph from a None RDKit molecule." + ) - bond_mapping[bond_id] = ( - bond_type, + graph = nx.Graph() + + for atom in molecule.GetAtoms(): + atom_id = atom.GetIdx() + + graph.add_node( + atom_id, + **{ + self.NODE_ATTRIBUTE: atom.GetSymbol(), + }, + ) + + for bond in molecule.GetBonds(): + atom1_id = bond.GetBeginAtomIdx() + atom2_id = bond.GetEndAtomIdx() + + graph.add_edge( atom1_id, atom2_id, + **{ + self.EDGE_ATTRIBUTE: str( + bond.GetBondType() + ), + }, + ) + + return graph + + def lammps_molecule_to_networkx( + self, + file_path: str | Path, + ) -> nx.Graph: + """ + Convert a LAMMPS molecule-template file into a NetworkX graph. + + Only the following sections are used: + + Types + Bonds + + Coordinates, charges, angles, dihedrals, impropers, atom IDs, + and bond IDs are not used in graph isomorphism comparison. + """ + file_path = Path(file_path) + + if not file_path.is_file(): + raise FileNotFoundError( + f"LAMMPS molecule file does not exist: {file_path}" + ) + + sections = self._read_lammps_sections(file_path) + + if "Types" not in sections: + raise ValueError( + f"Types section was not found in {file_path}." ) graph = nx.Graph() - for atom_id, atom_type in atom_mapping.items(): - if atom_id not in coord_mapping: + self._add_lammps_atoms( + graph=graph, + type_lines=sections["Types"], + file_path=file_path, + ) + + self._add_lammps_bonds( + graph=graph, + bond_lines=sections.get("Bonds", []), + file_path=file_path, + ) + + print( + f"Graph created from {file_path.name}: " + f"{graph.number_of_nodes()} atoms and " + f"{graph.number_of_edges()} bonds." + ) + + return graph + + def _add_lammps_atoms( + self, + graph: nx.Graph, + type_lines: list[str], + file_path: Path, + ) -> None: + """ + Add atoms from a LAMMPS Types section to a graph. + """ + for line in type_lines: + parts = line.split() + + if len(parts) < 2: raise ValueError( - f"Atom {atom_id} has a type but no coordinates " - f"in {file_path}." + f"Invalid Types line in {file_path}: {line!r}" + ) + + try: + atom_id = int(parts[0]) + except ValueError as error: + raise ValueError( + f"Invalid atom ID in {file_path}: {line!r}" + ) from error + + atom_type = parts[1] + + if atom_id in graph: + raise ValueError( + f"Duplicate atom ID {atom_id} in {file_path}." ) graph.add_node( atom_id, - atom_type=atom_type, - coords=coord_mapping[atom_id], + **{ + self.NODE_ATTRIBUTE: atom_type, + }, ) - for bond_id, bond_data in bond_mapping.items(): - bond_type, atom1_id, atom2_id = bond_data + def _add_lammps_bonds( + self, + graph: nx.Graph, + bond_lines: list[str], + file_path: Path, + ) -> None: + """ + Add bonds from a LAMMPS Bonds section to a graph. + """ + for line in bond_lines: + parts = line.split() - if atom1_id not in graph or atom2_id not in graph: + if len(parts) < 4: raise ValueError( - f"Bond {bond_id} references an undefined atom " - f"in {file_path}." + f"Invalid Bonds line in {file_path}: {line!r}" ) + try: + bond_id = int(parts[0]) + atom1_id = int(parts[2]) + atom2_id = int(parts[3]) + except ValueError as error: + raise ValueError( + f"Invalid Bonds line in {file_path}: {line!r}" + ) from error + + bond_type = parts[1] + + self._validate_bond_atoms( + graph=graph, + bond_id=bond_id, + atom1_id=atom1_id, + atom2_id=atom2_id, + source=file_path, + ) + graph.add_edge( atom1_id, atom2_id, - bond_id=bond_id, - bond_type=bond_type, + **{ + self.EDGE_ATTRIBUTE: bond_type, + }, ) - print( - f"Graph created from {file_path} with " - f"{graph.number_of_nodes()} nodes and " - f"{graph.number_of_edges()} edges." - ) - - return graph - - def _read_sections( + def _read_lammps_sections( self, file_path: Path, ) -> dict[str, list[str]]: """ Read relevant sections from a LAMMPS molecule-template file. """ - supported_sections = { + relevant_sections = { "Types", - "Coords", "Bonds", + } + + all_section_headers = { + "Coords", + "Types", "Charges", "Molecules", + "Bonds", "Angles", "Dihedrals", "Impropers", @@ -193,117 +414,269 @@ def _read_sections( sections: dict[str, list[str]] = {} current_section: str | None = None - with file_path.open("r", encoding="utf-8") as file: + with file_path.open( + "r", + encoding="utf-8", + ) as file: for raw_line in file: - # Remove comments but preserve the actual data. - line = raw_line.split("#", maxsplit=1)[0].strip() + # Remove comments while preserving the actual data. + line = raw_line.split( + "#", + maxsplit=1, + )[0].strip() if not line: continue - if line in supported_sections: - current_section = line - sections.setdefault(current_section, []) + if line in all_section_headers: + if line in relevant_sections: + current_section = line + sections.setdefault( + current_section, + [], + ) + else: + current_section = None + continue if current_section is not None: - # Stop collecting when another unsupported header/count - # line is encountered only through recognized sections. sections[current_section].append(line) return sections - def _couple_graphs( + def _validate_bond_atoms( self, - pre_template_graph: nx.Graph, - post_template_graph: nx.Graph, - ) -> dict[str, nx.Graph]: + graph: nx.Graph, + bond_id: int, + atom1_id: int, + atom2_id: int, + source: Path | str, + ) -> None: """ - Store the pre- and post-template graphs together. + Ensure that both atoms referenced by a bond exist. """ - return { - "pre_template_graph": pre_template_graph, - "post_template_graph": post_template_graph, - } + undefined_atoms = [ + atom_id + for atom_id in (atom1_id, atom2_id) + if atom_id not in graph + ] + + if undefined_atoms: + raise ValueError( + f"Bond {bond_id} references undefined atom IDs " + f"{undefined_atoms} in {source}." + ) - def _compare_graphs( + def compare_graphs( self, - mol_file_paths: list[str | Path], + molecule_file_paths: list[str | Path], ) -> dict[str, bool]: """ - Process pre-template files and report whether each reaction is - a duplicate of a previously processed pre/post pair. + Compare LAMMPS pre/post molecule-template pairs. + + A pre-template filename must contain ``pre``. Its corresponding + post-template filename is found by replacing the first occurrence + of ``pre`` with ``post``. Returns: - Mapping from the pre-template file path to duplicate status. + Mapping from each pre-template path to its duplicate status. """ results: dict[str, bool] = {} - for file_path_value in mol_file_paths: - file_path = Path(file_path_value) + for file_path_value in molecule_file_paths: + pre_file_path = Path(file_path_value) - if "pre" not in file_path.name: + if "pre" not in pre_file_path.name: continue - post_file_name = file_path.name.replace("pre", "post", 1) - post_file_path = file_path.with_name(post_file_name) + post_file_path = pre_file_path.with_name( + pre_file_path.name.replace( + "pre", + "post", + 1, + ) + ) - if not post_file_path.exists(): + if not post_file_path.is_file(): print( - f"Post-template file does not exist for " - f"{file_path}." + "Skipping reaction because its post-template file " + f"does not exist: {post_file_path}" ) continue - pre_template_graph = self.lammps_molecule_to_networkx( - file_path + pre_graph = self.lammps_molecule_to_networkx( + pre_file_path ) - post_template_graph = self.lammps_molecule_to_networkx( + + post_graph = self.lammps_molecule_to_networkx( post_file_path ) - is_duplicate = self.is_duplicate( - pre_template_graph, - post_template_graph, + duplicate = self.is_duplicate( + pre_template_graph=pre_graph, + post_template_graph=post_graph, + comparison_group=self.LAMMPS_COMPARISON_GROUP, ) - results[str(file_path)] = is_duplicate + results[str(pre_file_path)] = duplicate + + status = ( + "Duplicate" + if duplicate + else "Unique" + ) + + print( + f"{status} reaction: " + f"{pre_file_path.name} -> " + f"{post_file_path.name}" + ) + + return results + + def compare_graphs_mol( + self, + reaction_metadata_items: list[ReactionMetadata], + ) -> list[ReactionMetadata]: + """ + Detect duplicate reactions using in-memory RDKit molecules. + + Reactions whose ``activity_stats`` value is already False are + skipped. + + Duplicate reactions are disabled by setting: + + reaction_metadata.activity_stats = False + + Args: + reaction_metadata_items: + Prepared reaction metadata objects. + + Returns: + The original metadata list with duplicate reactions disabled. + """ + for reaction_index, reaction_metadata in enumerate( + reaction_metadata_items, + start=1, + ): + if reaction_metadata.activity_stats is False: + continue + + reactant_mol = ( + reaction_metadata.reactant_combined_RDmol + ) + product_mol = ( + reaction_metadata.product_combined_RDmol + ) + template_reactant_to_product_mapping = ( + reaction_metadata.template_reactant_to_product_mapping + ) + if reactant_mol is None: + raise ValueError( + f"Reaction {reaction_index} does not contain a " + "combined reactant RDKit molecule." + ) + + if product_mol is None: + raise ValueError( + f"Reaction {reaction_index} does not contain a " + "combined product RDKit molecule." + ) + + pre_graph = self.rdkit_mol_to_networkx( + reactant_mol + ) + + post_graph = self.rdkit_mol_to_networkx( + product_mol + ) + + duplicate = self.is_duplicate( + pre_template_graph=pre_graph, + post_template_graph=post_graph, + comparison_group=self.RDKIT_COMPARISON_GROUP, + ) + + if duplicate: + reaction_metadata.activity_stats = False - if is_duplicate: print( - f"Duplicate reaction: {file_path.name} and " - f"{post_file_path.name}" + f"Reaction {reaction_index}: " + "duplicate reaction detected and disabled." ) else: print( - f"Unique reaction: {file_path.name} and " - f"{post_file_path.name}" + f"Reaction {reaction_index}: " + "unique reaction retained." ) - return results + return reaction_metadata_items + def clear_cache( + self, + comparison_group: str | None = None, + ) -> None: + """ + Clear stored reaction graphs. -if __name__ == "__main__": - deduplication_detector = DeduplicationDetector() + Args: + comparison_group: + Clear only one cache group. When None, all cache groups + are cleared. + """ + if comparison_group is None: + for seen_graphs in self.seen_reactions.values(): + seen_graphs.clear() + return + + self.seen_reactions.setdefault( + comparison_group, + [], + ).clear() + + +if __name__ == "__main__": folder_path = Path( - "/mnt/c/Users/Janitha/Documents/AutoREACTER/examples/" - "AutoREACTER_outputs/" - "Epoxy_Test_Primary_Diamine_Diepoxy" + "/mnt/c/Users/janit/Documents/GitHub/AutoREACTER/" + "examples/AutoREACTER_outputs/" + "Epoxy_Test_Primary_Diamine_Diepoxy/" + "LAMMPS_input_files/" + "Epoxy_Test_Primary_Diamine_Diepoxy_epoxy_test" ) + if not folder_path.is_dir(): + raise NotADirectoryError( + f"Invalid folder path: {folder_path}" + ) + pre_template_files = sorted( file_path for file_path in folder_path.glob("*.molecule") if "pre" in file_path.name ) - results = deduplication_detector._compare_graphs( + print( + f"Found {len(pre_template_files)} " + "pre-reaction molecule files." + ) + + detector = DeduplicationDetector() + + results = detector.compare_graphs( pre_template_files ) print("\nDeduplication results:") - for file_path, is_duplicate in results.items(): - status = "duplicate" if is_duplicate else "unique" - print(f"{Path(file_path).name}: {status}") \ No newline at end of file + for file_path, duplicate in results.items(): + status = ( + "duplicate" + if duplicate + else "unique" + ) + + print( + f"{Path(file_path).name}: {status}" + ) \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py index 96b9c6fc..a9a571e5 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py @@ -1 +1 @@ -LUNAR_ROOT_DIR = None +LUNAR_ROOT_DIR = '/mnt/c/Users/janit/Documents/GitHub/LUNAR' diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 69eeed6c..426e88e7 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -103,6 +103,8 @@ def __init__(self, session: "Session"): self.staging_dir = Path(session.staging_dir) self.cache = self.staging_dir self.csv_cache = prepare_paths(self.cache, "csv_cache") + if not hasattr(session, "reaction_id_counter"): + session.reaction_id_counter = 0 # Initialize a counter for unique reaction IDs if not already present def prepare_reactions(self, session): prepared_reactions = self._prepare_reactions_stage(session) @@ -260,14 +262,14 @@ def _process_reaction_instances( return reaction_metadata def _process_reaction_products(self, - rxn: Chem.rdChemReactions.ChemicalReaction, - csv_cache: Path, - reaction_tuple: list, - delete_atoms: bool = True, - reaction_metadata: Optional[list[ReactionMetadata]] = None, - forced_indexes_1: Optional[set] = None, - forced_indexes_2: Optional[set] = None, - ) -> list[ReactionMetadata]: + rxn: Chem.rdChemReactions.ChemicalReaction, + csv_cache: Path, + reaction_tuple: list, + delete_atoms: bool = True, + reaction_metadata: Optional[list[ReactionMetadata]] = None, + forced_indexes_1: Optional[set] = None, + forced_indexes_2: Optional[set] = None, + ) -> list[ReactionMetadata]: """ Runs reactions on reactant pairs and builds metadata for each product set. @@ -340,7 +342,11 @@ def _process_reaction_products(self, pd.Series(byproduct_reactant_idxs, name="byproduct_idx") ], axis=1).astype(pd.Int64Dtype()) - total_products = len(reaction_metadata) + 1 + # counter so every reaction across the whole run — including every + # pass of the progression loop — gets a distinct, ever-increasing id. + self.session.reaction_id_counter += 1 + total_products = self.session.reaction_id_counter + self._clear_isotopes(reactant_combined, product_combined) df_combined.to_csv(csv_cache / f"reaction_{total_products}.csv", index=False) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index fc832b5c..8d5e7121 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -7,6 +7,7 @@ from AutoREACTER.detectors.functional_groups_detector import FunctionalGroupsDetector from AutoREACTER.detectors.reaction_detector import ReactionDetector +from AutoREACTER.reaction_preparation.deduplication_detector import DeduplicationDetector if TYPE_CHECKING: from AutoREACTER.session import Session @@ -54,12 +55,14 @@ def reaction_progression(self, max_loop: int = MAX_LOOP) -> list["ReactionMetada """ iteration = 0 monomer_roles_in_loop = self.session.monomer_roles.copy() - reaction_instances = self.session.reaction_instances.copy() + + # Accumulate prepared reactions across iterations to avoid reprocessing in each loop. + all_prepared_reactions: list["ReactionMetadata"] = [] while iteration < max_loop: iteration += 1 self.session.reaction_progression_session.iteration = iteration - + size_of_initial_reaction_pool = self._length_of_active_reactions() if iteration == 1: self._populate_monomer_roles() @@ -95,19 +98,39 @@ def reaction_progression(self, max_loop: int = MAX_LOOP) -> list["ReactionMetada rxns = self.rxn_detector.index_based_reaction_detector( monomer_roles_in_loop ) - reaction_instances.extend(rxns) - print(len(reaction_instances)) # Debug print + # Debug prints to trace the reaction progression loop. + if not rxns: + print( + f"No new reactions detected in iteration {iteration}. " + f"Ending the reaction progression loop." + ) + break + + print(len(rxns)) # Debug print (was len(reaction_instances); now just the new batch) print(monomer_roles_in_loop) # Debug print + + # prepared_reactions = self._index_based_reaction_preparation( - reaction_instances=reaction_instances + reaction_instances=rxns ) print(prepared_reactions) # Debug print + + # Accumulate prepared reactions across iterations. + all_prepared_reactions.extend(prepared_reactions) + print(size_of_initial_reaction_pool) + deduplication_detector = DeduplicationDetector() + all_prepared_reactions = deduplication_detector.compare_graphs_mol( + all_prepared_reactions + ) + if self._loop_break_condition( - size_before=size_of_pool, size_after=len(monomer_roles_in_loop) + size_before=size_of_initial_reaction_pool, size_after=len(all_prepared_reactions) ): - return prepared_reactions - return prepared_reactions + self.session.reaction_metadata = all_prepared_reactions + return all_prepared_reactions + self.session.reaction_metadata = all_prepared_reactions + return all_prepared_reactions def _index_based_reaction_preparation( self, reaction_instances: list["ReactionInstance"] @@ -128,6 +151,8 @@ def _prepare_products_for_idx_based_fg_detection( reaction_metadata = self.session.reaction_metadata for reaction in reaction_metadata: + if not reaction.activity_stats: + continue product_mol = reaction.product_combined_RDmol indexes_in_template, product_mol = self._get_product_idxs( reaction.template_reactant_to_product_mapping, @@ -321,4 +346,13 @@ def _loop_break_condition(self, size_before: int, size_after: int) -> bool: f"(before={size_before}, after={size_after})." ) return True - return False \ No newline at end of file + return False + + def _length_of_active_reactions(self) -> int: + """ + Returns the number of reactions in the session that have activity stats. + """ + return sum( + 1 for reaction in self.session.reaction_metadata + if reaction.activity_stats + ) \ No newline at end of file diff --git a/test.ipynb b/test.ipynb index 56f21e44..b37645ba 100644 --- a/test.ipynb +++ b/test.ipynb @@ -12,20 +12,13 @@ "from importlib.resources import files\n", "\n", "\n", - "def _add_progessive_chemistries():\n", - " rules_file = files(\"AutoREACTER.detectors\").joinpath(\"reaction_rules.json\")\n", - "\n", - " with rules_file.open(\"r\", encoding=\"utf-8\") as file:\n", - " reaction_rules = json.load(file)\n", - " rules = reaction_rules[\"multi_step_reactions\"]\n", - " print(rules)\n", "\n", " return reaction_rules" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 7, "id": "8af2ad56", "metadata": {}, "outputs": [ @@ -33,7 +26,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'multi_step_reactions': [{'name': 'epoxy_polymerization', 'if_reactions': 'Amine Epoxy Addition First Stage', 'required_reactions': ['Amine Epoxy Addition Second Stage'], 'fg_additon': {'primary_amine': 'secondary_amine'}}]}\n" + "[{'name': 'epoxy_polymerization', 'if_reactions': 'Amine Epoxy Addition First Stage', 'required_reactions': ['Amine Epoxy Addition Second Stage'], 'fg_additon': {'primary_amine': 'secondary_amine'}}]\n" ] } ], From 9259d0994e6c5ffd6ce2fb71102b5931d10ad247 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:23:47 -0400 Subject: [PATCH 021/176] Update deduplication_detector.py --- .../deduplication_detector.py | 837 ++++++++++-------- 1 file changed, 476 insertions(+), 361 deletions(-) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index e510aeef..a067c719 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -12,15 +12,25 @@ ) +""" +In here we do not add any coordinations, atom IDs, or bond IDs to the graphs. This is because these +There tempalate can generate from different reactanats but can have same template +How ever the is a possible herdle in here that element can be same but atom types in +LAMMPS can be different. In future release we can add one more attribute to +the graph which is atom type in LAMMPS and bond type in LAMMPS. +This will make sure that we are comparing the same template and not different template with same element. +""" + class DeduplicationDetector: """ - Detect duplicate pre/post reaction graph pairs. + Detect duplicate pre/post-reaction graph pairs. Coordinates, atom IDs, and bond IDs are ignored during graph isomorphism comparison. - A coupled graph is created for every reaction pair so that the same - atom mapping must be valid for both the reactant and product graphs. + Each pre/post pair is combined into a coupled graph. Correspondence + edges connect the same atom across the reactant and product states, + ensuring that one consistent atom mapping must satisfy both graphs. """ NODE_ATTRIBUTE = "atom_label" @@ -29,15 +39,41 @@ class DeduplicationDetector: LAMMPS_COMPARISON_GROUP = "lammps" RDKIT_COMPARISON_GROUP = "rdkit" + _PRE_PHASE = "pre" + _POST_PHASE = "post" + + _BOND_RELATIONSHIP = "bond" + _ATOM_CORRESPONDENCE_RELATIONSHIP = "atom_correspondence" + + _LAMMPS_RELEVANT_SECTIONS = { + "Types", + "Bonds", + } + + _LAMMPS_SECTION_HEADERS = { + "Coords", + "Types", + "Charges", + "Molecules", + "Bonds", + "Angles", + "Dihedrals", + "Impropers", + "Special Bond Counts", + "Special Bonds", + } + def __init__(self) -> None: - """ - Initialize independent deduplication caches. - """ + """Initialize independent deduplication caches.""" self.seen_reactions: dict[str, list[nx.Graph]] = { self.LAMMPS_COMPARISON_GROUP: [], self.RDKIT_COMPARISON_GROUP: [], } + # ------------------------------------------------------------------ + # Public duplicate-detection API + # ------------------------------------------------------------------ + def is_duplicate( self, pre_template_graph: nx.Graph, @@ -45,22 +81,20 @@ def is_duplicate( comparison_group: str, ) -> bool: """ - Check whether an equivalent pre/post reaction pair has been seen. + Check whether an equivalent pre/post-reaction pair was seen. Args: pre_template_graph: Graph representing the reactant state. - post_template_graph: Graph representing the product state. - comparison_group: Cache group used for the comparison, such as ``lammps`` or ``rdkit``. Returns: - True if an equivalent reaction pair has already been seen. - Otherwise, stores the reaction pair and returns False. + True when an equivalent reaction pair is already cached. + Otherwise, caches the reaction pair and returns False. """ coupled_graph = self._couple_graphs( pre_template_graph=pre_template_graph, @@ -83,7 +117,6 @@ def is_duplicate( ) for seen_graph in seen_graphs: - # Cheap checks before running graph isomorphism. if coupled_graph.number_of_nodes() != seen_graph.number_of_nodes(): continue @@ -99,151 +132,304 @@ def is_duplicate( return True seen_graphs.append(coupled_graph.copy()) - return False - def _couple_graphs( + def compare_graphs( self, - pre_template_graph: nx.Graph, - post_template_graph: nx.Graph, - ) -> nx.Graph: + molecule_file_paths: list[str | Path], + ) -> dict[str, bool]: """ - Combine the reactant and product graphs into one graph. + Compare LAMMPS pre/post molecule-template pairs. - Every atom is represented twice: + A pre-template filename must contain ``pre``. The corresponding + post-template filename is determined by replacing the first + occurrence of ``pre`` with ``post``. - ("pre", atom_id) - ("post", atom_id) + Args: + molecule_file_paths: + Candidate LAMMPS molecule-template file paths. - A correspondence edge connects the same atom ID in the pre- and - post-reaction graphs. This requires one consistent atom mapping - across both reaction states. + Returns: + A mapping from each processed pre-template path to its + duplicate status. """ - pre_atom_ids = set(pre_template_graph.nodes) - post_atom_ids = set(post_template_graph.nodes) + results: dict[str, bool] = {} - if pre_atom_ids != post_atom_ids: - missing_from_post = sorted( - pre_atom_ids - post_atom_ids - ) - missing_from_pre = sorted( - post_atom_ids - pre_atom_ids + for file_path_value in molecule_file_paths: + pre_file_path = Path(file_path_value) + + if "pre" not in pre_file_path.name: + continue + + post_file_path = pre_file_path.with_name( + pre_file_path.name.replace( + "pre", + "post", + 1, + ) ) - raise ValueError( - "Pre- and post-reaction graphs must contain matching " - "atom IDs. " - f"Missing from post graph: {missing_from_post}. " - f"Missing from pre graph: {missing_from_pre}." + if not post_file_path.is_file(): + print( + "Skipping reaction because its post-template file " + f"does not exist: {post_file_path}" + ) + continue + + pre_graph = self.lammps_molecule_to_networkx( + pre_file_path + ) + post_graph = self.lammps_molecule_to_networkx( + post_file_path ) - coupled_graph = nx.Graph() + duplicate = self.is_duplicate( + pre_template_graph=pre_graph, + post_template_graph=post_graph, + comparison_group=self.LAMMPS_COMPARISON_GROUP, + ) - self._add_phase_to_coupled_graph( - source_graph=pre_template_graph, - coupled_graph=coupled_graph, - phase="pre", - ) + results[str(pre_file_path)] = duplicate - self._add_phase_to_coupled_graph( - source_graph=post_template_graph, - coupled_graph=coupled_graph, - phase="post", - ) + status = "Duplicate" if duplicate else "Unique" - for atom_id in pre_atom_ids: - coupled_graph.add_edge( - ("pre", atom_id), - ("post", atom_id), - relationship="atom_correspondence", - **{self.EDGE_ATTRIBUTE: None}, + print( + f"{status} reaction: " + f"{pre_file_path.name} -> {post_file_path.name}" ) - return coupled_graph + return results - def _add_phase_to_coupled_graph( + def compare_graphs_mol( self, - source_graph: nx.Graph, - coupled_graph: nx.Graph, - phase: str, - ) -> None: + reaction_metadata_items: list[ReactionMetadata], + ) -> list[ReactionMetadata]: """ - Add one reaction phase to a coupled pre/post graph. + Detect duplicate reactions using in-memory RDKit molecules. + + Reactions whose ``activity_stats`` value is already False are + skipped. Detected duplicates are disabled by setting + ``activity_stats`` to False. + + Only atoms included in + ``template_reactant_to_product_mapping`` participate in duplicate + detection. Product atom indices are relabeled into reactant-index + space before the pre/post graphs are coupled. + + Args: + reaction_metadata_items: + Prepared reaction metadata objects. + + Returns: + The original metadata list with duplicate reactions disabled. """ - for atom_id, attributes in source_graph.nodes(data=True): - atom_label = attributes.get(self.NODE_ATTRIBUTE) + for reaction_index, reaction_metadata in enumerate( + reaction_metadata_items, + start=1, + ): + if reaction_metadata.activity_stats is False: + continue - if atom_label is None: - raise ValueError( - f"Node {atom_id} is missing the required " - f"{self.NODE_ATTRIBUTE!r} attribute." - ) + reactant_mol = reaction_metadata.reactant_combined_RDmol + product_mol = reaction_metadata.product_combined_RDmol - coupled_graph.add_node( - (phase, atom_id), - phase=phase, - **{self.NODE_ATTRIBUTE: atom_label}, + reactant_to_product_mapping = ( + reaction_metadata.template_reactant_to_product_mapping ) - for atom1_id, atom2_id, attributes in source_graph.edges( - data=True - ): - bond_label = attributes.get(self.EDGE_ATTRIBUTE) + if reactant_mol is None: + raise ValueError( + f"Reaction {reaction_index} does not contain a " + "combined reactant RDKit molecule." + ) - if bond_label is None: + if product_mol is None: raise ValueError( - f"Edge {atom1_id}-{atom2_id} is missing the required " - f"{self.EDGE_ATTRIBUTE!r} attribute." + f"Reaction {reaction_index} does not contain a " + "combined product RDKit molecule." ) - coupled_graph.add_edge( - (phase, atom1_id), - (phase, atom2_id), - relationship="bond", - **{self.EDGE_ATTRIBUTE: bond_label}, + if not reactant_to_product_mapping: + raise ValueError( + f"Reaction {reaction_index} does not contain a " + "template_reactant_to_product_mapping; duplicate " + "comparison cannot be restricted to template atoms." + ) + + reactant_template_indices = set( + reactant_to_product_mapping + ) + + product_to_reactant_mapping = { + product_index: reactant_index + for reactant_index, product_index + in reactant_to_product_mapping.items() + } + + product_template_indices = set( + product_to_reactant_mapping + ) + + pre_graph = self.rdkit_mol_to_networkx( + molecule=reactant_mol, + atom_idxs=reactant_template_indices, ) + post_graph = self.rdkit_mol_to_networkx( + molecule=product_mol, + atom_idxs=product_template_indices, + idx_relabel=product_to_reactant_mapping, + ) + + duplicate = self.is_duplicate( + pre_template_graph=pre_graph, + post_template_graph=post_graph, + comparison_group=self.RDKIT_COMPARISON_GROUP, + ) + + if duplicate: + reaction_metadata.activity_stats = False + + print( + f"Reaction {reaction_index}: " + "duplicate reaction detected and disabled." + ) + else: + print( + f"Reaction {reaction_index}: " + "unique reaction retained." + ) + + return reaction_metadata_items + + def clear_cache( + self, + comparison_group: str | None = None, + ) -> None: + """ + Clear stored reaction graphs. + + Args: + comparison_group: + Cache group to clear. When None, all cache groups are + cleared. + """ + if comparison_group is None: + for seen_graphs in self.seen_reactions.values(): + seen_graphs.clear() + + return + + self.seen_reactions.setdefault( + comparison_group, + [], + ).clear() + + # ------------------------------------------------------------------ + # Public graph-conversion API + # ------------------------------------------------------------------ + def rdkit_mol_to_networkx( self, molecule: Chem.Mol, + atom_idxs: set[int] | None = None, + idx_relabel: dict[int, int] | None = None, ) -> nx.Graph: """ Convert an in-memory RDKit molecule into a NetworkX graph. Coordinates are not read or stored. - Node attribute: + Node attributes: atom_label: Chemical element symbol. - Edge attribute: + Edge attributes: bond_label: - RDKit bond type. + RDKit bond type represented as a string. + + Args: + molecule: + RDKit molecule to convert. + atom_idxs: + Optional atom-index set defining the induced subgraph. + Atoms outside this set and bonds touching excluded atoms + are omitted. + idx_relabel: + Optional mapping from RDKit atom indices to graph node + IDs. This can be used to express a product graph in the + corresponding reactant-index space. + + Returns: + NetworkX representation of the selected molecule region. """ if molecule is None: raise ValueError( "Cannot create a graph from a None RDKit molecule." ) + included_atom_indices = ( + atom_idxs + if atom_idxs is not None + else { + atom.GetIdx() + for atom in molecule.GetAtoms() + } + ) + + if idx_relabel is not None: + missing_relabels = sorted( + included_atom_indices - idx_relabel.keys() + ) + + if missing_relabels: + raise ValueError( + "The atom-index relabel mapping does not contain " + f"entries for atom indices {missing_relabels}." + ) + graph = nx.Graph() for atom in molecule.GetAtoms(): - atom_id = atom.GetIdx() + atom_index = atom.GetIdx() + + if atom_index not in included_atom_indices: + continue + + node_id = self._resolve_node_id( + atom_index=atom_index, + idx_relabel=idx_relabel, + ) graph.add_node( - atom_id, + node_id, **{ self.NODE_ATTRIBUTE: atom.GetSymbol(), }, ) for bond in molecule.GetBonds(): - atom1_id = bond.GetBeginAtomIdx() - atom2_id = bond.GetEndAtomIdx() + atom1_index = bond.GetBeginAtomIdx() + atom2_index = bond.GetEndAtomIdx() + + if ( + atom1_index not in included_atom_indices + or atom2_index not in included_atom_indices + ): + continue + + node1_id = self._resolve_node_id( + atom_index=atom1_index, + idx_relabel=idx_relabel, + ) + node2_id = self._resolve_node_id( + atom_index=atom2_index, + idx_relabel=idx_relabel, + ) graph.add_edge( - atom1_id, - atom2_id, + node1_id, + node2_id, **{ self.EDGE_ATTRIBUTE: str( bond.GetBondType() @@ -260,13 +446,16 @@ def lammps_molecule_to_networkx( """ Convert a LAMMPS molecule-template file into a NetworkX graph. - Only the following sections are used: + Only the ``Types`` and ``Bonds`` sections are used. Coordinates, + charges, angles, dihedrals, impropers, atom IDs, and bond IDs do + not participate in graph-isomorphism comparison. - Types - Bonds + Args: + file_path: + Path to the LAMMPS molecule-template file. - Coordinates, charges, angles, dihedrals, impropers, atom IDs, - and bond IDs are not used in graph isomorphism comparison. + Returns: + NetworkX representation of the molecule template. """ file_path = Path(file_path) @@ -304,113 +493,136 @@ def lammps_molecule_to_networkx( return graph - def _add_lammps_atoms( + # ------------------------------------------------------------------ + # Private coupled-graph helpers + # ------------------------------------------------------------------ + + def _couple_graphs( self, - graph: nx.Graph, - type_lines: list[str], - file_path: Path, - ) -> None: - """ - Add atoms from a LAMMPS Types section to a graph. + pre_template_graph: nx.Graph, + post_template_graph: nx.Graph, + ) -> nx.Graph: """ - for line in type_lines: - parts = line.split() - - if len(parts) < 2: - raise ValueError( - f"Invalid Types line in {file_path}: {line!r}" - ) + Combine reactant and product graphs into one coupled graph. - try: - atom_id = int(parts[0]) - except ValueError as error: - raise ValueError( - f"Invalid atom ID in {file_path}: {line!r}" - ) from error + Every atom is represented twice: - atom_type = parts[1] + ("pre", atom_id) + ("post", atom_id) - if atom_id in graph: - raise ValueError( - f"Duplicate atom ID {atom_id} in {file_path}." - ) + A correspondence edge connects matching atom IDs across the two + phases, requiring one consistent mapping for both states. + """ + pre_atom_ids = set(pre_template_graph.nodes) + post_atom_ids = set(post_template_graph.nodes) - graph.add_node( - atom_id, - **{ - self.NODE_ATTRIBUTE: atom_type, - }, + if pre_atom_ids != post_atom_ids: + missing_from_post = sorted( + pre_atom_ids - post_atom_ids + ) + missing_from_pre = sorted( + post_atom_ids - pre_atom_ids ) - def _add_lammps_bonds( + raise ValueError( + "Pre- and post-reaction graphs must contain matching " + "atom IDs. " + f"Missing from post graph: {missing_from_post}. " + f"Missing from pre graph: {missing_from_pre}." + ) + + coupled_graph = nx.Graph() + + self._add_phase_to_coupled_graph( + source_graph=pre_template_graph, + coupled_graph=coupled_graph, + phase=self._PRE_PHASE, + ) + + self._add_phase_to_coupled_graph( + source_graph=post_template_graph, + coupled_graph=coupled_graph, + phase=self._POST_PHASE, + ) + + for atom_id in pre_atom_ids: + coupled_graph.add_edge( + (self._PRE_PHASE, atom_id), + (self._POST_PHASE, atom_id), + relationship=( + self._ATOM_CORRESPONDENCE_RELATIONSHIP + ), + **{ + self.EDGE_ATTRIBUTE: None, + }, + ) + + return coupled_graph + + def _add_phase_to_coupled_graph( self, - graph: nx.Graph, - bond_lines: list[str], - file_path: Path, + source_graph: nx.Graph, + coupled_graph: nx.Graph, + phase: str, ) -> None: - """ - Add bonds from a LAMMPS Bonds section to a graph. - """ - for line in bond_lines: - parts = line.split() + """Add one reaction phase to a coupled pre/post graph.""" + for atom_id, attributes in source_graph.nodes(data=True): + atom_label = attributes.get(self.NODE_ATTRIBUTE) - if len(parts) < 4: + if atom_label is None: raise ValueError( - f"Invalid Bonds line in {file_path}: {line!r}" + f"Node {atom_id} is missing the required " + f"{self.NODE_ATTRIBUTE!r} attribute." ) - try: - bond_id = int(parts[0]) - atom1_id = int(parts[2]) - atom2_id = int(parts[3]) - except ValueError as error: - raise ValueError( - f"Invalid Bonds line in {file_path}: {line!r}" - ) from error + coupled_graph.add_node( + (phase, atom_id), + phase=phase, + **{ + self.NODE_ATTRIBUTE: atom_label, + }, + ) - bond_type = parts[1] + for atom1_id, atom2_id, attributes in source_graph.edges( + data=True + ): + bond_label = attributes.get(self.EDGE_ATTRIBUTE) - self._validate_bond_atoms( - graph=graph, - bond_id=bond_id, - atom1_id=atom1_id, - atom2_id=atom2_id, - source=file_path, - ) + if bond_label is None: + raise ValueError( + f"Edge {atom1_id}-{atom2_id} is missing the required " + f"{self.EDGE_ATTRIBUTE!r} attribute." + ) - graph.add_edge( - atom1_id, - atom2_id, + coupled_graph.add_edge( + (phase, atom1_id), + (phase, atom2_id), + relationship=self._BOND_RELATIONSHIP, **{ - self.EDGE_ATTRIBUTE: bond_type, + self.EDGE_ATTRIBUTE: bond_label, }, ) + @staticmethod + def _resolve_node_id( + atom_index: int, + idx_relabel: dict[int, int] | None, + ) -> int: + """Resolve an RDKit atom index to its output graph node ID.""" + if idx_relabel is None: + return atom_index + + return idx_relabel[atom_index] + + # ------------------------------------------------------------------ + # Private LAMMPS parsing helpers + # ------------------------------------------------------------------ + def _read_lammps_sections( self, file_path: Path, ) -> dict[str, list[str]]: - """ - Read relevant sections from a LAMMPS molecule-template file. - """ - relevant_sections = { - "Types", - "Bonds", - } - - all_section_headers = { - "Coords", - "Types", - "Charges", - "Molecules", - "Bonds", - "Angles", - "Dihedrals", - "Impropers", - "Special Bond Counts", - "Special Bonds", - } - + """Read relevant sections from a LAMMPS molecule-template file.""" sections: dict[str, list[str]] = {} current_section: str | None = None @@ -419,7 +631,6 @@ def _read_lammps_sections( encoding="utf-8", ) as file: for raw_line in file: - # Remove comments while preserving the actual data. line = raw_line.split( "#", maxsplit=1, @@ -428,8 +639,8 @@ def _read_lammps_sections( if not line: continue - if line in all_section_headers: - if line in relevant_sections: + if line in self._LAMMPS_SECTION_HEADERS: + if line in self._LAMMPS_RELEVANT_SECTIONS: current_section = line sections.setdefault( current_section, @@ -445,205 +656,112 @@ def _read_lammps_sections( return sections - def _validate_bond_atoms( + def _add_lammps_atoms( self, graph: nx.Graph, - bond_id: int, - atom1_id: int, - atom2_id: int, - source: Path | str, + type_lines: list[str], + file_path: Path, ) -> None: - """ - Ensure that both atoms referenced by a bond exist. - """ - undefined_atoms = [ - atom_id - for atom_id in (atom1_id, atom2_id) - if atom_id not in graph - ] - - if undefined_atoms: - raise ValueError( - f"Bond {bond_id} references undefined atom IDs " - f"{undefined_atoms} in {source}." - ) - - def compare_graphs( - self, - molecule_file_paths: list[str | Path], - ) -> dict[str, bool]: - """ - Compare LAMMPS pre/post molecule-template pairs. - - A pre-template filename must contain ``pre``. Its corresponding - post-template filename is found by replacing the first occurrence - of ``pre`` with ``post``. - - Returns: - Mapping from each pre-template path to its duplicate status. - """ - results: dict[str, bool] = {} - - for file_path_value in molecule_file_paths: - pre_file_path = Path(file_path_value) - - if "pre" not in pre_file_path.name: - continue - - post_file_path = pre_file_path.with_name( - pre_file_path.name.replace( - "pre", - "post", - 1, - ) - ) + """Add atoms from a LAMMPS ``Types`` section.""" + for line in type_lines: + parts = line.split() - if not post_file_path.is_file(): - print( - "Skipping reaction because its post-template file " - f"does not exist: {post_file_path}" + if len(parts) < 2: + raise ValueError( + f"Invalid Types line in {file_path}: {line!r}" ) - continue - - pre_graph = self.lammps_molecule_to_networkx( - pre_file_path - ) - - post_graph = self.lammps_molecule_to_networkx( - post_file_path - ) - duplicate = self.is_duplicate( - pre_template_graph=pre_graph, - post_template_graph=post_graph, - comparison_group=self.LAMMPS_COMPARISON_GROUP, - ) + try: + atom_id = int(parts[0]) + except ValueError as error: + raise ValueError( + f"Invalid atom ID in {file_path}: {line!r}" + ) from error - results[str(pre_file_path)] = duplicate + atom_type = parts[1] - status = ( - "Duplicate" - if duplicate - else "Unique" - ) + if atom_id in graph: + raise ValueError( + f"Duplicate atom ID {atom_id} in {file_path}." + ) - print( - f"{status} reaction: " - f"{pre_file_path.name} -> " - f"{post_file_path.name}" + graph.add_node( + atom_id, + **{ + self.NODE_ATTRIBUTE: atom_type, + }, ) - return results - - def compare_graphs_mol( + def _add_lammps_bonds( self, - reaction_metadata_items: list[ReactionMetadata], - ) -> list[ReactionMetadata]: - """ - Detect duplicate reactions using in-memory RDKit molecules. - - Reactions whose ``activity_stats`` value is already False are - skipped. - - Duplicate reactions are disabled by setting: - - reaction_metadata.activity_stats = False - - Args: - reaction_metadata_items: - Prepared reaction metadata objects. - - Returns: - The original metadata list with duplicate reactions disabled. - """ - for reaction_index, reaction_metadata in enumerate( - reaction_metadata_items, - start=1, - ): - if reaction_metadata.activity_stats is False: - continue + graph: nx.Graph, + bond_lines: list[str], + file_path: Path, + ) -> None: + """Add bonds from a LAMMPS ``Bonds`` section.""" + for line in bond_lines: + parts = line.split() - reactant_mol = ( - reaction_metadata.reactant_combined_RDmol - ) - product_mol = ( - reaction_metadata.product_combined_RDmol - ) - template_reactant_to_product_mapping = ( - reaction_metadata.template_reactant_to_product_mapping - ) - if reactant_mol is None: + if len(parts) < 4: raise ValueError( - f"Reaction {reaction_index} does not contain a " - "combined reactant RDKit molecule." + f"Invalid Bonds line in {file_path}: {line!r}" ) - if product_mol is None: + try: + bond_id = int(parts[0]) + atom1_id = int(parts[2]) + atom2_id = int(parts[3]) + except ValueError as error: raise ValueError( - f"Reaction {reaction_index} does not contain a " - "combined product RDKit molecule." - ) + f"Invalid Bonds line in {file_path}: {line!r}" + ) from error - pre_graph = self.rdkit_mol_to_networkx( - reactant_mol - ) + bond_type = parts[1] - post_graph = self.rdkit_mol_to_networkx( - product_mol + self._validate_bond_atoms( + graph=graph, + bond_id=bond_id, + atom1_id=atom1_id, + atom2_id=atom2_id, + source=file_path, ) - duplicate = self.is_duplicate( - pre_template_graph=pre_graph, - post_template_graph=post_graph, - comparison_group=self.RDKIT_COMPARISON_GROUP, + graph.add_edge( + atom1_id, + atom2_id, + **{ + self.EDGE_ATTRIBUTE: bond_type, + }, ) - if duplicate: - reaction_metadata.activity_stats = False - - print( - f"Reaction {reaction_index}: " - "duplicate reaction detected and disabled." - ) - else: - print( - f"Reaction {reaction_index}: " - "unique reaction retained." - ) - - return reaction_metadata_items - - def clear_cache( - self, - comparison_group: str | None = None, + @staticmethod + def _validate_bond_atoms( + graph: nx.Graph, + bond_id: int, + atom1_id: int, + atom2_id: int, + source: Path | str, ) -> None: - """ - Clear stored reaction graphs. - - Args: - comparison_group: - Clear only one cache group. When None, all cache groups - are cleared. - """ - if comparison_group is None: - for seen_graphs in self.seen_reactions.values(): - seen_graphs.clear() - - return + """Ensure that both atoms referenced by a bond exist.""" + undefined_atoms = [ + atom_id + for atom_id in (atom1_id, atom2_id) + if atom_id not in graph + ] - self.seen_reactions.setdefault( - comparison_group, - [], - ).clear() + if undefined_atoms: + raise ValueError( + f"Bond {bond_id} references undefined atom IDs " + f"{undefined_atoms} in {source}." + ) -if __name__ == "__main__": +def _main() -> None: + """Run the standalone LAMMPS deduplication example.""" folder_path = Path( "/mnt/c/Users/janit/Documents/GitHub/AutoREACTER/" "examples/AutoREACTER_outputs/" "Epoxy_Test_Primary_Diamine_Diepoxy/" - "LAMMPS_input_files/" - "Epoxy_Test_Primary_Diamine_Diepoxy_epoxy_test" ) if not folder_path.is_dir(): @@ -663,20 +781,17 @@ def clear_cache( ) detector = DeduplicationDetector() - - results = detector.compare_graphs( - pre_template_files - ) + results = detector.compare_graphs(pre_template_files) print("\nDeduplication results:") for file_path, duplicate in results.items(): - status = ( - "duplicate" - if duplicate - else "unique" - ) + status = "duplicate" if duplicate else "unique" print( f"{Path(file_path).name}: {status}" - ) \ No newline at end of file + ) + + +if __name__ == "__main__": + _main() \ No newline at end of file From c262190275d2a19fd0db36dfa6d657fab64d7e53 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 09:45:40 -0400 Subject: [PATCH 022/176] Refactor reaction_progression for clarity Clean up imports, variable names, docstrings, and formatting throughout reaction_progression.py. Replace debug prints with informative log messages, improve inline comments, and apply consistent style (trailing newline, line-length wrapping). --- .../reaction_progression.py | 256 +++++++++++------- 1 file changed, 161 insertions(+), 95 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 8d5e7121..391c2690 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -1,26 +1,34 @@ -MAX_LOOP = 5 # Maximum number of iterations for the reaction progression loop. +MAX_LOOP = 5 # Maximum number of reaction progression iterations. from dataclasses import dataclass, field from typing import TYPE_CHECKING from rdkit import Chem -from AutoREACTER.detectors.functional_groups_detector import FunctionalGroupsDetector +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) from AutoREACTER.detectors.reaction_detector import ReactionDetector -from AutoREACTER.reaction_preparation.deduplication_detector import DeduplicationDetector +from AutoREACTER.reaction_preparation.deduplication_detector import ( + DeduplicationDetector, +) if TYPE_CHECKING: - from AutoREACTER.session import Session from AutoREACTER.detectors.functional_groups_detector import MonomerRole - from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ReactionInstance, ReactionMetadata + from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( + ReactionInstance, + ReactionMetadata, + ) + from AutoREACTER.session import Session @dataclass(slots=True) class MonomerRoleforIndexBasedFGDetection: """ - Represents a monomer role with its associated properties for - index-based functional group detection. + Represents a monomer role used for index-based functional-group + detection. """ + smiles: str name: str indexes_in_template: list[int] @@ -32,8 +40,9 @@ class MonomerRoleforIndexBasedFGDetection: @dataclass(slots=True) class ReactionProgressionSession: """ - Placeholder for future reaction progression state. + Stores state associated with reaction progression. """ + monomer_roles: list["MonomerRole"] = field(default_factory=list) iteration: int = 0 @@ -41,124 +50,167 @@ class ReactionProgressionSession: class ReactionProgression: def __init__(self, session: "Session"): self.session = session - self.session.reaction_progression_session = ReactionProgressionSession() + self.session.reaction_progression_session = ( + ReactionProgressionSession() + ) + self.fg_detector = FunctionalGroupsDetector() self.rxn_detector = ReactionDetector() - def reaction_progression(self, max_loop: int = MAX_LOOP) -> list["ReactionMetadata"]: + def reaction_progression( + self, + max_loop: int = MAX_LOOP, + ) -> list["ReactionMetadata"]: """ - Progresses the reaction by iteratively applying detected chemistries - to the session's molecules. + Progress a reaction by repeatedly detecting functional groups, + detecting reactions, preparing reactions, and removing duplicates. Args: - max_loop (int): Maximum number of iterations for the reaction progression loop. + max_loop: + Maximum number of progression iterations. + + Returns: + Prepared reaction metadata accumulated across the progression + loop. """ iteration = 0 monomer_roles_in_loop = self.session.monomer_roles.copy() - - # Accumulate prepared reactions across iterations to avoid reprocessing in each loop. all_prepared_reactions: list["ReactionMetadata"] = [] while iteration < max_loop: iteration += 1 self.session.reaction_progression_session.iteration = iteration - size_of_initial_reaction_pool = self._length_of_active_reactions() + + size_of_initial_reaction_pool = ( + self._length_of_active_reactions() + ) + if iteration == 1: self._populate_monomer_roles() if iteration > 1: print( f"Starting iteration {iteration} " - f"of the reaction progression loop." + "of the reaction progression loop." ) - size_of_pool = self._set_is_monomer_flag() + self._set_is_monomer_flag() + + initial_reaction_pool_size = ( + self._length_of_active_reactions() + ) - print(self.session.monomer_roles) # Debug print + print( + f"Initial reaction pool size at iteration {iteration}: " + f"{initial_reaction_pool_size}" + ) - monomer_roles_for_idx_based_fg_detection = ( + roles_for_fg_detection = ( self._prepare_products_for_idx_based_fg_detection() ) fg_detection_results = ( self.fg_detector.index_based_functional_groups_detector( - monomer_roles_for_idx_based_fg_detection + roles_for_fg_detection ) ) if not fg_detection_results: print( - f"No new functional groups detected in iteration {iteration}. " - f"Ending the reaction progression loop." + f"No new functional groups detected in iteration " + f"{iteration}. Ending the reaction progression loop." ) break monomer_roles_in_loop.extend(fg_detection_results) - rxns = self.rxn_detector.index_based_reaction_detector( - monomer_roles_in_loop + reaction_instances = ( + self.rxn_detector.index_based_reaction_detector( + monomer_roles_in_loop + ) ) - # Debug prints to trace the reaction progression loop. - if not rxns: + if not reaction_instances: print( f"No new reactions detected in iteration {iteration}. " - f"Ending the reaction progression loop." + "Ending the reaction progression loop." ) break - print(len(rxns)) # Debug print (was len(reaction_instances); now just the new batch) - print(monomer_roles_in_loop) # Debug print + print(len(reaction_instances)) - # - prepared_reactions = self._index_based_reaction_preparation( - reaction_instances=rxns + prepared_reactions = ( + self._index_based_reaction_preparation( + reaction_instances=reaction_instances + ) ) - print(prepared_reactions) # Debug print - # Accumulate prepared reactions across iterations. + print(prepared_reactions) + all_prepared_reactions.extend(prepared_reactions) + + print( + f"Total prepared reactions after iteration {iteration}: " + f"{len(all_prepared_reactions)}" + ) print(size_of_initial_reaction_pool) + deduplication_detector = DeduplicationDetector() - all_prepared_reactions = deduplication_detector.compare_graphs_mol( - all_prepared_reactions + + all_prepared_reactions = ( + deduplication_detector.compare_graphs_mol( + all_prepared_reactions + ) ) - - if self._loop_break_condition( - size_before=size_of_initial_reaction_pool, size_after=len(all_prepared_reactions) - ): + + should_break = self._loop_break_condition( + size_before=size_of_initial_reaction_pool, + size_after=len(all_prepared_reactions), + ) + + if should_break: self.session.reaction_metadata = all_prepared_reactions return all_prepared_reactions + self.session.reaction_metadata = all_prepared_reactions return all_prepared_reactions def _index_based_reaction_preparation( - self, reaction_instances: list["ReactionInstance"] + self, + reaction_instances: list["ReactionInstance"], ) -> list["ReactionMetadata"]: - from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions + from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( + PrepareReactions, + ) + + reaction_preparer = PrepareReactions(self.session) + + return reaction_preparer._prepare_reactions_stage( + reaction_instances + ) - prepare_reactions = PrepareReactions(self.session) - prepared_reactions = prepare_reactions._prepare_reactions_stage(reaction_instances) - return prepared_reactions - def _prepare_products_for_idx_based_fg_detection( self, ) -> list[MonomerRoleforIndexBasedFGDetection]: """ - Prepares generated reaction products for index-based functional group detection. + Prepare generated products for index-based functional-group + detection. """ - monomer_roles_for_idx_based_fg_detection = [] + prepared_monomer_roles = [] reaction_metadata = self.session.reaction_metadata for reaction in reaction_metadata: if not reaction.activity_stats: continue + product_mol = reaction.product_combined_RDmol + indexes_in_template, product_mol = self._get_product_idxs( - reaction.template_reactant_to_product_mapping, - product_mol - ) - monomer_roles_for_idx_based_fg_detection.append( + reaction.template_reactant_to_product_mapping, + product_mol, + ) + + prepared_monomer_roles.append( MonomerRoleforIndexBasedFGDetection( smiles=self._get_product_smiles(product_mol), name=f"new_{reaction.reaction_id}", @@ -169,17 +221,21 @@ def _prepare_products_for_idx_based_fg_detection( ) ) - return monomer_roles_for_idx_based_fg_detection + return prepared_monomer_roles - def _sanitize_molecule(self, mol: Chem.Mol) -> Chem.Mol | None: + def _sanitize_molecule( + self, + mol: Chem.Mol, + ) -> Chem.Mol | None: """ - Sanitizes an RDKit molecule object. + Sanitize an RDKit molecule. Args: - mol (Chem.Mol): RDKit molecule object. + mol: + RDKit molecule to sanitize. Returns: - Chem.Mol | None: Sanitized molecule, or None if sanitization fails. + The sanitized molecule, or ``None`` when sanitization fails. """ self._clean_product(mol) @@ -191,7 +247,7 @@ def _sanitize_molecule(self, mol: Chem.Mol) -> Chem.Mol | None: def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: """ - Return a copy of the molecule with atom-map numbers and isotope + Return a copy of a molecule with atom-map numbers and isotope labels removed. The input molecule is not modified. @@ -204,11 +260,10 @@ def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: return cleaned_mol - def _get_product_smiles(self, mol: Chem.Mol) -> str: """ Convert a product molecule to SMILES without modifying the - original RDKit molecule. + original molecule. """ cleaned_mol = self._clean_product(mol) @@ -217,20 +272,21 @@ def _get_product_smiles(self, mol: Chem.Mol) -> str: except Exception: return "" - def _get_product_idxs( self, template_reactant_to_product_mapping: dict[int, int], mol: Chem.Mol, ) -> tuple[list[int], Chem.Mol]: """ - Retrieve mapped product atom idxs and keep only the largest - molecular fragment when the product contains multiple fragments. + Retrieve mapped product atom indexes. + + When the product contains disconnected fragments, retain only + the fragment with the largest number of heavy atoms and remap + the product indexes to that fragment. Returns: - A tuple containing: - - Product atom idxs relative to the returned molecule. - - The complete product or its largest fragment. + A tuple containing the product atom indexes and the retained + product molecule. """ product = Chem.Mol(mol) @@ -248,26 +304,24 @@ def _get_product_idxs( return product_idxs, product - def _keep_largest_fragment( self, mol: Chem.Mol, product_idxs: list[int], ) -> tuple[Chem.Mol, list[int]]: """ - Keep the fragment with the largest number of heavy atoms and - remap product atom idxs to the retained fragment. + Retain the fragment with the largest number of heavy atoms and + remap product atom indexes to the retained fragment. Args: mol: Molecule containing one or more disconnected fragments. product_idxs: - Product atom idxs referring to the original molecule. + Product atom indexes referring to the original molecule. Returns: - A tuple containing: - - The largest fragment. - - Product atom idxs remapped to the largest fragment. + A tuple containing the largest fragment and the remapped + product atom indexes. """ fragment_atom_mappings: list[tuple[int, ...]] = [] @@ -279,17 +333,21 @@ def _keep_largest_fragment( ) if not fragments: - raise ValueError("No fragments found in the product molecule.") + raise ValueError( + "No fragments found in the product molecule." + ) largest_fragment_position = max( range(len(fragments)), - key=lambda position: fragments[position].GetNumHeavyAtoms(), + key=lambda position: ( + fragments[position].GetNumHeavyAtoms() + ), ) largest_fragment = fragments[largest_fragment_position] - # The atom mapping stores: - # new fragment idx -> original molecule idx. + # Mapping direction: + # fragment atom index -> original molecule atom index original_atom_idxs = fragment_atom_mappings[ largest_fragment_position ] @@ -309,10 +367,10 @@ def _keep_largest_fragment( def _set_is_monomer_flag(self) -> int: """ - Sets the is_looped flag for each monomer role in the session. + Mark every session monomer role as looped. Returns: - int: Number of monomer roles before functional group detection. + Number of monomer roles in the session. """ for monomer_role in self.session.monomer_roles: monomer_role.is_looped = True @@ -321,38 +379,46 @@ def _set_is_monomer_flag(self) -> int: def _populate_monomer_roles(self) -> None: """ - Populates RDKit molecule objects for monomers marked as monomers. + Populate RDKit molecules for roles marked as monomers. """ for monomer in self.session.monomer_roles: if monomer.is_monomer: - monomer.rdkit_mol = self._smiles_to_rdkit_mol(monomer.smiles) + monomer.rdkit_mol = self._smiles_to_rdkit_mol( + monomer.smiles + ) - def _smiles_to_rdkit_mol(self, smiles: str) -> Chem.Mol | None: + def _smiles_to_rdkit_mol( + self, + smiles: str, + ) -> Chem.Mol | None: """ - Converts a SMILES string to an RDKit molecule object. - - Args: - smiles (str): SMILES string. - - Returns: - Chem.Mol | None: RDKit molecule object. + Convert a SMILES string to an RDKit molecule. """ return Chem.MolFromSmiles(smiles) - def _loop_break_condition(self, size_before: int, size_after: int) -> bool: + def _loop_break_condition( + self, + size_before: int, + size_after: int, + ) -> bool: + """ + Determine whether progression should stop based on pool growth. + """ if size_after <= size_before: print( - f"Breaking the loop as the pool did not grow " + "Breaking the loop as the pool did not grow " f"(before={size_before}, after={size_after})." ) return True + return False - + def _length_of_active_reactions(self) -> int: """ - Returns the number of reactions in the session that have activity stats. + Return the number of session reactions with activity statistics. """ return sum( - 1 for reaction in self.session.reaction_metadata + 1 + for reaction in self.session.reaction_metadata if reaction.activity_stats ) \ No newline at end of file From 4fb669d2d2123721157069e22b27f758fe7fd2df Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:19:13 -0400 Subject: [PATCH 023/176] Refactor reaction progression logic - Move MAX_LOOP constant below imports for clarity - Add MolSanitizeException import and improve sanitization error logging - Instantiate DeduplicationDetector once in __init__ instead of per-loop - Initialize all_prepared_reactions from session state to support resumption - Rename _set_is_monomer_flag to _set_is_looped_flag with proper scoping - Rename _length_of_active_reactions to _count_active_reactions with explicit parameter - Add _store_reactions helper to reduce duplication - Sync session.monomer_roles and session.reaction_metadata incrementally - Fix loop break condition to use pre-iteration pool size - Condense docstrings throughout --- .../reaction_progression.py | 186 ++++++++---------- 1 file changed, 86 insertions(+), 100 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 391c2690..8c64f887 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -1,9 +1,8 @@ -MAX_LOOP = 5 # Maximum number of reaction progression iterations. - from dataclasses import dataclass, field from typing import TYPE_CHECKING from rdkit import Chem +from rdkit.Chem.rdchem import MolSanitizeException from AutoREACTER.detectors.functional_groups_detector import ( FunctionalGroupsDetector, @@ -22,12 +21,12 @@ from AutoREACTER.session import Session +MAX_LOOP = 5 + + @dataclass(slots=True) class MonomerRoleforIndexBasedFGDetection: - """ - Represents a monomer role used for index-based functional-group - detection. - """ + """Monomer role used for index-based functional-group detection.""" smiles: str name: str @@ -39,9 +38,7 @@ class MonomerRoleforIndexBasedFGDetection: @dataclass(slots=True) class ReactionProgressionSession: - """ - Stores state associated with reaction progression. - """ + """State associated with reaction progression.""" monomer_roles: list["MonomerRole"] = field(default_factory=list) iteration: int = 0 @@ -56,48 +53,49 @@ def __init__(self, session: "Session"): self.fg_detector = FunctionalGroupsDetector() self.rxn_detector = ReactionDetector() + self.deduplication_detector = DeduplicationDetector() def reaction_progression( self, max_loop: int = MAX_LOOP, ) -> list["ReactionMetadata"]: """ - Progress a reaction by repeatedly detecting functional groups, - detecting reactions, preparing reactions, and removing duplicates. + Repeatedly detect functional groups, detect reactions, prepare + reactions, and remove duplicate products. Args: max_loop: Maximum number of progression iterations. Returns: - Prepared reaction metadata accumulated across the progression - loop. + Reaction metadata generated during the progression loop. """ iteration = 0 - monomer_roles_in_loop = self.session.monomer_roles.copy() - all_prepared_reactions: list["ReactionMetadata"] = [] + monomer_roles_in_loop = list["MonomerRole"]( + self.session.monomer_roles + ) + all_prepared_reactions: list["ReactionMetadata"] = list( + self.session.reaction_metadata + ) while iteration < max_loop: iteration += 1 self.session.reaction_progression_session.iteration = iteration - size_of_initial_reaction_pool = ( - self._length_of_active_reactions() - ) - if iteration == 1: self._populate_monomer_roles() - - if iteration > 1: + else: print( f"Starting iteration {iteration} " "of the reaction progression loop." ) - self._set_is_monomer_flag() + self._set_is_looped_flag(monomer_roles_in_loop) initial_reaction_pool_size = ( - self._length_of_active_reactions() + self._length_of_active_reactions( + self.session.reaction_metadata + ) ) print( @@ -123,6 +121,7 @@ def reaction_progression( break monomer_roles_in_loop.extend(fg_detection_results) + self.session.monomer_roles = monomer_roles_in_loop reaction_instances = ( self.rxn_detector.index_based_reaction_detector( @@ -137,40 +136,35 @@ def reaction_progression( ) break - print(len(reaction_instances)) - prepared_reactions = ( self._index_based_reaction_preparation( reaction_instances=reaction_instances ) ) - - print(prepared_reactions) - + all_prepared_reactions.extend(prepared_reactions) + self.session.reaction_metadata = all_prepared_reactions - print( - f"Total prepared reactions after iteration {iteration}: " - f"{len(all_prepared_reactions)}" + all_prepared_reactions = ( + self.deduplication_detector.compare_graphs_mol( + all_prepared_reactions + ) ) - print(size_of_initial_reaction_pool) + self.session.reaction_metadata = all_prepared_reactions - deduplication_detector = DeduplicationDetector() - - all_prepared_reactions = ( - deduplication_detector.compare_graphs_mol( + deduplicated_reaction_count = ( + self._length_of_active_reactions( all_prepared_reactions ) ) should_break = self._loop_break_condition( - size_before=size_of_initial_reaction_pool, - size_after=len(all_prepared_reactions), + size_before=initial_reaction_pool_size, + size_after=deduplicated_reaction_count, ) if should_break: - self.session.reaction_metadata = all_prepared_reactions - return all_prepared_reactions + return self._store_reactions(all_prepared_reactions) self.session.reaction_metadata = all_prepared_reactions return all_prepared_reactions @@ -192,14 +186,12 @@ def _index_based_reaction_preparation( def _prepare_products_for_idx_based_fg_detection( self, ) -> list[MonomerRoleforIndexBasedFGDetection]: - """ - Prepare generated products for index-based functional-group - detection. - """ - prepared_monomer_roles = [] - reaction_metadata = self.session.reaction_metadata + """Prepare generated products for functional-group detection.""" + prepared_monomer_roles: list[ + MonomerRoleforIndexBasedFGDetection + ] = [] - for reaction in reaction_metadata: + for reaction in self.session.reaction_metadata: if not reaction.activity_stats: continue @@ -215,40 +207,45 @@ def _prepare_products_for_idx_based_fg_detection( smiles=self._get_product_smiles(product_mol), name=f"new_{reaction.reaction_id}", indexes_in_template=indexes_in_template, - is_monomer=False, - is_looped=False, rdkit_mol=self._sanitize_molecule(product_mol), ) ) return prepared_monomer_roles + + def _store_reactions( + self, + reactions: list["ReactionMetadata"], + ) -> list["ReactionMetadata"]: + self.session.reaction_metadata = reactions + return reactions def _sanitize_molecule( self, mol: Chem.Mol, ) -> Chem.Mol | None: """ - Sanitize an RDKit molecule. + Sanitize an RDKit molecule by cleaning it and applying RDKit sanitization. Args: - mol: - RDKit molecule to sanitize. + mol: The RDKit molecule to sanitize. Returns: - The sanitized molecule, or ``None`` when sanitization fails. + The sanitized molecule, or ``None`` if sanitization fails. """ - self._clean_product(mol) + cleaned_mol = self._clean_product(mol) try: - Chem.SanitizeMol(mol) - return mol - except Exception: + Chem.SanitizeMol(cleaned_mol) + except Exception as error: + print(f"Could not sanitize product molecule: {error}") return None + return cleaned_mol + def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: """ - Return a copy of a molecule with atom-map numbers and isotope - labels removed. + Return a molecule copy without atom-map numbers or isotope labels. The input molecule is not modified. """ @@ -261,10 +258,7 @@ def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: return cleaned_mol def _get_product_smiles(self, mol: Chem.Mol) -> str: - """ - Convert a product molecule to SMILES without modifying the - original molecule. - """ + """Convert a cleaned product molecule to SMILES.""" cleaned_mol = self._clean_product(mol) try: @@ -280,16 +274,11 @@ def _get_product_idxs( """ Retrieve mapped product atom indexes. - When the product contains disconnected fragments, retain only - the fragment with the largest number of heavy atoms and remap - the product indexes to that fragment. - - Returns: - A tuple containing the product atom indexes and the retained - product molecule. + When the product contains multiple fragments, retain the fragment + with the largest number of heavy atoms and remap the product + indexes to that fragment. """ product = Chem.Mol(mol) - product_idxs = list( template_reactant_to_product_mapping.values() ) @@ -311,17 +300,16 @@ def _keep_largest_fragment( ) -> tuple[Chem.Mol, list[int]]: """ Retain the fragment with the largest number of heavy atoms and - remap product atom indexes to the retained fragment. + remap the product indexes to the retained fragment. Args: mol: Molecule containing one or more disconnected fragments. product_idxs: - Product atom indexes referring to the original molecule. + Product indexes referring to the original molecule. Returns: - A tuple containing the largest fragment and the remapped - product atom indexes. + The largest fragment and its remapped product indexes. """ fragment_atom_mappings: list[tuple[int, ...]] = [] @@ -365,22 +353,16 @@ def _keep_largest_fragment( return largest_fragment, remapped_product_idxs - def _set_is_monomer_flag(self) -> int: - """ - Mark every session monomer role as looped. - - Returns: - Number of monomer roles in the session. - """ - for monomer_role in self.session.monomer_roles: + def _set_is_looped_flag( + self, + monomer_roles: list["MonomerRole"], + ) -> None: + """Mark the supplied monomer roles as already processed.""" + for monomer_role in monomer_roles: monomer_role.is_looped = True - return len(self.session.monomer_roles) - def _populate_monomer_roles(self) -> None: - """ - Populate RDKit molecules for roles marked as monomers. - """ + """Create RDKit molecules for roles marked as monomers.""" for monomer in self.session.monomer_roles: if monomer.is_monomer: monomer.rdkit_mol = self._smiles_to_rdkit_mol( @@ -391,9 +373,7 @@ def _smiles_to_rdkit_mol( self, smiles: str, ) -> Chem.Mol | None: - """ - Convert a SMILES string to an RDKit molecule. - """ + """Convert a SMILES string to an RDKit molecule.""" return Chem.MolFromSmiles(smiles) def _loop_break_condition( @@ -401,9 +381,7 @@ def _loop_break_condition( size_before: int, size_after: int, ) -> bool: - """ - Determine whether progression should stop based on pool growth. - """ + """Return whether the active reaction pool failed to grow.""" if size_after <= size_before: print( "Breaking the loop as the pool did not grow " @@ -413,12 +391,20 @@ def _loop_break_condition( return False - def _length_of_active_reactions(self) -> int: + def _count_active_reactions( + self, + reactions: list["ReactionMetadata"], + ) -> int: """ - Return the number of session reactions with activity statistics. + Count the number of active reactions in the supplied list. + + Args: + reactions: A list of ``ReactionMetadata`` objects to check for activity. + + Returns: + The number of reactions that have activity statistics. """ return sum( - 1 - for reaction in self.session.reaction_metadata - if reaction.activity_stats - ) \ No newline at end of file + bool(reaction.activity_stats) + for reaction in reactions + ) \ No newline at end of file From fb1d5573bfb58a69e603af321214068cfaf5efe1 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:20:40 -0400 Subject: [PATCH 024/176] Refine reaction progression loop state handling Updates the progression loop to track reactions through a single `all_prepared_reactions` list, keep `session.reaction_metadata` synchronized before and after deduplication, and base loop-break checks on the updated pool. It also simplifies list initialization typing, rewrites the method docstring for clarity, adds per-iteration reaction count logging, and replaces early return with a clean loop break followed by a single final return. --- .../reaction_progression.py | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 8c64f887..b26c26f9 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -60,23 +60,15 @@ def reaction_progression( max_loop: int = MAX_LOOP, ) -> list["ReactionMetadata"]: """ - Repeatedly detect functional groups, detect reactions, prepare - reactions, and remove duplicate products. - - Args: - max_loop: - Maximum number of progression iterations. - - Returns: - Reaction metadata generated during the progression loop. + Progresses the reaction process iteratively, detecting functional groups and reactions, + preparing reactions, and deduplicating them until no new reactions are found or the maximum + number of iterations is reached. + + Returns a list of all prepared reaction metadata. """ iteration = 0 - monomer_roles_in_loop = list["MonomerRole"]( - self.session.monomer_roles - ) - all_prepared_reactions: list["ReactionMetadata"] = list( - self.session.reaction_metadata - ) + monomer_roles_in_loop = list(self.session.monomer_roles) + all_prepared_reactions = list(self.session.reaction_metadata) while iteration < max_loop: iteration += 1 @@ -94,7 +86,7 @@ def reaction_progression( initial_reaction_pool_size = ( self._length_of_active_reactions( - self.session.reaction_metadata + all_prepared_reactions ) ) @@ -141,15 +133,24 @@ def reaction_progression( reaction_instances=reaction_instances ) ) - + all_prepared_reactions.extend(prepared_reactions) + + # Required for internal reaction-state modifications. self.session.reaction_metadata = all_prepared_reactions + print( + f"Total prepared reactions after iteration {iteration}: " + f"{len(all_prepared_reactions)}" + ) + all_prepared_reactions = ( self.deduplication_detector.compare_graphs_mol( - all_prepared_reactions + self.session.reaction_metadata ) ) + + # Update the session with the deduplicated reactions. self.session.reaction_metadata = all_prepared_reactions deduplicated_reaction_count = ( @@ -158,13 +159,11 @@ def reaction_progression( ) ) - should_break = self._loop_break_condition( + if self._loop_break_condition( size_before=initial_reaction_pool_size, size_after=deduplicated_reaction_count, - ) - - if should_break: - return self._store_reactions(all_prepared_reactions) + ): + break self.session.reaction_metadata = all_prepared_reactions return all_prepared_reactions From 5f350a7a7d208ac1a58ac786845b41f00bd31cd8 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:20:59 -0400 Subject: [PATCH 025/176] Add uncoupled pair-based duplicate detection Introduces is_duplicate_pair() for topology-only comparison of (reactant, product) graph pairs without coupling them into a single graph or requiring cross-phase atom mapping. Updates compare_graphs_mol() to use this simpler approach and adds index_source parameter supporting 'template' or 'first_shell' atom-index selection. Also clears the new seen_reaction_pairs cache in reset_seen_reactions(). --- .../deduplication_detector.py | 195 +++++++++++++++--- 1 file changed, 164 insertions(+), 31 deletions(-) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index a067c719..27ef363c 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -69,6 +69,9 @@ def __init__(self) -> None: self.LAMMPS_COMPARISON_GROUP: [], self.RDKIT_COMPARISON_GROUP: [], } + self.seen_reaction_pairs: dict[str, list[tuple[nx.Graph, nx.Graph]]] = { + self.RDKIT_COMPARISON_GROUP: [], + } # ------------------------------------------------------------------ # Public duplicate-detection API @@ -134,6 +137,79 @@ def is_duplicate( seen_graphs.append(coupled_graph.copy()) return False + def is_duplicate_pair( + self, + pre_graph: nx.Graph, + post_graph: nx.Graph, + comparison_group: str, + ) -> bool: + """ + # NEW METHOD + Simple, uncoupled duplicate check for a (reactant graph, product graph) + pair. + + Unlike is_duplicate, this does NOT combine the two graphs into one + coupled graph and does NOT require a single consistent atom mapping + across both phases. It only checks graph topology and atom/bond + labels — no coordinates, no atom IDs, no bond IDs, no cross-phase + atom correspondence. + + A pair is a duplicate only if BOTH: + - pre_graph is isomorphic to some cached pre_graph, AND + - post_graph is isomorphic to that SAME cached entry's post_graph. + + Args: + pre_graph: + Reactant-side graph, already restricted to the desired atom + indices (e.g. via rdkit_mol_to_networkx(atom_idxs=...)). + post_graph: + Product-side graph, already restricted to the desired atom + indices. + comparison_group: + Cache group used for the comparison. + + Returns: + True when an equivalent (reactant, product) pair was already + cached. Otherwise, caches the pair and returns False. + """ + node_match = nx.algorithms.isomorphism.categorical_node_match( + self.NODE_ATTRIBUTE, + None, + ) + + edge_match = nx.algorithms.isomorphism.categorical_edge_match( + self.EDGE_ATTRIBUTE, + None, + ) + + seen_pairs = self.seen_reaction_pairs.setdefault( + comparison_group, + [], + ) + + for seen_pre, seen_post in seen_pairs: + if pre_graph.number_of_nodes() != seen_pre.number_of_nodes(): + continue + if pre_graph.number_of_edges() != seen_pre.number_of_edges(): + continue + if post_graph.number_of_nodes() != seen_post.number_of_nodes(): + continue + if post_graph.number_of_edges() != seen_post.number_of_edges(): + continue + + if not nx.is_isomorphic( + pre_graph, seen_pre, node_match=node_match, edge_match=edge_match + ): + continue + + if nx.is_isomorphic( + post_graph, seen_post, node_match=node_match, edge_match=edge_match + ): + return True + + seen_pairs.append((pre_graph.copy(), post_graph.copy())) + return False + def compare_graphs( self, molecule_file_paths: list[str | Path], @@ -183,9 +259,9 @@ def compare_graphs( post_file_path ) - duplicate = self.is_duplicate( - pre_template_graph=pre_graph, - post_template_graph=post_graph, + duplicate = self.is_duplicate_pair( + pre_graph=pre_graph, + post_graph=post_graph, comparison_group=self.LAMMPS_COMPARISON_GROUP, ) @@ -203,6 +279,10 @@ def compare_graphs( def compare_graphs_mol( self, reaction_metadata_items: list[ReactionMetadata], + index_source: str = "template", # which ReactionMetadata index attribute + # restricts the graph build. Defaults to + # "template". Other supported value: + # "first_shell". ) -> list[ReactionMetadata]: """ Detect duplicate reactions using in-memory RDKit molecules. @@ -211,14 +291,27 @@ def compare_graphs_mol( skipped. Detected duplicates are disabled by setting ``activity_stats`` to False. - Only atoms included in - ``template_reactant_to_product_mapping`` participate in duplicate - detection. Product atom indices are relabeled into reactant-index - space before the pre/post graphs are coupled. + # NEW: Comparison is now a simple, uncoupled topology check. The + # reactant graph is built restricted to the selected reactant indices; + # the product graph is built restricted to the corresponding product + # indices. These two graphs form one "set" for this reaction. Each new + # set is compared against previously seen sets using is_duplicate_pair: + # if both the reactant graph and the product graph independently match + # a previously seen pair's reactant/product graphs (same atom/bond + # topology and labels — no coordinates, no atom IDs, no bond IDs, no + # cross-phase atom correspondence), the reaction is marked as a + # duplicate and disabled. Args: reaction_metadata_items: Prepared reaction metadata objects. + index_source: + Selects which ReactionMetadata attribute defines the + restricted atom-index set used to build the pre/post graphs. + "template" (default) uses template_reactant_to_product_mapping. + "first_shell" restricts the reactant side to + reaction_metadata.first_shell (mapped through + reactant_to_product_mapping for the product side) instead. Returns: The original metadata list with duplicate reactions disabled. @@ -233,10 +326,6 @@ def compare_graphs_mol( reactant_mol = reaction_metadata.reactant_combined_RDmol product_mol = reaction_metadata.product_combined_RDmol - reactant_to_product_mapping = ( - reaction_metadata.template_reactant_to_product_mapping - ) - if reactant_mol is None: raise ValueError( f"Reaction {reaction_index} does not contain a " @@ -249,27 +338,60 @@ def compare_graphs_mol( "combined product RDKit molecule." ) - if not reactant_to_product_mapping: - raise ValueError( - f"Reaction {reaction_index} does not contain a " - "template_reactant_to_product_mapping; duplicate " - "comparison cannot be restricted to template atoms." + # index_source selection block: picks which reactant->product + # index mapping restricts the graph build. + if index_source == "template": + reactant_to_product_mapping = ( + reaction_metadata.template_reactant_to_product_mapping ) - reactant_template_indices = set( - reactant_to_product_mapping - ) + if not reactant_to_product_mapping: + raise ValueError( + f"Reaction {reaction_index} does not contain a " + "template_reactant_to_product_mapping; duplicate " + "comparison cannot be restricted to template atoms." + ) + + elif index_source == "first_shell": + # Build the restriction from first_shell reactant indices, + # mapped to product indices via the full reactant_to_product_mapping. + first_shell_idxs = reaction_metadata.first_shell + full_mapping = reaction_metadata.reactant_to_product_mapping + + if not first_shell_idxs: + raise ValueError( + f"Reaction {reaction_index} does not contain " + "first_shell indices; duplicate comparison cannot " + "be restricted to first-shell atoms." + ) + + if not full_mapping: + raise ValueError( + f"Reaction {reaction_index} does not contain a " + "reactant_to_product_mapping; duplicate comparison " + "cannot be restricted to first-shell atoms." + ) + + reactant_to_product_mapping = { + r_idx: full_mapping[r_idx] + for r_idx in first_shell_idxs + if r_idx in full_mapping + } - product_to_reactant_mapping = { - product_index: reactant_index - for reactant_index, product_index - in reactant_to_product_mapping.items() - } + else: + raise ValueError( + f"Unsupported index_source {index_source!r}. " + "Expected 'template' or 'first_shell'." + ) - product_template_indices = set( - product_to_reactant_mapping - ) + reactant_template_indices = set(reactant_to_product_mapping) + product_template_indices = set(reactant_to_product_mapping.values()) + # NEW: no idx_relabel — each graph keeps its own native atom + # indices. Isomorphism comparison doesn't care about absolute + # index/label values, only structure + atom_label/bond_label + # attributes, so relabeling into a shared index space is + # unnecessary for this simple pairwise check. pre_graph = self.rdkit_mol_to_networkx( molecule=reactant_mol, atom_idxs=reactant_template_indices, @@ -278,12 +400,13 @@ def compare_graphs_mol( post_graph = self.rdkit_mol_to_networkx( molecule=product_mol, atom_idxs=product_template_indices, - idx_relabel=product_to_reactant_mapping, ) - duplicate = self.is_duplicate( - pre_template_graph=pre_graph, - post_template_graph=post_graph, + # NEW: simple uncoupled comparison instead of is_duplicate's + # coupled-graph approach. + duplicate = self.is_duplicate_pair( + pre_graph=pre_graph, + post_graph=post_graph, comparison_group=self.RDKIT_COMPARISON_GROUP, ) @@ -318,6 +441,10 @@ def clear_cache( for seen_graphs in self.seen_reactions.values(): seen_graphs.clear() + # NEW: also clear the pairwise cache used by compare_graphs_mol. + for seen_pairs in self.seen_reaction_pairs.values(): + seen_pairs.clear() + return self.seen_reactions.setdefault( @@ -325,6 +452,12 @@ def clear_cache( [], ).clear() + # NEW: mirror the clear on the pairwise cache. + self.seen_reaction_pairs.setdefault( + comparison_group, + [], + ).clear() + # ------------------------------------------------------------------ # Public graph-conversion API # ------------------------------------------------------------------ From 7d5027675a602447b2ca74b03539ede3da310eaa Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:21:16 -0400 Subject: [PATCH 026/176] Fix forced-reaction mode for same reactants Remove redundant AddHs calls and mol copies for mol_reactant_1/2 in forced-reaction mode, and add swapped ordering for same-reactant cases so both orientations are tried. --- .../reaction_processor/prepare_reactions.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 426e88e7..8444289c 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -223,24 +223,15 @@ def _process_reaction_instances( if loop: # FORCED-REACTION MODE: use the actual index-scoped rdkit_mol (not a # fresh SMILES reparse) so atom indices line up with fg_*_indexes. - # AddHs only appends new explicit H atoms at the end, so heavy-atom - # indices — the ones that matter for the FG match indices — are preserved. - mol_reactant_1 = Chem.AddHs(Chem.Mol(reaction.monomer_1.rdkit_mol)) forced_indexes_1 = self._flatten_fg_indexes(reaction.functional_group_1) - # Handle case where both reactants are identical - if same_reactants: - mol_reactant_2 = Chem.AddHs(Chem.Mol(reaction.monomer_1.rdkit_mol)) - else: - mol_reactant_2 = Chem.AddHs(Chem.Mol(reaction.monomer_2.rdkit_mol)) - if reaction.functional_group_2 is not None: forced_indexes_2 = self._flatten_fg_indexes(reaction.functional_group_2) # Direction is already known from the ReactionInstance (monomer_1 -> # reactant slot 1, monomer_2 -> reactant slot 2), so unlike the normal # path we do NOT also try the swapped ordering. - reaction_tuple = [[mol_reactant_1, mol_reactant_2]] + reaction_tuple = [[mol_reactant_1, mol_reactant_2], [mol_reactant_2, mol_reactant_1]] if same_reactants else [[mol_reactant_1, mol_reactant_2]] else: reactant_smiles_1 = reaction.monomer_1.smiles reactant_smiles_2 = reactant_smiles_1 if same_reactants else reaction.monomer_2.smiles From 1b4f5747ace00fe0fea102001574d95c1d8a2e24 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:21:29 -0400 Subject: [PATCH 027/176] Update test_epoxy.json --- examples/test_epoxy.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/test_epoxy.json b/examples/test_epoxy.json index 00fb094f..5558925c 100644 --- a/examples/test_epoxy.json +++ b/examples/test_epoxy.json @@ -18,7 +18,7 @@ }, { "name": "primary_diamine", - "smiles": "NCCN" + "smiles": "NCCCCCN" } ] } \ No newline at end of file From b9f4ae774de8f233e97bd2f50d0d602ab9afa627 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:52:41 -0400 Subject: [PATCH 028/176] Update functional_groups_detector.py --- AutoREACTER/detectors/functional_groups_detector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index d14395f3..c29099f0 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -557,7 +557,7 @@ def index_based_functional_groups_detector( if not monomer_roles_out: return False # No functional groups detected; handle as needed # first break condition: if no monomer roles are detected, return False to indicate no further processing is needed. - + return monomer_roles_out # Return list of MonomerRole; visualization not considered here. def functional_group_highlighted_molecules_image_grid(self, session: Session) -> Image: From fb47faa88a28170a6d390145ff68e2f5dfe65a5e Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:52:55 -0400 Subject: [PATCH 029/176] Refine deduplication cache behavior Improve `DeduplicationDetector` clarity and consistency by tightening docstrings, reorganizing helper sections, and cleaning formatting. Functional updates include initializing pair caches for both comparison groups, clearing the RDKit pair cache at the start of each `compare_graphs_mol` pass, and extracting index-source mapping logic into a dedicated helper for clearer validation and error messages. --- .../deduplication_detector.py | 429 +++++++++--------- 1 file changed, 209 insertions(+), 220 deletions(-) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 27ef363c..ee7c76d1 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -1,3 +1,12 @@ +""" +Graph-based reaction deduplication for RDKit molecules and LAMMPS +molecule templates. + +The comparison intentionally ignores coordinates, atom IDs, and bond IDs. +RDKit comparisons use chemical element and bond type. LAMMPS comparisons +use atom type and bond type. +""" + from __future__ import annotations from pathlib import Path @@ -7,31 +16,13 @@ from rdkit import Chem if TYPE_CHECKING: - from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ( + from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( ReactionMetadata, ) -""" -In here we do not add any coordinations, atom IDs, or bond IDs to the graphs. This is because these -There tempalate can generate from different reactanats but can have same template -How ever the is a possible herdle in here that element can be same but atom types in -LAMMPS can be different. In future release we can add one more attribute to -the graph which is atom type in LAMMPS and bond type in LAMMPS. -This will make sure that we are comparing the same template and not different template with same element. -""" - class DeduplicationDetector: - """ - Detect duplicate pre/post-reaction graph pairs. - - Coordinates, atom IDs, and bond IDs are ignored during graph - isomorphism comparison. - - Each pre/post pair is combined into a coupled graph. Correspondence - edges connect the same atom across the reactant and product states, - ensuring that one consistent atom mapping must satisfy both graphs. - """ + """Detect duplicate pre/post-reaction graph pairs.""" NODE_ATTRIBUTE = "atom_label" EDGE_ATTRIBUTE = "bond_label" @@ -64,17 +55,22 @@ class DeduplicationDetector: } def __init__(self) -> None: - """Initialize independent deduplication caches.""" + """Initialize independent graph-comparison caches.""" self.seen_reactions: dict[str, list[nx.Graph]] = { self.LAMMPS_COMPARISON_GROUP: [], self.RDKIT_COMPARISON_GROUP: [], } - self.seen_reaction_pairs: dict[str, list[tuple[nx.Graph, nx.Graph]]] = { + + self.seen_reaction_pairs: dict[ + str, + list[tuple[nx.Graph, nx.Graph]], + ] = { + self.LAMMPS_COMPARISON_GROUP: [], self.RDKIT_COMPARISON_GROUP: [], } # ------------------------------------------------------------------ - # Public duplicate-detection API + # Duplicate-detection API # ------------------------------------------------------------------ def is_duplicate( @@ -84,20 +80,12 @@ def is_duplicate( comparison_group: str, ) -> bool: """ - Check whether an equivalent pre/post-reaction pair was seen. + Check whether an equivalent coupled pre/post pair was previously + cached. - Args: - pre_template_graph: - Graph representing the reactant state. - post_template_graph: - Graph representing the product state. - comparison_group: - Cache group used for the comparison, such as ``lammps`` - or ``rdkit``. - - Returns: - True when an equivalent reaction pair is already cached. - Otherwise, caches the reaction pair and returns False. + The pre- and post-reaction graphs are coupled using atom + correspondence edges. This requires one consistent atom mapping + to satisfy both reaction phases. """ coupled_graph = self._couple_graphs( pre_template_graph=pre_template_graph, @@ -120,10 +108,16 @@ def is_duplicate( ) for seen_graph in seen_graphs: - if coupled_graph.number_of_nodes() != seen_graph.number_of_nodes(): + if ( + coupled_graph.number_of_nodes() + != seen_graph.number_of_nodes() + ): continue - if coupled_graph.number_of_edges() != seen_graph.number_of_edges(): + if ( + coupled_graph.number_of_edges() + != seen_graph.number_of_edges() + ): continue if nx.is_isomorphic( @@ -144,33 +138,11 @@ def is_duplicate_pair( comparison_group: str, ) -> bool: """ - # NEW METHOD - Simple, uncoupled duplicate check for a (reactant graph, product graph) - pair. + Check whether an equivalent uncoupled pre/post graph pair was + previously cached. - Unlike is_duplicate, this does NOT combine the two graphs into one - coupled graph and does NOT require a single consistent atom mapping - across both phases. It only checks graph topology and atom/bond - labels — no coordinates, no atom IDs, no bond IDs, no cross-phase - atom correspondence. - - A pair is a duplicate only if BOTH: - - pre_graph is isomorphic to some cached pre_graph, AND - - post_graph is isomorphic to that SAME cached entry's post_graph. - - Args: - pre_graph: - Reactant-side graph, already restricted to the desired atom - indices (e.g. via rdkit_mol_to_networkx(atom_idxs=...)). - post_graph: - Product-side graph, already restricted to the desired atom - indices. - comparison_group: - Cache group used for the comparison. - - Returns: - True when an equivalent (reactant, product) pair was already - cached. Otherwise, caches the pair and returns False. + A reaction is considered a duplicate only when both its reactant + graph and product graph match the same cached reaction entry. """ node_match = nx.algorithms.isomorphism.categorical_node_match( self.NODE_ATTRIBUTE, @@ -187,27 +159,58 @@ def is_duplicate_pair( [], ) - for seen_pre, seen_post in seen_pairs: - if pre_graph.number_of_nodes() != seen_pre.number_of_nodes(): - continue - if pre_graph.number_of_edges() != seen_pre.number_of_edges(): - continue - if post_graph.number_of_nodes() != seen_post.number_of_nodes(): + for seen_pre_graph, seen_post_graph in seen_pairs: + if ( + pre_graph.number_of_nodes() + != seen_pre_graph.number_of_nodes() + ): continue - if post_graph.number_of_edges() != seen_post.number_of_edges(): + + if ( + pre_graph.number_of_edges() + != seen_pre_graph.number_of_edges() + ): continue - if not nx.is_isomorphic( - pre_graph, seen_pre, node_match=node_match, edge_match=edge_match + if ( + post_graph.number_of_nodes() + != seen_post_graph.number_of_nodes() ): continue - if nx.is_isomorphic( - post_graph, seen_post, node_match=node_match, edge_match=edge_match + if ( + post_graph.number_of_edges() + != seen_post_graph.number_of_edges() ): + continue + + pre_matches = nx.is_isomorphic( + pre_graph, + seen_pre_graph, + node_match=node_match, + edge_match=edge_match, + ) + + if not pre_matches: + continue + + post_matches = nx.is_isomorphic( + post_graph, + seen_post_graph, + node_match=node_match, + edge_match=edge_match, + ) + + if post_matches: return True - seen_pairs.append((pre_graph.copy(), post_graph.copy())) + seen_pairs.append( + ( + pre_graph.copy(), + post_graph.copy(), + ) + ) + return False def compare_graphs( @@ -217,17 +220,9 @@ def compare_graphs( """ Compare LAMMPS pre/post molecule-template pairs. - A pre-template filename must contain ``pre``. The corresponding - post-template filename is determined by replacing the first - occurrence of ``pre`` with ``post``. - - Args: - molecule_file_paths: - Candidate LAMMPS molecule-template file paths. - - Returns: - A mapping from each processed pre-template path to its - duplicate status. + A pre-template filename must contain ``pre``. Its post-template + path is determined by replacing the first occurrence of ``pre`` + with ``post``. """ results: dict[str, bool] = {} @@ -255,6 +250,7 @@ def compare_graphs( pre_graph = self.lammps_molecule_to_networkx( pre_file_path ) + post_graph = self.lammps_molecule_to_networkx( post_file_path ) @@ -278,44 +274,41 @@ def compare_graphs( def compare_graphs_mol( self, - reaction_metadata_items: list[ReactionMetadata], - index_source: str = "template", # which ReactionMetadata index attribute - # restricts the graph build. Defaults to - # "template". Other supported value: - # "first_shell". - ) -> list[ReactionMetadata]: + reaction_metadata_items: list["ReactionMetadata"], + index_source: str = "template", + ) -> list["ReactionMetadata"]: """ Detect duplicate reactions using in-memory RDKit molecules. - Reactions whose ``activity_stats`` value is already False are - skipped. Detected duplicates are disabled by setting - ``activity_stats`` to False. - - # NEW: Comparison is now a simple, uncoupled topology check. The - # reactant graph is built restricted to the selected reactant indices; - # the product graph is built restricted to the corresponding product - # indices. These two graphs form one "set" for this reaction. Each new - # set is compared against previously seen sets using is_duplicate_pair: - # if both the reactant graph and the product graph independently match - # a previously seen pair's reactant/product graphs (same atom/bond - # topology and labels — no coordinates, no atom IDs, no bond IDs, no - # cross-phase atom correspondence), the reaction is marked as a - # duplicate and disabled. + The RDKit pair cache is cleared at the start of every call. This + makes each invocation one independent deduplication pass over the + supplied accumulated reaction pool. + + Reactions already marked inactive are skipped. When multiple active + reactions have equivalent reactant and product graphs, the first is + retained and later matches are disabled. Args: reaction_metadata_items: - Prepared reaction metadata objects. + Accumulated reaction metadata pool. + index_source: - Selects which ReactionMetadata attribute defines the - restricted atom-index set used to build the pre/post graphs. - "template" (default) uses template_reactant_to_product_mapping. - "first_shell" restricts the reactant side to - reaction_metadata.first_shell (mapped through - reactant_to_product_mapping for the product side) instead. + Determines which atom indexes restrict the graph comparison. + + ``template``: + Use ``template_reactant_to_product_mapping``. + + ``first_shell``: + Use ``first_shell`` reactant indexes mapped through + ``reactant_to_product_mapping``. Returns: The original metadata list with duplicate reactions disabled. """ + # Each call represents a new full-pool deduplication pass. + # Do not retain RDKit graph pairs from previous progression loops. + self._clear_pair_cache(self.RDKIT_COMPARISON_GROUP) + for reaction_index, reaction_metadata in enumerate( reaction_metadata_items, start=1, @@ -338,60 +331,22 @@ def compare_graphs_mol( "combined product RDKit molecule." ) - # index_source selection block: picks which reactant->product - # index mapping restricts the graph build. - if index_source == "template": - reactant_to_product_mapping = ( - reaction_metadata.template_reactant_to_product_mapping + reactant_to_product_mapping = ( + self._select_reactant_to_product_mapping( + reaction_metadata=reaction_metadata, + reaction_index=reaction_index, + index_source=index_source, ) + ) - if not reactant_to_product_mapping: - raise ValueError( - f"Reaction {reaction_index} does not contain a " - "template_reactant_to_product_mapping; duplicate " - "comparison cannot be restricted to template atoms." - ) - - elif index_source == "first_shell": - # Build the restriction from first_shell reactant indices, - # mapped to product indices via the full reactant_to_product_mapping. - first_shell_idxs = reaction_metadata.first_shell - full_mapping = reaction_metadata.reactant_to_product_mapping - - if not first_shell_idxs: - raise ValueError( - f"Reaction {reaction_index} does not contain " - "first_shell indices; duplicate comparison cannot " - "be restricted to first-shell atoms." - ) - - if not full_mapping: - raise ValueError( - f"Reaction {reaction_index} does not contain a " - "reactant_to_product_mapping; duplicate comparison " - "cannot be restricted to first-shell atoms." - ) - - reactant_to_product_mapping = { - r_idx: full_mapping[r_idx] - for r_idx in first_shell_idxs - if r_idx in full_mapping - } - - else: - raise ValueError( - f"Unsupported index_source {index_source!r}. " - "Expected 'template' or 'first_shell'." - ) + reactant_template_indices = set( + reactant_to_product_mapping + ) - reactant_template_indices = set(reactant_to_product_mapping) - product_template_indices = set(reactant_to_product_mapping.values()) + product_template_indices = set( + reactant_to_product_mapping.values() + ) - # NEW: no idx_relabel — each graph keeps its own native atom - # indices. Isomorphism comparison doesn't care about absolute - # index/label values, only structure + atom_label/bond_label - # attributes, so relabeling into a shared index space is - # unnecessary for this simple pairwise check. pre_graph = self.rdkit_mol_to_networkx( molecule=reactant_mol, atom_idxs=reactant_template_indices, @@ -402,8 +357,6 @@ def compare_graphs_mol( atom_idxs=product_template_indices, ) - # NEW: simple uncoupled comparison instead of is_duplicate's - # coupled-graph approach. duplicate = self.is_duplicate_pair( pre_graph=pre_graph, post_graph=post_graph, @@ -430,18 +383,17 @@ def clear_cache( comparison_group: str | None = None, ) -> None: """ - Clear stored reaction graphs. + Clear graph-comparison caches. Args: comparison_group: - Cache group to clear. When None, all cache groups are - cleared. + Specific cache group to clear. All groups are cleared + when omitted. """ if comparison_group is None: for seen_graphs in self.seen_reactions.values(): seen_graphs.clear() - # NEW: also clear the pairwise cache used by compare_graphs_mol. for seen_pairs in self.seen_reaction_pairs.values(): seen_pairs.clear() @@ -452,14 +404,13 @@ def clear_cache( [], ).clear() - # NEW: mirror the clear on the pairwise cache. self.seen_reaction_pairs.setdefault( comparison_group, [], ).clear() # ------------------------------------------------------------------ - # Public graph-conversion API + # RDKit graph conversion # ------------------------------------------------------------------ def rdkit_mol_to_networkx( @@ -469,32 +420,15 @@ def rdkit_mol_to_networkx( idx_relabel: dict[int, int] | None = None, ) -> nx.Graph: """ - Convert an in-memory RDKit molecule into a NetworkX graph. + Convert an RDKit molecule into a NetworkX graph. Coordinates are not read or stored. Node attributes: - atom_label: - Chemical element symbol. + ``atom_label`` contains the chemical element symbol. Edge attributes: - bond_label: - RDKit bond type represented as a string. - - Args: - molecule: - RDKit molecule to convert. - atom_idxs: - Optional atom-index set defining the induced subgraph. - Atoms outside this set and bonds touching excluded atoms - are omitted. - idx_relabel: - Optional mapping from RDKit atom indices to graph node - IDs. This can be used to express a product graph in the - corresponding reactant-index space. - - Returns: - NetworkX representation of the selected molecule region. + ``bond_label`` contains the RDKit bond type. """ if molecule is None: raise ValueError( @@ -555,6 +489,7 @@ def rdkit_mol_to_networkx( atom_index=atom1_index, idx_relabel=idx_relabel, ) + node2_id = self._resolve_node_id( atom_index=atom2_index, idx_relabel=idx_relabel, @@ -572,6 +507,10 @@ def rdkit_mol_to_networkx( return graph + # ------------------------------------------------------------------ + # LAMMPS graph conversion + # ------------------------------------------------------------------ + def lammps_molecule_to_networkx( self, file_path: str | Path, @@ -579,16 +518,7 @@ def lammps_molecule_to_networkx( """ Convert a LAMMPS molecule-template file into a NetworkX graph. - Only the ``Types`` and ``Bonds`` sections are used. Coordinates, - charges, angles, dihedrals, impropers, atom IDs, and bond IDs do - not participate in graph-isomorphism comparison. - - Args: - file_path: - Path to the LAMMPS molecule-template file. - - Returns: - NetworkX representation of the molecule template. + Only the ``Types`` and ``Bonds`` sections are included. """ file_path = Path(file_path) @@ -627,7 +557,74 @@ def lammps_molecule_to_networkx( return graph # ------------------------------------------------------------------ - # Private coupled-graph helpers + # Reaction-index selection + # ------------------------------------------------------------------ + + def _select_reactant_to_product_mapping( + self, + reaction_metadata: "ReactionMetadata", + reaction_index: int, + index_source: str, + ) -> dict[int, int]: + """Select the atom-index mapping used for graph restriction.""" + if index_source == "template": + mapping = ( + reaction_metadata.template_reactant_to_product_mapping + ) + + if not mapping: + raise ValueError( + f"Reaction {reaction_index} does not contain a " + "template_reactant_to_product_mapping." + ) + + return mapping + + if index_source == "first_shell": + first_shell_indices = reaction_metadata.first_shell + full_mapping = ( + reaction_metadata.reactant_to_product_mapping + ) + + if not first_shell_indices: + raise ValueError( + f"Reaction {reaction_index} does not contain " + "first_shell indices." + ) + + if not full_mapping: + raise ValueError( + f"Reaction {reaction_index} does not contain a " + "reactant_to_product_mapping." + ) + + return { + reactant_index: full_mapping[reactant_index] + for reactant_index in first_shell_indices + if reactant_index in full_mapping + } + + raise ValueError( + f"Unsupported index_source {index_source!r}. " + "Expected 'template' or 'first_shell'." + ) + + # ------------------------------------------------------------------ + # Cache helpers + # ------------------------------------------------------------------ + + def _clear_pair_cache( + self, + comparison_group: str, + ) -> None: + """Clear only the uncoupled pre/post pair cache for one group.""" + self.seen_reaction_pairs.setdefault( + comparison_group, + [], + ).clear() + + # ------------------------------------------------------------------ + # Coupled-graph helpers # ------------------------------------------------------------------ def _couple_graphs( @@ -636,15 +633,8 @@ def _couple_graphs( post_template_graph: nx.Graph, ) -> nx.Graph: """ - Combine reactant and product graphs into one coupled graph. - - Every atom is represented twice: - - ("pre", atom_id) - ("post", atom_id) - - A correspondence edge connects matching atom IDs across the two - phases, requiring one consistent mapping for both states. + Combine reactant and product graphs using atom-correspondence + edges. """ pre_atom_ids = set(pre_template_graph.nodes) post_atom_ids = set(post_template_graph.nodes) @@ -653,6 +643,7 @@ def _couple_graphs( missing_from_post = sorted( pre_atom_ids - post_atom_ids ) + missing_from_pre = sorted( post_atom_ids - pre_atom_ids ) @@ -698,7 +689,7 @@ def _add_phase_to_coupled_graph( coupled_graph: nx.Graph, phase: str, ) -> None: - """Add one reaction phase to a coupled pre/post graph.""" + """Add one reaction phase to a coupled graph.""" for atom_id, attributes in source_graph.nodes(data=True): atom_label = attributes.get(self.NODE_ATTRIBUTE) @@ -741,21 +732,21 @@ def _resolve_node_id( atom_index: int, idx_relabel: dict[int, int] | None, ) -> int: - """Resolve an RDKit atom index to its output graph node ID.""" + """Resolve an RDKit atom index to its graph node ID.""" if idx_relabel is None: return atom_index return idx_relabel[atom_index] # ------------------------------------------------------------------ - # Private LAMMPS parsing helpers + # LAMMPS parsing helpers # ------------------------------------------------------------------ def _read_lammps_sections( self, file_path: Path, ) -> dict[str, list[str]]: - """Read relevant sections from a LAMMPS molecule-template file.""" + """Read relevant sections from a LAMMPS molecule file.""" sections: dict[str, list[str]] = {} current_section: str | None = None @@ -875,7 +866,7 @@ def _validate_bond_atoms( atom2_id: int, source: Path | str, ) -> None: - """Ensure that both atoms referenced by a bond exist.""" + """Ensure both atoms referenced by a bond exist.""" undefined_atoms = [ atom_id for atom_id in (atom1_id, atom2_id) @@ -921,9 +912,7 @@ def _main() -> None: for file_path, duplicate in results.items(): status = "duplicate" if duplicate else "unique" - print( - f"{Path(file_path).name}: {status}" - ) + print(f"{Path(file_path).name}: {status}") if __name__ == "__main__": From 2c8e153b5c197ad86dba220a13a56b180c27af14 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:53:09 -0400 Subject: [PATCH 030/176] Delete fragment_comparison.py --- .../reaction_processor/fragment_comparison.py | 238 ------------------ 1 file changed, 238 deletions(-) delete mode 100644 AutoREACTER/reaction_preparation/reaction_processor/fragment_comparison.py diff --git a/AutoREACTER/reaction_preparation/reaction_processor/fragment_comparison.py b/AutoREACTER/reaction_preparation/reaction_processor/fragment_comparison.py deleted file mode 100644 index bbea598d..00000000 --- a/AutoREACTER/reaction_preparation/reaction_processor/fragment_comparison.py +++ /dev/null @@ -1,238 +0,0 @@ -# THIS WILL BE NEW PLACE HOLDER FOR NETWORKX CODE, NOT TO BE DELETED - -# """ -# Chemical Fragment Extraction and Comparison Utility -# This module provides functions to extract specific fragments from RDKit molecules, -# cap open valences with placeholder atoms (Francium), and compare these fragments -# against a history of processed structures to identify unique chemical transformations. -# """ - -# from rdkit import Chem - -# import copy - -# def dict_keys_to_list(input_dict): -# """ -# Converts a dictionary of atom mappings into two separate lists of indices. - -# Args: -# input_dict (dict): A dictionary where keys represent reactant atom indices -# and values represent product atom indices. - -# Returns: -# tuple: (reactant_indices, product_indices) as lists of integers. -# """ -# # Convert keys and values to integers to ensure consistent indexing -# reactant_indices = [int(k) for k in input_dict.keys()] -# product_indices = [int(v) for v in input_dict.values()] -# return reactant_indices, product_indices - - -# def extract_fragment_by_indices(mol, atom_indices_to_keep): -# """ -# Creates a new molecule containing only the atoms specified by the provided indices. -# All other atoms are removed. - -# Args: -# mol (rdkit.Chem.rdchem.Mol): The source RDKit molecule. -# atom_indices_to_keep (list): List of atom indices to retain in the fragment. - -# Returns: -# rdkit.Chem.rdchem.Mol: The extracted molecular fragment, or None if input is invalid. -# """ -# if mol is None: -# return None - -# # 1. Convert to an RWMol (Read-Write Molecule) object to allow structural editing -# rwmol = Chem.RWMol(mol) - -# # 2. Identify atoms to remove -# # We find the difference between all atoms in the molecule and the ones we want to keep -# all_indices = [a.GetIdx() for a in mol.GetAtoms()] -# atom_indices_to_remove = [idx for idx in all_indices if idx not in atom_indices_to_keep] - -# # 3. Sort indices in reverse (descending) order -# # Crucial: Removing atoms shifts the indices of subsequent atoms. -# # Removing from highest index to lowest prevents this shifting issue. -# sorted_indices = sorted(atom_indices_to_remove, reverse=True) - -# # 4. Iterate and remove atoms from the RWMol -# for idx in sorted_indices: -# rwmol.RemoveAtom(idx) - -# # Convert back to a standard Molecule object -# new_mol = rwmol.GetMol() - -# # 5. Attempt Sanitization -# # Fragments often have "broken" valences. We try to sanitize to refresh -# # molecular properties, but wrap it in a try-except to prevent valence errors -# # from crashing the execution. -# try: -# Chem.SanitizeMol(new_mol) -# except Exception: -# # If sanitization fails (e.g., due to invalid valences), we proceed with the raw fragment -# pass - -# return new_mol - -# def cap_open_valences_with_fr(new_mol_fragment, francium_atomic_num=87): -# """ -# Identifies atoms with unsatisfied valences and attaches Francium (Fr) atoms -# as placeholders. This is useful for maintaining structural context in fragments. - -# Args: -# new_mol_fragment (rdkit.Chem.rdchem.Mol): The fragment to cap. -# francium_atomic_num (int): The atomic number to use for capping (default 87 for Fr). - -# Returns: -# dict: A dictionary containing the RDKit object, SMILES string, and InChI string. -# """ -# # Handle empty or null fragments -# if new_mol_fragment is None or new_mol_fragment.GetNumAtoms() == 0: -# return {"object": None, "smiles": "", "inchi": ""} - -# rw_mol = Chem.RWMol(new_mol_fragment) - -# # Use a static list of atoms to avoid iterator invalidation during modification -# atoms = list(rw_mol.GetAtoms()) - -# for atom in atoms: -# atom_idx = atom.GetIdx() -# try: -# # Determine the expected valence for the atom type -# default_valence = Chem.GetPeriodicTable().GetDefaultValence(atom.GetAtomicNum()) - -# # Calculate the current valence based on existing bonds -# current_valence = sum(bond.GetBondTypeAsDouble() for bond in atom.GetBonds()) - -# # Handle cases where default valence might be a tuple (multiple oxidation states) -# base_valence = default_valence[0] if isinstance(default_valence, tuple) else default_valence - -# # Calculate how many bonds are "missing" -# open_valences = max(0, int(base_valence) - int(current_valence)) - -# # Add Francium atoms for each open valence -# if open_valences > 0: -# for _ in range(open_valences): -# fr_atom = Chem.Atom(francium_atomic_num) -# fr_idx = rw_mol.AddAtom(fr_atom) -# # Connect the placeholder atom with a single bond -# rw_mol.AddBond(atom_idx, fr_idx, Chem.BondType.SINGLE) -# except Exception: -# # Skip atoms where valence cannot be determined (e.g., certain metals) -# continue - -# # Finalize the molecule after capping -# capped_mol = rw_mol.GetMol() -# try: -# Chem.SanitizeMol(capped_mol) -# except Exception as e: -# # Some fragments (e.g., highly unusual or intentionally "broken" structures) -# # may fail RDKit sanitization. We keep the unsanitized molecule to preserve -# # behavior, but log the issue for easier debugging. -# print(f"Warning: RDKit sanitization failed for capped fragment: {e}") - -# return { -# "object": capped_mol, -# "smiles": Chem.MolToSmiles(capped_mol), -# "inchi": Chem.MolToInchi(capped_mol), -# } - -# def compare_fragments(mol1_info, mol2_info): -# """ -# Compares two molecular info dictionaries to determine if they represent -# the same chemical structure. - -# Args: -# mol1_info (dict): Dictionary containing 'smiles' and/or 'inchi'. -# mol2_info (dict): Dictionary containing 'smiles' and/or 'inchi'. - -# Returns: -# bool: True if molecules match by SMILES or InChI, False otherwise. -# """ -# if not mol1_info or not mol2_info: -# return False - -# # Check SMILES identity -# smiles1, smiles2 = mol1_info.get("smiles"), mol2_info.get("smiles") -# if smiles1 and smiles2 and smiles1 == smiles2: -# return True - -# # Check InChI identity (more robust for tautomers/stereoisomers in some cases) -# inchi1, inchi2 = mol1_info.get("inchi"), mol2_info.get("inchi") -# if inchi1 and inchi2 and inchi1 == inchi2: -# return True -# return False - -# def compare_rdkit_fragments(processed_dict, combined_reactant_mol, combined_product_mol, template_mapped_dict): -# """ -# Main logic to extract fragments from a reaction and check if this specific -# transformation has been encountered before. - -# Args: -# processed_dict (dict): A history of previously seen fragments. -# combined_reactant_mol (rdkit.Chem.rdchem.Mol): The full reactant molecule. -# combined_product_mol (rdkit.Chem.rdchem.Mol): The full product molecule. -# template_mapped_dict (dict): Mapping of atom indices involved in the reaction. - -# Returns: -# tuple: (bool, updated_processed_dict). True if the fragment pair was already known. -# """ -# # Create deep copies to avoid modifying the original molecules in memory -# react_mol = copy.deepcopy(combined_reactant_mol) -# prod_mol = copy.deepcopy(combined_product_mol) - -# # Get the indices of the atoms involved in the reaction center -# react_indices, prod_indices = dict_keys_to_list(template_mapped_dict) - -# # Process Reactant Fragment -# raw_react_frag = extract_fragment_by_indices(react_mol, react_indices) -# try: -# react_smiles = Chem.MolToSmiles(raw_react_frag) if raw_react_frag else "" -# except Exception: -# react_smiles = "" -# try: -# react_inchi = Chem.MolToInchi(raw_react_frag) if raw_react_frag else "" -# except Exception: -# react_inchi = "" -# raw_react_info = {"smiles": react_smiles, "inchi": react_inchi} -# capped_react_info = cap_open_valences_with_fr(raw_react_frag) - -# # Process Product Fragment -# raw_prod_frag = extract_fragment_by_indices(prod_mol, prod_indices) -# try: -# prod_smiles = Chem.MolToSmiles(raw_prod_frag) if raw_prod_frag else "" -# except Exception: -# prod_smiles = "" -# try: -# prod_inchi = Chem.MolToInchi(raw_prod_frag) if raw_prod_frag else "" -# except Exception: -# prod_inchi = "" -# raw_prod_info = {"smiles": prod_smiles, "inchi": prod_inchi} -# capped_prod_info = cap_open_valences_with_fr(raw_prod_frag) - -# # Compare against history -# for proc_id, history in processed_dict.items(): -# hist_react = history['reactant_info'] -# hist_prod = history['product_info'] - -# # Check if current reactant matches history (either raw or capped) -# react_match = compare_fragments(hist_react, raw_react_info) or \ -# compare_fragments(hist_react, capped_react_info) - -# # Check if current product matches history (either raw or capped) -# prod_match = compare_fragments(hist_prod, raw_prod_info) or \ -# compare_fragments(hist_prod, capped_prod_info) - -# # If both reactant and product fragments match an entry, it's a duplicate -# if react_match and prod_match: -# return True, processed_dict - -# # If it's a new transformation, add it to the history -# new_id = len(processed_dict) + 1 -# processed_dict[new_id] = { -# "reactant_info": capped_react_info, -# "product_info": capped_prod_info -# } - -# return False, processed_dict From 03b9d070e1e9cdf4a2f276795bbf3e659ca7fd4b Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:53:27 -0400 Subject: [PATCH 031/176] Raise error when no reactions are active Add a dedicated `ZeroActiveReactionsError` in reaction preparation and fail after building reaction metadata when none of the reactions include activity stats. This makes empty or invalid datasets surface as an explicit AutoREACTER error instead of continuing silently. --- .../reaction_processor/prepare_reactions.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 8444289c..b4e9ab7b 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -40,6 +40,8 @@ class MappingError(Exception): class SMARTSParsingError(Exception): """Custom exception raised when parsing SMILES or reaction SMARTS fails.""" +class ZeroActiveReactionsError(Exception): + """Custom exception raised when no active reactions are found in the dataset.""" @dataclass(slots=True) class ReactionMetadata: @@ -115,7 +117,28 @@ def prepare_reactions(self, session): prepared_reactions.extend(added_reaction_progression) session.reaction_metadata = prepared_reactions # update with full final list + self._zero_active_reactions_error(prepared_reactions) return session + + def _zero_active_reactions_error(self, reaction_metadata: list[ReactionMetadata]): + """ + Checks if there are any active reactions in the provided reaction metadata list. + + Args: + reaction_metadata: List of ReactionMetadata objects to check for active reactions. + + Raises: + ZeroActiveReactionsError: If no active reactions are found in the list. + """ + active_reactions = False + for reaction in reaction_metadata: + if reaction.activity_stats: + active_reactions = True + break + if not active_reactions: + raise ZeroActiveReactionsError("No active reactions found in the dataset." \ + "This is an AutoREACTER error indicating that no active reactions were found in the dataset." \ + "Please Raise an issue at https://github.com/NanoCIPHER-Lab/AutoREACTER/issues") def _prepare_reactions_stage(self, session: "Session", loop: bool = False) -> list[ReactionMetadata]: """ From 66bd8cfb7b3f2e7922a5feb62c0995a4b1c4fd5e Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:53:41 -0400 Subject: [PATCH 032/176] Refine reaction progression loop Clarify `ReactionProgression.progress_reaction_process` with a more focused docstring and explicit typing for the working reaction lists. The loop now counts active reactions from the current session state, deduplicates in-place without extra logging, and returns through `_store_reactions(...)` as soon as the break condition is met so the final reaction set is persisted consistently. --- .../reaction_progression.py | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index b26c26f9..4b2aba58 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -60,15 +60,23 @@ def reaction_progression( max_loop: int = MAX_LOOP, ) -> list["ReactionMetadata"]: """ - Progresses the reaction process iteratively, detecting functional groups and reactions, - preparing reactions, and deduplicating them until no new reactions are found or the maximum - number of iterations is reached. - - Returns a list of all prepared reaction metadata. + Repeatedly detect functional groups, detect reactions, prepare + reactions, and remove duplicate products. + + Args: + max_loop: + Maximum number of progression iterations. + + Returns: + Reaction metadata generated during the progression loop. """ iteration = 0 - monomer_roles_in_loop = list(self.session.monomer_roles) - all_prepared_reactions = list(self.session.reaction_metadata) + monomer_roles_in_loop = list["MonomerRole"]( + self.session.monomer_roles + ) + all_prepared_reactions: list["ReactionMetadata"] = list( + self.session.reaction_metadata + ) while iteration < max_loop: iteration += 1 @@ -85,8 +93,8 @@ def reaction_progression( self._set_is_looped_flag(monomer_roles_in_loop) initial_reaction_pool_size = ( - self._length_of_active_reactions( - all_prepared_reactions + self._count_active_reactions( + self.session.reaction_metadata ) ) @@ -133,37 +141,30 @@ def reaction_progression( reaction_instances=reaction_instances ) ) - + all_prepared_reactions.extend(prepared_reactions) - - # Required for internal reaction-state modifications. self.session.reaction_metadata = all_prepared_reactions - print( - f"Total prepared reactions after iteration {iteration}: " - f"{len(all_prepared_reactions)}" - ) - all_prepared_reactions = ( self.deduplication_detector.compare_graphs_mol( - self.session.reaction_metadata + all_prepared_reactions ) ) - - # Update the session with the deduplicated reactions. self.session.reaction_metadata = all_prepared_reactions deduplicated_reaction_count = ( - self._length_of_active_reactions( + self._count_active_reactions( all_prepared_reactions ) ) - if self._loop_break_condition( + should_break = self._loop_break_condition( size_before=initial_reaction_pool_size, size_after=deduplicated_reaction_count, - ): - break + ) + + if should_break: + return self._store_reactions(all_prepared_reactions) self.session.reaction_metadata = all_prepared_reactions return all_prepared_reactions From 61c0df217c0c056ac4188ca8cd433d8e930e2f61 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 12:38:26 -0400 Subject: [PATCH 033/176] Fix progression deduplication handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update reaction progression to keep the session’s final deduplicated reaction list instead of extending it with newly generated reactions. Deduplication now clears the full comparison cache per pass, drops repeated references to the same ReactionMetadata object without disabling it, and compares relabeled product graphs in reactant index space. The change also refreshes inline documentation around progression flow and product handling. --- .../deduplication_detector.py | 110 +++++----- .../reaction_processor/prepare_reactions.py | 18 +- .../reaction_progression.py | 188 ++++++++++++------ 3 files changed, 206 insertions(+), 110 deletions(-) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index ee7c76d1..c7f91d68 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -280,13 +280,19 @@ def compare_graphs_mol( """ Detect duplicate reactions using in-memory RDKit molecules. - The RDKit pair cache is cleared at the start of every call. This - makes each invocation one independent deduplication pass over the - supplied accumulated reaction pool. + Each call performs one independent deduplication pass over the + supplied accumulated reaction pool. The RDKit coupled-graph cache + is therefore cleared before the comparison starts. - Reactions already marked inactive are skipped. When multiple active - reactions have equivalent reactant and product graphs, the first is - retained and later matches are disabled. + Reactions that are already inactive are ignored. Repeated references + to the exact same ReactionMetadata object are removed from the + returned list without disabling the retained object. This matters + because setting ``activity_stats`` to False on one repeated reference + would otherwise disable every occurrence of that same object. + + For distinct ReactionMetadata objects, the first unique reaction is + retained. Later equivalent reactions are disabled by setting + ``activity_stats`` to False and are excluded from the returned pool. Args: reaction_metadata_items: @@ -303,17 +309,31 @@ def compare_graphs_mol( ``reactant_to_product_mapping``. Returns: - The original metadata list with duplicate reactions disabled. + A new list containing one active representative of each unique + reaction. """ - # Each call represents a new full-pool deduplication pass. - # Do not retain RDKit graph pairs from previous progression loops. - self._clear_pair_cache(self.RDKIT_COMPARISON_GROUP) + # Each call is a complete deduplication pass over the current pool. + # Cached graphs from an earlier progression iteration must not be + # reused, or retained reactions will match their own old cache entry. + self.clear_cache(self.RDKIT_COMPARISON_GROUP) + + unique_reactions: list["ReactionMetadata"] = [] + retained_object_ids: set[int] = set() for reaction_index, reaction_metadata in enumerate( reaction_metadata_items, start=1, ): - if reaction_metadata.activity_stats is False: + # Inactive reactions do not participate in the active pool. + if not reaction_metadata.activity_stats: + continue + + reaction_object_id = id(reaction_metadata) + + # The accumulated progression pool can contain the exact same + # metadata object more than once. Do not mark that object inactive; + # simply keep its first occurrence. + if reaction_object_id in retained_object_ids: continue reactant_mol = reaction_metadata.reactant_combined_RDmol @@ -339,44 +359,58 @@ def compare_graphs_mol( ) ) - reactant_template_indices = set( - reactant_to_product_mapping - ) - - product_template_indices = set( + reactant_indices = set(reactant_to_product_mapping) + product_indices = set( reactant_to_product_mapping.values() ) + # Relabel the product graph into reactant-index space so the + # coupled graph preserves atom correspondence across the + # pre- and post-reaction states. + product_to_reactant_mapping = { + product_idx: reactant_idx + for reactant_idx, product_idx + in reactant_to_product_mapping.items() + } + + if len(product_to_reactant_mapping) != len( + reactant_to_product_mapping + ): + raise ValueError( + f"Reaction {reaction_index} contains a non-bijective " + "reactant-to-product mapping." + ) + pre_graph = self.rdkit_mol_to_networkx( molecule=reactant_mol, - atom_idxs=reactant_template_indices, + atom_idxs=reactant_indices, ) post_graph = self.rdkit_mol_to_networkx( molecule=product_mol, - atom_idxs=product_template_indices, + atom_idxs=product_indices, + idx_relabel=product_to_reactant_mapping, ) - duplicate = self.is_duplicate_pair( - pre_graph=pre_graph, - post_graph=post_graph, + duplicate = self.is_duplicate( + pre_template_graph=pre_graph, + post_template_graph=post_graph, comparison_group=self.RDKIT_COMPARISON_GROUP, ) if duplicate: reaction_metadata.activity_stats = False + continue - print( - f"Reaction {reaction_index}: " - "duplicate reaction detected and disabled." - ) - else: - print( - f"Reaction {reaction_index}: " - "unique reaction retained." - ) + retained_object_ids.add(reaction_object_id) + unique_reactions.append(reaction_metadata) - return reaction_metadata_items + print( + f"Reaction {reaction_index}: " + "unique reaction retained." + ) + + return unique_reactions def clear_cache( self, @@ -609,20 +643,6 @@ def _select_reactant_to_product_mapping( "Expected 'template' or 'first_shell'." ) - # ------------------------------------------------------------------ - # Cache helpers - # ------------------------------------------------------------------ - - def _clear_pair_cache( - self, - comparison_group: str, - ) -> None: - """Clear only the uncoupled pre/post pair cache for one group.""" - self.seen_reaction_pairs.setdefault( - comparison_group, - [], - ).clear() - # ------------------------------------------------------------------ # Coupled-graph helpers # ------------------------------------------------------------------ diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index b4e9ab7b..2d04e0ad 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -109,16 +109,22 @@ def __init__(self, session: "Session"): session.reaction_id_counter = 0 # Initialize a counter for unique reaction IDs if not already present def prepare_reactions(self, session): + # 1. Get initial reactions prepared_reactions = self._prepare_reactions_stage(session) - session.reaction_metadata = prepared_reactions # set BEFORE progression needs it + session.reaction_metadata = prepared_reactions + # 2. Run progression loop (this returns the FULL, deduplicated list) reaction_progression = ReactionProgression(session) - added_reaction_progression = reaction_progression.reaction_progression() - - prepared_reactions.extend(added_reaction_progression) - session.reaction_metadata = prepared_reactions # update with full final list - self._zero_active_reactions_error(prepared_reactions) + final_reactions = reaction_progression.reaction_progression() + + # 3. Overwrite the session metadata with the final deduplicated list + session.reaction_metadata = final_reactions + + # 4. Error check + self._zero_active_reactions_error(final_reactions) + return session + def _zero_active_reactions_error(self, reaction_metadata: list[ReactionMetadata]): """ diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 4b2aba58..fb0d011d 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -21,12 +21,18 @@ from AutoREACTER.session import Session +# Prevent the progression process from continuing indefinitely when reactions +# keep producing additional detectable functional groups. MAX_LOOP = 5 @dataclass(slots=True) class MonomerRoleforIndexBasedFGDetection: - """Monomer role used for index-based functional-group detection.""" + """Describe a molecule prepared for index-based functional-group detection. + + The stored atom indexes refer to positions in the reaction template and + allow functional groups to be associated with their original reactants. + """ smiles: str name: str @@ -38,14 +44,27 @@ class MonomerRoleforIndexBasedFGDetection: @dataclass(slots=True) class ReactionProgressionSession: - """State associated with reaction progression.""" + """Track state that is shared across reaction-progression iterations.""" monomer_roles: list["MonomerRole"] = field(default_factory=list) iteration: int = 0 class ReactionProgression: + """Coordinate iterative functional-group detection and reaction generation. + + Each iteration uses products from previously prepared reactions as potential + monomers. Newly detected functional groups are converted into reaction + instances, prepared into reaction metadata, and deduplicated before the + next iteration begins. + """ + def __init__(self, session: "Session"): + """Initialize detectors and attach progression state to a session. + + Args: + session: Session containing monomer roles and reaction metadata. + """ self.session = session self.session.reaction_progression_session = ( ReactionProgressionSession() @@ -59,16 +78,18 @@ def reaction_progression( self, max_loop: int = MAX_LOOP, ) -> list["ReactionMetadata"]: - """ - Repeatedly detect functional groups, detect reactions, prepare - reactions, and remove duplicate products. + """Run the reaction-progression loop until no progress is possible. + + Each iteration detects functional groups in generated products, finds + compatible reactions, prepares the reactions, and removes duplicates. + The loop stops when no new functional groups or reactions are found, + when the reaction pool does not grow, or when ``max_loop`` is reached. Args: - max_loop: - Maximum number of progression iterations. + max_loop: Maximum number of progression iterations to execute. Returns: - Reaction metadata generated during the progression loop. + The prepared and deduplicated reaction metadata. """ iteration = 0 monomer_roles_in_loop = list["MonomerRole"]( @@ -83,6 +104,8 @@ def reaction_progression( self.session.reaction_progression_session.iteration = iteration if iteration == 1: + # Convert the initial monomer SMILES strings into RDKit + # molecules before the first functional-group search. self._populate_monomer_roles() else: print( @@ -90,12 +113,12 @@ def reaction_progression( "of the reaction progression loop." ) + # Roles seen in earlier iterations are marked so detectors can + # distinguish already-processed molecules from newly added ones. self._set_is_looped_flag(monomer_roles_in_loop) - initial_reaction_pool_size = ( - self._count_active_reactions( - self.session.reaction_metadata - ) + initial_reaction_pool_size = self._count_active_reactions( + self.session.reaction_metadata ) print( @@ -136,15 +159,15 @@ def reaction_progression( ) break - prepared_reactions = ( - self._index_based_reaction_preparation( - reaction_instances=reaction_instances - ) + prepared_reactions = self._index_based_reaction_preparation( + reaction_instances=reaction_instances ) - + all_prepared_reactions.extend(prepared_reactions) self.session.reaction_metadata = all_prepared_reactions + # Deduplication occurs after preparation because equivalent + # products may be generated through different reaction paths. all_prepared_reactions = ( self.deduplication_detector.compare_graphs_mol( all_prepared_reactions @@ -152,10 +175,8 @@ def reaction_progression( ) self.session.reaction_metadata = all_prepared_reactions - deduplicated_reaction_count = ( - self._count_active_reactions( - all_prepared_reactions - ) + deduplicated_reaction_count = self._count_active_reactions( + all_prepared_reactions ) should_break = self._loop_break_condition( @@ -166,13 +187,17 @@ def reaction_progression( if should_break: return self._store_reactions(all_prepared_reactions) - self.session.reaction_metadata = all_prepared_reactions return all_prepared_reactions def _index_based_reaction_preparation( self, reaction_instances: list["ReactionInstance"], ) -> list["ReactionMetadata"]: + """Convert detected reaction instances into prepared reaction metadata. + + The import is local to avoid importing the reaction-preparation module + during module initialization, which also helps prevent circular imports. + """ from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( PrepareReactions, ) @@ -186,12 +211,19 @@ def _index_based_reaction_preparation( def _prepare_products_for_idx_based_fg_detection( self, ) -> list[MonomerRoleforIndexBasedFGDetection]: - """Prepare generated products for functional-group detection.""" + """Prepare active reaction products for index-based FG detection. + + Products are converted into cleaned SMILES strings and RDKit molecules. + Their template atom indexes are retained so newly detected functional + groups can be traced back to the reaction that produced them. + """ prepared_monomer_roles: list[ MonomerRoleforIndexBasedFGDetection ] = [] for reaction in self.session.reaction_metadata: + # Inactive reactions do not contain products that can participate + # in a subsequent progression iteration. if not reaction.activity_stats: continue @@ -212,11 +244,12 @@ def _prepare_products_for_idx_based_fg_detection( ) return prepared_monomer_roles - + def _store_reactions( self, reactions: list["ReactionMetadata"], ) -> list["ReactionMetadata"]: + """Save reaction metadata to the session and return it.""" self.session.reaction_metadata = reactions return reactions @@ -224,11 +257,14 @@ def _sanitize_molecule( self, mol: Chem.Mol, ) -> Chem.Mol | None: - """ - Sanitize an RDKit molecule by cleaning it and applying RDKit sanitization. + """Clean and sanitize an RDKit molecule. + + Atom-map numbers and isotope labels are removed before sanitization. + Products that RDKit cannot sanitize are discarded and represented by + ``None``. Args: - mol: The RDKit molecule to sanitize. + mol: Molecule to clean and sanitize. Returns: The sanitized molecule, or ``None`` if sanitization fails. @@ -244,10 +280,15 @@ def _sanitize_molecule( return cleaned_mol def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: - """ - Return a molecule copy without atom-map numbers or isotope labels. + """Return a copy of ``mol`` without atom maps or isotope labels. + + The input molecule is copied and therefore remains unchanged. + + Args: + mol: Molecule whose atom annotations should be removed. - The input molecule is not modified. + Returns: + A cleaned copy of the input molecule. """ cleaned_mol = Chem.Mol(mol) @@ -258,7 +299,14 @@ def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: return cleaned_mol def _get_product_smiles(self, mol: Chem.Mol) -> str: - """Convert a cleaned product molecule to SMILES.""" + """Convert a cleaned product molecule to canonical SMILES. + + Args: + mol: Product molecule to serialize. + + Returns: + The product SMILES, or an empty string if conversion fails. + """ cleaned_mol = self._clean_product(mol) try: @@ -271,12 +319,20 @@ def _get_product_idxs( template_reactant_to_product_mapping: dict[int, int], mol: Chem.Mol, ) -> tuple[list[int], Chem.Mol]: - """ - Retrieve mapped product atom indexes. + """Return product indexes and the molecule containing those indexes. + + If the product contains multiple disconnected fragments, only the + fragment with the greatest number of heavy atoms is retained. Indexes + are remapped to match the retained fragment. - When the product contains multiple fragments, retain the fragment - with the largest number of heavy atoms and remap the product - indexes to that fragment. + Args: + template_reactant_to_product_mapping: + Mapping from template reactant atom indexes to product indexes. + mol: Combined product molecule. + + Returns: + A tuple containing remapped product indexes and the selected + product molecule. """ product = Chem.Mol(mol) product_idxs = list( @@ -298,18 +354,17 @@ def _keep_largest_fragment( mol: Chem.Mol, product_idxs: list[int], ) -> tuple[Chem.Mol, list[int]]: - """ - Retain the fragment with the largest number of heavy atoms and - remap the product indexes to the retained fragment. + """Keep the largest disconnected fragment and remap atom indexes. Args: - mol: - Molecule containing one or more disconnected fragments. - product_idxs: - Product indexes referring to the original molecule. + mol: Molecule containing one or more disconnected fragments. + product_idxs: Atom indexes referring to the original molecule. Returns: - The largest fragment and its remapped product indexes. + The largest fragment and the indexes remapped to that fragment. + + Raises: + ValueError: If the molecule contains no fragments. """ fragment_atom_mappings: list[tuple[int, ...]] = [] @@ -327,24 +382,22 @@ def _keep_largest_fragment( largest_fragment_position = max( range(len(fragments)), - key=lambda position: ( - fragments[position].GetNumHeavyAtoms() - ), + key=lambda position: fragments[position].GetNumHeavyAtoms(), ) largest_fragment = fragments[largest_fragment_position] - # Mapping direction: - # fragment atom index -> original molecule atom index + # RDKit provides each retained fragment's original atom indexes. + # Build the inverse mapping to translate indexes into fragment space. original_atom_idxs = fragment_atom_mappings[ largest_fragment_position ] - original_to_new_idx = { original_idx: new_idx for new_idx, original_idx in enumerate(original_atom_idxs) } + # Ignore mapped indexes that belong to discarded fragments. remapped_product_idxs = [ original_to_new_idx[product_idx] for product_idx in product_idxs @@ -357,12 +410,12 @@ def _set_is_looped_flag( self, monomer_roles: list["MonomerRole"], ) -> None: - """Mark the supplied monomer roles as already processed.""" + """Mark supplied monomer roles as processed by the current loop.""" for monomer_role in monomer_roles: monomer_role.is_looped = True def _populate_monomer_roles(self) -> None: - """Create RDKit molecules for roles marked as monomers.""" + """Create RDKit molecules for all roles identified as monomers.""" for monomer in self.session.monomer_roles: if monomer.is_monomer: monomer.rdkit_mol = self._smiles_to_rdkit_mol( @@ -373,7 +426,14 @@ def _smiles_to_rdkit_mol( self, smiles: str, ) -> Chem.Mol | None: - """Convert a SMILES string to an RDKit molecule.""" + """Parse a SMILES string into an RDKit molecule. + + Args: + smiles: SMILES representation of the molecule. + + Returns: + The parsed molecule, or ``None`` if RDKit cannot parse the string. + """ return Chem.MolFromSmiles(smiles) def _loop_break_condition( @@ -381,7 +441,18 @@ def _loop_break_condition( size_before: int, size_after: int, ) -> bool: - """Return whether the active reaction pool failed to grow.""" + """Return whether the active reaction pool failed to grow. + + A non-growing pool indicates that the latest iteration did not add + useful reaction products and further progression is unlikely to help. + + Args: + size_before: Active reaction count before the iteration. + size_after: Active reaction count after deduplication. + + Returns: + ``True`` when the pool stayed the same size or became smaller. + """ if size_after <= size_before: print( "Breaking the loop as the pool did not grow " @@ -395,16 +466,15 @@ def _count_active_reactions( self, reactions: list["ReactionMetadata"], ) -> int: - """ - Count the number of active reactions in the supplied list. + """Count reactions that contain activity statistics. Args: - reactions: A list of ``ReactionMetadata`` objects to check for activity. + reactions: Reaction metadata objects to inspect. Returns: - The number of reactions that have activity statistics. + The number of active reactions. """ return sum( bool(reaction.activity_stats) for reaction in reactions - ) \ No newline at end of file + ) From b25fe077cfaaabc75fd56568157f9c3381a41171 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 12:50:08 -0400 Subject: [PATCH 034/176] Remove noisy debug output Silences leftover print statements in functional group detection, reaction deduplication, and reaction progression. Also clears a few functional group library comments that were only carrying debug-style guidance. --- AutoREACTER/detectors/functional_groups_detector.py | 3 +-- AutoREACTER/detectors/functional_groups_library.py | 6 +++--- .../reaction_preparation/deduplication_detector.py | 9 +++++---- .../reaction_processor/reaction_progression.py | 2 -- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index c29099f0..803c2f6e 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -474,7 +474,6 @@ def index_based_functional_groups_detector( continue # Skip already processed monomers mol = monomer.rdkit_mol - print(f"Processing monomer: {monomer.name} with SMILES: {monomer.smiles}") target_indices = set(monomer.indexes_in_template or []) detected_functionalities = [] @@ -521,7 +520,7 @@ def index_based_functional_groups_detector( all_matches.extend(functional_matches) # Log detected functionality for debugging/user feedback. - print(f"{monomer.smiles} has functionality: {functional_group['group_name']}") + # print(f"{monomer.smiles} has functionality: {functional_group['group_name']}") if functional_group.get("comments"): print(f"Note: {monomer.smiles} - {functional_group['comments']}") diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index 3f38c5c5..3dd4a543 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -159,21 +159,21 @@ def __init__(self): "functionality_type": "di_identical", "smarts_1": "[CX4;R1]1[OX2;R1][CX4;R1]1", "group_name": "di_epoxide", - "comments": "Difunctional epoxide monomer. Required on the epoxy side for epoxy-amine polymerization.", + "comments": None, }, "primary_amine_monomer": { "functionality_type": "mono", "smarts_1": "[NX3H2;!$(NC=O);!$(NC=[N,O,S])]", "group_name": "primary_amine", - "comments": "Mono primary amine. One -NH2 group has two active hydrogens and can react with two epoxide groups.", + "comments": None, }, "secondary_amine_monomer": { "functionality_type": "mono", "smarts_1": "[NX3H1;!$(NC=O);!$(NC=[N,O,S])]", "group_name": "secondary_amine", - "comments": "Mono secondary amine. Represents the second-stage reactive amine after primary amine reacts once with epoxide. By itself, a mono secondary amine reacts only once with epoxide and is not a true polymer-forming monomer.", + "comments": None, }, # ============================================================ diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index c7f91d68..8602df2e 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -405,10 +405,11 @@ def compare_graphs_mol( retained_object_ids.add(reaction_object_id) unique_reactions.append(reaction_metadata) - print( - f"Reaction {reaction_index}: " - "unique reaction retained." - ) + # Debugging: print unique reaction retention information. + # print( + # f"Reaction {reaction_index}: " + # "unique reaction retained." + # ) return unique_reactions diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index fb0d011d..0a14fdec 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -345,8 +345,6 @@ def _get_product_idxs( product_idxs, ) - print(f"Product idxs: {product_idxs}") - return product_idxs, product def _keep_largest_fragment( From 339638c605d634498c2e4db9f0424fe177de7b07 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:31:54 -0400 Subject: [PATCH 035/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- examples/test_glycine.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/test_glycine.json b/examples/test_glycine.json index 33c5da9f..cb53b3af 100644 --- a/examples/test_glycine.json +++ b/examples/test_glycine.json @@ -1,18 +1,18 @@ { - "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "simulation_name": "Glycine_Test", "simulations": [ { - "tag": "epoxy_test", + "tag": "glycine_test", "temperature": 300, "density": 1.0, "monomer_counts": { - "di_epoxy": 200 + "glycine": 200 } } ], "monomers": [ { - "name": "di_epoxy", + "name": "glycine", "smiles": "NCC(=O)O" } ] From 070cc31682146870926738b3f46b227dcc65a0fe Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:32:39 -0400 Subject: [PATCH 036/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- AutoREACTER/detectors/functional_groups_detector.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index 803c2f6e..dd74bd5d 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -441,9 +441,9 @@ def _detect_functional_groups_by_index(self, mol: Chem.Mol, smarts: str, indices return bool(matching_hits) def index_based_functional_groups_detector( - self, monomer_roles_in: list[MonomerRoleforIndexBasedFGDetection] - ) -> None: - """ + self, + monomer_roles_in: list[MonomerRoleforIndexBasedFGDetection], + ) -> list[MonomerRole] | bool: Detect functional groups across a list of monomers and categorize them into roles, restricted to a given set of atom indices per monomer. From 8497c3837867e991b5151f16fb636ee86d77c186 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:33:43 -0400 Subject: [PATCH 037/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../reaction_processor/prepare_reactions.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 2d04e0ad..0faa52df 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -142,9 +142,11 @@ def _zero_active_reactions_error(self, reaction_metadata: list[ReactionMetadata] active_reactions = True break if not active_reactions: - raise ZeroActiveReactionsError("No active reactions found in the dataset." \ - "This is an AutoREACTER error indicating that no active reactions were found in the dataset." \ - "Please Raise an issue at https://github.com/NanoCIPHER-Lab/AutoREACTER/issues") + raise ZeroActiveReactionsError( + "No active reactions found in the dataset. " + "This is an AutoREACTER error indicating that no active reactions were found in the dataset. " + "Please raise an issue at https://github.com/NanoCIPHER-Lab/AutoREACTER/issues" + ) def _prepare_reactions_stage(self, session: "Session", loop: bool = False) -> list[ReactionMetadata]: """ From 0a52366ed6f5747b8d005f4485f4eabd1dc00d20 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:34:01 -0400 Subject: [PATCH 038/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../reaction_processor/warning_asci.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py index 629be0c7..2979cef2 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py @@ -2,15 +2,17 @@ def ascii_art(message: str) -> None: message = message.upper() print(f"WARNING: {message}") - """ _ _ _ _ + print( + """ _ _ _ _ | | | | (_) | | | | | | | | __ _ _ __ _ __ _ _ __ __ _| | | | | |/\| |/ _` | '__| '_ \| | '_ \ / _` | | | | \ /\ / (_| | | | | | | | | | | (_| |_|_|_| \/ \/ \__,_|_| |_| |_|_|_| |_|\__, (_|_|_) - __/ | - |___/ + __/ | + |___/ """ + ) def print_warning() -> None: From bbfa638b625dcba697fcebafedabc206b08c29cd Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:34:35 -0400 Subject: [PATCH 039/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- AutoREACTER/detectors/functional_groups_detector.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index dd74bd5d..704cdf06 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -118,8 +118,9 @@ logger = logging.getLogger(__name__) # Module-level logger for future diagnostics. if TYPE_CHECKING: from AutoREACTER.session import Session - from AutoREACTER.detectors.functional_groups_detector import MonomerRoleforIndexBasedFGDetection - + from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ( + MonomerRoleforIndexBasedFGDetection, + ) @dataclass(slots=True) class FunctionalGroupInfo: From 0450d2fbb632c7929a3d5f0466bd9d7536dc99df Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:34:48 -0400 Subject: [PATCH 040/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../reaction_processor/warning_asci.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py index 2979cef2..cdf3d8a0 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py @@ -16,8 +16,9 @@ def ascii_art(message: str) -> None: def print_warning() -> None: - message = "Warning " \ - "Entering to the reaction progression Loop still in the Beta phase" \ - "Caution: Can be chemically inaccurate" + message = ( + "Entering the reaction progression loop is still in the beta phase. " + "Caution: results can be chemically inaccurate." + ) ascii_art(message) From 7ff392f7d79b5160b43de598757d4700eaa72ef0 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:35:06 -0400 Subject: [PATCH 041/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../reaction_preparation/ff_wrapper/lunar_client/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py index a9a571e5..96b9c6fc 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py @@ -1 +1 @@ -LUNAR_ROOT_DIR = '/mnt/c/Users/janit/Documents/GitHub/LUNAR' +LUNAR_ROOT_DIR = None From fe390775ad57aaf01125b14c245bd5c399c425b9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Jul 2026 17:35:33 +0000 Subject: [PATCH 042/176] Remove unused numpy indices import --- AutoREACTER/detectors/functional_groups_detector.py | 1 - 1 file changed, 1 deletion(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index 704cdf06..c82fe1ef 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -1,7 +1,6 @@ from __future__ import annotations from typing import TYPE_CHECKING, List -from numpy import indices """ * Monomer Functionality Detection Module -------------------------------------- From e865c75ed436ea327e66a1226662f8f807c01a43 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:37:14 -0400 Subject: [PATCH 043/176] Refactor forced index handling in prepare_reactions.py --- .../reaction_processor/prepare_reactions.py | 50 ++++++++++++++----- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 0faa52df..ca170454 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -252,22 +252,46 @@ def _process_reaction_instances( forced_indexes_2 = None if loop: - # FORCED-REACTION MODE: use the actual index-scoped rdkit_mol (not a - # fresh SMILES reparse) so atom indices line up with fg_*_indexes. - forced_indexes_1 = self._flatten_fg_indexes(reaction.functional_group_1) - + forced_indexes_1 = self._flatten_fg_indexes( + reaction.functional_group_1 + ) + if reaction.functional_group_2 is not None: - forced_indexes_2 = self._flatten_fg_indexes(reaction.functional_group_2) - - # Direction is already known from the ReactionInstance (monomer_1 -> - # reactant slot 1, monomer_2 -> reactant slot 2), so unlike the normal - # path we do NOT also try the swapped ordering. - reaction_tuple = [[mol_reactant_1, mol_reactant_2], [mol_reactant_2, mol_reactant_1]] if same_reactants else [[mol_reactant_1, mol_reactant_2]] + forced_indexes_2 = self._flatten_fg_indexes( + reaction.functional_group_2 + ) + + mol_reactant_1 = Chem.AddHs( + Chem.Mol(reaction.monomer_1.rdkit_mol) + ) + + monomer_2 = ( + reaction.monomer_1 + if same_reactants + else reaction.monomer_2 + ) + mol_reactant_2 = Chem.AddHs( + Chem.Mol(monomer_2.rdkit_mol) + ) + + # ReactionInstance already defines slot direction. + reaction_tuple = [[mol_reactant_1, mol_reactant_2]] else: reactant_smiles_1 = reaction.monomer_1.smiles - reactant_smiles_2 = reactant_smiles_1 if same_reactants else reaction.monomer_2.smiles - mol_reactant_1, mol_reactant_2 = self._build_reactants(reactant_smiles_1, reactant_smiles_2) - reaction_tuple = self._build_reaction_tuple(same_reactants, mol_reactant_1, mol_reactant_2) + reactant_smiles_2 = ( + reactant_smiles_1 + if same_reactants + else reaction.monomer_2.smiles + ) + mol_reactant_1, mol_reactant_2 = self._build_reactants( + reactant_smiles_1, + reactant_smiles_2, + ) + reaction_tuple = self._build_reaction_tuple( + same_reactants, + mol_reactant_1, + mol_reactant_2, + ) rxn = self._build_reaction(rxn_smarts) From f828e695cd6279a3325e4311d4dedb637c6813bd Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:37:47 -0400 Subject: [PATCH 044/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../detectors/functional_groups_detector.py | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index c82fe1ef..ad4fbadb 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -414,31 +414,22 @@ def _functional_groups_detector_for_visualization( ) return monomer_roles_visualization - def _detect_functional_groups_by_index(self, mol: Chem.Mol, smarts: str, indices: list[int]) -> bool: - """ - mol: RDKit Mol object - smarts: SMARTS pattern string - indices: iterable of atom indices you care about - - Returns: bool - True if any of the specified indices match the SMARTS pattern, False otherwise - """ - target_indices = set(indices) - results = {} + def _detect_functional_groups_by_index( + self, + mol: Chem.Mol, + smarts: str, + atom_indices: list[int], + ) -> bool: + """Return True when any SMARTS match overlaps the supplied atom indices.""" + target_indices = set(atom_indices) patt = Chem.MolFromSmarts(smarts) if patt is None: - # invalid SMARTS - results["present"] = False - results["error"] = "invalid SMARTS" - return results - - matches = mol.GetSubstructMatches(patt, uniquify=True) # tuple of tuples of atom idx - - # check if ANY match shares AT LEAST ONE atom with your target indices - matching_hits = [m for m in matches if target_indices.intersection(m)] + logger.warning("Invalid SMARTS pattern: %s", smarts) + return False - return bool(matching_hits) + matches = mol.GetSubstructMatches(patt, uniquify=True) + return any(target_indices.intersection(match) for match in matches) def index_based_functional_groups_detector( self, From f425265adc6564176acb62019756d1894e25a44f Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 14:32:55 -0400 Subject: [PATCH 045/176] Add vinyl polymerization reaction support Introduces vinyl-specific functional groups (`vinyl` and `vinyl_chain_radical`) and adds initiation/propagation entries for vinyl addition polymerization in the reaction library. Reaction progression now sanitizes product molecules before reuse, skips failed sanitizations with a clear message, and uses the sanitized molecule for both SMILES extraction and downstream functional-group detection. Also fixes a missing docstring delimiter in `functional_groups_detector.py`. --- .../detectors/functional_groups_detector.py | 1 + .../detectors/functional_groups_library.py | 17 +++++++ AutoREACTER/detectors/reactions_library.py | 50 +++++++++++++++++++ .../reaction_progression.py | 15 ++++-- 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index ad4fbadb..6f1a9e53 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -435,6 +435,7 @@ def index_based_functional_groups_detector( self, monomer_roles_in: list[MonomerRoleforIndexBasedFGDetection], ) -> list[MonomerRole] | bool: + """ Detect functional groups across a list of monomers and categorize them into roles, restricted to a given set of atom indices per monomer. diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index 3dd4a543..0207c82d 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -175,6 +175,23 @@ def __init__(self): "group_name": "secondary_amine", "comments": None, }, + # ============================================================ + # Vinyl Addition Polymerization + # ============================================================ + + "vinyl_monomer": { + "functionality_type": "vinyl", + "smarts_1": "[CH2]=[C;!R]", + "group_name": "vinyl", + "comments": None, + }, + + "vinyl_chain_radical_monomer": { + "functionality_type": "mono", + "smarts_1": "[C]-[*]", + "group_name": "vinyl_chain_radical", + "comments": "Reactive chain-end group used for vinyl propagation.", + }, # ============================================================ # Commented functional groups diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py index 25f7fb9d..29cc7530 100644 --- a/AutoREACTER/detectors/reactions_library.py +++ b/AutoREACTER/detectors/reactions_library.py @@ -34,7 +34,15 @@ - Polymerization in Supercritical Carbon Dioxide - Thiophene Polymerizations: Oxidative Polymerization of Thiophenes """ +rxn_prop_smarts = ( + "[C:1]-[*:5].[CH2:3]=[CH;!R:4]-[*:6]" + ">>[C:1]([*:5])-[CH2:3]-[CH:4]-[*:6]" +) +rxn_init_smarts = ( + "[CH2:1]=[CH;!R:2].[CH2:3]=[C;!R:4]-[*:5]" + ">>[C:1]-[C:2]-[C:3]-[C:4]-[*:5]" +) class ReactionLibrary: def __init__(self): @@ -366,7 +374,49 @@ def __init__(self): }, "comments": "Secondary amine's remaining N-H opens a second epoxide ring. Nitrogen becomes a fully substituted tertiary amine (network crosslink point); no reactive N-H remains on this nitrogen." }, + + "Vinyl Addition Polymerization Initiation": { + "same_reactants": True, + "reactant_1": "vinyl", + "product": "vinyl_chain_radical", + "delete_atom": False, + "reaction": ( + "[CH2:1]=[CH;!R:3]." + "[CH2:2]=[C;!R:4]-[*:5]" + ">>" + "[C:1]-[C:3]-[C:2]-[C:4]-[*:5]" + ), + "reference": { + "smarts": None, + "reaction_and_mechanism": None, + }, + "comments": ( + "Vinyl initiation reaction. Atom maps 1 and 2 identify the " + "reacting atoms from the first and second vinyl molecules." + ), + }, + "Vinyl Addition Polymerization Propagation": { + "same_reactants": False, + "reactant_1": "vinyl_chain_radical", + "reactant_2": "vinyl", + "product": "vinyl_chain_radical", + "delete_atom": False, + "reaction": ( + "[C:1]-[*:5]." + "[CH2:2]=[CH;!R:3]-[*:6]" + ">>" + "[C:1]([*:5])-[CH2:2]-[CH:3]-[*:6]" + ), + "reference": { + "smarts": None, + "reaction_and_mechanism": None, + }, + "comments": ( + "Vinyl propagation reaction. Atom map 1 is the reacting chain-end " + "atom, and atom map 2 is the reacting atom of the incoming vinyl molecule." + ), + }, # ============================================================ # Commented reactions # ============================================================ diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 0a14fdec..38b096d5 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -222,8 +222,6 @@ def _prepare_products_for_idx_based_fg_detection( ] = [] for reaction in self.session.reaction_metadata: - # Inactive reactions do not contain products that can participate - # in a subsequent progression iteration. if not reaction.activity_stats: continue @@ -234,12 +232,21 @@ def _prepare_products_for_idx_based_fg_detection( product_mol, ) + sanitized_mol = self._sanitize_molecule(product_mol) + + if sanitized_mol is None: + print( + f"Skipping reaction product {reaction.reaction_id}: " + "RDKit molecule sanitization failed." + ) + continue + prepared_monomer_roles.append( MonomerRoleforIndexBasedFGDetection( - smiles=self._get_product_smiles(product_mol), + smiles=self._get_product_smiles(sanitized_mol), name=f"new_{reaction.reaction_id}", indexes_in_template=indexes_in_template, - rdkit_mol=self._sanitize_molecule(product_mol), + rdkit_mol=sanitized_mol, ) ) From 8f9c279f2ff22d01a243de593b34fb42aab2d8ca Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 17:09:44 -0400 Subject: [PATCH 046/176] Fix vinyl polymerization SMARTS and radical handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Overhaul vinyl addition polymerization detection and reaction logic: - Rename `vinyl_chain_radical_monomer` → `vinyl_chain_end_radical` with a corrected SMARTS that matches secondary carbon radicals without false-positives on unreacted monomers - Fix initiation and propagation reaction SMARTS/atom maps to correctly track radical chain ends - Add reverse-order retry when RDKit RunReactants fails - Rewrite `_sanitize_molecule` to patch radical electrons on newly formed chain ends and strip them from saturated carbons post-reaction - Add `_fix_radical_and_sanitize` helper for under-valent radical carbon recovery - Clear RDKit ghost atom properties (`old_mapno`, `react_atom_idx`) in `_clean_product` to prevent stale atom tracking - Add debug print statements for molecule inspection and substructure matching --- .../detectors/functional_groups_detector.py | 1 + .../detectors/functional_groups_library.py | 11 +- AutoREACTER/detectors/reactions_library.py | 32 ++-- .../reaction_processor/prepare_reactions.py | 15 +- .../reaction_progression.py | 152 +++++++++++++----- 5 files changed, 153 insertions(+), 58 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index 6f1a9e53..b0d9377d 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -532,6 +532,7 @@ def index_based_functional_groups_detector( # Add to roles if any functionalities detected. if detected_functionalities: + print(f"Detected functionalities for monomer {detected_functionalities}") monomer_roles_out.append( MonomerRole( smiles=monomer.smiles, diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index 0207c82d..155a8f1b 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -186,11 +186,14 @@ def __init__(self): "comments": None, }, - "vinyl_chain_radical_monomer": { + "vinyl_chain_end_radical": { "functionality_type": "mono", - "smarts_1": "[C]-[*]", - "group_name": "vinyl_chain_radical", - "comments": "Reactive chain-end group used for vinyl propagation.", + "smarts_1": "[C;!R;D3](-[H])(-[!#1])-[!#1]", + "group_name": "vinyl_chain_end_radical", + "comments": ( + "Secondary carbon-centered radical attached through two carbon bonds. " + "Does not match the valence-4 alkene carbon of an unreacted monomer." + ), }, # ============================================================ diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py index 29cc7530..4f9f4268 100644 --- a/AutoREACTER/detectors/reactions_library.py +++ b/AutoREACTER/detectors/reactions_library.py @@ -378,43 +378,43 @@ def __init__(self): "Vinyl Addition Polymerization Initiation": { "same_reactants": True, "reactant_1": "vinyl", - "product": "vinyl_chain_radical", + "product": "vinyl_chain_end_radical", "delete_atom": False, "reaction": ( - "[CH2:1]=[CH;!R:3]." - "[CH2:2]=[C;!R:4]-[*:5]" + "[CH2:1]=[CH:3]-[*:5]." + "[CH2:2]=[CH:4]-[*:6]" ">>" - "[C:1]-[C:3]-[C:2]-[C:4]-[*:5]" + "[CH2:1](-[C:3]-[*:5])-[CH2:2]-[C:4]-[*:6]" ), "reference": { "smarts": None, "reaction_and_mechanism": None, }, "comments": ( - "Vinyl initiation reaction. Atom maps 1 and 2 identify the " - "reacting atoms from the first and second vinyl molecules." + "Atom maps 1 and 2 are the initiating atoms from the two vinyl " + "molecules. Atom 4 becomes the new carbon-centered radical." ), }, - "Vinyl Addition Polymerization Propagation": { "same_reactants": False, - "reactant_1": "vinyl_chain_radical", - "reactant_2": "vinyl", - "product": "vinyl_chain_radical", + "reactant_1": "vinyl", + "reactant_2": "vinyl_chain_end_radical", + "product": "vinyl_chain_end_radical", "delete_atom": False, - "reaction": ( - "[C:1]-[*:5]." - "[CH2:2]=[CH;!R:3]-[*:6]" + "reaction":( + "[CH2:2]=[CH:3]-[*:6]." + "[*:5]-[C;!R;H1:1]-[*:7]" ">>" - "[C:1]([*:5])-[CH2:2]-[CH:3]-[*:6]" + "[*:5]-[C:1](-[*:7])-[CH2:2]-[C:3]-[*:6]" ), "reference": { "smarts": None, "reaction_and_mechanism": None, }, "comments": ( - "Vinyl propagation reaction. Atom map 1 is the reacting chain-end " - "atom, and atom map 2 is the reacting atom of the incoming vinyl molecule." + "Atom 1 is the existing radical chain-end carbon. Atom 2 is the " + "reacting atom of the incoming vinyl monomer. Atom 3 becomes the " + "new radical chain end." ), }, # ============================================================ diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index ca170454..e0fd2489 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -338,13 +338,24 @@ def _process_reaction_products(self, # Assign atom map numbers and isotopes to reactants for tracking through the reaction self._assign_atom_map_numbers_and_set_isotopes(r1, r2) - # Run the reaction and get product sets + # 1. Run the reaction in default order (A + B) products = rxn.RunReactants((r1, r2)) - # Skip if no products were generated + # 2. If it fails due to order mismatch, try the reverse (B + A) if not products: + print ("Reaction failed in default order, trying reverse order...") + products = rxn.RunReactants((r2, r1)) + + # Skip if no products were generated in either direction + if not products: + print ("Reaction failed in both orders, skipping this reactant pair.") + print(f"\n[ERROR] RDKit failed to react {r1.GetNumAtoms()} atoms with {r2.GetNumAtoms()} atoms.") + print(f"Reactant 1 SMILES: {Chem.MolToSmiles(r1)}") + print(f"Reactant 2 SMILES: {Chem.MolToSmiles(r2)}") + print(f"Reaction SMARTS: \n") continue + # Process each product set generated by the reaction for product_set in products: df = pd.DataFrame(columns=["reactant_idx", "product_idx"]) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 38b096d5..2b943043 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -145,13 +145,14 @@ def reaction_progression( monomer_roles_in_loop.extend(fg_detection_results) self.session.monomer_roles = monomer_roles_in_loop + print(monomer_roles_in_loop) reaction_instances = ( self.rxn_detector.index_based_reaction_detector( monomer_roles_in_loop ) ) - + print(reaction_instances) if not reaction_instances: print( f"No new reactions detected in iteration {iteration}. " @@ -193,11 +194,7 @@ def _index_based_reaction_preparation( self, reaction_instances: list["ReactionInstance"], ) -> list["ReactionMetadata"]: - """Convert detected reaction instances into prepared reaction metadata. - - The import is local to avoid importing the reaction-preparation module - during module initialization, which also helps prevent circular imports. - """ + """Convert detected reaction instances into prepared reaction metadata.""" from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( PrepareReactions, ) @@ -205,7 +202,7 @@ def _index_based_reaction_preparation( reaction_preparer = PrepareReactions(self.session) return reaction_preparer._prepare_reactions_stage( - reaction_instances + reaction_instances, loop=True ) def _prepare_products_for_idx_based_fg_detection( @@ -232,15 +229,33 @@ def _prepare_products_for_idx_based_fg_detection( product_mol, ) - sanitized_mol = self._sanitize_molecule(product_mol) - - if sanitized_mol is None: + sanitized_mol, success = self._sanitize_molecule(product_mol) + + # THIS IS A DEBUG BLOCK --- + if success: + print("\n--- DEBUG MOLECULE ---") + print("SMILES:", Chem.MolToSmiles(sanitized_mol)) + for a in sanitized_mol.GetAtoms(): + if a.GetDegree() == 2 and a.GetAtomicNum() == 6: + print(f"Atom {a.GetIdx()}: Symbol={a.GetSymbol()}, Heavy Neighbors={a.GetDegree()}, Total Hs={a.GetTotalNumHs()}, Radicals={a.GetNumRadicalElectrons()}") + print("----------------------\n") + # ---------------------------- + + matches = sanitized_mol.GetSubstructMatches(Chem.MolFromSmarts("[C;!R;D3](-[H])(-[!#1])-[!#1]")) + print(f"Substructure matches for radical carbon: {matches}") + print( + f"Sanitizing reaction product {reaction.reaction_id}... " + f"result {success}" + ) + if not success: print( f"Skipping reaction product {reaction.reaction_id}: " "RDKit molecule sanitization failed." ) - continue - + else: + print( + f"Reaction product {reaction.reaction_id} sanitized successfully." + ) prepared_monomer_roles.append( MonomerRoleforIndexBasedFGDetection( smiles=self._get_product_smiles(sanitized_mol), @@ -263,46 +278,111 @@ def _store_reactions( def _sanitize_molecule( self, mol: Chem.Mol, - ) -> Chem.Mol | None: - """Clean and sanitize an RDKit molecule. - - Atom-map numbers and isotope labels are removed before sanitization. - Products that RDKit cannot sanitize are discarded and represented by - ``None``. - - Args: - mol: Molecule to clean and sanitize. - - Returns: - The sanitized molecule, or ``None`` if sanitization fails. - """ + ) -> tuple[Chem.Mol | None, bool]: cleaned_mol = self._clean_product(mol) + patched_mol = Chem.RWMol(cleaned_mol) + patched_mol.UpdatePropertyCache(strict=False) + Chem.FastFindRings(patched_mol) + + for atom in patched_mol.GetAtoms(): + if atom.GetAtomicNum() == 6: + atom.SetNoImplicit(True) + + heavy_val = int(sum(bond.GetValenceContrib(atom) for bond in atom.GetBonds())) + explicit_hs = atom.GetNumExplicitHs() + rads = atom.GetNumRadicalElectrons() + + # 1. STRIP radical electrons ONLY from the OLD chain end! + # If it just formed a new bond, its heavy + Hs equals 4. It is no longer a radical. + if heavy_val + explicit_hs >= 4 and rads > 0: + atom.SetNumRadicalElectrons(0) + rads = 0 + + # 2. Fix over-valent carbons (if RunReactants forces too many Hs) + if heavy_val + explicit_hs + rads > 4: + allowed_hs = max(0, 4 - heavy_val - rads) + atom.SetNumExplicitHs(allowed_hs) + explicit_hs = allowed_hs + + # 3. PROTECT the NEW chain end! + # If it has 3 bonds, it's the new radical. Give it the electron back + # so Chem.AddHs() doesn't accidentally quench it with a fake hydrogen! + if heavy_val + explicit_hs == 3 and atom.GetFormalCharge() == 0: + atom.SetNumRadicalElectrons(1) + + patched_mol = patched_mol.GetMol() + patched_mol.ClearComputedProps() try: - Chem.SanitizeMol(cleaned_mol) - except Exception as error: - print(f"Could not sanitize product molecule: {error}") - return None - - return cleaned_mol + Chem.SanitizeMol(patched_mol) + return patched_mol, True + except Exception: + pass - def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: - """Return a copy of ``mol`` without atom maps or isotope labels. + radical_fixed_mol = self._fix_radical_and_sanitize(patched_mol) - The input molecule is copied and therefore remains unchanged. + try: + Chem.SanitizeMol(radical_fixed_mol) + return radical_fixed_mol, True + + except Exception as error2: + radical_fixed_mol.UpdatePropertyCache(strict=False) + Chem.FastFindRings(radical_fixed_mol) + return radical_fixed_mol, False + + def _fix_radical_and_sanitize( + self, + raw_mol: Chem.Mol, + query: str = "[CH;X3;v3]", + ) -> Chem.Mol: + """ + RunReactants() output is unsanitized. Our radical carbon is deliberately + under-valent (v3 instead of v4) to mark it in SMARTS, but that's not a + real chemical species RDKit can sanitize or round-trip through SMILES. + This finds that atom and gives it an actual radical electron, so the + missing valence is accounted for and the mol becomes fully sanitizable. Args: - mol: Molecule whose atom annotations should be removed. + raw_mol: Molecule that may contain an under-valent radical carbon. + query: SMARTS identifying the deliberately under-valent radical atom. Returns: - A cleaned copy of the input molecule. + A new Chem.Mol with the radical atom's valence properly accounted + for via NumRadicalElectrons, ready for Chem.SanitizeMol(). """ + mol = Chem.RWMol(raw_mol) + mol.UpdatePropertyCache(strict=False) # need valence to even run the query + Chem.FastFindRings(mol) + + query_mol = Chem.MolFromSmarts(query) + hits = mol.GetSubstructMatches(query_mol) + + for match in hits: + atom = mol.GetAtomWithIdx(match[0]) # first atom = the radical carbon + atom.SetNoImplicit(True) + if atom.GetTotalNumHs() != 1: + atom.SetNumExplicitHs(1) + atom.SetNumRadicalElectrons(1) + + return mol.GetMol() + + def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: + """Return a copy of ``mol`` without atom maps, isotopes, or ghost properties.""" cleaned_mol = Chem.Mol(mol) for atom in cleaned_mol.GetAtoms(): + # Clean standard tracking labels atom.SetAtomMapNum(0) atom.SetIsotope(0) + # EXORCISE THE GHOSTS: + # RDKit hides tracking data like 'old_mapno' deep in the atom properties. + # We MUST clear them so AutoREACTER doesn't mistake old atoms for new initiators! + if atom.HasProp("old_mapno"): + atom.ClearProp("old_mapno") + if atom.HasProp("react_atom_idx"): + atom.ClearProp("react_atom_idx") + return cleaned_mol def _get_product_smiles(self, mol: Chem.Mol) -> str: From 8c3f4ad920684973539ac0b64ad3a46a85480659 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 14 Jul 2026 17:12:02 -0400 Subject: [PATCH 047/176] Create test_styrene.json --- examples/test_styrene.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 examples/test_styrene.json diff --git a/examples/test_styrene.json b/examples/test_styrene.json new file mode 100644 index 00000000..d8721b8e --- /dev/null +++ b/examples/test_styrene.json @@ -0,0 +1,19 @@ +{ + "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "simulations": [ + { + "tag": "vinyl_test", + "temperature": 300, + "density": 1.0, + "monomer_counts": { + "styrene": 200 + } + } + ], + "monomers": [ + { + "name": "styrene", + "smiles": "c1ccccc1C=C" + } + ] +} \ No newline at end of file From ff253874591e4f9312aad92669768c1ab29f52fb Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 12:17:30 -0400 Subject: [PATCH 048/176] Improve 3D molecule prep and add repair step --- .../ff_wrapper/molecule_3d_preparation.py | 170 +++++++++++++----- 1 file changed, 127 insertions(+), 43 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/molecule_3d_preparation.py b/AutoREACTER/reaction_preparation/ff_wrapper/molecule_3d_preparation.py index 6500e37c..648d9b06 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/molecule_3d_preparation.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/molecule_3d_preparation.py @@ -219,69 +219,153 @@ def _optimization( cache_dir: Path, separate_fragments: bool = False, ) -> Path: - """Embed a molecule in 3D, optionally separate fragments, optimize geometry, - and save the result as a .mol file. + """Repair, embed, optimize, and save a molecule without adding hydrogens.""" - The optimization process includes: - 1. Sanitization and property cache update - 2. 3D coordinate embedding using ETKDG method - 3. Optional fragment separation for multi-molecule complexes - 4. Geometry optimization using MMFF force field - 5. File saving + # Work on a copy so the ReactionMetadata molecule and its indexing remain + # unchanged outside this 3D preparation step. + mol = Chem.Mol(mol) + n_atoms_start = mol.GetNumAtoms(onlyExplicit=True) - Args: - molecule_name: Name used for the output file. - mol: RDKit molecule to be optimized. - cache_dir: Directory where the .mol file will be saved. - separate_fragments: Whether to separate disconnected fragments before optimization. + try: + mol = self._repair_reaction_molecule_for_3d(mol) + except Exception as error: + raise OptimizationError( + f"Failed to repair molecule {molecule_name} before 3D embedding: " + f"{error}" + ) from error - Returns: - Path to the saved .mol file. + # Remove any old or partial conformers before embedding. + mol.RemoveAllConformers() - Raises: - OptimizationError: If atom count changes or optimization fails. - """ - # Record initial atom count for integrity check - n_atoms_start = mol.GetNumAtoms(onlyExplicit=True) + params = AllChem.ETKDGv3() + params.randomSeed = 0xF00D - # Update property cache and sanitize molecule - mol.UpdatePropertyCache(strict=False) - Chem.SanitizeMol( - mol, - sanitizeOps=Chem.SanitizeFlags.SANITIZE_ALL - ^ Chem.SanitizeFlags.SANITIZE_PROPERTIES, - ) + embed_result = AllChem.EmbedMolecule(mol, params) - # Generate initial 3D coordinates using ETKDG method - result = AllChem.EmbedMolecule(mol, AllChem.ETKDG()) - if result == -1: - raise OptimizationError(f"Failed to embed molecule {molecule_name} in 3D.") + if embed_result == -1: + raise OptimizationError( + f"Failed to embed molecule {molecule_name} in 3D." + ) - # Separate fragments if this is a complex (reactants or products) if separate_fragments: mol = self._separate_fragments_3d(mol) - # Perform geometry optimization using MMFF force field - ff_result = AllChem.MMFFOptimizeMolecule(mol) + # MMFF generally works for these carbon radicals, but keep a UFF fallback + # for structures for which MMFF lacks parameters. + if AllChem.MMFFHasAllMoleculeParams(mol): + ff_result = AllChem.MMFFOptimizeMolecule( + mol, + maxIters=1000, + ) + force_field_name = "MMFF" + elif AllChem.UFFHasAllMoleculeParams(mol): + ff_result = AllChem.UFFOptimizeMolecule( + mol, + maxIters=1000, + ) + force_field_name = "UFF" + else: + ff_result = None + force_field_name = None + print( + f"Warning: no MMFF or UFF parameters are available for " + f"{molecule_name}. Saving the embedded geometry without " + "force-field optimization." + ) + if ff_result == -1: - print(f"MMFF optimization failed for {molecule_name}.") + raise OptimizationError( + f"{force_field_name} optimization failed for {molecule_name}." + ) + if ff_result == 1: - print(f"Warning: MMFF optimization did not converge for {molecule_name}.") + print( + f"Warning: {force_field_name} optimization did not converge " + f"for {molecule_name}." + ) - # Verify atom count integrity (no atoms lost during optimization) - if n_atoms_start != mol.GetNumAtoms(onlyExplicit=True): + n_atoms_end = mol.GetNumAtoms(onlyExplicit=True) + + if n_atoms_start != n_atoms_end: raise OptimizationError( - f"Atom count mismatch for {molecule_name}: started with {n_atoms_start} " - f"explicit atoms but ended with {mol.GetNumAtoms(onlyExplicit=True)}." + f"Atom count mismatch for {molecule_name}: started with " + f"{n_atoms_start} explicit atoms but ended with {n_atoms_end}." ) - # Ensure cache directory exists os.makedirs(cache_dir, exist_ok=True) - # Save optimized structure to file output_path = Path(cache_dir) / f"{molecule_name}.mol" print(f"Saving optimized {molecule_name} to {output_path}") - Chem.MolToMolFile(mol, str(output_path)) + Chem.MolToMolFile( + mol, + str(output_path), + includeStereo=True, + kekulize=False, + ) return output_path + + def _repair_reaction_molecule_for_3d(self, mol: Mol) -> Mol: + """Repair RDKit reaction-product valence bookkeeping before 3D embedding. + + RunReactants may produce atoms that have both: + 1. explicit hydrogen atoms as neighbors, and + 2. a nonzero NumExplicitHs property inherited from the product SMARTS. + + That double-counts hydrogens and can produce apparent carbon valences of + five or six. This method changes atom properties only; it does not add or + remove atoms. + + Neutral, non-aromatic carbon atoms with bond valence three are retained as + carbon-centered radicals instead of being given an implicit hydrogen. + """ + repaired = Chem.RWMol(Chem.Mol(mol)) + repaired.UpdatePropertyCache(strict=False) + Chem.FastFindRings(repaired) + + for atom in repaired.GetAtoms(): + explicit_h_neighbors = sum( + neighbor.GetAtomicNum() == 1 + for neighbor in atom.GetNeighbors() + ) + + # The hydrogen atoms already exist as real graph atoms. Clear only the + # duplicate SMARTS hydrogen-count property. + if explicit_h_neighbors > 0: + if atom.GetNumExplicitHs() > 0: + atom.SetNumExplicitHs(0) + + # Do not let RDKit add another implicit hydrogen during sanitization. + atom.SetNoImplicit(True) + + if atom.GetAtomicNum() != 6: + continue + + bond_valence = sum( + bond.GetValenceContrib(atom) + for bond in atom.GetBonds() + ) + + # Preserve neutral carbon-centered radical chain ends. + if ( + not atom.GetIsAromatic() + and atom.GetFormalCharge() == 0 + and abs(bond_valence - 3.0) < 1.0e-6 + ): + atom.SetNoImplicit(True) + atom.SetNumRadicalElectrons(1) + + # Radical-radical coupling gives each carbon its fourth valence. + elif bond_valence >= 4.0: + atom.SetNumRadicalElectrons(0) + + repaired_mol = repaired.GetMol() + repaired_mol.ClearComputedProps() + repaired_mol.UpdatePropertyCache(strict=False) + + # Full sanitization is now safe because the duplicate hydrogen counts + # and radical valences have been repaired. + Chem.SanitizeMol(repaired_mol) + + return repaired_mol \ No newline at end of file From 735c20a931053d561c51aeed5ee583040c036bcb Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 12:17:50 -0400 Subject: [PATCH 049/176] Generalize vinyl radical SMARTS patterns --- .../detectors/functional_groups_library.py | 7 +-- AutoREACTER/detectors/reactions_library.py | 45 ++++++++++++++----- examples/test_ethelene.json | 19 ++++++++ 3 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 examples/test_ethelene.json diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index 155a8f1b..72f6069a 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -188,11 +188,12 @@ def __init__(self): "vinyl_chain_end_radical": { "functionality_type": "mono", - "smarts_1": "[C;!R;D3](-[H])(-[!#1])-[!#1]", + "smarts_1": "[C;!R;D3;v3]", "group_name": "vinyl_chain_end_radical", "comments": ( - "Secondary carbon-centered radical attached through two carbon bonds. " - "Does not match the valence-4 alkene carbon of an unreacted monomer." + "Neutral non-ring carbon-centered radical with degree 3 and " + "valence 3. Supports primary, secondary, and tertiary vinyl " + "polymer chain ends." ), }, diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py index 4f9f4268..6d28592a 100644 --- a/AutoREACTER/detectors/reactions_library.py +++ b/AutoREACTER/detectors/reactions_library.py @@ -381,18 +381,18 @@ def __init__(self): "product": "vinyl_chain_end_radical", "delete_atom": False, "reaction": ( - "[CH2:1]=[CH:3]-[*:5]." - "[CH2:2]=[CH:4]-[*:6]" + "[CH2:1]=[C;!R:3]." + "[CH2:2]=[C;!R:4]" ">>" - "[CH2:1](-[C:3]-[*:5])-[CH2:2]-[C:4]-[*:6]" + "[CH2:1](-[C:3])-[CH2:2]-[C:4]" ), "reference": { "smarts": None, "reaction_and_mechanism": None, }, "comments": ( - "Atom maps 1 and 2 are the initiating atoms from the two vinyl " - "molecules. Atom 4 becomes the new carbon-centered radical." + "Joins two terminal vinyl groups. The two alkene carbons that do " + "not form the new intermolecular bond become radical chain ends." ), }, "Vinyl Addition Polymerization Propagation": { @@ -401,20 +401,41 @@ def __init__(self): "reactant_2": "vinyl_chain_end_radical", "product": "vinyl_chain_end_radical", "delete_atom": False, - "reaction":( - "[CH2:2]=[CH:3]-[*:6]." - "[*:5]-[C;!R;H1:1]-[*:7]" + "reaction": ( + "[CH2:2]=[C;!R:3]." + "[C;!R;D3;v3:1]" + ">>" + "[C:1]-[CH2:2]-[C:3]" + ), + "reference": { + "smarts": None, + "reaction_and_mechanism": None, + }, + "comments": ( + "The existing carbon radical forms a bond with the terminal CH2 " + "of the incoming vinyl monomer. The other alkene carbon becomes " + "the new radical center." + ), + }, + "Vinyl Radical Coupling Termination": { + "same_reactants": True, + "reactant_1": "vinyl_chain_end_radical", + "product": "vinyl_terminated_chain", + "delete_atom": False, + "reaction": ( + "[C;!R;D3;v3;+0:1]." + "[C;!R;D3;v3;+0:2]" ">>" - "[*:5]-[C:1](-[*:7])-[CH2:2]-[C:3]-[*:6]" + "[C:1]-[C:2]" ), "reference": { "smarts": None, "reaction_and_mechanism": None, }, "comments": ( - "Atom 1 is the existing radical chain-end carbon. Atom 2 is the " - "reacting atom of the incoming vinyl monomer. Atom 3 becomes the " - "new radical chain end." + "Termination by combination of two neutral carbon-centered " + "vinyl chain-end radicals. A new carbon-carbon single bond " + "is formed and both radical centers are consumed." ), }, # ============================================================ diff --git a/examples/test_ethelene.json b/examples/test_ethelene.json new file mode 100644 index 00000000..d7f10d79 --- /dev/null +++ b/examples/test_ethelene.json @@ -0,0 +1,19 @@ +{ + "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "simulations": [ + { + "tag": "vinyl_test", + "temperature": 300, + "density": 1.0, + "monomer_counts": { + "styrene": 200 + } + } + ], + "monomers": [ + { + "name": "styrene", + "smiles": "C=C" + } + ] +} \ No newline at end of file From e6cd09c657fb3aa3f268a97feb8d8dc407728ba0 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:10:04 -0400 Subject: [PATCH 050/176] Make RDKit deduplication radical-aware Update reaction graph comparison to include radical state in RDKit atom labels and attach a full-molecule radical signature to coupled graphs before isomorphism checks. This prevents false duplicate matches when restricted templates miss radical centers, and adds robust radical detection/counting logic for unsanitized RunReactants products. --- .../deduplication_detector.py | 158 +++++++++++++++++- 1 file changed, 154 insertions(+), 4 deletions(-) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 8602df2e..70c35c5e 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -3,8 +3,8 @@ molecule templates. The comparison intentionally ignores coordinates, atom IDs, and bond IDs. -RDKit comparisons use chemical element and bond type. LAMMPS comparisons -use atom type and bond type. +RDKit comparisons use chemical element, radical state, and bond type. +LAMMPS comparisons use atom type and bond type. """ from __future__ import annotations @@ -27,6 +27,10 @@ class DeduplicationDetector: NODE_ATTRIBUTE = "atom_label" EDGE_ATTRIBUTE = "bond_label" + RADICAL_COUNT_ATTRIBUTE = "radical_count" + RADICAL_PRESENT_ATTRIBUTE = "contains_radical" + RADICAL_SIGNATURE_ATTRIBUTE = "radical_signature" + LAMMPS_COMPARISON_GROUP = "lammps" RDKIT_COMPARISON_GROUP = "rdkit" @@ -108,6 +112,19 @@ def is_duplicate( ) for seen_graph in seen_graphs: + # The restricted template graph may not include every radical + # center in the complete molecule. Compare the full-molecule + # pre/post radical signature before checking graph isomorphism. + if ( + coupled_graph.graph.get( + self.RADICAL_SIGNATURE_ATTRIBUTE + ) + != seen_graph.graph.get( + self.RADICAL_SIGNATURE_ATTRIBUTE + ) + ): + continue + if ( coupled_graph.number_of_nodes() != seen_graph.number_of_nodes() @@ -392,6 +409,33 @@ def compare_graphs_mol( idx_relabel=product_to_reactant_mapping, ) + # Keep full-molecule radical information in addition to the + # atom-level radical labels inside the restricted template graph. + # Progression may explicitly mark the product as radical even when + # the original unsanitized RDKit product does not retain the + # radical-electron property cleanly. + reactant_radical_count = self._count_radical_atoms( + reactant_mol + ) + product_radical_count = self._count_radical_atoms( + product_mol + ) + + pre_graph.graph[self.RADICAL_COUNT_ATTRIBUTE] = ( + reactant_radical_count + ) + post_graph.graph[self.RADICAL_COUNT_ATTRIBUTE] = ( + product_radical_count + ) + + pre_graph.graph[self.RADICAL_PRESENT_ATTRIBUTE] = ( + reactant_radical_count > 0 + ) + post_graph.graph[self.RADICAL_PRESENT_ATTRIBUTE] = ( + product_radical_count > 0 + or bool(getattr(reaction_metadata, "is_radical", False)) + ) + duplicate = self.is_duplicate( pre_template_graph=pre_graph, post_template_graph=post_graph, @@ -460,11 +504,14 @@ def rdkit_mol_to_networkx( Coordinates are not read or stored. Node attributes: - ``atom_label`` contains the chemical element symbol. + ``atom_label`` contains a tuple of: + - chemical element symbol + - whether the atom is a radical center Edge attributes: ``bond_label`` contains the RDKit bond type. """ + if molecule is None: raise ValueError( "Cannot create a graph from a None RDKit molecule." @@ -503,10 +550,17 @@ def rdkit_mol_to_networkx( idx_relabel=idx_relabel, ) + is_radical = self._is_radical_atom(atom) + + atom_label = ( + atom.GetSymbol(), + is_radical, + ) + graph.add_node( node_id, **{ - self.NODE_ATTRIBUTE: atom.GetSymbol(), + self.NODE_ATTRIBUTE: atom_label, }, ) @@ -657,6 +711,7 @@ def _couple_graphs( Combine reactant and product graphs using atom-correspondence edges. """ + pre_atom_ids = set(pre_template_graph.nodes) post_atom_ids = set(post_template_graph.nodes) @@ -678,6 +733,25 @@ def _couple_graphs( coupled_graph = nx.Graph() + coupled_graph.graph[self.RADICAL_SIGNATURE_ATTRIBUTE] = ( + pre_template_graph.graph.get( + self.RADICAL_COUNT_ATTRIBUTE, + 0, + ), + post_template_graph.graph.get( + self.RADICAL_COUNT_ATTRIBUTE, + 0, + ), + pre_template_graph.graph.get( + self.RADICAL_PRESENT_ATTRIBUTE, + False, + ), + post_template_graph.graph.get( + self.RADICAL_PRESENT_ATTRIBUTE, + False, + ), + ) + self._add_phase_to_coupled_graph( source_graph=pre_template_graph, coupled_graph=coupled_graph, @@ -899,6 +973,82 @@ def _validate_bond_atoms( f"Bond {bond_id} references undefined atom IDs " f"{undefined_atoms} in {source}." ) + + @classmethod + def _count_radical_atoms( + cls, + molecule: Chem.Mol, + ) -> int: + """Count radical atoms in a complete RDKit molecule.""" + return sum( + cls._is_radical_atom(atom) + for atom in molecule.GetAtoms() + ) + + @staticmethod + def _is_radical_atom(atom: Chem.Atom) -> bool: + """Return True for an explicit or structurally under-valent radical atom. + + Progression normally sets ``NumRadicalElectrons`` on the cleaned + product. The structural fallback is needed because the original + ``RunReactants`` product stored in ``ReactionMetadata`` can retain + incomplete valence bookkeeping before later sanitization. + + The fallback is intentionally limited to neutral, non-aromatic carbon + atoms used by the current vinyl-radical implementation. + """ + + # Best source when progression or RDKit has explicitly assigned the + # radical electron. + if atom.GetNumRadicalElectrons() > 0: + return True + + # Current vinyl implementation only needs neutral carbon radicals. + if atom.GetAtomicNum() != 6: + return False + + if atom.GetFormalCharge() != 0: + return False + + if atom.GetIsAromatic(): + return False + + # A normal carbon with an implicit hydrogen can have only three visible + # graph bonds. Do not classify it as a radical. + try: + if atom.GetNumImplicitHs() > 0: + return False + except RuntimeError: + # Unsanitized reaction products may not have a complete property + # cache. Continue with the graph-based valence calculation. + pass + + # Count actual graph bonds, including explicit hydrogen atoms. + # + # Do not blindly add GetNumExplicitHs(): RunReactants may retain both + # real hydrogen atoms and a duplicate product-SMARTS hydrogen count. + graph_bond_valence = sum( + bond.GetBondTypeAsDouble() + for bond in atom.GetBonds() + ) + + explicit_hydrogen_neighbors = sum( + neighbor.GetAtomicNum() == 1 + for neighbor in atom.GetNeighbors() + ) + + # When no real hydrogen atoms are attached, the explicit-H property is + # part of the atom's valence description and must be included. When + # real H atoms are already present, ignore the property to avoid + # double-counting the same hydrogens. + effective_valence = graph_bond_valence + + if explicit_hydrogen_neighbors == 0: + effective_valence += atom.GetNumExplicitHs() + + # Neutral carbon with effective valence three and no available implicit + # hydrogen is the carbon-centered radical used by vinyl progression. + return abs(effective_valence - 3.0) < 1.0e-6 def _main() -> None: From 584e6aaf0d8b872c6c352987af7eafe4f3fc1fdf Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:10:36 -0400 Subject: [PATCH 051/176] Track radical atoms before reaction dedup Adds radical metadata to `ReactionMetadata` (`is_radical` and `radical_atom_idxs`) and populates it by sanitizing product molecules before NetworkX deduplication. Radical atom indices are mapped from product space into reactant-index space so identity survives relabeling/comparison. The in-loop debug print block was replaced with structured metadata assignment and explicit non-radical defaults when sanitization or product data is unavailable. --- .../reaction_processor/prepare_reactions.py | 2 + .../reaction_progression.py | 81 ++++++++++++++++--- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index e0fd2489..4cfa7a04 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -88,6 +88,8 @@ class ReactionMetadata: delete_atom_idx: Optional[int] = None reactant_combined_3Dmol_path: Optional[Path] = None product_combined_3Dmol_path: Optional[Path] = None + is_radical: bool = False + radical_atom_idxs: Optional[tuple[int, ...]] = () activity_stats: bool = True diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 2b943043..71294c38 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -164,6 +164,11 @@ def reaction_progression( reaction_instances=reaction_instances ) + # Radical identity must exist before NetworkX deduplication. + self._annotate_radicals_before_deduplication( + prepared_reactions + ) + all_prepared_reactions.extend(prepared_reactions) self.session.reaction_metadata = all_prepared_reactions @@ -186,6 +191,7 @@ def reaction_progression( ) if should_break: + continue return self._store_reactions(all_prepared_reactions) return all_prepared_reactions @@ -230,16 +236,14 @@ def _prepare_products_for_idx_based_fg_detection( ) sanitized_mol, success = self._sanitize_molecule(product_mol) - - # THIS IS A DEBUG BLOCK --- - if success: - print("\n--- DEBUG MOLECULE ---") - print("SMILES:", Chem.MolToSmiles(sanitized_mol)) - for a in sanitized_mol.GetAtoms(): - if a.GetDegree() == 2 and a.GetAtomicNum() == 6: - print(f"Atom {a.GetIdx()}: Symbol={a.GetSymbol()}, Heavy Neighbors={a.GetDegree()}, Total Hs={a.GetTotalNumHs()}, Radicals={a.GetNumRadicalElectrons()}") - print("----------------------\n") - # ---------------------------- + if success and sanitized_mol is not None: + self._set_reaction_radical_metadata( + reaction, + sanitized_mol, + ) + else: + reaction.is_radical = False + reaction.radical_atom_idxs = () matches = sanitized_mol.GetSubstructMatches(Chem.MolFromSmarts("[C;!R;D3](-[H])(-[!#1])-[!#1]")) print(f"Substructure matches for radical carbon: {matches}") @@ -563,3 +567,60 @@ def _count_active_reactions( bool(reaction.activity_stats) for reaction in reactions ) + + def _set_reaction_radical_metadata( + self, + reaction: "ReactionMetadata", + sanitized_product: Chem.Mol, + ) -> None: + """Store product radical atoms in reactant-index space. + + Deduplication relabels product atoms into reactant-index space, so + radical indexes are converted using product_to_reactant_mapping. + """ + product_radical_idxs = { + atom.GetIdx() + for atom in sanitized_product.GetAtoms() + if atom.GetNumRadicalElectrons() > 0 + } + + radical_reactant_idxs = { + reaction.product_to_reactant_mapping[product_idx] + for product_idx in product_radical_idxs + if product_idx in reaction.product_to_reactant_mapping + } + + reaction.is_radical = bool(radical_reactant_idxs) + reaction.radical_atom_idxs = tuple( + sorted(radical_reactant_idxs) + ) + + def _annotate_radicals_before_deduplication( + self, + reactions: list["ReactionMetadata"], + ) -> None: + """Sanitize new products and record radical atoms before NetworkX comparison.""" + for reaction in reactions: + if not reaction.activity_stats: + continue + + product_mol = reaction.product_combined_RDmol + + if product_mol is None: + reaction.is_radical = False + reaction.radical_atom_idxs = () + continue + + sanitized_mol, success = self._sanitize_molecule( + product_mol + ) + + if not success or sanitized_mol is None: + reaction.is_radical = False + reaction.radical_atom_idxs = () + continue + + self._set_reaction_radical_metadata( + reaction, + sanitized_mol, + ) \ No newline at end of file From e52f82f8e6cd446a743ed78775a152b30ac12a22 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:15:47 -0400 Subject: [PATCH 052/176] Add loop controls for reaction progression This change introduces input-level loop configuration so users can disable progression entirely or provide a positive integer to cap loop iterations. The parser now validates `loop` and stores `loop`/`max_loop_count` in `SimulationSetup`, and reaction preparation conditionally runs progression based on that flag while still enforcing zero-active-reaction checks. The styrene example was also updated (name and monomer count) to reflect current test usage. --- AutoREACTER/input_parser.py | 30 +++++++++++++++++++ .../reaction_processor/prepare_reactions.py | 21 ++++++++----- .../reaction_progression.py | 2 ++ examples/test_styrene.json | 4 +-- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index be05278d..d6e2365b 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -149,6 +149,8 @@ class SimulationSetup: density: list[float] force_field: str | None monomers: list[MonomerEntry] + loop : bool = True + max_loop_count: int | None = None simulations: list[Simulation] | None = None composition_method: CompositionMethodType | None = None composition: dict[str, Any] | None = None @@ -203,6 +205,8 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: inputs.get("force_field", None) ) + loop, max_loop_count = self._validate_loop(inputs) + return SimulationSetup( simulation_name=simulation_name, temperature=validated_simulations["temperatures"], @@ -212,6 +216,8 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: composition_method=composition_method, composition=validated_simulations, force_field=force_field, + loop=loop, + max_loop_count=max_loop_count ) def molecule_representation_of_initial_molecules( @@ -939,6 +945,30 @@ def _validate_simulations( "systems": systems, "simulations": simulations, } + + def _validate_loop(self, inputs: dict) -> tuple[bool, int | None]: + """ + Validates the 'loop' parameter in the input dictionary. + + Returns a tuple (loop, max_loop_count) where 'loop' is a boolean indicating + whether looping is enabled, and 'max_loop_count' is an integer specifying + the maximum number of loop iterations if 'loop' is an integer, or None otherwise. + """ + loop_variables = ["loop", "repeat", "iterations", "do_loop"] + loop = inputs.get("loop", True) + if not isinstance(loop, bool): + if isinstance(loop, int): + if loop <= 0: + raise InputSchemaError( + "'loop' must be a positive integer." + ) + return True, loop + if loop in loop_variables: + return True, None + raise InputSchemaError( + "'loop' must be a boolean value or a positive integer." + ) + return loop, None if __name__ == "__main__": diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 4cfa7a04..6f2573c5 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -115,15 +115,20 @@ def prepare_reactions(self, session): prepared_reactions = self._prepare_reactions_stage(session) session.reaction_metadata = prepared_reactions - # 2. Run progression loop (this returns the FULL, deduplicated list) - reaction_progression = ReactionProgression(session) - final_reactions = reaction_progression.reaction_progression() + if session.inputs.loop: + # 2. Run progression loop (this returns the FULL, deduplicated list) + reaction_progression = ReactionProgression(session) + + final_reactions = reaction_progression.reaction_progression() - # 3. Overwrite the session metadata with the final deduplicated list - session.reaction_metadata = final_reactions - - # 4. Error check - self._zero_active_reactions_error(final_reactions) + # 3. Overwrite the session metadata with the final deduplicated list + session.reaction_metadata = final_reactions + + # 4. Check weather is there avaible reaction present + self._zero_active_reactions_error(final_reactions) + + else: + self._zero_active_reactions_error(prepared_reactions) return session diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 71294c38..d2283dd5 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -91,6 +91,8 @@ def reaction_progression( Returns: The prepared and deduplicated reaction metadata. """ + if self.session.inputs.max_loop_count is not None: + max_loop = self.session.inputs.max_loop_count iteration = 0 monomer_roles_in_loop = list["MonomerRole"]( self.session.monomer_roles diff --git a/examples/test_styrene.json b/examples/test_styrene.json index d8721b8e..6cdcfb75 100644 --- a/examples/test_styrene.json +++ b/examples/test_styrene.json @@ -1,12 +1,12 @@ { - "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "simulation_name": "Styrene_Test", "simulations": [ { "tag": "vinyl_test", "temperature": 300, "density": 1.0, "monomer_counts": { - "styrene": 200 + "styrene": 2000 } } ], From 3602aaaea4ab1d0cf32993867776eb0d624132cc Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:39:51 -0400 Subject: [PATCH 053/176] Refine loop parsing and trim debug output Updated input loop validation to explicitly handle booleans, positive integers, and supported loop keywords with clearer error messaging. Integer loop values now announce the max iteration setting before execution. Reaction progression now shows the warning ASCII banner at initialization, and several ad-hoc debug prints were removed from functional group and reaction progression paths to reduce noisy console output. The ethene example input was also refreshed to use the new simulation name and a fixed loop count. --- .../detectors/functional_groups_detector.py | 4 -- AutoREACTER/input_parser.py | 51 ++++++++++++------- .../reaction_progression.py | 19 ++----- .../reaction_processor/warning_asci.py | 7 ++- examples/test_ethelene.json | 7 +-- 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index b0d9377d..34aed969 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -514,9 +514,6 @@ def index_based_functional_groups_detector( # Log detected functionality for debugging/user feedback. # print(f"{monomer.smiles} has functionality: {functional_group['group_name']}") - if functional_group.get("comments"): - print(f"Note: {monomer.smiles} - {functional_group['comments']}") - detected_functionalities.append( FunctionalGroupInfo( functionality_type=ftype, @@ -532,7 +529,6 @@ def index_based_functional_groups_detector( # Add to roles if any functionalities detected. if detected_functionalities: - print(f"Detected functionalities for monomer {detected_functionalities}") monomer_roles_out.append( MonomerRole( smiles=monomer.smiles, diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index d6e2365b..9d9a8f77 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -2,6 +2,8 @@ import logging from dataclasses import dataclass from pathlib import Path +import time + from typing import Any, Literal, Optional from PIL.Image import Image @@ -948,27 +950,40 @@ def _validate_simulations( def _validate_loop(self, inputs: dict) -> tuple[bool, int | None]: """ - Validates the 'loop' parameter in the input dictionary. + Validate the ``loop`` input. + + Returns: + A tuple containing: + - Whether looping is enabled. + - The maximum iteration count, or ``None`` when no limit is specified. - Returns a tuple (loop, max_loop_count) where 'loop' is a boolean indicating - whether looping is enabled, and 'max_loop_count' is an integer specifying - the maximum number of loop iterations if 'loop' is an integer, or None otherwise. + Raises: + InputSchemaError: If ``loop`` is not a boolean, a positive integer, + or a supported loop keyword. """ - loop_variables = ["loop", "repeat", "iterations", "do_loop"] - loop = inputs.get("loop", True) - if not isinstance(loop, bool): - if isinstance(loop, int): - if loop <= 0: - raise InputSchemaError( - "'loop' must be a positive integer." - ) - return True, loop - if loop in loop_variables: - return True, None - raise InputSchemaError( - "'loop' must be a boolean value or a positive integer." + loop_keywords = {"loop", "repeat", "iterations", "do_loop"} + loop_value = inputs.get("loop", True) + + if isinstance(loop_value, bool): + return loop_value, None + + if isinstance(loop_value, int): + if loop_value <= 0: + raise InputSchemaError("'loop' must be a positive integer.") + + print( + f"Reaction will be looped and maximum iterations set to {loop_value}" ) - return loop, None + time.sleep(5) + return True, loop_value + + if isinstance(loop_value, str) and loop_value in loop_keywords: + return True, None + + raise InputSchemaError( + "'loop' must be a boolean value, a positive integer, " + "or a supported loop keyword." + ) if __name__ == "__main__": diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index d2283dd5..1dfd6f64 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -11,6 +11,9 @@ from AutoREACTER.reaction_preparation.deduplication_detector import ( DeduplicationDetector, ) +from AutoREACTER.reaction_preparation.reaction_processor.warning_asci import ( + print_warning +) if TYPE_CHECKING: from AutoREACTER.detectors.functional_groups_detector import MonomerRole @@ -73,6 +76,7 @@ def __init__(self, session: "Session"): self.fg_detector = FunctionalGroupsDetector() self.rxn_detector = ReactionDetector() self.deduplication_detector = DeduplicationDetector() + print_warning() def reaction_progression( self, @@ -147,14 +151,12 @@ def reaction_progression( monomer_roles_in_loop.extend(fg_detection_results) self.session.monomer_roles = monomer_roles_in_loop - print(monomer_roles_in_loop) reaction_instances = ( self.rxn_detector.index_based_reaction_detector( monomer_roles_in_loop ) ) - print(reaction_instances) if not reaction_instances: print( f"No new reactions detected in iteration {iteration}. " @@ -193,7 +195,6 @@ def reaction_progression( ) if should_break: - continue return self._store_reactions(all_prepared_reactions) return all_prepared_reactions @@ -246,22 +247,12 @@ def _prepare_products_for_idx_based_fg_detection( else: reaction.is_radical = False reaction.radical_atom_idxs = () - - matches = sanitized_mol.GetSubstructMatches(Chem.MolFromSmarts("[C;!R;D3](-[H])(-[!#1])-[!#1]")) - print(f"Substructure matches for radical carbon: {matches}") - print( - f"Sanitizing reaction product {reaction.reaction_id}... " - f"result {success}" - ) if not success: print( f"Skipping reaction product {reaction.reaction_id}: " "RDKit molecule sanitization failed." ) - else: - print( - f"Reaction product {reaction.reaction_id} sanitized successfully." - ) + prepared_monomer_roles.append( MonomerRoleforIndexBasedFGDetection( smiles=self._get_product_smiles(sanitized_mol), diff --git a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py index cdf3d8a0..667c5d1f 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py @@ -1,9 +1,13 @@ +import time + + def ascii_art(message: str) -> None: message = message.upper() print(f"WARNING: {message}") print( - """ _ _ _ _ +""" + _ _ _ _ | | | | (_) | | | | | | | | __ _ _ __ _ __ _ _ __ __ _| | | | | |/\| |/ _` | '__| '_ \| | '_ \ / _` | | | | @@ -21,4 +25,5 @@ def print_warning() -> None: "Caution: results can be chemically inaccurate." ) ascii_art(message) + time.sleep(5) diff --git a/examples/test_ethelene.json b/examples/test_ethelene.json index d7f10d79..14958a8e 100644 --- a/examples/test_ethelene.json +++ b/examples/test_ethelene.json @@ -1,18 +1,19 @@ { - "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "simulation_name": "Epoxy_ethene", + "loop": 9, "simulations": [ { "tag": "vinyl_test", "temperature": 300, "density": 1.0, "monomer_counts": { - "styrene": 200 + "ethene": 200 } } ], "monomers": [ { - "name": "styrene", + "name": "ethene", "smiles": "C=C" } ] From 80532a8d80260ebf8af50987958d27608001e523 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 17:49:06 -0400 Subject: [PATCH 054/176] Fix vinyl radical type and expand parser tests Updates `vinyl_chain_end_radical` in the functional group library to use `functionality_type: "vinyl"` instead of `"mono"`, aligning classification with its intended chemistry and downstream handling. Also replaces `tests/test_input_parser.py` with a comprehensive test suite covering format/schema checks, counts vs ratio mode detection, numeric and force-field validation, SMILES canonicalization and duplicate handling, monomer/simulation normalization, loop settings, end-to-end `validate_inputs` behavior, and molecule representation integration points. --- .../detectors/functional_groups_library.py | 2 +- tests/test_input_parser.py | 1152 +++++++++++++---- 2 files changed, 878 insertions(+), 276 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py index 72f6069a..92e00616 100644 --- a/AutoREACTER/detectors/functional_groups_library.py +++ b/AutoREACTER/detectors/functional_groups_library.py @@ -187,7 +187,7 @@ def __init__(self): }, "vinyl_chain_end_radical": { - "functionality_type": "mono", + "functionality_type": "vinyl", "smarts_1": "[C;!R;D3;v3]", "group_name": "vinyl_chain_end_radical", "comments": ( diff --git a/tests/test_input_parser.py b/tests/test_input_parser.py index f1df0780..db20f965 100644 --- a/tests/test_input_parser.py +++ b/tests/test_input_parser.py @@ -1,364 +1,927 @@ +""" +Comprehensive unit tests for :mod:`AutoREACTER.input_parser`. + +The suite exercises the current counts-mode and ratio-mode schemas, numeric +validation, force-field normalization, SMILES handling, monomer construction, +loop configuration, and the public ``validate_inputs`` workflow. + +Run from the repository root with either: + + python -m unittest tests.test_input_parser -v + +or: + + pytest -q tests/test_input_parser.py +""" + +from __future__ import annotations + +import copy import unittest -#this should import the main class from the code +from unittest.mock import patch + +from rdkit import Chem + from AutoREACTER.input_parser import ( - InputParser, - NumericFieldError, - InputSchemaError, CompatibilityError, DuplicateMonomerError, InputConflictError, - SmilesValidationError + InputParser, + InputSchemaError, + MonomerEntry, + NumericFieldError, + Simulation, + SimulationSetup, + SmilesValidationError, ) -class TestInputParser(unittest.TestCase) : - - def setUp(self): - """Runs automatically before every test to give us a fresh parser.""" - self.parser = InputParser() - #=============== - # Tests for: _validate_temperature - #=============== - - def test_validate_temperature_valid(self): - """Good Ending: A valid positive temp should return as a float.""" - result = self.parser._validate_temperature(300) - self.assertEqual(result, 300.0) - - def test_validate_temperature_negative(self): - """Bad Ending: A negative temp has to raise a NumericFieldError.""" - with self.assertRaises(NumericFieldError): - self.parser._validate_temperature(-150) - def test_validate_temperature_zero(self): - """Bad Ending: Absolute zero has to raise a NumericFieldError.""" - with self.assertRaises(NumericFieldError): - self.parser._validate_temperature(0) +class InputParserTestCase(unittest.TestCase): + """Shared fixtures and helpers for input-parser tests.""" - def test_validate_temperature_wrong_type(self): - """Bad Ending: If a string or boolean is given instead of a number it has to fail.""" - with self.assertRaises(NumericFieldError): - self.parser._validate_temperature("room_temperature") - - #=============== - # Tests for: _validate_density - #=============== - def test_validate_density_valid(self): - """Good Ending: Valid positive density returns as float.""" - result = self.parser._validate_density(0.85) - self.assertEqual(result, 0.85) - - def test_validate_density_negative_or_zero(self): - """Bad Ending: Rejects zero or negative density values.""" - with self.assertRaises(NumericFieldError): - self.parser._validate_density(0) - with self.assertRaises(NumericFieldError): - self.parser._validate_density(-0.5) - - #================ - # Tests for: _validate_force_field - #================ - - def test_validate_force_field_default(self): - """Good Ending: If None then defaults to 'PCFF'.""" - result = self.parser._validate_force_field(None) - self.assertEqual(result, "PCFF") - - def test_validate_force_field_canonical(self): - """Good path: Normalizes force-field capitalization and aliases.""" - result = self.parser._validate_force_field("pcff-iff") - self.assertEqual(result, "PCFF-IFF") - - def test_validate_force_field_unsupported (self): - """Bad Ending: Passing a completely random name should raise an InputSchemaError.""" - with self.assertRaises(InputSchemaError): - self.parser._validate_force_field("NotAForceField") - - def test_validate_force_field_incompatible(self): - """Bad Ending: 'OPLSAA' is recognized but incompatible, so it should raise a CompatibilityError.""" - with self.assertRaises(CompatibilityError): - self.parser._validate_force_field("oplsaa") - - # ========================================== - # Tests for: validate_no_duplicate_smiles - # ========================================== - - def test_validate_no_duplicate_smiles_good_path(self): - """Good Ending: Adding a unique SMILES appends it to the tracker list.""" - tracker_list = ["CCO", "C1=CC(=CC(=C1)N)N"] - new_smiles = "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" - - result = self.parser.validate_no_duplicate_smiles(new_smiles, tracker_list) - - # Verify the list grew to 3 items and includes this new molecule - self.assertEqual(len(result), 3) - self.assertIn(new_smiles, result) - - def test_validate_no_duplicate_smiles_raises_error(self): - """Bad Ending: Adding an existing SMILES triggers DuplicateMonomerError.""" - tracker_list = ["CCO", "C1=CC(=CC(=C1)N)N"] - duplicate_smiles = "CCO" # Already present! - - with self.assertRaises(DuplicateMonomerError): - self.parser.validate_no_duplicate_smiles(duplicate_smiles, tracker_list) + def setUp(self) -> None: + """Create a fresh parser before every test.""" + self.parser = InputParser() - # ========================================== - # Tests for: _validate_smiles - # ========================================== + @staticmethod + def counts_input() -> dict: + """Return a fresh, valid counts-mode input dictionary.""" + return { + "simulation_name": "counts_example", + "force_field": "pcff", + "loop": False, + "simulations": [ + { + "tag": "small", + "temperature": 300, + "density": 0.80, + "monomer_counts": { + "ethanol": 2, + "water": 1, + }, + }, + { + "tag": "large", + "temperature": 350.0, + "density": 0.95, + "monomer_counts": { + "ethanol": 20, + "water": 10, + }, + }, + ], + "monomers": [ + { + "name": "ethanol", + "smiles": "CCO", + }, + { + "name": "water", + "smiles": "O", + }, + ], + } - def test_validate_smiles_valid(self): - """Good Ending: A valid SMILES should return canonical SMILES and an RDKit Mol.""" - smiles, mol = self.parser._validate_smiles("CCO") + @staticmethod + def ratio_input() -> dict: + """Return a fresh, valid ratio-mode input dictionary.""" + return { + "simulation_name": "ratio_example", + "force_field": "PCFF-IFF", + "simulations": [ + { + "tag": "small", + "temperature": 300, + "density": 0.80, + "total_atoms": 1000, + "monomer_ratios": { + "ethanol": 2.0, + "water": 1.0, + }, + }, + { + "tag": "large", + "temperature": 350, + "density": 0.95, + "total_atoms": 10000, + "monomer_ratios": { + "ethanol": 2.0, + "water": 1.0, + }, + }, + ], + "monomers": [ + { + "name": "ethanol", + "smiles": "CCO", + }, + { + "name": "water", + "smiles": "O", + }, + ], + } - self.assertEqual(smiles, "CCO") - self.assertIsNotNone(mol) - def test_validate_smiles_empty_raises_error(self): - """Bad Ending: Empty SMILES should raise SmilesValidationError.""" - with self.assertRaises(SmilesValidationError): - self.parser._validate_smiles("") +class TestBasicFormat(InputParserTestCase): + """Tests for top-level input structure validation.""" - def test_validate_smiles_invalid_raises_error(self): - """Bad Ending: Invalid SMILES should raise SmilesValidationError.""" - with self.assertRaises(SmilesValidationError): - self.parser._validate_smiles("not_a_smiles") - - # ========================================== - # Tests for: validate_basic_format - # ========================================== - - def test_validate_basic_format_valid(self): - """Good Ending: A minimal valid top-level input should pass basic format validation.""" + def test_validate_basic_format_accepts_required_keys(self) -> None: inputs = { - "simulation_name": "test_sim", + "simulation_name": "demo", "simulations": [], "monomers": [], } self.assertIsNone(self.parser.validate_basic_format(inputs)) - def test_validate_basic_format_missing_key(self): - """Bad Ending: Missing required top-level keys should raise InputSchemaError.""" - inputs = { - "simulation_name": "test_sim", + def test_validate_basic_format_rejects_non_dictionary(self) -> None: + for value in (None, [], "input", 12): + with self.subTest(value=value): + with self.assertRaises(InputSchemaError): + self.parser.validate_basic_format(value) + + def test_validate_basic_format_rejects_each_missing_key(self) -> None: + valid = { + "simulation_name": "demo", "simulations": [], + "monomers": [], } - with self.assertRaises(InputSchemaError): - self.parser.validate_basic_format(inputs) + for missing_key in tuple(valid): + with self.subTest(missing_key=missing_key): + inputs = valid.copy() + inputs.pop(missing_key) - def test_validate_basic_format_wrong_type(self): - """Bad Ending: Non-dictionary input should raise InputSchemaError.""" - with self.assertRaises(InputSchemaError): - self.parser.validate_basic_format(["not", "a", "dict"]) + with self.assertRaises(InputSchemaError): + self.parser.validate_basic_format(inputs) - # ========================================== - # Tests for: _get_inputs_mode - # ========================================== - def test_get_inputs_mode_counts(self): - """Good Ending: Simulations using monomer_counts should be detected as counts mode.""" +class TestCompositionModeDetection(InputParserTestCase): + """Tests for counts/ratio mode inference.""" + + def test_get_inputs_mode_detects_counts(self) -> None: simulations = [ { - "tag": "10k", - "temperature": 300, - "density": 0.8, - "monomer_counts": {"tmc": 1}, + "tag": "a", + "monomer_counts": {"ethanol": 1}, } ] - result = self.parser._get_inputs_mode(simulations) - - self.assertEqual(result, "counts") + self.assertEqual(self.parser._get_inputs_mode(simulations), "counts") - def test_get_inputs_mode_ratio(self): - """Good Ending: Simulations using monomer_ratios should be detected as ratio mode.""" + def test_get_inputs_mode_detects_ratio(self) -> None: simulations = [ { - "tag": "10k", - "temperature": 300, - "density": 0.8, - "total_atoms": 10000, - "monomer_ratios": {"tmc": 1.0}, + "tag": "a", + "monomer_ratios": {"ethanol": 1.0}, } ] - result = self.parser._get_inputs_mode(simulations) + self.assertEqual(self.parser._get_inputs_mode(simulations), "ratio") - self.assertEqual(result, "ratio") + def test_get_inputs_mode_rejects_empty_or_non_list_value(self) -> None: + for value in (None, {}, (), [], "simulations"): + with self.subTest(value=value): + with self.assertRaises(InputSchemaError): + self.parser._get_inputs_mode(value) - def test_get_inputs_mode_mixed_modes_raises_error(self): - """Bad Ending: Mixing counts and ratio modes should raise InputConflictError.""" - simulations = [ - { - "tag": "counts_system", - "temperature": 300, - "density": 0.8, - "monomer_counts": {"tmc": 1}, - }, - { - "tag": "ratio_system", - "temperature": 300, - "density": 0.8, - "total_atoms": 10000, - "monomer_ratios": {"tmc": 1.0}, - }, - ] + def test_get_inputs_mode_rejects_non_dictionary_simulation(self) -> None: + with self.assertRaises(InputSchemaError): + self.parser._get_inputs_mode(["not-a-dictionary"]) + def test_get_inputs_mode_rejects_missing_composition_field(self) -> None: + with self.assertRaises(InputSchemaError): + self.parser._get_inputs_mode( + [ + { + "tag": "a", + "temperature": 300, + "density": 0.8, + } + ] + ) + + def test_get_inputs_mode_rejects_both_fields_in_one_simulation(self) -> None: with self.assertRaises(InputConflictError): - self.parser._get_inputs_mode(simulations) + self.parser._get_inputs_mode( + [ + { + "tag": "a", + "monomer_counts": {"ethanol": 1}, + "monomer_ratios": {"ethanol": 1.0}, + } + ] + ) + + def test_get_inputs_mode_rejects_mixed_modes(self) -> None: + with self.assertRaises(InputConflictError): + self.parser._get_inputs_mode( + [ + { + "tag": "counts", + "monomer_counts": {"ethanol": 1}, + }, + { + "tag": "ratio", + "monomer_ratios": {"ethanol": 1.0}, + }, + ] + ) + + +class TestNumericValidation(InputParserTestCase): + """Tests for temperature and density helpers.""" + + def test_validate_temperature_returns_float(self) -> None: + self.assertEqual(self.parser._validate_temperature(300), 300.0) + self.assertEqual(self.parser._validate_temperature(300.5), 300.5) + + def test_validate_temperature_rejects_non_numeric_and_boolean(self) -> None: + for value in (None, "300", True, False, [], {}): + with self.subTest(value=value): + with self.assertRaises(NumericFieldError): + self.parser._validate_temperature(value) + + def test_validate_temperature_rejects_zero_and_negative_values(self) -> None: + for value in (0, -1, -273.15): + with self.subTest(value=value): + with self.assertRaises(NumericFieldError): + self.parser._validate_temperature(value) + + def test_validate_density_returns_float(self) -> None: + self.assertEqual(self.parser._validate_density(1), 1.0) + self.assertEqual(self.parser._validate_density(0.85), 0.85) + + def test_validate_density_rejects_non_numeric_and_boolean(self) -> None: + for value in (None, "0.85", True, False, [], {}): + with self.subTest(value=value): + with self.assertRaises(NumericFieldError): + self.parser._validate_density(value) + + def test_validate_density_rejects_zero_and_negative_values(self) -> None: + for value in (0, -0.1, -1): + with self.subTest(value=value): + with self.assertRaises(NumericFieldError): + self.parser._validate_density(value) + + +class TestForceFieldValidation(InputParserTestCase): + """Tests for force-field defaults, aliases, and compatibility.""" + + def test_validate_force_field_defaults_to_pcff(self) -> None: + self.assertEqual(self.parser._validate_force_field(None), "PCFF") + + def test_validate_force_field_normalizes_supported_aliases(self) -> None: + aliases = { + "pcff": "PCFF", + " PCFF-IFF ": "PCFF-IFF", + "cvff": "CVFF", + "cvff-iff": "CVFF-IFF", + "clayff": "Clay-FF", + "clay-ff": "Clay-FF", + "dreiding": "DREIDING", + "drieding": "DREIDING", + } - def test_get_inputs_mode_both_counts_and_ratios_raises_error(self): - """Bad Ending: One simulation cannot contain both counts and ratios.""" - simulations = [ - { - "tag": "bad_system", - "temperature": 300, - "density": 0.8, - "monomer_counts": {"tmc": 1}, - "monomer_ratios": {"tmc": 1.0}, - } - ] + for raw_value, expected in aliases.items(): + with self.subTest(raw_value=raw_value): + self.assertEqual( + self.parser._validate_force_field(raw_value), + expected, + ) - with self.assertRaises(InputConflictError): - self.parser._get_inputs_mode(simulations) + def test_validate_force_field_rejects_empty_or_non_string_value(self) -> None: + for value in ("", " ", 12, True, [], {}): + with self.subTest(value=value): + with self.assertRaises(InputSchemaError): + self.parser._validate_force_field(value) - # ========================================== - # Tests for: validate_inputs - # ========================================== + def test_validate_force_field_rejects_unknown_name(self) -> None: + with self.assertRaises(InputSchemaError): + self.parser._validate_force_field("not-a-force-field") - def test_validate_inputs_counts_mode_valid(self): - """Good Ending: Full valid counts-mode input should produce a SimulationSetup object.""" - inputs = { - "simulation_name": "test_counts", - "simulations": [ - { - "tag": "10k", - "temperature": 300, - "density": 0.8, - "monomer_counts": { - "tmc": 1, - "mpd": 1, - }, - } - ], - "monomers": [ + def test_validate_force_field_rejects_currently_incompatible_fields(self) -> None: + for value in ("oplsaa", "opls", "opls-aa", "gaff"): + with self.subTest(value=value): + with self.assertRaises(CompatibilityError): + self.parser._validate_force_field(value) + + +class TestSmilesValidation(InputParserTestCase): + """Tests for SMILES parsing, canonicalization, and duplicates.""" + + def test_validate_smiles_returns_canonical_smiles_and_molecule(self) -> None: + smiles, mol = self.parser._validate_smiles(" C(C)O ") + + self.assertEqual(smiles, "CCO") + self.assertIsInstance(mol, Chem.Mol) + + def test_validate_smiles_rejects_empty_or_non_string_values(self) -> None: + for value in (None, "", " ", 10, True, [], {}): + with self.subTest(value=value): + with self.assertRaises(SmilesValidationError): + self.parser._validate_smiles(value) + + def test_validate_smiles_rejects_invalid_smiles(self) -> None: + with self.assertRaises(SmilesValidationError): + self.parser._validate_smiles("not_a_smiles") + + def test_validate_no_duplicate_smiles_appends_unique_value(self) -> None: + seen = ["O"] + + result = self.parser.validate_no_duplicate_smiles("CCO", seen) + + self.assertIs(result, seen) + self.assertEqual(result, ["O", "CCO"]) + + def test_validate_no_duplicate_smiles_rejects_duplicate_value(self) -> None: + with self.assertRaises(DuplicateMonomerError): + self.parser.validate_no_duplicate_smiles("CCO", ["CCO"]) + + +class TestMoleculeProperties(InputParserTestCase): + """Tests for RDKit-derived monomer properties.""" + + def test_derive_molecule_properties_includes_hydrogen_atoms(self) -> None: + mol = Chem.MolFromSmiles("CCO") + self.assertIsNotNone(mol) + + num_atoms, molecular_weight = self.parser._derive_molecule_properties( + mol + ) + + self.assertEqual(num_atoms, 9) + self.assertAlmostEqual(molecular_weight, 46.069, places=2) + + def test_int_to_dict_retains_legacy_shape(self) -> None: + self.assertEqual(self.parser._int_to_dict(7), {"_": 7}) + + +class TestLegacyCompositionValidation(InputParserTestCase): + """Tests for the legacy composition validation helper.""" + + def test_validate_composition_accepts_counts_targets(self) -> None: + composition = { + "targets": [ + {"tag": "a"}, + {"tag": "b"}, + ] + } + + self.assertIs( + self.parser._validate_composition(composition, "counts"), + composition, + ) + + def test_validate_composition_accepts_ratio_total_atoms(self) -> None: + composition = { + "targets": [ + {"tag": "a", "total_atoms": 1000}, + {"tag": "b", "total_atoms": 2000}, + ] + } + + self.assertIs( + self.parser._validate_composition(composition, "ratio"), + composition, + ) + + def test_validate_composition_rejects_missing_or_empty_targets(self) -> None: + for composition in ({}, {"targets": None}, {"targets": []}): + with self.subTest(composition=composition): + with self.assertRaises(InputSchemaError): + self.parser._validate_composition( + composition, + "counts", + ) + + def test_validate_composition_rejects_duplicate_tags(self) -> None: + with self.assertRaises(InputSchemaError): + self.parser._validate_composition( { - "name": "tmc", - "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O", + "targets": [ + {"tag": "same"}, + {"tag": "same"}, + ] }, + "counts", + ) + + def test_validate_composition_rejects_invalid_ratio_total_atoms(self) -> None: + for value in (None, 0, -1, 1.5, True): + with self.subTest(value=value): + with self.assertRaises(NumericFieldError): + self.parser._validate_composition( + { + "targets": [ + { + "tag": "a", + "total_atoms": value, + } + ] + }, + "ratio", + ) + + def test_validate_composition_rejects_total_atoms_in_counts_mode(self) -> None: + with self.assertRaises(InputSchemaError): + self.parser._validate_composition( { - "name": "mpd", - "smiles": "C1=CC(=CC(=C1)N)N", + "targets": [ + { + "tag": "a", + "total_atoms": 1000, + } + ] }, - ], - } + "counts", + ) + + +class TestSimulationValidation(InputParserTestCase): + """Tests for individual and grouped simulation validation.""" + + def test_validate_single_simulation_accepts_counts_mode(self) -> None: + simulation = Simulation( + tag="a", + temperature=300.0, + density=0.8, + monomer_counts={"ethanol": 0}, + ) + + self.assertIsNone( + self.parser._validate_single_simulation(simulation, "counts") + ) + + def test_validate_single_simulation_accepts_ratio_mode(self) -> None: + simulation = Simulation( + tag="a", + temperature=300.0, + density=0.8, + monomer_ratios={"ethanol": 0.0}, + total_atoms=1000, + ) + + self.assertIsNone( + self.parser._validate_single_simulation(simulation, "ratio") + ) + + def test_validate_single_simulation_rejects_invalid_common_fields(self) -> None: + cases = ( + Simulation( + tag="", + temperature=300.0, + density=0.8, + monomer_counts={"ethanol": 1}, + ), + Simulation( + tag="a", + temperature=0, + density=0.8, + monomer_counts={"ethanol": 1}, + ), + Simulation( + tag="a", + temperature=300.0, + density=0, + monomer_counts={"ethanol": 1}, + ), + ) + + expected_errors = ( + InputSchemaError, + NumericFieldError, + NumericFieldError, + ) + + for simulation, expected_error in zip(cases, expected_errors): + with self.subTest(simulation=simulation): + with self.assertRaises(expected_error): + self.parser._validate_single_simulation( + simulation, + "counts", + ) + + def test_validate_single_simulation_rejects_invalid_count(self) -> None: + simulation = Simulation( + tag="a", + temperature=300.0, + density=0.8, + monomer_counts={"ethanol": -1}, + ) - result = self.parser.validate_inputs(inputs) + with self.assertRaises(NumericFieldError): + self.parser._validate_single_simulation(simulation, "counts") - self.assertEqual(result.simulation_name, "test_counts") - self.assertEqual(result.composition_method, "counts") - self.assertEqual(result.force_field, "PCFF") - self.assertEqual(len(result.monomers), 2) - self.assertEqual(len(result.simulations), 1) + def test_validate_single_simulation_rejects_invalid_ratio(self) -> None: + simulation = Simulation( + tag="a", + temperature=300.0, + density=0.8, + monomer_ratios={"ethanol": -0.1}, + total_atoms=1000, + ) + + with self.assertRaises(NumericFieldError): + self.parser._validate_single_simulation(simulation, "ratio") + + def test_validate_simulations_normalizes_counts_mode(self) -> None: + systems = copy.deepcopy(self.counts_input()["simulations"]) + + result = self.parser._validate_simulations(systems, "counts") + + self.assertEqual(result["method"], "counts") + self.assertEqual(result["temperatures"], [300.0, 350.0]) + self.assertEqual(result["density"], [0.8, 0.95]) + self.assertEqual(len(result["simulations"]), 2) + self.assertTrue( + all( + isinstance(simulation, Simulation) + for simulation in result["simulations"] + ) + ) + + def test_validate_simulations_normalizes_ratio_mode(self) -> None: + systems = copy.deepcopy(self.ratio_input()["simulations"]) + + result = self.parser._validate_simulations(systems, "ratio") + + self.assertEqual(result["method"], "ratio") + self.assertEqual(result["temperatures"], [300.0, 350.0]) + self.assertEqual(result["density"], [0.8, 0.95]) + self.assertEqual( + [simulation.total_atoms for simulation in result["simulations"]], + [1000, 10000], + ) + + def test_validate_simulations_rejects_duplicate_tags(self) -> None: + systems = copy.deepcopy(self.counts_input()["simulations"]) + systems[1]["tag"] = systems[0]["tag"] + + with self.assertRaises(InputSchemaError): + self.parser._validate_simulations(systems, "counts") + + def test_validate_simulations_rejects_total_atoms_in_counts_mode(self) -> None: + systems = copy.deepcopy(self.counts_input()["simulations"]) + systems[0]["total_atoms"] = 1000 + + with self.assertRaises(InputSchemaError): + self.parser._validate_simulations(systems, "counts") + + def test_validate_simulations_rejects_different_ratios_between_systems( + self, + ) -> None: + systems = copy.deepcopy(self.ratio_input()["simulations"]) + systems[1]["monomer_ratios"]["water"] = 2.0 + + with self.assertRaises(InputSchemaError): + self.parser._validate_simulations(systems, "ratio") + + +class TestSystemMonomerKeys(InputParserTestCase): + """Tests for agreement between monomer definitions and systems.""" - def test_validate_inputs_ratio_mode_valid(self): - """Good Ending: Full valid ratio-mode input should produce a SimulationSetup object.""" + def test_validate_system_monomer_keys_accepts_exact_names(self) -> None: + inputs = self.counts_input() + systems = inputs["simulations"] + + self.assertIsNone( + self.parser._validate_system_monomer_keys( + inputs, + systems, + "counts", + ) + ) + + def test_validate_system_monomer_keys_assigns_default_name(self) -> None: inputs = { - "simulation_name": "test_ratio", - "simulations": [ - { - "tag": "10k", - "temperature": 300, - "density": 0.8, - "total_atoms": 10000, - "monomer_ratios": { - "tmc": 1.0, - "mpd": 1.0, - }, - } - ], "monomers": [ { - "name": "tmc", - "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O", - }, - { - "name": "mpd", - "smiles": "C1=CC(=CC(=C1)N)N", + "smiles": "CCO", + } + ] + } + systems = [ + { + "tag": "a", + "monomer_counts": { + "data_1": 1, }, - ], + } + ] + + self.parser._validate_system_monomer_keys( + inputs, + systems, + "counts", + ) + + self.assertEqual(inputs["monomers"][0]["name"], "data_1") + + def test_validate_system_monomer_keys_rejects_unknown_name(self) -> None: + inputs = self.counts_input() + systems = copy.deepcopy(inputs["simulations"]) + systems[0]["monomer_counts"]["unknown"] = 1 + + with self.assertRaises(InputSchemaError): + self.parser._validate_system_monomer_keys( + inputs, + systems, + "counts", + ) + + def test_validate_system_monomer_keys_rejects_missing_name(self) -> None: + inputs = self.counts_input() + systems = copy.deepcopy(inputs["simulations"]) + systems[0]["monomer_counts"].pop("water") + + with self.assertRaises(InputSchemaError): + self.parser._validate_system_monomer_keys( + inputs, + systems, + "counts", + ) + + +class TestMonomerEntryValidation(InputParserTestCase): + """Tests for construction of MonomerEntry objects.""" + + def test_validate_monomer_entry_builds_counts_map(self) -> None: + inputs = self.counts_input() + systems = copy.deepcopy(inputs["simulations"]) + + monomers = self.parser._validate_monomer_entry( + inputs, + "counts", + systems, + ) + + self.assertEqual(len(monomers), 2) + self.assertTrue( + all(isinstance(monomer, MonomerEntry) for monomer in monomers) + ) + self.assertEqual( + monomers[0].count, + { + "small": 2, + "large": 20, + }, + ) + self.assertIsNone(monomers[0].ratio) + self.assertEqual(monomers[0].smiles, "CCO") + self.assertIsInstance(monomers[0].rdkit_mol, Chem.Mol) + self.assertGreater(monomers[0].num_atoms, 0) + self.assertGreater(monomers[0].molecular_weight, 0.0) + + def test_validate_monomer_entry_builds_ratio_value(self) -> None: + inputs = self.ratio_input() + systems = copy.deepcopy(inputs["simulations"]) + + monomers = self.parser._validate_monomer_entry( + inputs, + "ratio", + systems, + ) + + self.assertEqual(monomers[0].ratio, 2.0) + self.assertIsNone(monomers[0].count) + + def test_validate_monomer_entry_rejects_non_list_monomers(self) -> None: + inputs = self.counts_input() + inputs["monomers"] = {} + + with self.assertRaises(InputSchemaError): + self.parser._validate_monomer_entry( + inputs, + "counts", + inputs["simulations"], + ) + + def test_validate_monomer_entry_rejects_non_dictionary_entry(self) -> None: + inputs = self.counts_input() + inputs["monomers"] = ["CCO"] + + with self.assertRaises(InputSchemaError): + self.parser._validate_monomer_entry( + inputs, + "counts", + inputs["simulations"], + ) + + def test_validate_monomer_entry_rejects_negative_count(self) -> None: + inputs = self.counts_input() + inputs["simulations"][0]["monomer_counts"]["ethanol"] = -1 + + with self.assertRaises(NumericFieldError): + self.parser._validate_monomer_entry( + inputs, + "counts", + inputs["simulations"], + ) + + def test_validate_monomer_entry_rejects_negative_ratio(self) -> None: + inputs = self.ratio_input() + inputs["simulations"][0]["monomer_ratios"]["ethanol"] = -1.0 + + with self.assertRaises(NumericFieldError): + self.parser._validate_monomer_entry( + inputs, + "ratio", + inputs["simulations"], + ) + + +class TestLegacyNumericFields(InputParserTestCase): + """Tests for the retained legacy numeric validator.""" + + def test_validate_numeric_fields_accepts_valid_values(self) -> None: + inputs = { + "density": 0.8, + "temperature": [300, 350.0], + "number_of_monomers": { + "data_1": 1, + "data_2": 2, + }, + } + + self.assertIsNone(self.parser._validate_numeric_fields(inputs)) + + def test_validate_numeric_fields_rejects_invalid_density(self) -> None: + inputs = { + "density": 0, + "temperature": 300, + "number_of_monomers": {"data_1": 1}, + } + + with self.assertRaises(NumericFieldError): + self.parser._validate_numeric_fields(inputs) + + def test_validate_numeric_fields_rejects_invalid_temperature(self) -> None: + inputs = { + "density": 0.8, + "temperature": [300, False], + "number_of_monomers": {"data_1": 1}, + } + + with self.assertRaises(NumericFieldError): + self.parser._validate_numeric_fields(inputs) + + def test_validate_numeric_fields_rejects_invalid_monomer_count(self) -> None: + inputs = { + "density": 0.8, + "temperature": 300, + "number_of_monomers": {"data_1": 0}, } + with self.assertRaises(NumericFieldError): + self.parser._validate_numeric_fields(inputs) + + +class TestLoopValidation(InputParserTestCase): + """Tests for loop configuration.""" + + def test_validate_loop_defaults_to_enabled(self) -> None: + self.assertEqual(self.parser._validate_loop({}), (True, None)) + + def test_validate_loop_accepts_booleans(self) -> None: + self.assertEqual( + self.parser._validate_loop({"loop": True}), + (True, None), + ) + self.assertEqual( + self.parser._validate_loop({"loop": False}), + (False, None), + ) + + @patch("AutoREACTER.input_parser.time.sleep") + def test_validate_loop_accepts_positive_integer( + self, + sleep_mock, + ) -> None: + self.assertEqual( + self.parser._validate_loop({"loop": 4}), + (True, 4), + ) + sleep_mock.assert_called_once_with(5) + + def test_validate_loop_accepts_supported_keywords(self) -> None: + for keyword in ("loop", "repeat", "iterations", "do_loop"): + with self.subTest(keyword=keyword): + self.assertEqual( + self.parser._validate_loop({"loop": keyword}), + (True, None), + ) + + def test_validate_loop_rejects_invalid_values(self) -> None: + for value in (0, -1, 1.5, None, "yes", [], {}): + with self.subTest(value=value): + with self.assertRaises(InputSchemaError): + self.parser._validate_loop({"loop": value}) + + +class TestValidateInputsWorkflow(InputParserTestCase): + """End-to-end tests for the public validation entry point.""" + + def test_validate_inputs_builds_counts_setup(self) -> None: + inputs = self.counts_input() + result = self.parser.validate_inputs(inputs) - self.assertEqual(result.simulation_name, "test_ratio") - self.assertEqual(result.composition_method, "ratio") + self.assertIsInstance(result, SimulationSetup) + self.assertEqual(result.simulation_name, "counts_example") + self.assertEqual(result.composition_method, "counts") self.assertEqual(result.force_field, "PCFF") + self.assertFalse(result.loop) + self.assertIsNone(result.max_loop_count) + self.assertEqual(result.temperature, [300.0, 350.0]) + self.assertEqual(result.density, [0.8, 0.95]) self.assertEqual(len(result.monomers), 2) - self.assertEqual(len(result.simulations), 1) + self.assertEqual(len(result.simulations), 2) + self.assertEqual( + result.monomers[0].count, + { + "small": 2, + "large": 20, + }, + ) - def test_validate_inputs_unknown_monomer_in_system_raises_error(self): - """Bad Ending: System composition cannot reference undefined monomers.""" + def test_validate_inputs_builds_ratio_setup(self) -> None: + inputs = self.ratio_input() + + result = self.parser.validate_inputs(inputs) + + self.assertIsInstance(result, SimulationSetup) + self.assertEqual(result.simulation_name, "ratio_example") + self.assertEqual(result.composition_method, "ratio") + self.assertEqual(result.force_field, "PCFF-IFF") + self.assertTrue(result.loop) + self.assertEqual( + [simulation.total_atoms for simulation in result.simulations], + [1000, 10000], + ) + self.assertEqual(result.monomers[0].ratio, 2.0) + self.assertIsNone(result.monomers[0].count) + + @patch("AutoREACTER.input_parser.time.sleep") + def test_validate_inputs_stores_integer_loop_limit( + self, + sleep_mock, + ) -> None: + inputs = self.counts_input() + inputs["loop"] = 3 + + result = self.parser.validate_inputs(inputs) + + self.assertTrue(result.loop) + self.assertEqual(result.max_loop_count, 3) + sleep_mock.assert_called_once_with(5) + + def test_validate_inputs_assigns_default_monomer_name(self) -> None: inputs = { - "simulation_name": "bad_unknown_monomer", + "simulation_name": "default_name", "simulations": [ { - "tag": "10k", + "tag": "a", "temperature": 300, "density": 0.8, "monomer_counts": { - "tmc": 1, - "unknown": 1, + "data_1": 1, }, } ], "monomers": [ { - "name": "tmc", - "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O", - }, + "smiles": "CCO", + } ], } + result = self.parser.validate_inputs(inputs) + + self.assertEqual(result.monomers[0].name, "data_1") + self.assertEqual(result.monomers[0].data_id, "data_1") + + def test_validate_inputs_rejects_unknown_system_monomer(self) -> None: + inputs = self.counts_input() + inputs["simulations"][0]["monomer_counts"]["unknown"] = 1 + with self.assertRaises(InputSchemaError): self.parser.validate_inputs(inputs) - def test_validate_inputs_missing_monomer_in_system_raises_error(self): - """Bad Ending: Every defined monomer must appear in each system composition.""" - inputs = { - "simulation_name": "bad_missing_monomer", - "simulations": [ - { - "tag": "10k", - "temperature": 300, - "density": 0.8, - "monomer_counts": { - "tmc": 1, - }, - } - ], - "monomers": [ - { - "name": "tmc", - "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O", - }, - { - "name": "mpd", - "smiles": "C1=CC(=CC(=C1)N)N", - }, - ], - } + def test_validate_inputs_rejects_missing_system_monomer(self) -> None: + inputs = self.counts_input() + inputs["simulations"][0]["monomer_counts"].pop("water") with self.assertRaises(InputSchemaError): self.parser.validate_inputs(inputs) - def test_validate_inputs_duplicate_monomer_smiles_raises_error(self): - """Bad Ending: Duplicate monomer SMILES should raise DuplicateMonomerError.""" + def test_validate_inputs_rejects_canonically_duplicate_smiles(self) -> None: inputs = { - "simulation_name": "bad_duplicate_smiles", + "simulation_name": "duplicates", "simulations": [ { - "tag": "10k", + "tag": "a", "temperature": 300, "density": 0.8, "monomer_counts": { @@ -374,7 +937,7 @@ def test_validate_inputs_duplicate_monomer_smiles_raises_error(self): }, { "name": "ethanol_b", - "smiles": "CCO", + "smiles": "C(C)O", }, ], } @@ -383,5 +946,44 @@ def test_validate_inputs_duplicate_monomer_smiles_raises_error(self): self.parser.validate_inputs(inputs) +class TestMoleculeRepresentation(InputParserTestCase): + """Tests for initial-molecule extraction and image-grid integration.""" + + def test_molecule_representation_returns_molecules_and_legends(self) -> None: + setup = self.parser.validate_inputs(self.counts_input()) + + molecules, legends = ( + self.parser.molecule_representation_of_initial_molecules(setup) + ) + + self.assertEqual(len(molecules), 2) + self.assertTrue(all(isinstance(mol, Chem.Mol) for mol in molecules)) + self.assertEqual(legends, ["ethanol", "water"]) + + @patch("AutoREACTER.input_parser.Draw.MolsToGridImage") + def test_initial_molecules_image_grid_delegates_to_rdkit( + self, + grid_mock, + ) -> None: + setup = self.parser.validate_inputs(self.counts_input()) + + class DummySession: + inputs = setup + + expected_image = object() + grid_mock.return_value = expected_image + + result = self.parser.initial_molecules_image_grid(DummySession()) + + self.assertIs(result, expected_image) + grid_mock.assert_called_once() + + args, kwargs = grid_mock.call_args + self.assertEqual(len(args[0]), 2) + self.assertEqual(kwargs["molsPerRow"], 3) + self.assertEqual(kwargs["subImgSize"], (400, 400)) + self.assertEqual(kwargs["legends"], ["ethanol", "water"]) + + if __name__ == "__main__": - unittest.main() + unittest.main(verbosity=2) \ No newline at end of file From 6960e2726dfbabcd5dd846c52cb2b12d9bebed18 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 18:09:03 -0400 Subject: [PATCH 055/176] Remove legacy compatibility shim Deletes the obsolete `_compat.py` patch helper and removes unused reaction SMARTS constants from `reactions_library.py`. --- AutoREACTER/_compat.py | 60 ---------------------- AutoREACTER/detectors/reactions_library.py | 9 ---- 2 files changed, 69 deletions(-) delete mode 100644 AutoREACTER/_compat.py diff --git a/AutoREACTER/_compat.py b/AutoREACTER/_compat.py deleted file mode 100644 index 28bf209d..00000000 --- a/AutoREACTER/_compat.py +++ /dev/null @@ -1,60 +0,0 @@ -import sys -import collections -import collections.abc -import numpy as np - -def apply_legacy_patches(): - """ - Injects removed aliases back into numpy and collections at runtime, - and bridges the OpenMM simtk namespace for older versions of Foyer/mBuild. - """ - # 1. Restore removed Collections aliases - _missing_classes = [ - "MutableSet", "MutableMapping", "Mapping", "MutableSequence", - "Sequence", "Set", "Iterable", "Iterator", "Callable", - "Container", "Hashable", "ItemsView", "KeysView", "ValuesView" - ] - for _name in _missing_classes: - if not hasattr(collections, _name) and hasattr(collections.abc, _name): - setattr(collections, _name, getattr(collections.abc, _name)) - - # 2. Restore removed NumPy aliases - if not hasattr(np, "float"): np.float = float - if not hasattr(np, "int"): np.int = int - if not hasattr(np, "complex"): np.complex = complex - if not hasattr(np, "bool"): np.bool = np.bool_ - if not hasattr(np, "object"): np.object = np.object_ - if not hasattr(np, "str"): np.str = np.str_ - - # 3. Robust OpenMM 'simtk' shim for Python 3.12+ - try: - import sys - import types - import openmm - import openmm.app - import openmm.app.element - import openmm.unit - - # Create pure, fake modules to bypass strict filesystem import checks - simtk = types.ModuleType("simtk") - simtk_openmm = types.ModuleType("simtk.openmm") - simtk_openmm_app = types.ModuleType("simtk.openmm.app") - - # Copy the contents of the real modules into our fake ones - simtk_openmm.__dict__.update(openmm.__dict__) - simtk_openmm_app.__dict__.update(openmm.app.__dict__) - - # Manually wire the internal tree together - simtk.openmm = simtk_openmm - simtk.unit = openmm.unit - simtk_openmm.app = simtk_openmm_app - simtk_openmm_app.element = openmm.app.element - - # Register them in sys.modules so the 'import' statements find them instantly - sys.modules["simtk"] = simtk - sys.modules["simtk.openmm"] = simtk_openmm - sys.modules["simtk.openmm.app"] = simtk_openmm_app - sys.modules["simtk.openmm.app.element"] = openmm.app.element - sys.modules["simtk.unit"] = openmm.unit - except ImportError: - pass \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py index 6d28592a..67a67396 100644 --- a/AutoREACTER/detectors/reactions_library.py +++ b/AutoREACTER/detectors/reactions_library.py @@ -34,15 +34,6 @@ - Polymerization in Supercritical Carbon Dioxide - Thiophene Polymerizations: Oxidative Polymerization of Thiophenes """ -rxn_prop_smarts = ( - "[C:1]-[*:5].[CH2:3]=[CH;!R:4]-[*:6]" - ">>[C:1]([*:5])-[CH2:3]-[CH:4]-[*:6]" -) - -rxn_init_smarts = ( - "[CH2:1]=[CH;!R:2].[CH2:3]=[C;!R:4]-[*:5]" - ">>[C:1]-[C:2]-[C:3]-[C:4]-[*:5]" -) class ReactionLibrary: def __init__(self): From 7f97a23dc757c78a5006bb0ca0f94b92513d011a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 15 Jul 2026 18:57:12 -0400 Subject: [PATCH 056/176] Refresh warning banner ASCII art Replace the warning output art in `warning_asci.py` with a new, wider banner style to make warning messages more visually prominent in terminal output. --- .../reaction_processor/warning_asci.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py index 667c5d1f..80c82cf0 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py @@ -7,14 +7,13 @@ def ascii_art(message: str) -> None: print(f"WARNING: {message}") print( """ - _ _ _ _ -| | | | (_) | | | | -| | | | __ _ _ __ _ __ _ _ __ __ _| | | | -| |/\| |/ _` | '__| '_ \| | '_ \ / _` | | | | -\ /\ / (_| | | | | | | | | | | (_| |_|_|_| - \/ \/ \__,_|_| |_| |_|_|_| |_|\__, (_|_|_) - __/ | - |___/ + ____ ____ _ _______ ____ _____ _____ ____ _____ ______ _ _ _ +|_ _| |_ _|/ \ |_ __ \ |_ \|_ _||_ _||_ \|_ _|.' ___ | | | | | | | + \ \ /\ / / / _ \ | |__) | | \ | | | | | \ | | / .' \_| | | | | | | + \ \/ \/ / / ___ \ | __ / | |\ \| | | | | |\ \| | | | ____ | | | | | | + \ /\ /_/ / \ \_ _| | \ \_ _| |_\ |_ _| |_ _| |_\ |_\ `.___] | |_| |_| |_| + \/ \/|____| |____||____| |___||_____|\____||_____||_____|\____|`._____.' (_) (_) (_) + """ ) From 91a5b7f1db248d146ce9c8c77e774f3993d4a147 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 20 Jul 2026 17:54:27 -0400 Subject: [PATCH 057/176] Refactor reaction progression and docs --- .../reaction_progression.py | 437 ++++++++++++------ 1 file changed, 302 insertions(+), 135 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 1dfd6f64..7724718a 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -1,8 +1,19 @@ +""" +Iterative reaction-progression engine for AutoREACTER. + +This module drives the discovery of follow-up reactions by repeatedly +re-detecting functional groups in products produced during earlier +reaction-generation rounds. Detected functional groups are turned into +new reaction instances, prepared into fully described reaction metadata, +deduplicated, and then fed back into the next loop iteration. A hard +iteration cap and a pool-growth guard prevent unbounded execution. +""" + from dataclasses import dataclass, field +import time from typing import TYPE_CHECKING from rdkit import Chem -from rdkit.Chem.rdchem import MolSanitizeException from AutoREACTER.detectors.functional_groups_detector import ( FunctionalGroupsDetector, @@ -12,7 +23,7 @@ DeduplicationDetector, ) from AutoREACTER.reaction_preparation.reaction_processor.warning_asci import ( - print_warning + print_warning, ) if TYPE_CHECKING: @@ -24,8 +35,8 @@ from AutoREACTER.session import Session -# Prevent the progression process from continuing indefinitely when reactions -# keep producing additional detectable functional groups. +# Prevent progression from continuing indefinitely when newly generated +# products keep exposing additional detectable functional groups. MAX_LOOP = 5 @@ -33,8 +44,20 @@ class MonomerRoleforIndexBasedFGDetection: """Describe a molecule prepared for index-based functional-group detection. - The stored atom indexes refer to positions in the reaction template and - allow functional groups to be associated with their original reactants. + These lightweight containers bridge the gap between prepared reaction + products and the index-based functional-group detector. The stored atom + indexes refer to positions in the parent reaction template, which makes + it possible to trace any newly detected functional group back to the + product (and ultimately the reactant) that produced it. + + Attributes: + smiles: Canonical SMILES of the prepared product. + name: Generated identifier for this potential monomer. + indexes_in_template: Atom indexes within the reaction template. + is_monomer: Whether this molecule should be treated as a monomer. + is_looped: Whether this molecule has already been processed by a + progression iteration. + rdkit_mol: Optional RDKit molecule object for downstream use. """ smiles: str @@ -47,7 +70,16 @@ class MonomerRoleforIndexBasedFGDetection: @dataclass(slots=True) class ReactionProgressionSession: - """Track state that is shared across reaction-progression iterations.""" + """Track state shared across reaction-progression iterations. + + This object is attached to the main ``Session`` so that other stages of + the pipeline can inspect or update progression-related bookkeeping. + + Attributes: + monomer_roles: Roles that have been produced by progression and + are eligible for subsequent functional-group detection. + iteration: Current progression loop iteration (1-indexed). + """ monomer_roles: list["MonomerRole"] = field(default_factory=list) iteration: int = 0 @@ -56,19 +88,36 @@ class ReactionProgressionSession: class ReactionProgression: """Coordinate iterative functional-group detection and reaction generation. - Each iteration uses products from previously prepared reactions as potential - monomers. Newly detected functional groups are converted into reaction - instances, prepared into reaction metadata, and deduplicated before the - next iteration begins. + The progression workflow repeatedly broadens the set of considered + monomers by using products from the previous round. In each iteration: + + 1. Active products are sanitized and converted into monomer-like roles. + 2. Functional groups are re-detected in those products by index. + 3. Compatible reactions are detected from the expanded monomer pool. + 4. Reaction instances are prepared into full ``ReactionMetadata``. + 5. Radical centers are annotated before deduplication. + 6. Duplicate reaction products are merged. + 7. The loop continues if the active reaction pool has grown. + + The class also owns the cleanup and sanitization of RDKit product + molecules, including special handling for radical carbons that are + deliberately under-valent in the underlying reaction SMARTS. """ - def __init__(self, session: "Session"): + def __init__(self, session: "Session", preparer=None): """Initialize detectors and attach progression state to a session. Args: - session: Session containing monomer roles and reaction metadata. + session: The active AutoREACTER ``Session`` that contains the + current monomer roles and reaction metadata. + preparer: An existing ``PrepareReactions`` instance used to + convert ``ReactionInstance`` objects into ``ReactionMetadata``. """ self.session = session + self.preparer = preparer + + # Attach a dedicated progression sub-session to the main session so + # that loop state is visible elsewhere in the pipeline. self.session.reaction_progression_session = ( ReactionProgressionSession() ) @@ -76,42 +125,51 @@ def __init__(self, session: "Session"): self.fg_detector = FunctionalGroupsDetector() self.rxn_detector = ReactionDetector() self.deduplication_detector = DeduplicationDetector() + + # Display the runtime warning banner (e.g. about experimental + # progression behavior or licensing). print_warning() def reaction_progression( self, max_loop: int = MAX_LOOP, ) -> list["ReactionMetadata"]: - """Run the reaction-progression loop until no progress is possible. + """Run progression until no further useful reactions are generated. Each iteration detects functional groups in generated products, finds - compatible reactions, prepares the reactions, and removes duplicates. - The loop stops when no new functional groups or reactions are found, - when the reaction pool does not grow, or when ``max_loop`` is reached. + compatible reactions, prepares them, and removes duplicates. The loop + stops when no new functional groups or reactions are found, when the + active reaction pool does not grow, or when ``max_loop`` is reached. Args: - max_loop: Maximum number of progression iterations to execute. + max_loop: Maximum number of progression iterations. Returns: - The prepared and deduplicated reaction metadata. + Prepared and deduplicated reaction metadata accumulated across + all iterations. """ + # Respect a user-supplied global loop limit if one was configured. if self.session.inputs.max_loop_count is not None: max_loop = self.session.inputs.max_loop_count + print( + f"Overriding default max_loop of {MAX_LOOP} with " + f"user-specified max_loop_count of {max_loop}." + ) + time.sleep(1) + iteration = 0 - monomer_roles_in_loop = list["MonomerRole"]( - self.session.monomer_roles - ) - all_prepared_reactions: list["ReactionMetadata"] = list( - self.session.reaction_metadata - ) + # Start from the monomer roles already present in the session. + monomer_roles_in_loop = list(self.session.monomer_roles) + # Accumulate reaction metadata across iterations for deduplication. + all_prepared_reactions = list(self.session.reaction_metadata) while iteration < max_loop: iteration += 1 self.session.reaction_progression_session.iteration = iteration if iteration == 1: - # Convert the initial monomer SMILES strings into RDKit - # molecules before the first functional-group search. + # On the first pass, convert input monomer SMILES into + # explicit RDKit molecules so detectors can work on them. self._populate_monomer_roles() else: print( @@ -119,29 +177,32 @@ def reaction_progression( "of the reaction progression loop." ) - # Roles seen in earlier iterations are marked so detectors can - # distinguish already-processed molecules from newly added ones. + # Mark roles from earlier iterations so detectors can distinguish + # already processed molecules from newly added molecules. self._set_is_looped_flag(monomer_roles_in_loop) + # Snapshot the pool size so we can decide whether this iteration + # produced any genuinely new chemistry. initial_reaction_pool_size = self._count_active_reactions( self.session.reaction_metadata ) - print( f"Initial reaction pool size at iteration {iteration}: " f"{initial_reaction_pool_size}" ) + # Convert active products into the form required by the + # index-based functional-group detector. roles_for_fg_detection = ( self._prepare_products_for_idx_based_fg_detection() ) - fg_detection_results = ( self.fg_detector.index_based_functional_groups_detector( roles_for_fg_detection ) ) + # No new functional groups means no new chemistry is possible. if not fg_detection_results: print( f"No new functional groups detected in iteration " @@ -149,14 +210,18 @@ def reaction_progression( ) break + # Expand the monomer pool with functional groups found in this + # iteration's products. monomer_roles_in_loop.extend(fg_detection_results) self.session.monomer_roles = monomer_roles_in_loop + # Search for reactions that involve the expanded monomer set. reaction_instances = ( self.rxn_detector.index_based_reaction_detector( monomer_roles_in_loop ) ) + if not reaction_instances: print( f"No new reactions detected in iteration {iteration}. " @@ -164,11 +229,17 @@ def reaction_progression( ) break + if not isinstance(reaction_instances, list): + reaction_instances = list(reaction_instances) + + # Convert raw reaction instances into fully prepared metadata. prepared_reactions = self._index_based_reaction_preparation( reaction_instances=reaction_instances ) - # Radical identity must exist before NetworkX deduplication. + # Radical identity must be available before NetworkX + # deduplication, because equivalent products may differ only in + # how radical centers are represented. self._annotate_radicals_before_deduplication( prepared_reactions ) @@ -176,8 +247,8 @@ def reaction_progression( all_prepared_reactions.extend(prepared_reactions) self.session.reaction_metadata = all_prepared_reactions - # Deduplication occurs after preparation because equivalent - # products may be generated through different reaction paths. + # Equivalent products can be generated through different reaction + # paths, so deduplication occurs after preparation. all_prepared_reactions = ( self.deduplication_detector.compare_graphs_mol( all_prepared_reactions @@ -189,12 +260,12 @@ def reaction_progression( all_prepared_reactions ) - should_break = self._loop_break_condition( + # If the pool did not grow, further iterations are unlikely to + # yield new chemistry. + if self._loop_break_condition( size_before=initial_reaction_pool_size, size_after=deduplicated_reaction_count, - ) - - if should_break: + ): return self._store_reactions(all_prepared_reactions) return all_prepared_reactions @@ -203,42 +274,55 @@ def _index_based_reaction_preparation( self, reaction_instances: list["ReactionInstance"], ) -> list["ReactionMetadata"]: - """Convert detected reaction instances into prepared reaction metadata.""" - from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( - PrepareReactions, - ) + """Convert detected reaction instances into reaction metadata. - reaction_preparer = PrepareReactions(self.session) + This is a thin wrapper around the preparer's loop-aware preparation + stage, which builds full ``ReactionMetadata`` records (products, + mappings, activity statistics, etc.) from the raw instances. - return reaction_preparer._prepare_reactions_stage( - reaction_instances, loop=True + Args: + reaction_instances: Reaction instances produced by the detector. + + Returns: + Fully prepared reaction metadata. + """ + return self.preparer._prepare_reactions_stage( + reaction_instances, + loop=True, ) def _prepare_products_for_idx_based_fg_detection( self, ) -> list[MonomerRoleforIndexBasedFGDetection]: - """Prepare active reaction products for index-based FG detection. + """Prepare active products for index-based functional-group detection. + + Active reaction products are converted into cleaned SMILES strings + and sanitized RDKit molecules. Their template atom indexes are + retained so that functional groups detected in the product can be + traced back to the reaction that produced them. - Products are converted into cleaned SMILES strings and RDKit molecules. - Their template atom indexes are retained so newly detected functional - groups can be traced back to the reaction that produced them. + Returns: + A list of roles ready for index-based functional-group detection. """ prepared_monomer_roles: list[ MonomerRoleforIndexBasedFGDetection ] = [] for reaction in self.session.reaction_metadata: + # Skip reactions that were deactivated during preparation. if not reaction.activity_stats: continue product_mol = reaction.product_combined_RDmol - indexes_in_template, product_mol = self._get_product_idxs( reaction.template_reactant_to_product_mapping, product_mol, ) sanitized_mol, success = self._sanitize_molecule(product_mol) + + # Record radical metadata when sanitization succeeds; otherwise + # mark the product as non-radical. if success and sanitized_mol is not None: self._set_reaction_radical_metadata( reaction, @@ -247,12 +331,13 @@ def _prepare_products_for_idx_based_fg_detection( else: reaction.is_radical = False reaction.radical_atom_idxs = () + if not success: print( f"Skipping reaction product {reaction.reaction_id}: " "RDKit molecule sanitization failed." ) - + prepared_monomer_roles.append( MonomerRoleforIndexBasedFGDetection( smiles=self._get_product_smiles(sanitized_mol), @@ -268,7 +353,14 @@ def _store_reactions( self, reactions: list["ReactionMetadata"], ) -> list["ReactionMetadata"]: - """Save reaction metadata to the session and return it.""" + """Persist reaction metadata in the session and return it. + + Args: + reactions: Final deduplicated reaction metadata. + + Returns: + The same list, now stored on the session. + """ self.session.reaction_metadata = reactions return reactions @@ -276,53 +368,97 @@ def _sanitize_molecule( self, mol: Chem.Mol, ) -> tuple[Chem.Mol | None, bool]: + """Clean and sanitize a product while preserving radical centers. + + RDKit ``RunReactants`` output is often not directly sanitizable, + especially when the reaction SMARTS intentionally leaves a carbon + under-valent (radical). This method strips tracking properties, + recomputes ring information, and adjusts explicit hydrogens and + radical electrons until the molecule either sanitizes cleanly or + is returned in the best possible state. + + Args: + mol: Raw product molecule from reaction preparation. + + Returns: + A tuple of (sanitized molecule or best-effort molecule, + success flag indicating whether RDKit sanitization succeeded). + """ cleaned_mol = self._clean_product(mol) patched_mol = Chem.RWMol(cleaned_mol) + + # Rebuild valence and ring state without raising on the first error. patched_mol.UpdatePropertyCache(strict=False) Chem.FastFindRings(patched_mol) for atom in patched_mol.GetAtoms(): - if atom.GetAtomicNum() == 6: - atom.SetNoImplicit(True) - - heavy_val = int(sum(bond.GetValenceContrib(atom) for bond in atom.GetBonds())) - explicit_hs = atom.GetNumExplicitHs() - rads = atom.GetNumRadicalElectrons() - - # 1. STRIP radical electrons ONLY from the OLD chain end! - # If it just formed a new bond, its heavy + Hs equals 4. It is no longer a radical. - if heavy_val + explicit_hs >= 4 and rads > 0: - atom.SetNumRadicalElectrons(0) - rads = 0 - - # 2. Fix over-valent carbons (if RunReactants forces too many Hs) - if heavy_val + explicit_hs + rads > 4: - allowed_hs = max(0, 4 - heavy_val - rads) - atom.SetNumExplicitHs(allowed_hs) - explicit_hs = allowed_hs - - # 3. PROTECT the NEW chain end! - # If it has 3 bonds, it's the new radical. Give it the electron back - # so Chem.AddHs() doesn't accidentally quench it with a fake hydrogen! - if heavy_val + explicit_hs == 3 and atom.GetFormalCharge() == 0: - atom.SetNumRadicalElectrons(1) + # Focus on carbons, where radical centers are expected. + if atom.GetAtomicNum() != 6: + continue + + # Disable automatic implicit-H addition so we can manage valence + # explicitly for the radical center. + atom.SetNoImplicit(True) + + heavy_valence = int( + sum( + bond.GetValenceContrib(atom) + for bond in atom.GetBonds() + ) + ) + explicit_hs = atom.GetNumExplicitHs() + radical_electrons = atom.GetNumRadicalElectrons() + + # A carbon that has reached valence four is no longer radical. + if ( + heavy_valence + explicit_hs >= 4 + and radical_electrons > 0 + ): + atom.SetNumRadicalElectrons(0) + radical_electrons = 0 + + # Reduce explicit hydrogens when reaction output is over-valent. + if ( + heavy_valence + + explicit_hs + + radical_electrons + > 4 + ): + explicit_hs = max( + 0, + 4 - heavy_valence - radical_electrons, + ) + atom.SetNumExplicitHs(explicit_hs) + + # Preserve a neutral, trivalent carbon as the new radical center. + if ( + heavy_valence + explicit_hs == 3 + and atom.GetFormalCharge() == 0 + ): + atom.SetNumRadicalElectrons(1) patched_mol = patched_mol.GetMol() patched_mol.ClearComputedProps() + # First attempt: sanitize the valence-patched molecule. try: Chem.SanitizeMol(patched_mol) return patched_mol, True except Exception: pass - radical_fixed_mol = self._fix_radical_and_sanitize(patched_mol) + # Second attempt: explicitly mark under-valent carbons as radicals + # and try sanitization again. + radical_fixed_mol = self._fix_radical_and_sanitize( + patched_mol + ) try: Chem.SanitizeMol(radical_fixed_mol) return radical_fixed_mol, True - - except Exception as error2: + except Exception: + # If sanitization still fails, return the best-effort molecule + # with updated caches so downstream code can still inspect it. radical_fixed_mol.UpdatePropertyCache(strict=False) Chem.FastFindRings(radical_fixed_mol) return radical_fixed_mol, False @@ -332,49 +468,63 @@ def _fix_radical_and_sanitize( raw_mol: Chem.Mol, query: str = "[CH;X3;v3]", ) -> Chem.Mol: - """ - RunReactants() output is unsanitized. Our radical carbon is deliberately - under-valent (v3 instead of v4) to mark it in SMARTS, but that's not a - real chemical species RDKit can sanitize or round-trip through SMILES. - This finds that atom and gives it an actual radical electron, so the - missing valence is accounted for and the mol becomes fully sanitizable. + """Represent deliberately under-valent carbons as radicals. + + ``RunReactants`` output can be unsanitized. The radical carbon is + deliberately under-valent in the reaction SMARTS, so this method adds + the radical electron needed for RDKit sanitization and SMILES + round-tripping. Args: raw_mol: Molecule that may contain an under-valent radical carbon. - query: SMARTS identifying the deliberately under-valent radical atom. + query: SMARTS used to identify the radical carbon. Defaults to a + neutral carbon with one hydrogen, three explicit connections, + and total valence three. Returns: - A new Chem.Mol with the radical atom's valence properly accounted - for via NumRadicalElectrons, ready for Chem.SanitizeMol(). + Molecule with radical valence represented explicitly. """ mol = Chem.RWMol(raw_mol) - mol.UpdatePropertyCache(strict=False) # need valence to even run the query + mol.UpdatePropertyCache(strict=False) Chem.FastFindRings(mol) query_mol = Chem.MolFromSmarts(query) hits = mol.GetSubstructMatches(query_mol) for match in hits: - atom = mol.GetAtomWithIdx(match[0]) # first atom = the radical carbon + atom = mol.GetAtomWithIdx(match[0]) atom.SetNoImplicit(True) + + # Ensure the matched carbon has exactly one explicit hydrogen. if atom.GetTotalNumHs() != 1: atom.SetNumExplicitHs(1) + + # Add the single radical electron that completes the valence + # representation. atom.SetNumRadicalElectrons(1) return mol.GetMol() def _clean_product(self, mol: Chem.Mol) -> Chem.Mol: - """Return a copy of ``mol`` without atom maps, isotopes, or ghost properties.""" + """Return a copy of a molecule stripped of preparation artifacts. + + Atom maps, isotope labels, and internal RDKit tracking properties are + removed so that downstream SMILES are canonical and do not carry + state from the reaction engine. + + Args: + mol: Molecule to clean. + + Returns: + A new molecule with atom maps, isotopes, and tracking properties + cleared. + """ cleaned_mol = Chem.Mol(mol) for atom in cleaned_mol.GetAtoms(): - # Clean standard tracking labels atom.SetAtomMapNum(0) atom.SetIsotope(0) - # EXORCISE THE GHOSTS: - # RDKit hides tracking data like 'old_mapno' deep in the atom properties. - # We MUST clear them so AutoREACTER doesn't mistake old atoms for new initiators! if atom.HasProp("old_mapno"): atom.ClearProp("old_mapno") if atom.HasProp("react_atom_idx"): @@ -386,10 +536,10 @@ def _get_product_smiles(self, mol: Chem.Mol) -> str: """Convert a cleaned product molecule to canonical SMILES. Args: - mol: Product molecule to serialize. + mol: Product molecule (may be ``None`` if sanitization failed). Returns: - The product SMILES, or an empty string if conversion fails. + Canonical SMILES string, or an empty string if conversion fails. """ cleaned_mol = self._clean_product(mol) @@ -405,18 +555,17 @@ def _get_product_idxs( ) -> tuple[list[int], Chem.Mol]: """Return product indexes and the molecule containing those indexes. - If the product contains multiple disconnected fragments, only the - fragment with the greatest number of heavy atoms is retained. Indexes - are remapped to match the retained fragment. + When a product contains disconnected fragments, only the fragment with + the greatest number of heavy atoms is retained and the indexes are + remapped into that fragment. Args: - template_reactant_to_product_mapping: - Mapping from template reactant atom indexes to product indexes. - mol: Combined product molecule. + template_reactant_to_product_mapping: Mapping from reactant atom + indexes to product atom indexes in the original template. + mol: Product molecule, possibly multi-fragment. Returns: - A tuple containing remapped product indexes and the selected - product molecule. + A tuple of (list of remapped product indexes, retained fragment). """ product = Chem.Mol(mol) product_idxs = list( @@ -436,20 +585,20 @@ def _keep_largest_fragment( mol: Chem.Mol, product_idxs: list[int], ) -> tuple[Chem.Mol, list[int]]: - """Keep the largest disconnected fragment and remap atom indexes. + """Keep the largest heavy-atom fragment and remap its atom indexes. Args: - mol: Molecule containing one or more disconnected fragments. - product_idxs: Atom indexes referring to the original molecule. + mol: Multi-fragment product molecule. + product_idxs: Product-side atom indexes to retain. Returns: - The largest fragment and the indexes remapped to that fragment. + A tuple of (largest fragment molecule, product indexes remapped + into that fragment). Raises: - ValueError: If the molecule contains no fragments. + ValueError: If no fragments could be extracted from the molecule. """ fragment_atom_mappings: list[tuple[int, ...]] = [] - fragments = Chem.GetMolFrags( mol, asMols=True, @@ -462,24 +611,24 @@ def _keep_largest_fragment( "No fragments found in the product molecule." ) + # Select the fragment with the most heavy atoms. largest_fragment_position = max( range(len(fragments)), - key=lambda position: fragments[position].GetNumHeavyAtoms(), + key=lambda position: ( + fragments[position].GetNumHeavyAtoms() + ), ) - largest_fragment = fragments[largest_fragment_position] - - # RDKit provides each retained fragment's original atom indexes. - # Build the inverse mapping to translate indexes into fragment space. original_atom_idxs = fragment_atom_mappings[ largest_fragment_position ] + + # Build a map from original atom indexes to their positions in the + # largest fragment. original_to_new_idx = { original_idx: new_idx for new_idx, original_idx in enumerate(original_atom_idxs) } - - # Ignore mapped indexes that belong to discarded fragments. remapped_product_idxs = [ original_to_new_idx[product_idx] for product_idx in product_idxs @@ -492,12 +641,20 @@ def _set_is_looped_flag( self, monomer_roles: list["MonomerRole"], ) -> None: - """Mark supplied monomer roles as processed by the current loop.""" + """Mark supplied monomer roles as processed by the current loop. + + Args: + monomer_roles: Monomer roles to flag as looped. + """ for monomer_role in monomer_roles: monomer_role.is_looped = True def _populate_monomer_roles(self) -> None: - """Create RDKit molecules for all roles identified as monomers.""" + """Create RDKit molecules for roles identified as monomers. + + Input monomers are typically supplied as SMILES; this method ensures + that each one has an associated RDKit molecule before detection runs. + """ for monomer in self.session.monomer_roles: if monomer.is_monomer: monomer.rdkit_mol = self._smiles_to_rdkit_mol( @@ -511,10 +668,10 @@ def _smiles_to_rdkit_mol( """Parse a SMILES string into an RDKit molecule. Args: - smiles: SMILES representation of the molecule. + smiles: SMILES string to parse. Returns: - The parsed molecule, or ``None`` if RDKit cannot parse the string. + The parsed RDKit molecule, or ``None`` if parsing fails. """ return Chem.MolFromSmiles(smiles) @@ -525,15 +682,12 @@ def _loop_break_condition( ) -> bool: """Return whether the active reaction pool failed to grow. - A non-growing pool indicates that the latest iteration did not add - useful reaction products and further progression is unlikely to help. - Args: - size_before: Active reaction count before the iteration. - size_after: Active reaction count after deduplication. + size_before: Number of active reactions before deduplication. + size_after: Number of active reactions after deduplication. Returns: - ``True`` when the pool stayed the same size or became smaller. + ``True`` if the pool did not grow and the loop should stop. """ if size_after <= size_before: print( @@ -548,13 +702,13 @@ def _count_active_reactions( self, reactions: list["ReactionMetadata"], ) -> int: - """Count reactions that contain activity statistics. + """Count reactions included in activity statistics. Args: - reactions: Reaction metadata objects to inspect. + reactions: Reaction metadata to inspect. Returns: - The number of active reactions. + Number of reactions with truthy ``activity_stats``. """ return sum( bool(reaction.activity_stats) @@ -569,14 +723,19 @@ def _set_reaction_radical_metadata( """Store product radical atoms in reactant-index space. Deduplication relabels product atoms into reactant-index space, so - radical indexes are converted using product_to_reactant_mapping. + radical indexes are converted through + ``product_to_reactant_mapping``. + + Args: + reaction: Reaction metadata to annotate. + sanitized_product: Sanitized product molecule in which radical + electrons have already been assigned. """ product_radical_idxs = { atom.GetIdx() for atom in sanitized_product.GetAtoms() if atom.GetNumRadicalElectrons() > 0 } - radical_reactant_idxs = { reaction.product_to_reactant_mapping[product_idx] for product_idx in product_radical_idxs @@ -592,7 +751,15 @@ def _annotate_radicals_before_deduplication( self, reactions: list["ReactionMetadata"], ) -> None: - """Sanitize new products and record radical atoms before NetworkX comparison.""" + """Sanitize products and record radical atoms before deduplication. + + This must run before ``compare_graphs_mol`` because the deduplication + step relies on consistent radical annotation to distinguish otherwise + isomorphic products. + + Args: + reactions: Newly prepared reaction metadata to annotate. + """ for reaction in reactions: if not reaction.activity_stats: continue @@ -616,4 +783,4 @@ def _annotate_radicals_before_deduplication( self._set_reaction_radical_metadata( reaction, sanitized_mol, - ) \ No newline at end of file + ) From ef489e12885bb0b973512a393fd7a5b7f41d1e7f Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 20 Jul 2026 18:01:53 -0400 Subject: [PATCH 058/176] Refactor reaction preparation workflow --- .../reaction_processor/prepare_reactions.py | 1212 ++++++++++------- 1 file changed, 756 insertions(+), 456 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 6f2573c5..f4a754db 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -1,74 +1,108 @@ -""" -Module for preparing chemical reactions for analysis, including atom mapping between reactants and products, -reaction metadata extraction, and visualization utilities using RDKit. +"""Prepare chemical reactions and generate reaction metadata. -This module processes reaction SMARTS, applies atom mappings, identifies key reaction features (e.g., first shell, -initiators, byproducts), and generates metadata and visualizations for downstream analysis. It also includes validation checks to ensure mapping -consistency and completeness. +This module processes reaction SMARTS, applies atom mappings, identifies +reaction features such as first-shell atoms, initiators, and byproducts, and +generates metadata and visualizations for downstream analysis. """ # WARNING: -# When modifying this file for dataframe or any other indexing variables use idx and idxs, do not use index or indices or similar. Mapping validation error +# For dataframe and mapping variables, use idx and idxs rather than index or +# indices. Other naming can cause mapping-validation errors. from dataclasses import dataclass from functools import reduce from pathlib import Path from typing import Dict, List, Optional, TYPE_CHECKING -from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import logger +import pandas as pd +from PIL.Image import Image from rdkit import Chem from rdkit.Chem import AllChem, Draw, rdmolops -from PIL.Image import Image -import pandas as pd -from AutoREACTER.detectors.reaction_detector import FunctionalGroupInfo, ReactionInstance +from AutoREACTER.detectors.reaction_detector import ( + FunctionalGroupInfo, + ReactionInstance, +) +from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import ( + logger, +) +from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ( + ReactionProgression, +) from AutoREACTER.reaction_preparation.reaction_processor.utils import ( - add_dict_as_new_columns, add_column_safe, compare_set, prepare_paths + add_column_safe, + add_dict_as_new_columns, + compare_set, + prepare_paths, +) +from AutoREACTER.reaction_preparation.reaction_processor.walker import ( + reaction_atom_walker, ) -from AutoREACTER.reaction_preparation.reaction_processor.walker import reaction_atom_walker -# Use TYPE_CHECKING to prevent circular imports with session.py if TYPE_CHECKING: from AutoREACTER.session import Session -from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ReactionProgression class MappingError(Exception): - """Custom exception raised when atom mapping between reactants and products fails or is inconsistent.""" + """Raised when reactant-to-product atom mapping is invalid.""" class SMARTSParsingError(Exception): - """Custom exception raised when parsing SMILES or reaction SMARTS fails.""" + """Raised when a reactant SMILES string cannot be parsed.""" + class ZeroActiveReactionsError(Exception): - """Custom exception raised when no active reactions are found in the dataset.""" + """Raised when no active reactions remain in the dataset.""" + @dataclass(slots=True) class ReactionMetadata: + """Store molecular structures, mappings, and analysis for one reaction. + + This dataclass holds all information required to describe a single + prepared reaction, including the combined reactant and product RDKit + molecules, forward and reverse atom mappings, detected reaction-site + features, file paths, and activity status. + + Attributes: + reaction_id: Unique integer identifier assigned to this reaction. + reactant_combined_RDmol: Combined reactant RDKit molecule. + product_combined_RDmol: Combined product RDKit molecule. + reactant_to_product_mapping: Mapping from reactant atom index to + product atom index. + product_to_reactant_mapping: Mapping from product atom index to + reactant atom index. + template_reactant_to_product_mapping: Subset mapping covering the + reaction template atoms (reactant index -> product index). + edge_atoms: Atom indices that form the boundary of the reaction + template in the reactant molecule. + first_shell: Reactant atom indices identified as the first-shell + reaction environment (mapped atoms in the product with template + map numbers below 999). + initiators: The two reactant atom indices whose product counterparts + carry template map numbers 1 and 2. + byproduct_indices: Reactant indices of atoms that end up in the + smallest product fragment when atoms are deleted during reaction. + reaction_smarts: SMARTS string describing the reaction transformation. + reactant_smiles: Combined SMILES representation of the reactants. + product_smiles: Combined SMILES representation of the products. + csv_path: Path to the CSV file storing the atom mapping dataframe. + reaction_dataframe: DataFrame containing atom mappings and reaction + feature columns (first_shell, initiators, byproduct_idx, etc.). + delete_atom: Whether atoms are removed from the reactants during the + reaction (e.g., condensation byproducts). + delete_atom_idx: Primary reactant index of the atom to delete, if any. + reactant_combined_3Dmol_path: Path to the 3D reactant structure file, + if generated. + product_combined_3Dmol_path: Path to the 3D product structure file, + if generated. + is_radical: Whether the reaction involves radical species. + radical_atom_idxs: Tuple of reactant indices flagged as radical atoms. + activity_stats: True if this reaction is active and unique; set to + False for duplicate or failed reactions so they can be filtered + downstream. """ - Stores comprehensive metadata for a single reaction including molecular structures, - atom mappings, and analysis results. - reaction_id: Unique identifier for the reaction instance - reactant_combined_mol: RDKit molecule object representing combined reactants - product_combined_mol: RDKit molecule object representing combined products - reactant_to_product_mapping: Dictionary mapping reactant atom indices to product atom indices - product_to_reactant_mapping: Dictionary mapping product atom indices back to reactant atom indices - template_reactant_to_product_mapping: Optional dictionary mapping reactant indices in the template to product indices - edge_atoms: Optional list of reactant atom indices that are at the edge of the local environment - first_shell: Optional list of reactant atom indices in the first coordination shell (reaction center) - initiators: Optional list of reactant atom indices that are initiators (map numbers 1 or 2) - byproduct_indices: Optional list of reactant atom indices corresponding to detected byproducts - reaction_smarts: Optional string of the reaction SMARTS pattern - reactant_smarts: Optional string of the combined reactant SMILES - product_smarts: Optional string of the combined product SMILES - csv_path: Optional Path to the CSV file containing atom mappings and analysis - reaction_dataframe: Optional pandas DataFrame containing detailed mapping and analysis results - delete_atom: Boolean indicating whether the reaction involves a delete atom (byproduct) - delete_atom_idx: Optional integer index of the reactant atom that corresponds to the byproduct - reactant_combined_3Dmol_path: Optional Path to the 3D structure file for the combined reactants - product_combined_3Dmol_path: Optional Path to the 3D structure file for the combined products - activity_stats: Boolean indicating whether this reaction should be included in activity statistics (e.g., not a duplicate) - """ + reaction_id: int reactant_combined_RDmol: Chem.Mol product_combined_RDmol: Chem.Mol @@ -94,184 +128,237 @@ class ReactionMetadata: class PrepareReactions: - """Processes chemical reactions: builds atom mappings, identifies reaction centers, and detects byproducts.""" - - # --- INITIALIZATION AND PUBLIC WORKFLOW --- + """Build reaction products, atom mappings, metadata, and visualizations. + + This class orchestrates the conversion of detected reaction instances + (``ReactionInstance`` objects) into fully mapped ``ReactionMetadata`` + objects. It runs RDKit reaction transforms, validates atom mappings, + identifies first-shell atoms and initiators, detects byproducts, and + writes per-reaction CSV files to the staging cache. + + Attributes: + session: Shared AutoREACTER session providing inputs, directories, and + state such as the reaction ID counter. + inputs: Shortcut to ``session.inputs``. + staging_dir: Root staging directory for the run. + cache: Working cache directory (currently the same as ``staging_dir``). + csv_cache: Subdirectory where per-reaction mapping CSVs are saved. + """ def __init__(self, session: "Session"): - """Initialize using the shared AutoREACTER session object.""" + """Initialize the processor with the shared AutoREACTER session. + + Args: + session: The active AutoREACTER ``Session`` object. A reaction ID + counter is attached to the session if it does not already + exist. + """ self.session = session self.inputs = session.inputs - - # In AutoREACTER, staging_dir is the working/cache directory. self.staging_dir = Path(session.staging_dir) self.cache = self.staging_dir self.csv_cache = prepare_paths(self.cache, "csv_cache") + if not hasattr(session, "reaction_id_counter"): - session.reaction_id_counter = 0 # Initialize a counter for unique reaction IDs if not already present + session.reaction_id_counter = 0 def prepare_reactions(self, session): - # 1. Get initial reactions + """Prepare initial reactions and optionally run reaction progression. + + This is the main entry point. It first builds the initial set of + mapped reactions, then optionally enters the looping/progression + phase when ``session.inputs.loop`` is enabled. In both cases it + verifies that at least one active reaction remains. + + Args: + session: The active AutoREACTER ``Session`` object. + + Returns: + The same ``Session`` object, with ``reaction_metadata`` populated. + + Raises: + ZeroActiveReactionsError: If no active reactions remain after + preparation (and progression, if enabled). + """ prepared_reactions = self._prepare_reactions_stage(session) session.reaction_metadata = prepared_reactions if session.inputs.loop: - # 2. Run progression loop (this returns the FULL, deduplicated list) - reaction_progression = ReactionProgression(session) - - final_reactions = reaction_progression.reaction_progression() - - # 3. Overwrite the session metadata with the final deduplicated list - session.reaction_metadata = final_reactions - - # 4. Check weather is there avaible reaction present + progression = ReactionProgression(session, preparer=self) + final_reactions = progression.reaction_progression() + session.reaction_metadata = final_reactions self._zero_active_reactions_error(final_reactions) - else: self._zero_active_reactions_error(prepared_reactions) - + return session - - def _zero_active_reactions_error(self, reaction_metadata: list[ReactionMetadata]): - """ - Checks if there are any active reactions in the provided reaction metadata list. + def _zero_active_reactions_error( + self, + reaction_metadata: list[ReactionMetadata], + ) -> None: + """Raise an error when the metadata contains no active reactions. Args: - reaction_metadata: List of ReactionMetadata objects to check for active reactions. + reaction_metadata: List of ``ReactionMetadata`` objects to inspect. Raises: - ZeroActiveReactionsError: If no active reactions are found in the list. + ZeroActiveReactionsError: If none of the reactions have + ``activity_stats`` set to True. """ - active_reactions = False - for reaction in reaction_metadata: - if reaction.activity_stats: - active_reactions = True - break - if not active_reactions: - raise ZeroActiveReactionsError( - "No active reactions found in the dataset. " - "This is an AutoREACTER error indicating that no active reactions were found in the dataset. " - "Please raise an issue at https://github.com/NanoCIPHER-Lab/AutoREACTER/issues" - ) + if any(reaction.activity_stats for reaction in reaction_metadata): + return + + raise ZeroActiveReactionsError( + "No active reactions found in the dataset. " + "This is an AutoREACTER error indicating that no active " + "reactions were found in the dataset. Please raise an issue at " + "https://github.com/NanoCIPHER-Lab/AutoREACTER/issues" + ) - def _prepare_reactions_stage(self, session: "Session", loop: bool = False) -> list[ReactionMetadata]: - """ - Main pipeline: processes reaction instances, detects duplicates, and enriches metadata with template mappings. + def _prepare_reactions_stage( + self, + session: "Session", + loop: bool = False, + ) -> list[ReactionMetadata]: + """Process reaction instances and add template mapping metadata. + + Converts detected reactions into mapped metadata, removes duplicate + reactions, and then walks the local environment around each reaction + to determine template-level mappings and edge atoms. The enriched + dataframes are saved to CSV for downstream use. Args: - session: The main Session object containing reaction instances to process - loop: Boolean indicating whether this is a looped call (default: False) + session: The active ``Session`` or, in recursive calls, a list-like + object containing ``ReactionInstance`` objects. ``loop`` mode + changes how reactants are sourced from each instance. + loop: If True, reactants are taken directly from the RDKit + molecules attached to the reaction instance (used during the + progression/looping stage). Returns: - List of processed ReactionMetadata objects with template mappings and edge atoms + A list of unique ``ReactionMetadata`` objects with template + mappings and edge atoms populated for active reactions. """ try: reaction_instances = session.reaction_instances except AttributeError: reaction_instances = session - # Process and filter reactions - reactions_metadata = self._process_reaction_instances(reaction_instances, loop=loop) - unique_reaction_metadata = self._detect_duplicates(reactions_metadata) + reaction_metadata = self._process_reaction_instances( + reaction_instances, + loop=loop, + ) + unique_reaction_metadata = self._detect_duplicates( + reaction_metadata + ) for reaction in unique_reaction_metadata: - # Skip reactions marked as duplicates if not reaction.activity_stats: continue - combined_reactant_molecule_object = reaction.reactant_combined_RDmol + reactant_mol = reaction.reactant_combined_RDmol reaction_dataframe = reaction.reaction_dataframe csv_save_path = reaction.csv_path - # Build full atom mapping dictionary from dataframe - fully_mapped_dict = reaction_dataframe.set_index("reactant_idx")["product_idx"].to_dict() + # Extract the full atom mapping and first-shell list from the + # dataframe; these are needed to determine the template subset. + fully_mapped_dict = reaction_dataframe.set_index( + "reactant_idx" + )["product_idx"].to_dict() first_shell = reaction_dataframe["first_shell"].dropna().tolist() - # Generate template mapping by walking reaction graph + # Walk outward from the first-shell atoms to find the minimal + # template mapping and the edge atoms of the reaction site. template_mapped_dict, edge_atoms = reaction_atom_walker( - combined_reactant_molecule_object, + reactant_mol, first_shell, - fully_mapped_dict + fully_mapped_dict, ) - # Add template mapping and edge atoms to dataframe + # Attach template mapping columns and edge-atom list to the + # dataframe, then persist the updated version to CSV. reaction_dataframe = add_dict_as_new_columns( reaction_dataframe, template_mapped_dict, - titles=["template_reactant_idx", "template_product_idx"] + titles=[ + "template_reactant_idx", + "template_product_idx", + ], ) - - # Add edge atoms as a new column in the dataframe reaction_dataframe = add_column_safe( reaction_dataframe, edge_atoms, - "edge_atoms" + "edge_atoms", ) - # Save updated dataframe back to CSV and update metadata reaction.reaction_dataframe = reaction_dataframe.copy() - # Save the updated dataframe with template mappings and edge atoms to CSV reaction_dataframe.to_csv(csv_save_path, index=False) - # Update metadata with template mapping and edge atoms reaction.edge_atoms = edge_atoms - # Store the template mapping in the metadata for later use - reaction.template_reactant_to_product_mapping = template_mapped_dict + reaction.template_reactant_to_product_mapping = ( + template_mapped_dict + ) - # Store the finalized metadata inside the session return unique_reaction_metadata - - # --- REACTION INSTANCE AND PRODUCT PROCESSING --- - def _process_reaction_instances( - self, detected_reactions: list[ReactionInstance], loop: bool = False + self, + detected_reactions: list[ReactionInstance], + loop: bool = False, ) -> list[ReactionMetadata]: - """ - Converts ReactionInstance objects into ReactionMetadata by building molecules and running reactions. + """Convert reaction instances into mapped reaction metadata. + + For each detected reaction, this method prepares the reactant RDKit + molecules (from SMILES in the initial stage or from existing molecules + in loop mode), builds the RDKit reaction object, and delegates product + generation and mapping to ``_process_reaction_products``. Args: - detected_reactions: List of detected reaction instances + detected_reactions: List of ``ReactionInstance`` objects produced + by the reaction detector. + loop: Whether the call is part of the reaction progression loop. Returns: - List of ReactionMetadata objects with atom mappings + A list of ``ReactionMetadata`` objects, one per successfully + mapped product set. """ - - - csv_cache = self.csv_cache - reaction_metadata = [] + reaction_metadata: list[ReactionMetadata] = [] for reaction in detected_reactions: - # SMARTS template associated with this detected reaction. - rxn_smarts = reaction.reaction_smarts - - if loop and (reaction.monomer_1.rdkit_mol is None or - (reaction.monomer_2 is not None and reaction.monomer_2.rdkit_mol is None)): + if loop and ( + reaction.monomer_1.rdkit_mol is None + or ( + reaction.monomer_2 is not None + and reaction.monomer_2.rdkit_mol is None + ) + ): logger.warning( - f"Skipping reaction {reaction.reaction_name}: monomer rdkit_mol is None " - f"(likely failed sanitization upstream)." + "Skipping reaction %s: monomer rdkit_mol is None " + "(likely failed sanitization upstream).", + reaction.reaction_name, ) continue - same_reactants = reaction.same_reactants - delete_atoms = reaction.delete_atom - forced_indexes_1 = None - forced_indexes_2 = None + same_reactants = reaction.same_reactants + forced_idxs_1 = None + forced_idxs_2 = None if loop: - forced_indexes_1 = self._flatten_fg_indexes( + # In loop mode, restrict accepted initiators to atoms that + # belong to the previously matched functional groups. This + # prevents the reaction from jumping to an unrelated site + # during polymerization-like progression. + forced_idxs_1 = self._flatten_fg_indexes( reaction.functional_group_1 ) - if reaction.functional_group_2 is not None: - forced_indexes_2 = self._flatten_fg_indexes( + forced_idxs_2 = self._flatten_fg_indexes( reaction.functional_group_2 ) - + mol_reactant_1 = Chem.AddHs( Chem.Mol(reaction.monomer_1.rdkit_mol) ) - monomer_2 = ( reaction.monomer_1 if same_reactants @@ -280,8 +367,8 @@ def _process_reaction_instances( mol_reactant_2 = Chem.AddHs( Chem.Mol(monomer_2.rdkit_mol) ) - - # ReactionInstance already defines slot direction. + + # The ReactionInstance already defines reactant-slot order. reaction_tuple = [[mol_reactant_1, mol_reactant_2]] else: reactant_smiles_1 = reaction.monomer_1.smiles @@ -300,123 +387,163 @@ def _process_reaction_instances( mol_reactant_2, ) - rxn = self._build_reaction(rxn_smarts) - + rxn = self._build_reaction(reaction.reaction_smarts) reaction_metadata = self._process_reaction_products( - rxn, - csv_cache, - reaction_tuple, - delete_atoms, - reaction_metadata, - forced_indexes_1=forced_indexes_1, - forced_indexes_2=forced_indexes_2, + rxn=rxn, + csv_cache=self.csv_cache, + reaction_tuple=reaction_tuple, + delete_atoms=reaction.delete_atom, + reaction_metadata=reaction_metadata, + forced_indexes_1=forced_idxs_1, + forced_indexes_2=forced_idxs_2, ) return reaction_metadata - def _process_reaction_products(self, - rxn: Chem.rdChemReactions.ChemicalReaction, - csv_cache: Path, - reaction_tuple: list, - delete_atoms: bool = True, - reaction_metadata: Optional[list[ReactionMetadata]] = None, - forced_indexes_1: Optional[set] = None, - forced_indexes_2: Optional[set] = None, - ) -> list[ReactionMetadata]: - """ - Runs reactions on reactant pairs and builds metadata for each product set. + def _process_reaction_products( + self, + rxn: Chem.rdChemReactions.ChemicalReaction, + csv_cache: Path, + reaction_tuple: list, + delete_atoms: bool = True, + reaction_metadata: Optional[list[ReactionMetadata]] = None, + forced_indexes_1: Optional[set] = None, + forced_indexes_2: Optional[set] = None, + ) -> list[ReactionMetadata]: + """Run reactions and build metadata for each generated product set. + + Applies the RDKit reaction to each reactant pair, attempts reverse + ordering on failure, builds atom mappings, validates them, identifies + first-shell atoms and initiators, detects byproducts, and stores the + result as ``ReactionMetadata`` with a persistent CSV file. Args: - rxn: RDKit ChemicalReaction object - csv_cache: Path to cache directory for saving CSVs - reaction_tuple: List of reactant pairs to process - delete_atoms: Whether to detect and track byproducts - reaction_metadata: Accumulator list for metadata objects + rxn: RDKit ``ChemicalReaction`` object built from SMARTS. + csv_cache: Directory where mapping CSV files are written. + reaction_tuple: List of [reactant_1, reactant_2] pairs to react. + delete_atoms: Whether the reaction removes a byproduct fragment. + reaction_metadata: Mutable list to append new metadata to. A new + list is created if None is supplied. + forced_indexes_1: Allowed initiator atom indices for reactant 1 + (used in loop mode). None disables the filter. + forced_indexes_2: Allowed initiator atom indices for reactant 2 + (used in loop mode). None disables the filter. Returns: - Updated list of ReactionMetadata objects + The updated list of ``ReactionMetadata`` objects. """ if reaction_metadata is None: reaction_metadata = [] for pair in reaction_tuple: - r1, r2 = Chem.Mol(pair[0]), Chem.Mol(pair[1]) - - # Assign atom map numbers and isotopes to reactants for tracking through the reaction + r1 = Chem.Mol(pair[0]) + r2 = Chem.Mol(pair[1]) self._assign_atom_map_numbers_and_set_isotopes(r1, r2) - # 1. Run the reaction in default order (A + B) products = rxn.RunReactants((r1, r2)) - - # 2. If it fails due to order mismatch, try the reverse (B + A) if not products: - print ("Reaction failed in default order, trying reverse order...") + print( + "Reaction failed in default order, " + "trying reverse order..." + ) products = rxn.RunReactants((r2, r1)) - # Skip if no products were generated in either direction if not products: - print ("Reaction failed in both orders, skipping this reactant pair.") - print(f"\n[ERROR] RDKit failed to react {r1.GetNumAtoms()} atoms with {r2.GetNumAtoms()} atoms.") + print( + "Reaction failed in both orders, " + "skipping this reactant pair." + ) + print( + f"\n[ERROR] RDKit failed to react " + f"{r1.GetNumAtoms()} atoms with " + f"{r2.GetNumAtoms()} atoms." + ) print(f"Reactant 1 SMILES: {Chem.MolToSmiles(r1)}") print(f"Reactant 2 SMILES: {Chem.MolToSmiles(r2)}") - print(f"Reaction SMARTS: \n") + print("Reaction SMARTS: \n") continue - - # Process each product set generated by the reaction for product_set in products: - df = pd.DataFrame(columns=["reactant_idx", "product_idx"]) - reactant_combined = Chem.CombineMols(r1, r2) - if len(product_set) == 1: - product_combined = product_set[0] - else: - product_combined = reduce(Chem.CombineMols, product_set) + product_combined = ( + product_set[0] + if len(product_set) == 1 + else reduce(Chem.CombineMols, product_set) + ) - # Reassign atom map numbers based on isotopes to recover original reactant identities - self._reassign_atom_map_numbers_by_isotope(product_combined) - mapping_dict, df = self._build_atom_index_mapping(reactant_combined, product_combined) - reverse_mapping = {v: k for k, v in mapping_dict.items()} + self._reassign_atom_map_numbers_by_isotope( + product_combined + ) + mapping_dict, mapping_df = self._build_atom_index_mapping( + reactant_combined, + product_combined, + ) + reverse_mapping = { + product_idx: reactant_idx + for reactant_idx, product_idx in mapping_dict.items() + } - # Reveal original template map numbers for visualization and validation self._reveal_template_map_numbers(product_combined) + self._validate_mapping( + mapping_df, + reactant_combined, + product_combined, + ) - # Validate mapping consistency - self._validate_mapping(df, reactant_combined, product_combined) + first_shell, initiator_idxs = ( + self._assign_first_shell_and_initiators( + reactant_combined, + product_combined, + reverse_mapping, + ) + ) - # Identify atoms involved in reaction center and initiators - first_shell, initiator_idxs = self._assign_first_shell_and_initiators( - reactant_combined, product_combined, reverse_mapping + # When loop-mode restrictions are active, discard product sets + # whose initiators fall outside the allowed functional-group + # atom sets. + if ( + forced_indexes_1 is not None + or forced_indexes_2 is not None + ) and not self._initiators_within_forced_indexes( + initiator_idxs, + r1.GetNumAtoms(), + forced_indexes_1, + forced_indexes_2, + ): + continue + + byproduct_reactant_idxs = self._detect_byproducts( + product_combined, + reverse_mapping, + delete_atoms, ) - # FORCED-INDEX CHECK: discard this product if the atom that actually - # reacted isn't inside the given index set for its side. - if forced_indexes_1 is not None or forced_indexes_2 is not None: - if not self._initiators_within_forced_indexes( - initiator_idxs, r1.GetNumAtoms(), forced_indexes_1, forced_indexes_2 - ): - continue - - byproduct_reactant_idxs = self._detect_byproducts(product_combined, reverse_mapping, delete_atoms) - - df_combined = pd.concat([ - df, - pd.Series(first_shell, name="first_shell"), - pd.Series(initiator_idxs, name="initiators"), - pd.Series(byproduct_reactant_idxs, name="byproduct_idx") - ], axis=1).astype(pd.Int64Dtype()) - - # counter so every reaction across the whole run — including every - # pass of the progression loop — gets a distinct, ever-increasing id. + reaction_df = pd.concat( + [ + mapping_df, + pd.Series(first_shell, name="first_shell"), + pd.Series(initiator_idxs, name="initiators"), + pd.Series( + byproduct_reactant_idxs, + name="byproduct_idx", + ), + ], + axis=1, + ).astype(pd.Int64Dtype()) + self.session.reaction_id_counter += 1 - total_products = self.session.reaction_id_counter + reaction_id = self.session.reaction_id_counter + csv_path = csv_cache / f"reaction_{reaction_id}.csv" - self._clear_isotopes(reactant_combined, product_combined) - df_combined.to_csv(csv_cache / f"reaction_{total_products}.csv", index=False) + self._clear_isotopes( + reactant_combined, + product_combined, + ) + reaction_df.to_csv(csv_path, index=False) reaction_metadata.append( ReactionMetadata( - reaction_id=total_products, + reaction_id=reaction_id, reactant_combined_RDmol=reactant_combined, product_combined_RDmol=product_combined, reactant_to_product_mapping=mapping_dict, @@ -424,61 +551,84 @@ def _process_reaction_products(self, first_shell=first_shell, initiators=initiator_idxs, byproduct_indices=byproduct_reactant_idxs, - csv_path=csv_cache / f"reaction_{total_products}.csv", - reaction_dataframe=df_combined, + csv_path=csv_path, + reaction_dataframe=reaction_df, delete_atom=delete_atoms, - delete_atom_idx=byproduct_reactant_idxs[0] if byproduct_reactant_idxs else None, - activity_stats=True + delete_atom_idx=( + byproduct_reactant_idxs[0] + if byproduct_reactant_idxs + else None + ), + activity_stats=True, ) ) return reaction_metadata + def _detect_duplicates( + self, + reaction_metadata_list: list[ReactionMetadata], + ) -> list[ReactionMetadata]: + """Return unique reaction metadata based on reactants and products. - def _detect_duplicates(self, reaction_metadata_list: list[ReactionMetadata]) -> list[ReactionMetadata]: - """ - Filters duplicate reactions based on reactant and product molecules. + Two reactions are considered duplicates if their combined reactant and + combined product molecules are structurally identical. Duplicate + entries are retained in the returned list but marked inactive via + ``activity_stats = False``. Args: - reaction_metadata_list: List of reaction metadata to filter + reaction_metadata_list: List of ``ReactionMetadata`` objects to + deduplicate. Returns: - List of unique reactions; duplicates marked with activity_stats=False + The same list, with duplicate reactions flagged as inactive. """ unique_metadata: list[ReactionMetadata] = [] for reaction in reaction_metadata_list: - # Compare current reaction's reactants and products against unique reactions collected so far - reactants = reaction.reactant_combined_RDmol - products = reaction.product_combined_RDmol - - # Keep reaction if it's unique, otherwise mark as duplicate - if compare_set(unique_metadata, reactants, products): + if compare_set( + unique_metadata, + reaction.reactant_combined_RDmol, + reaction.product_combined_RDmol, + ): unique_metadata.append(reaction) else: reaction.activity_stats = False return unique_metadata + def _flatten_fg_indexes( + self, + fg: Optional["FunctionalGroupInfo"], + ) -> Optional[set]: + """Flatten functional-group match indexes into one allowed idx set. - # --- PROGRESSION AND FORCED-INDEX HANDLING --- + A functional group can have multiple SMARTS matches, each match being + a tuple or list of atom indices. This helper merges all matches for + both functional group slots into a single set of allowed atom indices. - def _flatten_fg_indexes(self, fg: Optional["FunctionalGroupInfo"]) -> Optional[set]: - """ - Flattens a FunctionalGroupInfo's recorded match indexes (fg_1_indexes and, - if present, fg_2_indexes for di_different groups) into a single allowed - atom-index set for forced-reaction checking. + Args: + fg: ``FunctionalGroupInfo`` object, or None. - Returns None only if the FG has no recorded indexes at all (no forcing applied). + Returns: + A set of atom indices, or None if no matches are available. """ if fg is None: return None combined = set() if fg.fg_1_indexes: - combined.update(atom_idx for match in fg.fg_1_indexes for atom_idx in match) + combined.update( + atom_idx + for match in fg.fg_1_indexes + for atom_idx in match + ) if fg.fg_2_indexes: - combined.update(atom_idx for match in fg.fg_2_indexes for atom_idx in match) + combined.update( + atom_idx + for match in fg.fg_2_indexes + for atom_idx in match + ) return combined or None @@ -489,326 +639,446 @@ def _initiators_within_forced_indexes( forced_indexes_1: Optional[set], forced_indexes_2: Optional[set], ) -> bool: - """ - Checks whether the atoms that actually reacted (the two 'initiators') fall - within the forced index constraint for their respective side. + """Check initiator atoms against their reactants' allowed idx sets. + + Initiator indices are global indices into the combined reactant + molecule. Indices below ``r1_atom_count`` belong to reactant 1; the + rest belong to reactant 2 after subtracting the offset. + + Args: + initiator_idxs: Reactant indices of the two initiator atoms. + r1_atom_count: Number of atoms in reactant 1 before combining. + forced_indexes_1: Allowed indices for reactant 1, or None. + forced_indexes_2: Allowed indices for reactant 2, or None. - Combined-mol index ranges follow Chem.CombineMols(r1, r2) ordering: - [0, r1_atom_count) belongs to r1, [r1_atom_count, ...) belongs to r2. + Returns: + True if every initiator lies within its respective allowed set, + or if no restriction is applied to that reactant. """ for idx in initiator_idxs: if idx < r1_atom_count: - if forced_indexes_1 is not None and idx not in forced_indexes_1: + if ( + forced_indexes_1 is not None + and idx not in forced_indexes_1 + ): return False else: local_idx = idx - r1_atom_count - if forced_indexes_2 is not None and local_idx not in forced_indexes_2: + if ( + forced_indexes_2 is not None + and local_idx not in forced_indexes_2 + ): return False - return True + return True - def _index_based_reaction_preparation(self, reaction_instances): - from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions - prepare_reactions = PrepareReactions(self.session) - prepared_reactions = prepare_reactions._prepare_reactions_stage(reaction_instances, loop=True) - return prepared_reactions + def _index_based_reaction_preparation( + self, + reaction_instances, + ): + """Prepare index-based reaction instances in loop mode. + Creates a fresh ``PrepareReactions`` instance and runs the preparation + stage with ``loop=True``. This helper is typically invoked by the + progression machinery when reactions need to be re-prepared after each + loop iteration. - # --- REACTION-CENTER ANALYSIS AND VALIDATION --- + Args: + reaction_instances: Collection of ``ReactionInstance`` objects. - def _assign_first_shell_and_initiators(self, - reactant_combined: Chem.Mol, - product_combined: Chem.Mol, - reversed_mapping_dict: dict[int, int]) -> tuple[list[int], list[int]]: + Returns: + List of ``ReactionMetadata`` objects produced in loop mode. """ - Identifies atoms in the first coordination shell (atoms with map numbers < 999) and initiator atoms. - Initiators are atoms with map numbers 1 or 2 (typically the reactive centers). + prepare_reactions = PrepareReactions(self.session) + return prepare_reactions._prepare_reactions_stage( + reaction_instances, + loop=True, + ) + + def _assign_first_shell_and_initiators( + self, + reactant_combined: Chem.Mol, + product_combined: Chem.Mol, + reversed_mapping_dict: dict[int, int], + ) -> tuple[list[int], list[int]]: + """Identify first-shell atoms and the two reaction initiators. + + First-shell atoms are defined as product atoms whose atom map number + is below 999 (i.e., they were assigned a template map number by the + reaction SMARTS) and that can be traced back to a reactant atom via + the reverse mapping. The two atoms whose product counterparts have map + numbers 1 and 2 are labeled as initiators. Args: - reactant_combined: Combined reactant molecule - product_combined: Combined product molecule - reversed_mapping_dict: Product idx -> Reactant idx mapping + reactant_combined: Combined reactant molecule with isotope-based + tracking map numbers still intact on product-mapped atoms. + product_combined: Combined product molecule with template map + numbers revealed via ``_reveal_template_map_numbers``. + reversed_mapping_dict: Mapping from product atom index to reactant + atom index. Returns: - Tuple of (first_shell atom indices, initiator atom indices) + A tuple of (first_shell, initiator_idxs), where each is a list of + reactant atom indices. Raises: - ValueError: If exactly 2 initiators are not found + ValueError: If a mapped product atom has no reverse mapping, or if + the number of initiator atoms is not exactly two. """ first_shell = [] initiator_idxs = [] - for p_atom in product_combined.GetAtoms(): - # Only process atoms with valid map numbers (< 999 indicates non-byproduct) - if p_atom.GetAtomMapNum() < 999: - p_idx = p_atom.GetIdx() - - if p_idx not in reversed_mapping_dict: - raise ValueError(f"Mapping error: product atom {p_idx} not found in mapping_dict") + for product_atom in product_combined.GetAtoms(): + map_num = product_atom.GetAtomMapNum() + if map_num >= 999: + continue - r_idx = reversed_mapping_dict[p_idx] - atom = reactant_combined.GetAtomWithIdx(r_idx) - atom.SetAtomMapNum(p_atom.GetAtomMapNum()) + product_idx = product_atom.GetIdx() + if product_idx not in reversed_mapping_dict: + raise ValueError( + f"Mapping error: product atom {product_idx} " + "not found in mapping_dict" + ) - first_shell.append(r_idx) + reactant_idx = reversed_mapping_dict[product_idx] + reactant_atom = reactant_combined.GetAtomWithIdx( + reactant_idx + ) + reactant_atom.SetAtomMapNum(map_num) + first_shell.append(reactant_idx) - # Initiators are atoms with map numbers 1 or 2 - if p_atom.GetAtomMapNum() in [1, 2]: - initiator_idxs.append(r_idx) + if map_num in (1, 2): + initiator_idxs.append(reactant_idx) if len(initiator_idxs) != 2: - raise ValueError(f"Expected 2 initiators, got {len(initiator_idxs)}: {initiator_idxs}") + raise ValueError( + f"Expected 2 initiators, got {len(initiator_idxs)}: " + f"{initiator_idxs}" + ) return first_shell, initiator_idxs + def _detect_byproducts( + self, + product_combined: Chem.Mol, + reversed_mapping_dict: dict[int, int], + delete_atoms: bool, + ) -> list[int]: + """Map atoms in the smallest product fragment to reactant idxs. - def _detect_byproducts(self, - product_combined: Chem.Mol, - reversed_mapping_dict: dict[int, int], - delete_atoms: bool) -> list[int]: - """ - Identifies byproduct atoms (smallest molecular fragment) and maps them back to reactant space. + When ``delete_atoms`` is True, the reaction is assumed to produce a + removable byproduct. The smallest disconnected fragment in the product + is treated as that byproduct, and its atoms are translated back to the + reactant-index space using the reverse mapping. Args: - product_combined: Combined product molecule - reversed_mapping_dict: Product idx -> Reactant idx mapping - delete_atoms: Whether to perform byproduct detection + product_combined: Combined product molecule, possibly containing + multiple disconnected fragments. + reversed_mapping_dict: Mapping from product atom index to reactant + atom index. + delete_atoms: If False, an empty list is returned immediately. Returns: - List of reactant indices corresponding to byproduct atoms + Reactant indices of the atoms composing the detected byproduct. """ if not delete_atoms: return [] - # Get tuples of original atom indices for each fragment - frags_indices = rdmolops.GetMolFrags(product_combined) + fragment_idxs = rdmolops.GetMolFrags(product_combined) + smallest_fragment_idxs = min(fragment_idxs, key=len) - # Find the tuple with the smallest number of atoms - smallest_frag_indices = min(frags_indices, key=len) - - byproduct_reactant_indices = [] - - # Map byproduct product indices back to reactant indices - for p_idx in smallest_frag_indices: - if p_idx in reversed_mapping_dict: - byproduct_reactant_indices.append(reversed_mapping_dict[p_idx]) - - return byproduct_reactant_indices + return [ + reversed_mapping_dict[product_idx] + for product_idx in smallest_fragment_idxs + if product_idx in reversed_mapping_dict + ] + def _validate_mapping( + self, + df: pd.DataFrame, + reactant: Chem.Mol, + product: Chem.Mol, + ) -> None: + """Validate mapping columns, uniqueness, bounds, and completeness. - def _validate_mapping(self, df: pd.DataFrame, reactant: Chem.Mol, product: Chem.Mol) -> None: - """ - Validates atom mapping consistency: checks for required columns, duplicates, bounds, and completeness. + Ensures that every atom in both the reactant and product molecules is + accounted for exactly once in the mapping dataframe and that all + indices are within bounds. Args: - df: Dataframe containing reactant_idx and product_idx columns - reactant: Reactant molecule - product: Product molecule + df: DataFrame containing at least ``reactant_idx`` and + ``product_idx`` columns. + reactant: Combined reactant RDKit molecule. + product: Combined product RDKit molecule. Raises: - MappingError: If any validation check fails + MappingError: If the dataframe is empty, missing required columns, + unbalanced, contains duplicates, has out-of-bounds indices, or + does not cover every atom in either molecule. """ - # Ensure dataframe exists and has required columns if df is None or df.empty: - raise MappingError("Mapping validation failed: empty dataframe") + raise MappingError( + "Mapping validation failed: empty dataframe" + ) - # Check for required columns required_cols = {"reactant_idx", "product_idx"} if not required_cols.issubset(df.columns): - raise MappingError(f"Mapping validation error: required columns {required_cols} not found in dataframe.") + raise MappingError( + "Mapping validation error: required columns " + f"{required_cols} not found in dataframe." + ) - # Extract indices and perform validation checks r_idxs = df["reactant_idx"].dropna().tolist() p_idxs = df["product_idx"].dropna().tolist() - # Atom counts must match if len(r_idxs) != len(p_idxs): - raise MappingError(f"Mapping validation error: mismatch in atom counts between reactant and product.") - - # No duplicate mappings (1-to-1 mapping required) + raise MappingError( + "Mapping validation error: mismatch in atom counts " + "between reactant and product." + ) if len(set(r_idxs)) != len(r_idxs): - raise MappingError(f"Mapping validation error: duplicate indices found in reactant mapping.") + raise MappingError( + "Mapping validation error: duplicate idxs found in " + "reactant mapping." + ) if len(set(p_idxs)) != len(p_idxs): - raise MappingError(f"Mapping validation error: duplicate indices found in product mapping.") - - # Indices must be within molecule bounds + raise MappingError( + "Mapping validation error: duplicate idxs found in " + "product mapping." + ) if any(idx >= reactant.GetNumAtoms() for idx in r_idxs): - raise MappingError(f"Mapping validation error: reactant index out of bounds.") + raise MappingError( + "Mapping validation error: reactant idx out of bounds." + ) if any(idx >= product.GetNumAtoms() for idx in p_idxs): - raise MappingError(f"Mapping validation error: product index out of bounds.") - - # All atoms must be mapped (complete mapping) + raise MappingError( + "Mapping validation error: product idx out of bounds." + ) if len(r_idxs) != reactant.GetNumAtoms(): - raise MappingError(f"Mapping validation error: incomplete mapping for reactant.") - # pass + raise MappingError( + "Mapping validation error: incomplete mapping for " + "reactant." + ) if len(p_idxs) != product.GetNumAtoms(): - raise MappingError(f"Mapping validation error: incomplete mapping for product.") - # pass - # --- ATOM MAPPING --- + raise MappingError( + "Mapping validation error: incomplete mapping for product." + ) - def _assign_atom_map_numbers_and_set_isotopes(self, r1: Chem.Mol, r2: Chem.Mol) -> None: - """ - Assigns unique map numbers and isotopes to reactant atoms for tracking through reaction. - Isotopes survive RDKit's reaction engine, allowing atom identity recovery post-reaction. + def _assign_atom_map_numbers_and_set_isotopes( + self, + r1: Chem.Mol, + r2: Chem.Mol, + ) -> None: + """Assign tracking map numbers and isotopes to reactant atoms. + + Atoms in reactant 1 are tagged with 1001-based numbers, and atoms in + reactant 2 with 2001-based numbers. Both the atom map number and the + isotope are set to the same value so that product atoms can later be + traced back to their originating reactant atoms regardless of how the + reaction SMARTS rewrites the molecule. Args: - r1: First reactant molecule - r2: Second reactant molecule + r1: First reactant molecule; modified in place. + r2: Second reactant molecule; modified in place. """ - # Assign map numbers 1001+ to first reactant atoms for atom in r1.GetAtoms(): idx = 1001 + atom.GetIdx() atom.SetAtomMapNum(idx) - atom.SetIsotope(idx) # Isotope survives the reaction + atom.SetIsotope(idx) - # Assign map numbers 2001+ to second reactant atoms for atom in r2.GetAtoms(): idx = 2001 + atom.GetIdx() atom.SetAtomMapNum(idx) - atom.SetIsotope(idx) # Isotope survives the reaction + atom.SetIsotope(idx) + def _reassign_atom_map_numbers_by_isotope( + self, + mol: Chem.Mol, + ) -> None: + """Restore product atom map numbers from tracking isotopes. - def _reassign_atom_map_numbers_by_isotope(self, mol: Chem.Mol) -> None: - """ - Restores atom map numbers from isotope values after reaction. - RDKit's reaction engine preserves isotopes, allowing recovery of original atom identities. + After RDKit runs the reaction, atoms that survive from the reactants + retain their original isotope values. This method copies those values + back into the atom map number slot and clears the isotope so that the + product can be aligned with the reactant via ``_build_atom_index_mapping``. Args: - mol: Product molecule with isotope information + mol: Product molecule; modified in place. """ for atom in mol.GetAtoms(): surviving_idx = atom.GetIsotope() if surviving_idx != 0: - atom.SetAtomMapNum(surviving_idx) # Restore original map number - atom.SetIsotope(0) # Clear isotope to restore normal chemistry + atom.SetAtomMapNum(surviving_idx) + atom.SetIsotope(0) - def _build_atom_index_mapping(self, - reactant_combined: Chem.Mol, - product_combined: Chem.Mol) -> tuple[dict[int, int], pd.DataFrame]: - """ - Builds bidirectional atom index mapping between reactants and products using map numbers. + def _build_atom_index_mapping( + self, + reactant_combined: Chem.Mol, + product_combined: Chem.Mol, + ) -> tuple[dict[int, int], pd.DataFrame]: + """Build reactant-to-product atom mapping using map numbers. + + Matches atoms across the combined reactant and product molecules by + their shared atom map numbers. Atoms with map number 0 (e.g., newly + added hydrogens or atoms that lost their tag) are ignored because they + cannot be traced unambiguously. Args: - reactant_combined: Combined reactant molecule - product_combined: Combined product molecule + reactant_combined: Combined reactant molecule with tracking map + numbers on surviving atoms. + product_combined: Combined product molecule with matching map + numbers on surviving atoms. Returns: - Tuple of (mapping dict: reactant_idx -> product_idx, dataframe with mapping) + A tuple of (mapping_dict, mapping_df). ``mapping_dict`` maps + reactant atom index to product atom index. ``mapping_df`` contains + the same data in two columns, ``reactant_idx`` and ``product_idx``. """ - mapping_dict = {} - - # Pre-index product atoms by map number for O(1) lookup product_map = { atom.GetAtomMapNum(): atom.GetIdx() for atom in product_combined.GetAtoms() if atom.GetAtomMapNum() != 0 } + mapping_dict = {} rows = [] - for r_atom in reactant_combined.GetAtoms(): - r_map_num = r_atom.GetAtomMapNum() - # Match reactant atom to product atom via map number - if r_map_num != 0 and r_map_num in product_map: - r_idx = r_atom.GetIdx() - p_idx = product_map[r_map_num] + for reactant_atom in reactant_combined.GetAtoms(): + reactant_map_num = reactant_atom.GetAtomMapNum() + if ( + reactant_map_num == 0 + or reactant_map_num not in product_map + ): + continue - mapping_dict[r_idx] = p_idx - rows.append({ - "reactant_idx": r_idx, - "product_idx": p_idx - }) + reactant_idx = reactant_atom.GetIdx() + product_idx = product_map[reactant_map_num] + mapping_dict[reactant_idx] = product_idx + rows.append( + { + "reactant_idx": reactant_idx, + "product_idx": product_idx, + } + ) - df = pd.DataFrame(rows) - return mapping_dict, df + return mapping_dict, pd.DataFrame(rows) def _reveal_template_map_numbers(self, mol: Chem.Mol) -> None: - """ - Restores map numbers from RDKit's internal 'old_mapno' property for visualization. - RDKit stores original map numbers in this property after reaction execution. + """Restore template map numbers from RDKit's ``old_mapno`` property. + + RDKit reaction SMARTS with atom maps stores the original template map + number in the ``old_mapno`` atom property. Copying it back to the atom + map number makes the reaction-center atoms visible to downstream first- + shell and initiator detection. Args: - mol: Product molecule + mol: Product molecule; modified in place. """ for atom in mol.GetAtoms(): - if atom.HasProp('old_mapno'): - map_num = atom.GetIntProp('old_mapno') - atom.SetAtomMapNum(map_num) + if atom.HasProp("old_mapno"): + atom.SetAtomMapNum(atom.GetIntProp("old_mapno")) - def _clear_isotopes(self, mol_1: Chem.Mol, mol_2: Chem.Mol) -> None: - """ - Clears isotope values from molecules to restore normal chemistry after using isotopes for atom tracking. + def _clear_isotopes( + self, + mol_1: Chem.Mol, + mol_2: Chem.Mol, + ) -> None: + """Remove tracking isotopes from two molecules. Args: - mol_1: First molecule to clear - mol_2: Second molecule to clear + mol_1: First molecule; modified in place. + mol_2: Second molecule; modified in place. """ for atom in mol_1.GetAtoms(): atom.SetIsotope(0) for atom in mol_2.GetAtoms(): atom.SetIsotope(0) - # --- REACTION AND REACTANT BUILDERS --- - - def _build_reaction(self, rxn_smarts: str) -> Chem.rdChemReactions.ChemicalReaction: - """Builds RDKit ChemicalReaction object from SMARTS string.""" - return AllChem.ReactionFromSmarts(rxn_smarts) + def _build_reaction( + self, + rxn_smarts: str, + ) -> Chem.rdChemReactions.ChemicalReaction: + """Build an RDKit reaction from a SMARTS string. + Args: + rxn_smarts: Reaction SMARTS describing the transformation. - def _build_reactants(self, reactant_smiles_1: str, reactant_smiles_2: str) -> tuple[Chem.Mol, Chem.Mol]: + Returns: + An RDKit ``ChemicalReaction`` object ready for ``RunReactants``. """ - Builds reactant molecules from SMILES strings with explicit hydrogens added. + return AllChem.ReactionFromSmarts(rxn_smarts) + + def _build_reactants( + self, + reactant_smiles_1: str, + reactant_smiles_2: str, + ) -> tuple[Chem.Mol, Chem.Mol]: + """Build two explicit-hydrogen reactant molecules from SMILES. Args: - reactant_smiles_1: SMILES string for first reactant - reactant_smiles_2: SMILES string for second reactant + reactant_smiles_1: SMILES string for the first reactant. + reactant_smiles_2: SMILES string for the second reactant. Returns: - Tuple of (reactant1 molecule, reactant2 molecule) with explicit hydrogens + A tuple of two RDKit molecules with explicit hydrogens added. + + Raises: + SMARTSParsingError: If either SMILES string cannot be parsed by + RDKit. """ mol_reactant_1 = Chem.MolFromSmiles(reactant_smiles_1) if mol_reactant_1 is None: - raise SMARTSParsingError(f"Failed to parse first reactant SMILES: {reactant_smiles_1!r}") - mol_reactant_1 = Chem.AddHs(mol_reactant_1) + raise SMARTSParsingError( + "Failed to parse first reactant SMILES: " + f"{reactant_smiles_1!r}" + ) mol_reactant_2 = Chem.MolFromSmiles(reactant_smiles_2) if mol_reactant_2 is None: - raise SMARTSParsingError(f"Failed to parse second reactant SMILES: {reactant_smiles_2!r}") - mol_reactant_2 = Chem.AddHs(mol_reactant_2) + raise SMARTSParsingError( + "Failed to parse second reactant SMILES: " + f"{reactant_smiles_2!r}" + ) - return mol_reactant_1, mol_reactant_2 + return Chem.AddHs(mol_reactant_1), Chem.AddHs(mol_reactant_2) + def _build_reaction_tuple( + self, + same_reactants: bool, + mol_reactant_1: Chem.Mol, + mol_reactant_2: Chem.Mol, + ) -> list: + """Build the ordered reactant pairs to pass to RDKit. - def _build_reaction_tuple(self, same_reactants: bool, mol_reactant_1: Chem.Mol, mol_reactant_2: Chem.Mol) -> list: - """ - Builds list of reactant pairs to process. If reactants are identical, returns single pair. - Otherwise returns both orderings to account for reaction directionality. + When the two reactants are the same molecule, only one ordering is + needed. Otherwise, both orderings are attempted so that asymmetric + SMARTS can match either reactant in either slot. Args: - same_reactants: Whether both reactants are identical - mol_reactant_1: First reactant molecule - mol_reactant_2: Second reactant molecule + same_reactants: True if reactant 1 and reactant 2 are identical. + mol_reactant_1: First reactant molecule. + mol_reactant_2: Second reactant molecule. Returns: - List of reactant pairs [[r1, r2], ...] to process + A list of [reactant_1, reactant_2] pairs. """ if same_reactants: return [[mol_reactant_1, mol_reactant_1]] - return [[mol_reactant_1, mol_reactant_2], [mol_reactant_2, mol_reactant_1]] - - - # --- GENERAL HELPERS --- + return [ + [mol_reactant_1, mol_reactant_2], + [mol_reactant_2, mol_reactant_1], + ] def _is_consecutive(self, num_list: list[int]) -> bool: - """ - Checks if list contains consecutive integers with no duplicates. + """Return whether values are unique consecutive integers. Args: - num_list: List of integers to check + num_list: List of integers to inspect. Returns: - True if list is consecutive and has no duplicates, False otherwise + True if the list is non-empty, contains no duplicates, and spans a + contiguous range of integers; otherwise False. """ if not num_list: return False @@ -818,22 +1088,29 @@ def _is_consecutive(self, num_list: list[int]) -> bool: and max(num_list) - min(num_list) + 1 == len(num_list) ) - # --- VISUALIZATION --- - def reaction_templates_highlighted_image_grid( self, session: "Session", highlight_type: str = "template", ) -> Image: - """ - Generates grid image of reactions with highlighted atoms based on type. + """Generate a two-column grid of highlighted reaction structures. + + Renders each active reaction as a reactant/product pair, highlighting + atoms according to the chosen highlight type. Supported types are: + ``template`` (template reaction atoms), ``edge`` (edge atoms of the + reaction template), ``initiators`` (reaction initiators), and + ``delete`` (byproduct atoms). Args: - session: The Session object containing reaction metadata to visualize - highlight_type: Type of atoms to highlight - "template", "edge", "initiators", or "delete" + session: The active AutoREACTER ``Session`` object containing the + populated ``reaction_metadata`` list. + highlight_type: Category of atoms to highlight. One of + ``"template"``, ``"edge"``, ``"initiators"``, or ``"delete"``. Returns: - PIL Image containing 2-column grid of reactant-product pairs with highlighted atoms + A PIL ``Image`` containing the grid, or None if no reaction + metadata is available. Atom map numbers are cleared before drawing + to keep the visualization uncluttered. """ metadata_list = session.reaction_metadata if not metadata_list: @@ -847,63 +1124,87 @@ def reaction_templates_highlighted_image_grid( for metadata in metadata_list: reactant = Chem.RWMol(metadata.reactant_combined_RDmol) product = Chem.RWMol(metadata.product_combined_RDmol) - names.extend([f"pre_{metadata.reaction_id}", f"post_{metadata.reaction_id}"]) + names.extend( + [ + f"pre_{metadata.reaction_id}", + f"post_{metadata.reaction_id}", + ] + ) - # Clear atom maps for clean visualization + # Remove atom map numbers so they do not clutter the image. for atom in reactant.GetAtoms(): atom.SetAtomMapNum(0) for atom in product.GetAtoms(): atom.SetAtomMapNum(0) - df = metadata.reaction_dataframe + reaction_df = metadata.reaction_dataframe atoms: List[int] = [] color_map: Dict[int, tuple] = {} - # Select atoms to highlight based on type if highlight_type == "template": - atoms = list((metadata.template_reactant_to_product_mapping or {}).keys()) - for a in atoms: - color_map[a] = (0.2, 0.6, 1.0) # blue - + atoms = list( + ( + metadata.template_reactant_to_product_mapping + or {} + ).keys() + ) + color_map = { + atom_idx: (0.2, 0.6, 1.0) + for atom_idx in atoms + } elif highlight_type == "edge": atoms = metadata.edge_atoms or [] - for a in atoms: - color_map[a] = (1.0, 0.4, 0.0) # orange - + color_map = { + atom_idx: (1.0, 0.4, 0.0) + for atom_idx in atoms + } elif highlight_type == "initiators": - atoms = df["initiators"].dropna().astype(int).tolist() if df is not None else [] - for a in atoms: - color_map[a] = (0.0, 0.8, 0.2) # green - + if reaction_df is not None: + atoms = ( + reaction_df["initiators"] + .dropna() + .astype(int) + .tolist() + ) + color_map = { + atom_idx: (0.0, 0.8, 0.2) + for atom_idx in atoms + } elif highlight_type == "delete": if metadata.delete_atom and metadata.byproduct_indices: atoms = metadata.byproduct_indices - for a in atoms: - color_map[a] = (1.0, 0.0, 0.0) # red + color_map = { + atom_idx: (1.0, 0.0, 0.0) + for atom_idx in atoms + } mols.extend([reactant, product]) - # Build atom mappings for highlighting + # Translate reactant highlight atoms to product indices using the + # forward mapping so the same atoms are colored on both sides of + # the reaction arrow. forward_map = metadata.reactant_to_product_mapping - reactant_atoms = atoms - - # Map reactant atoms to product atoms - product_atoms = [] - for r_idx in reactant_atoms: - if r_idx in forward_map: - product_atoms.append(forward_map[r_idx]) - - # Build color maps for reactant and product - reactant_color_map = {a: color_map[a] for a in reactant_atoms} - product_color_map = {p: color_map[r] for r, p in forward_map.items() if r in reactant_atoms} - - highlight_lists.append(reactant_atoms) - highlight_lists.append(product_atoms) - highlight_colors.append(reactant_color_map) - highlight_colors.append(product_color_map) + product_atoms = [ + forward_map[reactant_idx] + for reactant_idx in atoms + if reactant_idx in forward_map + ] + reactant_color_map = { + atom_idx: color_map[atom_idx] + for atom_idx in atoms + } + product_color_map = { + product_idx: color_map[reactant_idx] + for reactant_idx, product_idx in forward_map.items() + if reactant_idx in atoms + } + + highlight_lists.extend([atoms, product_atoms]) + highlight_colors.extend( + [reactant_color_map, product_color_map] + ) - # Generate grid image with 2 molecules per row - img = Draw.MolsToGridImage( + return Draw.MolsToGridImage( mols, legends=names, molsPerRow=2, @@ -912,4 +1213,3 @@ def reaction_templates_highlighted_image_grid( subImgSize=(400, 400), useSVG=False, ) - return img From 50e1c6735bb8897019dec05ff4d16428231ec2b0 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 12:36:16 -0400 Subject: [PATCH 059/176] Fix epoxy polymer reaction rules Update the functional groups detector import to use the registry module and add epoxy polymer reaction definitions with corrected SN2 regioselectivity for primary and secondary amine additions. --- .../detectors/functional_groups_detector.py | 2 +- .../reactions_library/epoxy_polymers.py | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 AutoREACTER/detectors/reactions_library/epoxy_polymers.py diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index 34aed969..c17f09e7 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -112,7 +112,7 @@ from AutoREACTER.input_parser import MonomerEntry # Conditional import for FunctionalGroupsLibrary to support both installed and local usage. -from .functional_groups_library import FunctionalGroupsLibrary +from AutoREACTER.detectors.functional_groups_library.registry import FunctionalGroupsLibrary logger = logging.getLogger(__name__) # Module-level logger for future diagnostics. if TYPE_CHECKING: diff --git a/AutoREACTER/detectors/reactions_library/epoxy_polymers.py b/AutoREACTER/detectors/reactions_library/epoxy_polymers.py new file mode 100644 index 00000000..24f6d125 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/epoxy_polymers.py @@ -0,0 +1,34 @@ +""" +Reactions organized under the epoxy polymers polymer family. +Tested and Passed - 7/21/2026 +""" +REACTIONS = { + 'Primary Amine and Epoxide Polyaddition (Epoxy-Amine, First Addition)': + { + 'same_reactants': False, + 'reactant_1': 'primary_amine', + 'reactant_2': 'di_epoxide', + 'product': 'secondary_amine_hydroxyl_product', + 'delete_atom': False, + # FIXED: N attacks the less hindered CH2 (:2), O stays on the more hindered CH (:3) + 'reaction': '[NX3H2:1]-[H:6].[CH2;X4:2]1[OX2:5][CH1;X4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'Notes': 'Corrected for SN2 regioselectivity (attacks less hindered carbon)'}, + + 'Secondary Amine and Epoxide Polyaddition (Epoxy-Amine, Second Addition / Crosslink)': + { + 'same_reactants': False, + 'reactant_1': 'secondary_amine', + 'reactant_2': 'di_epoxide', + 'product': 'tertiary_amine_crosslink_product', + 'delete_atom': False, + # FIXED: N attacks the less hindered CH2 (:2), O stays on the more hindered CH (:3) + 'reaction': '[NX3H1:1]-[H:6].[CH2;X4:2]1[OX2:5][CH1;X4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]', + 'reference': {'smarts': None, + 'reaction_and_mechanism': None}, + 'Notes': 'Corrected for SN2 regioselectivity (attacks less hindered carbon)'} + , + } \ No newline at end of file From 19abeb7a1d660a27d1fcf65a0f769e5405c028e2 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 15:52:03 -0400 Subject: [PATCH 060/176] Add registries for groups and reactions Introduces new registry modules for functional groups and reaction libraries that aggregate all submodules into single dictionaries, validate duplicates, and keep backward-compatible wrapper classes (`FunctionalGroupsLibrary` and `ReactionLibrary`). Also cleans up `epoxy_polymers.py` structure/formatting so the REACTIONS mapping is consistently closed. --- .../functional_groups_library/registry.py | 62 ++++++++++++++++++ .../reactions_library/epoxy_polymers.py | 9 +-- .../detectors/reactions_library/registry.py | 64 +++++++++++++++++++ 3 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 AutoREACTER/detectors/functional_groups_library/registry.py create mode 100644 AutoREACTER/detectors/reactions_library/registry.py diff --git a/AutoREACTER/detectors/functional_groups_library/registry.py b/AutoREACTER/detectors/functional_groups_library/registry.py new file mode 100644 index 00000000..fc7e2075 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/registry.py @@ -0,0 +1,62 @@ +"""Aggregate and validate all motif-based functional-group modules.""" + +from .oxygen_groups import FUNCTIONAL_GROUPS as OXYGEN_GROUPS +from .sulfur_groups import FUNCTIONAL_GROUPS as SULFUR_GROUPS +from .nitrogen_groups import FUNCTIONAL_GROUPS as NITROGEN_GROUPS +from .carboxyl_and_carbonyl_groups import FUNCTIONAL_GROUPS as CARBOXYL_AND_CARBONYL_GROUPS +from .mixed_ab_groups import FUNCTIONAL_GROUPS as MIXED_AB_GROUPS +from .ring_groups import FUNCTIONAL_GROUPS as RING_GROUPS +from .vinyl_and_alkene_groups import FUNCTIONAL_GROUPS as VINYL_AND_ALKENE_GROUPS +from .aromatic_groups import FUNCTIONAL_GROUPS as AROMATIC_GROUPS +from .silicon_groups import FUNCTIONAL_GROUPS as SILICON_GROUPS +from .halide_groups import FUNCTIONAL_GROUPS as HALIDE_GROUPS +from .heterocumulene_groups import FUNCTIONAL_GROUPS as HETEROCUMULENE_GROUPS +from .active_centers import FUNCTIONAL_GROUPS as ACTIVE_CENTERS + +_FUNCTIONAL_GROUP_MODULES = [ + OXYGEN_GROUPS, + SULFUR_GROUPS, + NITROGEN_GROUPS, + CARBOXYL_AND_CARBONYL_GROUPS, + MIXED_AB_GROUPS, + RING_GROUPS, + VINYL_AND_ALKENE_GROUPS, + AROMATIC_GROUPS, + SILICON_GROUPS, + HALIDE_GROUPS, + HETEROCUMULENE_GROUPS, + ACTIVE_CENTERS, +] + + +def load_functional_groups() -> dict: + """Return one flat functional-group dictionary with duplicate protection.""" + merged = {} + group_name_to_key = {} + + for module in _FUNCTIONAL_GROUP_MODULES: + for entry_key, entry in module.items(): + if entry_key in merged: + raise ValueError(f"Duplicate functional-group key: {entry_key}") + + group_name = entry["group_name"] + if group_name in group_name_to_key: + previous = group_name_to_key[group_name] + raise ValueError( + f"Duplicate group_name {group_name!r} in {previous!r} and {entry_key!r}" + ) + + merged[entry_key] = entry + group_name_to_key[group_name] = entry_key + + return merged + + +FUNCTIONAL_GROUPS = load_functional_groups() + + +class FunctionalGroupsLibrary: + """Backward-compatible class exposing ``self.monomer_types``.""" + + def __init__(self): + self.monomer_types = load_functional_groups() diff --git a/AutoREACTER/detectors/reactions_library/epoxy_polymers.py b/AutoREACTER/detectors/reactions_library/epoxy_polymers.py index 24f6d125..26cfa9a6 100644 --- a/AutoREACTER/detectors/reactions_library/epoxy_polymers.py +++ b/AutoREACTER/detectors/reactions_library/epoxy_polymers.py @@ -16,7 +16,8 @@ 'smarts': None, 'reaction_and_mechanism': None }, - 'Notes': 'Corrected for SN2 regioselectivity (attacks less hindered carbon)'}, + 'Notes': 'Corrected for SN2 regioselectivity (attacks less hindered carbon)' + }, 'Secondary Amine and Epoxide Polyaddition (Epoxy-Amine, Second Addition / Crosslink)': { @@ -29,6 +30,6 @@ 'reaction': '[NX3H1:1]-[H:6].[CH2;X4:2]1[OX2:5][CH1;X4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]', 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'Notes': 'Corrected for SN2 regioselectivity (attacks less hindered carbon)'} - , - } \ No newline at end of file + 'Notes': 'Corrected for SN2 regioselectivity (attacks less hindered carbon)' + } + } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/registry.py b/AutoREACTER/detectors/reactions_library/registry.py new file mode 100644 index 00000000..15b2968b --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/registry.py @@ -0,0 +1,64 @@ +"""Aggregate and validate all polymer-family reaction modules.""" + +from .polyesters import REACTIONS as POLYESTERS +from .polyethers import REACTIONS as POLYETHERS +from .polyamides import REACTIONS as POLYAMIDES +from .polyanhydrides import REACTIONS as POLYANHYDRIDES +from .polythioesters import REACTIONS as POLYTHIOESTERS +from .polyurethanes import REACTIONS as POLYURETHANES +from .polyureas import REACTIONS as POLYUREAS +from .epoxy_polymers import REACTIONS as EPOXY_POLYMERS +from .vinyl_polymers import REACTIONS as VINYL_POLYMERS +from .polycarbonates import REACTIONS as POLYCARBONATES +from .polyimides import REACTIONS as POLYIMIDES +from .polybenzimidazoles import REACTIONS as POLYBENZIMIDAZOLES +# from .phenolic_resins import REACTIONS as PHENOLIC_RESINS +from .polysiloxanes import REACTIONS as POLYSILOXANES +from .polysulfides import REACTIONS as POLYSULFIDES +from .thiol_ene_polymers import REACTIONS as THIOL_ENE_POLYMERS +# from .metathesis_polymers import REACTIONS as METATHESIS_POLYMERS +# from .cycloaddition_polymers import REACTIONS as CYCLOADDITION_POLYMERS + +_REACTION_MODULES = [ + POLYESTERS, + POLYETHERS, + POLYAMIDES, + POLYANHYDRIDES, + POLYTHIOESTERS, + POLYURETHANES, + POLYUREAS, + EPOXY_POLYMERS, + VINYL_POLYMERS, + POLYCARBONATES, + POLYIMIDES, + POLYBENZIMIDAZOLES, + # PHENOLIC_RESINS, + POLYSILOXANES, + POLYSULFIDES, + THIOL_ENE_POLYMERS, + # METATHESIS_POLYMERS, + # CYCLOADDITION_POLYMERS, +] + + +def load_reactions() -> dict: + """Return one flat reaction dictionary with duplicate-name protection.""" + merged = {} + + for module in _REACTION_MODULES: + for reaction_name, reaction in module.items(): + if reaction_name in merged: + raise ValueError(f"Duplicate reaction name: {reaction_name}") + merged[reaction_name] = reaction + + return merged + + +REACTIONS = load_reactions() + + +class ReactionLibrary: + """Backward-compatible class exposing ``self.reactions``.""" + + def __init__(self): + self.reactions = load_reactions() From 8f85eaef62fa47b58d4a0c653fe7101c610c4f35 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 15:56:45 -0400 Subject: [PATCH 061/176] Add package exports for detector libraries Create `__init__.py` modules for `functional_groups_library` and `reactions_library` to expose their registry APIs (`load_*`, library classes, and constants) through clean package-level imports. --- AutoREACTER/detectors/functional_groups_library/__init__.py | 5 +++++ AutoREACTER/detectors/reactions_library/__init__.py | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 AutoREACTER/detectors/functional_groups_library/__init__.py create mode 100644 AutoREACTER/detectors/reactions_library/__init__.py diff --git a/AutoREACTER/detectors/functional_groups_library/__init__.py b/AutoREACTER/detectors/functional_groups_library/__init__.py new file mode 100644 index 00000000..133353b7 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/__init__.py @@ -0,0 +1,5 @@ +"""Functional groups organized by reactive motif.""" + +from .registry import FUNCTIONAL_GROUPS, FunctionalGroupsLibrary, load_functional_groups + +__all__ = ["FUNCTIONAL_GROUPS", "FunctionalGroupsLibrary", "load_functional_groups"] diff --git a/AutoREACTER/detectors/reactions_library/__init__.py b/AutoREACTER/detectors/reactions_library/__init__.py new file mode 100644 index 00000000..8bd1e695 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/__init__.py @@ -0,0 +1,5 @@ +"""Polymer reactions organized by polymer/product family.""" + +from .registry import REACTIONS, ReactionLibrary, load_reactions + +__all__ = ["REACTIONS", "ReactionLibrary", "load_reactions"] From 31e15b483bbad5f731dd14ea0b7968f5439f7bdf Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 16:15:14 -0400 Subject: [PATCH 062/176] Add polyamide reaction library Adds a new `polyamides` reaction library with polyamidation definitions for amino acid, diamine/diacid, and diacid halide routes, plus hydrolytic caprolactam initiation. Includes source references and notes for untested or later-implemented reactions. --- .../detectors/reactions_library/polyamides.py | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 AutoREACTER/detectors/reactions_library/polyamides.py diff --git a/AutoREACTER/detectors/reactions_library/polyamides.py b/AutoREACTER/detectors/reactions_library/polyamides.py new file mode 100644 index 00000000..80e56de6 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polyamides.py @@ -0,0 +1,130 @@ +"""Reactions organized under the polyamides polymer family. + +Uncommented reactions from the supplied working library retain their original dictionary values. Formerly commented and newly added reactions remain marked UNTESTED in comments.""" + +REACTIONS = { + 'Amino Acid Polycondensation (Polyamidation)': + { + 'same_reactants': True, + 'reactant_1': 'amino_acid', + 'product': 'polyamide_chain', + 'delete_atom': True, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', + 'reference': + { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': + [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', + 'https://pubs.acs.org/doi/10.1021/ed073pA312' + ] + }, + 'comments': None}, + 'Amino Acid and Amino Acid Polycondensation (Polyamidation)': + { + 'same_reactants': False, + 'reactant_1': 'amino_acid', + 'reactant_2': 'amino_acid', + 'product': 'polyamide_chain', + 'delete_atom': True, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', + 'reference': + { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': + [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', + 'https://pubs.acs.org/doi/10.1021/ed073pA312' + ] + }, + 'comments': None + }, + 'Di-Amine and Di-Carboxylic Acid Polycondensation (Polyamidation)': + { + 'same_reactants': False, + 'reactant_1': 'di_amine', + 'reactant_2': 'di_carboxylic_acid', + 'product': 'polyamide_chain', + 'delete_atom': True, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', + 'reference': + { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': + [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1' + ] + }, + 'comments': None + }, + 'Di-Amine and Di-Carboxylic Acid Halide Polycondensation (Polyamidation)': + { + 'same_reactants': False, + 'reactant_1': 'di_amine', + 'reactant_2': 'di_carboxylic_acid_halide', + 'product': 'polyamide_chain', + 'delete_atom': True, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[Cl,Br,I:5]>>[NX3:1]-[CX3:2](=[O:4]).[Cl,Br,I:5]-[H:3]', + 'reference': + { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': + [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734' + ] + }, + 'comments': None + }, + 'Hydrolytic Initiation of Caprolactam': + { + 'same_reactants': False, + 'reactant_1': 'water', + 'reactant_2': 'lactam', + 'product': 'polyamide_chain', + 'delete_atom': False, + 'reaction': '[O:1]-[H:12].[CX3:2]1(=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4]1-[H:6]>>[O:1]-[CX3:2](=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4](-[H:6])-[H:12]', + 'reference': + { + 'smarts': None, + 'reaction_and_mechanism': ['https://doi.org/10.1002/047147875X'] + }, + 'comments': None, + 'Notes': "Validated on 2026-07-26, Passed" + }, + } + +### LATER IMPLEMENTATION: Consider adding more detailed reaction mechanisms and validation steps for hydrolytic initiation of caprolactam. + +# 'Caprolactam Ring-Opening Polyamidation': +# { +# 'same_reactants': True, +# 'reactant_1': 'lactam', +# 'product': 'polyamide_chain', +# 'delete_atom': False, +# # Reactant 2 explicitly maps the 5 CH2 groups (maps 7 through 11) and uses '1' for the ring closure. +# # Product SMARTS removes the '.' and explicitly connects the opened chain. +# 'reaction': '[NX3:1]-[H:5].[CX3:2]1(=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4]1-[H:6]>>[NX3:1]-[CX3:2](=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4](-[H:5])-[H:6]', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# }, +# }, +# 'Lactam and Lactam Ring-Opening Copolyamidation': +# { +# 'same_reactants': False, +# 'reactant_1': 'lactam', +# 'reactant_2': 'lactam', +# 'product': 'polyamide_chain', +# 'delete_atom': False, +# 'reaction': '[NX3H1;R:1]-[H:2].[CX3;R:3](=[OX1:4])[NX3H1;R:5]-[H:6]>>[NX3:1]-[CX3:3](=[OX1:4]).[NX3:5](-[H:2])-[H:6]', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': +# } +# } From 13b70d95bbd785c73167775c4015578a23ae65f1 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 16:26:13 -0400 Subject: [PATCH 063/176] Add mixed AB groups and polymer reaction libraries Introduces a new `mixed_ab_groups` functional-group library with hydroxy/carboxylic, hydroxy/acid-halide, amino-acid, acid/acid-halide, and hydroxy/thiol monomer patterns. Adds new polymer reaction library modules for cycloaddition, metathesis, phenolic resins, and polyanhydrides; the polyanhydride pathways are defined as active reactions, while the others are scaffolded as commented UNTESTED templates for future implementation. --- .../mixed_ab_groups.py | 43 +++++++++++++++ .../cycloaddition_polymers.py | 29 +++++++++++ .../reactions_library/metathesis_polymers.py | 22 ++++++++ .../reactions_library/phenolic_resins.py | 52 +++++++++++++++++++ .../reactions_library/polyanhydrides.py | 31 +++++++++++ 5 files changed, 177 insertions(+) create mode 100644 AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py create mode 100644 AutoREACTER/detectors/reactions_library/cycloaddition_polymers.py create mode 100644 AutoREACTER/detectors/reactions_library/metathesis_polymers.py create mode 100644 AutoREACTER/detectors/reactions_library/phenolic_resins.py create mode 100644 AutoREACTER/detectors/reactions_library/polyanhydrides.py diff --git a/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py b/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py new file mode 100644 index 00000000..aee41c55 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py @@ -0,0 +1,43 @@ + +FUNCTIONAL_GROUPS = { + 'hydroxy_carboxylic_acid_monomer': + { + 'functionality_type': 'di_different', + 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', + 'smarts_2': '[CX3:2](=[O])[OX2H1]', + 'group_name': 'hydroxy_carboxylic_acid', + 'comments': None + }, + 'hydroxy_acid_halides_monomer': + { + 'functionality_type': 'di_different', + 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', + 'smarts_2': '[CX3:2](=[O])[Cl,Br,I]', + 'group_name': 'hydroxy_acid_halide', + 'comments': None + }, + 'amino_acid_monomer': + { + 'functionality_type': 'di_different', + 'smarts_1': '[NX3;H2,H1;!$([N][C,S]=*):1]', + 'smarts_2': '[CX3:2](=[O])[OX2H1]', + 'group_name': 'amino_acid', + 'comments': None + }, + 'carboxylic_acid_acid_halide_monomer': + { + 'functionality_type': 'di_different', + 'smarts_1': '[CX3:1](=[O])[OX2H1]', + 'smarts_2': '[CX3:2](=[O])[Cl,Br,I]', + 'group_name': 'carboxylic_acid_acid_halide', + 'comments': None + }, + 'hydroxy_thiol_monomer': + { + 'functionality_type': 'di_different', + 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', + 'smarts_2': '[SX2H1;!$([S][C,S]=*):2]', + 'group_name': 'hydroxy_thiol', + 'comments': None + } +} diff --git a/AutoREACTER/detectors/reactions_library/cycloaddition_polymers.py b/AutoREACTER/detectors/reactions_library/cycloaddition_polymers.py new file mode 100644 index 00000000..5d48677c --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/cycloaddition_polymers.py @@ -0,0 +1,29 @@ +# """Reactions organized under the cycloaddition polymers polymer family.""" + +# Yet to be tested and implemented +# REACTIONS = { +# 'Bis-Alkene Four-Center Cycloaddition Polymerization': +# { +# 'same_reactants': True, +# 'reactant_1': 'bis_alkene', +# 'product': 'polycyclobutane_chain', +# 'delete_atom': False, +# 'reaction': '[C:1]=[C:2].[C:3]=[C:4]>>[C:1]1-[C:2]-[C:3]-[C:4]-1', +# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, +# 'comments': 'UNTESTED new chemistry; generic [2+2] ' +# 'four-center cycloaddition.' +# }, +# 'Bis-Alkene and Bis-Alkene Four-Center Copolymerization': +# { +# 'same_reactants': False, +# 'reactant_1': 'bis_alkene', +# 'reactant_2': 'bis_alkene', +# 'product': 'polycyclobutane_chain', +# 'delete_atom': False, +# 'reaction': '[C:1]=[C:2].[C:3]=[C:4]>>[C:1]1-[C:2]-[C:3]-[C:4]-1', +# 'reference': {'smarts': None, +# 'reaction_and_mechanism': None}, +# 'comments': 'UNTESTED: separate false instance for two ' +# 'different bis-alkenes.' +# } +# } diff --git a/AutoREACTER/detectors/reactions_library/metathesis_polymers.py b/AutoREACTER/detectors/reactions_library/metathesis_polymers.py new file mode 100644 index 00000000..17cab81e --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/metathesis_polymers.py @@ -0,0 +1,22 @@ +# """Reactions organized under the metathesis polymers polymer family. + +# Uncommented reactions from the supplied working library retain their original dictionary values. Formerly commented and newly added reactions remain marked UNTESTED in comments.""" + +# REACTIONS = { +# 'ROMP Initiation': { +# 'same_reactants': False, +# 'reactant_1': 'romp_alkylidene', +# 'reactant_2': 'cyclic_olefin', +# 'product': 'romp_chain_end', +# 'delete_atom': False, +# 'reaction': '[Ru:1]=[C:2].[CX3;R:3]=[CX3;R:4]>>[Ru:1]=[CX3:4].[C:2]-[CX3:3]', +# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, +# 'comments': 'UNTESTED new chemistry. Initiator Ru/alkylidene carbon are maps 1 and 2.'}, +# 'ROMP Propagation': {'same_reactants': False, +# 'reactant_1': 'romp_alkylidene', +# 'reactant_2': 'cyclic_olefin', +# 'product': 'romp_chain_end', +# 'delete_atom': False, +# 'reaction': '[Ru:1]=[C:2].[CX3;R:3]=[CX3;R:4]>>[Ru:1]=[CX3:4].[C:2]-[CX3:3]', +# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, +# 'comments': 'UNTESTED new chemistry.'}} diff --git a/AutoREACTER/detectors/reactions_library/phenolic_resins.py b/AutoREACTER/detectors/reactions_library/phenolic_resins.py new file mode 100644 index 00000000..09761f29 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/phenolic_resins.py @@ -0,0 +1,52 @@ +# """Reactions organized under the phenolic resins polymer family. + +# Uncommented reactions from the supplied working library retain their original dictionary values. Formerly commented and newly added reactions remain marked UNTESTED in comments.""" + +# REACTIONS = { +# "Phenol and Formaldehyde Hydroxymethylation": { +# "same_reactants": False, +# "reactant_1": "phenol", +# "reactant_2": "formaldehyde", +# "product": "hydroxymethyl_phenol", +# "delete_atom": False, +# "reaction": ( +# "[c:1]-[H:4].[CH2:2]=[OX1:3]" +# ">>" +# "[c:1]-[C:2]-[OX2:3]-[H:4]" +# ), +# "reference": { +# "smarts": None, +# "reaction_and_mechanism": None, +# }, +# "comments": ( +# "UNTESTED new chemistry; first Bakelite-forming step. " +# "Generic aromatic C-H matching is not restricted to " +# "ortho/para substitution." +# ), +# }, + +# "Hydroxymethyl Phenol and Phenol Condensation " +# "(Methylene Bridge Formation)": { +# "same_reactants": False, +# "reactant_1": "hydroxymethyl_phenol", +# "reactant_2": "phenol", +# "product": "phenol_formaldehyde_chain", +# "delete_atom": True, +# "reaction": ( +# "[c:1]-[CH2:2]-[OX2H1:3]-[H:6]." +# "[c:4]-[H:5]" +# ">>" +# "[c:1]-[C:2]-[c:4]." +# "[OX2:3](-[H:5])-[H:6]" +# ), +# "reference": { +# "smarts": None, +# "reaction_and_mechanism": None, +# }, +# "comments": ( +# "UNTESTED. Produces a methylene bridge and water. " +# "Generic aromatic C-H matching is not restricted to " +# "ortho/para substitution." +# ), +# }, +# } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polyanhydrides.py b/AutoREACTER/detectors/reactions_library/polyanhydrides.py new file mode 100644 index 00000000..513cd9a7 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polyanhydrides.py @@ -0,0 +1,31 @@ +REACTIONS = { + 'Carboxylic Acid and Acid Halide Polycondensation(Polyanhydride Formation)': + { + 'same_reactants': True, + 'reactant_1': 'carboxylic_acid_acid_halide', + 'product': 'polyanhydride_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]', + 'reference': + { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + }, + 'Carboxylic Acid and Acid Halide Polycondensation(Polyanhydride Formation) - Different Reactants': + { + 'same_reactants': False, + 'reactant_1': 'carboxylic_acid_acid_halide', + 'reactant_2': 'carboxylic_acid_acid_halide', + 'product': 'polyanhydride_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]', + 'reference': + { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + } + } From 90e9792fbba92ea6b6b8dc01b971119e1b28956a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 16:33:09 -0400 Subject: [PATCH 064/176] Add nitrogen functional groups library Add definitions for nitrogen-based functional groups (primary amine, secondary amine, di-amine, di-primary amine) to support amine-based polymer reactions. Also stage polybenzimidazole reaction definitions for future work, currently disabled pending validation. --- .../nitrogen_groups.py | 41 +++++++++++++++++++ .../reactions_library/polybenzimidazoles.py | 17 ++++++++ .../detectors/reactions_library/registry.py | 2 +- 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 AutoREACTER/detectors/functional_groups_library/nitrogen_groups.py create mode 100644 AutoREACTER/detectors/reactions_library/polybenzimidazoles.py diff --git a/AutoREACTER/detectors/functional_groups_library/nitrogen_groups.py b/AutoREACTER/detectors/functional_groups_library/nitrogen_groups.py new file mode 100644 index 00000000..c21ced15 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/nitrogen_groups.py @@ -0,0 +1,41 @@ +"""Functional-group definitions organized by the nitrogen groups motif. + +Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" + +FUNCTIONAL_GROUPS = { + 'primary_amine_monomer': + { + 'functionality_type': 'mono', + 'smarts_1': '[NX3H2;!$(NC=O);!$(NC=[N,O,S])]', + 'group_name': 'primary_amine', + 'comments': None + }, # Tested - Passed + 'secondary_amine_monomer': + { + 'functionality_type': 'mono', + 'smarts_1': '[NX3H1;!$(NC=O);!$(NC=[N,O,S])]', + 'group_name': 'secondary_amine', + 'comments': None + }, + 'di_amine_monomer': + { + 'functionality_type': 'di_identical', + 'smarts_1': '[NX3;H2,H1;!$([N][C,S]=*):1]', + 'group_name': 'di_amine', + 'comments': None + }, + 'di_primary_amine_monomer': + { + 'functionality_type': 'di_identical', + 'smarts_1': '[NX3H2;!$([N][C,S]=*)]', + 'group_name': 'di_primary_amine', + 'comments': None + }, + # 'tetra_amine_monomer': + # { + # 'functionality_type': 'di_identical', + # 'smarts_1': '[c]([NX3H2;!$([N][C,S]=*)])[c][NX3H2;!$([N][C,S]=*)]', + # 'group_name': 'tetra_amine', + # 'comments': None + # } +} diff --git a/AutoREACTER/detectors/reactions_library/polybenzimidazoles.py b/AutoREACTER/detectors/reactions_library/polybenzimidazoles.py new file mode 100644 index 00000000..31f07aaf --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polybenzimidazoles.py @@ -0,0 +1,17 @@ +# """ +# This is an EDGE case for polybenzimidazole formation reactions. This needs to be futher studied and realease the reaction only after thorough validation. +# """ + +# REACTIONS = {'Tetra-Amine and Di-Carboxylic Acid Polycondensation (PBI Formation)': +# { +# 'same_reactants': False, +# 'reactant_1': 'tetra_amine', +# 'reactant_2': 'di_carboxylic_acid', +# 'product': 'polybenzimidazole_chain', +# 'delete_atom': True, +# 'reaction': '[c:7]([NX3H2:1](-[H:6])-[H:9])-[c:8]([NX3H2:2](-[H:10])-[H:11]).[CX3:3](=[OX1:4])[OX2H1:5]-[H:12]>>[c:7]1-[NX3:1](-[H:6])-[CX3:3]=[NX2:2]-[c:8]-1.[OX2:4](-[H:9])-[H:10].[OX2:5](-[H:11])-[H:12]', +# 'reference': {'smarts': None, +# 'reaction_and_mechanism': None}, +# 'comments': 'UNTESTED new chemistry; one benzimidazole ring-forming event with two mapped waters.' +# } +# } diff --git a/AutoREACTER/detectors/reactions_library/registry.py b/AutoREACTER/detectors/reactions_library/registry.py index 15b2968b..b1d87c83 100644 --- a/AutoREACTER/detectors/reactions_library/registry.py +++ b/AutoREACTER/detectors/reactions_library/registry.py @@ -11,7 +11,7 @@ from .vinyl_polymers import REACTIONS as VINYL_POLYMERS from .polycarbonates import REACTIONS as POLYCARBONATES from .polyimides import REACTIONS as POLYIMIDES -from .polybenzimidazoles import REACTIONS as POLYBENZIMIDAZOLES +# from .polybenzimidazoles import REACTIONS as POLYBENZIMIDAZOLES # from .phenolic_resins import REACTIONS as PHENOLIC_RESINS from .polysiloxanes import REACTIONS as POLYSILOXANES from .polysulfides import REACTIONS as POLYSULFIDES From 59c8200b28c916767b48de0eab5ea098353732ae Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 16:33:25 -0400 Subject: [PATCH 065/176] Update registry.py --- AutoREACTER/detectors/reactions_library/registry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutoREACTER/detectors/reactions_library/registry.py b/AutoREACTER/detectors/reactions_library/registry.py index b1d87c83..81f589ab 100644 --- a/AutoREACTER/detectors/reactions_library/registry.py +++ b/AutoREACTER/detectors/reactions_library/registry.py @@ -31,7 +31,7 @@ VINYL_POLYMERS, POLYCARBONATES, POLYIMIDES, - POLYBENZIMIDAZOLES, + #POLYBENZIMIDAZOLES, # PHENOLIC_RESINS, POLYSILOXANES, POLYSULFIDES, From 92ad7932d134a1c2eca7c43f40f0af0cbd201d69 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 16:54:47 -0400 Subject: [PATCH 066/176] Add polycarbonate synthesis pathways Add functional group definitions for carboxyl and carbonyl groups, and reaction pathways for polycarbonate formation via diol with phosgene or diphenyl carbonate. --- .../carboxyl_and_carbonyl_groups.py | 40 +++++++++++++++++++ .../reactions_library/polycarbonates.py | 32 +++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py create mode 100644 AutoREACTER/detectors/reactions_library/polycarbonates.py diff --git a/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py b/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py new file mode 100644 index 00000000..af4e6f63 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py @@ -0,0 +1,40 @@ +"""Functional-group definitions organized by the carboxyl and carbonyl groups motif. + +Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" + +FUNCTIONAL_GROUPS = { + 'di_carboxylic_acid_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[CX3:1](=[O])[OX2H1]', + 'group_name': 'di_carboxylic_acid', + 'comments': None + }, + 'di_carboxylic_acid_halide_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[CX3:1](=[O])[Cl,Br,I]', + 'group_name': 'di_carboxylic_acid_halide', + 'comments': None + }, + 'di_carboxylic_ester_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[CX3:1](=[O])[OX2H0][#6]', + 'group_name': 'di_carboxylic_ester', + 'comments': None + }, + 'phosgene_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[CX3](=[OX1])[Cl]', + 'group_name': 'phosgene', + 'comments': None, + }, + 'diphenyl_carbonate_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[CX3](=[OX1])[OX2][c]', + 'group_name': 'diphenyl_carbonate', + 'comments': None + } +# 'formaldehyde_monomer': {'functionality_type': 'mono', +# 'smarts_1': '[CH2]=[OX1]', +# 'group_name': 'formaldehyde', +# 'comments': None}} +} \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polycarbonates.py b/AutoREACTER/detectors/reactions_library/polycarbonates.py new file mode 100644 index 00000000..10fd7054 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polycarbonates.py @@ -0,0 +1,32 @@ +REACTIONS = { + 'Diol and Phosgene Polycondensation(Polycarbonate Formation)': + { + 'same_reactants': False, + 'reactant_1': 'diol', + 'reactant_2': 'phosgene', + 'product': 'polycarbonate_chain', + 'delete_atom': True, + 'reaction': '[OX2:1]-[H:4].[CX3:2](=[OX1:5])[Cl:3]>>[OX2:1]-[CX3:2](=[OX1:5]).[Cl:3]-[H:4]', + 'reference': + { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None, + }, + 'Diol and Diphenyl Carbonate Polycondensation(Transcarbonation)': + { + 'same_reactants': False, + 'reactant_1': 'diol', + 'reactant_2': 'diphenyl_carbonate', + 'product': 'polycarbonate_chain', + 'delete_atom': True, + 'reaction': '[OX2:1]-[H:4].[CX3:2](=[OX1:5])[OX2:3][c:6]>>[OX2:1]-[CX3:2](=[OX1:5]).[OX2:3](-[H:4])-[c:6]', + 'reference': + { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + } + } \ No newline at end of file From 3fa18ed72e1ea694657d0ed17ba4a96413a32ff1 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 21 Jul 2026 17:28:20 -0400 Subject: [PATCH 067/176] Fix phosgene SMARTS to prevent partial matches Changed phosgene_monomer from di_identical to mono functionality type and updated the SMARTS pattern to strictly require both chlorines on the carbonyl carbon, preventing false matches with standard acid chlorides. --- .../carboxyl_and_carbonyl_groups.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py b/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py index af4e6f63..8a1fb1c9 100644 --- a/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py @@ -22,8 +22,9 @@ 'comments': None }, 'phosgene_monomer': { - 'functionality_type': 'di_identical', - 'smarts_1': '[CX3](=[OX1])[Cl]', + 'functionality_type': 'mono', + # Elaborated SMARTS strictly requires a carbonyl carbon bonded to exactly two chlorines + 'smarts_1': '[Cl:1]-[CX3:2](=[OX1:3])-[Cl:4]', 'group_name': 'phosgene', 'comments': None, }, From 126dedc82299d0e89398f3871e9d7c18e0d831b6 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 22 Jul 2026 11:59:53 -0400 Subject: [PATCH 068/176] Add polyester polycondensation reaction library --- .../detectors/reactions_library/polyesters.py | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 AutoREACTER/detectors/reactions_library/polyesters.py diff --git a/AutoREACTER/detectors/reactions_library/polyesters.py b/AutoREACTER/detectors/reactions_library/polyesters.py new file mode 100644 index 00000000..c29deb8b --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polyesters.py @@ -0,0 +1,139 @@ +REACTIONS = { + 'Hydroxy Carboxylic Acid Polycondensation(Polyesterification)': + { + 'same_reactants': True, + 'reactant_1': 'hydroxy_carboxylic_acid', + 'product': 'polyester_chain', + 'delete_atom': True, + 'reaction': '[OX2;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[OX2:4]>>[OX2:1]-[CX3:2](=[O:5]).[O:4]-[H:3]', + 'reference': { + 'smarts': 'https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329', + 'reaction_and_mechanism': [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', + 'https://pubs.acs.org/doi/10.1021/ed073pA312' + ] + }, + 'comments': 'Fixed SMARTS to prevent RDKit explicit node valence crashes.' + }, + 'Hydroxy Carboxylic and Hydroxy Carboxylic Polycondensation(Polyesterification)': + { + 'same_reactants': False, + 'reactant_1': 'hydroxy_carboxylic_acid', + 'reactant_2': 'hydroxy_carboxylic_acid', + 'product': 'polyester_chain', + 'delete_atom': True, + 'reaction': '[OX2;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[OX2:4]>>[OX2:1]-[CX3:2](=[O:5]).[O:4]-[H:3]', + 'reference': { + 'smarts': 'https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329', + 'reaction_and_mechanism': [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', + 'https://pubs.acs.org/doi/10.1021/ed073pA312' + ] + }, + 'comments': 'Fixed SMARTS to prevent RDKit explicit node valence crashes.' + }, + 'Hydroxy Acid Halides Polycondensation(Polyesterification)': + { + 'same_reactants': True, + 'reactant_1': 'hydroxy_acid_halide', + 'product': 'polyester_chain', + 'delete_atom': True, + 'reaction': '[OX2;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[Cl,Br,I:4]>>[OX2:1]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:3]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': ['https://pubs.acs.org/doi/10.1021/ed073pA312'] + }, + 'comments': 'Fixed SMARTS to prevent RDKit explicit node valence crashes.' + }, + 'Hydroxy Acid Halides Hydroxy Acid Halides Polycondensation(Polyesterification)': + { + 'same_reactants': False, + 'reactant_1': 'hydroxy_acid_halide', + 'reactant_2': 'hydroxy_acid_halide', + 'product': 'polyester_chain', + 'delete_atom': True, + 'reaction': '[OX2;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[Cl,Br,I:4]>>[OX2:1]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:3]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': ['https://pubs.acs.org/doi/10.1021/ed073pA312'] + }, + 'comments': 'Fixed SMARTS to prevent RDKit explicit node valence crashes.' + }, + 'Diol and Di-Carboxylic Acid Polycondensation(Polyesterification)': + { + 'same_reactants': False, + 'reactant_1': 'diol', + 'reactant_2': 'di_carboxylic_acid', + 'product': 'polyester_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[OX2:4].[OX2;!$([O][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[OX2:2].[O:4]-[H:5]', + 'reference': { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', + 'https://pubs.acs.org/doi/10.1021/ed073pA312' + ] + }, + 'comments': 'Fixed SMARTS to prevent RDKit explicit node valence crashes.' + }, + 'Diol and Di-Acid Halide Polycondensation(Polyesterification)': + { + 'same_reactants': False, + 'reactant_1': 'diol', + 'reactant_2': 'di_carboxylic_acid_halide', + 'product': 'polyester_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[OX2;!$([O][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[OX2:2].[Cl,Br,I:4]-[H:5]', + 'reference': { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', + 'https://pubs.acs.org/doi/10.1021/ed073pA312' + ] + }, + 'comments': 'Fixed SMARTS to prevent RDKit explicit node valence crashes.' + }, + 'Diol and Di-Carboxylic Ester Polycondensation(Transesterification)': + { + 'same_reactants': False, + 'reactant_1': 'diol', + 'reactant_2': 'di_carboxylic_ester', + 'product': 'polyester_chain', + 'delete_atom': True, + 'reaction': '[OX2;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[OX2:4][#6:6]>>[OX2:1]-[CX3:2](=[O:5]).[OX2:4](-[H:3])-[#6:6]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + }, + # Skipped for later additinos after proper validations + # 'Lactone Ring-Opening Polyesterification': + # { + # 'same_reactants': False, + # 'reactant_1': 'lactone', + # 'reactant_2': 'lactone_initiator', + # 'product': 'polyester_chain', + # 'delete_atom': False, + # 'reaction': '[OX2:1]-[H:2].[CX3:3]1(=[OX1:4])-[CX4:6]-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[OX2:5]1>>[OX2:1]-[CX3:3](=[OX1:4])-[CX4:6]-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[OX2:5]-[H:2]', + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # 'comments': None + # }, + # 'Cyclic Anhydride and Epoxide Polyesterification': + # { + # 'same_reactants': False, + # 'reactant_1': 'cyclic_anhydride', + # 'reactant_2': 'epoxide', + # 'product': 'polyester_chain', + # 'delete_atom': False, + # 'reaction': '[CX3:1]1(=[OX1:2])-[OX2:3]-[CX3:4](=[OX1:5])-[CX4:9]-[CX4:10]1.[CX4:6]2-[OX2:7]-[CX4:8]2>>[CX3:1](=[OX1:2])-[OX2:7]-[CX4:6]-[CX4:8]-[OX2:3]-[CX3:4](=[OX1:5])-[CX4:9]-[CX4:10]', + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # 'comments': None + # } +} \ No newline at end of file From 0f8f49c8a6f9f4bd8720d3c81c35beb69d1df361 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 22 Jul 2026 16:31:33 -0400 Subject: [PATCH 069/176] Add polysiloxane reactions, disable draft modules --- .../detectors/reactions_library/polyethers.py | 92 +++++++++++++++++++ .../detectors/reactions_library/polyimides.py | 18 ++++ .../reactions_library/polysiloxanes.py | 46 ++++++++++ .../detectors/reactions_library/registry.py | 10 +- 4 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 AutoREACTER/detectors/reactions_library/polyethers.py create mode 100644 AutoREACTER/detectors/reactions_library/polyimides.py create mode 100644 AutoREACTER/detectors/reactions_library/polysiloxanes.py diff --git a/AutoREACTER/detectors/reactions_library/polyethers.py b/AutoREACTER/detectors/reactions_library/polyethers.py new file mode 100644 index 00000000..b0c24d18 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polyethers.py @@ -0,0 +1,92 @@ + +# REACTIONS = { +# 'Epoxide Ring-Opening Polyetherification': +# { +# 'same_reactants': False, +# 'reactant_1': 'epoxide', +# 'reactant_2': 'initiator', +# 'product': 'polyether_chain', +# 'delete_atom': False, +# 'reaction': '[OX2H1:1]-[H:2].[CX4:3]1[OX2:4][CX4:5]1>>[OX2:1]-[CX4:3]-[CX4:5]-[OX2:4]-[H:2]', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# }, +# 'Cyclic Anhydride and Epoxide Polyetherification': +# { +# 'same_reactants': False, +# 'reactant_1': 'cyclic_anhydride', +# 'reactant_2': 'epoxide', +# 'product': 'polyester_chain', +# 'delete_atom': False, +# 'reaction': '[CX3;R:1](=[OX1:2])[OX2;R:3][CX3;R:4](=[OX1:5]).[CX4:6]1[OX2:7][CX4:8]1>>[CX3:1](=[OX1:2])-[OX2:7]-[CX4:8]-[CX4:6]-[OX2:3]-[CX3:4](=[OX1:5])', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# }, +# 'Hindered Phenol Polyetherification': +# { +# 'same_reactants': True, +# 'reactant_1': 'hindered_phenol', +# 'product': 'polyether_chain', +# 'delete_atom': False, +# 'reaction': '[c:1]-[OX2H1:2]-[H:5].[cH1:3]-[H:4]>>[c:1]-[OX2:2]-[c:3].[H:4]-[H:5]', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# }, +# 'Hindered Phenol Hindered Phenol Polyetherification': +# { +# 'same_reactants': False, +# 'reactant_1': 'hindered_phenol', +# 'reactant_2': 'hindered_phenol', +# 'product': 'polyether_chain', +# 'delete_atom': False, +# 'reaction': '[c:1]-[OX2H1:2]-[H:5].[cH1:3]-[H:4]>>[c:1]-[OX2:2]-[c:3].[H:4]-[H:5]', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# }, +# 'Bis(p-halogenatedaryl)sulfone Diol (without thiol) polycondensation': +# { +# 'same_reactants': False, +# 'reactant_1': 'bis(p-halogenatedaryl)sulfone', +# 'reactant_2': 'diol', +# 'product': 'polyether_chain', +# 'delete_atom': True, +# 'reaction': '[c:1]([F,Cl,Br,I:3]).[OX2H1:2]-[H:4]>>[c:1]-[OX2:2].[F,Cl,Br,I:3]-[H:4]', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# }, +# 'Bis(bis(p-fluoroaryl)ketone Diol (without thiol) polycondensation': +# { +# 'same_reactants': False, +# 'reactant_1': 'bis(p-fluoroaryl)ketone_monomer', +# 'reactant_2': 'diol', +# 'product': 'polyether_chain', +# 'delete_atom': True, +# 'reaction': '[c:1]([F:3]).[OX2H1:2]-[H:4]>>[c:1]-[OX2:2].[F:3]-[H:4]', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# } +# } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polyimides.py b/AutoREACTER/detectors/reactions_library/polyimides.py new file mode 100644 index 00000000..d3176ea6 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polyimides.py @@ -0,0 +1,18 @@ +# This reaction also needs to further studied and validated +# REACTIONS = { +# 'Di-cyclic Anhydride and Di-Primary Amine Polycondensation (Polyimidation)': +# { +# 'same_reactants': False, +# 'reactant_1': 'di_cyclic_anhydride', +# 'reactant_2': 'di_primary_amine', +# 'product': 'polyimide_chain', +# 'delete_atom': True, +# 'reaction': '[NX3H2:1](-[H:6])-[H:8].[CX3;R:2](=[OX1:4])[OX2;R:5][CX3;R:3](=[OX1:7])>>[NX3:1]([CX3:2](=[OX1:4]))[CX3:3](=[OX1:7]).[OX2:5](-[H:6])-[H:8]', +# 'reference': +# { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# } +# } diff --git a/AutoREACTER/detectors/reactions_library/polysiloxanes.py b/AutoREACTER/detectors/reactions_library/polysiloxanes.py new file mode 100644 index 00000000..4afe7f3c --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polysiloxanes.py @@ -0,0 +1,46 @@ +REACTIONS = { + 'Dichlorosilane Hydrolysis to Silanol': + { + 'same_reactants': False, + 'reactant_1': 'dichlorosilane', + 'reactant_2': 'water', + 'product': 'silanediol', + 'delete_atom': True, + 'reaction': '[Si:1]-[Cl:2].[OX2H2:3](-[H:4])-[H:5]>>[Si:1]-[OX2:3]-[H:4].[Cl:2]-[H:5]', + 'reference': + { + 'smarts': None, + 'reaction_and_mechanism': None + }, + "Note": "Tested, but LUNAR cannot parameterize silicone chemistry" + }, + 'Silanediol Polycondensation(Polysiloxane Formation)': + { + 'same_reactants': True, + 'reactant_1': 'silanediol', + 'product': 'polysiloxane_chain', + 'delete_atom': True, + 'reaction': '[Si:1]-[OX2H1:2]-[H:5].[Si:3]-[OX2H1:4]-[H:6]>>[Si:1]-[OX2:2]-[Si:3].[OX2:4](-[H:5])-[H:6]', + 'reference': + { + 'smarts': None, + 'reaction_and_mechanism': None + }, + "Note": "Tested, but LUNAR cannot parameterize silicone chemistry" + }, + 'Silanediol and Silanediol Copolycondensation(Polysiloxane Formation)': + { + 'same_reactants': False, + 'reactant_1': 'silanediol', + 'reactant_2': 'silanediol', + 'product': 'polysiloxane_chain', + 'delete_atom': True, + 'reaction': '[Si:1]-[OX2H1:2]-[H:5].[Si:3]-[OX2H1:4]-[H:6]>>[Si:1]-[OX2:2]-[Si:3].[OX2:4](-[H:5])-[H:6]', + 'reference': + { + 'smarts': None, + 'reaction_and_mechanism': None + }, + "Note": "Tested, but LUNAR cannot parameterize silicone chemistry" + } +} diff --git a/AutoREACTER/detectors/reactions_library/registry.py b/AutoREACTER/detectors/reactions_library/registry.py index 81f589ab..15ba12c5 100644 --- a/AutoREACTER/detectors/reactions_library/registry.py +++ b/AutoREACTER/detectors/reactions_library/registry.py @@ -1,7 +1,7 @@ """Aggregate and validate all polymer-family reaction modules.""" from .polyesters import REACTIONS as POLYESTERS -from .polyethers import REACTIONS as POLYETHERS +# from .polyethers import REACTIONS as POLYETHERS from .polyamides import REACTIONS as POLYAMIDES from .polyanhydrides import REACTIONS as POLYANHYDRIDES from .polythioesters import REACTIONS as POLYTHIOESTERS @@ -10,7 +10,7 @@ from .epoxy_polymers import REACTIONS as EPOXY_POLYMERS from .vinyl_polymers import REACTIONS as VINYL_POLYMERS from .polycarbonates import REACTIONS as POLYCARBONATES -from .polyimides import REACTIONS as POLYIMIDES +# from .polyimides import REACTIONS as POLYIMIDES # from .polybenzimidazoles import REACTIONS as POLYBENZIMIDAZOLES # from .phenolic_resins import REACTIONS as PHENOLIC_RESINS from .polysiloxanes import REACTIONS as POLYSILOXANES @@ -21,7 +21,7 @@ _REACTION_MODULES = [ POLYESTERS, - POLYETHERS, + # POLYETHERS, POLYAMIDES, POLYANHYDRIDES, POLYTHIOESTERS, @@ -30,8 +30,8 @@ EPOXY_POLYMERS, VINYL_POLYMERS, POLYCARBONATES, - POLYIMIDES, - #POLYBENZIMIDAZOLES, + # POLYIMIDES, + # POLYBENZIMIDAZOLES, # PHENOLIC_RESINS, POLYSILOXANES, POLYSULFIDES, From 9f82c8d3a7124f3f355a2eb7b01a39e7894923dc Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:24:52 -0400 Subject: [PATCH 070/176] Disable untested halide and polysulfide entries Comments out halide functional-group registration and polysulfide reaction registration so untested chemistry is not loaded by default. Adds a new `polysulfides.py` scaffold with the planned reaction definition kept fully commented for future activation once validated. --- .../functional_groups_library/registry.py | 4 ++-- .../detectors/reactions_library/polysulfides.py | 17 +++++++++++++++++ .../detectors/reactions_library/registry.py | 4 ++-- 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 AutoREACTER/detectors/reactions_library/polysulfides.py diff --git a/AutoREACTER/detectors/functional_groups_library/registry.py b/AutoREACTER/detectors/functional_groups_library/registry.py index fc7e2075..79d3a7d6 100644 --- a/AutoREACTER/detectors/functional_groups_library/registry.py +++ b/AutoREACTER/detectors/functional_groups_library/registry.py @@ -9,7 +9,7 @@ from .vinyl_and_alkene_groups import FUNCTIONAL_GROUPS as VINYL_AND_ALKENE_GROUPS from .aromatic_groups import FUNCTIONAL_GROUPS as AROMATIC_GROUPS from .silicon_groups import FUNCTIONAL_GROUPS as SILICON_GROUPS -from .halide_groups import FUNCTIONAL_GROUPS as HALIDE_GROUPS +# from .halide_groups import FUNCTIONAL_GROUPS as HALIDE_GROUPS from .heterocumulene_groups import FUNCTIONAL_GROUPS as HETEROCUMULENE_GROUPS from .active_centers import FUNCTIONAL_GROUPS as ACTIVE_CENTERS @@ -23,7 +23,7 @@ VINYL_AND_ALKENE_GROUPS, AROMATIC_GROUPS, SILICON_GROUPS, - HALIDE_GROUPS, + # HALIDE_GROUPS, HETEROCUMULENE_GROUPS, ACTIVE_CENTERS, ] diff --git a/AutoREACTER/detectors/reactions_library/polysulfides.py b/AutoREACTER/detectors/reactions_library/polysulfides.py new file mode 100644 index 00000000..65732c0f --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polysulfides.py @@ -0,0 +1,17 @@ +# Polysulfide formation reactions are currently commented out as they are untested. +# REACTIONS = { +# 'Organic Dihalide and Sodium Sulfide Polycondensation(Polysulfide Formation)': +# { +# 'same_reactants': False, +# 'reactant_1': 'organic_dihalide', +# 'reactant_2': 'sodium_sulfide', +# 'product': 'polysulfide_chain', +# 'delete_atom': True, +# 'reaction': '[CX4:1]-[Cl,Br,I:2].[S-2:3].[Na+:4].[Na+:5]>>[CX4:1]-[S-:3].[Cl-,Br-,I-:2].[Na+:4].[Na+:5]', +# 'reference': {'smarts': None, +# 'reaction_and_mechanism': None}, +# 'comments': 'UNTESTED new chemistry; ' +# 'one substitution event ' +# 'leaves a thiolate chain ' +# 'end for continued ' +# 'growth.'}} diff --git a/AutoREACTER/detectors/reactions_library/registry.py b/AutoREACTER/detectors/reactions_library/registry.py index 15ba12c5..30eb35ba 100644 --- a/AutoREACTER/detectors/reactions_library/registry.py +++ b/AutoREACTER/detectors/reactions_library/registry.py @@ -14,7 +14,7 @@ # from .polybenzimidazoles import REACTIONS as POLYBENZIMIDAZOLES # from .phenolic_resins import REACTIONS as PHENOLIC_RESINS from .polysiloxanes import REACTIONS as POLYSILOXANES -from .polysulfides import REACTIONS as POLYSULFIDES +# from .polysulfides import REACTIONS as POLYSULFIDES from .thiol_ene_polymers import REACTIONS as THIOL_ENE_POLYMERS # from .metathesis_polymers import REACTIONS as METATHESIS_POLYMERS # from .cycloaddition_polymers import REACTIONS as CYCLOADDITION_POLYMERS @@ -34,7 +34,7 @@ # POLYBENZIMIDAZOLES, # PHENOLIC_RESINS, POLYSILOXANES, - POLYSULFIDES, + # POLYSULFIDES, THIOL_ENE_POLYMERS, # METATHESIS_POLYMERS, # CYCLOADDITION_POLYMERS, From ead2824156743c4eb86f8341162a73aec56fb976 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:25:05 -0400 Subject: [PATCH 071/176] Add polythioester reaction library entries --- .../reactions_library/polythioesters.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 AutoREACTER/detectors/reactions_library/polythioesters.py diff --git a/AutoREACTER/detectors/reactions_library/polythioesters.py b/AutoREACTER/detectors/reactions_library/polythioesters.py new file mode 100644 index 00000000..43dd6dc3 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polythioesters.py @@ -0,0 +1,57 @@ +REACTIONS = { + 'Dithiol and Di-Carboxylic Acid Halide Polycondensation(Polythioesterification)': { + 'same_reactants': False, + 'reactant_1': 'dithiol', + 'reactant_2': 'di_carboxylic_acid_halide', + 'product': 'polythioester_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[SX2H1;!$([S][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[SX2:2].[Cl,Br,I:4]-[H:5]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + }, + + 'Dithiol and Di-Carboxylic Acid Polycondensation(Polythioesterification)': { + 'same_reactants': False, + 'reactant_1': 'dithiol', + 'reactant_2': 'di_carboxylic_acid', + 'product': 'polythioester_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[OX2H1:4].[SX2H1;!$([S][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[SX2:2].[O:4]-[H:5]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': 'Possible thioesterification with water elimination, but generally less straightforward than acid-halide route.' + }, + + 'Hydroxy-Thiol and Di-Carboxylic Acid Halide Polycondensation through Hydroxy Group': { + 'same_reactants': False, + 'reactant_1': 'hydroxy_thiol', + 'reactant_2': 'di_carboxylic_acid_halide', + 'product': 'mixed_polyester_polythioester_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[OX2H1;!$([O][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[OX2:2].[Cl,Br,I:4]-[H:5]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + }, + + 'Hydroxy-Thiol and Di-Carboxylic Acid Halide Polycondensation through Thiol Group': { + 'same_reactants': False, + 'reactant_1': 'hydroxy_thiol', + 'reactant_2': 'di_carboxylic_acid_halide', + 'product': 'mixed_polyester_polythioester_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[SX2H1;!$([S][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[SX2:2].[Cl,Br,I:4]-[H:5]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + } +} \ No newline at end of file From 38052b96540187b7bdab24ad986ffa163f8b360a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:31:14 -0400 Subject: [PATCH 072/176] Add functional groups and polyurea reaction --- .../active_centers.py | 21 +++++++++++++++++++ .../halide_groups.py | 8 +++++++ .../sulfur_groups.py | 17 +++++++++++++++ .../detectors/reactions_library/polyureas.py | 15 +++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 AutoREACTER/detectors/functional_groups_library/active_centers.py create mode 100644 AutoREACTER/detectors/functional_groups_library/halide_groups.py create mode 100644 AutoREACTER/detectors/functional_groups_library/sulfur_groups.py create mode 100644 AutoREACTER/detectors/reactions_library/polyureas.py diff --git a/AutoREACTER/detectors/functional_groups_library/active_centers.py b/AutoREACTER/detectors/functional_groups_library/active_centers.py new file mode 100644 index 00000000..f1cf6ad2 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/active_centers.py @@ -0,0 +1,21 @@ +"""Functional-group definitions organized by the active centers motif. + +Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" + +FUNCTIONAL_GROUPS = { + 'vinyl_chain_end_radical': + { + 'functionality_type': 'vinyl', + 'smarts_1': '[C;!R;D3;v3]', + 'group_name': 'vinyl_chain_end_radical', + 'comments': None + }, + # 'romp_alkylidene_motif': + # { + # 'functionality_type': 'mono', + # 'smarts_1': '[Ru]=[C]', + # 'group_name': 'romp_alkylidene', + # 'comments': 'UNTESTED simplified ruthenium alkylidene motif used for both ROMP initiation ' + # 'and propagation. Atom maps 1 and 2 are assigned only in the reaction SMARTS.' + # } + } diff --git a/AutoREACTER/detectors/functional_groups_library/halide_groups.py b/AutoREACTER/detectors/functional_groups_library/halide_groups.py new file mode 100644 index 00000000..a9bcad58 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/halide_groups.py @@ -0,0 +1,8 @@ +# FUNCTIONAL_GROUPS = { +# 'organic_dihalide_monomer': { +# 'functionality_type': 'di_identical', +# 'smarts_1': '[CX4][Cl,Br,I]', +# 'group_name': 'organic_dihalide', +# 'comments': None +# } +# } diff --git a/AutoREACTER/detectors/functional_groups_library/sulfur_groups.py b/AutoREACTER/detectors/functional_groups_library/sulfur_groups.py new file mode 100644 index 00000000..d688600f --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/sulfur_groups.py @@ -0,0 +1,17 @@ +"""Functional-group definitions organized by the sulfur groups motif. + +Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" + +FUNCTIONAL_GROUPS = { + 'dithiol_monomer': + { + 'functionality_type': 'di_identical', + 'smarts_1': '[SX2H1;!$([S][C,S]=*):1]', + 'group_name': 'dithiol', + 'comments': None + }, +# 'sodium_sulfide_monomer': {'functionality_type': 'mono', +# 'smarts_1': '[S-2]', +# 'group_name': 'sodium_sulfide', +# 'comments': 'Sulfide dianion; sodium counterions are included in the reaction SMARTS.'} +} diff --git a/AutoREACTER/detectors/reactions_library/polyureas.py b/AutoREACTER/detectors/reactions_library/polyureas.py new file mode 100644 index 00000000..5b631cde --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polyureas.py @@ -0,0 +1,15 @@ +REACTIONS = { + 'Di-Amine and Di-Isocyanate Polyaddition(Polyurea Formation)': { + 'same_reactants': False, + 'reactant_1': 'di_amine', + 'reactant_2': 'di_isocyanate', + 'product': 'polyurea_chain', + 'delete_atom': False, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[NX2:4]=[CX2:2]=[OX1:5]>>[NX3:1]-[CX3:2](=[OX1:5])-[NX3:4]-[H:3]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + } +} \ No newline at end of file From 49bb79a9780b99d9508812c82bb34cd8a9a3a4b3 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:36:26 -0400 Subject: [PATCH 073/176] Add polyurethanes reactions library module --- .../reactions_library/polyurethanes.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 AutoREACTER/detectors/reactions_library/polyurethanes.py diff --git a/AutoREACTER/detectors/reactions_library/polyurethanes.py b/AutoREACTER/detectors/reactions_library/polyurethanes.py new file mode 100644 index 00000000..d898ef0e --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/polyurethanes.py @@ -0,0 +1,29 @@ +REACTIONS = { + 'Diol and Di-Isocyanate Polyaddition(Polyurethane Formation)': { + 'same_reactants': False, + 'reactant_1': 'diol', + 'reactant_2': 'di_isocyanate', + 'product': 'polyurethane_chain', + 'delete_atom': False, + 'reaction': '[OX2H1;!$([O][C,S]=*):1]-[H:3].[NX2:4]=[CX2:2]=[OX1:5]>>[OX2:1]-[CX3:2](=[OX1:5])-[NX3:4]-[H:3]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + }, + + 'Dithiol and Di-Isocyanate Polyaddition(Polythiourethane Formation)': { + 'same_reactants': False, + 'reactant_1': 'dithiol', + 'reactant_2': 'di_isocyanate', + 'product': 'polythiourethane_chain', + 'delete_atom': False, + 'reaction': '[SX2H1;!$([S][C,S]=*):1]-[H:3].[NX2:4]=[CX2:2]=[OX1:5]>>[SX2:1]-[CX3:2](=[OX1:5])-[NX3:4]-[H:3]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': 'UNTESTED: chemically consistent replacement for the commented entry whose label said epoxide/isocyanate but whose SMARTS was isocyanate + O/S-H.' + } +} \ No newline at end of file From a6fd6a27fca8a11abeed92fde8a17b6603df6d69 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:36:50 -0400 Subject: [PATCH 074/176] Update polyurethanes.py --- AutoREACTER/detectors/reactions_library/polyurethanes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutoREACTER/detectors/reactions_library/polyurethanes.py b/AutoREACTER/detectors/reactions_library/polyurethanes.py index d898ef0e..3d908a6f 100644 --- a/AutoREACTER/detectors/reactions_library/polyurethanes.py +++ b/AutoREACTER/detectors/reactions_library/polyurethanes.py @@ -24,6 +24,6 @@ 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': 'UNTESTED: chemically consistent replacement for the commented entry whose label said epoxide/isocyanate but whose SMARTS was isocyanate + O/S-H.' + 'comments': None } } \ No newline at end of file From c4de1ed60702b9a97787ffd749b9918f4bd8dc46 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 12:15:55 -0400 Subject: [PATCH 075/176] Improve embedding for congested polymers --- .../ff_wrapper/molecule_3d_preparation.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/molecule_3d_preparation.py b/AutoREACTER/reaction_preparation/ff_wrapper/molecule_3d_preparation.py index 648d9b06..a9316f97 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/molecule_3d_preparation.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/molecule_3d_preparation.py @@ -239,6 +239,13 @@ def _optimization( params = AllChem.ETKDGv3() params.randomSeed = 0xF00D + + # --- ADDED PARAMETERS FOR STERICALLY CONGESTED POLYMERS --- + # Use random coordinates for large, flexible, or dense macro-structures + params.useRandomCoords = True + # Force RDKit to output a structure even if the distance bounds aren't perfectly smoothed + params.ignoreSmoothingFailures = True + # ---------------------------------------------------------- embed_result = AllChem.EmbedMolecule(mol, params) From 29da8c967ca531fc31c6c2e4f80f1f2248b994ef Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 12:16:35 -0400 Subject: [PATCH 076/176] Add vinyl polymer reaction library definitions --- .../reactions_library/vinyl_polymers.py | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 AutoREACTER/detectors/reactions_library/vinyl_polymers.py diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py new file mode 100644 index 00000000..bca2d62f --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -0,0 +1,79 @@ +REACTIONS = { + 'Vinyl Addition Polymerization Initiation': { + 'same_reactants': True, + 'reactant_1': 'vinyl', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + 'reaction': '[CH2:1]=[C;!R:3].[CH2:2]=[C;!R:4]>>[CH2:1](-[C:3])-[CH2:2]-[C:4]', + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None + }, + 'Vinyl Addition Polymerization Propagation': { + 'same_reactants': False, + 'reactant_1': 'vinyl', + 'reactant_2': 'vinyl_chain_end_radical', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + 'reaction': '[CH2:2]=[C;!R:3].[C;!R;D3;v3:1]>>[C:1]-[CH2:2]-[C:3]', + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None + }, + # 'Vinyl Radical Coupling Termination': { + # 'same_reactants': True, + # 'reactant_1': 'vinyl_chain_end_radical', + # 'product': 'vinyl_terminated_chain', + # 'delete_atom': False, + # 'reaction': '[C;!R;D3;v3;+0:1].[C;!R;D3;v3;+0:2]>>[C:1]-[C:2]', + # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # 'comments': None + # }, + # 'Vinyl Addition Polymerization': { + # 'same_reactants': True, + # 'reactant_1': 'vinyl', + # 'product': 'polyvinyl_chain', + # 'delete_atom': False, + # 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', + # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # 'comments': None + # }, + 'Vinyl Copolymerization': { + 'same_reactants': False, + 'reactant_1': 'vinyl', + 'reactant_2': 'vinyl', + 'product': 'copolyvinyl_chain', + 'delete_atom': False, + 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None + }, + # Later Implementation + # 'Cyclic Olefin Addition Polymerization': { + # 'same_reactants': True, + # 'reactant_1': 'cyclic_olefin', + # 'product': 'polycyclic_chain', + # 'delete_atom': False, + # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', + # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # 'comments': None + # }, + # 'Cyclic Olefin and Vinyl Copolymerization': { + # 'same_reactants': False, + # 'reactant_1': 'vinyl', + # 'reactant_2': 'cyclic_olefin', + # 'product': 'copolycyclicvinyl_chain', + # 'delete_atom': False, + # 'reaction': '[CH2:1]=[C;!R:2].[C;R:3]=[C;R:4]>>[C:1]-[C:2]-[C:3]-[C:4]', + # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # 'comments': None + # }, + # 'Cyclic Olefin Copolymerization': { + # 'same_reactants': False, + # 'reactant_1': 'cyclic_olefin', + # 'reactant_2': 'cyclic_olefin', + # 'product': 'copolycyclic_chain', + # 'delete_atom': False, + # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', + # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # 'comments': None + # } +} \ No newline at end of file From b12183f9539ac7cc14b1dd0f209744625775d9da Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 12:51:29 -0400 Subject: [PATCH 077/176] Add new functional group library modules --- .../heterocumulene_groups.py | 11 ++++++++ .../oxygen_groups.py | 27 +++++++++++++++++++ .../vinyl_and_alkene_groups.py | 24 +++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 AutoREACTER/detectors/functional_groups_library/heterocumulene_groups.py create mode 100644 AutoREACTER/detectors/functional_groups_library/oxygen_groups.py create mode 100644 AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py diff --git a/AutoREACTER/detectors/functional_groups_library/heterocumulene_groups.py b/AutoREACTER/detectors/functional_groups_library/heterocumulene_groups.py new file mode 100644 index 00000000..1730c037 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/heterocumulene_groups.py @@ -0,0 +1,11 @@ + + +FUNCTIONAL_GROUPS = { + 'di_isocyanate_monomer': + { + 'functionality_type': 'di_identical', + 'smarts_1': '[NX2]=[CX2:1]=[OX1]', + 'group_name': 'di_isocyanate', + 'comments': None + } + } diff --git a/AutoREACTER/detectors/functional_groups_library/oxygen_groups.py b/AutoREACTER/detectors/functional_groups_library/oxygen_groups.py new file mode 100644 index 00000000..0fa3a941 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/oxygen_groups.py @@ -0,0 +1,27 @@ +"""Functional-group definitions organized by the oxygen groups motif. + +Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" + +FUNCTIONAL_GROUPS = { + 'diol_monomer': + { + 'functionality_type': 'di_identical', + 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', + 'group_name': 'diol', + 'comments': None + }, + # 'initiator_monomer': + # { + # 'functionality_type': 'mono', + # 'smarts_1': '[OX2H1;!$([O][C,S]=*)]', + # 'group_name': 'lactone_initiator', + # 'comments': None, + # }, + 'water_monomer': + { + 'functionality_type': 'mono', + 'smarts_1': '[OH2:1]', + 'group_name': 'water', + 'comments': None + } +} diff --git a/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py b/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py new file mode 100644 index 00000000..b76eb3ca --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py @@ -0,0 +1,24 @@ +"""Functional-group definitions organized by the vinyl and alkene groups motif. + +Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" + +FUNCTIONAL_GROUPS = { + 'vinyl_monomer': + { + 'functionality_type': 'vinyl', + 'smarts_1': '[CH2]=[C;!R]', + 'group_name': 'vinyl', + 'comments': None + }, + 'diene_monomer': + { + 'functionality_type': 'di_identical', + 'smarts_1': '[CH2]=[C;!R]', + 'group_name': 'diene', + 'comments': None + }, +} +# 'bis_alkene_monomer': {'functionality_type': 'di_identical', +# 'smarts_1': '[C]=[C]', +# 'group_name': 'bis_alkene', +# 'comments': 'One alkene site; a bis-alkene supplies two identical matches.'}} From f49b0c3a89e8c0da6cb2d434859c0e4f196ebd7a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:09:37 -0400 Subject: [PATCH 078/176] Refactor reaction libraries into package modules --- .../detectors/functional_groups_library.py | 290 --------- AutoREACTER/detectors/reaction_detector.py | 2 +- AutoREACTER/detectors/reactions_library.py | 566 ------------------ 3 files changed, 1 insertion(+), 857 deletions(-) delete mode 100644 AutoREACTER/detectors/functional_groups_library.py delete mode 100644 AutoREACTER/detectors/reactions_library.py diff --git a/AutoREACTER/detectors/functional_groups_library.py b/AutoREACTER/detectors/functional_groups_library.py deleted file mode 100644 index 92e00616..00000000 --- a/AutoREACTER/detectors/functional_groups_library.py +++ /dev/null @@ -1,290 +0,0 @@ -""" -Functional group library for epoxy polymerization chemistry. - -This library focuses on monomers and curing-agent functional groups relevant to -epoxy polymerization / epoxy curing systems. It includes epoxides and common -epoxy-reactive groups such as primary amines, secondary amines, thiols, alcohols, -carboxylic acids, and cyclic anhydrides. - -Each entry defines: - - functionality_type: - "mono" : one reactive functional group - "di_identical" : two identical reactive functional groups - "di_different" : two different reactive functional groups - - - smarts_1 / smarts_2: - SMARTS patterns used for substructure matching - - - group_name: - functional group label used by the detector - - - comments: - optional chemistry notes -""" - - - -class FunctionalGroupsLibrary: - def __init__(self): - self.monomer_types = { - - # ============================================================ - # Hydroxy / Carboxylic Acid AB-Type Monomers - # ============================================================ - - "hydroxy_carboxylic_acid_monomer": { - "functionality_type": "di_different", - "smarts_1": "[OX2H1;!$([O][C,S]=*):1]", - "smarts_2": "[CX3:2](=[O])[OX2H1]", - "group_name": "hydroxy_carboxylic_acid", - "comments": None, - }, - - "hydroxy_acid_halides_monomer": { - "functionality_type": "di_different", - "smarts_1": "[OX2H1;!$([O][C,S]=*):1]", - "smarts_2": "[CX3:2](=[O])[Cl,Br,I]", - "group_name": "hydroxy_acid_halide", - "comments": "Hydroxy acid halides are highly reactive and less commonly used monomers for polyesterification compared to hydroxy carboxylic acids." - }, - - # ============================================================ - # Alcohol / Thiol Functional Monomers - # ============================================================ - - "diol_monomer": { - "functionality_type": "di_identical", - "smarts_1": "[OX2H1;!$([O][C,S]=*):1]", - "group_name": "diol", - "comments": None, - }, - - "dithiol_monomer": { - "functionality_type": "di_identical", - "smarts_1": "[SX2H1;!$([S][C,S]=*):1]", - "group_name": "dithiol", - "comments": None, - }, - - "hydroxy_thiol_monomer": { - "functionality_type": "di_different", - "smarts_1": "[OX2H1;!$([O][C,S]=*):1]", - "smarts_2": "[SX2H1;!$([S][C,S]=*):2]", - "group_name": "hydroxy_thiol", - "comments": None, - }, - - # ============================================================ - # Amine / Amino Acid Monomers - # ============================================================ - - "amino_acid_monomer": { - "functionality_type": "di_different", - "smarts_1": "[NX3;H2,H1;!$([N][C,S]=*):1]", - "smarts_2": "[CX3:2](=[O])[OX2H1]", - "group_name": "amino_acid", - "comments": None, - }, - - "di_amine_monomer": { - "functionality_type": "di_identical", - "smarts_1": "[NX3;H2,H1;!$([N][C,S]=*):1]", - "group_name": "di_amine", - "comments": None, - }, - - # ============================================================ - # Carboxylic Acid / Acid Halide / Ester Monomers - # ============================================================ - - "di_carboxylic_acid_monomer": { - "functionality_type": "di_identical", - "smarts_1": "[CX3:1](=[O])[OX2H1]", - "group_name": "di_carboxylic_acid", - "comments": None, - }, - - "di_carboxylic_acid_halide_monomer": { - "functionality_type": "di_identical", - "smarts_1": "[CX3:1](=[O])[Cl,Br,I]", - "group_name": "di_carboxylic_acid_halide", - "comments": None, - }, - - "carboxylic_acid_acid_halide_monomer": { - "functionality_type": "di_different", - "smarts_1": "[CX3:1](=[O])[OX2H1]", - "smarts_2": "[CX3:2](=[O])[Cl,Br,I]", - "group_name": "carboxylic_acid_acid_halide", - "comments": "Mixed COOH/acid-halide AB monomer. Edge case; forms polyanhydride-type linkage, not polyester.", - }, - - "di_carboxylic_ester_monomer": { - "functionality_type": "di_identical", - "smarts_1": "[CX3:1](=[O])[OX2H0][#6]", - "group_name": "di_carboxylic_ester", - "comments": None, - }, - - # ============================================================ - # Isocyanate Monomers - # ============================================================ - - "di_isocyanate_monomer": { - "functionality_type": "di_identical", - "smarts_1": "[NX2]=[CX2:1]=[OX1]", - "group_name": "di_isocyanate", - "comments": None, - }, - - # ============================================================ - # Epoxy / Amine Functional Monomers - # Relevant for epoxy-amine polymerization - # - # Polymer-forming epoxy monomer: - # must contain two epoxide groups, i.e. diepoxy - # - # Primary monoamine: - # one -NH2 group has two active hydrogens - # can react with two epoxide groups in two stages - # - # Stage 1: - # primary amine + epoxide -> secondary amine - # - # Stage 2: - # secondary amine + epoxide -> tertiary amine - # ============================================================ - - "di_epoxy_monomer": { - "functionality_type": "di_identical", - "smarts_1": "[CX4;R1]1[OX2;R1][CX4;R1]1", - "group_name": "di_epoxide", - "comments": None, - }, - - "primary_amine_monomer": { - "functionality_type": "mono", - "smarts_1": "[NX3H2;!$(NC=O);!$(NC=[N,O,S])]", - "group_name": "primary_amine", - "comments": None, - }, - - "secondary_amine_monomer": { - "functionality_type": "mono", - "smarts_1": "[NX3H1;!$(NC=O);!$(NC=[N,O,S])]", - "group_name": "secondary_amine", - "comments": None, - }, - # ============================================================ - # Vinyl Addition Polymerization - # ============================================================ - - "vinyl_monomer": { - "functionality_type": "vinyl", - "smarts_1": "[CH2]=[C;!R]", - "group_name": "vinyl", - "comments": None, - }, - - "vinyl_chain_end_radical": { - "functionality_type": "vinyl", - "smarts_1": "[C;!R;D3;v3]", - "group_name": "vinyl_chain_end_radical", - "comments": ( - "Neutral non-ring carbon-centered radical with degree 3 and " - "valence 3. Supports primary, secondary, and tertiary vinyl " - "polymer chain ends." - ), - }, - - # ============================================================ - # Commented functional groups - # ============================================================ - - # ------------------------------------------------------------ - # Cyclic Anhydride / Epoxide Functional Groups - # ------------------------------------------------------------ - - # "di_cyclic_anhydride_monomer": { - # "functionality_type": "di_identical", - # "smarts_1": "[CX3,c;R:1](=[OX1])[OX2,o;R][CX3,c;R:2](=[OX1])", - # "group_name": "di_cyclic_anhydride" - # }, - - # "di_epoxide_monomer": { - # "functionality_type": "di_identical", - # "smarts_1": "[CX4;H2,H1,H0;R:1]1[OX2;R:2][CX4;H1,H0;R:3]1", - # "group_name": "di_epoxide" - # }, - - # ------------------------------------------------------------ - # Vinyl / Olefin Functional Groups - # ------------------------------------------------------------ - - # "vinyl_monomer": { - # "functionality_type": "vinyl", - # "smarts_1": "[C]=[C;D1]", - # "group_name": "vinyl" - # }, - - # "cyclic_olefin_monomer": { - # "functionality_type": "vinyl", - # "smarts_1": "[CX3;R:1]=[CX3;R:2]", - # "group_name": "cyclic_olefin" - # }, - - # ------------------------------------------------------------ - # Ring-Opening Functional Groups - # ------------------------------------------------------------ - - # "lactone_monomer": { - # "functionality_type": "mono", - # "smarts_1": "[CX3;R:1](=[OX1])[OX2;R:2]", - # "group_name": "lactone" - # }, - - # "cyclic_anhydride_monomer": { - # "functionality_type": "mono", - # "smarts_1": "[C,c;R:1][CX3,c;R](=[OX1])[OX2,o;R][CX3,c;R](=[OX1])[C,c;R:2]", - # "group_name": "cyclic_anhydride" - # }, - - # "epoxide_monomer": { - # "functionality_type": "mono", - # "smarts_1": "[CX4;R:3]1[OX2;R:4][CX4;R:5]1", - # "group_name": "epoxide" - # }, - - # "lactam_monomer": { - # "functionality_type": "mono", - } # "smarts_1": "[CX3;R:1](=[OX1])[NX3;R:2]", - # "group_name": "lactam" - # }, - # "di_amine_monomer": { - # "functionality_type": "di_identical", - # "smarts_1": "[N&X3;H2,H1;!$(NC=*):3]", - - # "group_name": "di_amine" - # }, - # "primery_di_amine_monomer": { - # "functionality_type": "di_identical", - # "smarts_1": "[C,c:6][NX3;H2;!$(N[C,S]=*)]", - # "group_name": "di_primery_amine" - # }, - # "di_cyclic_anhydride_monomer": { - # "functionality_type": "di_identical", - # "smarts_1": "[CX3,c;R:1](=[OX1])[OX2,o;R][CX3,c;R:2](=[OX1])", - # "group_name": "di_cyclic_anhydride" - # }, - # "di_isocyanate_monomer": { - # "functionality_type": "di_identical", - # "smarts_1": "[NX2:1]=[CX2]=[OX1,SX1:2]", - # "group_name": "di_isocyanate" - # }, - # "di_epoxide_monomer": { - # "functionality_type": "di_identical", - # "smarts_1": "[CX4;H2,H1,H0;R:1]1[OX2;R:2][CX4;H1,H0;R:3]1", - # "group_name": "di_epoxide" - # } - # need to add more functional groups here from "J. Chem. Inf. Model. 2023, 63, 5539−5548" - # is there monomers with both COCl and COOH groups? diff --git a/AutoREACTER/detectors/reaction_detector.py b/AutoREACTER/detectors/reaction_detector.py index 73b6911a..1bfe070c 100644 --- a/AutoREACTER/detectors/reaction_detector.py +++ b/AutoREACTER/detectors/reaction_detector.py @@ -42,7 +42,7 @@ # Attempt to import internal library components try: - from reactions_library import ReactionLibrary + from AutoREACTER.detectors.reactions_library.registry import ReactionLibrary except (ImportError, ModuleNotFoundError): from .reactions_library import ReactionLibrary diff --git a/AutoREACTER/detectors/reactions_library.py b/AutoREACTER/detectors/reactions_library.py deleted file mode 100644 index 67a67396..00000000 --- a/AutoREACTER/detectors/reactions_library.py +++ /dev/null @@ -1,566 +0,0 @@ -import json -from typing import Dict, Any - - -""" -TODO: Missing Polymerization Mechanisms - -Step-Growth Condensation / Addition -- Polycarbonates: Diols + Phosgene or Diphenyl Carbonate -- Polyureas: Diamines + Diisocyanates -- Aromatic Polyimides: Dianhydrides + Diamines -- Polybenzimidazoles (PBI): Tetraamines + Dicarboxylates -- Phenol-Formaldehyde (Bakelite): Phenol + Formaldehyde - -Aromatic / High-Performance Polymers -- Aromatic Polyethers (PEEK/Sulfones): Activated dihalides + Bisphenols -- Spiro Polymers - -Sulfur / Silicon-Based Polymers -- Polysiloxanes (Silicones): Hydrolysis/Condensation of Dichlorosilanes -- Polysulfides: Dihalides + Sodium Sulfide - -Click / Ring-Opening / Metathesis Polymerizations -- Thiol-Ene Click Polymerizations -- Ring-Opening Metathesis Polymerization (ROMP) -- Cycloaddition (Four-Center) Reactions - -Architectural / Supramolecular Polymers -- Dendritic Polymers: Random Hyperbranched and Dendrimers -- Pseudopolyrotaxanes and Polyrotaxanes - -Special Polymerization Environments -- Enzymatic Polymerizations: In Vivo / In Vitro biocatalysis -- Polymerization in Supercritical Carbon Dioxide -- Thiophene Polymerizations: Oxidative Polymerization of Thiophenes -""" - -class ReactionLibrary: - def __init__(self): - self.reactions = { - - # ============================================================ - # Polyesterification: Hydroxy Acids / Acid Halides - # ============================================================ - - "Hydroxy Carboxylic Acid Polycondensation(Polyesterification)": { - "same_reactants": True, - "reactant_1": "hydroxy_carboxylic_acid", - "product": "polyester_chain", - "delete_atom": True, - "reaction": "[OX2H1;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[OX2H1:4]>>[OX2:1]-[CX3:2](=[O:5]).[O:4]-[H:3]", - "reference": { - "smarts": "https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329", - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed048pA734.1", - "https://pubs.acs.org/doi/10.1021/ed073pA312" - ] - }, - "comments": None - }, - - "Hydroxy Carboxylic and Hydroxy Carboxylic Polycondensation(Polyesterification)": { - "same_reactants": False, - "reactant_1": "hydroxy_carboxylic_acid", - "reactant_2": "hydroxy_carboxylic_acid", - "product": "polyester_chain", - "delete_atom": True, - "reaction": "[OX2H1;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[OX2H1:4]>>[OX2:1]-[CX3:2](=[O:5]).[O:4]-[H:3]", - "reference": { - "smarts": "https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329", - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed048pA734.1", - "https://pubs.acs.org/doi/10.1021/ed073pA312" - ] - }, - "comments": None - }, - - "Hydroxy Acid Halides Polycondensation(Polyesterification)": { - "same_reactants": True, - "reactant_1": "hydroxy_acid_halide", - "product": "polyester_chain", - "delete_atom": True, - "reaction": "[OX2H1;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[Cl,Br,I:4]>>[OX2:1]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:3]", - "reference": { - "smarts": None, - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed073pA312" - ] - }, - "comments": None - }, - - "Hydroxy Acid Halides Hydroxy Acid Halides Polycondensation(Polyesterification)": { - "same_reactants": False, - "reactant_1": "hydroxy_acid_halide", - "reactant_2": "hydroxy_acid_halide", - "product": "polyester_chain", - "delete_atom": True, - "reaction": "[OX2H1;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[Cl,Br,I:4]>>[OX2:1]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:3]", - "reference": { - "smarts": None, - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed073pA312" - ] - }, - "comments": None - }, - - # ============================================================ - # Polyesterification: Diols + Diacids / Diacid Halides / Esters - # ============================================================ - - "Diol and Di-Carboxylic Acid Polycondensation(Polyesterification)": { - "same_reactants": False, - "reactant_1": "diol", - "reactant_2": "di_carboxylic_acid", - "product": "polyester_chain", - "delete_atom": True, - "reaction": "[CX3:1](=[O:3])[OX2H1:4].[OX2H1;!$([O][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[OX2:2].[O:4]-[H:5]", - "reference": { - "smarts": [ - "https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329" - ], - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed048pA734.1", - "https://pubs.acs.org/doi/10.1021/ed073pA312" - ] - }, - "comments": None - }, - - "Diol and Di-Acid Halide Polycondensation(Polyesterification)": { - "same_reactants": False, - "reactant_1": "diol", - "reactant_2": "di_carboxylic_acid_halide", - "product": "polyester_chain", - "delete_atom": True, - "reaction": "[CX3:1](=[O:3])[Cl,Br,I:4].[OX2H1;!$([O][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[OX2:2].[Cl,Br,I:4]-[H:5]", - "reference": { - "smarts": [ - "https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329" - ], - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed048pA734.1", - "https://pubs.acs.org/doi/10.1021/ed073pA312" - ] - }, - "comments": None - }, - - "Diol and Di-Carboxylic Ester Polycondensation(Transesterification)": { - "same_reactants": False, - "reactant_1": "diol", - "reactant_2": "di_carboxylic_ester", - "product": "polyester_chain", - "delete_atom": True, - "reaction": "[OX2H1;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[OX2H0:4][#6:6]>>[OX2:1]-[CX3:2](=[O:5]).[OX2:4](-[H:3])-[#6:6]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": None - }, - - # ============================================================ - # Polyanhydride Formation - # ============================================================ - - "Carboxylic Acid and Acid Halide Polycondensation(Polyanhydride Formation)": { - "same_reactants": True, - "reactant_1": "carboxylic_acid_acid_halide", - "product": "polyanhydride_chain", - "delete_atom": True, - "reaction": "[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2H1:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": None - }, - - # ============================================================ - # Polythioesterification - # ============================================================ - - "Dithiol and Di-Carboxylic Acid Halide Polycondensation(Polythioesterification)": { - "same_reactants": False, - "reactant_1": "dithiol", - "reactant_2": "di_carboxylic_acid_halide", - "product": "polythioester_chain", - "delete_atom": True, - "reaction": "[CX3:1](=[O:3])[Cl,Br,I:4].[SX2H1;!$([S][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[SX2:2].[Cl,Br,I:4]-[H:5]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": None - }, - - "Dithiol and Di-Carboxylic Acid Polycondensation(Polythioesterification)": { - "same_reactants": False, - "reactant_1": "dithiol", - "reactant_2": "di_carboxylic_acid", - "product": "polythioester_chain", - "delete_atom": True, - "reaction": "[CX3:1](=[O:3])[OX2H1:4].[SX2H1;!$([S][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[SX2:2].[O:4]-[H:5]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": "Possible thioesterification with water elimination, but generally less straightforward than acid-halide route." - }, - - # ============================================================ - # Polyamidation - # ============================================================ - - "Amino Acid Polycondensation (Polyamidation)": { - "same_reactants": True, - "reactant_1": "amino_acid", - "product": "polyamide_chain", - "delete_atom": True, - "reaction": "[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]", - "reference": { - "smarts": [ - "https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329" - ], - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed048pA734.1", - "https://pubs.acs.org/doi/10.1021/ed073pA312" - ] - }, - "comments": None - }, - - "Amino Acid and Amino Acid Polycondensation (Polyamidation)": { - "same_reactants": False, - "reactant_1": "amino_acid", - "reactant_2": "amino_acid", - "product": "polyamide_chain", - "delete_atom": True, - "reaction": "[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]", - "reference": { - "smarts": [ - "https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329" - ], - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed048pA734.1", - "https://pubs.acs.org/doi/10.1021/ed073pA312" - ] - }, - "comments": None - }, - - "Di-Amine and Di-Carboxylic Acid Polycondensation (Polyamidation)": { - "same_reactants": False, - "reactant_1": "di_amine", - "reactant_2": "di_carboxylic_acid", - "product": "polyamide_chain", - "delete_atom": True, - "reaction": "[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]", - "reference": { - "smarts": [ - "https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329" - ], - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed048pA734" - ] - }, - "comments": None - }, - - "Di-Amine and Di-Carboxylic Acid Halide Polycondensation (Polyamidation)": { - "same_reactants": False, - "reactant_1": "di_amine", - "reactant_2": "di_carboxylic_acid_halide", - "product": "polyamide_chain", - "delete_atom": True, - "reaction": "[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[Cl,Br,I:5]>>[NX3:1]-[CX3:2](=[O:4]).[Cl,Br,I:5]-[H:3]", - "reference": { - "smarts": [ - "https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329" - ], - "reaction_and_mechanism": [ - "https://pubs.acs.org/doi/10.1021/ed048pA734" - ] - }, - "comments": None - }, - - # ============================================================ - # Mixed Polyester / Polythioester Formation - # ============================================================ - - "Hydroxy-Thiol and Di-Carboxylic Acid Halide Polycondensation through Hydroxy Group": { - "same_reactants": False, - "reactant_1": "hydroxy_thiol", - "reactant_2": "di_carboxylic_acid_halide", - "product": "mixed_polyester_polythioester_chain", - "delete_atom": True, - "reaction": "[CX3:1](=[O:3])[Cl,Br,I:4].[OX2H1;!$([O][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[OX2:2].[Cl,Br,I:4]-[H:5]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": None - }, - - "Hydroxy-Thiol and Di-Carboxylic Acid Halide Polycondensation through Thiol Group": { - "same_reactants": False, - "reactant_1": "hydroxy_thiol", - "reactant_2": "di_carboxylic_acid_halide", - "product": "mixed_polyester_polythioester_chain", - "delete_atom": True, - "reaction": "[CX3:1](=[O:3])[Cl,Br,I:4].[SX2H1;!$([S][C,S]=*):2]-[H:5]>>[CX3:1](=[O:3])-[SX2:2].[Cl,Br,I:4]-[H:5]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": None - }, - - # ============================================================ - # Polyurethane Formation - # ============================================================ - - "Diol and Di-Isocyanate Polyaddition(Polyurethane Formation)": { - "same_reactants": False, - "reactant_1": "diol", - "reactant_2": "di_isocyanate", - "product": "polyurethane_chain", - "delete_atom": False, - "reaction": "[OX2H1;!$([O][C,S]=*):1]-[H:3].[NX2:4]=[CX2:2]=[OX1:5]>>[OX2:1]-[CX3:2](=[OX1:5])-[NX3:4]-[H:3]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": None - }, - "Primary Amine and Epoxide Polyaddition (Epoxy-Amine, First Addition)": { - "same_reactants": False, - "reactant_1": "primary_amine", - "reactant_2": "di_epoxide", - "product": "secondary_amine_hydroxyl_product", - "delete_atom": False, - "reaction": "[NX3H2:1]-[H:6].[CX4:2]1[OX2:5][CX4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": "Primary amine (-NH2) opens one epoxide ring. One N-H is consumed and transferred to the epoxide oxygen as -OH; nitrogen becomes a secondary amine with one remaining N-H, still reactive toward a second epoxide." - }, - - "Secondary Amine and Epoxide Polyaddition (Epoxy-Amine, Second Addition / Crosslink)": { - "same_reactants": False, - "reactant_1": "secondary_amine", - "reactant_2": "di_epoxide", - "product": "tertiary_amine_crosslink_product", - "delete_atom": False, - "reaction": "[NX3H1:1]-[H:6].[CX4:2]1[OX2:5][CX4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]", - "reference": { - "smarts": None, - "reaction_and_mechanism": None - }, - "comments": "Secondary amine's remaining N-H opens a second epoxide ring. Nitrogen becomes a fully substituted tertiary amine (network crosslink point); no reactive N-H remains on this nitrogen." - }, - - "Vinyl Addition Polymerization Initiation": { - "same_reactants": True, - "reactant_1": "vinyl", - "product": "vinyl_chain_end_radical", - "delete_atom": False, - "reaction": ( - "[CH2:1]=[C;!R:3]." - "[CH2:2]=[C;!R:4]" - ">>" - "[CH2:1](-[C:3])-[CH2:2]-[C:4]" - ), - "reference": { - "smarts": None, - "reaction_and_mechanism": None, - }, - "comments": ( - "Joins two terminal vinyl groups. The two alkene carbons that do " - "not form the new intermolecular bond become radical chain ends." - ), - }, - "Vinyl Addition Polymerization Propagation": { - "same_reactants": False, - "reactant_1": "vinyl", - "reactant_2": "vinyl_chain_end_radical", - "product": "vinyl_chain_end_radical", - "delete_atom": False, - "reaction": ( - "[CH2:2]=[C;!R:3]." - "[C;!R;D3;v3:1]" - ">>" - "[C:1]-[CH2:2]-[C:3]" - ), - "reference": { - "smarts": None, - "reaction_and_mechanism": None, - }, - "comments": ( - "The existing carbon radical forms a bond with the terminal CH2 " - "of the incoming vinyl monomer. The other alkene carbon becomes " - "the new radical center." - ), - }, - "Vinyl Radical Coupling Termination": { - "same_reactants": True, - "reactant_1": "vinyl_chain_end_radical", - "product": "vinyl_terminated_chain", - "delete_atom": False, - "reaction": ( - "[C;!R;D3;v3;+0:1]." - "[C;!R;D3;v3;+0:2]" - ">>" - "[C:1]-[C:2]" - ), - "reference": { - "smarts": None, - "reaction_and_mechanism": None, - }, - "comments": ( - "Termination by combination of two neutral carbon-centered " - "vinyl chain-end radicals. A new carbon-carbon single bond " - "is formed and both radical centers are consumed." - ), - }, - # ============================================================ - # Commented reactions - # ============================================================ - - # "Vinyl Addition Polymerization": { - # "same_reactants": True, - # "reactant_1": "vinyl", - # "product": "polyvinyl_chain", - # "delete_atom": False, - # "reaction": "[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]" - # }, - - # "Cyclic Olefin Addition Polymerization": { - # "same_reactants": True, - # "reactant_1": "cyclic_olefin", - # "product": "polycyclic_chain", - # "delete_atom": False, - # "reaction": "[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]" - # }, - - # "Vinyl Copolymerization": { - # "same_reactants": False, - # "reactant_1": "vinyl", - # "reactant_2": "vinyl", - # "product": "copolyvinyl_chain", - # "delete_atom": False, - # "reaction": "[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]" - # }, - - # "Cyclic Olefin and Vinyl Copolymerization": { - # "same_reactants": False, - # "reactant_1": "vinyl", - # "reactant_2": "cyclic_olefin", - # "product": "copolycyclicvinyl_chain", - # "delete_atom": False, - # "reaction": "[CH2:1]=[CH;H1,H0;!R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CH2:3]-[CH:4]" - # }, - - # "Cyclic Olefin Copolymerization": { - # "same_reactants": False, - # "reactant_1": "cyclic_olefin", - # "reactant_2": "cyclic_olefin", - # "product": "copolycyclic_chain", - # "delete_atom": False, - # "reaction": "[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]" - # }, - - # "Lactone Ring-Opening Polyesterification": { - # "same_reactants": False, - # "reactant_1": "lactone", - # "reactant_2": "initiator", - # "product": "polyester_chain", - # "delete_atom": False - # }, - - # "Cyclic Anhydride and Epoxide Polyesterification": { - # "same_reactants": False, - # "reactant_1": "cyclic_anhydride_monomer", - # "reactant_2": "diol_monomer", - # "product": "polyester_chain", - # "delete_atom": False - # }, - - # "Cyclic Anhydride and Epoxide Polyetherification": { - # "same_reactants": False, - # "reactant_1": "cyclic_anhydride", - # "reactant_2": "epoxide", - # "product": "polyether_chain", - # "delete_atom": False - # }, - - # "Epoxide Ring-Opening Polyetherification": { - # "same_reactants": False, - # "reactant_1": "epoxide", - # "reactant_2": "initiator", - # "product": "polyether_chain", - # "delete_atom": False - # }, - - # "Hindered Phenol Polyetherification": { - # "same_reactants": True, - # "reactant_1": "hindered_phenol", - # "product": "polyether_chain", - # "delete_atom": False - # }, - - # "Hindered Phenol Hindered Phenol Polyetherification": { - # "same_reactants": False, - # "reactant_1": "hindered_phenol", - # "reactant_2": "hindered_phenol", - # "product": "polyether_chain", - # "delete_atom": False - # }, - - # "Bis(p-halogenatedaryl)sulfone Diol (without thiol) polycondensation": { - # "same_reactants": False, - # "reactant_1": "bis(p-halogenatedaryl)sulfone", - # "reactant_2": "diol", - # "product": "polyether_chain", - # "delete_atom": True - # }, - - # "Bis(bis(p-fluoroaryl)ketone Diol (without thiol) polycondensation": { - # "same_reactants": False, - # "reactant_1": "bis(p-fluoroaryl)ketone_monomer", - # "reactant_2": "diol_monomer", - # "product": "polyether_chain", - # "delete_atom": True - # }, - - # "Lactam Ring-Opening Polyamidation": { - # "same_reactants": True, - # "reactant_1": "lactam_monomer", - # "product": "polyamide_chain", - # "delete_atom": False - # }, - - # "Di-cyclic Anhydride and Di-Primary Amine Polycondensation (Polyimidation)": { - # "same_reactants": False, - # "reactant_1": "di_cyclic_anhydride_monomer", - # "reactant_2": "di_amine_monomer", - # "product": "polyimide_chain", - # "delete_atom": True - # }, - - # "Di-Epoxide and Di-Isocyanate Polyamination": { - # "same_reactants": False, - # "reactant_1": "di_epoxide_monomer", - # "reactant_2": "di_isocyanate_monomer", - # "product": "polyamine_chain", - # "delete_atom": False, - # "reaction": "[NX2:3]=[CX2:4]=[OX1,SX1:5].[OX2,SX2;H1;!$([O,S]C=*):6]>>[NX3:3][CX3:4](=[OX1,SX1:5])[OX2,SX2;!$([O,S]C=*):6]" - # }, - #} - } \ No newline at end of file From 6c418ee1f90ba224906d0abdc1e182d5aa62714b Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:15:24 -0400 Subject: [PATCH 079/176] Disable aromatic group registration --- .../active_centers.py | 33 ++++++++----------- .../aromatic_groups.py | 32 ++++++++++++++++++ .../carboxyl_and_carbonyl_groups.py | 18 +++++----- .../functional_groups_library/registry.py | 4 +-- 4 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 AutoREACTER/detectors/functional_groups_library/aromatic_groups.py diff --git a/AutoREACTER/detectors/functional_groups_library/active_centers.py b/AutoREACTER/detectors/functional_groups_library/active_centers.py index f1cf6ad2..033e7062 100644 --- a/AutoREACTER/detectors/functional_groups_library/active_centers.py +++ b/AutoREACTER/detectors/functional_groups_library/active_centers.py @@ -1,21 +1,14 @@ -"""Functional-group definitions organized by the active centers motif. - -Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" - FUNCTIONAL_GROUPS = { - 'vinyl_chain_end_radical': - { - 'functionality_type': 'vinyl', - 'smarts_1': '[C;!R;D3;v3]', - 'group_name': 'vinyl_chain_end_radical', - 'comments': None - }, - # 'romp_alkylidene_motif': - # { - # 'functionality_type': 'mono', - # 'smarts_1': '[Ru]=[C]', - # 'group_name': 'romp_alkylidene', - # 'comments': 'UNTESTED simplified ruthenium alkylidene motif used for both ROMP initiation ' - # 'and propagation. Atom maps 1 and 2 are assigned only in the reaction SMARTS.' - # } - } + 'vinyl_chain_end_radical': { + 'functionality_type': 'vinyl', + 'smarts_1': '[C;!R;D3;v3]', + 'group_name': 'vinyl_chain_end_radical', + 'comments': None + }, + # 'romp_alkylidene_motif': { + # 'functionality_type': 'mono', + # 'smarts_1': '[Ru]=[C]', + # 'group_name': 'romp_alkylidene', + # 'comments': None + # } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/aromatic_groups.py b/AutoREACTER/detectors/functional_groups_library/aromatic_groups.py new file mode 100644 index 00000000..5bcf472b --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/aromatic_groups.py @@ -0,0 +1,32 @@ +# FUNCTIONAL_GROUPS = { +# 'bis_p_halogenatedaryl_sulfone_monomer': { +# 'functionality_type': 'di_identical', +# 'smarts_1': '[c]([F,Cl,Br,I])[c][SX4](=[OX1])(=[OX1])', +# 'group_name': 'bis(p-halogenatedaryl)sulfone', +# 'comments': None +# }, +# 'bis_p_fluoroaryl_ketone_monomer': { +# 'functionality_type': 'di_identical', +# 'smarts_1': '[c]([F])[c][CX3](=[OX1])', +# 'group_name': 'bis(p-fluoroaryl)ketone_monomer', +# 'comments': None +# }, +# 'phenol_monomer': { +# 'functionality_type': 'di_identical', +# 'smarts_1': '[cH1][c][OX2H1]', +# 'group_name': 'phenol', +# 'comments': None +# }, +# 'hydroxymethyl_phenol_monomer': { +# 'functionality_type': 'mono', +# 'smarts_1': '[c][CH2][OX2H1]', +# 'group_name': 'hydroxymethyl_phenol', +# 'comments': None +# }, +# 'hindered_phenol_monomer': { +# 'functionality_type': 'di_identical', +# 'smarts_1': '[c]1([OX2H1])[c]([C])[c][cH1][c][c]1([C])', +# 'group_name': 'hindered_phenol', +# 'comments': None +# } +# } \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py b/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py index 8a1fb1c9..99f5eb25 100644 --- a/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/carboxyl_and_carbonyl_groups.py @@ -1,14 +1,10 @@ -"""Functional-group definitions organized by the carboxyl and carbonyl groups motif. - -Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" - FUNCTIONAL_GROUPS = { 'di_carboxylic_acid_monomer': { 'functionality_type': 'di_identical', 'smarts_1': '[CX3:1](=[O])[OX2H1]', 'group_name': 'di_carboxylic_acid', 'comments': None - }, + }, 'di_carboxylic_acid_halide_monomer': { 'functionality_type': 'di_identical', 'smarts_1': '[CX3:1](=[O])[Cl,Br,I]', @@ -26,7 +22,7 @@ # Elaborated SMARTS strictly requires a carbonyl carbon bonded to exactly two chlorines 'smarts_1': '[Cl:1]-[CX3:2](=[OX1:3])-[Cl:4]', 'group_name': 'phosgene', - 'comments': None, + 'comments': None }, 'diphenyl_carbonate_monomer': { 'functionality_type': 'di_identical', @@ -34,8 +30,10 @@ 'group_name': 'diphenyl_carbonate', 'comments': None } -# 'formaldehyde_monomer': {'functionality_type': 'mono', -# 'smarts_1': '[CH2]=[OX1]', -# 'group_name': 'formaldehyde', -# 'comments': None}} + # 'formaldehyde_monomer': { + # 'functionality_type': 'mono', + # 'smarts_1': '[CH2]=[OX1]', + # 'group_name': 'formaldehyde', + # 'comments': None + # } } \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/registry.py b/AutoREACTER/detectors/functional_groups_library/registry.py index 79d3a7d6..98c1391d 100644 --- a/AutoREACTER/detectors/functional_groups_library/registry.py +++ b/AutoREACTER/detectors/functional_groups_library/registry.py @@ -7,7 +7,7 @@ from .mixed_ab_groups import FUNCTIONAL_GROUPS as MIXED_AB_GROUPS from .ring_groups import FUNCTIONAL_GROUPS as RING_GROUPS from .vinyl_and_alkene_groups import FUNCTIONAL_GROUPS as VINYL_AND_ALKENE_GROUPS -from .aromatic_groups import FUNCTIONAL_GROUPS as AROMATIC_GROUPS +# from .aromatic_groups import FUNCTIONAL_GROUPS as AROMATIC_GROUPS from .silicon_groups import FUNCTIONAL_GROUPS as SILICON_GROUPS # from .halide_groups import FUNCTIONAL_GROUPS as HALIDE_GROUPS from .heterocumulene_groups import FUNCTIONAL_GROUPS as HETEROCUMULENE_GROUPS @@ -21,7 +21,7 @@ MIXED_AB_GROUPS, RING_GROUPS, VINYL_AND_ALKENE_GROUPS, - AROMATIC_GROUPS, + # AROMATIC_GROUPS, SILICON_GROUPS, # HALIDE_GROUPS, HETEROCUMULENE_GROUPS, From ab4281f525db52d3f5aa1cce173bf2448317fb79 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:19:16 -0400 Subject: [PATCH 080/176] Add ring/silicon groups and normalize defs --- .../mixed_ab_groups.py | 78 +++++++++---------- .../nitrogen_groups.py | 71 ++++++++--------- .../oxygen_groups.py | 45 +++++------ .../functional_groups_library/ring_groups.py | 44 +++++++++++ .../silicon_groups.py | 14 ++++ .../sulfur_groups.py | 29 ++++--- .../vinyl_and_alkene_groups.py | 42 +++++----- 7 files changed, 176 insertions(+), 147 deletions(-) create mode 100644 AutoREACTER/detectors/functional_groups_library/ring_groups.py create mode 100644 AutoREACTER/detectors/functional_groups_library/silicon_groups.py diff --git a/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py b/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py index aee41c55..8679d04d 100644 --- a/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py @@ -1,43 +1,37 @@ - FUNCTIONAL_GROUPS = { - 'hydroxy_carboxylic_acid_monomer': - { - 'functionality_type': 'di_different', - 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', - 'smarts_2': '[CX3:2](=[O])[OX2H1]', - 'group_name': 'hydroxy_carboxylic_acid', - 'comments': None - }, - 'hydroxy_acid_halides_monomer': - { - 'functionality_type': 'di_different', - 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', - 'smarts_2': '[CX3:2](=[O])[Cl,Br,I]', - 'group_name': 'hydroxy_acid_halide', - 'comments': None - }, - 'amino_acid_monomer': - { - 'functionality_type': 'di_different', - 'smarts_1': '[NX3;H2,H1;!$([N][C,S]=*):1]', - 'smarts_2': '[CX3:2](=[O])[OX2H1]', - 'group_name': 'amino_acid', - 'comments': None - }, - 'carboxylic_acid_acid_halide_monomer': - { - 'functionality_type': 'di_different', - 'smarts_1': '[CX3:1](=[O])[OX2H1]', - 'smarts_2': '[CX3:2](=[O])[Cl,Br,I]', - 'group_name': 'carboxylic_acid_acid_halide', - 'comments': None - }, - 'hydroxy_thiol_monomer': - { - 'functionality_type': 'di_different', - 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', - 'smarts_2': '[SX2H1;!$([S][C,S]=*):2]', - 'group_name': 'hydroxy_thiol', - 'comments': None - } -} + 'hydroxy_carboxylic_acid_monomer': { + 'functionality_type': 'di_different', + 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', + 'smarts_2': '[CX3:2](=[O])[OX2H1]', + 'group_name': 'hydroxy_carboxylic_acid', + 'comments': None + }, + 'hydroxy_acid_halides_monomer': { + 'functionality_type': 'di_different', + 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', + 'smarts_2': '[CX3:2](=[O])[Cl,Br,I]', + 'group_name': 'hydroxy_acid_halide', + 'comments': None + }, + 'amino_acid_monomer': { + 'functionality_type': 'di_different', + 'smarts_1': '[NX3;H2,H1;!$([N][C,S]=*):1]', + 'smarts_2': '[CX3:2](=[O])[OX2H1]', + 'group_name': 'amino_acid', + 'comments': None + }, + 'carboxylic_acid_acid_halide_monomer': { + 'functionality_type': 'di_different', + 'smarts_1': '[CX3:1](=[O])[OX2H1]', + 'smarts_2': '[CX3:2](=[O])[Cl,Br,I]', + 'group_name': 'carboxylic_acid_acid_halide', + 'comments': None + }, + 'hydroxy_thiol_monomer': { + 'functionality_type': 'di_different', + 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', + 'smarts_2': '[SX2H1;!$([S][C,S]=*):2]', + 'group_name': 'hydroxy_thiol', + 'comments': None + } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/nitrogen_groups.py b/AutoREACTER/detectors/functional_groups_library/nitrogen_groups.py index c21ced15..36aa22bb 100644 --- a/AutoREACTER/detectors/functional_groups_library/nitrogen_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/nitrogen_groups.py @@ -1,41 +1,32 @@ -"""Functional-group definitions organized by the nitrogen groups motif. - -Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" - FUNCTIONAL_GROUPS = { - 'primary_amine_monomer': - { - 'functionality_type': 'mono', - 'smarts_1': '[NX3H2;!$(NC=O);!$(NC=[N,O,S])]', - 'group_name': 'primary_amine', - 'comments': None - }, # Tested - Passed - 'secondary_amine_monomer': - { - 'functionality_type': 'mono', - 'smarts_1': '[NX3H1;!$(NC=O);!$(NC=[N,O,S])]', - 'group_name': 'secondary_amine', - 'comments': None - }, - 'di_amine_monomer': - { - 'functionality_type': 'di_identical', - 'smarts_1': '[NX3;H2,H1;!$([N][C,S]=*):1]', - 'group_name': 'di_amine', - 'comments': None - }, - 'di_primary_amine_monomer': - { - 'functionality_type': 'di_identical', - 'smarts_1': '[NX3H2;!$([N][C,S]=*)]', - 'group_name': 'di_primary_amine', - 'comments': None - }, - # 'tetra_amine_monomer': - # { - # 'functionality_type': 'di_identical', - # 'smarts_1': '[c]([NX3H2;!$([N][C,S]=*)])[c][NX3H2;!$([N][C,S]=*)]', - # 'group_name': 'tetra_amine', - # 'comments': None - # } -} + 'primary_amine_monomer': { + 'functionality_type': 'mono', + 'smarts_1': '[NX3H2;!$(NC=O);!$(NC=[N,O,S])]', + 'group_name': 'primary_amine', + 'comments': None + }, + 'secondary_amine_monomer': { + 'functionality_type': 'mono', + 'smarts_1': '[NX3H1;!$(NC=O);!$(NC=[N,O,S])]', + 'group_name': 'secondary_amine', + 'comments': None + }, + 'di_amine_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[NX3;H2,H1;!$([N][C,S]=*):1]', + 'group_name': 'di_amine', + 'comments': None + }, + 'di_primary_amine_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[NX3H2;!$([N][C,S]=*)]', + 'group_name': 'di_primary_amine', + 'comments': None + }, + # 'tetra_amine_monomer': { + # 'functionality_type': 'di_identical', + # 'smarts_1': '[c]([NX3H2;!$([N][C,S]=*)])[c][NX3H2;!$([N][C,S]=*)]', + # 'group_name': 'tetra_amine', + # 'comments': None + # } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/oxygen_groups.py b/AutoREACTER/detectors/functional_groups_library/oxygen_groups.py index 0fa3a941..d87891e2 100644 --- a/AutoREACTER/detectors/functional_groups_library/oxygen_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/oxygen_groups.py @@ -1,27 +1,20 @@ -"""Functional-group definitions organized by the oxygen groups motif. - -Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" - FUNCTIONAL_GROUPS = { - 'diol_monomer': - { - 'functionality_type': 'di_identical', - 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', - 'group_name': 'diol', - 'comments': None - }, - # 'initiator_monomer': - # { - # 'functionality_type': 'mono', - # 'smarts_1': '[OX2H1;!$([O][C,S]=*)]', - # 'group_name': 'lactone_initiator', - # 'comments': None, - # }, - 'water_monomer': - { - 'functionality_type': 'mono', - 'smarts_1': '[OH2:1]', - 'group_name': 'water', - 'comments': None - } -} + 'diol_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', + 'group_name': 'diol', + 'comments': None + }, + # 'initiator_monomer': { + # 'functionality_type': 'mono', + # 'smarts_1': '[OX2H1;!$([O][C,S]=*)]', + # 'group_name': 'lactone_initiator', + # 'comments': None + # }, + 'water_monomer': { + 'functionality_type': 'mono', + 'smarts_1': '[OH2:1]', + 'group_name': 'water', + 'comments': None + } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/ring_groups.py b/AutoREACTER/detectors/functional_groups_library/ring_groups.py new file mode 100644 index 00000000..8aee8f8c --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/ring_groups.py @@ -0,0 +1,44 @@ +FUNCTIONAL_GROUPS = { + # 'epoxide_monomer': { + # 'functionality_type': 'mono', + # 'smarts_1': '[CX4;R:3]1[OX2;R:4][CX4;R:5]1', + # 'group_name': 'epoxide', + # 'comments': None + # }, + 'di_epoxy_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[CX4;R1]1[OX2;R1][CX4;R1]1', + 'group_name': 'di_epoxide', + 'comments': None + }, + # 'lactone_monomer': { + # 'functionality_type': 'mono', + # 'smarts_1': '[CX3;R:1](=[OX1])[OX2;R:2]', + # 'group_name': 'lactone', + # 'comments': None + # }, + # 'lactam_monomer': { + # 'functionality_type': 'mono', + # 'smarts_1': '[CX3;R:1](=[OX1])[NX3H1;R:2]', + # 'group_name': 'lactam', + # 'comments': None + # }, + # 'cyclic_anhydride_monomer': { + # 'functionality_type': 'mono', + # 'smarts_1': '[CX3;R:1](=[OX1])[OX2;R][CX3;R:2](=[OX1])', + # 'group_name': 'cyclic_anhydride', + # 'comments': None + # }, + # 'di_cyclic_anhydride_monomer': { + # 'functionality_type': 'di_identical', + # 'smarts_1': '[CX3,c;R:1](=[OX1])[OX2,o;R][CX3,c;R:2](=[OX1])', + # 'group_name': 'di_cyclic_anhydride', + # 'comments': None + # }, + # 'cyclic_olefin_monomer': { + # 'functionality_type': 'vinyl', + # 'smarts_1': '[CX3;R:1]=[CX3;R:2]', + # 'group_name': 'cyclic_olefin', + # 'comments': None + # } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/silicon_groups.py b/AutoREACTER/detectors/functional_groups_library/silicon_groups.py new file mode 100644 index 00000000..117ec720 --- /dev/null +++ b/AutoREACTER/detectors/functional_groups_library/silicon_groups.py @@ -0,0 +1,14 @@ +FUNCTIONAL_GROUPS = { + 'dichlorosilane_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[Si][Cl]', + 'group_name': 'dichlorosilane', + 'comments': None + }, + 'silanediol_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[Si][OX2H1]', + 'group_name': 'silanediol', + 'comments': None + } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/sulfur_groups.py b/AutoREACTER/detectors/functional_groups_library/sulfur_groups.py index d688600f..fbc6b955 100644 --- a/AutoREACTER/detectors/functional_groups_library/sulfur_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/sulfur_groups.py @@ -1,17 +1,14 @@ -"""Functional-group definitions organized by the sulfur groups motif. - -Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" - FUNCTIONAL_GROUPS = { - 'dithiol_monomer': - { - 'functionality_type': 'di_identical', - 'smarts_1': '[SX2H1;!$([S][C,S]=*):1]', - 'group_name': 'dithiol', - 'comments': None - }, -# 'sodium_sulfide_monomer': {'functionality_type': 'mono', -# 'smarts_1': '[S-2]', -# 'group_name': 'sodium_sulfide', -# 'comments': 'Sulfide dianion; sodium counterions are included in the reaction SMARTS.'} -} + 'dithiol_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[SX2H1;!$([S][C,S]=*):1]', + 'group_name': 'dithiol', + 'comments': None + }, + # 'sodium_sulfide_monomer': { + # 'functionality_type': 'mono', + # 'smarts_1': '[S-2]', + # 'group_name': 'sodium_sulfide', + # 'comments': None + # } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py b/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py index b76eb3ca..1641eda1 100644 --- a/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py @@ -1,24 +1,20 @@ -"""Functional-group definitions organized by the vinyl and alkene groups motif. - -Each entry is defined once in the entire functional-group registry. Reaction libraries reference the entry's group_name value.""" - FUNCTIONAL_GROUPS = { - 'vinyl_monomer': - { - 'functionality_type': 'vinyl', - 'smarts_1': '[CH2]=[C;!R]', - 'group_name': 'vinyl', - 'comments': None - }, - 'diene_monomer': - { - 'functionality_type': 'di_identical', - 'smarts_1': '[CH2]=[C;!R]', - 'group_name': 'diene', - 'comments': None - }, -} -# 'bis_alkene_monomer': {'functionality_type': 'di_identical', -# 'smarts_1': '[C]=[C]', -# 'group_name': 'bis_alkene', -# 'comments': 'One alkene site; a bis-alkene supplies two identical matches.'}} + 'vinyl_monomer': { + 'functionality_type': 'vinyl', + 'smarts_1': '[CH2]=[C;!R]', + 'group_name': 'vinyl', + 'comments': None + }, + 'diene_monomer': { + 'functionality_type': 'di_identical', + 'smarts_1': '[CH2]=[C;!R]', + 'group_name': 'diene', + 'comments': None + }, + # 'bis_alkene_monomer': { + # 'functionality_type': 'di_identical', + # 'smarts_1': '[C]=[C]', + # 'group_name': 'bis_alkene', + # 'comments': None + # } +} \ No newline at end of file From 99fc3985e0bd21167c2af2d5c340d26c996cbd81 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:26:08 -0400 Subject: [PATCH 081/176] Normalize polymer reaction library entries --- .../cycloaddition_polymers.py | 46 ++-- .../reactions_library/epoxy_polymers.py | 61 +++-- .../reactions_library/metathesis_polymers.py | 34 +-- .../reactions_library/phenolic_resins.py | 70 ++---- .../detectors/reactions_library/polyamides.py | 226 ++++++++---------- .../reactions_library/polyanhydrides.py | 52 ++-- .../detectors/reactions_library/polyimides.py | 29 +-- 7 files changed, 227 insertions(+), 291 deletions(-) diff --git a/AutoREACTER/detectors/reactions_library/cycloaddition_polymers.py b/AutoREACTER/detectors/reactions_library/cycloaddition_polymers.py index 5d48677c..3d2a79f7 100644 --- a/AutoREACTER/detectors/reactions_library/cycloaddition_polymers.py +++ b/AutoREACTER/detectors/reactions_library/cycloaddition_polymers.py @@ -1,29 +1,21 @@ -# """Reactions organized under the cycloaddition polymers polymer family.""" - -# Yet to be tested and implemented # REACTIONS = { -# 'Bis-Alkene Four-Center Cycloaddition Polymerization': -# { -# 'same_reactants': True, -# 'reactant_1': 'bis_alkene', -# 'product': 'polycyclobutane_chain', -# 'delete_atom': False, -# 'reaction': '[C:1]=[C:2].[C:3]=[C:4]>>[C:1]1-[C:2]-[C:3]-[C:4]-1', -# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, -# 'comments': 'UNTESTED new chemistry; generic [2+2] ' -# 'four-center cycloaddition.' -# }, -# 'Bis-Alkene and Bis-Alkene Four-Center Copolymerization': -# { -# 'same_reactants': False, -# 'reactant_1': 'bis_alkene', -# 'reactant_2': 'bis_alkene', -# 'product': 'polycyclobutane_chain', -# 'delete_atom': False, -# 'reaction': '[C:1]=[C:2].[C:3]=[C:4]>>[C:1]1-[C:2]-[C:3]-[C:4]-1', -# 'reference': {'smarts': None, -# 'reaction_and_mechanism': None}, -# 'comments': 'UNTESTED: separate false instance for two ' -# 'different bis-alkenes.' -# } +# 'Bis-Alkene Four-Center Cycloaddition Polymerization': { +# 'same_reactants': True, +# 'reactant_1': 'bis_alkene', +# 'product': 'polycyclobutane_chain', +# 'delete_atom': False, +# 'reaction': '[C:1]=[C:2].[C:3]=[C:4]>>[C:1]1-[C:2]-[C:3]-[C:4]-1', +# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, +# 'comments': None +# }, +# 'Bis-Alkene and Bis-Alkene Four-Center Copolymerization': { +# 'same_reactants': False, +# 'reactant_1': 'bis_alkene', +# 'reactant_2': 'bis_alkene', +# 'product': 'polycyclobutane_chain', +# 'delete_atom': False, +# 'reaction': '[C:1]=[C:2].[C:3]=[C:4]>>[C:1]1-[C:2]-[C:3]-[C:4]-1', +# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, +# 'comments': None # } +# } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/epoxy_polymers.py b/AutoREACTER/detectors/reactions_library/epoxy_polymers.py index 26cfa9a6..dac56bcf 100644 --- a/AutoREACTER/detectors/reactions_library/epoxy_polymers.py +++ b/AutoREACTER/detectors/reactions_library/epoxy_polymers.py @@ -1,35 +1,30 @@ -""" -Reactions organized under the epoxy polymers polymer family. -Tested and Passed - 7/21/2026 -""" REACTIONS = { - 'Primary Amine and Epoxide Polyaddition (Epoxy-Amine, First Addition)': - { - 'same_reactants': False, - 'reactant_1': 'primary_amine', - 'reactant_2': 'di_epoxide', - 'product': 'secondary_amine_hydroxyl_product', - 'delete_atom': False, - # FIXED: N attacks the less hindered CH2 (:2), O stays on the more hindered CH (:3) - 'reaction': '[NX3H2:1]-[H:6].[CH2;X4:2]1[OX2:5][CH1;X4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]', - 'reference': { - 'smarts': None, - 'reaction_and_mechanism': None - }, - 'Notes': 'Corrected for SN2 regioselectivity (attacks less hindered carbon)' + 'Primary Amine and Epoxide Polyaddition (Epoxy-Amine, First Addition)': { + 'same_reactants': False, + 'reactant_1': 'primary_amine', + 'reactant_2': 'di_epoxide', + 'product': 'secondary_amine_hydroxyl_product', + 'delete_atom': False, + # FIXED: N attacks the less hindered CH2 (:2), O stays on the more hindered CH (:3) + 'reaction': '[NX3H2:1]-[H:6].[CH2;X4:2]1[OX2:5][CH1;X4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None }, - - 'Secondary Amine and Epoxide Polyaddition (Epoxy-Amine, Second Addition / Crosslink)': - { - 'same_reactants': False, - 'reactant_1': 'secondary_amine', - 'reactant_2': 'di_epoxide', - 'product': 'tertiary_amine_crosslink_product', - 'delete_atom': False, - # FIXED: N attacks the less hindered CH2 (:2), O stays on the more hindered CH (:3) - 'reaction': '[NX3H1:1]-[H:6].[CH2;X4:2]1[OX2:5][CH1;X4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]', - 'reference': {'smarts': None, - 'reaction_and_mechanism': None}, - 'Notes': 'Corrected for SN2 regioselectivity (attacks less hindered carbon)' - } - } \ No newline at end of file + 'comments': None + }, + 'Secondary Amine and Epoxide Polyaddition (Epoxy-Amine, Second Addition / Crosslink)': { + 'same_reactants': False, + 'reactant_1': 'secondary_amine', + 'reactant_2': 'di_epoxide', + 'product': 'tertiary_amine_crosslink_product', + 'delete_atom': False, + # FIXED: N attacks the less hindered CH2 (:2), O stays on the more hindered CH (:3) + 'reaction': '[NX3H1:1]-[H:6].[CH2;X4:2]1[OX2:5][CH1;X4:3]1>>[NX3:1][C:2][C:3][OX2:5][H:6]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/metathesis_polymers.py b/AutoREACTER/detectors/reactions_library/metathesis_polymers.py index 17cab81e..78fa98d4 100644 --- a/AutoREACTER/detectors/reactions_library/metathesis_polymers.py +++ b/AutoREACTER/detectors/reactions_library/metathesis_polymers.py @@ -1,7 +1,3 @@ -# """Reactions organized under the metathesis polymers polymer family. - -# Uncommented reactions from the supplied working library retain their original dictionary values. Formerly commented and newly added reactions remain marked UNTESTED in comments.""" - # REACTIONS = { # 'ROMP Initiation': { # 'same_reactants': False, @@ -10,13 +6,23 @@ # 'product': 'romp_chain_end', # 'delete_atom': False, # 'reaction': '[Ru:1]=[C:2].[CX3;R:3]=[CX3;R:4]>>[Ru:1]=[CX3:4].[C:2]-[CX3:3]', -# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, -# 'comments': 'UNTESTED new chemistry. Initiator Ru/alkylidene carbon are maps 1 and 2.'}, -# 'ROMP Propagation': {'same_reactants': False, -# 'reactant_1': 'romp_alkylidene', -# 'reactant_2': 'cyclic_olefin', -# 'product': 'romp_chain_end', -# 'delete_atom': False, -# 'reaction': '[Ru:1]=[C:2].[CX3;R:3]=[CX3;R:4]>>[Ru:1]=[CX3:4].[C:2]-[CX3:3]', -# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, -# 'comments': 'UNTESTED new chemistry.'}} +# 'reference': { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# }, +# 'ROMP Propagation': { +# 'same_reactants': False, +# 'reactant_1': 'romp_alkylidene', +# 'reactant_2': 'cyclic_olefin', +# 'product': 'romp_chain_end', +# 'delete_atom': False, +# 'reaction': '[Ru:1]=[C:2].[CX3;R:3]=[CX3;R:4]>>[Ru:1]=[CX3:4].[C:2]-[CX3:3]', +# 'reference': { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# } +# } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/phenolic_resins.py b/AutoREACTER/detectors/reactions_library/phenolic_resins.py index 09761f29..ff71d190 100644 --- a/AutoREACTER/detectors/reactions_library/phenolic_resins.py +++ b/AutoREACTER/detectors/reactions_library/phenolic_resins.py @@ -1,52 +1,28 @@ -# """Reactions organized under the phenolic resins polymer family. - -# Uncommented reactions from the supplied working library retain their original dictionary values. Formerly commented and newly added reactions remain marked UNTESTED in comments.""" - # REACTIONS = { -# "Phenol and Formaldehyde Hydroxymethylation": { -# "same_reactants": False, -# "reactant_1": "phenol", -# "reactant_2": "formaldehyde", -# "product": "hydroxymethyl_phenol", -# "delete_atom": False, -# "reaction": ( -# "[c:1]-[H:4].[CH2:2]=[OX1:3]" -# ">>" -# "[c:1]-[C:2]-[OX2:3]-[H:4]" -# ), -# "reference": { -# "smarts": None, -# "reaction_and_mechanism": None, +# 'Phenol and Formaldehyde Hydroxymethylation': { +# 'same_reactants': False, +# 'reactant_1': 'phenol', +# 'reactant_2': 'formaldehyde', +# 'product': 'hydroxymethyl_phenol', +# 'delete_atom': False, +# 'reaction': '[c:1]-[H:4].[CH2:2]=[OX1:3]>>[c:1]-[C:2]-[OX2:3]-[H:4]', +# 'reference': { +# 'smarts': None, +# 'reaction_and_mechanism': None # }, -# "comments": ( -# "UNTESTED new chemistry; first Bakelite-forming step. " -# "Generic aromatic C-H matching is not restricted to " -# "ortho/para substitution." -# ), +# 'comments': None # }, - -# "Hydroxymethyl Phenol and Phenol Condensation " -# "(Methylene Bridge Formation)": { -# "same_reactants": False, -# "reactant_1": "hydroxymethyl_phenol", -# "reactant_2": "phenol", -# "product": "phenol_formaldehyde_chain", -# "delete_atom": True, -# "reaction": ( -# "[c:1]-[CH2:2]-[OX2H1:3]-[H:6]." -# "[c:4]-[H:5]" -# ">>" -# "[c:1]-[C:2]-[c:4]." -# "[OX2:3](-[H:5])-[H:6]" -# ), -# "reference": { -# "smarts": None, -# "reaction_and_mechanism": None, +# 'Hydroxymethyl Phenol and Phenol Condensation (Methylene Bridge Formation)': { +# 'same_reactants': False, +# 'reactant_1': 'hydroxymethyl_phenol', +# 'reactant_2': 'phenol', +# 'product': 'phenol_formaldehyde_chain', +# 'delete_atom': True, +# 'reaction': '[c:1]-[CH2:2]-[OX2H1:3]-[H:6].[c:4]-[H:5]>>[c:1]-[C:2]-[c:4].[OX2:3](-[H:5])-[H:6]', +# 'reference': { +# 'smarts': None, +# 'reaction_and_mechanism': None # }, -# "comments": ( -# "UNTESTED. Produces a methylene bridge and water. " -# "Generic aromatic C-H matching is not restricted to " -# "ortho/para substitution." -# ), -# }, +# 'comments': None +# } # } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polyamides.py b/AutoREACTER/detectors/reactions_library/polyamides.py index 80e56de6..29b9e05b 100644 --- a/AutoREACTER/detectors/reactions_library/polyamides.py +++ b/AutoREACTER/detectors/reactions_library/polyamides.py @@ -1,130 +1,104 @@ -"""Reactions organized under the polyamides polymer family. - -Uncommented reactions from the supplied working library retain their original dictionary values. Formerly commented and newly added reactions remain marked UNTESTED in comments.""" - REACTIONS = { - 'Amino Acid Polycondensation (Polyamidation)': - { - 'same_reactants': True, - 'reactant_1': 'amino_acid', - 'product': 'polyamide_chain', - 'delete_atom': True, - 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', - 'reference': - { - 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], - 'reaction_and_mechanism': - [ - 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', - 'https://pubs.acs.org/doi/10.1021/ed073pA312' - ] - }, - 'comments': None}, - 'Amino Acid and Amino Acid Polycondensation (Polyamidation)': - { - 'same_reactants': False, - 'reactant_1': 'amino_acid', - 'reactant_2': 'amino_acid', - 'product': 'polyamide_chain', - 'delete_atom': True, - 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', - 'reference': - { - 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], - 'reaction_and_mechanism': - [ - 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', - 'https://pubs.acs.org/doi/10.1021/ed073pA312' - ] - }, - 'comments': None - }, - 'Di-Amine and Di-Carboxylic Acid Polycondensation (Polyamidation)': - { - 'same_reactants': False, - 'reactant_1': 'di_amine', - 'reactant_2': 'di_carboxylic_acid', - 'product': 'polyamide_chain', - 'delete_atom': True, - 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', - 'reference': - { - 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], - 'reaction_and_mechanism': - [ - 'https://pubs.acs.org/doi/10.1021/ed048pA734.1' - ] - }, - 'comments': None + 'Amino Acid Polycondensation (Polyamidation)': { + 'same_reactants': True, + 'reactant_1': 'amino_acid', + 'product': 'polyamide_chain', + 'delete_atom': True, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', + 'reference': { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', + 'https://pubs.acs.org/doi/10.1021/ed073pA312' + ] }, - 'Di-Amine and Di-Carboxylic Acid Halide Polycondensation (Polyamidation)': - { - 'same_reactants': False, - 'reactant_1': 'di_amine', - 'reactant_2': 'di_carboxylic_acid_halide', - 'product': 'polyamide_chain', - 'delete_atom': True, - 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[Cl,Br,I:5]>>[NX3:1]-[CX3:2](=[O:4]).[Cl,Br,I:5]-[H:3]', - 'reference': - { - 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], - 'reaction_and_mechanism': - [ - 'https://pubs.acs.org/doi/10.1021/ed048pA734' - ] - }, - 'comments': None + 'comments': None + }, + 'Amino Acid and Amino Acid Polycondensation (Polyamidation)': { + 'same_reactants': False, + 'reactant_1': 'amino_acid', + 'reactant_2': 'amino_acid', + 'product': 'polyamide_chain', + 'delete_atom': True, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', + 'reference': { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1', + 'https://pubs.acs.org/doi/10.1021/ed073pA312' + ] }, - 'Hydrolytic Initiation of Caprolactam': - { - 'same_reactants': False, - 'reactant_1': 'water', - 'reactant_2': 'lactam', - 'product': 'polyamide_chain', - 'delete_atom': False, - 'reaction': '[O:1]-[H:12].[CX3:2]1(=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4]1-[H:6]>>[O:1]-[CX3:2](=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4](-[H:6])-[H:12]', - 'reference': - { - 'smarts': None, - 'reaction_and_mechanism': ['https://doi.org/10.1002/047147875X'] - }, - 'comments': None, - 'Notes': "Validated on 2026-07-26, Passed" + 'comments': None + }, + 'Di-Amine and Di-Carboxylic Acid Polycondensation (Polyamidation)': { + 'same_reactants': False, + 'reactant_1': 'di_amine', + 'reactant_2': 'di_carboxylic_acid', + 'product': 'polyamide_chain', + 'delete_atom': True, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[OX2H1:5]>>[NX3:1]-[CX3:2](=[O:4]).[O:5]-[H:3]', + 'reference': { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734.1' + ] }, - } - -### LATER IMPLEMENTATION: Consider adding more detailed reaction mechanisms and validation steps for hydrolytic initiation of caprolactam. - -# 'Caprolactam Ring-Opening Polyamidation': -# { -# 'same_reactants': True, -# 'reactant_1': 'lactam', -# 'product': 'polyamide_chain', -# 'delete_atom': False, -# # Reactant 2 explicitly maps the 5 CH2 groups (maps 7 through 11) and uses '1' for the ring closure. -# # Product SMARTS removes the '.' and explicitly connects the opened chain. -# 'reaction': '[NX3:1]-[H:5].[CX3:2]1(=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4]1-[H:6]>>[NX3:1]-[CX3:2](=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4](-[H:5])-[H:6]', -# 'reference': -# { -# 'smarts': None, -# 'reaction_and_mechanism': None -# }, -# 'comments': None -# }, -# }, -# 'Lactam and Lactam Ring-Opening Copolyamidation': -# { -# 'same_reactants': False, -# 'reactant_1': 'lactam', -# 'reactant_2': 'lactam', -# 'product': 'polyamide_chain', -# 'delete_atom': False, -# 'reaction': '[NX3H1;R:1]-[H:2].[CX3;R:3](=[OX1:4])[NX3H1;R:5]-[H:6]>>[NX3:1]-[CX3:3](=[OX1:4]).[NX3:5](-[H:2])-[H:6]', -# 'reference': -# { -# 'smarts': None, -# 'reaction_and_mechanism': None -# }, -# 'comments': -# } -# } + 'comments': None + }, + 'Di-Amine and Di-Carboxylic Acid Halide Polycondensation (Polyamidation)': { + 'same_reactants': False, + 'reactant_1': 'di_amine', + 'reactant_2': 'di_carboxylic_acid_halide', + 'product': 'polyamide_chain', + 'delete_atom': True, + 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[CX3:2](=[O:4])[Cl,Br,I:5]>>[NX3:1]-[CX3:2](=[O:4]).[Cl,Br,I:5]-[H:3]', + 'reference': { + 'smarts': ['https://pubs.acs.org/doi/10.1021/acs.jcim.3c00329'], + 'reaction_and_mechanism': [ + 'https://pubs.acs.org/doi/10.1021/ed048pA734' + ] + }, + 'comments': None + }, + 'Hydrolytic Initiation of Caprolactam': { + 'same_reactants': False, + 'reactant_1': 'water', + 'reactant_2': 'lactam', + 'product': 'polyamide_chain', + 'delete_atom': False, + 'reaction': '[O:1]-[H:12].[CX3:2]1(=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4]1-[H:6]>>[O:1]-[CX3:2](=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4](-[H:6])-[H:12]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': ['https://doi.org/10.1002/047147875X'] + }, + 'comments': None, + 'Notes': 'Validated on 2026-07-26, Passed' + }, + # 'Caprolactam Ring-Opening Polyamidation': { + # 'same_reactants': True, + # 'reactant_1': 'lactam', + # 'product': 'polyamide_chain', + # 'delete_atom': False, + # # Reactant 2 explicitly maps the 5 CH2 groups (maps 7 through 11) and uses '1' for the ring closure. + # # Product SMARTS removes the '.' and explicitly connects the opened chain. + # 'reaction': '[NX3:1]-[H:5].[CX3:2]1(=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4]1-[H:6]>>[NX3:1]-[CX3:2](=[OX1:3])-[CX4:7]-[CX4:8]-[CX4:9]-[CX4:10]-[CX4:11]-[NX3:4](-[H:5])-[H:6]', + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # 'comments': None + # }, + # 'Lactam and Lactam Ring-Opening Copolyamidation': { + # 'same_reactants': False, + # 'reactant_1': 'lactam', + # 'reactant_2': 'lactam', + # 'product': 'polyamide_chain', + # 'delete_atom': False, + # 'reaction': '[NX3H1;R:1]-[H:2].[CX3;R:3](=[OX1:4])[NX3H1;R:5]-[H:6]>>[NX3:1]-[CX3:3](=[OX1:4]).[NX3:5](-[H:2])-[H:6]', + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # 'comments': None + # } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polyanhydrides.py b/AutoREACTER/detectors/reactions_library/polyanhydrides.py index 513cd9a7..9bb33466 100644 --- a/AutoREACTER/detectors/reactions_library/polyanhydrides.py +++ b/AutoREACTER/detectors/reactions_library/polyanhydrides.py @@ -1,31 +1,27 @@ REACTIONS = { - 'Carboxylic Acid and Acid Halide Polycondensation(Polyanhydride Formation)': - { - 'same_reactants': True, - 'reactant_1': 'carboxylic_acid_acid_halide', - 'product': 'polyanhydride_chain', - 'delete_atom': True, - 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]', - 'reference': - { - 'smarts': None, - 'reaction_and_mechanism': None - }, - 'comments': None + 'Carboxylic Acid and Acid Halide Polycondensation (Polyanhydride Formation)': { + 'same_reactants': True, + 'reactant_1': 'carboxylic_acid_acid_halide', + 'product': 'polyanhydride_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None }, - 'Carboxylic Acid and Acid Halide Polycondensation(Polyanhydride Formation) - Different Reactants': - { - 'same_reactants': False, - 'reactant_1': 'carboxylic_acid_acid_halide', - 'reactant_2': 'carboxylic_acid_acid_halide', - 'product': 'polyanhydride_chain', - 'delete_atom': True, - 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]', - 'reference': - { - 'smarts': None, - 'reaction_and_mechanism': None - }, - 'comments': None - } + 'comments': None + }, + 'Carboxylic Acid and Acid Halide Copolycondensation (Polyanhydride Copolymerization)': { + 'same_reactants': False, + 'reactant_1': 'carboxylic_acid_acid_halide', + 'reactant_2': 'carboxylic_acid_acid_halide', + 'product': 'polyanhydride_chain', + 'delete_atom': True, + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polyimides.py b/AutoREACTER/detectors/reactions_library/polyimides.py index d3176ea6..d407f397 100644 --- a/AutoREACTER/detectors/reactions_library/polyimides.py +++ b/AutoREACTER/detectors/reactions_library/polyimides.py @@ -1,18 +1,15 @@ -# This reaction also needs to further studied and validated # REACTIONS = { -# 'Di-cyclic Anhydride and Di-Primary Amine Polycondensation (Polyimidation)': -# { -# 'same_reactants': False, -# 'reactant_1': 'di_cyclic_anhydride', -# 'reactant_2': 'di_primary_amine', -# 'product': 'polyimide_chain', -# 'delete_atom': True, -# 'reaction': '[NX3H2:1](-[H:6])-[H:8].[CX3;R:2](=[OX1:4])[OX2;R:5][CX3;R:3](=[OX1:7])>>[NX3:1]([CX3:2](=[OX1:4]))[CX3:3](=[OX1:7]).[OX2:5](-[H:6])-[H:8]', -# 'reference': -# { -# 'smarts': None, -# 'reaction_and_mechanism': None -# }, -# 'comments': None -# } +# 'Tetra-Amine and Di-Carboxylic Acid Polycondensation (PBI Formation)': { +# 'same_reactants': False, +# 'reactant_1': 'tetra_amine', +# 'reactant_2': 'di_carboxylic_acid', +# 'product': 'polybenzimidazole_chain', +# 'delete_atom': True, +# 'reaction': '[c:7]([NX3H2:1](-[H:6])-[H:9])-[c:8]([NX3H2:2](-[H:10])-[H:11]).[CX3:3](=[OX1:4])[OX2H1:5]-[H:12]>>[c:7]1-[NX3:1](-[H:6])-[CX3:3]=[NX2:2]-[c:8]-1.[OX2:4](-[H:9])-[H:10].[OX2:5](-[H:11])-[H:12]', +# 'reference': { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None # } +# } \ No newline at end of file From f2fb2f60c44a705ccff80ef47efddb519c060149 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:29:11 -0400 Subject: [PATCH 082/176] Normalization --- .../reactions_library/polysiloxanes.py | 80 +++++++++---------- .../reactions_library/polysulfides.py | 30 ++++--- .../reactions_library/polythioesters.py | 5 +- 3 files changed, 52 insertions(+), 63 deletions(-) diff --git a/AutoREACTER/detectors/reactions_library/polysiloxanes.py b/AutoREACTER/detectors/reactions_library/polysiloxanes.py index 4afe7f3c..f7f3e6a3 100644 --- a/AutoREACTER/detectors/reactions_library/polysiloxanes.py +++ b/AutoREACTER/detectors/reactions_library/polysiloxanes.py @@ -1,46 +1,40 @@ REACTIONS = { - 'Dichlorosilane Hydrolysis to Silanol': - { - 'same_reactants': False, - 'reactant_1': 'dichlorosilane', - 'reactant_2': 'water', - 'product': 'silanediol', - 'delete_atom': True, - 'reaction': '[Si:1]-[Cl:2].[OX2H2:3](-[H:4])-[H:5]>>[Si:1]-[OX2:3]-[H:4].[Cl:2]-[H:5]', - 'reference': - { - 'smarts': None, - 'reaction_and_mechanism': None - }, - "Note": "Tested, but LUNAR cannot parameterize silicone chemistry" + 'Dichlorosilane Hydrolysis to Silanol': { + 'same_reactants': False, + 'reactant_1': 'dichlorosilane', + 'reactant_2': 'water', + 'product': 'silanediol', + 'delete_atom': True, + 'reaction': '[Si:1]-[Cl:2].[OX2H2:3](-[H:4])-[H:5]>>[Si:1]-[OX2:3]-[H:4].[Cl:2]-[H:5]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None }, - 'Silanediol Polycondensation(Polysiloxane Formation)': - { - 'same_reactants': True, - 'reactant_1': 'silanediol', - 'product': 'polysiloxane_chain', - 'delete_atom': True, - 'reaction': '[Si:1]-[OX2H1:2]-[H:5].[Si:3]-[OX2H1:4]-[H:6]>>[Si:1]-[OX2:2]-[Si:3].[OX2:4](-[H:5])-[H:6]', - 'reference': - { - 'smarts': None, - 'reaction_and_mechanism': None - }, - "Note": "Tested, but LUNAR cannot parameterize silicone chemistry" + 'comments': None + }, + 'Silanediol Polycondensation(Polysiloxane Formation)': { + 'same_reactants': True, + 'reactant_1': 'silanediol', + 'product': 'polysiloxane_chain', + 'delete_atom': True, + 'reaction': '[Si:1]-[OX2H1:2]-[H:5].[Si:3]-[OX2H1:4]-[H:6]>>[Si:1]-[OX2:2]-[Si:3].[OX2:4](-[H:5])-[H:6]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None }, - 'Silanediol and Silanediol Copolycondensation(Polysiloxane Formation)': - { - 'same_reactants': False, - 'reactant_1': 'silanediol', - 'reactant_2': 'silanediol', - 'product': 'polysiloxane_chain', - 'delete_atom': True, - 'reaction': '[Si:1]-[OX2H1:2]-[H:5].[Si:3]-[OX2H1:4]-[H:6]>>[Si:1]-[OX2:2]-[Si:3].[OX2:4](-[H:5])-[H:6]', - 'reference': - { - 'smarts': None, - 'reaction_and_mechanism': None - }, - "Note": "Tested, but LUNAR cannot parameterize silicone chemistry" - } -} + 'comments': None + }, + 'Silanediol and Silanediol Copolycondensation(Polysiloxane Formation)': { + 'same_reactants': False, + 'reactant_1': 'silanediol', + 'reactant_2': 'silanediol', + 'product': 'polysiloxane_chain', + 'delete_atom': True, + 'reaction': '[Si:1]-[OX2H1:2]-[H:5].[Si:3]-[OX2H1:4]-[H:6]>>[Si:1]-[OX2:2]-[Si:3].[OX2:4](-[H:5])-[H:6]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + } +} \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polysulfides.py b/AutoREACTER/detectors/reactions_library/polysulfides.py index 65732c0f..4b0482b2 100644 --- a/AutoREACTER/detectors/reactions_library/polysulfides.py +++ b/AutoREACTER/detectors/reactions_library/polysulfides.py @@ -1,17 +1,15 @@ -# Polysulfide formation reactions are currently commented out as they are untested. # REACTIONS = { -# 'Organic Dihalide and Sodium Sulfide Polycondensation(Polysulfide Formation)': -# { -# 'same_reactants': False, -# 'reactant_1': 'organic_dihalide', -# 'reactant_2': 'sodium_sulfide', -# 'product': 'polysulfide_chain', -# 'delete_atom': True, -# 'reaction': '[CX4:1]-[Cl,Br,I:2].[S-2:3].[Na+:4].[Na+:5]>>[CX4:1]-[S-:3].[Cl-,Br-,I-:2].[Na+:4].[Na+:5]', -# 'reference': {'smarts': None, -# 'reaction_and_mechanism': None}, -# 'comments': 'UNTESTED new chemistry; ' -# 'one substitution event ' -# 'leaves a thiolate chain ' -# 'end for continued ' -# 'growth.'}} +# 'Organic Dihalide and Sodium Sulfide Polycondensation(Polysulfide Formation)': { +# 'same_reactants': False, +# 'reactant_1': 'organic_dihalide', +# 'reactant_2': 'sodium_sulfide', +# 'product': 'polysulfide_chain', +# 'delete_atom': True, +# 'reaction': '[CX4:1]-[Cl,Br,I:2].[S-2:3].[Na+:4].[Na+:5]>>[CX4:1]-[S-:3].[Cl-,Br-,I-:2].[Na+:4].[Na+:5]', +# 'reference': { +# 'smarts': None, +# 'reaction_and_mechanism': None +# }, +# 'comments': None +# } +# } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polythioesters.py b/AutoREACTER/detectors/reactions_library/polythioesters.py index 43dd6dc3..830a8a50 100644 --- a/AutoREACTER/detectors/reactions_library/polythioesters.py +++ b/AutoREACTER/detectors/reactions_library/polythioesters.py @@ -12,7 +12,6 @@ }, 'comments': None }, - 'Dithiol and Di-Carboxylic Acid Polycondensation(Polythioesterification)': { 'same_reactants': False, 'reactant_1': 'dithiol', @@ -24,9 +23,8 @@ 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': 'Possible thioesterification with water elimination, but generally less straightforward than acid-halide route.' + 'comments': None }, - 'Hydroxy-Thiol and Di-Carboxylic Acid Halide Polycondensation through Hydroxy Group': { 'same_reactants': False, 'reactant_1': 'hydroxy_thiol', @@ -40,7 +38,6 @@ }, 'comments': None }, - 'Hydroxy-Thiol and Di-Carboxylic Acid Halide Polycondensation through Thiol Group': { 'same_reactants': False, 'reactant_1': 'hydroxy_thiol', From d48858b7a3bc455c1d816b0fe0e16584b0133097 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:29:17 -0400 Subject: [PATCH 083/176] Create thiol_ene_polymers.py --- .../reactions_library/thiol_ene_polymers.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 AutoREACTER/detectors/reactions_library/thiol_ene_polymers.py diff --git a/AutoREACTER/detectors/reactions_library/thiol_ene_polymers.py b/AutoREACTER/detectors/reactions_library/thiol_ene_polymers.py new file mode 100644 index 00000000..c14641e3 --- /dev/null +++ b/AutoREACTER/detectors/reactions_library/thiol_ene_polymers.py @@ -0,0 +1,15 @@ +REACTIONS = { + 'Dithiol and Diene Thiol-Ene Click Polymerization': { + 'same_reactants': False, + 'reactant_1': 'dithiol', + 'reactant_2': 'diene', + 'product': 'poly_thioether_chain', + 'delete_atom': False, + 'reaction': '[SX2H1:1]-[H:5].[CH2:2]=[C;!R:3]>>[SX2:1]-[CH2:2]-[C:3]-[H:5]', + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None + } +} \ No newline at end of file From cd2f3c8e6c5e6f6facdfd15795dea2cdda2e510d Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:45:46 -0400 Subject: [PATCH 084/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- AutoREACTER/input_parser.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 9d9a8f77..8bfedb21 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -971,10 +971,10 @@ def _validate_loop(self, inputs: dict) -> tuple[bool, int | None]: if loop_value <= 0: raise InputSchemaError("'loop' must be a positive integer.") - print( - f"Reaction will be looped and maximum iterations set to {loop_value}" + logger.info( + "Looping enabled with maximum iterations set to %s", + loop_value, ) - time.sleep(5) return True, loop_value if isinstance(loop_value, str) and loop_value in loop_keywords: From adc3739e6d55cbb3c641b666e0728051706cfe85 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:45:57 -0400 Subject: [PATCH 085/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../reaction_preparation/reaction_processor/warning_asci.py | 1 - 1 file changed, 1 deletion(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py index 80c82cf0..8bfa6d48 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py @@ -24,5 +24,4 @@ def print_warning() -> None: "Caution: results can be chemically inaccurate." ) ascii_art(message) - time.sleep(5) From 8ae3698273727969027458670969749dac296bd8 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:46:06 -0400 Subject: [PATCH 086/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../reaction_processor/prepare_reactions.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index f4a754db..9c677252 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -460,8 +460,10 @@ def _process_reaction_products( ) print(f"Reactant 1 SMILES: {Chem.MolToSmiles(r1)}") print(f"Reactant 2 SMILES: {Chem.MolToSmiles(r2)}") - print("Reaction SMARTS: \n") - continue + print( + "Reaction SMARTS: " + f"{Chem.rdChemReactions.ReactionToSmarts(rxn)}\n" + ) for product_set in products: reactant_combined = Chem.CombineMols(r1, r2) From dc12f88b90c1735549ed8dedb369257e93bff60d Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:46:14 -0400 Subject: [PATCH 087/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- examples/test_ethelene.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/test_ethelene.json b/examples/test_ethelene.json index 14958a8e..622948a7 100644 --- a/examples/test_ethelene.json +++ b/examples/test_ethelene.json @@ -1,5 +1,5 @@ { - "simulation_name": "Epoxy_ethene", + "simulation_name": "Ethene_Test", "loop": 9, "simulations": [ { From 188d51a94fea1b0e0313f30f7fc8cac9ffe95072 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:46:23 -0400 Subject: [PATCH 088/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../reaction_processor/reaction_progression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 7724718a..b2d1d6be 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -155,7 +155,7 @@ def reaction_progression( f"Overriding default max_loop of {MAX_LOOP} with " f"user-specified max_loop_count of {max_loop}." ) - time.sleep(1) + # Avoid sleeping in library code; callers control pacing. iteration = 0 # Start from the monomer roles already present in the session. From b16c63f98d7f32599536282b8a9309a6fead4125 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:46:33 -0400 Subject: [PATCH 089/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- tests/test_input_parser.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_input_parser.py b/tests/test_input_parser.py index db20f965..18257d63 100644 --- a/tests/test_input_parser.py +++ b/tests/test_input_parser.py @@ -794,16 +794,13 @@ def test_validate_loop_accepts_booleans(self) -> None: (False, None), ) - @patch("AutoREACTER.input_parser.time.sleep") def test_validate_loop_accepts_positive_integer( self, - sleep_mock, ) -> None: self.assertEqual( self.parser._validate_loop({"loop": 4}), (True, 4), ) - sleep_mock.assert_called_once_with(5) def test_validate_loop_accepts_supported_keywords(self) -> None: for keyword in ("loop", "repeat", "iterations", "do_loop"): From 5f7d61218df2818f584255d4ed15b614b2d06e85 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 24 Jul 2026 16:15:10 -0400 Subject: [PATCH 090/176] Add TFE vinyl polymerization support --- .../vinyl_and_alkene_groups.py | 6 ++ .../detectors/reactions_library/registry.py | 57 +++++++++++++------ .../reactions_library/vinyl_polymers.py | 20 +++++++ examples/test.json | 19 +++++++ 4 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 examples/test.json diff --git a/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py b/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py index 1641eda1..569a0039 100644 --- a/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/vinyl_and_alkene_groups.py @@ -17,4 +17,10 @@ # 'group_name': 'bis_alkene', # 'comments': None # } + 'tetrafluoroethylene_monomer': { + 'functionality_type': 'vinyl', + 'smarts_1': '[CX3](-[F])(-[F])=[CX3](-[F])(-[F])', + 'group_name': 'tetrafluoroethylene', + 'comments': None + } } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/registry.py b/AutoREACTER/detectors/reactions_library/registry.py index 30eb35ba..65b35114 100644 --- a/AutoREACTER/detectors/reactions_library/registry.py +++ b/AutoREACTER/detectors/reactions_library/registry.py @@ -1,23 +1,36 @@ """Aggregate and validate all polymer-family reaction modules.""" +try: + from .polyesters import REACTIONS as POLYESTERS + # from .polyethers import REACTIONS as POLYETHERS + from .polyamides import REACTIONS as POLYAMIDES + from .polyanhydrides import REACTIONS as POLYANHYDRIDES + from .polythioesters import REACTIONS as POLYTHIOESTERS + from .polyurethanes import REACTIONS as POLYURETHANES + from .polyureas import REACTIONS as POLYUREAS + from .epoxy_polymers import REACTIONS as EPOXY_POLYMERS + from .vinyl_polymers import REACTIONS as VINYL_POLYMERS + from .polycarbonates import REACTIONS as POLYCARBONATES + # from .polyimides import REACTIONS as POLYIMIDES + # from .polybenzimidazoles import REACTIONS as POLYBENZIMIDAZOLES + # from .phenolic_resins import REACTIONS as PHENOLIC_RESINS + from .polysiloxanes import REACTIONS as POLYSILOXANES + # from .polysulfides import REACTIONS as POLYSULFIDES + from .thiol_ene_polymers import REACTIONS as THIOL_ENE_POLYMERS + # from .metathesis_polymers import REACTIONS as METATHESIS_POLYMERS + # from .cycloaddition_polymers import REACTIONS as CYCLOADDITION_POLYMERS -from .polyesters import REACTIONS as POLYESTERS -# from .polyethers import REACTIONS as POLYETHERS -from .polyamides import REACTIONS as POLYAMIDES -from .polyanhydrides import REACTIONS as POLYANHYDRIDES -from .polythioesters import REACTIONS as POLYTHIOESTERS -from .polyurethanes import REACTIONS as POLYURETHANES -from .polyureas import REACTIONS as POLYUREAS -from .epoxy_polymers import REACTIONS as EPOXY_POLYMERS -from .vinyl_polymers import REACTIONS as VINYL_POLYMERS -from .polycarbonates import REACTIONS as POLYCARBONATES -# from .polyimides import REACTIONS as POLYIMIDES -# from .polybenzimidazoles import REACTIONS as POLYBENZIMIDAZOLES -# from .phenolic_resins import REACTIONS as PHENOLIC_RESINS -from .polysiloxanes import REACTIONS as POLYSILOXANES -# from .polysulfides import REACTIONS as POLYSULFIDES -from .thiol_ene_polymers import REACTIONS as THIOL_ENE_POLYMERS -# from .metathesis_polymers import REACTIONS as METATHESIS_POLYMERS -# from .cycloaddition_polymers import REACTIONS as CYCLOADDITION_POLYMERS +except ImportError as e: + from polyesters import REACTIONS as POLYESTERS + from polyamides import REACTIONS as POLYAMIDES + from polyanhydrides import REACTIONS as POLYANHYDRIDES + from polythioesters import REACTIONS as POLYTHIOESTERS + from polyurethanes import REACTIONS as POLYURETHANES + from polyureas import REACTIONS as POLYUREAS + from epoxy_polymers import REACTIONS as EPOXY_POLYMERS + from vinyl_polymers import REACTIONS as VINYL_POLYMERS + from polycarbonates import REACTIONS as POLYCARBONATES + from polysiloxanes import REACTIONS as POLYSILOXANES + from thiol_ene_polymers import REACTIONS as THIOL_ENE_POLYMERS _REACTION_MODULES = [ POLYESTERS, @@ -62,3 +75,11 @@ class ReactionLibrary: def __init__(self): self.reactions = load_reactions() + + +if __name__ == "__main__": + REACTIONS = load_reactions() + num = 0 + for reaction_name, reaction in REACTIONS.items(): + num += 1 + print(f"{num:3}. AutoREACTER can support the reaction: {reaction_name}") \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py index bca2d62f..faec21fc 100644 --- a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -76,4 +76,24 @@ # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, # 'comments': None # } + + 'Tetrafluoroethylene Addition Polymerization Initiation': { + 'same_reactants': True, + 'reactant_1': 'tetrafluoroethylene', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + 'reaction': '[CX3:1](-[F:5])(-[F:6])=[C;!R:3](-[F:7])(-[F:8]).[CX3:2](-[F:9])(-[F:10])=[C;!R:4](-[F:11])(-[F:12])>>[CX3:1](-[F:5])(-[F:6])(-[C:3](-[F:7])(-[F:8]))-[CX3:2](-[F:9])(-[F:10])-[C;!R;D3;v3:4](-[F:11])(-[F:12])', + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': 'Self-initiation cheat for TFE polymerization' + }, + 'Tetrafluoroethylene Addition Polymerization Propagation': { + 'same_reactants': False, + 'reactant_1': 'tetrafluoroethylene', + 'reactant_2': 'vinyl_chain_end_radical', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + 'reaction': '[CX3:2](-[F:5])(-[F:6])=[C;!R:3](-[F:7])(-[F:8]).[C;!R;D3;v3:1](-[F:9])(-[F:10])>>[C:1](-[F:9])(-[F:10])-[CX3:2](-[F:5])(-[F:6])-[C;!R;D3;v3:3](-[F:7])(-[F:8])', + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': 'Propagation step carrying the radical center forward for TFE' + } } \ No newline at end of file diff --git a/examples/test.json b/examples/test.json new file mode 100644 index 00000000..54e6bd19 --- /dev/null +++ b/examples/test.json @@ -0,0 +1,19 @@ +{ + "simulation_name": "TFE_Test", + "simulations": [ + { + "tag": "tfe_test", + "temperature": 300, + "density": 1.5, + "monomer_counts": { + "tetrafluoroethylene": 200 + } + } + ], + "monomers": [ + { + "name": "tetrafluoroethylene", + "smiles": "C(=C(F)F)(F)F" + } + ] +} From 71b2a3b70cf64e43acf3397c27b76531cfc8df07 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 27 Jul 2026 14:36:02 -0400 Subject: [PATCH 091/176] Bump to v0.3 and update reaction workflows --- AutoREACTER/__init__.py | 2 +- .../detectors/reactions_library/registry.py | 11 +- .../deduplication_detector.py | 2 +- .../reaction_progression.py | 1 - .../writers/rxn_first_stage_writer.py | 24 ++- docs/source/supported-reactions.md | 184 ++++++++++++++---- 6 files changed, 174 insertions(+), 50 deletions(-) diff --git a/AutoREACTER/__init__.py b/AutoREACTER/__init__.py index 7c18550a..0a0bf2cb 100644 --- a/AutoREACTER/__init__.py +++ b/AutoREACTER/__init__.py @@ -3,7 +3,7 @@ AutoREACTER is a tool for automated reaction-based molecular system generation. """ -__version__ = "0.2.3" +__version__ = "0.3" __title__ = "AutoREACTER" __author__ = "Janitha Mahanthe, Jacob Gissinger" diff --git a/AutoREACTER/detectors/reactions_library/registry.py b/AutoREACTER/detectors/reactions_library/registry.py index 65b35114..48a70977 100644 --- a/AutoREACTER/detectors/reactions_library/registry.py +++ b/AutoREACTER/detectors/reactions_library/registry.py @@ -80,6 +80,11 @@ def __init__(self): if __name__ == "__main__": REACTIONS = load_reactions() num = 0 - for reaction_name, reaction in REACTIONS.items(): - num += 1 - print(f"{num:3}. AutoREACTER can support the reaction: {reaction_name}") \ No newline at end of file + + with open("reactions.txt", "w") as f: + for reaction in REACTIONS.items(): + f.write(str(reaction) + "\n") + reaction_len = len(REACTIONS) + import os + file_abs_path = os.path.abspath("reactions.txt") + print(f"reactions.txt has been written to {file_abs_path}, num reactions: {reaction_len}") \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 70c35c5e..e37ec327 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -8,7 +8,6 @@ """ from __future__ import annotations - from pathlib import Path from typing import TYPE_CHECKING @@ -1016,6 +1015,7 @@ def _is_radical_atom(atom: Chem.Atom) -> bool: # A normal carbon with an implicit hydrogen can have only three visible # graph bonds. Do not classify it as a radical. try: + atom.GetOwningMol().UpdatePropertyCache(strict=False) if atom.GetNumImplicitHs() > 0: return False except RuntimeError: diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index b2d1d6be..7d04787f 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -10,7 +10,6 @@ """ from dataclasses import dataclass, field -import time from typing import TYPE_CHECKING from rdkit import Chem diff --git a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py index 41bb2c3a..ade793be 100644 --- a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py @@ -140,20 +140,26 @@ def write_first_stage_reaction_files(self, simulation: Simulation) -> str: lines.append("#------------Define Reaction Templates------------") rxn_commands: list[str] = [] - for i, template in enumerate(rf.template_files, 1): - pre_id = f"mol_pre_{i}" - post_id = f"mol_post_{i}" + for template in (rf.template_files): # Extract filenames from the dataclass fields pre_file = template.pre_reaction_file.lmp_molecule_file.name post_file = template.post_reaction_file.lmp_molecule_file.name map_file = template.map_file.name + id = template.reaction_id + pre_id = f"mol_pre_{id}" + post_id = f"mol_post_{id}" - lines.append(f"{'molecule':<16} {pre_id} {pre_file}") - lines.append(f"{'molecule':<16} {post_id} {post_file}\n") - + lines.append(f"{'molecule':<16} {pre_id:<16} {pre_file}") + lines.append(f"{'molecule':<16} {post_id:<16} {post_file}\n") + rxn_stp = f"rxn_stp_{id}" rxn_str = ( - f"react rxn_stp_{i} all 1 0.0 3.5 {pre_id} {post_id} {map_file} " + f"react " + f"{rxn_stp:<15} " + f"all 1 0.0 3.5 " + f"{pre_id:<14} " + f"{post_id:<15} " + f"{map_file:<15} " f"stabilize_steps 60 rescale_charges yes" ) rxn_commands.append(rxn_str) @@ -162,8 +168,8 @@ def write_first_stage_reaction_files(self, simulation: Simulation) -> str: lines.extend([ "", - f"{'fix':<16} rxns all bond/react stabilization yes statted_grp 0.03 &", - f"{'':<16} {all_reactions}", + f"{'fix':<16}rxns all bond/react stabilization yes statted_grp 0.03 &", + f"{'':<16}{all_reactions}", "", "", "# Note: If atoms are being deleted during the reaction, ensure you use the correct Map file", diff --git a/docs/source/supported-reactions.md b/docs/source/supported-reactions.md index bc2ff2f6..5d10cd3a 100644 --- a/docs/source/supported-reactions.md +++ b/docs/source/supported-reactions.md @@ -1,12 +1,12 @@ ## Supported Reactions -AutoREACTER is currently in **v0.2.2-beta**. At this stage of development, the reaction library is limited to selected step-growth polymerization reactions, including **polycondensation**, **transesterification**, and **polyaddition** reactions. +AutoREACTER is currently in **v{{ autoreacter_version }}**. At this stage of development, the reaction library supports a broad range of step-growth and chain-growth polymerization reactions, including **polycondensation**, **transesterification**, **polyaddition**, **hydrolysis initiation**, and **addition polymerization**. The core `Detector` module automatically identifies the following functional groups and maps them to their respective reaction pathways. **Important:** If your `input.json` contains monomers with functional groups outside of this list, AutoREACTER will classify them as *non-reactive molecules* (which you can choose to retain as solvents/additives or discard). -**NOTE:** Certain force fields do not support all atom types; for example, iodine ``(I)`` is sometimes unsupported. +**NOTE:** Certain force fields do not support all atom types; for example, iodine `(I)` is sometimes unsupported. --- @@ -14,25 +14,34 @@ The core `Detector` module automatically identifies the following functional gro These reactions form ester linkages (`-COO-`) and typically release water (`H₂O`), alcohols (`R-OH`), or hydrogen halides (e.g., `HCl`) as byproducts. -* **Hydroxy–Carboxylic Acid Polycondensation** +* **Hydroxy Carboxylic Acid Polycondensation** +* *Reactants:* `-OH` + `-COOH` - * *Reactants:* `-OH` + `-COOH` -* **Hydroxy Acid Halide Polycondensation** +* **Hydroxy Carboxylic and Hydroxy Carboxylic Polycondensation** +* *Reactants:* `-OH` + `-COOH` (Intermolecular) - * *Reactants:* `-OH` + `-COX` where `X = Cl, Br, I` -* **Diol + Di-Carboxylic Acid Polycondensation** +* **Hydroxy Acid Halides Polycondensation** +* *Reactants:* `-OH` + `-COX` where `X = Cl, Br, I` - * *Reactants:* Two `-OH` groups + Two `-COOH` groups -* **Diol + Di-Acid Halide Polycondensation** +* **Hydroxy Acid Halides Hydroxy Acid Halides Polycondensation** +* *Reactants:* `-OH` + `-COX` where `X = Cl, Br, I` (Intermolecular) - * *Reactants:* Two `-OH` groups + Two `-COX` groups where `X = Cl, Br, I` -* **Diol + Di-Carboxylic Ester Transesterification** +* **Diol and Di-Carboxylic Acid Polycondensation** +* *Reactants:* Two `-OH` groups + Two `-COOH` groups + + +* **Diol and Di-Acid Halide Polycondensation** +* *Reactants:* Two `-OH` groups + Two `-COX` groups where `X = Cl, Br, I` + + +* **Diol and Di-Carboxylic Ester Polycondensation (Transesterification)** +* *Reactants:* Two `-OH` groups + Two ester groups (`-COOR`) + - * *Reactants:* Two `-OH` groups + Two ester groups (`-COOR`) --- @@ -41,20 +50,25 @@ These reactions form ester linkages (`-COO-`) and typically release water (`H₂ These reactions form amide linkages (`-CONH-`) and typically release water (`H₂O`) or hydrogen halides (e.g., `HCl`) as byproducts. * **Amino Acid Polycondensation** +* *Reactants:* `-NH₂` / `-NH-` + `-COOH` - * *Reactants:* `-NH₂` / `-NH-` + `-COOH` -* **Amino Acid + Amino Acid Polycondensation** +* **Amino Acid and Amino Acid Polycondensation** +* *Reactants:* `-NH₂` / `-NH-` + `-COOH` (Intermolecular) - * *Reactants:* `-NH₂` / `-NH-` + `-COOH` -* **Diamine + Di-Carboxylic Acid Polycondensation** +* **Di-Amine and Di-Carboxylic Acid Polycondensation** +* *Reactants:* Two amine groups (`-NH₂` / `-NH-`) + Two `-COOH` groups - * *Reactants:* Two amine groups (`-NH₂` / `-NH-`) + Two `-COOH` groups -* **Diamine + Di-Carboxylic Acid Halide Polycondensation** +* **Di-Amine and Di-Carboxylic Acid Halide Polycondensation** +* *Reactants:* Two amine groups (`-NH₂` / `-NH-`) + Two `-COX` groups where `X = Cl, Br, I` + + +* **Hydrolytic Initiation of Caprolactam** +* *Reactants:* Water (`H₂O`) + Lactam ring opening + - * *Reactants:* Two amine groups (`-NH₂` / `-NH-`) + Two `-COX` groups where `X = Cl, Br, I` --- @@ -62,9 +76,14 @@ These reactions form amide linkages (`-CONH-`) and typically release water (`H These reactions form anhydride linkages (`-CO-O-CO-`) and typically release hydrogen halides (e.g., `HCl`) as byproducts. -* **Carboxylic Acid + Acid Halide Polycondensation** +* **Carboxylic Acid and Acid Halide Polycondensation** +* *Reactants:* `-COOH` + `-COX` where `X = Cl, Br, I` + + +* **Carboxylic Acid and Acid Halide Copolycondensation** +* *Reactants:* Mixed `-COOH` + `-COX` copolymerization systems + - * *Reactants:* `-COOH` + `-COX` where `X = Cl, Br, I` --- @@ -72,13 +91,14 @@ These reactions form anhydride linkages (`-CO-O-CO-`) and typically release hydr These reactions form thioester linkages (`-COS-`) and typically release water (`H₂O`) or hydrogen halides (e.g., `HCl`) as byproducts. -* **Dithiol + Di-Carboxylic Acid Polycondensation** +* **Dithiol and Di-Carboxylic Acid Halide Polycondensation** +* *Reactants:* Two `-SH` groups + Two `-COX` groups where `X = Cl, Br, I` - * *Reactants:* Two `-SH` groups + Two `-COOH` groups -* **Dithiol + Di-Carboxylic Acid Halide Polycondensation** +* **Dithiol and Di-Carboxylic Acid Polycondensation** +* *Reactants:* Two `-SH` groups + Two `-COOH` groups + - * *Reactants:* Two `-SH` groups + Two `-COX` groups where `X = Cl, Br, I` --- @@ -86,25 +106,119 @@ These reactions form thioester linkages (`-COS-`) and typically release water (` These reactions are supported for hydroxy–thiol monomers reacting with acid halides. Depending on the reacting group, either an ester or thioester linkage can be formed. -* **Hydroxy–Thiol + Di-Carboxylic Acid Halide through Hydroxy Group** +* **Hydroxy-Thiol and Di-Carboxylic Acid Halide Polycondensation through Hydroxy Group** +* *Reactants:* `-OH` + `-COX` where `X = Cl, Br, I` + + +* **Hydroxy-Thiol and Di-Carboxylic Acid Halide Polycondensation through Thiol Group** +* *Reactants:* `-SH` + `-COX` where `X = Cl, Br, I` + + + +--- + +### 6. Polyurethane, Polythiourethane, and Polyurea Formation + +These reactions form urethane, thiourethane, or urea linkages via **polyaddition** pathways. + +* **Diol and Di-Isocyanate Polyaddition (Polyurethane Formation)** +* *Reactants:* Two `-OH` groups + Two isocyanate groups (`-NCO`) + + +* **Dithiol and Di-Isocyanate Polyaddition (Polythiourethane Formation)** +* *Reactants:* Two `-SH` groups + Two isocyanate groups (`-NCO`) + + +* **Di-Amine and Di-Isocyanate Polyaddition (Polyurea Formation)** +* *Reactants:* Two amine groups (`-NH₂` / `-NH-`) + Two isocyanate groups (`-NCO`) + + + +--- + +### 7. Epoxy-Amine Addition and Crosslinking + +These reactions model step-growth/network formation between amine curing agents and epoxy rings. + +* **Primary Amine and Epoxide Polyaddition (First Addition)** +* *Reactants:* Primary amine (`-NH₂`) + Epoxide ring + + +* **Secondary Amine and Epoxide Polyaddition (Second Addition / Crosslink)** +* *Reactants:* Secondary amine (`-NH-`) + Epoxide ring + + + +--- + +### 8. Vinyl and Fluoropolymer Addition Polymerization + +These chain-growth pathways model radical initiation, propagation, and copolymerization of vinyl and fluorinated monomers. + +* **Vinyl Addition Polymerization Initiation** +* *Reactants:* Vinyl double bonds (`-CH=C-`) + + +* **Vinyl Addition Polymerization Propagation** +* *Reactants:* Vinyl monomer + Chain-end radical + + +* **Vinyl Copolymerization** +* *Reactants:* Mixed vinyl monomer systems + + +* **Tetrafluoroethylene Addition Polymerization Initiation** +* *Reactants:* Tetrafluoroethylene (`TFE`) self-initiation + + +* **Tetrafluoroethylene Addition Polymerization Propagation** +* *Reactants:* Tetrafluoroethylene monomer + TFE radical chain-end + + + +--- + +### 9. Polycarbonate Formation + +These reactions build carbonate linkages via condensation or transcarbonation. + +* **Diol and Phosgene Polycondensation (Polycarbonate Formation)** +* *Reactants:* Two `-OH` groups + Phosgene (`COCl₂`) + + +* **Diol and Diphenyl Carbonate Polycondensation (Transcarbonation)** +* *Reactants:* Two `-OH` groups + Diphenyl carbonate + + + +--- + +### 10. Polysiloxane Formation + +These pathways handle hydrolysis of chlorosilanes and condensation of silanols into silicone chains. + +* **Dichlorosilane Hydrolysis to Silanol** +* *Reactants:* Dichlorosilane (`-Si-Cl`) + Water (`H₂O`) + + +* **Silanediol Polycondensation (Polysiloxane Formation)** +* *Reactants:* Silanediols (`-Si-OH`) + - * *Reactants:* `-OH` + `-COX` where `X = Cl, Br, I` +* **Silanediol and Silanediol Copolycondensation (Polysiloxane Formation)** +* *Reactants:* Mixed silanediol systems -* **Hydroxy–Thiol + Di-Carboxylic Acid Halide through Thiol Group** - * *Reactants:* `-SH` + `-COX` where `X = Cl, Br, I` --- -### 6. Polyurethane Formation +### 11. Thiol-Ene Click Polymerization -These reactions form urethane linkages (`-O-CO-NH-`). Unlike most polycondensation reactions, this reaction is a **polyaddition** reaction. +* **Dithiol and Diene Thiol-Ene Click Polymerization** +* *Reactants:* Dithiol (`-SH`) + Diene (`-C=C-`) -* **Diol + Di-Isocyanate Polyaddition** - * *Reactants:* Two `-OH` groups + Two isocyanate groups (`-NCO`) --- -NOTE: If you would like support for a specific reaction, please open an issue on - [AutoREACTER GitHub Repository](https://github.com/NanoCIPHER-Lab/AutoREACTER). +NOTE: If you would like support for a specific reaction, please open an issue on [AutoREACTER GitHub Repository](https://github.com/NanoCIPHER-Lab/AutoREACTER). \ No newline at end of file From 014e3e0cd827ee54f1dbb33a97a81d947d754095 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 27 Jul 2026 15:31:27 -0400 Subject: [PATCH 092/176] Add LAMMPS template deduplication step --- .../deduplication_detector.py | 77 +++++++++++++++++-- .../ff_wrapper/REACTER_files_builder.py | 12 ++- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index e37ec327..644a6ad0 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -18,6 +18,9 @@ from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( ReactionMetadata, ) + from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import ( + TemplateFile, + ) class DeduplicationDetector: @@ -636,14 +639,78 @@ def lammps_molecule_to_networkx( file_path=file_path, ) - print( - f"Graph created from {file_path.name}: " - f"{graph.number_of_nodes()} atoms and " - f"{graph.number_of_edges()} bonds." - ) + # print( + # f"Graph created from {file_path.name}: " + # f"{graph.number_of_nodes()} atoms and " + # f"{graph.number_of_edges()} bonds." + # ) return graph + def compare_lammps_templates( + self, + template_files: list["TemplateFile"], + ) -> list["TemplateFile"]: + """ + Compare LAMMPS pre/post molecule-template pairs. + + Filters a list of TemplateFile objects by generating LAMMPS graphs + for their pre and post reaction files, detecting duplicates, and + returning a list containing only unique templates. + """ + # Clear the cache for a fresh deduplication pass + self.clear_cache(self.LAMMPS_COMPARISON_GROUP) + + unique_templates: list["TemplateFile"] = [] + + for template in template_files: + # Safely check if the template has both required files + if template.pre_reaction_file is None or template.post_reaction_file is None: + print( + f"Skipping template ID {template.reaction_id}: " + "Missing pre or post reaction file definitions." + ) + continue + + pre_file_path = template.pre_reaction_file.lmp_molecule_file + post_file_path = template.post_reaction_file.lmp_molecule_file + + if not pre_file_path.is_file(): + print( + f"Skipping template ID {template.reaction_id}: " + f"Pre-template file does not exist: {pre_file_path}" + ) + continue + + if not post_file_path.is_file(): + print( + f"Skipping template ID {template.reaction_id}: " + f"Post-template file does not exist: {post_file_path}" + ) + continue + + # Convert to graphs + pre_graph = self.lammps_molecule_to_networkx(pre_file_path) + post_graph = self.lammps_molecule_to_networkx(post_file_path) + + # Check if this pair has been seen before + duplicate = self.is_duplicate_pair( + pre_graph=pre_graph, + post_graph=post_graph, + comparison_group=self.LAMMPS_COMPARISON_GROUP, + ) + + # status = "Duplicate" if duplicate else "Unique" + # print( + # f"{status} template ID {template.reaction_id}: " + # f"{pre_file_path.name} -> {post_file_path.name}" + # ) + + if not duplicate: + unique_templates.append(template) + + return unique_templates + # ------------------------------------------------------------------ # Reaction-index selection # ------------------------------------------------------------------ diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index 1114a480..0eb61614 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -26,6 +26,7 @@ from typing import Optional import datetime import re +from AutoREACTER.reaction_preparation.deduplication_detector import DeduplicationDetector from AutoREACTER.reaction_preparation.ff_wrapper.ff_wrapper import FFFiles from AutoREACTER.reaction_preparation.ff_wrapper.modifiers_molecule_files import ( modify_types, modify_charges, modify_coords, @@ -92,7 +93,7 @@ def __init__( ) self.force_field = self.updated_inputs_with_3d_mols.force_field - + def _get_ending_integer(self, s: str) -> int | None: """ @@ -782,5 +783,12 @@ def molecule_template_preparation(self, session: "Session") -> None: session.reacter_files = reacter_files - + + # print (session.reacter_files) + detector = DeduplicationDetector() + template_files = session.reacter_files.template_files + # print("Comparing LAMMPS templates for duplicates...") + session.reacter_files.template_files = detector.compare_lammps_templates( + template_files=template_files + ) return None \ No newline at end of file From 8cce4dd55c3b406389b8ce9fd54b65746e3e953d Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 28 Jul 2026 12:08:42 -0400 Subject: [PATCH 093/176] Add s_m sulfone params to PCFF force field --- .../ff_wrapper/FF_files/pcff.frc | 112 +++++++++++++++++- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc index 07ecac85..50875e24 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc +++ b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc @@ -163,6 +163,7 @@ 1.0 1 p 30.97380 P 4 general phosphorous atom 1.0 1 p= 30.97380 P 5 phosphazene phosphorous atom 1.0 1 s 32.06400 S 2 sp3 sulfur + 1.0 1 s_m 32.06400 S 2 sulfone sulfur # Duplicated from base parameter 's' 1.0 1 s' 32.06400 S 1 S in thioketone group 1.0 1 s- 32.06400 S 1 partial double sulfur 1.0 1 s1 32.06400 S 2 sp3 sulfur involved in (S-S) group of disulfides @@ -487,6 +488,7 @@ 2.0 2 br op 0.3140 -0.3140 2.0 2 br p -0.2156 0.2156 2.0 2 br s -0.0437 0.0437 + 2.0 2 br s_m -0.0437 0.0437 # Duplicated from base parameter 's' 2.0 2 br s' 0.0034 -0.0034 2.0 2 br si -0.3273 0.3273 2.0 2 br sp 0.0034 -0.0034 @@ -523,6 +525,7 @@ 2.0 2 c p 0.0110 -0.0110 3.1 12 c p= -0.0500 0.0500 1.0 1 c s 0.0650 -0.0650 + 1.0 1 c s_m 0.0650 -0.0650 # Duplicated from base parameter 's' 2.2 9 c si -0.1350 0.1350 2.0 2 c si -0.1767 0.1767 1.0 4 c sio -0.1000 0.1000 @@ -550,6 +553,7 @@ 2.0 2 c- op 0.3241 -0.3241 2.0 2 c- p -0.0857 0.0857 2.0 2 c- s -0.0087 0.0087 + 2.0 2 c- s_m -0.0087 0.0087 # Duplicated from base parameter 's' 2.0 2 c- s- -0.1223 -0.3777 2.0 2 c- si -0.2775 0.2775 2.0 1 c= c= 0.0000 0.0000 @@ -578,6 +582,7 @@ 2.0 2 c= op 0.3583 -0.3583 2.0 2 c= p -0.0380 0.0380 2.0 2 c= s -0.0120 0.0120 + 2.0 2 c= s_m -0.0120 0.0120 # Duplicated from base parameter 's' 2.0 2 c= s' 0.0732 -0.0732 2.0 2 c= si -0.2270 0.2270 2.0 2 c= sp 0.0732 -0.0732 @@ -605,6 +610,7 @@ 2.0 2 c=1 op 0.3583 -0.3583 2.0 2 c=1 p -0.0380 0.0380 2.0 2 c=1 s -0.0120 0.0120 + 2.0 2 c=1 s_m -0.0120 0.0120 # Duplicated from base parameter 's' 2.0 2 c=1 s' 0.0732 -0.0732 2.0 2 c=1 si -0.2270 0.2270 2.0 2 c=1 sp 0.0732 -0.0732 @@ -633,6 +639,7 @@ 2.0 2 c=2 op 0.3583 -0.3583 2.0 2 c=2 p -0.0380 0.0380 2.0 2 c=2 s -0.0120 0.0120 + 2.0 2 c=2 s_m -0.0120 0.0120 # Duplicated from base parameter 's' 2.0 2 c=2 s' 0.0732 -0.0732 2.0 2 c=2 si -0.2270 0.2270 2.0 2 c=2 sp 0.0732 -0.0732 @@ -658,6 +665,7 @@ 1.0 1 c_0 op 0.0283 -0.0283 2.0 2 c_0 p -0.2396 0.2396 2.0 2 c_0 s -0.0140 0.0140 + 2.0 2 c_0 s_m -0.0140 0.0140 # Duplicated from base parameter 's' 2.0 3 c_0 s' 0.0000 0.0000 2.0 2 c_0 si -0.4405 0.4405 1.0 1 c_0 sp -0.0130 0.0130 @@ -685,6 +693,7 @@ 1.0 1 c_1 op 0.0283 -0.0283 2.0 2 c_1 p -0.2396 0.2396 2.0 2 c_1 s -0.0140 0.0140 + 2.0 2 c_1 s_m -0.0140 0.0140 # Duplicated from base parameter 's' 2.0 3 c_1 s' 0.0000 0.0000 2.0 2 c_1 si -0.4405 0.4405 1.0 1 c_1 sp -0.0130 0.0130 @@ -712,6 +721,7 @@ 2.0 2 cl p -0.2544 0.2544 3.1 12 cl p= -0.1200 0.1200 2.0 2 cl s -0.0898 0.0898 + 2.0 2 cl s_m -0.0898 0.0898 # Duplicated from base parameter 's' 2.0 2 cl s' -0.0457 0.0457 2.0 2 cl si -0.3598 0.3598 2.0 2 cl sp -0.0457 0.0457 @@ -738,6 +748,7 @@ 1.0 2 cp p -0.0380 0.0380 3.1 12 cp p= -0.0600 0.0600 2.0 2 cp s -0.0120 0.0120 + 2.0 2 cp s_m -0.0120 0.0120 # Duplicated from base parameter 's' 2.0 2 cp s' 0.0732 -0.0732 2.2 9 cp si -0.1170 0.1170 2.0 2 cp si -0.2270 0.2270 @@ -764,6 +775,7 @@ 2.0 2 ct o 0.0675 -0.0675 2.0 2 ct p -0.1335 0.1335 2.0 2 ct s -0.0522 0.0522 + 2.0 2 ct s_m -0.0522 0.0522 # Duplicated from base parameter 's' 2.0 2 ct si -0.3266 0.3266 2.0 4 cz oo 0.5000 -0.5000 2.0 4 cz oz 0.1000 -0.1000 @@ -785,6 +797,7 @@ 2.0 2 f p -0.3869 0.3869 3.1 12 f p= -0.1800 0.1800 2.0 2 f s -0.2380 0.2380 + 2.0 2 f s_m -0.2380 0.2380 # Duplicated from base parameter 's' 2.0 2 f s' -0.2011 0.2011 2.0 2 f si -0.4789 0.4789 2.0 2 f sp -0.2011 0.2011 @@ -794,6 +807,7 @@ 2.0 2 h p -0.0356 0.0356 3.1 12 h p= -0.0500 0.0500 2.0 2 h s 0.1392 -0.1392 + 2.0 2 h s_m 0.1392 -0.1392 # Duplicated from base parameter 's' 2.0 2 h s' 0.1932 -0.1932 2.2 9 h si -0.1260 0.1260 2.0 2 h si -0.1537 0.1537 @@ -835,6 +849,7 @@ 2.0 2 i op 0.3297 -0.3297 2.0 2 i p -0.2110 0.2110 2.0 2 i s -0.0345 0.0345 + 2.0 2 i s_m -0.0345 0.0345 # Duplicated from base parameter 's' 2.0 2 i s' 0.0140 -0.0140 2.0 2 i si -0.3263 0.3263 2.0 2 i sp 0.0140 -0.0140 @@ -853,6 +868,7 @@ 2.0 2 n p -0.3359 0.3359 3.1 12 n p= -0.1200 0.1200 2.0 2 n s -0.1753 0.1753 + 2.0 2 n s_m -0.1753 0.1753 # Duplicated from base parameter 's' 2.0 2 n s' -0.1346 0.1346 2.0 2 n si -0.4368 0.4368 2.0 2 n sp -0.1346 0.1346 @@ -869,6 +885,7 @@ 2.0 2 n+ op 0.3418 -0.0918 2.0 2 n+ p -0.1994 0.4494 2.0 2 n+ s -0.0255 0.2755 + 2.0 2 n+ s_m -0.0255 0.2755 # Duplicated from base parameter 's' 2.0 2 n+ s' 0.0159 0.2341 2.0 2 n+ si -0.3083 0.5583 2.0 2 n+ sp 0.0159 0.2341 @@ -885,6 +902,7 @@ 2.0 2 n= p -0.3359 0.3359 3.1 12 n= p= -0.3500 0.3500 2.0 2 n= s -0.1753 0.1753 + 2.0 2 n= s_m -0.1753 0.1753 # Duplicated from base parameter 's' 2.0 2 n= s' -0.1346 0.1346 2.0 2 n= si -0.4368 0.4368 2.0 2 n= sp -0.1346 0.1346 @@ -899,6 +917,7 @@ 2.0 2 n=1 op 0.1684 -0.1684 2.0 2 n=1 p -0.3359 0.3359 2.0 2 n=1 s -0.1753 0.1753 + 2.0 2 n=1 s_m -0.1753 0.1753 # Duplicated from base parameter 's' 2.0 2 n=1 s' -0.1346 0.1346 2.0 2 n=1 si -0.4368 0.4368 2.0 2 n=1 sp -0.1346 0.1346 @@ -913,6 +932,7 @@ 2.0 2 n=2 op 0.1684 -0.1684 2.0 2 n=2 p -0.3359 0.3359 2.0 2 n=2 s -0.1753 0.1753 + 2.0 2 n=2 s_m -0.1753 0.1753 # Duplicated from base parameter 's' 2.0 2 n=2 s' -0.1346 0.1346 2.0 2 n=2 si -0.4368 0.4368 2.0 2 n=2 sp -0.1346 0.1346 @@ -925,6 +945,7 @@ 2.0 2 na op 0.2369 -0.2369 2.0 2 na p -0.2518 0.2518 2.0 2 na s -0.0966 0.0966 + 2.0 2 na s_m -0.0966 0.0966 # Duplicated from base parameter 's' 2.0 2 na s' -0.0551 0.0551 2.0 2 na si -0.3501 0.3501 2.0 2 na sp -0.0551 0.0551 @@ -936,6 +957,7 @@ 2.0 2 nh op 0.3148 -0.3148 2.0 2 nh p -0.1375 0.1375 2.0 2 nh s 0.0046 -0.0046 + 2.0 2 nh s_m 0.0046 -0.0046 # Duplicated from base parameter 's' 2.0 2 nh s' 0.0454 -0.0454 2.0 2 nh si -0.2278 0.2278 2.0 2 nh sp 0.0454 -0.0454 @@ -946,6 +968,7 @@ 2.0 2 nn op 0.1684 -0.1684 2.0 2 nn p -0.3359 0.3359 2.0 2 nn s -0.1753 0.1753 + 2.0 2 nn s_m -0.1753 0.1753 # Duplicated from base parameter 's' 2.0 2 nn s' -0.1346 0.1346 2.0 2 nn si -0.4368 0.4368 2.0 2 nn sp -0.1346 0.1346 @@ -955,6 +978,7 @@ 2.0 2 np op 0.1684 -0.1684 2.0 2 np p -0.3359 0.3359 2.0 2 np s -0.1753 0.1753 + 2.0 2 np s_m -0.1753 0.1753 # Duplicated from base parameter 's' 2.0 2 np s' -0.1346 0.1346 2.0 2 np si -0.4368 0.4368 2.0 2 np sp -0.1346 0.1346 @@ -965,6 +989,7 @@ 2.0 2 o p -0.2548 0.2548 3.1 12 o p= -0.1400 0.1400 2.0 2 o s -0.1143 0.1143 + 2.0 2 o s_m -0.1143 0.1143 # Duplicated from base parameter 's' 2.0 2 o s' -0.0766 0.0766 2.0 2 o si -0.3425 0.3425 2.0 2 o sp -0.0766 0.0766 @@ -976,6 +1001,7 @@ 2.0 2 o_1 op 0.0000 0.0000 2.0 2 o_1 p -0.4933 0.4933 2.0 2 o_1 s -0.3386 0.3386 + 2.0 2 o_1 s_m -0.3386 0.3386 # Duplicated from base parameter 's' 2.0 2 o_1 s' -0.3024 0.3024 2.0 2 o_1 si -0.5883 0.5883 2.0 2 o_1 sp -0.3024 0.3024 @@ -984,6 +1010,7 @@ 2.0 2 op op 0.0000 0.0000 2.0 2 op p -0.4933 0.4933 2.0 2 op s -0.3386 0.3386 + 2.0 2 op s_m -0.3386 0.3386 # Duplicated from base parameter 's' 2.0 2 op s' -0.3024 0.3024 2.0 2 op si -0.5883 0.5883 2.0 2 op sp -0.3024 0.3024 @@ -992,14 +1019,20 @@ 3.0 10 oss sz -0.1309 0.1309 2.0 2 p p 0.0000 0.0000 2.0 2 p s 0.1600 -0.1600 + 2.0 2 p s_m 0.1600 -0.1600 # Duplicated from base parameter 's' 2.0 2 p s' 0.2106 -0.2106 2.0 2 p s- 0.1824 -0.6824 2.0 2 p si -0.1069 0.1069 2.0 2 p sp 0.2106 -0.2106 2.0 2 s s 0.0000 0.0000 + 2.0 2 s s_m 0.0000 0.0000 # Duplicated from base parameter 's' + 2.0 2 s_m s_m 0.0000 0.0000 # Duplicated from base parameter 's' 2.0 2 s s' 0.0455 -0.0455 + 2.0 2 s_m s' 0.0455 -0.0455 # Duplicated from base parameter 's' 2.0 2 s si -0.2634 0.2634 + 2.0 2 s_m si -0.2634 0.2634 # Duplicated from base parameter 's' 2.0 2 s sp 0.0455 -0.0455 + 2.0 2 s_m sp 0.0455 -0.0455 # Duplicated from base parameter 's' 2.0 2 s' s' 0.0000 0.0000 2.0 2 s' si -0.3172 0.3172 2.0 2 s' sp 0.0000 0.0000 @@ -1670,6 +1703,7 @@ 2.1 8 c h 1.1010 345.0000 -691.8900 844.6000 1.0 1 c h 1.1010 341.0000 -691.8900 844.6000 1.0 1 c n 1.4520 327.1657 -547.8990 526.5000 + 1.0 1 c2 nn 1.4520 327.1657 -547.8990 526.5000 # AutoREACTER addition; copied from base c n 1.0 1 c n+ 1.5185 293.1700 -603.7882 629.6900 1.1 1 c n= 1.4750 336.0000 0.0000 0.0000 1.1 1 c n=1 1.4750 336.0000 0.0000 0.0000 @@ -1683,6 +1717,8 @@ 2.1 6 c o_2 1.4457 326.7273 -608.5306 689.0333 2.0 5 c oz 1.4457 326.7273 -608.5306 689.0333 1.0 1 c s 1.8230 225.2768 -327.7057 488.9722 + 1.0 1 c s_m 1.8230 225.2768 -327.7057 488.9722 # Duplicated from base parameter 's' + 1.0 1 cp s_m 1.8230 225.2768 -327.7057 488.9722 # AutoREACTER addition; copied from base c s 2.2 9 c si 1.8995 189.6536 -279.4210 307.5135 1.0 4 c sio 1.9073 157.0049 -237.7023 356.0328 1.0 1 c+ nr 1.3834 380.4600 -814.4300 1153.3000 @@ -1702,6 +1738,7 @@ 1.0 1 c=2 h 1.0883 365.7679 -725.5404 781.6621 2.1 8 c=2 o= 1.1600 1112.0000 0.0000 0.0000 2.1 8 c=2 s' 1.5526 567.3600 0.0000 0.0000 + 2.1 8 c=2 s_m 1.5526 567.3600 0.0000 0.0000 # Duplicated from base parameter 's' 2.1 8 c_0 cp 1.4890 339.3574 -655.7236 670.2362 2.1 8 c_0 h 1.1220 304.8631 -623.3705 700.2828 2.1 8 c_0 o_1 1.2160 823.7948 -1878.7940 2303.5311 @@ -1749,6 +1786,7 @@ 2.1 8 h h 0.7414 414.0000 0.0000 0.0000 3.1 12 h p= 1.3861 285.2043 -575.6851 677.8456 1.0 1 h s 1.3261 275.1123 -531.3181 562.9630 + 1.0 1 h s_m 1.3261 275.1123 -531.3181 562.9630 # Duplicated from base parameter 's' 2.2 9 h si 1.4783 202.7798 -305.3603 280.2685 1.0 4 h sio 1.4802 187.1010 -280.7306 258.8998 1.0 1 h* n 1.0100 462.7500 -1053.6300 1545.7570 @@ -1756,6 +1794,7 @@ 1.0 1 h* na 1.0060 466.7400 -1073.6018 1251.1056 1.0 1 h* nh 1.0053 463.9230 -1050.8070 1284.7262 1.0 1 h* nn 1.0012 465.8608 -1066.2360 1496.5647 + 1.0 1 hn2 nn 1.0012 465.8608 -1066.2360 1496.5647 # AutoREACTER addition; copied from base h* nn 1.0 1 h* nr 1.0023 462.3900 -1044.6000 1468.7000 1.0 1 h* o 0.9650 532.5062 -1282.9050 2004.7658 1.2 3 h* o* 0.9700 563.2800 -1428.2200 1902.1200 @@ -1777,12 +1816,15 @@ 4.0 13 o p 1.6100 245.2000 0.0000 0.0000 2.1 8 o= o= 1.2074 847.4400 0.0000 0.0000 2.1 8 o= s' 1.4308 743.7600 0.0000 0.0000 + 2.1 8 o= s_m 1.4308 743.7600 0.0000 0.0000 # Duplicated from base parameter 's' 3.0 10 oas sz 1.5923 392.6680 -1004.4800 3452.8601 3.0 10 ob sz 1.6446 393.6690 -989.8420 1461.9800 3.0 10 osh sz 1.6125 420.0240 -845.6110 1438.6300 1.0 4 osi sio 1.6562 306.1232 -517.3424 673.7067 3.0 10 oss sz 1.6155 325.4430 -943.3640 1454.6700 1.0 1 s s 2.0559 197.6560 -196.1366 644.4103 + 1.0 1 s s_m 2.0559 197.6560 -196.1366 644.4103 # Duplicated from base parameter 's' + 1.0 1 s_m s_m 2.0559 197.6560 -196.1366 644.4103 # Duplicated from base parameter 's' 2.2 9 si si 2.3384 114.2164 -140.4212 80.7084 @@ -2133,7 +2175,7 @@ !--- --- ----- ----- ----- -------- -------- -------- -------- 3.0 10 oah az oah 119.5540 56.2161 67.5146 75.6704 3.0 10 oah az oas 135.8500 1.5716 -23.2602 24.2341 - 3.0 10 oah az ob 96.9383 41.2978 -101.1850 180.8230 + 3.0 10 oah az ob 96.9383 41.2978 -101.1850 180.8230 3.0 10 oas az oas 114.1500 112.9470 -37.6330 22.7467 3.0 10 oas az ob 97.0360 73.0531 -31.9551 5.5982 3.0 10 ob az ob 97.0360 73.0531 -31.9551 5.5982 @@ -2163,6 +2205,7 @@ 2.1 6 c c o_2 107.4100 63.3907 -13.4513 1.6650 2.0 5 c c oz 105.4100 63.3907 -13.4513 0.0000 1.0 1 c c s 112.5642 47.0276 -10.6790 -10.1687 + 1.0 1 c c s_m 112.5642 47.0276 -10.6790 -10.1687 # Duplicated from base parameter 's' 2.2 9 c c si 112.6700 39.5160 -7.4430 0.0000 1.0 1 c- c h 109.6700 37.9190 -7.3877 -8.0694 1.3 1 c- c n 100.5663 52.0966 -5.2642 -10.7045 @@ -2201,9 +2244,13 @@ 2.1 6 h c o_2 107.6880 65.4801 -10.3498 5.8866 2.0 5 h c oz 107.6880 70.4801 -10.3498 0.0000 1.0 1 h c s 107.8522 51.4949 -13.5270 7.0260 + 1.0 1 h c s_m 107.8522 51.4949 -13.5270 7.0260 # Duplicated from base parameter 's' 2.2 9 h c si 112.0355 28.7721 -13.9523 0.0000 1.0 4 h c sio 111.5360 30.2481 -15.5255 0.0000 1.0 1 s c s 111.5000 27.9677 0.0000 0.0000 + 1.0 1 s_m c s 111.5000 27.9677 0.0000 0.0000 # Duplicated from base parameter 's' + 1.0 1 s c s_m 111.5000 27.9677 0.0000 0.0000 # Duplicated from base parameter 's' + 1.0 1 s_m c s_m 111.5000 27.9677 0.0000 0.0000 # Duplicated from base parameter 's' 1.0 1 nr c+ nr 117.4500 83.9840 0.0000 0.0000 1.0 1 c c- o- 115.0600 59.0960 -15.1430 -12.9820 1.0 1 h c- o- 112.7500 61.1530 -14.0190 -13.2380 @@ -2405,10 +2452,19 @@ 3.1 12 o p= o 95.5000 87.7686 -4.5699 -17.8523 4.0 13 o p o 109.0000 45.0000 0.0000 0.0000 1.0 1 c s c 97.5000 57.6938 -5.0559 -11.8206 + 1.0 1 c s_m c 97.5000 57.6938 -5.0559 -11.8206 # Duplicated from base parameter 's' 1.0 1 c s h 96.8479 56.7336 14.2713 0.0000 + 1.0 1 c s_m h 96.8479 56.7336 14.2713 0.0000 # Duplicated from base parameter 's' 1.0 1 c s s 100.3000 57.2900 -6.5301 -11.8204 + 1.0 1 c s_m s 100.3000 57.2900 -6.5301 -11.8204 # Duplicated from base parameter 's' + 1.0 1 c s s_m 100.3000 57.2900 -6.5301 -11.8204 # Duplicated from base parameter 's' + 1.0 1 c s_m s_m 100.3000 57.2900 -6.5301 -11.8204 # Duplicated from base parameter 's' 1.0 1 h s h 94.3711 54.9676 0.0000 0.0000 + 1.0 1 h s_m h 94.3711 54.9676 0.0000 0.0000 # Duplicated from base parameter 's' 1.0 1 h s s 97.2876 54.4281 0.0000 0.0000 + 1.0 1 h s_m s 97.2876 54.4281 0.0000 0.0000 # Duplicated from base parameter 's' + 1.0 1 h s s_m 97.2876 54.4281 0.0000 0.0000 # Duplicated from base parameter 's' + 1.0 1 h s_m s_m 97.2876 54.4281 0.0000 0.0000 # Duplicated from base parameter 's' 2.1 8 o- s' o- 119.3290 135.0000 0.0000 0.0000 2.2 9 c si c 113.1855 36.2069 -20.3939 20.0172 2.2 9 c si h 112.0977 36.4832 -12.8094 0.0000 @@ -2434,6 +2490,10 @@ 3.0 10 osh sz osh 115.0310 68.3381 49.4314 116.2400 3.0 10 osh sz oss 110.6700 117.5060 -49.8921 0.0000 3.0 10 oss sz oss 110.6120 154.1860 -68.6595 23.6292 + 1.0 1 cp cp s_m 112.5642 47.0276 -10.6790 -10.1687 # AutoREACTER addition; copied from base c c s + 1.0 1 cp s_m cp 97.5000 57.6938 -5.0559 -11.8206 # AutoREACTER addition; copied from base c s c + 1.0 1 cp s_m o= 113.1000 42.3000 0.0000 0.0000 # AutoREACTER addition; based on auto * s o + 1.0 1 o= s_m o= 115.0000 50.0000 0.0000 0.0000 # AutoREACTER addition; generic O=S=O sulfone angle #torsion_1 cff91_auto @@ -2707,6 +2767,7 @@ 2.1 6 c c c o_2 0.0000 0.0 0.0000 0.0 -0.2500 0.0 2.0 5 c c c oz -3.6896 0.0 0.0000 0.0 0.0000 0.0 1.0 1 c c c s -0.7017 0.0 0.0201 0.0 0.1040 0.0 + 1.0 1 c c c s_m -0.7017 0.0 0.0201 0.0 0.1040 0.0 # Duplicated from base parameter 's' 2.2 9 c c c si 0.0000 0.0 0.0514 0.0 -0.1430 0.0 1.3 1 c- c c c_1 0.0972 0.0 0.0722 0.0 -0.2581 0.0 1.3 1 c- c c cp 0.0972 0.0 0.0722 0.0 -0.2581 0.0 @@ -2733,6 +2794,7 @@ 1.0 1 c_1 c c n 0.0972 0.0 0.0722 0.0 -0.2581 0.0 1.3 1 c_1 c c o -0.0858 0.0 -0.1320 0.0 -0.5909 0.0 1.3 1 c_1 c c s 0.0972 0.0 0.0722 0.0 -0.2581 0.0 + 1.3 1 c_1 c c s_m 0.0972 0.0 0.0722 0.0 -0.2581 0.0 # Duplicated from base parameter 's' 2.1 8 cl c c cl 0.0000 0.0 0.0000 0.0 -0.1000 0.0 2.1 8 cl c c f 0.0000 0.0 0.0000 0.0 -0.1000 0.0 2.1 8 cl c c h 0.0000 0.0 0.0000 0.0 -0.1000 0.0 @@ -2755,9 +2817,11 @@ 2.1 6 h c c o_2 0.0000 0.0 0.0000 0.0 -0.2500 0.0 2.0 5 h c c oz -3.6896 0.0 0.0000 0.0 0.0000 0.0 1.0 1 h c c s -0.2078 0.0 -0.1060 0.0 -0.3595 0.0 + 1.0 1 h c c s_m -0.2078 0.0 -0.1060 0.0 -0.3595 0.0 # Duplicated from base parameter 's' 2.2 9 h c c si 0.0000 0.0 0.0514 0.0 -0.1430 0.0 1.3 1 n c c o -0.1820 0.0 -0.1084 0.0 -0.7047 0.0 1.3 1 n c c s 0.0972 0.0 0.0722 0.0 -0.2581 0.0 + 1.3 1 n c c s_m 0.0972 0.0 0.0722 0.0 -0.2581 0.0 # Duplicated from base parameter 's' 2.1 7 n_2 c c n_2 0.0000 0.0 0.0060 0.0 -0.1441 0.0 2.1 7 n_2 c c o_2 0.0000 0.0 0.0000 0.0 -0.1441 0.0 1.0 1 na c c na 0.3805 0.0 0.3547 0.0 -0.1102 0.0 @@ -2765,6 +2829,9 @@ 2.1 6 o_2 c c o_2 -0.6070 0.0 0.0060 0.0 -0.1441 0.0 2.0 5 oz c c oz -0.6070 0.0 0.0060 0.0 -0.1441 0.0 1.0 1 s c c s -1.2002 0.0 -1.2999 0.0 -0.1626 0.0 + 1.0 1 s_m c c s -1.2002 0.0 -1.2999 0.0 -0.1626 0.0 # Duplicated from base parameter 's' + 1.0 1 s c c s_m -1.2002 0.0 -1.2999 0.0 -0.1626 0.0 # Duplicated from base parameter 's' + 1.0 1 s_m c c s_m -1.2002 0.0 -1.2999 0.0 -0.1626 0.0 # Duplicated from base parameter 's' 1.0 1 c c c- o- 1.7311 0.0 1.8510 0.0 -0.1933 0.0 1.0 1 h c c- o- -2.5999 0.0 1.0488 0.0 -0.2089 0.0 1.3 1 n c c- o- 0.0899 0.0 0.1220 0.0 0.0905 0.0 @@ -2918,13 +2985,29 @@ 2.0 5 h c oz cz 0.0000 0.0 0.0000 0.0 -0.1932 0.0 2.0 5 oz c oz cz 0.0000 0.0 0.0000 0.0 -0.1932 0.0 1.0 1 c c s c -0.5073 0.0 0.0155 0.0 -0.0671 0.0 + 1.0 1 c c s_m c -0.5073 0.0 0.0155 0.0 -0.0671 0.0 # Duplicated from base parameter 's' 1.0 1 c c s h -0.4871 0.0 -0.4514 0.0 -0.1428 0.0 + 1.0 1 c c s_m h -0.4871 0.0 -0.4514 0.0 -0.1428 0.0 # Duplicated from base parameter 's' 1.0 1 c c s s -0.6269 0.0 -0.9598 0.0 -0.4957 0.0 + 1.0 1 c c s_m s -0.6269 0.0 -0.9598 0.0 -0.4957 0.0 # Duplicated from base parameter 's' + 1.0 1 c c s s_m -0.6269 0.0 -0.9598 0.0 -0.4957 0.0 # Duplicated from base parameter 's' + 1.0 1 c c s_m s_m -0.6269 0.0 -0.9598 0.0 -0.4957 0.0 # Duplicated from base parameter 's' 1.0 1 h c s c -0.3338 0.0 -0.0684 0.0 -0.1706 0.0 + 1.0 1 h c s_m c -0.3338 0.0 -0.0684 0.0 -0.1706 0.0 # Duplicated from base parameter 's' 1.0 1 h c s h -0.5374 0.0 -0.5091 0.0 -0.1361 0.0 + 1.0 1 h c s_m h -0.5374 0.0 -0.5091 0.0 -0.1361 0.0 # Duplicated from base parameter 's' 1.0 1 h c s s -0.0610 0.0 -0.6387 0.0 -0.3072 0.0 + 1.0 1 h c s_m s -0.0610 0.0 -0.6387 0.0 -0.3072 0.0 # Duplicated from base parameter 's' + 1.0 1 h c s s_m -0.0610 0.0 -0.6387 0.0 -0.3072 0.0 # Duplicated from base parameter 's' + 1.0 1 h c s_m s_m -0.0610 0.0 -0.6387 0.0 -0.3072 0.0 # Duplicated from base parameter 's' 1.0 1 s c s c -1.9835 0.0 -1.9213 0.0 -0.3816 0.0 + 1.0 1 s_m c s c -1.9835 0.0 -1.9213 0.0 -0.3816 0.0 # Duplicated from base parameter 's' + 1.0 1 s c s_m c -1.9835 0.0 -1.9213 0.0 -0.3816 0.0 # Duplicated from base parameter 's' + 1.0 1 s_m c s_m c -1.9835 0.0 -1.9213 0.0 -0.3816 0.0 # Duplicated from base parameter 's' 1.0 1 s c s h -0.0591 0.0 -0.6235 0.0 -0.0788 0.0 + 1.0 1 s_m c s h -0.0591 0.0 -0.6235 0.0 -0.0788 0.0 # Duplicated from base parameter 's' + 1.0 1 s c s_m h -0.0591 0.0 -0.6235 0.0 -0.0788 0.0 # Duplicated from base parameter 's' + 1.0 1 s_m c s_m h -0.0591 0.0 -0.6235 0.0 -0.0788 0.0 # Duplicated from base parameter 's' 2.2 9 c c si c 0.0000 0.0 0.0000 0.0 -0.0657 0.0 2.2 9 c c si cp 0.0000 0.0 0.0000 0.0 -0.0657 0.0 2.2 9 c c si h 0.0000 0.0 0.0000 0.0 -0.0657 0.0 @@ -2959,15 +3042,15 @@ 2.1 6 o_1 c_1 cp cp 0.0000 0.0 0.9063 0.0 0.0000 0.0 2.1 6 o_2 c_1 cp cp 0.0000 0.0 0.9063 0.0 0.0000 0.0 1.0 1 h c_1 n c_1 0.1907 0.0 1.1212 0.0 0.0426 0.0 - 1.0 1 hn c_1 na c2 0.1907 0.0 1.1212 0.0 0.0426 0.0 + 1.0 1 hn c_1 na c2 0.1907 0.0 1.1212 0.0 0.0426 0.0 # AutoREACTER addition; copied from h c_1 n c_1; c2/hn mapped to c_1/h and na mapped to n 1.0 1 n c_1 n h* -0.7358 0.0 0.4643 0.0 -1.1098 0.0 1.0 1 o_1 c_1 n c 0.8297 0.0 3.7234 0.0 -0.0495 0.0 - 1.0 1 o_1 c_1 na c2 0.8297 0.0 3.7234 0.0 -0.0495 0.0 + 1.0 1 o_1 c_1 na c2 0.8297 0.0 3.7234 0.0 -0.0495 0.0 # AutoREACTER addition; copied from o_1 c_1 n c; mapped c->c2 and n->na 1.0 1 o_1 c_1 n c_1 -0.4066 0.0 1.2513 0.0 -0.7507 0.0 1.0 1 o_1 c_1 n h* -1.6938 0.0 2.7386 0.0 -0.3360 0.0 - 1.0 1 o_1 c_1 na hn -1.6938 0.0 2.7386 0.0 -0.3360 0.0 + 1.0 1 o_1 c_1 na hn -1.6938 0.0 2.7386 0.0 -0.3360 0.0 # AutoREACTER addition; copied from o_1 c_1 n h*; mapped h*->hn and n->na 2.1 8 c c_1 n_2 c -0.7532 0.0 2.7392 0.0 0.0907 0.0 - 2.1 8 c2 c_1 na c2 -0.7532 0.0 2.7392 0.0 0.0907 0.0 + 2.1 8 c2 c_1 na c2 -0.7532 0.0 2.7392 0.0 0.0907 0.0 # AutoREACTER addition; copied from c c_1 n_2 c; mapped n_2->na and c->c2 2.1 8 c c_1 n_2 hn2 -0.8236 0.0 2.1467 0.0 -0.2142 0.0 2.1 8 cp c_1 n_2 c -1.1077 0.0 2.0082 0.0 0.0000 0.0 2.1 8 cp c_1 n_2 cp -1.1077 0.0 2.0082 0.0 0.0000 0.0 @@ -3176,6 +3259,24 @@ 2.1 8 oh c_1 cg hc -0.6359 0.0 1.4807 0.0 -0.0438 0.0 # AutoREACTER addition; copied from h c c_1 o_2 reversed; mapped o_2->oh, c->cg, h->hc 2.1 8 oh c_1 c2 na 1.8341 0.0 2.0603 0.0 -0.0195 0.0 # AutoREACTER addition; copied from c c c_1 o_2 reversed; mapped o_2->oh, c->c2/na 2.1 8 oh c_1 cg na 1.8341 0.0 2.0603 0.0 -0.0195 0.0 # AutoREACTER addition; copied from c c c_1 o_2 reversed; mapped o_2->oh, c->cg/na + 1.0 1 c c s c -0.5073 0.0 0.0155 0.0 -0.0671 0.0 # AutoREACTER addition; generic aliphatic-sulfur dihedral + 1.0 1 cp cp s_m cp -0.5073 0.0 0.0155 0.0 -0.0671 0.0 # AutoREACTER addition; mapped from c c s c for cp-cp-s_m-cp + 1.0 1 cp cp s_m o= 0.2433 0.0 0.0000 0.0 0.1040 0.0 # AutoREACTER addition; mapped for cp-cp-s_m-o= + 1.0 1 c1 c2 nn c2 0.0883 0.0 0.0000 0.0 -0.0198 0.0 # AutoREACTER addition; mapped from c c c c for c1-c2-nn-c2 + 1.0 1 c1 c2 nn cp 0.0972 0.0 0.0722 0.0 -0.2581 0.0 # AutoREACTER addition; mapped from c c c n for c1-c2-nn-cp + 1.0 1 c1 c2 nn hn -0.0228 0.0 0.0280 0.0 -0.1863 0.0 # AutoREACTER addition; mapped from h c c n for c1-c2-nn-hn + 1.0 1 cp cp nn hn2 0.0143 0.0 -0.0132 0.0 0.0091 0.0 # AutoREACTER addition; mapped from c c n c_1 for cp-cp-nn-hn2 + 1.0 1 hc c1 c2 nn 0.0972 0.0 0.0722 0.0 -0.2581 0.0 # AutoREACTER addition; mapped for hc-c1-c2-nn + 1.0 1 hc c2 nn c2 0.0000 0.0 0.0514 0.0 -0.1430 0.0 # AutoREACTER addition; mapped for hc-c2-nn-c2 + 1.0 1 hc c2 nn cp 0.0972 0.0 0.0722 0.0 -0.2581 0.0 # AutoREACTER addition; mapped for hc-c2-nn-cp + 1.0 1 hc c2 nn hn -0.0228 0.0 0.0280 0.0 -0.1863 0.0 # AutoREACTER addition; mapped for hc-c2-nn-hn + 1.0 1 hn2 nn cp cp 0.0143 0.0 -0.0132 0.0 0.0091 0.0 # AutoREACTER addition; mapped for hn2-nn-cp-cp + 1.0 1 o= s_m o= * 0.0860 0.0 5.1995 0.0 0.0000 0.0 # AutoREACTER addition; mapped for o=-s_m-o=-* + 1.0 1 cp cp cp s_m 0.0000 0.0 4.8498 0.0 0.0000 0.0 # AutoREACTER addition; mapped from cp-cp-cp-o + 1.0 1 h cp cp s_m 0.0000 0.0 1.7234 0.0 0.0000 0.0 # AutoREACTER addition; mapped from h-cp-cp-o + 1.0 1 hc cp cp s_m 0.0000 0.0 1.7234 0.0 0.0000 0.0 # AutoREACTER addition; mapped from h-cp-cp-o + + #wilson_out_of_plane cff91 > E = K * (Chi - Chi0)^2 @@ -3374,6 +3475,7 @@ 2.0 3 p 4.2950 0.21500 3.1 12 p= 4.3000 0.21500 2.0 1 s 4.0270 0.07100 + 2.0 1 s_m 4.0270 0.07100 # Duplicated from base parameter 's' 2.1 8 s' 4.0270 0.25000 2.0 1 s' 4.0270 0.07100 2.2 9 si 4.4500 0.19000 From a5f5f80a6e0f52c969e0c18614cc1d9ee5fcb518 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 28 Jul 2026 15:51:17 -0400 Subject: [PATCH 094/176] Improve reaction/merge handling and PCFF params --- AutoREACTER/arx_cli.py | 8 +++- AutoREACTER/detectors/reaction_detector.py | 12 +++++- .../detectors/reactions_library/polyureas.py | 2 +- .../ff_wrapper/FF_files/pcff.frc | 41 ++++++++++++++++++- .../ff_wrapper/lunar_client/lunar_executor.py | 4 +- .../ff_wrapper/lunar_client/merge_builder.py | 15 ++++--- 6 files changed, 70 insertions(+), 12 deletions(-) diff --git a/AutoREACTER/arx_cli.py b/AutoREACTER/arx_cli.py index c2683c46..94cb6254 100644 --- a/AutoREACTER/arx_cli.py +++ b/AutoREACTER/arx_cli.py @@ -30,6 +30,9 @@ from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import REACTERFilesBuilder from AutoREACTER.sim_setup.simulation_setup import SimulationSetupManager +class NoReactionGenerated(Exception): + """Custom exception raised when no reaction is generated in the pipeline.""" + pass class ErrorHandler: """ @@ -384,7 +387,10 @@ def _save_rdkit_img(self, img, path: Path, is_non_reactant: bool = False): if img is None: if is_non_reactant: return - raise ValueError("No image was generated. Cannot save molecule image.") + raise NoReactionGenerated( + "No reaction was generated. This is an error from AutoREACTER. " + "Please file an issue on https://github.com/NanoCIPHER-Lab/AutoREACTER/issues to improve the software." + ) # Case 1: PIL image if hasattr(img, "save"): diff --git a/AutoREACTER/detectors/reaction_detector.py b/AutoREACTER/detectors/reaction_detector.py index 1bfe070c..6b7ad8c1 100644 --- a/AutoREACTER/detectors/reaction_detector.py +++ b/AutoREACTER/detectors/reaction_detector.py @@ -63,7 +63,6 @@ class EmptyReactionListError(Exception): This should be prevented by the reaction_selection method, but this error serves as a safeguard.""" pass - @dataclass(slots=True) class ReactionInstance: """ @@ -239,7 +238,16 @@ def reaction_detector(self, session: "Session") -> None: functional_group_2=fg_2 ) ) - session.reaction_instances = reaction_instances + if not reaction_instances: + raise EmptyReactionListError( + "\nNo reaction instances found for the specified monomer combination. " + "Please verify that your input monomer combinations are correct. " + "If you believe this represents a valid and standard reaction that AutoREACTER should support, " + "please submit an issue at https://github.com/NanoCIPHER-Lab/AutoREACTER/issues for consideration.\n" + "Thank you for helping improve AutoREACTER." + ) + else: + session.reaction_instances = reaction_instances def index_based_reaction_detector( diff --git a/AutoREACTER/detectors/reactions_library/polyureas.py b/AutoREACTER/detectors/reactions_library/polyureas.py index 5b631cde..854b672e 100644 --- a/AutoREACTER/detectors/reactions_library/polyureas.py +++ b/AutoREACTER/detectors/reactions_library/polyureas.py @@ -5,7 +5,7 @@ 'reactant_2': 'di_isocyanate', 'product': 'polyurea_chain', 'delete_atom': False, - 'reaction': '[NX3;H2,H1;!$([N][C,S]=*):1]-[H:3].[NX2:4]=[CX2:2]=[OX1:5]>>[NX3:1]-[CX3:2](=[OX1:5])-[NX3:4]-[H:3]', + 'reaction': '[NX3;H2:1]-[C:3].[NX2:4]=[CX2:2]=[OX1:5]>>[NX3:1]-[CX3:2](=[OX1:5])-[NX2:4]-[C:3]', 'reference': { 'smarts': None, 'reaction_and_mechanism': None diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc index 50875e24..3ac98dd2 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc +++ b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc @@ -1826,6 +1826,7 @@ 1.0 1 s s_m 2.0559 197.6560 -196.1366 644.4103 # Duplicated from base parameter 's' 1.0 1 s_m s_m 2.0559 197.6560 -196.1366 644.4103 # Duplicated from base parameter 's' 2.2 9 si si 2.3384 114.2164 -140.4212 80.7084 + 1.0 1 c_2 na 1.4570 365.8052 -699.6368 998.4842 # AutoREACTER addition; copied from base c na #quadratic_angle cff91_auto @@ -3275,7 +3276,45 @@ 1.0 1 cp cp cp s_m 0.0000 0.0 4.8498 0.0 0.0000 0.0 # AutoREACTER addition; mapped from cp-cp-cp-o 1.0 1 h cp cp s_m 0.0000 0.0 1.7234 0.0 0.0000 0.0 # AutoREACTER addition; mapped from h-cp-cp-o 1.0 1 hc cp cp s_m 0.0000 0.0 1.7234 0.0 0.0000 0.0 # AutoREACTER addition; mapped from h-cp-cp-o - + 1.0 1 c= c1 cp cp 0.0000 0.0 0.5000 0.0 0.0000 0.0 # AutoREACTER addition; mapped from c= c=1 cp cp + 1.0 1 c2 c2 n=2 ct 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero to pass validator + 1.0 1 c2 n=2 ct o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero to pass validator + 1.0 1 hc c2 n=2 ct 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero to pass validator + 1.0 1 o_1 c=2 na c2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero to pass validator + 1.0 1 o_1 c=2 na hn 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero to pass validator + 1.0 1 sc c=2 na c2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero to pass validator + 1.0 1 sc c=2 na hn 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero to pass validator + 1.0 1 c2 c1 ct nt 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for linear nitrile + 1.0 1 c2 c=2 ct nt 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for linear nitrile + 1.0 1 c= c1 ct nt 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for linear nitrile + 1.0 1 c= c=1 ct nt 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for linear nitrile + 1.0 1 hc c1 ct nt 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for linear nitrile + 1.0 1 hc c=1 ct nt 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for linear nitrile + 1.0 1 hc c=2 ct nt 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for linear nitrile + 1.0 1 c2 na c_2 na 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for c2-na-c_2-na + 1.0 1 c2 na c_2 o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for c2-na-c_2-o_1 + 1.0 1 hc c2 na c_2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for hc-c2-na-c_2 + 1.0 1 hn na c_2 na 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for hn-na-c_2-na + 1.0 1 hn na c_2 o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for hn-na-c_2-na + 1.0 1 o_1 c_1 c1 o_2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 o_1 c_1 c1 oh 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 o_2 c_1 c1 o_2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 o_2 c_1 c1 oh 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 c_1 c1 o_2 c_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 c= c1 o_2 c_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 o_1 c_1 c2 o_2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 o_1 c_1 c2 oh 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 o_2 c_1 c2 o_2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 o_2 c_1 c2 oh 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 oh c_1 c1 c3 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 oh c_1 c1 hc 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 oh c_1 c1 o_2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 oh c_1 c1 oh 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 oh c_1 c2 o_2 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 oh c_1 c2 oh 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 hn2 na c_2 o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 hn2 na c_2 na 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 1.0 1 hn na c_2 o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator #wilson_out_of_plane cff91 diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/lunar_executor.py b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/lunar_executor.py index 0995aec8..4ba2b285 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/lunar_executor.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/lunar_executor.py @@ -174,6 +174,7 @@ def run_bond_react_merge( all2lmp_results: list[All2LMPResult] ) -> FFFiles: """Executes bond_react_merge.py to create the final unified simulation setup.""" + print(f"[LUNAR bond_react_merge] Running bond_react_merge with input file {merge_input_file_path}") env = os.environ.copy() env["QT_QPA_PLATFORM"] = "offscreen" subprocess.run( @@ -183,7 +184,8 @@ def run_bond_react_merge( "-files", f"infile:{merge_input_file_path.name}", "-atomstyle", "full", "-tl", "T", - "-wrd", "T", + "-wrd", "F", + "-map", "F" ], cwd=str(self.cache_bond_react_merge), env=env, diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/merge_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/merge_builder.py index b398f8da..ad430e12 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/merge_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/merge_builder.py @@ -81,8 +81,9 @@ def write_bond_react_merge_input( reaction_pairs[rid]["post"] = r # Write pre/post pairs in order - rxn_counter = 1 + for rid in sorted(reaction_pairs): + pair = reaction_pairs[rid] pre = pair.get("pre") @@ -93,11 +94,13 @@ def write_bond_react_merge_input( pre_path = normalize_path(Path(cache_all2lmp) / pre.all2lmp_data_file) post_path = normalize_path(Path(cache_all2lmp) / post.all2lmp_data_file) - - merge_files += f"{f'pre{rxn_counter}':<10}{pre_path:<150}# for rxn{rxn_counter}\n" - merge_files += f"{f'post{rxn_counter}':<10}{post_path:<150}# for rxn{rxn_counter}\n" - - rxn_counter += 1 + data_counter += 1 + tag = f"data{data_counter}" + merge_files += f"{tag:<10}{pre_path:<150}{comment}\n" + data_counter += 1 + tag = f"data{data_counter}" + merge_files += f"{tag:<10}{post_path:<150}{comment}\n" + data_counter += 1 merge_files += f"\n# Specify the parent_directory of where to write results (optional)\n" From 90f4a5db1b1f4024de08499de9e15b13bc50f347 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 28 Jul 2026 16:15:35 -0400 Subject: [PATCH 095/176] Add changelog entry for v0.3 --- docs/source/change_log.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/source/change_log.md b/docs/source/change_log.md index 62a703d5..3a32b240 100644 --- a/docs/source/change_log.md +++ b/docs/source/change_log.md @@ -22,6 +22,30 @@ This serves two purposes: At release time, you can move the Unreleased section changes into a new release version section. --> +## [0.3] - [2026-08-xx] +### Added + +* **Reaction Progression:** Multi-stage reaction template generation to handle multi stage reaction progressions, copolymerizations and small molecules which needs few templates for the polymerization reactions. +* **Looping Control:** A new loop control parameter in the input file to prevent the explosion of unnecessary reactions. Defaults to `5` loops, but can be optimized by setting `loop: ` or disabled entirely with `loop: False`. +* **Advanced Detection:** Index-based functional group detection and index-based reaction detection to accurately identify reacting atoms post-first reaction. +* **Pathway Deduplication:** NetworkX-based deduplication detection to actively filter redundant reaction pathways. +* **Reaction Libraries:** Robust library modules for various polymer chemistries, including Epoxies, Polyamides, Polyesters, Polycarbonates, Polysiloxanes, Polyureas, Polyurethanes, and Vinyl polymers. +* **Force Field Parameters:** PCFF force field additions, specifically including new `s_m` sulfone parameters. + +### Changed + +* **Library Organization:** Centralized the reaction libraries into dedicated modules to improve maintainability and expandability. +* **Structure Generation:** Improved 3D molecule embedding to better handle highly congested polymer structures. + +### Removed + +* **Legacy Code:** Removed legacy compatibility shims (`_compat.py`). + +### Fixed + +* Addressed various stability and progression issues tracked in recent bug reports. +* Improved Error handling when no reaction instances are found for the specified monomer combinations. + ## [0.2.3] - [2026-06-24] ### Added From 5a330b89838147aebcdf7e0cb7143de228f6f574 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 28 Jul 2026 17:27:16 -0400 Subject: [PATCH 096/176] Use full atom count (H included) for num_atoms --- .../sim_setup/system_property_calculations.py | 23 +++++++++++++++---- tests/test_input_parser.py | 4 ++-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/AutoREACTER/sim_setup/system_property_calculations.py b/AutoREACTER/sim_setup/system_property_calculations.py index effe2123..1f8ce2c6 100644 --- a/AutoREACTER/sim_setup/system_property_calculations.py +++ b/AutoREACTER/sim_setup/system_property_calculations.py @@ -1,4 +1,5 @@ import math +from rdkit import Chem from rdkit.Chem import Descriptors from AutoREACTER.input_parser import SimulationSetup @@ -56,11 +57,17 @@ def process_all(self) -> SimulationSetup: def _populate_monomer_properties(self) -> None: """ Populate each active monomer with basic structural properties derived from its RDKit molecule. - + For every monomer whose status is True: - - num_atoms is set to the heavy atom count. - - molecular_weight is set using RDKit's Descriptors.MolWt (g/mol). - + - num_atoms is set to the FULL atom count (heavy atoms + explicit hydrogens), + since this must match the atom count of the final built system, not just + the heavy-atom skeleton. Using AddHs() on a temporary copy avoids mutating + monomer.rdkit_mol, which other stages (e.g. functional group / reaction + detection) still expect in its original heavy-atom-only form. + - molecular_weight is set using RDKit's Descriptors.MolWt (g/mol). Unaffected + by explicit vs. implicit H representation -- MolWt already accounts for + implicit hydrogens correctly. + Raises: NoneMonomerError: If a monomer is marked active but has no RDKit Mol object. """ @@ -75,8 +82,14 @@ def _populate_monomer_properties(self) -> None: f"Monomer with ID {monomer.id} has no RDKit Mol object." ) - monomer.num_atoms = monomer.rdkit_mol.GetNumAtoms() + # count on an AddHs'd copy so num_atoms reflects the true final + # atom count (heavy + explicit H), matching what total_atoms means + # to the rest of the simulation-setup pipeline. Original rdkit_mol + # is left untouched for downstream heavy-atom-based logic. + mol_with_hs = Chem.AddHs(monomer.rdkit_mol) + monomer.num_atoms = mol_with_hs.GetNumAtoms() monomer.molecular_weight = Descriptors.MolWt(monomer.rdkit_mol) + def _calculate_replica_properties(self) -> None: """ diff --git a/tests/test_input_parser.py b/tests/test_input_parser.py index 18257d63..3c85c00c 100644 --- a/tests/test_input_parser.py +++ b/tests/test_input_parser.py @@ -866,12 +866,12 @@ def test_validate_inputs_stores_integer_loop_limit( sleep_mock, ) -> None: inputs = self.counts_input() - inputs["loop"] = 3 + inputs["loop"] = 10 # Triggers the warning and the sleep(5) result = self.parser.validate_inputs(inputs) self.assertTrue(result.loop) - self.assertEqual(result.max_loop_count, 3) + self.assertEqual(result.max_loop_count, 10) # Matches the new input sleep_mock.assert_called_once_with(5) def test_validate_inputs_assigns_default_monomer_name(self) -> None: From 7d37cffdaf06b201d2aaad81580003351d8bae21 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 29 Jul 2026 17:18:08 -0400 Subject: [PATCH 097/176] Add input snapshot and polymerization updates --- AutoREACTER/arx_cli.py | 8 +- .../reactions_library/vinyl_polymers.py | 68 ++++++++------- AutoREACTER/input_parser.py | 4 +- .../deduplication_detector.py | 83 +++++++++++++++++-- .../ff_wrapper/FF_files/pcff.frc | 2 + 5 files changed, 129 insertions(+), 36 deletions(-) diff --git a/AutoREACTER/arx_cli.py b/AutoREACTER/arx_cli.py index 94cb6254..14a2efc8 100644 --- a/AutoREACTER/arx_cli.py +++ b/AutoREACTER/arx_cli.py @@ -14,6 +14,7 @@ from contextlib import contextmanager import os from pathlib import Path +import shutil import sys import threading from PIL import Image @@ -101,7 +102,8 @@ def __init__(self, input: Path) -> None: self.img_dir = self.session.images_dir # with open(self.session.output_dir / "AutoREACTER.log", 'w') as f: # f.write("--- Starting AutoREACTER Session ---\n") - + # Save a copy of the input JSON to the output directory + self._save_input_json(abs_path) # Save an initial grid image of all monomers self._save_rdkit_img( InputParser().initial_molecules_image_grid(self.session), @@ -317,6 +319,10 @@ def process(self): # ------------------------------------------------------------------ # Internal helpers – lazy detection & image saving # ------------------------------------------------------------------ + def _save_input_json(self, abs_path: Path): + destination_file = "input.json" + destination_path = self.session.output_dir / destination_file + shutil.copy(abs_path, destination_path) def _ensure_fg_detected(self): """ diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py index faec21fc..e7f2c27d 100644 --- a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -1,23 +1,35 @@ REACTIONS = { 'Vinyl Addition Polymerization Initiation': { - 'same_reactants': True, - 'reactant_1': 'vinyl', - 'product': 'vinyl_chain_end_radical', - 'delete_atom': False, - 'reaction': '[CH2:1]=[C;!R:3].[CH2:2]=[C;!R:4]>>[CH2:1](-[C:3])-[CH2:2]-[C:4]', - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': None - }, - 'Vinyl Addition Polymerization Propagation': { - 'same_reactants': False, - 'reactant_1': 'vinyl', - 'reactant_2': 'vinyl_chain_end_radical', - 'product': 'vinyl_chain_end_radical', - 'delete_atom': False, - 'reaction': '[CH2:2]=[C;!R:3].[C;!R;D3;v3:1]>>[C:1]-[CH2:2]-[C:3]', - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': None - }, + 'same_reactants': True, + 'reactant_1': 'vinyl', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + 'reaction': '[CH2:1]=[C;!R:3].[CH2:2]=[C;!R:4]>>[CH2:1](-[C:3])-[CH2:2]-[C:4]', + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None +}, + +'Vinyl Addition Polymerization Propagation': { + 'same_reactants': False, + 'reactant_1': 'vinyl', + 'reactant_2': 'vinyl_chain_end_radical', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + 'reaction': '[CH2:2]=[C;!R:3].[C;!R;D3;v3:1]>>[C:1]-[CH2:2]-[C:3]', + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None +}, + +'Vinyl Copolymerization': { + 'same_reactants': False, + 'reactant_1': 'vinyl', + 'reactant_2': 'vinyl', + 'product': 'copolyvinyl_chain', + 'delete_atom': False, + 'reaction': '[CH2:1]=[C;!R:2].[CH2:3]=[C;!R:4]>>[CH2:1]-[C:2]-[CH2:3]-[C:4]', + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': 'General vinyl copolymerization; supports terminal vinyl and methacrylate-style substituted vinyls' +}, # 'Vinyl Radical Coupling Termination': { # 'same_reactants': True, # 'reactant_1': 'vinyl_chain_end_radical', @@ -36,16 +48,16 @@ # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, # 'comments': None # }, - 'Vinyl Copolymerization': { - 'same_reactants': False, - 'reactant_1': 'vinyl', - 'reactant_2': 'vinyl', - 'product': 'copolyvinyl_chain', - 'delete_atom': False, - 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': None - }, + # 'Vinyl Copolymerization': { + # 'same_reactants': False, + # 'reactant_1': 'vinyl', + # 'reactant_2': 'vinyl', + # 'product': 'copolyvinyl_chain', + # 'delete_atom': False, + # 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', + # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # 'comments': None + # }, # Later Implementation # 'Cyclic Olefin Addition Polymerization': { # 'same_reactants': True, diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 8bfedb21..0e159d0e 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -152,6 +152,7 @@ class SimulationSetup: force_field: str | None monomers: list[MonomerEntry] loop : bool = True + input_json: dict | None = None max_loop_count: int | None = None simulations: list[Simulation] | None = None composition_method: CompositionMethodType | None = None @@ -219,7 +220,8 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: composition=validated_simulations, force_field=force_field, loop=loop, - max_loop_count=max_loop_count + max_loop_count=max_loop_count, + input_json=inputs, ) def molecule_representation_of_initial_molecules( diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 644a6ad0..234341d3 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -25,7 +25,7 @@ class DeduplicationDetector: """Detect duplicate pre/post-reaction graph pairs.""" - + DEEP_CHECK = False NODE_ATTRIBUTE = "atom_label" EDGE_ATTRIBUTE = "bond_label" @@ -459,6 +459,68 @@ def compare_graphs_mol( return unique_reactions + @classmethod + def _one_neighbor_edge_environment_signature( + cls, + atom: Chem.Atom, + included_atom_indices: set[int], + ) -> tuple[tuple[str, int, bool, str, int, bool, str], ...]: + """ + Return a one-bond external chemical-environment signature for + boundary atoms. + + Only neighbors outside the restricted comparison graph are used. + This avoids walking into the next molecule or building a larger + shell. Internal atoms return an empty signature. + + Each external-neighbor signature contains: + - neighbor element + - neighbor formal charge + - neighbor aromatic state + - neighbor hybridization + - neighbor total hydrogen count + - neighbor radical state + - bond type connecting edge atom to neighbor + """ + external_neighbor_signatures = [] + + try: + atom.GetOwningMol().UpdatePropertyCache(strict=False) + except RuntimeError: + pass + + for bond in atom.GetBonds(): + neighbor = bond.GetOtherAtom(atom) + + if neighbor.GetIdx() in included_atom_indices: + continue + + external_neighbor_signatures.append( + ( + neighbor.GetSymbol(), + neighbor.GetFormalCharge(), + neighbor.GetIsAromatic(), + str(neighbor.GetHybridization()), + cls._safe_total_hydrogen_count(neighbor), + cls._is_radical_atom(neighbor), + str(bond.GetBondType()), + ) + ) + + return tuple(sorted(external_neighbor_signatures)) + + @staticmethod + def _safe_total_hydrogen_count(atom: Chem.Atom) -> int: + """Return total hydrogen count without failing on unsanitized mols.""" + try: + return atom.GetTotalNumHs() + except RuntimeError: + explicit_h_neighbors = sum( + neighbor.GetAtomicNum() == 1 + for neighbor in atom.GetNeighbors() + ) + return explicit_h_neighbors + atom.GetNumExplicitHs() + def clear_cache( self, comparison_group: str | None = None, @@ -553,11 +615,20 @@ def rdkit_mol_to_networkx( ) is_radical = self._is_radical_atom(atom) - - atom_label = ( - atom.GetSymbol(), - is_radical, - ) + if not DEEP_CHECK: + atom_label = ( + atom.GetSymbol(), + is_radical, + ) + else: + atom_label = ( + atom.GetSymbol(), + is_radical, + self._one_neighbor_edge_environment_signature( + atom=atom, + included_atom_indices=included_atom_indices, + ), + ) graph.add_node( node_id, diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc index 3ac98dd2..dcf5e251 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc +++ b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc @@ -2917,6 +2917,7 @@ 2.1 8 na c_1 c2 c2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->na and c->c2 2.1 8 c c c_1 o_1 0.0442 0.0 0.0292 0.0 0.0562 0.0 2.1 8 c c c_1 o_2 1.8341 0.0 2.0603 0.0 -0.0195 0.0 + 2.1 8 o_2 c_1 c c= 1.8341 0.0 2.0603 0.0 -0.0195 0.0 # AutoREACTER addition; copied from c c c_1 o_2 reversed; mapped terminal c -> c= 2.1 8 oh c_1 c2 c2 1.8341 0.0 2.0603 0.0 -0.0195 0.0 # AutoREACTER addition; copied from c c c_1 o_2 reversed; mapped o_2->oh and c->c2 2.1 8 h c c_1 n_2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 2.1 8 h c c_1 o_1 -0.1804 0.0 0.0012 0.0 0.0371 0.0 @@ -3315,6 +3316,7 @@ 1.0 1 hn2 na c_2 o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator 1.0 1 hn2 na c_2 na 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator 1.0 1 hn na c_2 o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator + 2.1 8 o_1 c_1 c c= 0.0442 0.0 0.0292 0.0 0.0562 0.0 # AutoREACTER addition; copied from c c c_1 o_1 reversed; mapped terminal c -> c= #wilson_out_of_plane cff91 From 5e2a15354990a72baced022320642a75d7c127fd Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 31 Jul 2026 10:06:43 -0400 Subject: [PATCH 098/176] Disable transesterification and tweak equilibration --- .../detectors/reactions_library/polyesters.py | 28 +++++++++---------- .../deduplication_detector.py | 7 ++++- .../sim_setup/writers/pre_eq_writer.py | 20 ++++++------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/AutoREACTER/detectors/reactions_library/polyesters.py b/AutoREACTER/detectors/reactions_library/polyesters.py index c29deb8b..2c77c637 100644 --- a/AutoREACTER/detectors/reactions_library/polyesters.py +++ b/AutoREACTER/detectors/reactions_library/polyesters.py @@ -93,20 +93,20 @@ }, 'comments': 'Fixed SMARTS to prevent RDKit explicit node valence crashes.' }, - 'Diol and Di-Carboxylic Ester Polycondensation(Transesterification)': - { - 'same_reactants': False, - 'reactant_1': 'diol', - 'reactant_2': 'di_carboxylic_ester', - 'product': 'polyester_chain', - 'delete_atom': True, - 'reaction': '[OX2;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[OX2:4][#6:6]>>[OX2:1]-[CX3:2](=[O:5]).[OX2:4](-[H:3])-[#6:6]', - 'reference': { - 'smarts': None, - 'reaction_and_mechanism': None - }, - 'comments': None - }, + # 'Diol and Di-Carboxylic Ester Polycondensation(Transesterification)': + # { + # 'same_reactants': False, + # 'reactant_1': 'diol', + # 'reactant_2': 'di_carboxylic_ester', + # 'product': 'polyester_chain', + # 'delete_atom': True, + # 'reaction': '[OX2;!$([O][C,S]=*):1]-[H:3].[CX3:2](=[O:5])[OX2:4][#6:6]>>[OX2:1]-[CX3:2](=[O:5]).[OX2:4](-[H:3])-[#6:6]', + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # 'comments': None + # }, # Skipped for later additinos after proper validations # 'Lactone Ring-Opening Polyesterification': # { diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 234341d3..2b5fd680 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -615,11 +615,16 @@ def rdkit_mol_to_networkx( ) is_radical = self._is_radical_atom(atom) - if not DEEP_CHECK: + + # Determine the atom label based on the DEEP_CHECK setting + # DEEP_CHECK should be able to change from input script + if not self.DEEP_CHECK: atom_label = ( atom.GetSymbol(), is_radical, ) + + # If DEEP_CHECK is enabled, include the one-neighbor edge environment signature in the atom label. else: atom_label = ( atom.GetSymbol(), diff --git a/AutoREACTER/sim_setup/writers/pre_eq_writer.py b/AutoREACTER/sim_setup/writers/pre_eq_writer.py index 6771f47e..18893dcb 100644 --- a/AutoREACTER/sim_setup/writers/pre_eq_writer.py +++ b/AutoREACTER/sim_setup/writers/pre_eq_writer.py @@ -126,18 +126,18 @@ def write_pre_eq_file(self, simulation: Simulation) -> str: "#------------Stage 1: NVT Temperature Ramp------------", "# (25,000 steps × 1 fs timestep)", f"{'fix':<16} nvt_1 all nvt temp 298.15 {simulation.temperature} 100.0", - f"{'run':<16} 25000", + f"{'run':<16} 50000", f"{'unfix':<16} nvt_1", "", - "#------------Stage 2: NPT Equilibration------------", - "# Isotropic pressure control at 0 atm while maintaining target temperature.", - "# This allows the box volume to adjust to the correct density at the", - "# desired temperature and pressure.", - f"{'fix':<16} npt_2 all npt temp {simulation.temperature} {simulation.temperature} 100.0 iso 0.0 0.0 1000.0", - f"{'run':<16} 25000", - f"{'unfix':<16} npt_2", - "", - "#------------Stage 3: Final NVT Equilibration------------", + # "#------------Stage 2: NPT Equilibration------------", + # "# Isotropic pressure control at 0 atm while maintaining target temperature.", + # "# This allows the box volume to adjust to the correct density at the", + # "# desired temperature and pressure.", + # f"{'fix':<16} npt_2 all npt temp {simulation.temperature} {simulation.temperature} 100.0 iso 0.0 0.0 1000.0", + # f"{'run':<16} 25000", + # f"{'unfix':<16} npt_2", + # "", + "#------------Stage 2: Final NVT Equilibration------------", "# Extended constant-volume equilibration at the final temperature.", "# This stabilizes the system after the density adjustment in the NPT stage.", f"{'fix':<16} nvt_3 all nvt temp {simulation.temperature} {simulation.temperature} 100.0", From 7a310fe496140168484db29c4ee4b7ab2c03c68d Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 4 Aug 2026 17:28:18 -0400 Subject: [PATCH 099/176] Validate reaction initiator atom maps Add registry-level validation for reaction SMARTS to ensure the reserved AutoREACTER initiator atom maps are present and bonded in products. Update polyanhydride and polysiloxane templates to use the reserved maps consistently and replace legacy comments with notes. --- .../reactions_library/polyanhydrides.py | 9 +- .../reactions_library/polysiloxanes.py | 8 +- .../detectors/reactions_library/registry.py | 174 +++++++++++++++++- 3 files changed, 181 insertions(+), 10 deletions(-) diff --git a/AutoREACTER/detectors/reactions_library/polyanhydrides.py b/AutoREACTER/detectors/reactions_library/polyanhydrides.py index 9bb33466..cf8672c8 100644 --- a/AutoREACTER/detectors/reactions_library/polyanhydrides.py +++ b/AutoREACTER/detectors/reactions_library/polyanhydrides.py @@ -4,24 +4,25 @@ 'reactant_1': 'carboxylic_acid_acid_halide', 'product': 'polyanhydride_chain', 'delete_atom': True, - 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]', + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:6](=[O:5])[OX2:2]-[H:7]>>[CX3:1](=[O:3])-[OX2:2]-[CX3:6](=[O:5]).[Cl,Br,I:4]-[H:7]', 'reference': { 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': None + 'notes': 'Atom maps 1 and 2 are reserved as AutoREACTER/LAMMPS bond/react initiator atoms.' }, + 'Carboxylic Acid and Acid Halide Copolycondensation (Polyanhydride Copolymerization)': { 'same_reactants': False, 'reactant_1': 'carboxylic_acid_acid_halide', 'reactant_2': 'carboxylic_acid_acid_halide', 'product': 'polyanhydride_chain', 'delete_atom': True, - 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:2](=[O:5])[OX2:6]-[H:7]>>[CX3:1](=[O:3])-[OX2:6]-[CX3:2](=[O:5]).[Cl,Br,I:4]-[H:7]', + 'reaction': '[CX3:1](=[O:3])[Cl,Br,I:4].[CX3:6](=[O:5])[OX2:2]-[H:7]>>[CX3:1](=[O:3])-[OX2:2]-[CX3:6](=[O:5]).[Cl,Br,I:4]-[H:7]', 'reference': { 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': None + 'notes': 'Atom maps 1 and 2 are reserved as AutoREACTER/LAMMPS bond/react initiator atoms.' } } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/polysiloxanes.py b/AutoREACTER/detectors/reactions_library/polysiloxanes.py index f7f3e6a3..83441ffe 100644 --- a/AutoREACTER/detectors/reactions_library/polysiloxanes.py +++ b/AutoREACTER/detectors/reactions_library/polysiloxanes.py @@ -5,12 +5,12 @@ 'reactant_2': 'water', 'product': 'silanediol', 'delete_atom': True, - 'reaction': '[Si:1]-[Cl:2].[OX2H2:3](-[H:4])-[H:5]>>[Si:1]-[OX2:3]-[H:4].[Cl:2]-[H:5]', + 'reaction': '[Si:1]-[Cl:3].[OX2H2:2](-[H:4])-[H:5]>>[Si:1]-[OX2:2]-[H:4].[Cl:3]-[H:5]', 'reference': { 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': None + 'notes': 'Atom maps 1 and 2 are reserved as AutoREACTER/LAMMPS bond/react initiator atoms.' }, 'Silanediol Polycondensation(Polysiloxane Formation)': { 'same_reactants': True, @@ -22,7 +22,7 @@ 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': None + 'notes': None }, 'Silanediol and Silanediol Copolycondensation(Polysiloxane Formation)': { 'same_reactants': False, @@ -35,6 +35,6 @@ 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': None + 'notes': None } } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/registry.py b/AutoREACTER/detectors/reactions_library/registry.py index 48a70977..957eeadd 100644 --- a/AutoREACTER/detectors/reactions_library/registry.py +++ b/AutoREACTER/detectors/reactions_library/registry.py @@ -1,4 +1,13 @@ """Aggregate and validate all polymer-family reaction modules.""" + +from __future__ import annotations + +try: + from rdkit.Chem import rdChemReactions +except ImportError: # pragma: no cover + rdChemReactions = None + + try: from .polyesters import REACTIONS as POLYESTERS # from .polyethers import REACTIONS as POLYETHERS @@ -32,6 +41,7 @@ from polysiloxanes import REACTIONS as POLYSILOXANES from thiol_ene_polymers import REACTIONS as THIOL_ENE_POLYMERS + _REACTION_MODULES = [ POLYESTERS, # POLYETHERS, @@ -54,6 +64,158 @@ ] +class ReactionLibraryValidationError(ValueError): + """Raised when a reaction-library SMARTS violates AutoREACTER rules.""" + + +def _atom_maps_in_templates(templates) -> set[int]: + """Return all nonzero atom-map numbers present in RDKit templates.""" + atom_maps: set[int] = set() + + for template in templates: + for atom in template.GetAtoms(): + atom_map = atom.GetAtomMapNum() + if atom_map: + atom_maps.add(atom_map) + + return atom_maps + + +def _has_bond_between_atom_maps( + templates, + atom_map_1: int, + atom_map_2: int, +) -> bool: + """Return True if any template contains a bond between two atom maps.""" + target = {atom_map_1, atom_map_2} + + for template in templates: + for bond in template.GetBonds(): + begin_map = bond.GetBeginAtom().GetAtomMapNum() + end_map = bond.GetEndAtom().GetAtomMapNum() + + if {begin_map, end_map} == target: + return True + + return False + + +def _validate_reaction_smarts( + reaction_name: str, + reaction: dict, +) -> list[str]: + """ + Validate one reaction-library entry. + + AutoREACTER convention: + atom maps :1 and :2 are reserved as LAMMPS bond/react initiator atoms. + + By default this validator requires: + - reaction["reaction"] exists + - maps 1 and 2 exist in reactants + - maps 1 and 2 exist in products + - products contain a bond between map 1 and map 2 + + A reaction can override this with: + "initiator_atom_maps": (a, b) + + A special reaction can skip this check with: + "validate_initiator_bond": False + """ + errors: list[str] = [] + + smarts = reaction.get("reaction") + + if not smarts: + return [f"{reaction_name}: missing required key 'reaction'"] + + if reaction.get("validate_initiator_bond", True) is False: + return errors + + if rdChemReactions is None: + return [f"{reaction_name}: RDKit is required to validate reaction SMARTS"] + + initiator_atom_maps = reaction.get("initiator_atom_maps", (1, 2)) + + if len(initiator_atom_maps) != 2: + return [ + f"{reaction_name}: initiator_atom_maps must contain exactly two atom maps" + ] + + initiator_1, initiator_2 = map(int, initiator_atom_maps) + + try: + rdkit_reaction = rdChemReactions.ReactionFromSmarts(smarts) + except Exception as error: + return [f"{reaction_name}: invalid reaction SMARTS: {error}"] + + if rdkit_reaction is None: + return [f"{reaction_name}: RDKit could not parse reaction SMARTS"] + + reactant_templates = [ + rdkit_reaction.GetReactantTemplate(i) + for i in range(rdkit_reaction.GetNumReactantTemplates()) + ] + + product_templates = [ + rdkit_reaction.GetProductTemplate(i) + for i in range(rdkit_reaction.GetNumProductTemplates()) + ] + + reactant_maps = _atom_maps_in_templates(reactant_templates) + product_maps = _atom_maps_in_templates(product_templates) + + required_maps = {initiator_1, initiator_2} + + missing_reactant_maps = required_maps - reactant_maps + missing_product_maps = required_maps - product_maps + + if missing_reactant_maps: + errors.append( + f"{reaction_name}: initiator atom maps missing from reactants: " + f"{sorted(missing_reactant_maps)}" + ) + + if missing_product_maps: + errors.append( + f"{reaction_name}: initiator atom maps missing from products: " + f"{sorted(missing_product_maps)}" + ) + + product_has_initiator_bond = _has_bond_between_atom_maps( + product_templates, + initiator_1, + initiator_2, + ) + + if not product_has_initiator_bond: + errors.append( + f"{reaction_name}: product does not contain required " + f"AutoREACTER initiator bond between atom maps " + f"{initiator_1} and {initiator_2}" + ) + + return errors + + +def validate_reactions(reactions: dict) -> None: + """Validate the merged AutoREACTER reaction library.""" + errors: list[str] = [] + + for reaction_name, reaction in reactions.items(): + if not isinstance(reaction, dict): + errors.append(f"{reaction_name}: reaction entry must be a dictionary") + continue + + errors.extend(_validate_reaction_smarts(reaction_name, reaction)) + + if errors: + message = "\n".join(f" - {error}" for error in errors) + raise ReactionLibraryValidationError( + "Reaction library validation failed:\n" + message + ) + + def load_reactions() -> dict: """Return one flat reaction dictionary with duplicate-name protection.""" merged = {} @@ -64,6 +226,8 @@ def load_reactions() -> dict: raise ValueError(f"Duplicate reaction name: {reaction_name}") merged[reaction_name] = reaction + validate_reactions(merged) + return merged @@ -80,11 +244,17 @@ def __init__(self): if __name__ == "__main__": REACTIONS = load_reactions() num = 0 - + with open("reactions.txt", "w") as f: for reaction in REACTIONS.items(): f.write(str(reaction) + "\n") + reaction_len = len(REACTIONS) + import os + file_abs_path = os.path.abspath("reactions.txt") - print(f"reactions.txt has been written to {file_abs_path}, num reactions: {reaction_len}") \ No newline at end of file + print( + f"reactions.txt has been written to {file_abs_path}, " + f"num reactions: {reaction_len}" + ) \ No newline at end of file From 18c338689c673d760e6fe1496fac76bf734919a8 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 4 Aug 2026 17:30:48 -0400 Subject: [PATCH 100/176] Add LAMMPS map-based template deduplication --- .../deduplication_detector.py | 397 ++++++++++++------ .../ff_wrapper/lunar_client/merge_builder.py | 15 +- .../reaction_processor/prepare_reactions.py | 33 +- .../reaction_progression.py | 16 + 4 files changed, 324 insertions(+), 137 deletions(-) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 2b5fd680..a01d2c37 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -8,6 +8,8 @@ """ from __future__ import annotations + +import re from pathlib import Path from typing import TYPE_CHECKING @@ -25,7 +27,9 @@ class DeduplicationDetector: """Detect duplicate pre/post-reaction graph pairs.""" - DEEP_CHECK = False + + DEEP_CHECK = True + NODE_ATTRIBUTE = "atom_label" EDGE_ATTRIBUTE = "bond_label" @@ -92,12 +96,31 @@ def is_duplicate( The pre- and post-reaction graphs are coupled using atom correspondence edges. This requires one consistent atom mapping to satisfy both reaction phases. + + This path is mainly used for RDKit molecules where pre and post + graphs have already been relabeled into the same atom-index space. """ coupled_graph = self._couple_graphs( pre_template_graph=pre_template_graph, post_template_graph=post_template_graph, ) + return self.is_duplicate_coupled_graph( + coupled_graph=coupled_graph, + comparison_group=comparison_group, + ) + + def is_duplicate_coupled_graph( + self, + coupled_graph: nx.Graph, + comparison_group: str, + ) -> bool: + """ + Check whether an already-coupled pre/post graph was previously cached. + + This is used for LAMMPS templates where atom correspondence comes from + the RXN_*.map Equivalences section instead of matching atom IDs. + """ node_match = nx.algorithms.isomorphism.categorical_node_match( ["phase", self.NODE_ATTRIBUTE], [None, None], @@ -114,9 +137,6 @@ def is_duplicate( ) for seen_graph in seen_graphs: - # The restricted template graph may not include every radical - # center in the complete molecule. Compare the full-molecule - # pre/post radical signature before checking graph isomorphism. if ( coupled_graph.graph.get( self.RADICAL_SIGNATURE_ATTRIBUTE @@ -150,6 +170,241 @@ def is_duplicate( seen_graphs.append(coupled_graph.copy()) return False + def is_duplicate_lammps_template_pair( + self, + pre_file_path: str | Path, + post_file_path: str | Path, + comparison_group: str | None = None, + ) -> bool: + """ + Check LAMMPS template duplication using: + - template_pre_*.molecule + - template_post_*.molecule + - RXN_*.map Equivalences + + This ignores coordinates, atom IDs, and bond IDs, but preserves + the pre-to-post atom correspondence from the LAMMPS map file. + """ + pre_file_path = Path(pre_file_path) + post_file_path = Path(post_file_path) + + if comparison_group is None: + comparison_group = self.LAMMPS_COMPARISON_GROUP + + pre_graph = self.lammps_molecule_to_networkx(pre_file_path) + post_graph = self.lammps_molecule_to_networkx(post_file_path) + + map_file_path = self._lammps_map_path_from_template_path( + pre_file_path + ) + + if not map_file_path.is_file(): + return self.is_duplicate_pair( + pre_graph=pre_graph, + post_graph=post_graph, + comparison_group=comparison_group, + ) + + pre_to_post_mapping = self._read_lammps_equivalences( + map_file_path + ) + + if not pre_to_post_mapping: + raise ValueError( + f"No Equivalences mapping found in {map_file_path}." + ) + + coupled_graph = self._couple_lammps_graphs( + pre_graph=pre_graph, + post_graph=post_graph, + pre_to_post_mapping=pre_to_post_mapping, + source=map_file_path, + ) + + return self.is_duplicate_coupled_graph( + coupled_graph=coupled_graph, + comparison_group=comparison_group, + ) + + @staticmethod + def _lammps_reaction_id_from_template_path( + file_path: str | Path, + ) -> str: + """ + Extract reaction ID from names like: + template_pre_22.molecule + template_post_22.molecule + template_pre_1_homo2.molecule + """ + file_path = Path(file_path) + + match = re.match( + r"template_(?:pre|post)_(.+)\.molecule$", + file_path.name, + ) + + if match is None: + raise ValueError( + f"Could not infer reaction ID from template file name: " + f"{file_path.name}" + ) + + return match.group(1) + + def _lammps_map_path_from_template_path( + self, + file_path: str | Path, + ) -> Path: + """Return the RXN_*.map path matching a template molecule path.""" + file_path = Path(file_path) + reaction_id = self._lammps_reaction_id_from_template_path( + file_path + ) + return file_path.with_name(f"RXN_{reaction_id}.map") + + @staticmethod + def _read_lammps_equivalences( + map_file_path: str | Path, + ) -> dict[int, int]: + """ + Read pre-to-post atom equivalences from a LAMMPS bond/react map file. + + Returns: + {pre_atom_id: post_atom_id} + """ + map_file_path = Path(map_file_path) + + section_headers = { + "InitiatorIDs", + "EdgeIDs", + "Equivalences", + "DeleteIDs", + } + + current_section: str | None = None + mapping: dict[int, int] = {} + + with map_file_path.open("r", encoding="utf-8") as file: + for raw_line in file: + line = raw_line.split("#", maxsplit=1)[0].strip() + + if not line: + continue + + if line in section_headers: + current_section = line + continue + + first_token = line.split()[0] + + if first_token in section_headers: + current_section = first_token + continue + + if current_section != "Equivalences": + continue + + parts = line.split() + + if len(parts) < 2: + continue + + try: + pre_atom_id = int(parts[0]) + post_atom_id = int(parts[1]) + except ValueError: + continue + + if ( + pre_atom_id in mapping + and mapping[pre_atom_id] != post_atom_id + ): + raise ValueError( + f"Conflicting Equivalences entry in " + f"{map_file_path}: pre atom {pre_atom_id} maps to " + f"both {mapping[pre_atom_id]} and {post_atom_id}." + ) + + mapping[pre_atom_id] = post_atom_id + + post_to_pre: dict[int, int] = {} + + for pre_atom_id, post_atom_id in mapping.items(): + if ( + post_atom_id in post_to_pre + and post_to_pre[post_atom_id] != pre_atom_id + ): + raise ValueError( + f"Non-bijective Equivalences section in " + f"{map_file_path}: post atom {post_atom_id} is mapped " + f"from both {post_to_pre[post_atom_id]} and " + f"{pre_atom_id}." + ) + + post_to_pre[post_atom_id] = pre_atom_id + + return mapping + + def _couple_lammps_graphs( + self, + pre_graph: nx.Graph, + post_graph: nx.Graph, + pre_to_post_mapping: dict[int, int], + source: Path | str, + ) -> nx.Graph: + """ + Couple LAMMPS pre/post template graphs using RXN_*.map equivalences. + + Unlike the RDKit coupling path, this does not require matching atom IDs + in pre and post files. The map file defines correspondence. + """ + coupled_graph = nx.Graph() + + coupled_graph.graph[self.RADICAL_SIGNATURE_ATTRIBUTE] = ( + pre_graph.graph.get(self.RADICAL_COUNT_ATTRIBUTE, 0), + post_graph.graph.get(self.RADICAL_COUNT_ATTRIBUTE, 0), + pre_graph.graph.get(self.RADICAL_PRESENT_ATTRIBUTE, False), + post_graph.graph.get(self.RADICAL_PRESENT_ATTRIBUTE, False), + ) + + self._add_phase_to_coupled_graph( + source_graph=pre_graph, + coupled_graph=coupled_graph, + phase=self._PRE_PHASE, + ) + + self._add_phase_to_coupled_graph( + source_graph=post_graph, + coupled_graph=coupled_graph, + phase=self._POST_PHASE, + ) + + for pre_atom_id, post_atom_id in pre_to_post_mapping.items(): + if pre_atom_id not in pre_graph: + raise ValueError( + f"Map file {source} references pre atom " + f"{pre_atom_id}, but that atom is not in the " + "pre-template graph." + ) + + if post_atom_id not in post_graph: + raise ValueError( + f"Map file {source} references post atom " + f"{post_atom_id}, but that atom is not in the " + "post-template graph." + ) + + coupled_graph.add_edge( + (self._PRE_PHASE, pre_atom_id), + (self._POST_PHASE, post_atom_id), + relationship=self._ATOM_CORRESPONDENCE_RELATIONSHIP, + **{ + self.EDGE_ATTRIBUTE: None, + }, + ) + + return coupled_graph + def is_duplicate_pair( self, pre_graph: nx.Graph, @@ -266,17 +521,9 @@ def compare_graphs( ) continue - pre_graph = self.lammps_molecule_to_networkx( - pre_file_path - ) - - post_graph = self.lammps_molecule_to_networkx( - post_file_path - ) - - duplicate = self.is_duplicate_pair( - pre_graph=pre_graph, - post_graph=post_graph, + duplicate = self.is_duplicate_lammps_template_pair( + pre_file_path=pre_file_path, + post_file_path=post_file_path, comparison_group=self.LAMMPS_COMPARISON_GROUP, ) @@ -312,28 +559,7 @@ def compare_graphs_mol( For distinct ReactionMetadata objects, the first unique reaction is retained. Later equivalent reactions are disabled by setting ``activity_stats`` to False and are excluded from the returned pool. - - Args: - reaction_metadata_items: - Accumulated reaction metadata pool. - - index_source: - Determines which atom indexes restrict the graph comparison. - - ``template``: - Use ``template_reactant_to_product_mapping``. - - ``first_shell``: - Use ``first_shell`` reactant indexes mapped through - ``reactant_to_product_mapping``. - - Returns: - A new list containing one active representative of each unique - reaction. """ - # Each call is a complete deduplication pass over the current pool. - # Cached graphs from an earlier progression iteration must not be - # reused, or retained reactions will match their own old cache entry. self.clear_cache(self.RDKIT_COMPARISON_GROUP) unique_reactions: list["ReactionMetadata"] = [] @@ -343,15 +569,11 @@ def compare_graphs_mol( reaction_metadata_items, start=1, ): - # Inactive reactions do not participate in the active pool. if not reaction_metadata.activity_stats: continue reaction_object_id = id(reaction_metadata) - # The accumulated progression pool can contain the exact same - # metadata object more than once. Do not mark that object inactive; - # simply keep its first occurrence. if reaction_object_id in retained_object_ids: continue @@ -383,9 +605,6 @@ def compare_graphs_mol( reactant_to_product_mapping.values() ) - # Relabel the product graph into reactant-index space so the - # coupled graph preserves atom correspondence across the - # pre- and post-reaction states. product_to_reactant_mapping = { product_idx: reactant_idx for reactant_idx, product_idx @@ -411,11 +630,6 @@ def compare_graphs_mol( idx_relabel=product_to_reactant_mapping, ) - # Keep full-molecule radical information in addition to the - # atom-level radical labels inside the restricted template graph. - # Progression may explicitly mark the product as radical even when - # the original unsanitized RDKit product does not retain the - # radical-electron property cleanly. reactant_radical_count = self._count_radical_atoms( reactant_mol ) @@ -451,12 +665,6 @@ def compare_graphs_mol( retained_object_ids.add(reaction_object_id) unique_reactions.append(reaction_metadata) - # Debugging: print unique reaction retention information. - # print( - # f"Reaction {reaction_index}: " - # "unique reaction retained." - # ) - return unique_reactions @classmethod @@ -472,15 +680,6 @@ def _one_neighbor_edge_environment_signature( Only neighbors outside the restricted comparison graph are used. This avoids walking into the next molecule or building a larger shell. Internal atoms return an empty signature. - - Each external-neighbor signature contains: - - neighbor element - - neighbor formal charge - - neighbor aromatic state - - neighbor hybridization - - neighbor total hydrogen count - - neighbor radical state - - bond type connecting edge atom to neighbor """ external_neighbor_signatures = [] @@ -520,7 +719,7 @@ def _safe_total_hydrogen_count(atom: Chem.Atom) -> int: for neighbor in atom.GetNeighbors() ) return explicit_h_neighbors + atom.GetNumExplicitHs() - + def clear_cache( self, comparison_group: str | None = None, @@ -566,16 +765,7 @@ def rdkit_mol_to_networkx( Convert an RDKit molecule into a NetworkX graph. Coordinates are not read or stored. - - Node attributes: - ``atom_label`` contains a tuple of: - - chemical element symbol - - whether the atom is a radical center - - Edge attributes: - ``bond_label`` contains the RDKit bond type. """ - if molecule is None: raise ValueError( "Cannot create a graph from a None RDKit molecule." @@ -616,15 +806,11 @@ def rdkit_mol_to_networkx( is_radical = self._is_radical_atom(atom) - # Determine the atom label based on the DEEP_CHECK setting - # DEEP_CHECK should be able to change from input script if not self.DEEP_CHECK: atom_label = ( atom.GetSymbol(), is_radical, ) - - # If DEEP_CHECK is enabled, include the one-neighbor edge environment signature in the atom label. else: atom_label = ( atom.GetSymbol(), @@ -715,12 +901,6 @@ def lammps_molecule_to_networkx( file_path=file_path, ) - # print( - # f"Graph created from {file_path.name}: " - # f"{graph.number_of_nodes()} atoms and " - # f"{graph.number_of_edges()} bonds." - # ) - return graph def compare_lammps_templates( @@ -734,14 +914,15 @@ def compare_lammps_templates( for their pre and post reaction files, detecting duplicates, and returning a list containing only unique templates. """ - # Clear the cache for a fresh deduplication pass self.clear_cache(self.LAMMPS_COMPARISON_GROUP) unique_templates: list["TemplateFile"] = [] for template in template_files: - # Safely check if the template has both required files - if template.pre_reaction_file is None or template.post_reaction_file is None: + if ( + template.pre_reaction_file is None + or template.post_reaction_file is None + ): print( f"Skipping template ID {template.reaction_id}: " "Missing pre or post reaction file definitions." @@ -765,23 +946,12 @@ def compare_lammps_templates( ) continue - # Convert to graphs - pre_graph = self.lammps_molecule_to_networkx(pre_file_path) - post_graph = self.lammps_molecule_to_networkx(post_file_path) - - # Check if this pair has been seen before - duplicate = self.is_duplicate_pair( - pre_graph=pre_graph, - post_graph=post_graph, + duplicate = self.is_duplicate_lammps_template_pair( + pre_file_path=pre_file_path, + post_file_path=post_file_path, comparison_group=self.LAMMPS_COMPARISON_GROUP, ) - # status = "Duplicate" if duplicate else "Unique" - # print( - # f"{status} template ID {template.reaction_id}: " - # f"{pre_file_path.name} -> {post_file_path.name}" - # ) - if not duplicate: unique_templates.append(template) @@ -852,8 +1022,9 @@ def _couple_graphs( """ Combine reactant and product graphs using atom-correspondence edges. + + This RDKit path expects pre and post graph atom IDs to already match. """ - pre_atom_ids = set(pre_template_graph.nodes) post_atom_ids = set(post_template_graph.nodes) @@ -910,9 +1081,7 @@ def _couple_graphs( coupled_graph.add_edge( (self._PRE_PHASE, atom_id), (self._POST_PHASE, atom_id), - relationship=( - self._ATOM_CORRESPONDENCE_RELATIONSHIP - ), + relationship=self._ATOM_CORRESPONDENCE_RELATIONSHIP, **{ self.EDGE_ATTRIBUTE: None, }, @@ -1115,7 +1284,7 @@ def _validate_bond_atoms( f"Bond {bond_id} references undefined atom IDs " f"{undefined_atoms} in {source}." ) - + @classmethod def _count_radical_atoms( cls, @@ -1139,13 +1308,9 @@ def _is_radical_atom(atom: Chem.Atom) -> bool: The fallback is intentionally limited to neutral, non-aromatic carbon atoms used by the current vinyl-radical implementation. """ - - # Best source when progression or RDKit has explicitly assigned the - # radical electron. if atom.GetNumRadicalElectrons() > 0: return True - # Current vinyl implementation only needs neutral carbon radicals. if atom.GetAtomicNum() != 6: return False @@ -1155,21 +1320,13 @@ def _is_radical_atom(atom: Chem.Atom) -> bool: if atom.GetIsAromatic(): return False - # A normal carbon with an implicit hydrogen can have only three visible - # graph bonds. Do not classify it as a radical. try: atom.GetOwningMol().UpdatePropertyCache(strict=False) if atom.GetNumImplicitHs() > 0: return False except RuntimeError: - # Unsanitized reaction products may not have a complete property - # cache. Continue with the graph-based valence calculation. pass - # Count actual graph bonds, including explicit hydrogen atoms. - # - # Do not blindly add GetNumExplicitHs(): RunReactants may retain both - # real hydrogen atoms and a duplicate product-SMARTS hydrogen count. graph_bond_valence = sum( bond.GetBondTypeAsDouble() for bond in atom.GetBonds() @@ -1180,17 +1337,11 @@ def _is_radical_atom(atom: Chem.Atom) -> bool: for neighbor in atom.GetNeighbors() ) - # When no real hydrogen atoms are attached, the explicit-H property is - # part of the atom's valence description and must be included. When - # real H atoms are already present, ignore the property to avoid - # double-counting the same hydrogens. effective_valence = graph_bond_valence if explicit_hydrogen_neighbors == 0: effective_valence += atom.GetNumExplicitHs() - # Neutral carbon with effective valence three and no available implicit - # hydrogen is the carbon-centered radical used by vinyl progression. return abs(effective_valence - 3.0) < 1.0e-6 diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/merge_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/merge_builder.py index ad430e12..b398f8da 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/merge_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/merge_builder.py @@ -81,9 +81,8 @@ def write_bond_react_merge_input( reaction_pairs[rid]["post"] = r # Write pre/post pairs in order - + rxn_counter = 1 for rid in sorted(reaction_pairs): - pair = reaction_pairs[rid] pre = pair.get("pre") @@ -94,13 +93,11 @@ def write_bond_react_merge_input( pre_path = normalize_path(Path(cache_all2lmp) / pre.all2lmp_data_file) post_path = normalize_path(Path(cache_all2lmp) / post.all2lmp_data_file) - data_counter += 1 - tag = f"data{data_counter}" - merge_files += f"{tag:<10}{pre_path:<150}{comment}\n" - data_counter += 1 - tag = f"data{data_counter}" - merge_files += f"{tag:<10}{post_path:<150}{comment}\n" - data_counter += 1 + + merge_files += f"{f'pre{rxn_counter}':<10}{pre_path:<150}# for rxn{rxn_counter}\n" + merge_files += f"{f'post{rxn_counter}':<10}{post_path:<150}# for rxn{rxn_counter}\n" + + rxn_counter += 1 merge_files += f"\n# Specify the parent_directory of where to write results (optional)\n" diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 9c677252..0b140e57 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -356,16 +356,16 @@ def _process_reaction_instances( reaction.functional_group_2 ) - mol_reactant_1 = Chem.AddHs( - Chem.Mol(reaction.monomer_1.rdkit_mol) + mol_reactant_1 = self._copy_loop_reactant_mol( + reaction.monomer_1 ) monomer_2 = ( reaction.monomer_1 if same_reactants else reaction.monomer_2 ) - mol_reactant_2 = Chem.AddHs( - Chem.Mol(monomer_2.rdkit_mol) + mol_reactant_2 = self._copy_loop_reactant_mol( + monomer_2 ) # The ReactionInstance already defines reactant-slot order. @@ -400,6 +400,29 @@ def _process_reaction_instances( return reaction_metadata + def _copy_loop_reactant_mol(self, monomer_role) -> Chem.Mol: + """Copy a loop-mode reactant without changing generated products. + + Initial input monomers are stored as RDKit molecules without explicit + hydrogens before the loop starts, so they still need ``Chem.AddHs``. + Generated products already passed through reaction-progression + sanitization and may contain explicit hydrogens, radical electrons, + and no-implicit flags. Adding hydrogens to those products again can + change the representation that is later sent to LUNAR. + """ + if monomer_role is None or monomer_role.rdkit_mol is None: + raise SMARTSParsingError( + "Loop-mode reactant is missing its RDKit molecule." + ) + + loop_mol = Chem.Mol(monomer_role.rdkit_mol) + loop_mol.UpdatePropertyCache(strict=False) + + if getattr(monomer_role, "is_monomer", False): + return Chem.AddHs(loop_mol) + + return loop_mol + def _process_reaction_products( self, rxn: Chem.rdChemReactions.ChemicalReaction, @@ -1212,6 +1235,6 @@ def reaction_templates_highlighted_image_grid( molsPerRow=2, highlightAtomLists=highlight_lists, highlightAtomColors=highlight_colors, - subImgSize=(400, 400), + subImgSize=(1000, 1000), useSVG=False, ) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 7d04787f..c6f08822 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -313,6 +313,9 @@ def _prepare_products_for_idx_based_fg_detection( continue product_mol = reaction.product_combined_RDmol + product_is_single_fragment = ( + len(Chem.GetMolFrags(product_mol)) == 1 + ) indexes_in_template, product_mol = self._get_product_idxs( reaction.template_reactant_to_product_mapping, product_mol, @@ -323,6 +326,19 @@ def _prepare_products_for_idx_based_fg_detection( # Record radical metadata when sanitization succeeds; otherwise # mark the product as non-radical. if success and sanitized_mol is not None: + # Keep the stage handoff molecule consistent. For + # non-deletion, single-fragment products, the sanitized + # molecule has the same atom indexing as the stored product + # and can safely become the source for both the current + # post-template and the next loop reactant. + if ( + not reaction.delete_atom + and product_is_single_fragment + ): + reaction.product_combined_RDmol = Chem.Mol( + sanitized_mol + ) + self._set_reaction_radical_metadata( reaction, sanitized_mol, From f1ca90a4a94d35f26cb06dbdf3e51ef3f99fae97 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 7 Aug 2026 19:31:45 -0400 Subject: [PATCH 101/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- AutoREACTER/detectors/functional_groups_detector.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index c17f09e7..bff0448d 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -140,10 +140,10 @@ class FunctionalGroupInfo: fg_name: str fg_smarts_1: str fg_count_1: int - fg_1_indexes: Optional[Tuple[int, ...]] = None + fg_1_indexes: Optional[Tuple[Tuple[int, ...], ...]] = None fg_smarts_2: Optional[str] = None fg_count_2: Optional[int] = None - fg_2_indexes: Optional[Tuple[int, ...]] = None + fg_2_indexes: Optional[Tuple[Tuple[int, ...], ...]] = None @dataclass(slots=True) From bb12d911660976b425bc6c0bcb7f815c9a9f85f9 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 7 Aug 2026 19:31:53 -0400 Subject: [PATCH 102/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- AutoREACTER/input_parser.py | 1 - 1 file changed, 1 deletion(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 0e159d0e..7ae674bc 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -2,7 +2,6 @@ import logging from dataclasses import dataclass from pathlib import Path -import time from typing import Any, Literal, Optional From 73ea96af8a6251b1d37d1db5a208107595e13021 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 7 Aug 2026 19:32:03 -0400 Subject: [PATCH 103/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../reaction_preparation/reaction_processor/warning_asci.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py index 8bfa6d48..a1fbf330 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py @@ -1,6 +1,5 @@ -import time - +# (unused import removed) def ascii_art(message: str) -> None: message = message.upper() From 24837c0c8ef7cb65e3246ba2c5224810d08d90e3 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 7 Aug 2026 19:32:20 -0400 Subject: [PATCH 104/176] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/source/supported-reactions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/supported-reactions.md b/docs/source/supported-reactions.md index 5d10cd3a..3971263b 100644 --- a/docs/source/supported-reactions.md +++ b/docs/source/supported-reactions.md @@ -18,7 +18,7 @@ These reactions form ester linkages (`-COO-`) and typically release water (`H₂ * *Reactants:* `-OH` + `-COOH` -* **Hydroxy Carboxylic and Hydroxy Carboxylic Polycondensation** +* **Hydroxy Carboxylic Acid and Hydroxy Carboxylic Acid Polycondensation** * *Reactants:* `-OH` + `-COOH` (Intermolecular) From e8ee361743606d070561ad8f7bcf135b67ed15ed Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:03:35 -0400 Subject: [PATCH 105/176] Move file paths into domain dataclasses Removes intermediate LMPMoleculeFiles, MoleculeFile, and TemplateFile dataclasses. LAMMPS molecule file paths are now stored directly on MonomerEntry, and reaction template/map file paths are stored on ReactionMetadata. REACTERFiles is simplified accordingly. --- AutoREACTER/input_parser.py | 9 ++-- .../ff_wrapper/REACTER_files_builder.py | 41 +++---------------- .../reaction_processor/prepare_reactions.py | 10 ++++- 3 files changed, 19 insertions(+), 41 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 7ae674bc..315acfe2 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -76,20 +76,21 @@ class MonomerEntry: count: Dictionary mapping replica tags to integer counts in counts mode. ratio: Molar ratio of the monomer in ratio mode. rdkit_mol: RDKit Mol object corresponding to the monomer SMILES. - molecule_3Dmol_path: Optional file path to the 3D .mol representation. + molecule_3Dmol_path: Optional file path to the 3D .mol representation. Later stages will generate this file. + lmp_molecule_file: Optional file path to the LAMMPS molecule file. Later stages will generate this file. num_atoms: Number of atoms in the monomer with hydrogens included. molecular_weight: Molecular weight of the monomer from RDKit. status: Boolean indicating whether the monomer should be included. """ - id: int data_id: str name: str | None smiles: str - count: dict | None # None only if ratio mode. - ratio: float | None # None only if counts mode. + count: dict | None + ratio: float | None rdkit_mol: Chem.Mol | None = None molecule_3Dmol_path: Optional[Path] = None + lmp_molecule_file: Optional[Path] = None num_atoms: int | None = None molecular_weight: float | None = None status: bool = True diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index 0eb61614..f3d873ba 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -41,26 +41,6 @@ import logging logger = logging.getLogger(__name__) -@dataclass(slots=True) -class LMPMoleculeFiles: - """Simple container for paired LAMMPS data and molecule files.""" - lmp_molecule_file: Path # Associated *.molecule molecule template - -@dataclass(slots=True) -class MoleculeFile: - """Wrapper associating a molecule ID with its generated data files.""" - id: str - molecule_files: Optional[LMPMoleculeFiles] - -@dataclass(slots=True) -class TemplateFile: - """ - Container for pre- and post-reaction template file pairs. - """ - reaction_id: Optional[int] - map_file: Optional[Path] - pre_reaction_file: Optional[LMPMoleculeFiles] - post_reaction_file: Optional[LMPMoleculeFiles] @dataclass(slots=True) class REACTERFiles: @@ -69,8 +49,7 @@ class REACTERFiles: """ force_field_data: Path # force_field.data (FF parameters) in_file: Path # in.fix_bond_react.script (LAMMPS input) - molecule_files: list[MoleculeFile] - template_files: list[TemplateFile] + class REACTERFilesBuilder: def __init__( @@ -683,10 +662,7 @@ def _copy_lunar_files_to_cache(self, ff_files: FFFiles) -> tuple[Path, Path, lis src = mol.molecule_files.lmp_molecule_file dest = self.cache_dir / f"{mol.id}.molecule" shutil.copy2(src, dest) - molecule_files.append(MoleculeFile( - id=mol.id, - molecule_files=LMPMoleculeFiles(lmp_molecule_file=dest) - )) + monomer.lmp_molecule_file = dest return ff_dest, in_dest, molecule_files @@ -755,16 +731,9 @@ def molecule_template_preparation(self, session: "Session") -> None: edge_atoms = edge_atoms, delete_ids = delete_ids ) - template_files.append(TemplateFile( - reaction_id = id, - map_file = Path(map_path), - pre_reaction_file = LMPMoleculeFiles( - lmp_molecule_file = Path(pre_out) - ), - post_reaction_file = LMPMoleculeFiles( - lmp_molecule_file = Path(post_out) - ) - )) + current_rxn_metadata.map_file = Path(map_path) + current_rxn_metadata.pre_reaction_file = Path(pre_out) + current_rxn_metadata.post_reaction_file = Path(post_out) reacter_files = REACTERFiles( force_field_data=force_field_data, diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 0b140e57..1b092fcb 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -96,6 +96,11 @@ class ReactionMetadata: if generated. product_combined_3Dmol_path: Path to the 3D product structure file, if generated. + map_file: Path to the standard map file generated by REACTER. + map_file_with_delete_ids: Path to the map file including deleted atom + indices, if applicable. + pre_reaction_file: Path to the pre-reaction molecule file. + post_reaction_file: Path to the post-reaction molecule file. is_radical: Whether the reaction involves radical species. radical_atom_idxs: Tuple of reactant indices flagged as radical atoms. activity_stats: True if this reaction is active and unique; set to @@ -122,11 +127,14 @@ class ReactionMetadata: delete_atom_idx: Optional[int] = None reactant_combined_3Dmol_path: Optional[Path] = None product_combined_3Dmol_path: Optional[Path] = None + map_file: Optional[Path] = None + map_file_with_delete_ids: Optional[Path] = None + pre_reaction_file: Optional[Path] = None + post_reaction_file: Optional[Path] = None is_radical: bool = False radical_atom_idxs: Optional[tuple[int, ...]] = () activity_stats: bool = True - class PrepareReactions: """Build reaction products, atom mappings, metadata, and visualizations. From 0fd8215cb0149be4fc1802c51a111a831d775f2a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:11:07 -0400 Subject: [PATCH 106/176] Fix cached LUNAR molecule file handling Update REACTER file preparation to copy LUNAR molecule files directly onto the matching monomer entries instead of returning a separate molecule file list. This also removes unused template/molecule data from the generated REACTERFiles payload and replaces an improper cross-module logger import with a local module logger. --- .../ff_wrapper/REACTER_files_builder.py | 60 +++++++++++-------- .../reaction_processor/prepare_reactions.py | 5 +- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index f3d873ba..f0e74cea 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -624,29 +624,21 @@ def _build_bond_react_templates(self, return pre_out, post_out, map_path - def _copy_lunar_files_to_cache(self, ff_files: FFFiles) -> tuple[Path, Path, list[MoleculeFile]]: + def _copy_lunar_files_to_cache(self, ff_files: FFFiles) -> tuple[Path, Path]: """ - Copy all LUNAR output files into cache_dir. - - Copies force_field.data, in_file, and all molecule files (.lmpmol -> .molecule). + Copy LUNAR output files into cache_dir. - Parameters - ---------- - ff_files : FFFiles - - Returns - ------- - tuple[Path, Path, list[MoleculeFile]] - - force_field_data destination path - - in_file destination path - - list of MoleculeFile with updated cache paths + The run-level files are returned directly. Monomer-level molecule + files are attached to the existing MonomerEntry objects on + session.inputs.monomers. """ ff_dest = self.cache_dir / ff_files.force_field_data.name try: shutil.copy2(ff_files.force_field_data, ff_dest) except Exception as e: raise FileNotFoundError( - f"Failed to copy force field data from '{ff_files.force_field_data}' to '{ff_dest}'." + f"Failed to copy force field data from " + f"'{ff_files.force_field_data}' to '{ff_dest}'." ) from e if not ff_dest.is_file(): @@ -657,14 +649,33 @@ def _copy_lunar_files_to_cache(self, ff_files: FFFiles) -> tuple[Path, Path, lis in_dest = self.cache_dir / ff_files.in_file.name shutil.copy2(ff_files.in_file, in_dest) - molecule_files: list[MoleculeFile] = [] - for mol in ff_files.molecule_files: - src = mol.molecule_files.lmp_molecule_file - dest = self.cache_dir / f"{mol.id}.molecule" + monomers_by_key = {} + for monomer_entry in self.session.inputs.monomers: + monomers_by_key[str(monomer_entry.id)] = monomer_entry + monomers_by_key[str(monomer_entry.data_id)] = monomer_entry + if monomer_entry.name is not None: + monomers_by_key[str(monomer_entry.name)] = monomer_entry + + for mol_file in ff_files.molecule_files: + src = mol_file.molecule_files.lmp_molecule_file + mol_id = str(mol_file.id) + dest = self.cache_dir / f"{mol_id}.molecule" shutil.copy2(src, dest) - monomer.lmp_molecule_file = dest - return ff_dest, in_dest, molecule_files + monomer_entry = monomers_by_key.get(mol_id) + if monomer_entry is None: + logger.warning( + "Could not attach copied molecule file %s to a MonomerEntry " + "using molecule id %s.", + dest, + mol_id, + ) + continue + + monomer_entry.lmp_molecule_file = dest + + return ff_dest, in_dest + def molecule_template_preparation(self, session: "Session") -> None: @@ -686,9 +697,8 @@ def molecule_template_preparation(self, session: "Session") -> None: """ ff_files = session.ff_files prepared_reactions_with_3d_mols = session.reaction_metadata # <--- CHANGED FROM session.inputs - template_files = [] pre_and_post_files = ff_files.template_files - force_field_data, in_file, molecule_files = self._copy_lunar_files_to_cache(ff_files) + force_field_data, in_file = self._copy_lunar_files_to_cache(ff_files) updated_inputs_with_3d_mols= session.inputs # Iterate each reaction entry and build templates for that single reaction only. for rxn in pre_and_post_files: @@ -737,9 +747,7 @@ def molecule_template_preparation(self, session: "Session") -> None: reacter_files = REACTERFiles( force_field_data=force_field_data, - in_file=in_file, - molecule_files=molecule_files, - template_files=template_files + in_file=in_file ) from AutoREACTER.cache import RunDirectoryManager # Import here to avoid circular dependency issues, since RunDirectoryManager also imports REACTERFilesBuilder # Move generated files to final output directory using RunDirectoryManager diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 1b092fcb..4520b030 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -23,9 +23,8 @@ FunctionalGroupInfo, ReactionInstance, ) -from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import ( - logger, -) +import logging +logger = logging.getLogger(__name__) from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ( ReactionProgression, ) From d1256f32d3106da02918af67903059bc111d362a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:14:14 -0400 Subject: [PATCH 107/176] Rebuild REACTER file wrappers during output copy --- .../ff_wrapper/REACTER_files_builder.py | 158 +++++++++++++++--- 1 file changed, 138 insertions(+), 20 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index f0e74cea..4ea16e54 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -42,15 +42,38 @@ logger = logging.getLogger(__name__) + + @dataclass(slots=True) -class REACTERFiles: - """ - Complete collection of output files from the LUNAR workflow. - """ - force_field_data: Path # force_field.data (FF parameters) - in_file: Path # in.fix_bond_react.script (LAMMPS input) +class LMPMoleculeFiles: + """Compatibility wrapper for one LAMMPS molecule/template file.""" + lmp_molecule_file: Path + + +@dataclass(slots=True) +class MoleculeFile: + """Compatibility wrapper used by existing simulation writers.""" + id: str + molecule_files: LMPMoleculeFiles +@dataclass(slots=True) +class TemplateFile: + """Compatibility wrapper used by existing reaction writers/deduplication.""" + reaction_id: int | None + map_file: Path | None + pre_reaction_file: LMPMoleculeFiles | None + post_reaction_file: LMPMoleculeFiles | None + + +@dataclass(slots=True) +class REACTERFiles: + """Run-level files plus compatibility lists for existing writers.""" + force_field_data: Path + in_file: Path + molecule_files: list[MoleculeFile] + template_files: list[TemplateFile] + class REACTERFilesBuilder: def __init__( self, @@ -678,6 +701,25 @@ def _copy_lunar_files_to_cache(self, ff_files: FFFiles) -> tuple[Path, Path]: + def _copy_path_to_final(self, src: Path | str | None, final_dir: Path) -> Path | None: + """Copy one generated REACTER file to the final output directory.""" + if src is None: + return None + + src = Path(src) + if not src.is_file(): + logger.warning("Skipping missing REACTER output file: %s", src) + return None + + final_dir.mkdir(parents=True, exist_ok=True) + dest = final_dir / src.name + + if src.resolve() != dest.resolve(): + shutil.copy2(src, dest) + + return dest + + def molecule_template_preparation(self, session: "Session") -> None: """ Top-level orchestrator that loops over reactions and prepares template @@ -745,27 +787,103 @@ def molecule_template_preparation(self, session: "Session") -> None: current_rxn_metadata.pre_reaction_file = Path(pre_out) current_rxn_metadata.post_reaction_file = Path(post_out) + final_dir = Path(session.output_dir) + + force_field_data = self._copy_path_to_final(force_field_data, final_dir) + in_file = self._copy_path_to_final(in_file, final_dir) + + if force_field_data is None: + raise FileNotFoundError("force_field.data was not copied to final output.") + if in_file is None: + raise FileNotFoundError("LAMMPS input file was not copied to final output.") + + # Keep squeezed data on MonomerEntry, but rebuild old molecule_files list + # because current simulation writers still consume session.reacter_files.molecule_files. + molecule_files: list[MoleculeFile] = [] + for monomer_entry in session.inputs.monomers: + moved_molecule_file = self._copy_path_to_final( + monomer_entry.lmp_molecule_file, + final_dir, + ) + monomer_entry.lmp_molecule_file = moved_molecule_file + + if moved_molecule_file is None: + continue + + molecule_id = ( + monomer_entry.name + or monomer_entry.data_id + or str(monomer_entry.id) + ) + + molecule_files.append( + MoleculeFile( + id=str(molecule_id), + molecule_files=LMPMoleculeFiles( + lmp_molecule_file=moved_molecule_file, + ), + ) + ) + + # Keep squeezed data on ReactionMetadata, but rebuild old template_files list + # because current writers/deduplication still consume template wrappers. + template_files: list[TemplateFile] = [] + for reaction in session.reaction_metadata: + reaction.map_file = self._copy_path_to_final( + reaction.map_file, + final_dir, + ) + reaction.map_file_with_delete_ids = self._copy_path_to_final( + reaction.map_file_with_delete_ids, + final_dir, + ) + reaction.pre_reaction_file = self._copy_path_to_final( + reaction.pre_reaction_file, + final_dir, + ) + reaction.post_reaction_file = self._copy_path_to_final( + reaction.post_reaction_file, + final_dir, + ) + + if ( + reaction.map_file is None + and reaction.pre_reaction_file is None + and reaction.post_reaction_file is None + ): + continue + + template_files.append( + TemplateFile( + reaction_id=reaction.reaction_id, + map_file=reaction.map_file, + pre_reaction_file=( + LMPMoleculeFiles(reaction.pre_reaction_file) + if reaction.pre_reaction_file is not None + else None + ), + post_reaction_file=( + LMPMoleculeFiles(reaction.post_reaction_file) + if reaction.post_reaction_file is not None + else None + ), + ) + ) + reacter_files = REACTERFiles( force_field_data=force_field_data, - in_file=in_file - ) - from AutoREACTER.cache import RunDirectoryManager # Import here to avoid circular dependency issues, since RunDirectoryManager also imports REACTERFilesBuilder - # Move generated files to final output directory using RunDirectoryManager - run_manager = RunDirectoryManager(session.output_dir.parent) - reacter_files = run_manager.move_reacter_files( - reacter_files, - staging_dir=session.staging_dir, - final_dir=session.output_dir + in_file=in_file, + molecule_files=molecule_files, + template_files=template_files, ) session.reacter_files = reacter_files - - # print (session.reacter_files) + print(f"[OK] Moved files → {final_dir}") + detector = DeduplicationDetector() - template_files = session.reacter_files.template_files - # print("Comparing LAMMPS templates for duplicates...") session.reacter_files.template_files = detector.compare_lammps_templates( - template_files=template_files + template_files=session.reacter_files.template_files, ) + return None \ No newline at end of file From 66dc381ce0fca89323682b05799d05e8be6156a8 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:23:34 -0400 Subject: [PATCH 108/176] Remove legacy REACTER file wrapper types --- .../ff_wrapper/REACTER_files_builder.py | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index 4ea16e54..c6f1ed38 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -42,37 +42,11 @@ logger = logging.getLogger(__name__) - - -@dataclass(slots=True) -class LMPMoleculeFiles: - """Compatibility wrapper for one LAMMPS molecule/template file.""" - lmp_molecule_file: Path - - -@dataclass(slots=True) -class MoleculeFile: - """Compatibility wrapper used by existing simulation writers.""" - id: str - molecule_files: LMPMoleculeFiles - - -@dataclass(slots=True) -class TemplateFile: - """Compatibility wrapper used by existing reaction writers/deduplication.""" - reaction_id: int | None - map_file: Path | None - pre_reaction_file: LMPMoleculeFiles | None - post_reaction_file: LMPMoleculeFiles | None - - @dataclass(slots=True) class REACTERFiles: """Run-level files plus compatibility lists for existing writers.""" force_field_data: Path in_file: Path - molecule_files: list[MoleculeFile] - template_files: list[TemplateFile] class REACTERFilesBuilder: def __init__( From 2703656c2d26fe674dff928b47da341cc99ae1c4 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:32:40 -0400 Subject: [PATCH 109/176] Simplify REACTERFiles to store metadata directly --- .../ff_wrapper/REACTER_files_builder.py | 66 +++---------------- 1 file changed, 8 insertions(+), 58 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index c6f1ed38..46a3170c 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -44,9 +44,11 @@ @dataclass(slots=True) class REACTERFiles: - """Run-level files plus compatibility lists for existing writers.""" + """Run-level files plus final monomer/reaction metadata lists.""" force_field_data: Path in_file: Path + molecule_files: list + template_files: list class REACTERFilesBuilder: def __init__( @@ -771,37 +773,14 @@ def molecule_template_preparation(self, session: "Session") -> None: if in_file is None: raise FileNotFoundError("LAMMPS input file was not copied to final output.") - # Keep squeezed data on MonomerEntry, but rebuild old molecule_files list - # because current simulation writers still consume session.reacter_files.molecule_files. - molecule_files: list[MoleculeFile] = [] + # Store final monomer molecule paths directly on MonomerEntry. for monomer_entry in session.inputs.monomers: - moved_molecule_file = self._copy_path_to_final( + monomer_entry.lmp_molecule_file = self._copy_path_to_final( monomer_entry.lmp_molecule_file, final_dir, ) - monomer_entry.lmp_molecule_file = moved_molecule_file - if moved_molecule_file is None: - continue - - molecule_id = ( - monomer_entry.name - or monomer_entry.data_id - or str(monomer_entry.id) - ) - - molecule_files.append( - MoleculeFile( - id=str(molecule_id), - molecule_files=LMPMoleculeFiles( - lmp_molecule_file=moved_molecule_file, - ), - ) - ) - - # Keep squeezed data on ReactionMetadata, but rebuild old template_files list - # because current writers/deduplication still consume template wrappers. - template_files: list[TemplateFile] = [] + # Store final reaction template/map paths directly on ReactionMetadata. for reaction in session.reaction_metadata: reaction.map_file = self._copy_path_to_final( reaction.map_file, @@ -820,44 +799,15 @@ def molecule_template_preparation(self, session: "Session") -> None: final_dir, ) - if ( - reaction.map_file is None - and reaction.pre_reaction_file is None - and reaction.post_reaction_file is None - ): - continue - - template_files.append( - TemplateFile( - reaction_id=reaction.reaction_id, - map_file=reaction.map_file, - pre_reaction_file=( - LMPMoleculeFiles(reaction.pre_reaction_file) - if reaction.pre_reaction_file is not None - else None - ), - post_reaction_file=( - LMPMoleculeFiles(reaction.post_reaction_file) - if reaction.post_reaction_file is not None - else None - ), - ) - ) - reacter_files = REACTERFiles( force_field_data=force_field_data, in_file=in_file, - molecule_files=molecule_files, - template_files=template_files, + molecule_files=list(session.inputs.monomers), + template_files=list(session.reaction_metadata), ) session.reacter_files = reacter_files print(f"[OK] Moved files → {final_dir}") - detector = DeduplicationDetector() - session.reacter_files.template_files = detector.compare_lammps_templates( - template_files=session.reacter_files.template_files, - ) - return None \ No newline at end of file From 63a2438ad851a30ebbcf5ebb9ec88f3b09b5d9fd Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:33:09 -0400 Subject: [PATCH 110/176] Fix writer paths for reaction template files --- AutoREACTER/sim_setup/writers/densification_writer.py | 8 ++++---- AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py | 8 ++++---- AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/AutoREACTER/sim_setup/writers/densification_writer.py b/AutoREACTER/sim_setup/writers/densification_writer.py index e8847fdb..c2027775 100644 --- a/AutoREACTER/sim_setup/writers/densification_writer.py +++ b/AutoREACTER/sim_setup/writers/densification_writer.py @@ -165,7 +165,7 @@ def write_lammps_densification_file(self, simulation: Simulation) -> str: for i, mol in enumerate(rf.molecule_files, 1): m_id = f"mol_{i}" mol_ids[mol.id] = m_id - lines.append(f"{'molecule':<16} {m_id} {mol.molecule_files.lmp_molecule_file.name}") + lines.append(f"{'molecule':<16} {m_id} {mol.lmp_molecule_file.name}") lines.append("\n#------------Randomly Insert Molecules------------") for m_name, count in simulation.monomer_counts.items(): @@ -324,7 +324,7 @@ def _copy_required_files(self, dest_dir: Path) -> None: for mol in rf.molecule_files: if (mol.molecule_files and - mol.molecule_files.lmp_molecule_file and - mol.molecule_files.lmp_molecule_file.exists()): - src = mol.molecule_files.lmp_molecule_file + mol.lmp_molecule_file and + mol.lmp_molecule_file.exists()): + src = mol.lmp_molecule_file shutil.copy2(src, dest_dir / src.name) diff --git a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py index ade793be..3e3773b6 100644 --- a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py @@ -143,8 +143,8 @@ def write_first_stage_reaction_files(self, simulation: Simulation) -> str: for template in (rf.template_files): # Extract filenames from the dataclass fields - pre_file = template.pre_reaction_file.lmp_molecule_file.name - post_file = template.post_reaction_file.lmp_molecule_file.name + pre_file = template.pre_reaction_file.name + post_file = template.post_reaction_file.name map_file = template.map_file.name id = template.reaction_id pre_id = f"mol_pre_{id}" @@ -217,8 +217,8 @@ def _copy_required_files(self, dest_dir: Path) -> None: for template in rf.template_files: files: list[Path] = [ template.map_file, - template.pre_reaction_file.lmp_molecule_file, - template.post_reaction_file.lmp_molecule_file, + template.pre_reaction_file, + template.post_reaction_file, ] for file in files: diff --git a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py index f0fdbb4e..383023d2 100644 --- a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py @@ -139,8 +139,8 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: post_id = f"mol_post_{i}" # Extract molecule and mapping file names from template objects - pre_file = template.pre_reaction_file.lmp_molecule_file.name - post_file = template.post_reaction_file.lmp_molecule_file.name + pre_file = template.pre_reaction_file.name + post_file = template.post_reaction_file.name map_file = template.map_file.name # Register molecule templates in LAMMPS @@ -208,8 +208,8 @@ def _copy_required_files(self, dest_dir: Path) -> None: # Collect all files associated with this reaction template files = [ template.map_file, - template.pre_reaction_file.lmp_molecule_file, - template.post_reaction_file.lmp_molecule_file + template.pre_reaction_file, + template.post_reaction_file ] # Copy each file to the destination, preserving metadata From 17a829536acfaf701d66d896ef10b8858b96e650 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:38:47 -0400 Subject: [PATCH 111/176] Fix molecule file copy guard in densification --- AutoREACTER/sim_setup/writers/densification_writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutoREACTER/sim_setup/writers/densification_writer.py b/AutoREACTER/sim_setup/writers/densification_writer.py index c2027775..e64fc1ee 100644 --- a/AutoREACTER/sim_setup/writers/densification_writer.py +++ b/AutoREACTER/sim_setup/writers/densification_writer.py @@ -323,7 +323,7 @@ def _copy_required_files(self, dest_dir: Path) -> None: shutil.copy2(rf.force_field_data, dest_dir / rf.force_field_data.name) for mol in rf.molecule_files: - if (mol.molecule_files and + if (mol.lmp_molecule_file and mol.lmp_molecule_file and mol.lmp_molecule_file.exists()): src = mol.lmp_molecule_file From e86583269124cdc2f52d2b2a1eb2d9d74db5ee34 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:55:32 -0400 Subject: [PATCH 112/176] Filter inactive reaction templates in pipeline --- AutoREACTER/arx_cli.py | 19 +- .../reactions_library/vinyl_polymers.py | 240 ++++++++++++++---- .../deduplication_detector.py | 34 ++- .../ff_wrapper/REACTER_files_builder.py | 16 +- .../reaction_processor/prepare_reactions.py | 6 + .../writers/rxn_first_stage_writer.py | 10 +- .../writers/rxn_second_stage_writer.py | 11 +- 7 files changed, 265 insertions(+), 71 deletions(-) diff --git a/AutoREACTER/arx_cli.py b/AutoREACTER/arx_cli.py index 14a2efc8..cef2b1b2 100644 --- a/AutoREACTER/arx_cli.py +++ b/AutoREACTER/arx_cli.py @@ -246,14 +246,6 @@ def prepare_reactions(self) -> None: """ PrepareReactions(self.session).prepare_reactions(self.session) self.error_handler["process"] = True - highlight_types = ["template", "edge", "initiators", "delete"] - for highlight_type in highlight_types: - img = PrepareReactions(self.session).reaction_templates_highlighted_image_grid( - self.session, highlight_type=highlight_type - ) - self._save_rdkit_img( - img, self.img_dir / f"templates_{highlight_type}.png" - ) return None def show_reaction_templates(self, highlight_type: str = "template") -> Image: @@ -316,6 +308,17 @@ def process(self): SimulationSetupManager().setup_and_write_simulation(self.session) + highlight_types = ["template", "edge", "initiators", "delete"] + for highlight_type in highlight_types: + img = PrepareReactions(self.session).reaction_templates_highlighted_image_grid( + self.session, highlight_type=highlight_type + ) + self._save_rdkit_img( + img, self.img_dir / f"templates_{highlight_type}.png" + ) + + self.error_handler["process"] = True + # ------------------------------------------------------------------ # Internal helpers – lazy detection & image saving # ------------------------------------------------------------------ diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py index e7f2c27d..f246312f 100644 --- a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -1,44 +1,162 @@ REACTIONS = { 'Vinyl Addition Polymerization Initiation': { + 'same_reactants': True, + 'reactant_1': 'vinyl', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + # H-T self-initiation cheat: + # + # tail=head + tail=head + # ↓ + # cap-tail-head-tail-head* + # + # AutoREACTER/LAMMPS rule: + # maps 1 and 2 are the initiator atoms. + # the new bond is 1-2. + # + # Map 3 = first vinyl terminal CH2 tail; capped as CH3 + # Map 1 = first vinyl substituted head + # Map 2 = second vinyl terminal CH2 tail + # Map 4 = second vinyl substituted head; becomes active radical + 'reaction': ( + '[CH2:3]=[C;!R:1].' + '[CH2:2]=[C;!R:4]' + '>>' + '[CH3:3]-[C:1]-[CH2:2]-[C;!R:4]' + ), + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None, + 'notes': ( + 'Self-initiation cheat for styrene/vinyl. H-T topology. ' + 'New bond is maps 1-2. Map 3 is capped as CH3 so the ' + 'post-initiation template matches propagation. Map 4 is the ' + 'new active chain-end radical.' + ), + }, + + 'Vinyl Addition Polymerization Propagation': { + 'same_reactants': False, + 'reactant_1': 'vinyl', + 'reactant_2': 'vinyl_chain_end_radical', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + # H-T propagation: + # + # chain-head* + tail=head + # ↓ + # chain-head-tail-head* + # + # AutoREACTER/LAMMPS rule: + # maps 1 and 2 are the initiator atoms. + # the new bond is 1-2. + # + # Map 1 = existing radical chain end/head. + # This is forced by the loop-detected + # vinyl_chain_end_radical index. + # Map 2 = incoming vinyl terminal CH2 tail + # Map 3 = incoming vinyl substituted head; becomes new radical + 'reaction': ( + '[CH2:2]=[C;!R:3].' + '[C;!R:1]' + '>>' + '[C:1]-[CH2:2]-[C;!R:3]' + ), + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None, + 'notes': ( + 'Head-to-tail vinyl propagation. Existing chain-end radical map ' + '1 bonds to incoming vinyl tail map 2. Map 3 becomes the new ' + 'active chain-end radical. Map 1 is selected from explicit ' + 'radical detection during loop progression.' + ), + }, + +'Vinyl Radical Coupling Termination': { 'same_reactants': True, - 'reactant_1': 'vinyl', - 'product': 'vinyl_chain_end_radical', + 'reactant_1': 'vinyl_chain_end_radical', + 'product': 'vinyl_terminated_chain', 'delete_atom': False, - 'reaction': '[CH2:1]=[C;!R:3].[CH2:2]=[C;!R:4]>>[CH2:1](-[C:3])-[CH2:2]-[C:4]', - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': None -}, -'Vinyl Addition Polymerization Propagation': { - 'same_reactants': False, - 'reactant_1': 'vinyl', - 'reactant_2': 'vinyl_chain_end_radical', - 'product': 'vinyl_chain_end_radical', - 'delete_atom': False, - 'reaction': '[CH2:2]=[C;!R:3].[C;!R;D3;v3:1]>>[C:1]-[CH2:2]-[C:3]', + # H-H radical coupling termination: + # + # chain-head* + *head-chain + # ↓ + # chain-head-head-chain + # + # This is intentionally the only head-to-head vinyl step. + # Initiation and propagation remain head-to-tail. + # + # AutoREACTER/LAMMPS rule: + # maps 1 and 2 are the initiator atoms. + # the new termination bond is 1-2. + # + # Map 1 = active radical head carbon on one vinyl chain end. + # Map 2 = active radical head carbon on another vinyl chain end. + # + # The D3/v3/+0 constraints make this target the methacrylate-style + # chain-end radical center instead of any ordinary acyclic carbon. + 'reaction': ( + '[C;!R;D3;v3;+0:1].' + '[C;!R;D3;v3;+0:2]' + '>>' + '[C:1]-[C:2]' + ), + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': None + 'comments': None, + 'notes': ( + 'Head-to-head radical coupling termination for PMMA/TEGDMA-style ' + 'vinyl chain ends. Maps 1 and 2 are the two active radical head ' + 'carbons and form the new 1-2 termination bond. This reaction ' + 'should be controlled separately from initiation and propagation, ' + 'usually turned on late or pulsed so it does not kill vinyl growth ' + 'too early.' + ), }, - -'Vinyl Copolymerization': { +'Vinyl Branchable Copolymerization Initiation': { 'same_reactants': False, 'reactant_1': 'vinyl', 'reactant_2': 'vinyl', - 'product': 'copolyvinyl_chain', + 'product': 'vinyl_chain_end_radical', 'delete_atom': False, - 'reaction': '[CH2:1]=[C;!R:2].[CH2:3]=[C;!R:4]>>[CH2:1]-[C:2]-[CH2:3]-[C:4]', + + # H-T branchable-vinyl copolymerization initiation: + # + # branchable tail=head + vinyl tail=head + # ↓ + # capped-branchable-head-tail-vinyl-head* + # + # This intentionally forces the rare branchable vinyl into the seed. + # + # AutoREACTER/LAMMPS rule: + # maps 1 and 2 are the initiator atoms. + # the new bond is 1-2. + # + # Map 3 = branchable vinyl terminal CH2 tail; capped as CH3 + # Map 1 = branchable vinyl substituted head + # Map 2 = incoming normal vinyl terminal CH2 tail + # Map 4 = incoming normal vinyl substituted head; becomes active radical + 'reaction': ( + '[CH2:3]=[C;!R:1].' + '[CH2:2]=[C;!R:4]' + '>>' + '[CH3:3]-[C:1]-[CH2:2]-[C;!R;D3;v3;+0:4]' + ), + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': 'General vinyl copolymerization; supports terminal vinyl and methacrylate-style substituted vinyls' + 'comments': None, + 'notes': ( + 'Forced H-T copolymerization initiation between a rare branchable ' + 'vinyl/crosslinker vinyl and a normal vinyl monomer. The branchable ' + 'vinyl is placed into the initial chain segment, while the active ' + 'radical is carried forward on the normal vinyl head atom map 4. ' + 'Maps 1 and 2 form the new bond. Use this reaction with separate ' + 'time control or max_rxn limits so the low-count crosslinker is not ' + 'over-consumed at the beginning.' + ), }, - # 'Vinyl Radical Coupling Termination': { - # 'same_reactants': True, - # 'reactant_1': 'vinyl_chain_end_radical', - # 'product': 'vinyl_terminated_chain', - # 'delete_atom': False, - # 'reaction': '[C;!R;D3;v3;+0:1].[C;!R;D3;v3;+0:2]>>[C:1]-[C:2]', - # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # 'comments': None - # }, + + # ---- kept commented, unchanged ---- # 'Vinyl Addition Polymerization': { # 'same_reactants': True, # 'reactant_1': 'vinyl', @@ -58,7 +176,6 @@ # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, # 'comments': None # }, - # Later Implementation # 'Cyclic Olefin Addition Polymerization': { # 'same_reactants': True, # 'reactant_1': 'cyclic_olefin', @@ -87,25 +204,58 @@ # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, # 'comments': None - # } + # }, - 'Tetrafluoroethylene Addition Polymerization Initiation': { - 'same_reactants': True, - 'reactant_1': 'tetrafluoroethylene', - 'product': 'vinyl_chain_end_radical', + 'Tetrafluoroethylene Initiation': { + 'same_reactants': False, + 'reactant_1': 'initiator_radical', + 'reactant_2': 'tetrafluoroethylene', + 'product': 'ptfe_active_center', 'delete_atom': False, - 'reaction': '[CX3:1](-[F:5])(-[F:6])=[C;!R:3](-[F:7])(-[F:8]).[CX3:2](-[F:9])(-[F:10])=[C;!R:4](-[F:11])(-[F:12])>>[CX3:1](-[F:5])(-[F:6])(-[C:3](-[F:7])(-[F:8]))-[CX3:2](-[F:9])(-[F:10])-[C;!R;D3;v3:4](-[F:11])(-[F:12])', - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': 'Self-initiation cheat for TFE polymerization' + 'reaction': ( + '[*:1].' + '[CX3:2](-[F:4])(-[F:5])=[CX3:3](-[F:6])(-[F:7])' + '>>' + '[*:1]-[CX4:2](-[F:4])(-[F:5])-[CX4:3](-[F:6])(-[F:7])' + ), + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': 'Initiation of TFE to form the first active center' }, - 'Tetrafluoroethylene Addition Polymerization Propagation': { + + 'Tetrafluoroethylene Propagation': { 'same_reactants': False, - 'reactant_1': 'tetrafluoroethylene', - 'reactant_2': 'vinyl_chain_end_radical', - 'product': 'vinyl_chain_end_radical', + 'reactant_1': 'ptfe_active_center', + 'reactant_2': 'tetrafluoroethylene', + 'product': 'ptfe_active_center', 'delete_atom': False, - 'reaction': '[CX3:2](-[F:5])(-[F:6])=[C;!R:3](-[F:7])(-[F:8]).[C;!R;D3;v3:1](-[F:9])(-[F:10])>>[C:1](-[F:9])(-[F:10])-[CX3:2](-[F:5])(-[F:6])-[C;!R;D3;v3:3](-[F:7])(-[F:8])', - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': 'Propagation step carrying the radical center forward for TFE' - } + 'reaction': ( + '[*:1]-[CX4:2](-[F:4])(-[F:5]).' + '[CX3:3](-[F:6])(-[F:7])=[CX3:8](-[F:9])(-[F:10])' + '>>' + '[*:1]-[CX4:2](-[F:4])(-[F:5])-' + '[CX4:3](-[F:6])(-[F:7])-[CX4:8](-[F:9])(-[F:10])' + ), + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': 'Propagation step for PTFE chain growth' + }, + + # 'Tetrafluoroethylene Termination (Recombination)': { + # 'same_reactants': True, + # 'reactant_1': 'ptfe_active_center', + # 'product': 'ptfe_chain', + # 'delete_atom': False, + # # Two growing chains meet and recombine at their active CX4 centers + # 'reaction': '[*:1]-[CX4:2](-[F:4])(-[F:5]).[*:3]-[CX4:6](-[F:7])(-[F:8])>>[*:1]-[CX4:2](-[F:4])(-[F:5])-[CX4:6](-[F:7])(-[F:8])-[*:3]', + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # 'comments': 'UNTESTED: Radical recombination termination for PTFE' + # } } \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index a01d2c37..e9bda978 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -20,9 +20,6 @@ from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( ReactionMetadata, ) - from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import ( - TemplateFile, - ) class DeduplicationDetector: @@ -905,20 +902,23 @@ def lammps_molecule_to_networkx( def compare_lammps_templates( self, - template_files: list["TemplateFile"], - ) -> list["TemplateFile"]: + template_files: list["ReactionMetadata"], + ) -> list["ReactionMetadata"]: """ Compare LAMMPS pre/post molecule-template pairs. - Filters a list of TemplateFile objects by generating LAMMPS graphs - for their pre and post reaction files, detecting duplicates, and - returning a list containing only unique templates. + Filters a list of ReactionMetadata objects by generating LAMMPS graphs + for their pre and post reaction files, detecting duplicates, setting + duplicate reactions inactive, and returning only active unique templates. """ self.clear_cache(self.LAMMPS_COMPARISON_GROUP) - unique_templates: list["TemplateFile"] = [] + unique_templates: list["ReactionMetadata"] = [] for template in template_files: + if not template.activity_stats: + continue + if ( template.pre_reaction_file is None or template.post_reaction_file is None @@ -927,16 +927,18 @@ def compare_lammps_templates( f"Skipping template ID {template.reaction_id}: " "Missing pre or post reaction file definitions." ) + template.activity_stats = False continue - pre_file_path = template.pre_reaction_file.lmp_molecule_file - post_file_path = template.post_reaction_file.lmp_molecule_file + pre_file_path = Path(template.pre_reaction_file) + post_file_path = Path(template.post_reaction_file) if not pre_file_path.is_file(): print( f"Skipping template ID {template.reaction_id}: " f"Pre-template file does not exist: {pre_file_path}" ) + template.activity_stats = False continue if not post_file_path.is_file(): @@ -944,6 +946,7 @@ def compare_lammps_templates( f"Skipping template ID {template.reaction_id}: " f"Post-template file does not exist: {post_file_path}" ) + template.activity_stats = False continue duplicate = self.is_duplicate_lammps_template_pair( @@ -952,8 +955,13 @@ def compare_lammps_templates( comparison_group=self.LAMMPS_COMPARISON_GROUP, ) - if not duplicate: - unique_templates.append(template) + if duplicate: + template.activity_stats = False + print(f"Duplicate template disabled: RXN_{template.reaction_id}") + continue + + template.activity_stats = True + unique_templates.append(template) return unique_templates diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index 46a3170c..33360342 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -799,11 +799,25 @@ def molecule_template_preparation(self, session: "Session") -> None: final_dir, ) + active_template_reactions = [ + reaction + for reaction in session.reaction_metadata + if reaction.activity_stats + and reaction.map_file is not None + and reaction.pre_reaction_file is not None + and reaction.post_reaction_file is not None + ] + + detector = DeduplicationDetector() + active_template_reactions = detector.compare_lammps_templates( + template_files=active_template_reactions, + ) + reacter_files = REACTERFiles( force_field_data=force_field_data, in_file=in_file, molecule_files=list(session.inputs.monomers), - template_files=list(session.reaction_metadata), + template_files=active_template_reactions, ) session.reacter_files = reacter_files diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 4520b030..5141c9ec 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -1154,6 +1154,9 @@ def reaction_templates_highlighted_image_grid( names = [] for metadata in metadata_list: + if not metadata.activity_stats: + continue + reactant = Chem.RWMol(metadata.reactant_combined_RDmol) product = Chem.RWMol(metadata.product_combined_RDmol) names.extend( @@ -1236,6 +1239,9 @@ def reaction_templates_highlighted_image_grid( [reactant_color_map, product_color_map] ) + if not mols: + return None + return Draw.MolsToGridImage( mols, legends=names, diff --git a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py index 3e3773b6..29082969 100644 --- a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py @@ -140,7 +140,10 @@ def write_first_stage_reaction_files(self, simulation: Simulation) -> str: lines.append("#------------Define Reaction Templates------------") rxn_commands: list[str] = [] - for template in (rf.template_files): + for template in [ + t for t in rf.template_files + if getattr(t, "activity_stats", True) + ]: # Extract filenames from the dataclass fields pre_file = template.pre_reaction_file.name @@ -214,7 +217,10 @@ def _copy_required_files(self, dest_dir: Path) -> None: """ rf = self.reacter_files - for template in rf.template_files: + for template in [ + t for t in rf.template_files + if getattr(t, "activity_stats", True) + ]: files: list[Path] = [ template.map_file, template.pre_reaction_file, diff --git a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py index 383023d2..93732a72 100644 --- a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py @@ -133,7 +133,11 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: # Define reaction templates and build reaction fix commands lines.append("#------------Define Reaction Templates------------") rxn_commands = [] - for i, template in enumerate(rf.template_files, 1): + for template in [ + t for t in rf.template_files + if getattr(t, "activity_stats", True) + ]: + i = template.reaction_id # Create unique identifiers for pre- and post-reaction molecule templates pre_id = f"mol_pre_{i}" post_id = f"mol_post_{i}" @@ -204,7 +208,10 @@ def _copy_required_files(self, dest_dir: Path) -> None: FileNotFoundError: If any required reaction file is missing or cannot be accessed """ rf = self.reacter_files - for template in rf.template_files: + for template in [ + t for t in rf.template_files + if getattr(t, "activity_stats", True) + ]: # Collect all files associated with this reaction template files = [ template.map_file, From 85f939ef324bdf9fd40696d95be83317c36e064d Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:57:11 -0400 Subject: [PATCH 113/176] Disable vinyl termination and rename initiation --- .../reactions_library/vinyl_polymers.py | 84 +++++++++---------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py index f246312f..20a6d009 100644 --- a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -70,50 +70,50 @@ 'radical detection during loop progression.' ), }, +# Users can uncomment the following reactions if they want to include vinyl radical coupling termination in their simulation. However, this reaction is typically controlled separately from initiation and propagation to avoid premature termination of vinyl growth. +# 'Vinyl Radical Coupling Termination': { +# 'same_reactants': True, +# 'reactant_1': 'vinyl_chain_end_radical', +# 'product': 'vinyl_terminated_chain', +# 'delete_atom': False, -'Vinyl Radical Coupling Termination': { - 'same_reactants': True, - 'reactant_1': 'vinyl_chain_end_radical', - 'product': 'vinyl_terminated_chain', - 'delete_atom': False, +# # H-H radical coupling termination: +# # +# # chain-head* + *head-chain +# # ↓ +# # chain-head-head-chain +# # +# # This is intentionally the only head-to-head vinyl step. +# # Initiation and propagation remain head-to-tail. +# # +# # AutoREACTER/LAMMPS rule: +# # maps 1 and 2 are the initiator atoms. +# # the new termination bond is 1-2. +# # +# # Map 1 = active radical head carbon on one vinyl chain end. +# # Map 2 = active radical head carbon on another vinyl chain end. +# # +# # The D3/v3/+0 constraints make this target the methacrylate-style +# # chain-end radical center instead of any ordinary acyclic carbon. +# 'reaction': ( +# '[C;!R;D3;v3;+0:1].' +# '[C;!R;D3;v3;+0:2]' +# '>>' +# '[C:1]-[C:2]' +# ), - # H-H radical coupling termination: - # - # chain-head* + *head-chain - # ↓ - # chain-head-head-chain - # - # This is intentionally the only head-to-head vinyl step. - # Initiation and propagation remain head-to-tail. - # - # AutoREACTER/LAMMPS rule: - # maps 1 and 2 are the initiator atoms. - # the new termination bond is 1-2. - # - # Map 1 = active radical head carbon on one vinyl chain end. - # Map 2 = active radical head carbon on another vinyl chain end. - # - # The D3/v3/+0 constraints make this target the methacrylate-style - # chain-end radical center instead of any ordinary acyclic carbon. - 'reaction': ( - '[C;!R;D3;v3;+0:1].' - '[C;!R;D3;v3;+0:2]' - '>>' - '[C:1]-[C:2]' - ), - - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': None, - 'notes': ( - 'Head-to-head radical coupling termination for PMMA/TEGDMA-style ' - 'vinyl chain ends. Maps 1 and 2 are the two active radical head ' - 'carbons and form the new 1-2 termination bond. This reaction ' - 'should be controlled separately from initiation and propagation, ' - 'usually turned on late or pulsed so it does not kill vinyl growth ' - 'too early.' - ), -}, -'Vinyl Branchable Copolymerization Initiation': { +# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, +# 'comments': None, +# 'notes': ( +# 'Head-to-head radical coupling termination for PMMA/TEGDMA-style ' +# 'vinyl chain ends. Maps 1 and 2 are the two active radical head ' +# 'carbons and form the new 1-2 termination bond. This reaction ' +# 'should be controlled separately from initiation and propagation, ' +# 'usually turned on late or pulsed so it does not kill vinyl growth ' +# 'too early.' +# ), +# }, +'Vinyl Copolymerization Initiation': { 'same_reactants': False, 'reactant_1': 'vinyl', 'reactant_2': 'vinyl', From 181efef809d71131cf6b6082541a0be00566897a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:30:55 -0400 Subject: [PATCH 114/176] Add reaction workflow options to session setup --- AutoREACTER/input_parser.py | 41 +++++++++++++++ AutoREACTER/session.py | 100 +++++++++++++++++++++++++++++++++--- 2 files changed, 133 insertions(+), 8 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 315acfe2..27f5ad2a 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -144,6 +144,13 @@ class SimulationSetup: ratio: Optional mapping of monomer IDs to ratios. number_of_total_atoms: Optional list of total atom targets. box_estimates: Optional estimated box size placeholder. + deep_search: Enables deeper reaction/functional-group searching. + reaction_iteration_depth: Maximum reaction progression depth. Use an + integer or "all". + wildcards: Enables wildcard handling when supported downstream. + deduplicate_reaction_templates: Enables LAMMPS template deduplication. + write_second_reaction_stage: Enables writing the second reaction-stage + LAMMPS input files. """ simulation_name: str @@ -160,6 +167,11 @@ class SimulationSetup: ratio: dict[int, float] | None = None number_of_total_atoms: list[int] | None = None box_estimates: float | None = None + deep_search: bool = True + reaction_iteration_depth: int | Literal["all"] = 5 + wildcards: bool = True + deduplicate_reaction_templates: bool = True + write_second_reaction_stage: bool = True class InputParser: @@ -210,6 +222,30 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: loop, max_loop_count = self._validate_loop(inputs) + deep_search = self._validate_bool_option( + inputs, + key="deep_search", + default=True, + ) + reaction_iteration_depth = self._validate_reaction_iteration_depth( + inputs + ) + wildcards = self._validate_bool_option( + inputs, + key="wildcards", + default=True, + ) + deduplicate_reaction_templates = self._validate_bool_option( + inputs, + key="deduplicate_reaction_templates", + default=True, + ) + write_second_reaction_stage = self._validate_bool_option( + inputs, + key="write_second_reaction_stage", + default=True, + ) + return SimulationSetup( simulation_name=simulation_name, temperature=validated_simulations["temperatures"], @@ -222,6 +258,11 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: loop=loop, max_loop_count=max_loop_count, input_json=inputs, + deep_search=deep_search, + reaction_iteration_depth=reaction_iteration_depth, + wildcards=wildcards, + deduplicate_reaction_templates=deduplicate_reaction_templates, + write_second_reaction_stage=write_second_reaction_stage, ) def molecule_representation_of_initial_molecules( diff --git a/AutoREACTER/session.py b/AutoREACTER/session.py index c4100760..fe9753d7 100644 --- a/AutoREACTER/session.py +++ b/AutoREACTER/session.py @@ -15,22 +15,106 @@ if TYPE_CHECKING: from AutoREACTER.detectors.functional_groups_detector import MonomerRole -@dataclass +from dataclasses import dataclass, field +from pathlib import Path +from typing import Literal + + +@dataclass(slots=True) class Session: """ - Holds the validated inputs and directory paths for a single AutoREACTER run. - This acts as the 'state object' passed through the pipeline. + Runtime state container for one AutoREACTER workflow. + + A Session stores the validated input model, run directories, and all + intermediate/final objects generated as the pipeline progresses. + + The object is intentionally passed through the full AutoREACTER pipeline so + each stage can attach its own outputs without requiring large return-value + chains. + + Pipeline state + -------------- + inputs: + Validated simulation setup parsed from the input JSON. + + staging_dir: + Temporary working directory used for intermediate/cache files. + + output_dir: + Final AutoREACTER output directory for this run. + + images_dir: + Directory where molecule, functional-group, reaction, and template + visualization images are saved. + + monomer_roles: + MonomerRole objects after functional-group classification. + + reaction_instances: + Detected reaction candidates before full reaction preparation. + + non_reactants: + MonomerRole objects selected as non-reactive species. + + reaction_metadata: + Prepared reaction objects. Each ReactionMetadata object stores RDKit + mappings, template atoms, initiators, edge atoms, byproducts, generated + REACTER template files, map files, and activity status. + + ff_files: + Raw force-field and LUNAR output files before REACTER-specific file + organization. + + reacter_files: + Final REACTER file bundle. This should contain run-level files plus the + final monomer and reaction metadata lists used by LAMMPS writers. + + Workflow options + ---------------- + deep_search_enabled: + If True, AutoREACTER performs deeper functional-group/reaction searching + when supported by the detector logic. + + reaction_iteration_depth: + Maximum reaction-progression depth. An integer limits the number of + progression iterations. The string "all" can be used for unlimited or + exhaustive progression if supported downstream. + + use_wildcard_atom_types: + If True, generated templates may use wildcard atom typing behavior where + supported. + + deduplicate_reaction_templates: + If True, duplicate LAMMPS pre/post reaction template pairs are detected + and disabled by setting ReactionMetadata.activity_stats = False. + + write_second_reaction_stage: + If True, AutoREACTER writes the second reaction-stage LAMMPS input files. + If False, only the first-stage reaction input is written. """ + + # Core run configuration inputs: SimulationSetup staging_dir: Path output_dir: Path images_dir: Path - monomer_roles: list["MonomerRole"] = None - reaction_instances: list[ReactionInstance] = None - non_reactants: list["MonomerRole"] = None - reaction_metadata: list[ReactionMetadata] = None # Placeholder for actual ReactionMetadata type + + # Pipeline-generated state + monomer_roles: list["MonomerRole"] = field(default_factory=list) + reaction_instances: list[ReactionInstance] = field(default_factory=list) + non_reactants: list["MonomerRole"] = field(default_factory=list) + reaction_metadata: list[ReactionMetadata] = field(default_factory=list) + + # File bundles generated later in the pipeline ff_files: FFFiles | None = None - reacter_files: REACTERFiles = None # Placeholder for the actual REACTERFiles dataclass + reacter_files: REACTERFiles | None = None + + # Workflow options + deep_search: bool = True + reaction_iteration_depth: int | Literal["all"] = 5 + wildcards: bool = True + deduplicate_reaction_templates: bool = True + write_second_reaction_stage: bool = True def _resolve_input_path(input_file_path: str) -> Path: """ From 9bcf3aeff89773e5a5fc42a41dcd35115e585fcd Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:32:01 -0400 Subject: [PATCH 115/176] Add deep search and iteration depth settings --- AutoREACTER/input_parser.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 27f5ad2a..417c0d19 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -151,6 +151,13 @@ class SimulationSetup: deduplicate_reaction_templates: Enables LAMMPS template deduplication. write_second_reaction_stage: Enables writing the second reaction-stage LAMMPS input files. + deep_search: Enables deeper reaction/functional-group searching. + reaction_iteration_depth: Maximum reaction progression depth. Use an + integer or "all". + wildcards: Enables wildcard handling when supported downstream. + deduplicate_reaction_templates: Enables LAMMPS template deduplication. + write_second_reaction_stage: Enables writing the second reaction-stage + LAMMPS input files. """ simulation_name: str @@ -172,6 +179,11 @@ class SimulationSetup: wildcards: bool = True deduplicate_reaction_templates: bool = True write_second_reaction_stage: bool = True + deep_search: bool = True + reaction_iteration_depth: int | Literal["all"] = 5 + wildcards: bool = True + deduplicate_reaction_templates: bool = True + write_second_reaction_stage: bool = True class InputParser: From c994808e31988e58cd7b0ba01ba9d1f8c9f92bda Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:41:01 -0400 Subject: [PATCH 116/176] Refactor loop/iteration depth validation --- AutoREACTER/input_parser.py | 225 +++++++++++++++++++++++++++++------- 1 file changed, 181 insertions(+), 44 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 417c0d19..0a4df292 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -145,15 +145,9 @@ class SimulationSetup: number_of_total_atoms: Optional list of total atom targets. box_estimates: Optional estimated box size placeholder. deep_search: Enables deeper reaction/functional-group searching. - reaction_iteration_depth: Maximum reaction progression depth. Use an - integer or "all". - wildcards: Enables wildcard handling when supported downstream. - deduplicate_reaction_templates: Enables LAMMPS template deduplication. - write_second_reaction_stage: Enables writing the second reaction-stage - LAMMPS input files. - deep_search: Enables deeper reaction/functional-group searching. - reaction_iteration_depth: Maximum reaction progression depth. Use an - integer or "all". + reaction_iteration_depth: Maximum reaction progression depth. Defaults + to 5 when omitted. A value of 0 disables looping. Values greater + than 0 enable looping for that many iterations. wildcards: Enables wildcard handling when supported downstream. deduplicate_reaction_templates: Enables LAMMPS template deduplication. write_second_reaction_stage: Enables writing the second reaction-stage @@ -175,12 +169,7 @@ class SimulationSetup: number_of_total_atoms: list[int] | None = None box_estimates: float | None = None deep_search: bool = True - reaction_iteration_depth: int | Literal["all"] = 5 - wildcards: bool = True - deduplicate_reaction_templates: bool = True - write_second_reaction_stage: bool = True - deep_search: bool = True - reaction_iteration_depth: int | Literal["all"] = 5 + reaction_iteration_depth: int = 5 wildcards: bool = True deduplicate_reaction_templates: bool = True write_second_reaction_stage: bool = True @@ -232,30 +221,57 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: inputs.get("force_field", None) ) - loop, max_loop_count = self._validate_loop(inputs) + reaction_iteration_depth = self._validate_reaction_iteration_depth( + inputs + ) + loop = reaction_iteration_depth > 0 + max_loop_count = reaction_iteration_depth if loop else None deep_search = self._validate_bool_option( inputs, key="deep_search", default=True, - ) - reaction_iteration_depth = self._validate_reaction_iteration_depth( - inputs + aliases=[ + "deepsearch", + "deep_search", + "deep-search", + "DEEP_SEARCH", + ], ) wildcards = self._validate_bool_option( inputs, key="wildcards", default=True, + aliases=[ + "wildcard", + "wildcards", + "use_wildcards", + "use-wildcards", + ], ) deduplicate_reaction_templates = self._validate_bool_option( inputs, key="deduplicate_reaction_templates", default=True, + aliases=[ + "deduplicate_reaction_templates", + "deduplicate-templates", + "template_deduplication", + "template_dedup", + "dedup_templates", + ], ) write_second_reaction_stage = self._validate_bool_option( inputs, key="write_second_reaction_stage", default=True, + aliases=[ + "write_second_reaction_stage", + "write-second-reaction-stage", + "second_stage", + "write_stage_2", + "stage_2", + ], ) return SimulationSetup( @@ -1003,43 +1019,164 @@ def _validate_simulations( "simulations": simulations, } - def _validate_loop(self, inputs: dict) -> tuple[bool, int | None]: + def _normalized_option_key(self, key: str) -> str: """ - Validate the ``loop`` input. + Normalize workflow option keys so common spellings are accepted. - Returns: - A tuple containing: - - Whether looping is enabled. - - The maximum iteration count, or ``None`` when no limit is specified. + This is intentionally used only for optional workflow switches, not for + the core input schema. + """ + return key.strip().lower().replace("_", "").replace("-", "").replace(" ", "") - Raises: - InputSchemaError: If ``loop`` is not a boolean, a positive integer, - or a supported loop keyword. + def _get_workflow_option( + self, + inputs: dict, + key: str, + default: Any, + aliases: list[str] | None = None, + ) -> Any: + """ + Read an optional workflow setting using a canonical key plus aliases. + + The lookup is case-insensitive and ignores underscores, hyphens, and + spaces. If multiple aliases are provided with conflicting values, the + input is rejected. """ - loop_keywords = {"loop", "repeat", "iterations", "do_loop"} - loop_value = inputs.get("loop", True) + aliases = aliases or [] + accepted_keys = [key, *aliases] + accepted_normalized = { + self._normalized_option_key(option_key) + for option_key in accepted_keys + } - if isinstance(loop_value, bool): - return loop_value, None + matches = [] + for input_key, value in inputs.items(): + if self._normalized_option_key(str(input_key)) in accepted_normalized: + matches.append((input_key, value)) - if isinstance(loop_value, int): - if loop_value <= 0: - raise InputSchemaError("'loop' must be a positive integer.") + if not matches: + return default - logger.info( - "Looping enabled with maximum iterations set to %s", - loop_value, - ) - return True, loop_value + first_value = matches[0][1] + for input_key, value in matches[1:]: + if value != first_value: + raise InputConflictError( + f"Conflicting values were provided for workflow option " + f"'{key}': {matches!r}" + ) + + return first_value + + def _validate_bool_option( + self, + inputs: dict, + key: str, + default: bool, + aliases: list[str] | None = None, + ) -> bool: + """ + Validate an optional boolean workflow switch. + + Only the new workflow options use this relaxed alias/lowercase lookup. + Core schema keys such as simulations and monomers remain strict. + """ + value = self._get_workflow_option( + inputs=inputs, + key=key, + default=default, + aliases=aliases, + ) + + if isinstance(value, bool): + return value - if isinstance(loop_value, str) and loop_value in loop_keywords: - return True, None + if isinstance(value, str): + normalized_value = value.strip().lower() + if normalized_value in {"true", "yes", "y", "on", "1"}: + return True + if normalized_value in {"false", "no", "n", "off", "0"}: + return False raise InputSchemaError( - "'loop' must be a boolean value, a positive integer, " - "or a supported loop keyword." + f"'{key}' must be a boolean value. Got: {value!r}" ) + def _validate_reaction_iteration_depth( + self, + inputs: dict, + ) -> int: + """ + Validate the reaction-iteration depth option. + + Accepted keys include: + - reaction_iteration_depth + - rxn_iteration_depth + - reaction_depth + - loop + - max_loop_count + - iterations + + Accepted values: + - missing key: defaults to 5 + - positive integer: enables looping for that many iterations + - 0: disables looping + - False or false-like strings: disables looping + + Raises: + InputSchemaError: If the value is negative, non-integer, or invalid. + """ + value = self._get_workflow_option( + inputs=inputs, + key="reaction_iteration_depth", + default=5, + aliases=[ + "rxn_iteration_depth", + "reaction_depth", + "iteration_depth", + "max_loop_count", + "max_iterations", + "iterations", + "loop", + ], + ) + + if isinstance(value, bool): + return 5 if value else 0 + + if isinstance(value, str): + normalized_value = value.strip().lower() + + if normalized_value in {"false", "no", "n", "off", "0", "none"}: + return 0 + + if normalized_value in {"true", "yes", "y", "on"}: + return 5 + + try: + value = int(normalized_value) + except ValueError as error: + raise InputSchemaError( + "'reaction_iteration_depth' must be an integer greater " + "than or equal to 0, or a boolean value. " + f"Got: {value!r}" + ) from error + + if isinstance(value, bool) or not isinstance(value, int): + raise InputSchemaError( + "'reaction_iteration_depth' must be an integer greater " + f"than or equal to 0, or a boolean value. Got: {value!r}" + ) + + if value < 0: + raise InputSchemaError( + "'reaction_iteration_depth' must be greater than or equal to 0. " + f"Got: {value!r}" + ) + + return value + + + if __name__ == "__main__": # Sample input data for quick manual verification of the parser. From 6e1a974ec31bce0bddf5b4aa599971eb0c6e4038 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:42:29 -0400 Subject: [PATCH 117/176] Move workflow flags out of Session state --- AutoREACTER/input_parser.py | 10 +++++----- AutoREACTER/session.py | 11 +++-------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 0a4df292..a499ba67 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -168,11 +168,11 @@ class SimulationSetup: ratio: dict[int, float] | None = None number_of_total_atoms: list[int] | None = None box_estimates: float | None = None - deep_search: bool = True - reaction_iteration_depth: int = 5 - wildcards: bool = True - deduplicate_reaction_templates: bool = True - write_second_reaction_stage: bool = True + deep_search: bool = True # yet to implement + reaction_iteration_depth: int = 5 # yet to implement + wildcards: bool = True # yet to implement + deduplicate_reaction_templates: bool = True # yet to implement + write_second_reaction_stage: bool = True # yet to implement class InputParser: diff --git a/AutoREACTER/session.py b/AutoREACTER/session.py index fe9753d7..a5d78849 100644 --- a/AutoREACTER/session.py +++ b/AutoREACTER/session.py @@ -96,8 +96,8 @@ class Session: # Core run configuration inputs: SimulationSetup staging_dir: Path - output_dir: Path - images_dir: Path + output_dir: Path # coustem output dir yet to implement + images_dir: Path # Pipeline-generated state monomer_roles: list["MonomerRole"] = field(default_factory=list) @@ -109,12 +109,7 @@ class Session: ff_files: FFFiles | None = None reacter_files: REACTERFiles | None = None - # Workflow options - deep_search: bool = True - reaction_iteration_depth: int | Literal["all"] = 5 - wildcards: bool = True - deduplicate_reaction_templates: bool = True - write_second_reaction_stage: bool = True + def _resolve_input_path(input_file_path: str) -> Path: """ From e68dcc4cbe3b236c4ae3544c3426e402826443ee Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 16:54:18 -0400 Subject: [PATCH 118/176] Sync session options and output paths --- AutoREACTER/session.py | 96 ++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/AutoREACTER/session.py b/AutoREACTER/session.py index a5d78849..fd3e0bdb 100644 --- a/AutoREACTER/session.py +++ b/AutoREACTER/session.py @@ -17,7 +17,6 @@ from dataclasses import dataclass, field from pathlib import Path -from typing import Literal @dataclass(slots=True) @@ -68,29 +67,6 @@ class Session: reacter_files: Final REACTER file bundle. This should contain run-level files plus the final monomer and reaction metadata lists used by LAMMPS writers. - - Workflow options - ---------------- - deep_search_enabled: - If True, AutoREACTER performs deeper functional-group/reaction searching - when supported by the detector logic. - - reaction_iteration_depth: - Maximum reaction-progression depth. An integer limits the number of - progression iterations. The string "all" can be used for unlimited or - exhaustive progression if supported downstream. - - use_wildcard_atom_types: - If True, generated templates may use wildcard atom typing behavior where - supported. - - deduplicate_reaction_templates: - If True, duplicate LAMMPS pre/post reaction template pairs are detected - and disabled by setting ReactionMetadata.activity_stats = False. - - write_second_reaction_stage: - If True, AutoREACTER writes the second reaction-stage LAMMPS input files. - If False, only the first-stage reaction input is written. """ # Core run configuration @@ -109,6 +85,13 @@ class Session: ff_files: FFFiles | None = None reacter_files: REACTERFiles | None = None + # Workflow options copied from SimulationSetup + deep_search: bool = True + reaction_iteration_depth: int = 5 + wildcards: bool = True + deduplicate_reaction_templates: bool = True + write_second_reaction_stage: bool = True + def _resolve_input_path(input_file_path: str) -> Path: @@ -138,19 +121,44 @@ def _clear_directory(path: Path): elif item.is_dir(): shutil.rmtree(item) -def _normalize_output_dir(raw_output_dir: str, input_path: Path) -> Path: +def _resolve_output_dir( + raw_output_dir: str | None, + input_path: Path, + simulation_name: str, +) -> Path: """ - Normalize output_dir from JSON. + Resolve the final AutoREACTER output directory. + + Behavior: + - If output_dir is missing, None, or empty, use the default location beside + the input JSON: + input_json_folder / AutoREACTER_outputs / simulation_name + + - If output_dir is relative, resolve it relative to the input JSON folder. + + - If output_dir is a Linux/WSL absolute path, use it directly. - Supports: - - Linux/WSL absolute paths: /mnt/c/... - - Windows paths: C:/Users/... - - Relative paths: AutoREACTER_outputs/run_name + - If output_dir is a Windows-style path such as C:/Users/... or C:\\Users\\..., + convert it to the WSL form /mnt/c/Users/.... + + This function returns an absolute path. Directory creation/clearing happens + in read_input(). """ + if raw_output_dir is None or str(raw_output_dir).strip() == "": + return ( + input_path.parent + / "AutoREACTER_outputs" + / simulation_name + ).resolve() + raw_output_dir = str(raw_output_dir).strip() - # Handle Windows-style path when running in WSL/Linux. - if len(raw_output_dir) >= 3 and raw_output_dir[1] == ":" and raw_output_dir[2] in {"/", "\\"}: + # Windows path while running from WSL/Linux. + if ( + len(raw_output_dir) >= 3 + and raw_output_dir[1] == ":" + and raw_output_dir[2] in {"/", "\\"} + ): drive = raw_output_dir[0].lower() rest = raw_output_dir[3:].replace("\\", "/") return Path(f"/mnt/{drive}/{rest}").resolve() @@ -197,12 +205,16 @@ def read_input(input_file_path: str, clear_staging: bool = True) -> Session: raw_output_dir = input_data.get("output_dir", None) - if raw_output_dir is not None: - output_dir = _normalize_output_dir(raw_output_dir, input_path) + output_dir = _resolve_output_dir( + raw_output_dir=raw_output_dir, + input_path=input_path, + simulation_name=sim_name, + ) - else: - # Backward-compatible default behavior. - output_dir = input_path.parent / "AutoREACTER_outputs" / sim_name + if output_dir.exists() and not output_dir.is_dir(): + raise ValueError( + f"Resolved output_dir exists but is not a directory: {output_dir}" + ) if output_dir.exists(): _clear_directory(output_dir) @@ -212,14 +224,6 @@ def read_input(input_file_path: str, clear_staging: bool = True) -> Session: images_dir = output_dir / "images" images_dir.mkdir(parents=True, exist_ok=True) - if output_dir.exists(): - _clear_directory(output_dir) # Only clear this specific run's old files - output_dir.mkdir(parents=True, exist_ok=True) - - # Now create the images folder safely inside the simulation folder - images_dir = Path((output_dir) / "images") - images_dir.mkdir(parents=True, exist_ok=True) - # 6. Return the State Object print(f"[INFO] Initialized AutoREACTER Session") print(f"[INFO] Simulation Name: {validated_inputs.simulation_name}") @@ -231,6 +235,6 @@ def read_input(input_file_path: str, clear_staging: bool = True) -> Session: inputs=validated_inputs, staging_dir=staging_dir, output_dir=output_dir, - images_dir=images_dir + images_dir=images_dir, ) From ecde0c37e7842f2e3c5ce7a41b2de9e194ff03a7 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:10:40 -0400 Subject: [PATCH 119/176] Handle loop depth and add session counters --- AutoREACTER/input_parser.py | 11 ++++++++--- AutoREACTER/session.py | 6 +++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index a499ba67..94094aea 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -159,7 +159,6 @@ class SimulationSetup: density: list[float] force_field: str | None monomers: list[MonomerEntry] - loop : bool = True input_json: dict | None = None max_loop_count: int | None = None simulations: list[Simulation] | None = None @@ -169,6 +168,7 @@ class SimulationSetup: number_of_total_atoms: list[int] | None = None box_estimates: float | None = None deep_search: bool = True # yet to implement + loop : bool = True reaction_iteration_depth: int = 5 # yet to implement wildcards: bool = True # yet to implement deduplicate_reaction_templates: bool = True # yet to implement @@ -224,8 +224,13 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: reaction_iteration_depth = self._validate_reaction_iteration_depth( inputs ) - loop = reaction_iteration_depth > 0 - max_loop_count = reaction_iteration_depth if loop else None + + if reaction_iteration_depth == 0: + loop = False + max_loop_count = None + else: + loop = True + max_loop_count = reaction_iteration_depth deep_search = self._validate_bool_option( inputs, diff --git a/AutoREACTER/session.py b/AutoREACTER/session.py index fd3e0bdb..e1172d5b 100644 --- a/AutoREACTER/session.py +++ b/AutoREACTER/session.py @@ -72,7 +72,7 @@ class Session: # Core run configuration inputs: SimulationSetup staging_dir: Path - output_dir: Path # coustem output dir yet to implement + output_dir: Path images_dir: Path # Pipeline-generated state @@ -85,6 +85,10 @@ class Session: ff_files: FFFiles | None = None reacter_files: REACTERFiles | None = None + # Runtime counters / sub-sessions attached during reaction preparation + reaction_id_counter: int = 0 + reaction_progression_session: object | None = None + # Workflow options copied from SimulationSetup deep_search: bool = True reaction_iteration_depth: int = 5 From ef4f1e781611fd3807d00172871674ddcb2712a3 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:11:03 -0400 Subject: [PATCH 120/176] Refine dedup and progression controls --- .../ff_wrapper/REACTER_files_builder.py | 29 ++++++++++++++++--- .../reaction_processor/prepare_reactions.py | 2 +- .../reaction_progression.py | 19 +++++++----- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index 33360342..26c7f9e9 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -71,6 +71,10 @@ def __init__( ) self.force_field = self.updated_inputs_with_3d_mols.force_field + self.wildcards = self.updated_inputs_with_3d_mols.wildcards + self.deduplicate_reaction_templates = ( + self.updated_inputs_with_3d_mols.deduplicate_reaction_templates + ) def _get_ending_integer(self, s: str) -> int | None: @@ -808,10 +812,27 @@ def molecule_template_preparation(self, session: "Session") -> None: and reaction.post_reaction_file is not None ] - detector = DeduplicationDetector() - active_template_reactions = detector.compare_lammps_templates( - template_files=active_template_reactions, - ) + if self.deduplicate_reaction_templates: + detector = DeduplicationDetector() + active_template_reactions = detector.compare_lammps_templates( + template_files=active_template_reactions, + ) + else: + print("[INFO] Skipping LAMMPS reaction-template deduplication.") + + if self.wildcards: + wildcard_template_reactions = [ + reaction + for reaction in active_template_reactions + if reaction.activity_stats + ] + + detector = DeduplicationDetector() + wildcard_template_reactions = detector.compare_lammps_templates( + template_files=wildcard_template_reactions, + ) + + active_template_reactions = wildcard_template_reactions reacter_files = REACTERFiles( force_field_data=force_field_data, diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 5141c9ec..b4adc959 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -190,7 +190,7 @@ def prepare_reactions(self, session): prepared_reactions = self._prepare_reactions_stage(session) session.reaction_metadata = prepared_reactions - if session.inputs.loop: + if session.inputs.deep_search and session.inputs.loop: progression = ReactionProgression(session, preparer=self) final_reactions = progression.reaction_progression() session.reaction_metadata = final_reactions diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index c6f08822..e0614210 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -147,14 +147,17 @@ def reaction_progression( Prepared and deduplicated reaction metadata accumulated across all iterations. """ - # Respect a user-supplied global loop limit if one was configured. - if self.session.inputs.max_loop_count is not None: - max_loop = self.session.inputs.max_loop_count - print( - f"Overriding default max_loop of {MAX_LOOP} with " - f"user-specified max_loop_count of {max_loop}." - ) - # Avoid sleeping in library code; callers control pacing. + # Respect the validated reaction progression depth from input_parser. + reaction_iteration_depth = self.session.inputs.reaction_iteration_depth + + if reaction_iteration_depth <= 0: + return list(self.session.reaction_metadata) + + max_loop = reaction_iteration_depth + print( + f"Using reaction_iteration_depth={max_loop} for " + "reaction progression." + ) iteration = 0 # Start from the monomer roles already present in the session. From b8571a6f85a1e78ea7cd2f1ee1272215ce287fc4 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:11:55 -0400 Subject: [PATCH 121/176] Update input_parser.py --- AutoREACTER/input_parser.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 94094aea..8baa46ee 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -167,12 +167,12 @@ class SimulationSetup: ratio: dict[int, float] | None = None number_of_total_atoms: list[int] | None = None box_estimates: float | None = None - deep_search: bool = True # yet to implement + deep_search: bool = True loop : bool = True - reaction_iteration_depth: int = 5 # yet to implement - wildcards: bool = True # yet to implement - deduplicate_reaction_templates: bool = True # yet to implement - write_second_reaction_stage: bool = True # yet to implement + reaction_iteration_depth: int = 5 + wildcards: bool = True + deduplicate_reaction_templates: bool = True + write_second_reaction_stage: bool = True class InputParser: From 44243cd437d8d4d3014d02c9d0425225f9d51f6e Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:22:27 -0400 Subject: [PATCH 122/176] Add wildcard-aware LAMMPS deduplication --- .../deduplication_detector.py | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index e9bda978..128f17da 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -172,6 +172,7 @@ def is_duplicate_lammps_template_pair( pre_file_path: str | Path, post_file_path: str | Path, comparison_group: str | None = None, + wildcards: bool = False, ) -> bool: """ Check LAMMPS template duplication using: @@ -211,6 +212,16 @@ def is_duplicate_lammps_template_pair( f"No Equivalences mapping found in {map_file_path}." ) + if wildcards: + pre_graph, post_graph, pre_to_post_mapping = ( + self._apply_lammps_wildcards( + pre_graph=pre_graph, + post_graph=post_graph, + pre_to_post_mapping=pre_to_post_mapping, + map_file_path=map_file_path, + ) + ) + coupled_graph = self._couple_lammps_graphs( pre_graph=pre_graph, post_graph=post_graph, @@ -342,6 +353,110 @@ def _read_lammps_equivalences( return mapping + @staticmethod + def _read_lammps_edge_ids( + map_file_path: str | Path, + ) -> list[int]: + """ + Read pre-template EdgeIDs from a LAMMPS bond/react map file. + """ + map_file_path = Path(map_file_path) + + section_headers = { + "InitiatorIDs", + "EdgeIDs", + "Equivalences", + "DeleteIDs", + } + + current_section: str | None = None + edge_ids: list[int] = [] + + with map_file_path.open("r", encoding="utf-8") as file: + for raw_line in file: + line = raw_line.split("#", maxsplit=1)[0].strip() + + if not line: + continue + + first_token = line.split()[0] + + if line in section_headers: + current_section = line + continue + + if first_token in section_headers: + current_section = first_token + continue + + if current_section != "EdgeIDs": + continue + + try: + edge_ids.append(int(first_token)) + except ValueError: + continue + + return edge_ids + + @staticmethod + def _remove_nodes_if_present( + graph: nx.Graph, + node_ids: list[int], + ) -> nx.Graph: + """ + Return a graph copy with selected nodes removed. + """ + graph_copy = graph.copy() + + graph_copy.remove_nodes_from( + node_id + for node_id in node_ids + if node_id in graph_copy + ) + + return graph_copy + + def _apply_lammps_wildcards( + self, + pre_graph: nx.Graph, + post_graph: nx.Graph, + pre_to_post_mapping: dict[int, int], + map_file_path: Path, + ) -> tuple[nx.Graph, nx.Graph, dict[int, int]]: + """ + Apply wildcard-style template comparison. + + EdgeIDs are defined in pre-template atom ID space. Their equivalent + post-template atom IDs are obtained from the Equivalences section. + These atoms are removed before graph comparison. + """ + pre_edge_ids = self._read_lammps_edge_ids(map_file_path) + + post_edge_ids = [ + pre_to_post_mapping[pre_atom_id] + for pre_atom_id in pre_edge_ids + if pre_atom_id in pre_to_post_mapping + ] + + pre_graph = self._remove_nodes_if_present( + pre_graph, + pre_edge_ids, + ) + post_graph = self._remove_nodes_if_present( + post_graph, + post_edge_ids, + ) + + pre_to_post_mapping = { + pre_atom_id: post_atom_id + for pre_atom_id, post_atom_id in pre_to_post_mapping.items() + if pre_atom_id not in pre_edge_ids + and post_atom_id not in post_edge_ids + } + + return pre_graph, post_graph, pre_to_post_mapping + def _couple_lammps_graphs( self, pre_graph: nx.Graph, @@ -522,6 +637,7 @@ def compare_graphs( pre_file_path=pre_file_path, post_file_path=post_file_path, comparison_group=self.LAMMPS_COMPARISON_GROUP, + wildcards=wildcards, ) results[str(pre_file_path)] = duplicate @@ -747,6 +863,7 @@ def clear_cache( comparison_group, [], ).clear() + # ------------------------------------------------------------------ # RDKit graph conversion @@ -903,6 +1020,7 @@ def lammps_molecule_to_networkx( def compare_lammps_templates( self, template_files: list["ReactionMetadata"], + wildcards: bool = False, ) -> list["ReactionMetadata"]: """ Compare LAMMPS pre/post molecule-template pairs. @@ -953,6 +1071,7 @@ def compare_lammps_templates( pre_file_path=pre_file_path, post_file_path=post_file_path, comparison_group=self.LAMMPS_COMPARISON_GROUP, + wildcards=wildcards, ) if duplicate: From c6a194886d0bed5475ff13fd9036b83a26d6499f Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:18:02 -0400 Subject: [PATCH 123/176] Add wildcard map support for templates --- .../deduplication_detector.py | 381 +++++++++++++++--- .../ff_wrapper/REACTER_files_builder.py | 17 +- examples/DGEBA_MMA_IPN.json | 36 ++ examples/DGEBA_MMA_IPN_homo1.json | 21 + examples/DGEBA_MMA_IPN_homo2.json | 21 + examples/test.json | 22 +- examples/test_epoxy.json | 2 +- examples/test_epoxy_dgeba_dds.json | 25 ++ examples/test_ethelene.json | 23 +- examples/test_styrene.json | 89 +++- 10 files changed, 542 insertions(+), 95 deletions(-) create mode 100644 examples/DGEBA_MMA_IPN.json create mode 100644 examples/DGEBA_MMA_IPN_homo1.json create mode 100644 examples/DGEBA_MMA_IPN_homo2.json create mode 100644 examples/test_epoxy_dgeba_dds.json diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 128f17da..6ee16da8 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -61,6 +61,14 @@ class DeduplicationDetector: "Special Bonds", } + _LAMMPS_MAP_SECTION_HEADERS = { + "InitiatorIDs", + "EdgeIDs", + "Equivalences", + "DeleteIDs", + "Wildcards", + } + def __init__(self) -> None: """Initialize independent graph-comparison caches.""" self.seen_reactions: dict[str, list[nx.Graph]] = { @@ -172,6 +180,7 @@ def is_duplicate_lammps_template_pair( pre_file_path: str | Path, post_file_path: str | Path, comparison_group: str | None = None, + map_file_path: str | Path | None = None, wildcards: bool = False, ) -> bool: """ @@ -182,6 +191,10 @@ def is_duplicate_lammps_template_pair( This ignores coordinates, atom IDs, and bond IDs, but preserves the pre-to-post atom correspondence from the LAMMPS map file. + + When ``wildcards`` is True, the EdgeIDs from the map file are treated + as wildcard atoms. Those pre-template atoms and their equivalent + post-template atoms are removed before graph comparison. """ pre_file_path = Path(pre_file_path) post_file_path = Path(post_file_path) @@ -192,9 +205,12 @@ def is_duplicate_lammps_template_pair( pre_graph = self.lammps_molecule_to_networkx(pre_file_path) post_graph = self.lammps_molecule_to_networkx(post_file_path) - map_file_path = self._lammps_map_path_from_template_path( - pre_file_path - ) + if map_file_path is None: + map_file_path = self._lammps_map_path_from_template_path( + pre_file_path + ) + else: + map_file_path = Path(map_file_path) if not map_file_path.is_file(): return self.is_duplicate_pair( @@ -270,27 +286,37 @@ def _lammps_map_path_from_template_path( ) return file_path.with_name(f"RXN_{reaction_id}.map") - @staticmethod - def _read_lammps_equivalences( - map_file_path: str | Path, - ) -> dict[int, int]: - """ - Read pre-to-post atom equivalences from a LAMMPS bond/react map file. + @classmethod + def _is_lammps_map_section_header(cls, line: str) -> bool: + """Return True if a stripped line starts a map-file section.""" + if not line: + return False - Returns: - {pre_atom_id: post_atom_id} - """ - map_file_path = Path(map_file_path) + first_token = line.split()[0] + return ( + line in cls._LAMMPS_MAP_SECTION_HEADERS + or first_token in cls._LAMMPS_MAP_SECTION_HEADERS + ) - section_headers = { - "InitiatorIDs", - "EdgeIDs", - "Equivalences", - "DeleteIDs", - } + @staticmethod + def _is_lammps_count_line(line: str) -> bool: + """Return True for count lines such as '11 edgeIDs'.""" + return re.match( + r"^\s*\d+\s+(?:edgeIDs|equivalences|wildcards)\s*$", + line, + flags=re.IGNORECASE, + ) is not None + @classmethod + def _read_lammps_map_integer_section( + cls, + map_file_path: str | Path, + section_name: str, + ) -> list[list[int]]: + """Read integer rows from a LAMMPS bond/react map-file section.""" + map_file_path = Path(map_file_path) current_section: str | None = None - mapping: dict[int, int] = {} + rows: list[list[int]] = [] with map_file_path.open("r", encoding="utf-8") as file: for raw_line in file: @@ -299,41 +325,56 @@ def _read_lammps_equivalences( if not line: continue - if line in section_headers: - current_section = line - continue - first_token = line.split()[0] - if first_token in section_headers: + if cls._is_lammps_map_section_header(line): current_section = first_token continue - if current_section != "Equivalences": - continue - - parts = line.split() - - if len(parts) < 2: + if current_section != section_name: continue try: - pre_atom_id = int(parts[0]) - post_atom_id = int(parts[1]) + rows.append([int(part) for part in line.split()]) except ValueError: continue - if ( - pre_atom_id in mapping - and mapping[pre_atom_id] != post_atom_id - ): - raise ValueError( - f"Conflicting Equivalences entry in " - f"{map_file_path}: pre atom {pre_atom_id} maps to " - f"both {mapping[pre_atom_id]} and {post_atom_id}." - ) + return rows - mapping[pre_atom_id] = post_atom_id + @classmethod + def _read_lammps_equivalences( + cls, + map_file_path: str | Path, + ) -> dict[int, int]: + """ + Read pre-to-post atom equivalences from a LAMMPS bond/react map file. + + Returns: + {pre_atom_id: post_atom_id} + """ + mapping: dict[int, int] = {} + + for row in cls._read_lammps_map_integer_section( + map_file_path, + "Equivalences", + ): + if len(row) < 2: + continue + + pre_atom_id = row[0] + post_atom_id = row[1] + + if ( + pre_atom_id in mapping + and mapping[pre_atom_id] != post_atom_id + ): + raise ValueError( + f"Conflicting Equivalences entry in " + f"{map_file_path}: pre atom {pre_atom_id} maps to " + f"both {mapping[pre_atom_id]} and {post_atom_id}." + ) + + mapping[pre_atom_id] = post_atom_id post_to_pre: dict[int, int] = {} @@ -353,12 +394,110 @@ def _read_lammps_equivalences( return mapping - @staticmethod + @classmethod def _read_lammps_edge_ids( + cls, + map_file_path: str | Path, + ) -> list[int]: + """Read pre-template EdgeIDs from a LAMMPS bond/react map file.""" + edge_ids: list[int] = [] + + for row in cls._read_lammps_map_integer_section( + map_file_path, + "EdgeIDs", + ): + if not row: + continue + + edge_ids.append(row[0]) + + return edge_ids + + @staticmethod + def _remove_lammps_map_section( + lines: list[str], + section_name: str, + ) -> list[str]: + """Remove a named map-file section and its body.""" + section_headers = { + "InitiatorIDs", + "EdgeIDs", + "Equivalences", + "DeleteIDs", + "Wildcards", + } + + output: list[str] = [] + inside_target = False + + for line in lines: + stripped = line.strip() + first_token = stripped.split()[0] if stripped else "" + + is_header = ( + stripped in section_headers + or first_token in section_headers + ) + + if is_header and first_token == section_name: + inside_target = True + continue + + if inside_target and is_header: + inside_target = False + + if not inside_target: + output.append(line) + + return output + + def _replace_lammps_count_lines( + self, + lines: list[str], + edge_count: int, + equivalence_count: int, + wildcard_count: int, + ) -> list[str]: + """ + Replace the map-file count block. + + The final order is: + N edgeIDs + N equivalences + N wildcards + """ + filtered_lines = [ + line + for line in lines + if not self._is_lammps_count_line(line.strip()) + ] + + insert_idx = 0 + for idx, line in enumerate(filtered_lines): + if line.strip().startswith("#") or not line.strip(): + insert_idx = idx + 1 + continue + break + + count_lines = [ + f"{edge_count} edgeIDs\n", + f"{equivalence_count} equivalences\n", + f"{wildcard_count} wildcards\n", + ] + + return ( + filtered_lines[:insert_idx] + + count_lines + + filtered_lines[insert_idx:] + ) + + @staticmethod + def _read_lammps_single_column_section( map_file_path: str | Path, + section_name: str, ) -> list[int]: """ - Read pre-template EdgeIDs from a LAMMPS bond/react map file. + Read a single-column integer section from a LAMMPS bond/react map file. """ map_file_path = Path(map_file_path) @@ -367,10 +506,11 @@ def _read_lammps_edge_ids( "EdgeIDs", "Equivalences", "DeleteIDs", + "Wildcards", } current_section: str | None = None - edge_ids: list[int] = [] + values: list[int] = [] with map_file_path.open("r", encoding="utf-8") as file: for raw_line in file: @@ -389,24 +529,125 @@ def _read_lammps_edge_ids( current_section = first_token continue - if current_section != "EdgeIDs": + if current_section != section_name: continue try: - edge_ids.append(int(first_token)) + values.append(int(first_token)) except ValueError: continue - return edge_ids + return values + + def _write_lammps_wildcard_map_file( + self, + map_file_path: str | Path, + wildcard_ids: list[int], + ) -> None: + """ + Replace the original RXN_*.map with a wildcard-enabled map. + + The map path is unchanged. The Wildcards section is written from the + pre-template EdgeIDs. + """ + map_file_path = Path(map_file_path) + + # Preserve input order while removing repeated IDs. + seen_wildcards: set[int] = set() + wildcard_ids = [ + atom_id + for atom_id in wildcard_ids + if not ( + atom_id in seen_wildcards + or seen_wildcards.add(atom_id) + ) + ] + + original_lines = map_file_path.read_text( + encoding="utf-8", + ).splitlines() + + header_lines: list[str] = [] + + for line in original_lines: + stripped = line.strip() + + if not stripped: + continue + + if stripped.startswith("#"): + header_lines.append(stripped) + continue + + break + + initiator_ids = self._read_lammps_single_column_section( + map_file_path, + "InitiatorIDs", + ) + edge_ids = self._read_lammps_edge_ids(map_file_path) + equivalences = self._read_lammps_equivalences(map_file_path) + delete_ids = self._read_lammps_single_column_section( + map_file_path, + "DeleteIDs", + ) + + lines: list[str] = [] + + for header_line in header_lines: + lines.append(f"{header_line}\n") + + lines.append("\n") + lines.append(f"{len(edge_ids)} edgeIDs\n") + lines.append(f"{len(equivalences)} equivalences\n") + + if delete_ids: + lines.append(f"{len(delete_ids)} deleteIDs\n") + + lines.append(f"{len(wildcard_ids)} wildcards\n") + lines.append("\n") + + lines.append("InitiatorIDs\n") + lines.append("\n") + for atom_id in initiator_ids: + lines.append(f"{atom_id}\n") + lines.append("\n") + + lines.append("EdgeIDs\n") + lines.append("\n") + for atom_id in edge_ids: + lines.append(f"{atom_id}\n") + lines.append("\n") + + lines.append("Equivalences\n") + lines.append("\n") + for pre_atom_id, post_atom_id in equivalences.items(): + lines.append(f"{pre_atom_id:<5} {post_atom_id}\n") + lines.append("\n") + + if delete_ids: + lines.append("DeleteIDs\n") + lines.append("\n") + for atom_id in delete_ids: + lines.append(f"{atom_id}\n") + lines.append("\n") + + lines.append("Wildcards\n") + lines.append("\n") + for atom_id in wildcard_ids: + lines.append(f"{atom_id}\n") + + map_file_path.write_text( + "".join(lines), + encoding="utf-8", + ) @staticmethod def _remove_nodes_if_present( graph: nx.Graph, node_ids: list[int], ) -> nx.Graph: - """ - Return a graph copy with selected nodes removed. - """ + """Return a graph copy with selected nodes removed.""" graph_copy = graph.copy() graph_copy.remove_nodes_from( @@ -448,11 +689,14 @@ def _apply_lammps_wildcards( post_edge_ids, ) + pre_edge_id_set = set(pre_edge_ids) + post_edge_id_set = set(post_edge_ids) + pre_to_post_mapping = { pre_atom_id: post_atom_id for pre_atom_id, post_atom_id in pre_to_post_mapping.items() - if pre_atom_id not in pre_edge_ids - and post_atom_id not in post_edge_ids + if pre_atom_id not in pre_edge_id_set + and post_atom_id not in post_edge_id_set } return pre_graph, post_graph, pre_to_post_mapping @@ -602,6 +846,7 @@ def is_duplicate_pair( def compare_graphs( self, molecule_file_paths: list[str | Path], + wildcards: bool = False, ) -> dict[str, bool]: """ Compare LAMMPS pre/post molecule-template pairs. @@ -863,7 +1108,6 @@ def clear_cache( comparison_group, [], ).clear() - # ------------------------------------------------------------------ # RDKit graph conversion @@ -1067,18 +1311,41 @@ def compare_lammps_templates( template.activity_stats = False continue + map_file_value = getattr(template, "map_file", None) + map_file_path = ( + Path(map_file_value) + if map_file_value is not None + else self._lammps_map_path_from_template_path( + pre_file_path + ) + ) + duplicate = self.is_duplicate_lammps_template_pair( pre_file_path=pre_file_path, post_file_path=post_file_path, comparison_group=self.LAMMPS_COMPARISON_GROUP, + map_file_path=map_file_path, wildcards=wildcards, ) if duplicate: template.activity_stats = False - print(f"Duplicate template disabled: RXN_{template.reaction_id}") + print( + f"Duplicate template disabled: " + f"RXN_{template.reaction_id}" + ) continue + if wildcards and map_file_path.is_file(): + wildcard_ids = self._read_lammps_edge_ids(map_file_path) + + self._write_lammps_wildcard_map_file( + map_file_path=map_file_path, + wildcard_ids=wildcard_ids, + ) + + template.map_file = map_file_path + template.activity_stats = True unique_templates.append(template) @@ -1508,4 +1775,4 @@ def _main() -> None: if __name__ == "__main__": - _main() \ No newline at end of file + _main() diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index 26c7f9e9..f30f0b3b 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -389,7 +389,7 @@ def _map_file_write(self, reactant_to_product, initiator_atoms, edge_atoms, dele current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 2. Build the custom header - map_file = f"# This nominal superimpose file for the {self.force_field} forcefield was generated on {current_time} for {file_name}.\n\n" + map_file = f"# This nominal superimpose file for the {self.force_field} forcefield was generated on {current_time} for {file_name} by AutoREACTER.\n\n" # Write counts map_file += f"{len(edge_atoms)} edgeIDs\n" @@ -816,24 +816,11 @@ def molecule_template_preparation(self, session: "Session") -> None: detector = DeduplicationDetector() active_template_reactions = detector.compare_lammps_templates( template_files=active_template_reactions, + wildcards=self.wildcards, ) else: print("[INFO] Skipping LAMMPS reaction-template deduplication.") - if self.wildcards: - wildcard_template_reactions = [ - reaction - for reaction in active_template_reactions - if reaction.activity_stats - ] - - detector = DeduplicationDetector() - wildcard_template_reactions = detector.compare_lammps_templates( - template_files=wildcard_template_reactions, - ) - - active_template_reactions = wildcard_template_reactions - reacter_files = REACTERFiles( force_field_data=force_field_data, in_file=in_file, diff --git a/examples/DGEBA_MMA_IPN.json b/examples/DGEBA_MMA_IPN.json new file mode 100644 index 00000000..6379ff0b --- /dev/null +++ b/examples/DGEBA_MMA_IPN.json @@ -0,0 +1,36 @@ +{ + "simulation_name": "DGEBA_MMA_ED900_TEGDMA_IPN_500K_100k", + "force_field": "PCFF", + "simulations": [ + { + "tag": "ipn_100k_500K", + "temperature": 500.0, + "density": 1.23, + "total_atoms": 100000, + "monomer_ratios": { + "dgeba": 2.0, + "jeffamine_ed900_rep": 1.0, + "mma": 14.0, + "tegdma": 0.7 + } + } + ], + "monomers": [ + { + "name": "dgeba", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c3ccc(OCC4CO4)cc3" + }, + { + "name": "jeffamine_ed900_rep", + "smiles": "CC(N)COCC(C)OCC(C)OCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCC(C)OCC(C)OCC(C)N" + }, + { + "name": "mma", + "smiles": "COC(=O)C(C)=C" + }, + { + "name": "tegdma", + "smiles": "CC(=C)C(=O)OCCOCCOCCOC(=O)C(=C)C" + } + ] +} \ No newline at end of file diff --git a/examples/DGEBA_MMA_IPN_homo1.json b/examples/DGEBA_MMA_IPN_homo1.json new file mode 100644 index 00000000..5ae41c55 --- /dev/null +++ b/examples/DGEBA_MMA_IPN_homo1.json @@ -0,0 +1,21 @@ +{ + "simulation_name": "DGEBA_MMA_ED900_TEGDMA_IPN_homo1", + "force_field": "PCFF", + "simulations": [ + { + "tag": "ipn_10k_298K", + "temperature": 298.15, + "density": 1.23, + "total_atoms": 10000, + "monomer_ratios": { + "tegdma": 0.7 + } + } + ], + "monomers": [ + { + "name": "tegdma", + "smiles": "CC(=C)C(=O)OCCOCCOCCOC(=O)C(=C)C" + } + ] +} diff --git a/examples/DGEBA_MMA_IPN_homo2.json b/examples/DGEBA_MMA_IPN_homo2.json new file mode 100644 index 00000000..f395ecd9 --- /dev/null +++ b/examples/DGEBA_MMA_IPN_homo2.json @@ -0,0 +1,21 @@ +{ + "simulation_name": "DGEBA_MMA_ED900_TEGDMA_IPN_homo2", + "force_field": "PCFF", + "simulations": [ + { + "tag": "ipn_10k_298K", + "temperature": 298.15, + "density": 1.23, + "total_atoms": 10000, + "monomer_ratios": { + "mma": 14.0 + } + } + ], + "monomers": [ + { + "name": "mma", + "smiles": "COC(=O)C(C)=C" + } + ] +} diff --git a/examples/test.json b/examples/test.json index 54e6bd19..f87de57e 100644 --- a/examples/test.json +++ b/examples/test.json @@ -1,19 +1,25 @@ { - "simulation_name": "TFE_Test", + "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", "simulations": [ { - "tag": "tfe_test", + "tag": "epoxy_test", "temperature": 300, - "density": 1.5, - "monomer_counts": { - "tetrafluoroethylene": 200 + "density": 0.5, + "total_atoms": 25000, + "monomer_ratios": { + "dgeba_epoxy": 2.0, + "DDS_diamine": 1.0 } } ], "monomers": [ { - "name": "tetrafluoroethylene", - "smiles": "C(=C(F)F)(F)F" + "name": "dgeba_epoxy", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" + }, + { + "name": "DDS_diamine", + "smiles": "Nc1ccc(S(=O)(=O)c2ccc(N)cc2)cc1" } ] -} +} \ No newline at end of file diff --git a/examples/test_epoxy.json b/examples/test_epoxy.json index 5558925c..0b2eea70 100644 --- a/examples/test_epoxy.json +++ b/examples/test_epoxy.json @@ -14,7 +14,7 @@ "monomers": [ { "name": "di_epoxy", - "smiles": "C1OC1COCCOCC1CO1" + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" }, { "name": "primary_diamine", diff --git a/examples/test_epoxy_dgeba_dds.json b/examples/test_epoxy_dgeba_dds.json new file mode 100644 index 00000000..240163f3 --- /dev/null +++ b/examples/test_epoxy_dgeba_dds.json @@ -0,0 +1,25 @@ +{ + "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "simulations": [ + { + "tag": "epoxy_test", + "temperature": 300, + "density": 0.5, + "total_atoms": 25000, + "monomer_ratios": { + "dgeba_epoxy": 2.0, + "DDS_diamine": 1.0 + } + } + ], + "monomers": [ + { + "name": "dgeba_epoxy", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" + }, + { + "name": "DDS_diamine", + "smiles": "[S](=O)(=O)(c2ccc(cc2)N)c1ccc(cc1)N" + } + ] +} diff --git a/examples/test_ethelene.json b/examples/test_ethelene.json index 622948a7..0325cce0 100644 --- a/examples/test_ethelene.json +++ b/examples/test_ethelene.json @@ -1,20 +1,31 @@ { - "simulation_name": "Ethene_Test", + "simulation_name": "Styrene", "loop": 9, + "force_field": "PCFF", "simulations": [ { - "tag": "vinyl_test", + "tag": "styrene_10k", "temperature": 300, "density": 1.0, - "monomer_counts": { - "ethene": 200 + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + } + }, + { + "tag": "styrene_100k", + "temperature": 300, + "density": 1.0, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 } } ], "monomers": [ { - "name": "ethene", - "smiles": "C=C" + "name": "styrene", + "smiles": "C=Cc1ccccc1" } ] } \ No newline at end of file diff --git a/examples/test_styrene.json b/examples/test_styrene.json index 6cdcfb75..b14e0fc6 100644 --- a/examples/test_styrene.json +++ b/examples/test_styrene.json @@ -1,19 +1,92 @@ { - "simulation_name": "Styrene_Test", + "simulation_name": "Styrene2", + "force_field": "PCFF", "simulations": [ { - "tag": "vinyl_test", - "temperature": 300, - "density": 1.0, - "monomer_counts": { - "styrene": 2000 - } + "tag": "styrene_10k_298K", + "temperature": 298.15, + "density": 1.05, + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Room-temperature reference system. The 10k system is intended for rapid testing, workflow validation, and establishing baseline structural and reaction behavior at ambient conditions." + }, + { + "tag": "styrene_100k_298K", + "temperature": 298.15, + "density": 1.05, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Large room-temperature reference system. It is used to evaluate finite-size effects and obtain more statistically representative structural and reaction data than the 10k system." + }, + { + "tag": "styrene_10k_373K", + "temperature": 373.15, + "density": 1.05, + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Approximately 100 degrees Celsius. This small system probes accelerated polymerization behavior near a temperature where uncontrolled self-heating and runaway risks may become important, depending on initiators, inhibitors, and heat removal." + }, + { + "tag": "styrene_100k_373K", + "temperature": 373.15, + "density": 1.05, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Large system at approximately 100 degrees Celsius. It is included to examine system-size effects, heat-sensitive reaction behavior, and network development near the upper region of common styrene polymerization temperatures." + }, + { + "tag": "styrene_10k_523K", + "temperature": 523.15, + "density": 1.05, + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Approximately 250 degrees Celsius. This system probes the transition toward strong thermal initiation, radical formation, oligomerization, and possible thermal degradation rather than normal controlled polystyrene production." + }, + { + "tag": "styrene_100k_523K", + "temperature": 523.15, + "density": 1.05, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Large system at approximately 250 degrees Celsius. It is intended to capture larger-scale thermal decomposition, branching, fragmentation, and spatially heterogeneous reaction behavior." + }, + { + "tag": "styrene_10k_800K", + "temperature": 800.0, + "density": 1.05, + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "High-temperature screening system at 800 K, equivalent to approximately 526.85 degrees Celsius. It probes extreme thermal chemistry and decomposition behavior and is not a conventional styrene polymerization condition." + }, + { + "tag": "styrene_100k_800K", + "temperature": 800.0, + "density": 1.05, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Large high-temperature system at 800 K. It is used to investigate finite-size effects and statistically significant reaction pathways under extreme thermal conditions." } ], "monomers": [ { "name": "styrene", - "smiles": "c1ccccc1C=C" + "smiles": "C=Cc1ccccc1" } ] } \ No newline at end of file From bdf188c96404bd157236c0420c584b87d3b8f009 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:38:20 -0400 Subject: [PATCH 124/176] Skip second reaction stage when disabled --- .../sim_setup/writers/post_eq_writer.py | 29 +++++++++++++++---- AutoREACTER/sim_setup/writers/writer.py | 20 ++++++++----- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/AutoREACTER/sim_setup/writers/post_eq_writer.py b/AutoREACTER/sim_setup/writers/post_eq_writer.py index ea68f4e7..e77cf74c 100644 --- a/AutoREACTER/sim_setup/writers/post_eq_writer.py +++ b/AutoREACTER/sim_setup/writers/post_eq_writer.py @@ -31,7 +31,14 @@ class PostEqWriter: sim_name (str): Base simulation name used in file naming. """ - def __init__(self, out_dir: Path, settings: LammpsSettings, simulation: Simulation, sim_name: str): + def __init__( + self, + out_dir: Path, + settings: LammpsSettings, + simulation: Simulation, + sim_name: str, + write_second_reaction_stage: bool = True, + ): """ Initialize the writer and generate the post-equilibration input script. @@ -46,9 +53,16 @@ def __init__(self, out_dir: Path, settings: LammpsSettings, simulation: Simulati self.sim_name = sim_name # Write the post-equilibration file immediately during construction. - self.write_post_eq_file(simulation=simulation) - - def write_post_eq_file(self, simulation: Simulation) -> str: + self.write_post_eq_file( + simulation=simulation, + write_second_reaction_stage=write_second_reaction_stage, + ) + + def write_post_eq_file( + self, + simulation: Simulation, + write_second_reaction_stage: bool = True, + ) -> str: """ Create the LAMMPS input script for the post-equilibration stage. @@ -74,8 +88,11 @@ def write_post_eq_file(self, simulation: Simulation) -> str: s = self.settings - # Input is the reacted structure produced by the second reaction stage. - input_data = f"{tag}_reacted_1M-3.5_5.0A.data" + # Input is the reacted structure produced by the final reaction stage. + if write_second_reaction_stage: + input_data = f"{tag}_reacted_1M-3.5_5.0A.data" + else: + input_data = f"{tag}_reacted_0M-1M_3.5A.data" # Output files written after equilibration completes. output_xyz = f"{tag}_post_equilibration.xyz" diff --git a/AutoREACTER/sim_setup/writers/writer.py b/AutoREACTER/sim_setup/writers/writer.py index 7e155bad..42716277 100644 --- a/AutoREACTER/sim_setup/writers/writer.py +++ b/AutoREACTER/sim_setup/writers/writer.py @@ -50,18 +50,22 @@ def write_all_files(self, run_dir: Path, simulation_setup: SimulationSetup) -> N ) - RxnSecondStageWriter( - out_dir=sub_dir, - settings=self.settings, - reacter_files=self.reacter_files, - simulation=simulation, - sim_name=sim_name - ) + if simulation_setup.write_second_reaction_stage: + RxnSecondStageWriter( + out_dir=sub_dir, + settings=self.settings, + reacter_files=self.reacter_files, + simulation=simulation, + sim_name=sim_name + ) PostEqWriter( out_dir=sub_dir, settings=self.settings, simulation=simulation, - sim_name=sim_name + sim_name=sim_name, + write_second_reaction_stage=( + simulation_setup.write_second_reaction_stage + ) ) \ No newline at end of file From cf6822d24a72c2995bd1ee736fa8b6a42dfb1833 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:40:54 -0400 Subject: [PATCH 125/176] Refine second-stage LAMMPS script generation --- .../writers/rxn_second_stage_writer.py | 212 +++++++++++------- 1 file changed, 125 insertions(+), 87 deletions(-) diff --git a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py index 93732a72..9c7166bc 100644 --- a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py @@ -10,10 +10,12 @@ import shutil from pathlib import Path from datetime import datetime + from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import REACTERFiles from AutoREACTER.sim_setup.writers.lammps_settings import LammpsSettings from AutoREACTER.input_parser import Simulation + # Generate current date string for file headers and timestamping now = datetime.now().strftime("%Y-%m-%d") @@ -21,67 +23,90 @@ class RxnSecondStageWriter: """ Generates LAMMPS input scripts for second-stage reaction simulations. - + This class creates a complete LAMMPS input script for the second reaction stage, configures inter-molecular reaction parameters, and manages the copying of required reaction template files to the output directory. - + Attributes: - settings (LammpsSettings): LAMMPS simulation settings and parameters - out_dir (Path): Output directory for generated files - sim_name (str): Base name for the simulation - reacter_files (REACTERFiles): Container for reaction template files - second_stage_file_name (str): Name of the generated second-stage input file + settings (LammpsSettings): LAMMPS simulation settings and parameters. + out_dir (Path): Output directory for generated files. + sim_name (str): Base name for the simulation. + reacter_files (REACTERFiles): Container for reaction template files. + second_stage_file_name (str): Name of the generated second-stage input file. """ - def __init__(self, out_dir: Path, settings: LammpsSettings, reacter_files: REACTERFiles, simulation: Simulation, sim_name: str): + def __init__( + self, + out_dir: Path, + settings: LammpsSettings, + reacter_files: REACTERFiles, + simulation: Simulation, + sim_name: str, + ): """ Initialize the RxnSecondStageWriter and generate second-stage reaction files. - + Args: - out_dir (Path): Root output directory for simulation files - settings (LammpsSettings): LAMMPS simulation settings and force field parameters - reacter_files (REACTERFiles): Container with reaction template and molecule files - simulation (Simulation): Simulation configuration with temperature and tag information - sim_name (str): Base simulation name used for file naming + out_dir (Path): Root output directory for simulation files. + settings (LammpsSettings): LAMMPS simulation settings and force field parameters. + reacter_files (REACTERFiles): Container with reaction template and molecule files. + simulation (Simulation): Simulation configuration with temperature and tag information. + sim_name (str): Base simulation name used for file naming. """ self.settings = settings self.out_dir = out_dir self.sim_name = sim_name self.reacter_files = reacter_files - # Generate and store the second-stage input file name - self.second_stage_file_name = self.write_second_stage_reaction_files(simulation=simulation) + + # Generate and store the second-stage input file name. + self.second_stage_file_name = self.write_second_stage_reaction_files( + simulation=simulation, + ) def write_second_stage_reaction_files(self, simulation: Simulation) -> str: """ Generate LAMMPS input script for second-stage inter-molecular reactions. - + Creates a complete LAMMPS input file with reaction definitions, simulation parameters, and thermal dynamics settings. This stage simulates reactions - between molecules at medium intermolecular distances (1M-3.5 Angstroms). - + between molecules at medium intermolecular distances. + Args: - simulation (Simulation): Simulation configuration containing temperature and unique tag - + simulation (Simulation): Simulation configuration containing temperature and unique tag. + Returns: - str: Filename of the generated second-stage input script - + str: Filename of the generated second-stage input script. + Raises: - FileNotFoundError: If required reaction template files are missing + FileNotFoundError: If required reaction template files are missing. + ValueError: If no active reaction templates are available. """ tag = f"{self.sim_name}_{simulation.tag}" rxn_dir = self.out_dir / "4_reaction_second_stage" rxn_dir.mkdir(parents=True, exist_ok=True) - - # Reference commonly used objects for cleaner code + + # Reference commonly used objects for cleaner code. s = self.settings rf = self.reacter_files + now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - # Define input and output data file names + # Define input and output data file names. input_data = f"{tag}_reacted_0M-1M_3.5A.data" output_base = f"{tag}_reacted_1M-3.5_5.0A" - - # Build LAMMPS script header and core simulation parameters + + active_templates = [ + template + for template in rf.template_files + if getattr(template, "activity_stats", True) + ] + + if not active_templates: + raise ValueError( + "No active reaction templates available for the second reaction stage." + ) + + # ----- Header / Initialization --------------------------------- lines = [ f"# {tag} Second Reaction Stage Script - Generated {now} by AutoREACTER\n", "#------------Initialization------------", @@ -90,106 +115,116 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: f"{'boundary':<16} {s.boundary}", f"{'atom_style':<16} {s.atom_style}", "", - # Force field style definitions - "#------------Force Field Styles------------", + "# ------------Force Field Styles------------", f"{'angle_style':<16} {s.angle_style}", f"{'bond_style':<16} {s.bond_style}", f"{'dihedral_style':<16} {s.dihedral_style}", f"{'improper_style':<16} {s.improper_style}", "", - # Pair and electrostatic interaction styles f"{'pair_style':<16} {s.pair_style}", f"{'kspace_style':<16} {s.kspace_style}", - f"{'pair_modify':<16} {s.pair_modify}" + f"{'pair_modify':<16} {s.pair_modify}", ] - - # Add optional neighbor list settings if specified + + # Add optional neighbor list settings if specified. if s.neighbor: lines.append(f"{'neighbor':<16} {s.neighbor}") if s.neigh_modify: lines.append(f"{'neigh_modify':<16} {s.neigh_modify}") - # Define data file reading with extra bonding capacity for reactions + # ----- Read first-stage reacted structure ----------------------- lines.extend([ "", - "#------------Read First Stage reacted Box------------", - f"{'read_data':<16} \"{input_data}\" &", + "#------------Read First Stage Reacted Box------------", + f"{'read_data':<16} {input_data} &", f"{'':<16} extra/bond/per/atom 50 &", f"{'':<16} extra/angle/per/atom 50 &", f"{'':<16} extra/dihedral/per/atom 50 &", f"{'':<16} extra/improper/per/atom 50 &", f"{'':<16} extra/special/per/atom 50", "", - # Initial energy minimization and simulation setup - "#------------Minimization and Velocity Initialization------------", + "#------------Minimization and Velocity------------", f"{'minimize':<16} 1.0e-4 1.0e-6 1000 10000", - f"{'velocity':<16} all create {simulation.temperature} {random.randint(10000, 9999999)} loop geom", + f"{'velocity':<16} all create {simulation.temperature} {random.randint(10_000, 9_999_999)} dist gaussian", f"{'timestep':<16} 1.0", f"{'thermo':<16} 100", f"{'reset_timestep':<16} 1000000", - "" + "", ]) - # Define reaction templates and build reaction fix commands + # ----- Reaction templates & fix bond/react --------------------- lines.append("#------------Define Reaction Templates------------") - rxn_commands = [] - for template in [ - t for t in rf.template_files - if getattr(t, "activity_stats", True) - ]: - i = template.reaction_id - # Create unique identifiers for pre- and post-reaction molecule templates - pre_id = f"mol_pre_{i}" - post_id = f"mol_post_{i}" - - # Extract molecule and mapping file names from template objects + rxn_commands: list[str] = [] + + for template in active_templates: + reaction_id = template.reaction_id + + # Create unique identifiers for pre- and post-reaction molecule templates. + pre_id = f"mol_pre_{reaction_id}" + post_id = f"mol_post_{reaction_id}" + + # Extract molecule and mapping file names from template objects. pre_file = template.pre_reaction_file.name post_file = template.post_reaction_file.name map_file = template.map_file.name - - # Register molecule templates in LAMMPS - lines.append(f"{'molecule':<16} {pre_id} {pre_file}") - lines.append(f"{'molecule':<16} {post_id} {post_file}") - - # Build reaction command with cutoff at 5.0 Angstroms for inter-molecular reactions - # stabilize_steps: equilibration steps after reaction to prevent explosion - rxn_str = f"react rxn_stp_{i} all 1 0.0 5.0 {pre_id} {post_id} {map_file} stabilize_steps 200 rescale_charges yes" + + # Register molecule templates in LAMMPS. + lines.append(f"{'molecule':<16} {pre_id:<16} {pre_file}") + lines.append(f"{'molecule':<16} {post_id:<16} {post_file}\n") + + # Build reaction command with cutoff at 5.0 Angstroms for inter-molecular reactions. + # stabilize_steps: equilibration steps after reaction to prevent explosion. + rxn_stp = f"rxn_stp_{reaction_id}" + rxn_str = ( + f"react " + f"{rxn_stp:<15} " + f"all 1 0.0 5.0 " + f"{pre_id:<14} " + f"{post_id:<15} " + f"{map_file:<15} " + f"stabilize_steps 200 rescale_charges yes" + ) rxn_commands.append(rxn_str) - # Combine all reaction commands with line continuation + # Combine all reaction commands with line continuation. all_reactions = " & \n ".join(rxn_commands) - - # Configure bond/react fix with stabilization groups and define fixes for simulation + + # Use explicit f_rxns[i] fields because some LAMMPS builds do not accept f_rxns[*]. + rxn_thermo_values = " ".join( + f"f_rxns[{position}]" + for position in range(1, len(rxn_commands) + 1) + ) + + # Configure bond/react fix with stabilization groups and define fixes for simulation. lines.extend([ "", f"{'fix':<16} rxns all bond/react stabilization yes statted_grp 0.03 &", f"{'':<16} {all_reactions}", "", + "", "# Note: If atoms are being deleted during the reaction, ensure you use the correct Map file", - "# (e.g., RXN_i_with_delete_ids.map). ", + "# (e.g., RXN_i_with_delete_ids.map).", "# NPT is recommended for deletion to account for density changes.\n", - # NVT thermostat for stabilized group (uncomment NPT if density changes expected) - f"{'fix':<16} 1 statted_grp_REACT nvt temp {simulation.temperature} {simulation.temperature} 100.0\n", + f"{'fix':<16} 1 statted_grp_REACT nvt temp {simulation.temperature} {simulation.temperature} 100.0\n", f"#{'fix':<16} 1 statted_grp_REACT npt temp {simulation.temperature} {simulation.temperature} 100.0 iso 0.0 0.0 1000.0", "", - # Output configuration - f"{'thermo_style':<16} custom step time temp f_rxns[*] press density vol pe ke etotal", + "#------------Output and Run------------", + f"{'thermo_style':<16} custom step time temp {rxn_thermo_values} press density vol pe ke etotal", f"{'dump':<16} traj all xyz 1000 {output_base}.xyz", f"{'dump_modify':<16} traj types labels", "", - # Run simulation for 2.5 million timesteps and save periodic backups f"{'run':<16} 2500000", f"{'restart':<16} 100 {output_base}_backup1.restart {output_base}_backup2.restart", f"{'write_restart':<16} {output_base}.restart", - f"{'write_data':<16} {output_base}.data nofix" + f"{'write_data':<16} {output_base}.data nofix", ]) - # Write assembled LAMMPS input script to file + # ----- Write the .in file -------------------------------------- in_file_path = rxn_dir / f"in.{tag}_reaction_stage_2" - with open(in_file_path, 'w') as f: + with open(in_file_path, "w") as f: f.write("\n".join(lines)) - - # Copy all required reaction template files to output directory + + # ----- Copy auxiliary files into the reaction directory --------- self._copy_required_files(dest_dir=rxn_dir) return in_file_path.name @@ -197,30 +232,33 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: def _copy_required_files(self, dest_dir: Path) -> None: """ Copy reaction template and molecule definition files to the output directory. - + Copies pre-reaction molecules, post-reaction molecules, and atom mapping files required by LAMMPS to the simulation directory for execution. - + Args: - dest_dir (Path): Destination directory for copied files - + dest_dir (Path): Destination directory for copied files. + Raises: - FileNotFoundError: If any required reaction file is missing or cannot be accessed + FileNotFoundError: If any required reaction file is missing or cannot be accessed. """ rf = self.reacter_files + for template in [ t for t in rf.template_files if getattr(t, "activity_stats", True) ]: - # Collect all files associated with this reaction template - files = [ + # Collect all files associated with this reaction template. + files: list[Path] = [ template.map_file, template.pre_reaction_file, - template.post_reaction_file + template.post_reaction_file, ] - - # Copy each file to the destination, preserving metadata + + # Copy each file to the destination, preserving metadata. for file in files: if file is None or not file.exists(): - raise FileNotFoundError(f"Required reaction file not found: {file}") + raise FileNotFoundError( + f"Required reaction file not found: {file}" + ) shutil.copy2(file, dest_dir / file.name) From 48b21144d7515b9fbe40b3fd1d2a73c26295080f Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:38:50 -0400 Subject: [PATCH 126/176] Add TMC/MPD example, fix bugs, refactor reactions --- .../reactions_library/vinyl_polymers.py | 133 +++++++++--------- AutoREACTER/input_parser.py | 18 +++ .../deduplication_detector.py | 36 +++++ .../ff_wrapper/REACTER_files_builder.py | 19 ++- .../reaction_progression.py | 10 +- .../sim_setup/writers/densification_writer.py | 3 +- examples/TMC_MPD.json | 42 ++++++ examples/test_ethelene.json | 32 ++--- 8 files changed, 202 insertions(+), 91 deletions(-) create mode 100644 examples/TMC_MPD.json diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py index 20a6d009..ae23657e 100644 --- a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -145,72 +145,75 @@ 'reference': {'smarts': None, 'reaction_and_mechanism': None}, 'comments': None, - 'notes': ( - 'Forced H-T copolymerization initiation between a rare branchable ' - 'vinyl/crosslinker vinyl and a normal vinyl monomer. The branchable ' - 'vinyl is placed into the initial chain segment, while the active ' - 'radical is carried forward on the normal vinyl head atom map 4. ' - 'Maps 1 and 2 form the new bond. Use this reaction with separate ' - 'time control or max_rxn limits so the low-count crosslinker is not ' - 'over-consumed at the beginning.' - ), -}, - - # ---- kept commented, unchanged ---- - # 'Vinyl Addition Polymerization': { - # 'same_reactants': True, - # 'reactant_1': 'vinyl', - # 'product': 'polyvinyl_chain', - # 'delete_atom': False, - # 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', - # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # 'comments': None - # }, - # 'Vinyl Copolymerization': { - # 'same_reactants': False, - # 'reactant_1': 'vinyl', - # 'reactant_2': 'vinyl', - # 'product': 'copolyvinyl_chain', - # 'delete_atom': False, - # 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', - # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # 'comments': None - # }, - # 'Cyclic Olefin Addition Polymerization': { - # 'same_reactants': True, - # 'reactant_1': 'cyclic_olefin', - # 'product': 'polycyclic_chain', - # 'delete_atom': False, - # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', - # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # 'comments': None - # }, - # 'Cyclic Olefin and Vinyl Copolymerization': { - # 'same_reactants': False, - # 'reactant_1': 'vinyl', - # 'reactant_2': 'cyclic_olefin', - # 'product': 'copolycyclicvinyl_chain', - # 'delete_atom': False, - # 'reaction': '[CH2:1]=[C;!R:2].[C;R:3]=[C;R:4]>>[C:1]-[C:2]-[C:3]-[C:4]', - # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # 'comments': None - # }, - # 'Cyclic Olefin Copolymerization': { - # 'same_reactants': False, - # 'reactant_1': 'cyclic_olefin', - # 'reactant_2': 'cyclic_olefin', - # 'product': 'copolycyclic_chain', - # 'delete_atom': False, - # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', - # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # 'comments': None - # }, + # Disabled until branchable_vinyl functional-group detection + # or explicit reactant ordering is implemented. +# + # 'notes': ( + # 'Forced H-T copolymerization initiation between a rare branchable ' + # 'vinyl/crosslinker vinyl and a normal vinyl monomer. The branchable ' + # 'vinyl is placed into the initial chain segment, while the active ' + # 'radical is carried forward on the normal vinyl head atom map 4. ' + # 'Maps 1 and 2 form the new bond. Use this reaction with separate ' + # 'time control or max_rxn limits so the low-count crosslinker is not ' + # 'over-consumed at the beginning.' + # ), +# }, +# + # # ---- kept commented, unchanged ---- + # # 'Vinyl Addition Polymerization': { + # # 'same_reactants': True, + # # 'reactant_1': 'vinyl', + # # 'product': 'polyvinyl_chain', + # # 'delete_atom': False, + # # 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', + # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # # 'comments': None + # # }, + # # 'Vinyl Copolymerization': { + # # 'same_reactants': False, + # # 'reactant_1': 'vinyl', + # # 'reactant_2': 'vinyl', + # # 'product': 'copolyvinyl_chain', + # # 'delete_atom': False, + # # 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', + # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # # 'comments': None + # # }, + # # 'Cyclic Olefin Addition Polymerization': { + # # 'same_reactants': True, + # # 'reactant_1': 'cyclic_olefin', + # # 'product': 'polycyclic_chain', + # # 'delete_atom': False, + # # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', + # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # # 'comments': None + # # }, + # # 'Cyclic Olefin and Vinyl Copolymerization': { + # # 'same_reactants': False, + # # 'reactant_1': 'vinyl', + # # 'reactant_2': 'cyclic_olefin', + # # 'product': 'copolycyclicvinyl_chain', + # # 'delete_atom': False, + # # 'reaction': '[CH2:1]=[C;!R:2].[C;R:3]=[C;R:4]>>[C:1]-[C:2]-[C:3]-[C:4]', + # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # # 'comments': None + # # }, + # # 'Cyclic Olefin Copolymerization': { + # # 'same_reactants': False, + # # 'reactant_1': 'cyclic_olefin', + # # 'reactant_2': 'cyclic_olefin', + # # 'product': 'copolycyclic_chain', + # # 'delete_atom': False, + # # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', + # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + # # 'comments': None + # # }, 'Tetrafluoroethylene Initiation': { 'same_reactants': False, - 'reactant_1': 'initiator_radical', + 'reactant_1': 'tetrafluoroethylene', 'reactant_2': 'tetrafluoroethylene', - 'product': 'ptfe_active_center', + 'product': 'vinyl_chain_end_radical', 'delete_atom': False, 'reaction': ( '[*:1].' @@ -227,9 +230,9 @@ 'Tetrafluoroethylene Propagation': { 'same_reactants': False, - 'reactant_1': 'ptfe_active_center', + 'reactant_1': 'vinyl_chain_end_radical', 'reactant_2': 'tetrafluoroethylene', - 'product': 'ptfe_active_center', + 'product': 'vinyl_chain_end_radical', 'delete_atom': False, 'reaction': ( '[*:1]-[CX4:2](-[F:4])(-[F:5]).' @@ -247,7 +250,7 @@ # 'Tetrafluoroethylene Termination (Recombination)': { # 'same_reactants': True, - # 'reactant_1': 'ptfe_active_center', + # 'reactant_1': 'vinyl_chain_end_radical', # 'product': 'ptfe_chain', # 'delete_atom': False, # # Two growing chains meet and recombine at their active CX4 centers diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 8baa46ee..62f6ab19 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -1024,6 +1024,24 @@ def _validate_simulations( "simulations": simulations, } + def _validate_loop( + self, + inputs: dict, + ) -> tuple[bool, int | None]: + """ + Backward-compatible wrapper for older loop validation tests. + + New logic is handled by _validate_reaction_iteration_depth. + """ + reaction_iteration_depth = self._validate_reaction_iteration_depth( + inputs + ) + + if reaction_iteration_depth == 0: + return False, None + + return True, reaction_iteration_depth + def _normalized_option_key(self, key: str) -> str: """ Normalize workflow option keys so common spellings are accepted. diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 6ee16da8..327cb107 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -1261,6 +1261,42 @@ def lammps_molecule_to_networkx( return graph + def write_wildcard_maps( + self, + template_files: list["ReactionMetadata"], + ) -> list["ReactionMetadata"]: + """ + Write Wildcards sections for active LAMMPS templates without + performing duplicate filtering. + """ + active_templates: list["ReactionMetadata"] = [] + + for template in template_files: + if not template.activity_stats: + continue + + if template.map_file is None: + template.activity_stats = False + continue + + map_file_path = Path(template.map_file) + + if not map_file_path.is_file(): + template.activity_stats = False + continue + + wildcard_ids = self._read_lammps_edge_ids(map_file_path) + + self._write_lammps_wildcard_map_file( + map_file_path=map_file_path, + wildcard_ids=wildcard_ids, + ) + + template.map_file = map_file_path + active_templates.append(template) + + return active_templates + def compare_lammps_templates( self, template_files: list["ReactionMetadata"], diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index f30f0b3b..ca175da5 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -790,6 +790,17 @@ def molecule_template_preparation(self, session: "Session") -> None: reaction.map_file, final_dir, ) + if ( + reaction.map_file_with_delete_ids is None + and reaction.map_file is not None + and reaction.reaction_id is not None + ): + delete_map_path = Path(reaction.map_file).with_name( + f"RXN_{reaction.reaction_id}_with_delete_ids.map" + ) + if delete_map_path.is_file(): + reaction.map_file_with_delete_ids = delete_map_path + reaction.map_file_with_delete_ids = self._copy_path_to_final( reaction.map_file_with_delete_ids, final_dir, @@ -812,8 +823,9 @@ def molecule_template_preparation(self, session: "Session") -> None: and reaction.post_reaction_file is not None ] + detector = DeduplicationDetector() + if self.deduplicate_reaction_templates: - detector = DeduplicationDetector() active_template_reactions = detector.compare_lammps_templates( template_files=active_template_reactions, wildcards=self.wildcards, @@ -821,6 +833,11 @@ def molecule_template_preparation(self, session: "Session") -> None: else: print("[INFO] Skipping LAMMPS reaction-template deduplication.") + if self.wildcards: + active_template_reactions = detector.write_wildcard_maps( + template_files=active_template_reactions, + ) + reacter_files = REACTERFiles( force_field_data=force_field_data, in_file=in_file, diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index e0614210..22a8a388 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -147,13 +147,13 @@ def reaction_progression( Prepared and deduplicated reaction metadata accumulated across all iterations. """ - # Respect the validated reaction progression depth from input_parser. - reaction_iteration_depth = self.session.inputs.reaction_iteration_depth + # Respect the validated reaction progression depth from input_parser + # unless the caller explicitly supplies a loop limit. + if max_loop is None: + max_loop = self.session.inputs.reaction_iteration_depth - if reaction_iteration_depth <= 0: + if max_loop <= 0: return list(self.session.reaction_metadata) - - max_loop = reaction_iteration_depth print( f"Using reaction_iteration_depth={max_loop} for " "reaction progression." diff --git a/AutoREACTER/sim_setup/writers/densification_writer.py b/AutoREACTER/sim_setup/writers/densification_writer.py index e64fc1ee..582eb97f 100644 --- a/AutoREACTER/sim_setup/writers/densification_writer.py +++ b/AutoREACTER/sim_setup/writers/densification_writer.py @@ -164,7 +164,8 @@ def write_lammps_densification_file(self, simulation: Simulation) -> str: mol_ids = {} for i, mol in enumerate(rf.molecule_files, 1): m_id = f"mol_{i}" - mol_ids[mol.id] = m_id + mol_name = mol.name or mol.data_id + mol_ids[mol_name] = m_id lines.append(f"{'molecule':<16} {m_id} {mol.lmp_molecule_file.name}") lines.append("\n#------------Randomly Insert Molecules------------") diff --git a/examples/TMC_MPD.json b/examples/TMC_MPD.json new file mode 100644 index 00000000..c2631e9b --- /dev/null +++ b/examples/TMC_MPD.json @@ -0,0 +1,42 @@ +{ + "simulation_name": "Trimesoyl_Chloride_m_Phenylenediamine", + "force_field": "PCFF", + + "deep_search": true, + "reaction_iteration_depth": 5, + "wildcards": true, + "deduplicate_reaction_templates": true, + "write_second_reaction_stage": true, + + "simulations": [ + { + "tag": "10k_300K", + "temperature": 300, + "density": 0.8, + "monomer_counts": { + "trimesoyl_chloride": 238, + "m_phenylenediamine": 357 + } + }, + { + "tag": "100k_300K", + "temperature": 300, + "density": 0.8, + "monomer_counts": { + "trimesoyl_chloride": 2380, + "m_phenylenediamine": 3570 + } + } + ], + + "monomers": [ + { + "name": "trimesoyl_chloride", + "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" + }, + { + "name": "m_phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + } + ] +} diff --git a/examples/test_ethelene.json b/examples/test_ethelene.json index 0325cce0..34eacca0 100644 --- a/examples/test_ethelene.json +++ b/examples/test_ethelene.json @@ -1,31 +1,25 @@ { - "simulation_name": "Styrene", - "loop": 9, + "simulation_name": "Ethene_Test", "force_field": "PCFF", + "deep_search": true, + "reaction_iteration_depth": 5, + "wildcards": true, + "deduplicate_reaction_templates": true, + "write_second_reaction_stage": true, "simulations": [ { - "tag": "styrene_10k", + "tag": "10k_300K", "temperature": 300, - "density": 1.0, - "total_atoms": 10000, - "monomer_ratios": { - "styrene": 1.0 - } - }, - { - "tag": "styrene_100k", - "temperature": 300, - "density": 1.0, - "total_atoms": 100000, - "monomer_ratios": { - "styrene": 1.0 + "density": 0.8, + "monomer_counts": { + "ethene": 5000 } } ], "monomers": [ { - "name": "styrene", - "smiles": "C=Cc1ccccc1" + "name": "ethene", + "smiles": "C=C" } ] -} \ No newline at end of file +} From a088d020df4d67bb0b3af3028d451e0b97bbe2ab Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 18 Aug 2026 11:22:13 -0400 Subject: [PATCH 127/176] Fix vinyl polymer reactions dict and add docs page --- AutoREACTER/detectors/reactions_library/vinyl_polymers.py | 1 + docs/source/adavnce_options.md | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 docs/source/adavnce_options.md diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py index ae23657e..cede3a3e 100644 --- a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -261,4 +261,5 @@ # }, # 'comments': 'UNTESTED: Radical recombination termination for PTFE' # } +} } \ No newline at end of file diff --git a/docs/source/adavnce_options.md b/docs/source/adavnce_options.md new file mode 100644 index 00000000..888f4116 --- /dev/null +++ b/docs/source/adavnce_options.md @@ -0,0 +1,3 @@ +## Title of the Documentation + +titles should start with ## since the main title is already in Getting Started and overview pages. \ No newline at end of file From 7767c4f9cdf5bc2cd46944aaa689db738acfd250 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 18 Aug 2026 12:27:25 -0400 Subject: [PATCH 128/176] Add deep-check toggle and advanced options docs --- AutoREACTER/input_parser.py | 1 - .../deduplication_detector.py | 9 ++++- .../ff_wrapper/FF_files/pcff.frc | 4 +++ .../ff_wrapper/lunar_client/config.py | 2 +- .../reaction_processor/prepare_reactions.py | 3 +- docs/source/adavnce_options.md | 20 +++++++++-- examples/doc_2.json | 34 +++++++++++++++++++ 7 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 examples/doc_2.json diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 62f6ab19..1197bb80 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -278,7 +278,6 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: "stage_2", ], ) - return SimulationSetup( simulation_name=simulation_name, temperature=validated_simulations["temperatures"], diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index 327cb107..b7f35666 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -900,7 +900,10 @@ def compare_graphs_mol( self, reaction_metadata_items: list["ReactionMetadata"], index_source: str = "template", + deep_check: bool = True, ) -> list["ReactionMetadata"]: + + """ Detect duplicate reactions using in-memory RDKit molecules. @@ -980,12 +983,14 @@ def compare_graphs_mol( pre_graph = self.rdkit_mol_to_networkx( molecule=reactant_mol, atom_idxs=reactant_indices, + deep_check=deep_check, ) post_graph = self.rdkit_mol_to_networkx( molecule=product_mol, atom_idxs=product_indices, idx_relabel=product_to_reactant_mapping, + deep_check=deep_check ) reactant_radical_count = self._count_radical_atoms( @@ -1118,6 +1123,7 @@ def rdkit_mol_to_networkx( molecule: Chem.Mol, atom_idxs: set[int] | None = None, idx_relabel: dict[int, int] | None = None, + deep_check: bool = True, ) -> nx.Graph: """ Convert an RDKit molecule into a NetworkX graph. @@ -1164,7 +1170,8 @@ def rdkit_mol_to_networkx( is_radical = self._is_radical_atom(atom) - if not self.DEEP_CHECK: + + if not deep_check: atom_label = ( atom.GetSymbol(), is_radical, diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc index dcf5e251..c42ea18b 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc +++ b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc @@ -2914,6 +2914,10 @@ 1.0 1 o c c_0 h -0.0390 0.0 1.4052 0.0 0.0757 0.0 1.0 1 o c c_0 o_1 0.6444 0.0 0.7897 0.0 1.0604 0.0 2.1 8 c c c_1 n_2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 + 2.1 8 nn c_1 c c2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->nn, c->c/c2 + 2.1 8 nn c_1 c c3 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->nn, c->c/c3 + 2.1 8 nn c_1 c2 c2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->nn, c->c2 + 2.1 8 nn c_1 c2 hc 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from h c c_1 n_2 reversed; mapped n_2->nn, c->c2, h->hc 2.1 8 na c_1 c2 c2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->na and c->c2 2.1 8 c c c_1 o_1 0.0442 0.0 0.0292 0.0 0.0562 0.0 2.1 8 c c c_1 o_2 1.8341 0.0 2.0603 0.0 -0.0195 0.0 diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py index 96b9c6fc..a6dba3d1 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/lunar_client/config.py @@ -1 +1 @@ -LUNAR_ROOT_DIR = None +LUNAR_ROOT_DIR = '/mnt/c/Users/Janitha/Documents/GitHub/LUNAR' diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index b4adc959..4b4d706d 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -190,7 +190,8 @@ def prepare_reactions(self, session): prepared_reactions = self._prepare_reactions_stage(session) session.reaction_metadata = prepared_reactions - if session.inputs.deep_search and session.inputs.loop: + if session.inputs.loop: + print("\n[INFO] Reaction progression is enabled. ") progression = ReactionProgression(session, preparer=self) final_reactions = progression.reaction_progression() session.reaction_metadata = final_reactions diff --git a/docs/source/adavnce_options.md b/docs/source/adavnce_options.md index 888f4116..1d4942a7 100644 --- a/docs/source/adavnce_options.md +++ b/docs/source/adavnce_options.md @@ -1,3 +1,19 @@ -## Title of the Documentation +## Advanced Options -titles should start with ## since the main title is already in Getting Started and overview pages. \ No newline at end of file +AutoREACTER gives users control over reaction generation through the input JSON file. These options allow users to tune how aggressively reactions are searched, how many reaction-growth iterations are attempted, how reaction templates are simplified, and whether one or two reaction stages are written for LAMMPS. + +### Deep search + +`deep_search` controls whether AutoREACTER performs iterative reaction discovery beyond the first set of directly detected reactions. + +When `deep_search` is disabled, AutoREACTER detects reactions only from the functional groups present in the initial input monomers. This is useful for simple systems where only the first reaction event is needed. + +When `deep_search` is enabled, AutoREACTER uses newly generated reaction products as possible reactants for later reaction searches. This allows the workflow to discover chain-growth, crosslinking, and multi-generation polymerization reactions that are not visible from the starting monomers alone. + +For example, in a vinyl polymerization workflow, the first reaction may generate an active chain-end radical. That new radical product can then react with another vinyl monomer in the next search iteration. Without deep search, AutoREACTER may only detect the initial reaction. With deep search enabled, AutoREACTER can continue discovering propagation-style reactions from newly generated products. + +```json +{ + "deep_search": true, + "reaction_iteration_depth": 5 +} \ No newline at end of file diff --git a/examples/doc_2.json b/examples/doc_2.json new file mode 100644 index 00000000..581c2cd7 --- /dev/null +++ b/examples/doc_2.json @@ -0,0 +1,34 @@ +{ + "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", + "deep_search": false, + "reaction_iteration_depth": 5, + "wildcards": false, + "deduplicate_reaction_templates": true, + "write_second_reaction_stage": true, + "simulations": [ + { + "tag": "epoxy_test", + "temperature": 300, + "density": 1.0, + "monomer_counts": { + "di_epoxy": 200, + "primary_diamine": 100, + "primary_diamine_2": 50 + } + } + ], + "monomers": [ + { + "name": "di_epoxy", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" + }, + { + "name": "primary_diamine", + "smiles": "NCCCCCN" + }, + { + "name": "primary_diamine_2", + "smiles": "CC(CCN)CCN" + } + ] +} From 1e9cac1d73f5c334867814d8c07cc7e334ea8691 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 18 Aug 2026 12:34:24 -0400 Subject: [PATCH 129/176] Remove debug print on reaction fallback --- .../reaction_processor/prepare_reactions.py | 8 ++++---- .../reaction_processor/reaction_progression.py | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 4b4d706d..d743270c 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -473,10 +473,10 @@ def _process_reaction_products( products = rxn.RunReactants((r1, r2)) if not products: - print( - "Reaction failed in default order, " - "trying reverse order..." - ) + # print( + # "Reaction failed in default order, " + # "trying reverse order..." + # ) # this was a debug print, not needed in normal operation products = rxn.RunReactants((r2, r1)) if not products: diff --git a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py index 22a8a388..dcac0562 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/reaction_progression.py @@ -125,8 +125,7 @@ def __init__(self, session: "Session", preparer=None): self.rxn_detector = ReactionDetector() self.deduplication_detector = DeduplicationDetector() - # Display the runtime warning banner (e.g. about experimental - # progression behavior or licensing). + # Loop warnings are printed only once per session, so that users are not overwhelmed by repeated messages. print_warning() def reaction_progression( @@ -149,6 +148,7 @@ def reaction_progression( """ # Respect the validated reaction progression depth from input_parser # unless the caller explicitly supplies a loop limit. + if max_loop is None: max_loop = self.session.inputs.reaction_iteration_depth @@ -253,7 +253,8 @@ def reaction_progression( # paths, so deduplication occurs after preparation. all_prepared_reactions = ( self.deduplication_detector.compare_graphs_mol( - all_prepared_reactions + all_prepared_reactions, + deep_check=self.session.inputs.deep_search, ) ) self.session.reaction_metadata = all_prepared_reactions From d42a855f50449cf5aed19ab34239433f70c363e6 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Tue, 18 Aug 2026 18:54:16 -0400 Subject: [PATCH 130/176] Document advanced options and dedupe --- .../ff_wrapper/FF_files/pcff.frc | 4 + .../reaction_processor/prepare_reactions.py | 12 +- .../deep_search_figures/edge_monomers.png | Bin 0 -> 29765 bytes .../edge_templates_template.png | Bin 0 -> 129046 bytes .../deep_search_figures/input_monomers.png | Bin 0 -> 26291 bytes .../missed_templates_template.png | Bin 0 -> 158972 bytes .../deep_search_figures/w_deep_search.png | Bin 0 -> 225171 bytes .../deep_search_figures/w_o_deep_search.png | Bin 0 -> 102225 bytes .../glycine_templates_template.png | Bin 0 -> 282860 bytes .../_static/loop_figures/loop_monomers.png | Bin 0 -> 21313 bytes .../loop_figures/loop_templates_template.png | Bin 0 -> 283741 bytes .../wo_loop_templates_template.png | Bin 0 -> 107678 bytes ...CTER_wildcards_Diels-Alder-example_ed.avif | Bin 0 -> 19151 bytes .../prior_templates_template.png | Bin 0 -> 431550 bytes .../wild_cards-templates_template.png | Bin 0 -> 310704 bytes docs/source/adavnce_options.md | 19 - docs/source/advanced_options.md | 378 ++++++++++++++++++ docs/source/index.rst | 4 +- docs/source/input-configuration.md | 8 + 19 files changed, 403 insertions(+), 22 deletions(-) create mode 100644 docs/source/_static/deep_search_figures/edge_monomers.png create mode 100644 docs/source/_static/deep_search_figures/edge_templates_template.png create mode 100644 docs/source/_static/deep_search_figures/input_monomers.png create mode 100644 docs/source/_static/deep_search_figures/missed_templates_template.png create mode 100644 docs/source/_static/deep_search_figures/w_deep_search.png create mode 100644 docs/source/_static/deep_search_figures/w_o_deep_search.png create mode 100644 docs/source/_static/loop_figures/glycine_templates_template.png create mode 100644 docs/source/_static/loop_figures/loop_monomers.png create mode 100644 docs/source/_static/loop_figures/loop_templates_template.png create mode 100644 docs/source/_static/loop_figures/wo_loop_templates_template.png create mode 100644 docs/source/_static/wild_cards_figures/REACTER_wildcards_Diels-Alder-example_ed.avif create mode 100644 docs/source/_static/wild_cards_figures/prior_templates_template.png create mode 100644 docs/source/_static/wild_cards_figures/wild_cards-templates_template.png delete mode 100644 docs/source/adavnce_options.md create mode 100644 docs/source/advanced_options.md diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc index c42ea18b..e38ab419 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc +++ b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc @@ -2914,16 +2914,20 @@ 1.0 1 o c c_0 h -0.0390 0.0 1.4052 0.0 0.0757 0.0 1.0 1 o c c_0 o_1 0.6444 0.0 0.7897 0.0 1.0604 0.0 2.1 8 c c c_1 n_2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 + 2.1 8 nn c_1 c1 c=1 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->nn, c->c1/c=1 + 2.1 8 nn c_1 c1 c2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->nn, c->c1/c2 2.1 8 nn c_1 c c2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->nn, c->c/c2 2.1 8 nn c_1 c c3 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->nn, c->c/c3 2.1 8 nn c_1 c2 c2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->nn, c->c2 2.1 8 nn c_1 c2 hc 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from h c c_1 n_2 reversed; mapped n_2->nn, c->c2, h->hc 2.1 8 na c_1 c2 c2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from c c c_1 n_2 reversed; mapped n_2->na and c->c2 2.1 8 c c c_1 o_1 0.0442 0.0 0.0292 0.0 0.0562 0.0 + 2.1 8 o_1 c_1 c1 c=1 0.0442 0.0 0.0292 0.0 0.0562 0.0 # AutoREACTER addition; copied from c c c_1 o_1 reversed; mapped c->c1/c=1 2.1 8 c c c_1 o_2 1.8341 0.0 2.0603 0.0 -0.0195 0.0 2.1 8 o_2 c_1 c c= 1.8341 0.0 2.0603 0.0 -0.0195 0.0 # AutoREACTER addition; copied from c c c_1 o_2 reversed; mapped terminal c -> c= 2.1 8 oh c_1 c2 c2 1.8341 0.0 2.0603 0.0 -0.0195 0.0 # AutoREACTER addition; copied from c c c_1 o_2 reversed; mapped o_2->oh and c->c2 2.1 8 h c c_1 n_2 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 + 2.1 8 nn c_1 c1 hc 0.1693 0.0 -0.0090 0.0 -0.0687 0.0 # AutoREACTER addition; copied from h c c_1 n_2 reversed; mapped n_2->nn, c->c1, h->hc 2.1 8 h c c_1 o_1 -0.1804 0.0 0.0012 0.0 0.0371 0.0 2.1 8 h c c_1 o_2 -0.6359 0.0 1.4807 0.0 -0.0438 0.0 1.0 1 n c c_1 n -0.0892 0.0 0.1259 0.0 -0.0884 0.0 diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index d743270c..0abde5ba 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -28,6 +28,9 @@ from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ( ReactionProgression, ) +from AutoREACTER.reaction_preparation.deduplication_detector import ( + DeduplicationDetector, +) from AutoREACTER.reaction_preparation.reaction_processor.utils import ( add_column_safe, add_dict_as_new_columns, @@ -198,6 +201,14 @@ def prepare_reactions(self, session): self._zero_active_reactions_error(final_reactions) else: self._zero_active_reactions_error(prepared_reactions) + self.deduplication_detector = DeduplicationDetector() + session.reaction_metadata = ( + self.deduplication_detector.compare_graphs_mol( + session.reaction_metadata, + deep_check=self.session.inputs.deep_search, + ) + ) + return session @@ -595,7 +606,6 @@ def _process_reaction_products( activity_stats=True, ) ) - return reaction_metadata def _detect_duplicates( diff --git a/docs/source/_static/deep_search_figures/edge_monomers.png b/docs/source/_static/deep_search_figures/edge_monomers.png new file mode 100644 index 0000000000000000000000000000000000000000..f9cb2bee1a2da50e6618b1e795c618bc70e7442f GIT binary patch literal 29765 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 ME!WpgU241gf6<8_KmY&$ literal 0 HcmV?d00001 diff --git a/docs/source/_static/deep_search_figures/edge_templates_template.png b/docs/source/_static/deep_search_figures/edge_templates_template.png new file mode 100644 index 0000000000000000000000000000000000000000..b9fbdbbc708ece5d88473c85a624a87ebc496746 GIT binary patch literal 129046 zcmeEug;&*G*X>bM9;HMDL`o4sK)R$=5EKxkJCyD^bShFJAX3sOAl=;v(%m2>-5|{& z?>gx7-S5^PaL0J}a5&%y=j`9!Yp*reoOA2@Qc@J>%B?F11On&zGhrD70<#N&z*zX_ zJiKz5Z}S*&4uN*c#E{BJX;u0FXcXW^0Xb^t$7 zB{!4MtvItVv(h}bC?GA=K)y!Wm*j@$)oY)a&%e6z2JuSoAlA9pWjjGL`N@2 z&+IsFcVnu}^9(wOCVbl4sT9x*ZPvL4AAUBvIE<1o{_C6TFH8RYM(f;-wSQk%LU{82 z`!(UCN!-6*yI=gzkN;<7{u2cMIUfJX1c?6x!T%pY;I6QUa5v>vcFJpeN%-sP)rG4m zNW#AbZTB6)+Je8)i$d-lZusLETs15nsBUl4vO#-Fw;xXV{qN5WF)5TJ5Ye)PRD_-W z48NyIo+V&%E!f9E{^zh+KE?Xpex^n-UCiGy>F$zXA!?qRZ#AEpY|hX{B|*Kb4v;s{Gy_%caVH7EpPt8mU*6Wav9^F}!Pcdm%Cc1C`RCsc_yBW=%m1k?Y~)`kh6#uWJ-ULWOA_X{ zdhC6lRS8rlm_O(vI(fP4F^lo{-xqxEk9KeQ+Yr-JdZ*)&NOJW5d0H^nr_EE z;!G~bJA;`qId<#g;Tn#MnZ@IIdS_4OUXPwqdHZsaK%@ZWruV2I(je$?>s)8`&F!z> zb?kqSdaM&v4w{}jhu|MAvsqTiR4FtYD;tn}CMKp*XwSQRR7Zol5s zDZrea{q*s+;K}{^`l%_(sw!6FFp1B%=|X#&|Grs0;8iktLFdzn=QKdHX; zKTZ#o)UoOB-wdyATFw@im){C+@DFx75}Iq5r6fcQy(udzd;9h+p=Me}MuF8$^m{$B zi?_h!nadKegSBw#96jtw3g4zaZavmic%H31psqs4HGZGh?!Avh^nI=|s>hFIWbb0) zwS;T71l`TkdQ*Y=#&?j?^Y~m1q3O?p=D|V5#j~U4ZYDg5iyVs4uq%64GU_nb;Wl@g z-=efL=g!stRe>i&K11maysL*thVorJzAhd2HgTqA{=KH%)y@5BRjsz4iI+ETePa@;LMrf9tMBh7%u{f@mtGVeGoP14 z&0NP13fBzNJjp|q*a`{`mq>eI<9j@I-6DB<{=B=tYL3?TQU$)lm3*<}v;9Vwysqb1 ze1sd zLzk}D#cxrL-K{1$h$(M4o}LPHa-EO;e4o;)mEmi5fn$ehv9AI>Wu8m9&6B_9xX7cH zY~j;C#XjvqoK6OOCr+s9z1Yg)ak*^d*EMMw%K1(|Sn{C(L!OuqH}6nd?dK5u`>ULu z@T+Oe#X0X@T^?6iFKM+b)*VwYPLt;ex<|@S=XSi@S^jz; zndYe9SaZMlZt2Oicf(%)?s3uf$cW^Gf_8>9kF-9qf1YJRTNKT7L$h_~bFr4t=|aJ= zrxq3^4Fu8AkIaHd5VRXi3-5P;`~naP?mf3H9~aUhGxp{<{pSN%B01E^7&7M2Yr(Kq<|< z8SO~kufDf0gg8r$M?-P@aTgb_kJb&Tu)AW0C^Owi9>%EEWdmH#PG^v@P85zcE ztJ{Y7K_|!M42+1OxGI;!OBXNhtd0~HULPGB^LYFA=;$aT;w;-}S<(eJCn7J!i*jpN zJFhjDLQ>zOs5mXG&n_(=F`Czqy-UK`M4#RC-Gh?SsBqLiAw!MUdj7pwe=UkluW4;8 z&mhQo>qYutTU$k*;Zky3%cpx|*GT>@t^9|Oa}P`sx0(_spL4C2E*^W2#|gT*8XBhd z_-0uxh45{C*j{Jan_$Akdmk5

j`I8P;1^w0N}0uL%Og=jgYGTE);(sJ8Y~VOY9@ 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%0A3x~h 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%0DZq7y4#&>;e<9cQ3hGNf)0n`F> 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%0A!!Hqu*n&DqZmlM^v8FtlYDV&-k+{D7caOZIyu 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 literal 0 HcmV?d00001 diff --git a/docs/source/_static/deep_search_figures/w_deep_search.png b/docs/source/_static/deep_search_figures/w_deep_search.png new file mode 100644 index 0000000000000000000000000000000000000000..297be9f82219c11c822aa418bbec607c1f76c5ed GIT binary patch literal 225171 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.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
?Hf z>%1|w-671?_vPXM5P*vTzXHLBH~NR`(vZMH!eY5;IN*r3UkPr;6vH_6<oHQ~67sU5D#45oJoEoRnOWF58OwTE4ikKDq^Dj7@p4D# z7wt91*wDFdtmLnI*e$1i$U4i=x^CVoPsSDLIGR6*QaB9w%xBh}(s@M&8exQCM(mrB zPT6U`cXxvIucUpl;n&$K6}yUBs^|QWbswZGJ#O#EPATJh;?W+rVl$^@V74GHvTE|I`;JHoHecSe^S+}9@_t9G|)%lnJ4K;)6j5FQJICtu@ zcE3^gsTv-7#E$@uriNe@!YHqbTNTg}pRn3fy0aS93Skrk)Vs)v6bRJjvXJmB?1c3< z^Bx=+9Mh1zm(aVS0d=vRybMa@be_2y=bFVpad&Ah1b#3dEe6p;WhF|)2(0*VIZl5O z+S3ngPZaDVf zKvazDy3I%)ajloW7Y%kCo9*8h$72OQumPvYJZu>)s5WSjA1EGgN#zk%e{B)rmB<5tzmGat3%5$`Ec-vdMyKYt{&mf)$w?3 zHBqYwb+pSweOz=k{nPpLAnaE@3w34Njb9tK9y>vvhYGNS+^=6hb-tEfsV6Np4T5^Q z*fjiYN05;Ki;&0m$)a|9Es)K)5k%MR{*=Z`on_@y!!5D?VQ&1wa=VdjlopouuVi6* zFI^SXtO$F8QrR^tj-58Mvx;>E#WN7=pE~2+i-4GDeqI-? z?za0x+(1Ugd_uq4jZH-4E+8WCqP_w+6LPJc(BT{{%B*_$M&`y`z;rXMg`kpS{ z_4idcUJx(3d2Liedaq+&?vn8pi0Qq_B zrd^j96l&$Qz}cbN!#Tc%EJwDk^o%=|3}wB|dBLKUCL(yeD-gOB=$-@pLYeqOkq}Bh zCWUKomeZ$rz4if8Pu1Qh<2_1~&@>y){^InNymRQxz{fekbDUgl(Z?B>>3kh|0%M50 ziCjni31=sOmGMG1g zrY7^#*`vu{a>6k0*0#--z!W{|I^SAY7WWwjzG>NC?HHE|XlDDU!3cUN!KB#deFNJg zB`~>aGsIPEI>OuddnpR`QRDvU#uE!4+Dd=2*C&nZlU=5&eoGd}xo;uc>^(`mt|+$F z@pS>CzF^sMuoku#Zl-0{)p8MZ&uY)wpO#JL4l^rzPLrWE3Rj~Se0-pkntCboFQg>{ zkmkJ*|H4<%JcxToOeRY0wVNm|`gJtB;W9l&ZUo;xn|d&u&wd>W)X+YO?)>oebv!-* zQb}Y3)J=g+GXo;*Pe+?le<~ly|0=NE=$+^O*t7-MgpHiJT6`h94NlneGG^~NbIsu} z&UXefDI#VO5^h40D-ZIr3+L=Vjih@?x%MAuDkoyV5h-@FcW>PaZTb5^Af%;Ed~nDr zD8}va+acIV5&0VeU4q#H;J_p|6hCYeZe<{19WOHRkm4%nsrO)ZB`z3~+@0K?8B!Y* zD4KSr)|^#Owf`oJr)teBp<;+mO}I_)_g!-=%4UEKB9spA(**TY46~qGSDGWaU5Rw- zs0SZ4nLu?{65M|d7l*~>_<(l>EZ20acca-U6=Lt@{F9FikS}dJKxNQGw)TB+vt{!E zev+bc@bG@D6V7O0$Rssp;VwIIOPo{#dqp=2=ol~J_ zF}3OED`VYHqZH7HA3ybWWvLzG2Iv1A%|OLJai}QtbhxRiE`&a-keXlTBvlOp9)=%t z7^#6&yRD2^5N{k3EIdxCZ{Obeedh)1S?#Cm3E&HVVTbi4N3sFb(|$bbr|GU&VxE@p zOF^mX88=Z|`b85ifyuM#rLgbmcBkGLo0yM1kCJy?W{k2p4r-e2^4OErK=+ z^RH(j{_v;E82UVSrocz;-v`%n%u<>y&EUhx_uR&v?q%!3QM&?L(>@yN zDbo$`0i9p0XBOP$44mNyQWSP~_U`2N7~rQWT1ks)jw2F&mHpOi?=07Y+BAiB>ye76 z4PFLRx^CL}(29tU=;?*$*NPUFI%ZCIXz|B1`IBlIpQ^OiYyUdh84fJi#^ z_OM#RPJJBA7I1!}xAnqo3}R7lw=9sE1&>cRY@VL->Vy!%;Qt_f$rMR19XL@*S)-Qz z-*)GK?QTS+xRJ21=E@bTS#P_J0TJge&yb~`tni7MjBssLZDPj0f8*(PmF1MgGFL5c zP^ZXoZVIf1DD7atvWf%ZC-?um4qD(kz8FPg#}s9S_nukE_Xgu@DLLb?Fxwt4HlvY* zDfWptB5@n2C8ixEhFt|c4{eXZuOnM62U29Xqs(bcP(bv+usjT-0E0`ge{Glsc&49l zfSP;A=aTLC(9na%YC2eZ`#brx@MLIkbJZcnZg>0vrjrza7%$0tqPk&W=wny>`nt`~ zcBjRm6CRhllK1cUKsU>iyWf28gID+Mq{KY#b<yir(HusZ_C`r0RWe z3WNtEL|S}w-P*33H2iCMeX5$@;PG?A8XDXwzHGG5_lzUtdH{FXr;emwuT(NNM(?QJ zpreWHIooOm5XQb{Xv?X*{A4#$Ee6ouO!o1Ee#zs@7(OMzm2&{P;yTzJJ&L%sHO_$?Pc0k?lZn~>MyhoQ(PaN7LxX;-Y^K(Bd4Ulst{E8(gTYdYBuu-XHs{oF-I z)!vM^l%${`HZHF98fh@clPCMQ7@Ll=VRM?rP17AymukR=m0HvOK7S4*AvtTivX~oP zrpSh9H4krOM@ch<$Orf4zR6ZJ%f1EaE7i#$z2Q3}J0G6ilY1pQT8brY0gM3wJP}hz zoEX%vXoM-j4zb%-cwg-`q6Qf+&y+x~Ft9;MC5D>E`xU2&2Y0OpYf&*0SLPm4k%E4t zNP|5}5)-F(dX>Zv#~g_MZhH_8-IN{2afCsEEO1db{4v>FgG>EV_HG)u(7EJB(^Nf! z{K37LKK>WvaYIjy_HO%lPW;q~DP@vYL|JM^F`~4>tfjtWN*8skCaR6H2EV-uB6}rw zpI2z@Ht$bA)lSdnIWoG#;Ri0HOaN4OE&eR$l+-sqIE`o4F6VY!J%#FO&3q^kDB$Vl z4#g z+t^xjH7Vv>Ohd7cx4zcCfVJM;5H*Yx?0m0Uh)Fn|(UfHLBmeT8)`aThmU zdH7(jPi>@B4g=1Y8X(gl8uxnOl68{cZi z6J-Y<9n-bMX4zu5`-S$5h$W2L_;V6*(o+FVPdN1j@ESdJ*~z11wv@2-csyWYL1yF8 z@%!ZY7+@^�Um%HlPLZ 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
nf=pYG?Kp1A?ZB2QGWv@xZrsXQ!{V=WMNK zlyDru@PE9&)4WSd^7Au{Kfkov{3x3DGZ`wbDHdktZL%6GS3V$Qw;D zGs`4Og8e`BzzJpsWo*omuDksyTc2Cm;{h2^B%wt=$m!wjJ@O%!7dRulHED&(7tZQ= z$8H-~1LZU|$WLCeRAq;eG?+(-QT=rNW8NrP0x5X_$9Ud#NTHvr$B6kWdiy?IkE zFVVl3N$_c#>49pD19{GNJi{=+$p~8v0{gm=z-7}pk!nJXJNo#T%hmLi$C0w2WBa_O zdzYC1wWy_Pd=){0}o z%18w;pJ3|M$o8_|)R*W;Sy`O`kdv1y^{538D{NwtZ^?4o6-MbJ5^QdFb+mkYdH4v1 zyMT%0cC*oQ!|Z)?5fQ_6_W#N93LCjSNk65Uh1P&_jKg*rZwmp$p>5$AkT;C{Nh%1oT1%Em+~!X+S+#1D z>djBlt97Z-q;Y&_MmoYb=sV9&C#E;D?rbqc))g4@DUBog=GD;(NK|lON$?O6;mVz^ zYPBtpJM4uYg^p&NzYGIWD!=o^ODZb!>C#tJR9SBB|A{N~eAo+axBFEKPP^M#DH;_< zQBk`Ug8w??vC%EdPIKxU!}7AbsUk%;2mf)yK+T`^yaBG1jug12Up#3zD;}Qe3_jTV z4c_D|(ls# zV6^a(hiLoC9zPdTzgOAdyxAUdHlvY>3}7Zhwge23u)k^99^ABpo$+W=zDB~$_YjSO ztp+y5t!Hy>c9kwo0bqHP+e?T=I0-K75bax>+8(qJjc`hofKMf&ajw+IiHz zxxEd+W2ON4PPD2SsHq#?BVZ8oydWiAEKsci<8@TCbZ-?>YMh-Y-k{vyR{dL3-`@m0 z?o=R;dRkHiH`VEb(l1Gw6+W@8XGAu)6e(AJgq3D7$V|1Y3-~(Y+JLOQ^8>7hB;~5R zNZd~ycTmH+Cd9o7iX-H?U%g2JiJSvP4yXnNYHBEPl=A49uSF2@X&+WEbgrLbuIugK zjWQO`o7sNeX0l^vyUDy|yf^`2+WfXyInot=bK zWtY2?AAEwGxX+z(bObP4`KA-J54(5J2Jj)vT%Q#B! zh1j^*ARDQV-UF8T%VuTHiS+J^c0~0g*$vv0C%}1Ci#;`EsS|6HFp#;k@T+jL0-TxQ zfqoqgmIzT`6|MbJp`;8VS%~zv>QU=v_kcOV9V4UCU?#rC{N1hzLA7Ec%ND>Dw2)h1 z&1?0WO410)2qsd0tJMV6U0eM!7XBQ^rQ~po1{jwtb6>pmph0u?gqk|ow5_Y3bmgAk)L&PzFh4 zrZe)}n9FgsS}vUv?njXMD5T4A3aZ@8GoDt%;nW;SE4@{7z?EK&$v~j-SQOisQ*r-+)BGZ{r)?IT`VU znG5eQ(9`=nDX9I^-!yzcHq^C14rh@YtqyWNZ|Bd~*u~+FWMrQGq~6Vr&`6#G3At#6 zDldhdi`)(0sUZu<0CMO#9_0zz@aMJMCj;-ioH)3hUdF)MV;LJ9K*o6T`Orvl19w~~ zv3G20$HqRd>RtfP^sOQ@Bcr~dp)(LaA~ZBKHWrVB#Emk>ED2l^q`SKt(aW>b`i7UX z5A(-cFd{AitlI$>lN1|U4U&HtIK*;$IcQQszE4RG%iO3`O}PC^mfe_fH1RF+GYm%b zc5j9WMo^lRWIa60lCkN|%F2qRw-jJ!&0;O#PoF-0{kjZhL+KADn}QOB5STl;IgkYO zPxA8e1vf$$1F@a4SOqvN+|XrL6U_^h*zhMDve zxr_R78|04HYs3y%8YdKVj`-&xi?$YTJ~>05=_%)OR?njb7<~PQI-s+;kcykrvnvb7 zc^uFX;lCOv0D0_ITd8PX)b_gvltE5zn_4_}f@(Vtk~8AB#+x-M_m|)r#RQHw(fh26 zMs=1MTpSZJnA_XioiFy@NlPz)Jt=@Hx_`I{W(J#?VtV@*%D?i1Jw#wLig`pt1VClR zw-Qy96k*@?XDYy4k40c)U|G|*xiU$?@1wI1!Y(DMdp}EGe^{8L6+E$?u)nOk ztk39WO-LZcK4KDh9w4q-w8n8EL9np6Xp;q4shbR;WZ9X`w37{(;~o?|9R0MDz4msN zvN&E3pu55+eYIuOGv~Zur4v^dfJqu8@%XDF=AR%^qSN;`h;&^4pCD3mV4nH0K)voF z+4+Fk?!DpS`@QetY0UZuBqSv7-o5)bhJs_c-IbkzMxLI7EE5>yu{DFv)Da~z|64r% z!|d>} z86K}&LWXwF0ST^IYh$Rb{W~T`QCoWj6qG_p1sS5=V?BQk*4F^+^+{G%YY%Vqz>wDi zm=Q@xmHDDT)cf&;iYd>V1(v9&D1gz%RDGd#1I5P@&~WYDdgoA$^3fFL!w0+w;SN^f%82ISwpy}c3P;W%_kLrw1PzS}~^NDj`< zm)oNf1qxuK%C83F5)6^l(0|bs_;z-lAg&@KaXwS{=pBjy1j@W$E!#iaE<1h{3x?jY z9e{Q}dmO7XDL1(VW%=|XR6Xeb$u zrhNiI!aFG`_|V9ODzc-;fA70CGT=il21{pBg3G)1ayPg{OzWuuO;Vb_Q_dayBd z%t?wlJqHz23IZ95=qF5UXhlz}oN^|Z{An%hcX_@)^EWOF*){4(Amx7_G1rf5!Ae*S zm)*~e;K6vF%~SVkbrl7%qO=<_@hh*vsor9CBrxhn&Y-jU&Dq6>tLAu=K8jic|Lvk{ z@2RG~zCPGdb`2QM`rCs#et!Of>w%b7H|3Px#3y;8{sE~*t zTPnn1XHL(Z#AbeV63ujDneXJ7d-H7RAlX45lSh^^WEbdw_z-ud5RCx;AHZ;=&i6Zc(egMA9+c1xG!I8s=g}IK z6l~1`R`!}y#4N|B-O+6`XOZxdn=|Cy9WQ|dHv*u@mLpvaWQ?lqs?pZ~rtPe(Sb^0w zD=XT9f=xjDVutMV2kh(t8`q{5ng`0KRqi`1(NsE zGJp%zrE7{m_VY*YRdiY4$KAI zxvVLiT%l90V&>5+8KP8rK9qF2LeW^!Q^}!2cxgJzB~VXJ|NM#1?qpFD*p2nSPG&0C zTN-g>Lt{joH`lUwt!J@sQ7N%E!I%2od4VF-Bt#fxKv)73%AvXWeYv|f2vKT&KjD|H zJok0A#i8PQ(ge*Dv1Ib+k7nn*>OAOZHM?*?<4w@SCeQ*1`#$x#yzNN)x@UxhgqWD2 z2?@@}EA1DB?F>L91O~8-861E`O{V|Lu%7^$TWuglL~b&B9*Ig6EE$}5=1UbS7PMm0 ztUc+?ceZ|mEKHK*VJv@}z$FI>T9~n&PO-qqwk5hPa{a9XRI+ie9Cw+8I13eS?L5E6 z0?{g*4s$dji4~k zmP=jNt9CCi0ohG0VlK$DuJ4YDCto_PZwl2n%yv^ltXZt<{;^8~udYXS$&K~OVg0GJF7&mQ`7wbmh0Az?ZnX;_hUxTA|M^bRf4#Jyj$?LXb;7u@`d^)) zb*q%8q0RRMWM(_w;VIYwnP))5)ZQ3&GxKw1534`q6QRBIYAxIT-rx=!kRd7~kHUO5 zAYmE%^1;g)Wxi$>+YsF!!*uq&sS)Uqg4i9*<%}E6*5UBJe(^*{TYIMN$$vf_s#L%n zQA>K7BPN@;2oq2iGOX1;1|z)0yHXUvpfPvfxjy^@61h!;6%is!XwP78V}64MdH}v< z=Y=6&;`G4vCD|6_$iZ&Pk$AxfhX%}+%g#P|`t)F-q3%;oI=diLi}LrgI+y%W@X6OU z5~;n#%~f8EO%)|ZD9EMLaCKtU)%td#mu^;);4n2elLg;*_~>#^e&pBu`M#oJw^T6I z>I@Y=x(8n9hv31|y!pndD5m_@LS`p>6`5TO8j49yH)7gmicVvySW zpbNwsf9m&14YIFA*BU?(?$h^1JvyGrbnX}c82W}Cix`4S>2y`kh4^RG_=vGy;9mG`qw z;31ZRFJeAK5;>}{R z@7saP0i!)DqAC>S@jSZr)vZUi!qrrrZm6bn81hSI9ipz! z2q8cI=~r5yr%0x!j+5oWzJ)GIjYd+Q{1vaL!ytaFUisUrDV{NQK!diaG}dqN(WJg}Le{IVeuM5;~DLPEmo3`@yo}NtDqM z-c`--G9+!6XR99szkqj|2L9z1Bu;MiI1kLDg_D!mE~?FEn3CO%+T!6SXXg*b9BlMpAHocwc;rq zDD}M*IfD4MTuJtA1uzH>VQa#r_Y>LHz!9dh9fhXAtLN2UR z0Y(%`DD;;VN^?BF*L~g`o3!_JkBTxx8mKhQac83@8E%k-yNu6vh&(Kr2Xo6FX$B9E ze%3X0zmYg$@`1HyeR5h#YsFaG!{<_mHUvY!--!oA6Ohsa9lYf2!^qEIT4y~kjwccE z{Qm4OVXwLQ`N0&yl!yo{0)m-^buND}mJ>`MEo;al0~e)|q2{B9RB}mEj<}WJO3?>P zQ()-aieNI(>@OXQdq}o_p1&!@jI%FpiEdN@`DJ<$UnU*G!w)g3@n7r3Bl?cey0p7x zZVJxS6yzMR+ILiSPp;on4-n3}zKkX8Ag}?&JxEt=NRV}YO-Eun?Ah7sl(|Vwn&fJ1 ztP33m;sgi}d24IBkk#kn=7}v$bx1EosyS5StK8mckYhY2uXXr(tmNYC2M4kgc-WR~ zxipJ?Dxk^&8a^vB!iY(2MVv97;PM8P1{fn^JN1^e3a(Joh?~7o&-PAwg7?dUcY|0zgz@>2t)AB!g+Fq44_|rU>K-yV0Ul? zcpg*vAonEq9%VEDg0^hiN&9F8i~8jl0oyDK=TiSq_S4f^| z-idEK(1q6y5wJ&GJPw{J+I3&Gy;?)&ac+Khz+*Zr;b)QAbtYdxTdQPihYAU4v{x3$ z{ha& z=)1;>e2DjO+!w0fR^2kQztB@A1?70wwKFv|ZUzP!?cj9)#T(h1AFDNg8^w^)#+KIC zG7X)lTMkEY&hsUejo;7Wi<6yVcew-=pen1Yi}lP{qdG?t-=!`q8xd8&UIlQKqn-)({*eV|iAYsG{6wiy;1iwsR40WE&i zL@B#Vxc`R#Xg`XS^y|3_)P2?RmDL>P#!uMRHZS zTw}!lVBh9DZZC<56JV!lzi5ZLbEafl-d_k5cWpV)jF6c--ft(MPPt)%U7Jahf|FAU zWPebRu9P<(DdEKA0vDWp>YOIQRI99_e3E1J^>CV_LQzlSnBO*No#No!7)li#A0KaU zI)8#}5qu6)2*AS9u>%;R`6cJ`zB(#2PUmM=BPOu?GQ>pBLmk|_<>59SeUqm%b3@)xa6;%g@1N_@Ko^5nqQk`SsIH zl{#u(Yp`A!O#5DFa8^YgO)5)4gOHM@Oid|OsJMcE0n%D%$W=JI<<=>GNVy9##|K(n z7vBMvjGcaFsiUL-{@afTTG@GTrpmLIg`?XKH}gLixhlEl?$2_UHm4Yxx_pHCm*%(; z77>3(D%8~Bs(S5Q1-Wb*$<@E<7+jLMVJ26hxiSs_k6{DDC@=rz8xw$m2UWvVY4)*!Z`P$mPfD#no$1+NI?sT9g zf*8wGX=Z=OEKGJ<=28p#Z@Ff@#ti|s=ivLCCS3SCD6ayy^MqV0-)j9tB~rdh5WIQv z$3Nex+iS&zMQMWG=tV1TJfXfxBE@0y(&kSldvM&C(VoB-O@DAq?rNvkMm8Q&)SR2Y zixeD@ORW?(wEIK-%KZ_C93p)z(JPnSN2tI`a>p2E{gfN8);D zWVI#r?Dc)10E~kbnNvBFPIt@xT#bCuB&Zq80o$0v1M?x^gebz$05sy}b_CEKaGU0b zR(m5@GJMRID{mnsB_+`kjevO>6u71H0E?EVezSnffQMLQz|yFv@yCzQt@^StWwI-V z!k;sljYa9P&lQaQ(2KrX@(9E1J>>jvuPv*q=z9eBaWQnB%AS24;>rB%eEhmPcj%{1Ak>(^| z;(ni$XqMLw;NkrR6d4`_)m1Nh zvajlqFIm}&sk0lmZ}uWYbhf{pXWRqewm21K>qNb4w)Yua=s*DU zXasMFM!8F?#!;Oihr_>3Akc3p3>=NHHlHOw`H%MRMVS~@ro&}xRL;!LDMb5*5ckD0#*IXG8( z(k4V$XXn`fvMM{H7ge|hZ%Ji)02YK|P_{8I#s?<;B=2VCy=oN5p4yK8-op|;>d^=Y z;5Iy%>lQ+pEn>u|Y|eeF0`_}$WpChxn!N@rC^vV|WXG1{+>Z~G0{6xyqHHaur~gn& z{Ndx%a#J}5q!Uaa3BL-N#X{3Z*PFBB)6+Vqb0cwaap;bpIwI)FEoU|?i{W<3G1Pl0 zs-E{cn{cehn97Nb`z3ST^9V0%TxA{tuI-O0Uqe*zLa)!yen#3R`oX(&wR6f7fCpgk zHX!r)%3f(+XpuLN5kXi^?{$^D3U5|OAf;wHh}_0tx~*W!!y&`cY6xp5se$yM`PatU z+O6M~Yd(6EkZcxZf4HIt0rb9;D4<7u<4>oSk@$t-QP>1Z}@{Azuomz*F_)J~X}c#!LhJLyZd%t4Vq}A@lc%Zv#0G z1hn>(W4OYZDrx$G8d?Rh?C$J_5e+fUehU>A_!BX4ul6JZq?pP1{><<-ZLdV0*yqUp zot@Z@AVMT9VBi1^QQJ)LwnD=<(s*x?p|!~55!b5k$)CarHDO0Lg9xl38^p5{W2hJM zAlsVR`r?GOzyJ{FdXHT}IgZ4sMIn4luUr8PXbgU)v9<0e+;WBmQgM(GSeikpEdYk- z`soys7hym*>kzL;+Ic$b)f?=J8IHR60gnhDE@l75fnpCMBbq0u&v5kLNXbYeLQX&A z@`QkL88BP*Y76pLuk?Ty-B*7KzNN^_Cl5kCb=mAY^N{*mrN%MP-j&_y4)j`o?hRw|s+*pE%ZP*C# zd}Brg#2>pmUz3+3zI9q&7Qh>?F}!>U;v31>Ctu90Xa!g?;>hi8$l82=F+n6{~s>P>fGU7f}48KWfV%?)L(P*&3_JWt6$! z;(&H_1?1Tz;BSs!S#6puHQqkSFL^HSgz__Y_MwzGnAxHVGt-!DstNQv(IG>ytHWZ1n$$^)r9rlT*sv`faa z9AY)?jMJ-G&ywY%(DHQzF&C+y-$Oq1QW7V7wx4)8*wLOu6*R0@DFmn?B;Vks5Se;m z7lYG%0J1xOdERiObsu$5geBniW(-Rpv@6(@f~Izwz@dJkKi&RY1O(MuWT~u z{5`Do=*EO59>T%9u_XLiG0ol_o=em(DLM$BRh;?-36G6rs%*JEJvc4MhB_qAr4CWv zdA&P;jWgf$a|andBm=4Oqv}|m&7z`hhH}1i>kb?E9W;<~Rb?Aohp|H(L<~2T1&`Gq zRLP<`my(k$%tx!I503EYh{m_FoFdv>_}H`i3-z1WocQh;A8IWqId5}qmF#gCO^j>J zV8D&zgPwm4BjSM<>c#_RjVWjZ`LR4?UGI30lS&8nLyd@^>Z-2y5O;aPW#mNY72!Us5DjcNZ++Hx#VtzSh*KV(L4{NDtGpl>>9A-hrLv0Q* zrWBCQj3%N+&&E_fC*QH|?=KjdUouSJ$E}zB3|GXH0Hbg6C&*usGQRT61OmpyCm?_2 zD#Ah-+Des_0h%$61Y0m5VBBZhe zBsrQfX~Rj;pMajwd1o1`L;iPb^W7)Ppk5I~d0n^wc?s3Sv`AlfWc`o{A+Nx+<$(-+ ziOD$`$UYhPhE3lm2AX>CBzBBxA=$QE@qXsgQ@=DowUT<~z?T*bWdY2Xsa|6(SrTJd zjU9(`Yx@5rdOVvybK2Q4PqYft0u_|4ZZgPFv&s+~eA2$`BxLt7;8E(JdOGX9`t*tH z`PVCp1nlu+Km#zSl>0*y1M)Vx_N$ekFb8MOF?0=@6LmhXLzU-z*REe4rfb7{Rm7e_ z07luH6eAcbyB0e$(%Wt38Pu-v4}%^|IyEc;rKGx zjwbJ8M*ON*uzd%9x6Z0%?|Cf?@r(x-B&p&yfbKxRCoBnbeI8Mf(mOO5nolQA4%Zux z&ejF#Ux`?^{^Phh5v$4j=Iz#PiD;7A>pYdbDsz{784D{SJ7$}D-V+Hv4MT4AjUz5I z#yxXFBYn!rNvJR}3@YL^b#+;wMSE?{+jm5L1sIe+904v$bUUwef?hltCHlcD^n>vg zY@42ydO=(dsv~0N&CO9^Fh%N9#>HEp$-yci!>=nXJbX)zAtJDV?-fQb`;ZYQTom#OadO>gdSP5S- zov{itJJ0YO)0YQsQ@!LNO3CM#{9T_GUr21c@f>i$uy35A2bdB^S`k;h9J88JnXz{m zYAnI;*lu6isN^XW7#%)`0t0PZ{`=x(5|_B|=bMm@F~+*{yH3Vzu49Sr@4Y zAvKm0IU@^^d0ciz@5?@48-T(Dr{EYPCh1V#FrwRgpZBvJlljo-1cm3)o;V+0wY?+m z_R3vKtjrbKdiD|}kb`qiMKBKD_bVco@e;|BetQR_FpIHzjp#RKslopC_JE@!p!VRP zh2BN-bkVRUM{`;x@t(@A&*;4TF*xN`Z^@L)?CWdnNT_!O6p9og_wH9N*{J&qc-M3R zATKDz^AOsYyp#2xo57yOs(4C;`qiyt7@ehy0uHofGVOMe@!}l(pqJAHjbZp?S0dPo# zhAZpgt&(esgKJ`h_mZ%``H`ef{Tt@zv_Sp3u^QK-{x-H+i%?L{G88u!E%UVK9@Ai?d)x6%XFC7bQXOFr-&;ek6OBt*zSr~n7D#^2HF99U)X9^kPC z6>{_)@-t+TwS3x4g830_!OY5gJs-X^%ca-8fbgLUP_I+L`^(U-L^_}y>;~ok><(|n zvlUhWoef38mvMwdOa~c#MOnC}x6KAqX@ra?SshcQBf(vLXqVctam&)4&Z5&%(L6@c zr1u$sbwbU`LuHKR{hTFXhFS*X{B6(vCIZw2?e+WBYEQ?{r5xna6K=Y>92n-FkXxNy zNW2$7Go9>}rDzj%ZPrmCF^o~d;kAdwX+0awl2h_8W_l|&o&R?X4yLoEv7$@VpDU_H zi}Owi)GGRO0tfTefrH26El#n$$%;a*w39Yc!CIMwIbxU1#)O7Gm!*N}*7*cjAgbP> zBQBt=QB$fjpC*2%2h7c417!d{uHmXSFJ=SG`@*iNKfiO>S{ulFNhkd8Yv13| ze~gjCO`nX?k8h|>8{hyki%Z0)05z^ZqDK6M-ebe4E9fsgiXs1sdf#Vw&!%Ya>{4vkxw1@-HKF&{ z{v3jT`}W9x4zsS7Iz$^s47W_T4C_5WLEs0P-3GB9Td>Ei4}uIp`ej@1jRueW2(V@8 zQYX-RyR}cFq=h_58F9nXl*57u<0QYlC`98Z32VVNkcadGQ|}OTw7yXfruJ?QOg9pU ziP6&eCX(FW54Q^Tg!cwwZ8oSzZUT*>&Bh-*$lGYC7c6&$?+YjXd|`#8r>D=%%y80$ zR}nlvXJ4!id@9hNc{!r>;RV$5sUt$)kW1qsu(r$lO}4%D2oJo<2fxua#c#u0Dy-)e z!OjLaiBwaG_p7{luY&S}Uc{-hOlYm{GaMyuub_C_dr+ccu9-#C{oIR44vp3BXt38! zTtKRD=Uw!qc(^m@Mh+nyA@9aorF;(cdSrjZqy(zaHuVd^bzWP?$*MyOQJ!5;+%>r# zeE=j1aoUkL!G%l*Ofz?Wr}wgxX?=HRUwt)*Kuo^aGCfzTLRebRyF1D>IEh;B{T)|H zbc1{iJ}5`-arWT_b+$;z_V-!|9+#sI7zBAGUjg^!-jkS~EDnC7zn7Yn5{p|awo=Pt z8~l&Tr<6wt(9$6u_qBbg^Wuu^(Fp*##6I*Xy_ig86tVIoA(*3zvSsKqFVHCa7 z<=3au{RtB#)!6#If3Kf`7ozMt2T^b4+?ylnsah!B3uKgg9B@3z6MSojalY?a3l^P& z9UqvC4nCKex5so_DrByYY$=6qm$N6GYN@?%c`Liww;ca~MS$AFeL z!~M~I*-vq=I)|sxrhmG;Ca)L0SfhFuSTWTyQ_|7(8Fv4T=kENN!L5UL&KSwc6?bD9 zSznVW?ic4JTfc7wJ9;SEoXXh?-zJQWP;hU|`=4rrCBOU1(%)~L+t!REfRV{-APqmu zX}@*GoF06}$S_QWi>KECi%S60*5-Y^^u%l|p9xi8AIF7ZHYJkVnHm0q853uqghUvz z+zaGNq+|IaQS2V+>JHbrvxRT|-PoV$$FXJFUg5emNzN!+UbKoyO? zl#&GuwcoonagsXPbs``{C_{xpxtwV&h`E7E@cYUQ)p2DVBy!D|#k#cUy%h5M7pN4L zl^Ofe4i21v1oE7@Dny_fbe6N6bdNUc#8BMuY}bgrU^?9J`u@$cw4F`*%3V3CNndq& zDjqNJxXPydpw!3Azi|+#PYnhI;SLAtf6Q`QAW*Kav}jwnD}2-1>}Sb7FzC@;6KB_H zV0#JM`ryB;TcidR(_N$vR;<6(AJDz(S_Cb*K!aPl=8<+FRDrK0k6b*WZ6r|^>bDeXI!DtH})O2Kg&({WD5>lNcN$XyFo zpB(}G9v`0X@p|pwz%@wyhs0M@p4UV8rd&t*(jAZaMA6)|Ub-lonhuI%Qawmu| z{*fjD;_)B4I951F%VPp~lr13)-7+S{yz{#0#sl_2U!Pb@ zA{gh!LNOEOTP!6f*h-7U^ajMogS99VUJZgAnpf3)|4LQak98@)PI2Q^-1F=Pl;eJp z-Z(mNol%Dm86^#;wUwN7Wtp^<%$>>jG8Vrj0wUB$dZwZfj|T~z5>pjq%=M16$9fhV zYx$f;Uyk8kR~jj3TXq*9+Q>iW*j^={M1EOS<(91fVxLYs~8s*>hr;%oR;?F<) zsSlC=cQ&V$zl(hy9JyYe!pk%@7T!%o&Zb;F`7TBw|wB^!$25|tQ7?tyj#o6 zv%CY8E%9I}-)=;*_Sf}pAA&T7#}U`8d0~JT5(-#97ULDTly-W&V&9>DFjqI^rQ5po z5-y~L9Qw;TM94Lw2#pfAk_-1TYvNm$X2!_7@7UIDOw^cHJ>pju2qJ?l^I#*X+ z^83?!SadRIuMQD9{7s?zdv1?r%v>=x5YdH*`B6i4Xo=W!;*x00C;C2!Q|dcGLyCm0 zhB*^nWSHzZcyy%)zE^7|-WpU#9t%}k?hUI}|5x}Qrf0|ff^S98Qot+2f}+BuxIPjL zRY9q@7uEe0!Bfo@-ToaYHcCvZ=a=@Yi4H&W&%Xhtfb=s%{Pj{wkxC$sbt!$l+9?CJ z$)jo1LN?iX~ z0#mf|#}Q-vv&;{-RXJz7LhZKTYhA*Z;;Z%CPQybrnR+Ep5BF$Et5Nt28ZR;9WYp2% zJ4vjX^!i*R@1C_)21yXRf}_u`R$n?^xn`*({AsSj;F{%KdmpeC3++ zp36OaIf5JJ%8V}O8@n~Z$;#Ub2L&>%7VJI@8;ZA58YO`J3HFWQuWGE}pfL2IfaV{W zC7wLc%E|y!tAc2 zC%24{e-PqY^M89}ZdQ`^hu8L?Yx{LTLrnn^pN+n=^RM5+>O`MEFR%GBYEfEP|NLG^ zr&3~GJNxeyC3yw7x~ygv+?{bTej>jymMIf2KMG`1%c9W^LzL9}Pta z<|b#!L7kr5VJ=8ym3u^Epj&RuWy($(@abmj^vM|qb?m17==*01)w*CCGp<0V<0wjb ze?px@dmP>C{dEj_#~lwR7fXJ@OGK@=1ak=i4u;@FW4deR)NoSXq8>;6J@ zEZXg_Ht`o)JT?r5YWmXj76jK)(^M}D1di|I!Ugl6#AYu6Zlxq(N3z7xpO?e>X$4mn z*LvT`-d=ra(P+59T|!_5ERk)(T=TiHLouQDjQKKWa`k*ynqBn%(Y-x`1I)UUc*ahh ze4+C5A#KdtOG^#aSgV20`56>T+w!ou>v!^Y#&mb6Z8N&Ja!&>~b}FR|f=xYj2UxDI zoucnxR(<9wKCM!EJQ77lUN6IZ`NGbhr9%A%$#KCil3L;OJbCxbPhnqp2DLKXb{{x^ zCykMijbm=-uAt-Cdd|3$LOyxrvmBENXfAImxtn-iY`|=avqG0I#Th|?i%n1n6XoG7 zs!0B1J!H+~6Hj!gJxErkLkqAh^%xru7eQ~Ys-{b&e`(EA?Dp^aE|OB{MTET-Sgbm^ zT4KPEmF46}{Soy1V$VaKON)<=cD{vWBjigXaztFGk1i8w%9`A@w9bAxFA%(>jVXXG zgP44G7tLySMKQraS5)2JJ1@-;@{X@y*oPTA#qwo;(O%Q_9R_;7mx2Fu_t^+Waavii-5ld2lP+9Z%%7 zr|z7l^9*(4e;z3G7I1kQ9rCm+Cb;#N%vy=yr z*H~jNWE2#+ux5x&2gR=$#6w>~H}S$l z|M|J!*XB*gi3&kRIhnVOS&Vu(hN&@!f?#0q-R6b6Un8u|zjp3D8d_F+w)MD(+1KR0YUKSjxW?UBFY9S~3k+yB^3isEswVP5 zQsf?|&R&h^ZYk&Q*zskitC=Jc?{01CL=_+grbx$PWSJ01Cek z1R&tFfwA8%ia>74)w^cO_4Tn)u>4CWc#EQjkBY;+Q@q?$d<(v7eqvNaljUs%QXXgs z6qM5znKX50N11V?iR;AMLW1WW-}Gn@UYy|4^$X;&TK6!sp6m))CUk>fYKh zqpIOsH3`S_n$QWez7%isym#|wq8Gd@%-JufkA#j-b-WkVoyo}Ba4n^*?1=d~n~*K0 z!~^4)o3v6gzI@O;AH4nCXamd5;Gwyu76hESGbm9JYt@iyl$Vnu&AgLE-tVCyf)C#r zwT_2HulL!Cbi%8xbYDGz$3)_jKR*KP>#Uj4zG!p?}JV?t>ZK?NMsSRZ1tVXLsym~vq%Tl`p zdMI&bmAHV~dbe7;bUb5}lN^lS4wfQt_MFQwx>C|pU~(#5EJnh@=|j#bxKdY;o`r|1 zDGxtI<-T!M8k@4@Wq*V@Iucdj==HGpsy%2m1VK!$Q3S2P8wdsxeprTy+NJsF7xSgC z!v(0c4Cq4DwftPLEo?Z@5rp@v9~NR|<@Uf4Lk~9Le%L1P*c#gX{Q=7i8;vDzm=MlTH|B7uuSh~>$?XRgXWC|Neqk!dTXX>3;3gnuT?jdc} zI}8TcP^+TMu3j>9G?y#O!einhB7MFK3oOQ%4oC2PtH*jD6TVE0K8JP^^(sVSGzi}X zuHg_TulXQp5`VCqpr34jSa6whRln1B?+jQ2P7IeMkB=m-R~dEFRZ9bCzVKk{{P-7jjzbz+{-@Xo;Uv(K8Mxz3#7K76DJ#zPYvRI8DL3T^Gg%> z-5AS;?h4R9QA_9+s>{kv#{Y5m0iOJup&IZ=mdAbe@(xp%TdAeiSak1TT zNjSS>viMj3`}f~3_Nc>-(gnEVa1Iu2^}$)y-S{}QE@wL4g>F%C*V*iQJ$eSKG6+AIokEA z-8OF!!a~n`3LdsnK&mu8eFB$c$IF^a;n60|w9PIHLVAg|D8YlhEIJ*&6{U zjdr-7*CWHMbTK{ZaG)$@=K9onm?IF6ttsd~n2#f-VB*Axea$wR3vgvrR=Vg+C>?t4 zuuo@dHKvV0wRQbCJ~h=V%cZewM1!Eh@6VfD%m&(m#p=aJW=2c(3bW|+utEhyh!8P0 zT{w}^bIEviqqCFuX|7C4^Uc~WO=jsE12h-!M6OP=TZcd>z9dkd!31+T2)Engc!6B~ zaj6t$`@XGKq~7xkN|?22JCI@&6VdPZtTL(wCPGqP(I;D4=3wE6n7X>UYRTsj!Xppr z!5~F;ktC7tG>>uqcP_#&yyBKRbm6VBG7`C38euALN9G;${iVJJ5q|HOT-2cb8PAD} zY^E&sd|Ch4oLEDA5o%5EBg~v9sMwS~BGr3fbafQ(S=atbZ%8;DeOS^UH0j?6{;4`S zK3*hOsqD_#HPZ%GeSPBL55FP74&nygM+L3jklulA@nkIMnH2?B%ocDbYed6%;)>ZLg{EIL{5C|8LR0wwR<+Y9a_Ac`}u?Dn|I&qr^D81IGbhak#*3iHgrt>gvco0~8< zA1rG*{|I}M17en}*JtuG=@cHep1Z(3^qtB}`N4Yqf^u(OFn=CoZ+_4xYLQ$Kh^k!y z-U9{GT&#d$ngm0B80_J#QWR=u=O&=-1SQAk-5tzgzw3$Oi^B+JwUGM z25b?H)i>??P;vYa9^@p3o(W{!@wPUR*CKJe8BHT&7#T4+Z8*>nRG4~FJUocJI+D&( zj9k8z@R%Fcvu3@EoahNXW5RQGH((-FlK!3JA+QiiV<@@Rq0eNSP2M{L zos+O=zylI6L(_R-CXm*ML4II#f&Af)*KWIYt}MazTCeGW6Od5D$Rs7p^wckN^YReA zQYm_mNLTru&yWv(f3V(K9lZ!_4h{jWK1fz>?OW?o&(8VmV7$U-yuW!)i>R5|;W;!V zej?|1*tFmrvcA54M@I)eD!2Qsori#GI4TWWIZDe%y+1uet)~yZewwjP7%52pjmkk1 zssA(CYM|J-lKEkim-04=;j3Mcew@jhwF7qVy8`OEuIj*lw3VYT9zIT{VKi8zo54z$ z(PL3qh5HYCr@Z_=w>>i5OcH=W%^2qDr50k8(q34qzoUpe&p`L)4HVp=>|fz471vwF zLEJhDzCbK$4Z@;{)oq0_2Rf1k0GOa6OKNO1$(-GniVhtw)nDB)iFP3!RFdPrSpO-f zLC6ej#$Y*a@v&}n5*AplRCp2dzU}oc*s3TAp+NJhW0aLrpt>ew-!h{p(4~_nD@|eFRY~i5ch+xnBQ)k86bg!#9u!yHZgqZQU~S#{o*Qy~tG}-{hbx&B)CgPa*gIsfiT{eB^j&2==T;Ob zX9pws$_tNv@c?dpEfl zoy~RdedymP-p-aQ+E^9}ZO+}KAGKTe>$fr>|G=7L2)E;2Spil)pxG}c&|dM?Fn~eL z>!_u3cLF>xuy8YF0(ZLmwjylvR*T7wi$r+cHfJ);a47h8>ut#zf50uO=P{dHUUY>L zD(-PTqGHFz!U9Gh=JalE5pl*+bNqZ|_H^)Qrc2M%ors#3*m{@dW0!10LYXYQika<7 za`81rL;hXqwgRIb|hf)6?}BE zj-4@PkLCWYwUq#yO;qtP^Iq2H9!{at&Z{wDItHP!dR4*rqU%vQGmI0aeb`u=;bABd(;btnsPfq(`=?1%1NHK|@pvO^z0Ltqg>_@K`RlY_cn!@?2KFllhw*M1yye?@q=`(jpR zjBJ+N<2X=CTY{?16cl}qTJB1Ro|WXQlApCs`k0=pTF)n7;kf96a(6{dgHT`3Z4C*= zPuJu!pGSm{lV4w`*40;=b$7M%&l6ymVwOT(mBG88pi3*sKj7$maq>B(7Bu@)nMkU* zS4M{tZu!1=GNHOA{~JfIY;gvnm(U=~+^4R9MBko2@p#uS0E7+fERAm_Vc)&~{&AxP zYPDVM9HmO%A}dp~3<6Opc`p+>!{UCcyRSxzd%cR1IPsMU2tfW~+(aZv^a#%nf(dlG z{zPBj7`fdsEV^Qh<+P6t#x6YvPkIt=OxLRytk@7KspHEz@aF01A)8aIWiitrm ziGDP@<~I_T*H~i!V4ZG9pRN_SEhk58Er;_)+nT)YY2&b%AF%(_2WA)w7aIpPvM_f-lCijE8`;N9C8N*lyc zO$3CxdNUL-6{X&94k37L^rf$9;I-3I0d!AV9%7;DToGfV5dZv-$h2mZ=grLLLhgV~QX$a=EFxsR)(A&8vdd?JRV_>|oon`C?Mjs=1nj8t|Jy zw5K$uDv*xOavPmI2q(MHOQ$G~tY30v+)3`dC?+JvLw&+fr=vqxhY9!?(j*CCy2(z;F z4mA4X^c<$8ne=Aa-L9#~-EpC%2xP#yEq*@p3ViM+K6a;o%mvc6~WP#yZvU5<| zcGv4TZcqHItmc{&HrDjVgXCrOpF7v)8_=gFqGAtg&(p)6uAc>09{PEOo1|%zD+5}2 zJJSR6W76f1q`e+vsE#FV0DpUsVJ?&3p4h0X%Y&|*a$g9>lEA|6zdZ~as<_FqT|Df& zHfE<2F^F0NF8$Qm@9mPt;c7Zowv%28PP$^>vAqj`ljkEJnwx6`BHDxJ731e`9`u`d zJU#o9kbI%~VyYeAIOv{j4tRKYfMm+#NMygw+dOJAp#~;I&*cu&~JCLO&DU`zZW@ zp;w`}0u~71=I$dp_QSih8D_#oN-$)qqHk0^T~LL7E%d#5Tu8u(_;I|6$UIpRJ{=j) zhK29XW>oeyc!tGIU~>S*>uRYss*m^Q=%`||_R+xsL)x1s+3*yo|2#>ffyR+g3ZKGUWya2(k~z<1WHa%91EaTR+umvigW%}8qV8U?3g5TN}| zq{=bQUZw*kZPHk3D7#D4WJVQ!Jf0ziR#!kNo!e(hf_Tm^tKxG4j21-uF@<35cKxk_ zQO?wPHRv>1vh&1+;stpZ{y5m=#>-$*T#RNupMd>X(_8=;o-=JT6@dLgi` z|Ev4h#yebk%tD9Yy1v?BVelIsaI49#jxn4hajipHCmkX!hVsl2O$Vsr0|8s6l6C}y ze$v_Mg57<5??kz+01rs#N$4W6pG_pl5~j0xY>yxBfDi})D#Noj@n8VpLpt zh6Z_FbLS&g*S)waAHpK_>0uFLgM9pL_{R{k1JOG2nDiJtdn|cBa#d zHjMf|uO)OjArTR9wPR{Q%#U*Ym?}WXi~sxg^}TJ=X^_QUB~6rmm7+Ki`>nVu0O|;y z_$4iE;#)c|Wez28%AN-$Mz)?X0Bfv?cu$}guW(3?sWwdD3lDh5ps`P4p*Ql0IvTxD zPEQ_FpJ#PD>{r{1V%T03>l#8hsc}<zz?VF{2lSb(HqIe8=^ zxLDg3!ARGp028E+>=^Y@0OZfYT&7D1`H;G5B0=6$^WHncCR#;fawuf2~}2BF3gjrcjFB_r^0^^COSfXVp0FJ zI>IG)Ba>+#I7r#ISD)U_jeiZN?KaN-EH>6g<^?_&Eb9_jZiyziVxQMhb<5xFHv}?c z!gExeZLUimh~M0PT4SU*hCSV=10e6%6A_9pZyM-DX#`9;iY$@SwP?qF!&4#ao}O?r zWozN~*HY)!3EF>q2zYHEn*dzY*Oy2b@t0UzUh(DINAtlF+o;#nXthP{XPV`Qq^xvl zBf>^r;uy(L8vG?Ht5fdtHHVOMybs0xk7_xvueS{X4Zu$Dwer$ zZ1$I1xI6elU#S$V?$UMO)L)0Xyz^Ys6q}0yUdF_Z1*fv9I;_)a^_MIdoj9(3EPTRX zXD?Q;QHgj~VtMt=IU;rg0ubSc&ehz$o((B!2;tZU;sJaW9}Zw_z@|A&lcr#F1L3Nx zvQ7yF*LwKU<0Hq#sL87jLI68$^t=J`s$x?jvx&t>NE6@0aS(qknk?^==+|;rR3O(u zF+Ood_V@@u*8sX)h|TK*GOAde)veTWW2}yjy58%%HE)FDjaapE=p{FUx!ZU6yDJ_r zfL#fL!6&b+{mdp6yxq<`(2`BmQ>)pK^ZPsP1YznkSB%(DillTW$gNxM`q4F8$;Wc2 zUO*Et#tm#FYwGIi>gnkLiv#(Hhwhe|^G(M4#P)I>RV9zjXjy<6-ky@H`+n)y9&xJ( zi1N_>P;ryz7F$0)!?FsdyLz<^sM4O{H6S3*yTP&QfOQ1QGn`*;aF#8o;Y+Lb<{zRx zIV}{JKInc7_uI1ENA7v0?XI=F1|3h>QUVUh&*w`uwd1?V;vf_{q97M&{_^A5nLuuN zzv$K)7*0Wx8LUbYWt0mJ6}j*X*{Ptrm&892kL4-&W{2J?+sm^VF30K|-=C?KckIXY zf3({J$J<69B3iYc4O!no?NW=)S`Qit=R8O%099&14WPc7oX_0c-G`ER){c&r7B{Mh zTvz~F`tNHq+0N{=0>^ht8^hS$eC5OPvtK6Or$j3<(p&Jc?R=+(VFaBJ)gOdTe?9O| z%r(Y@4G!U+vZM=F6P{_tqHuol^fYC@x zjfkdlT7Ey5C8*r(tMO(F+}tg)bM}M4ub;#g(kqcG%5+!CrHQdRD(e&TItDuo_Pf$H zWIJSOx||w+n;)vS{F))_t7bO$)iWn(xxeokJCyA@!^8VFoXn|BtGK35{MjrJjz1%OXuXpL1 zZr{4~+ZhD~wne>BYs3e+FoqzgyvYz3LhPFX^z#ZFIWX6NSxENA0^$FhHKV3jL_d;9 z@9&si%d+$CgJIT ztNp!5=Ius-#)DBKM?mEPr3-4jX*q{241BSaj#4^X&av{%E%BIti9oDs4B(P&1RsCL zZV9GY>Q=HVRu3&V3vKHjs{&O;Ba8y;Jw-5nWt4lMMhaPRqi@!Te3aFJ0MCU;+d9=UQrr+ZE5EVFn41k$0YUg^ zbjV-}ma=LRRN7Fl@}@u%^SeiG7$MrLqX#`INIrzkfTa=C@rRg}^>CUsx+5=|ZgOT= z^7FUn2rMn@T<}s-IO$7Z{x$b%0G?)m3gtSbj{uOQ05hzpqy!9WPncS+Gn)HM44$Es z|DIq);Km}(yCCiK zRJ0`PE(lp^j5j%jyPZWARrUsp8d|yzHr<>_ zuS=B{_ffAnZ4AcNvqg$Nh*jhFeE6qf_78BnTU#y^9NM{DB|oI_Y1buv9bxM^#fr5^ zy3=HGH>2<7f@;s;#yrj%jV_pzAqRnns})lxTk?UMu7Cs24Cpu2b1)bf0E?J|Icd-P zk*ygc3r!sfy?e6_UAF4tt?DUlY0%vZ3ArD}Ituzfnb^(`nzAoQm;3GQzMupkr^Yup z{M>ZU8pD_kB%&Z$VVcJg5zx(+3Qi|f zQ~L)O%biZ5XDYK5^BGX~5l#R8WGUt+)(^dugaKLv&H8WILX>KihM^yO%F8O7ZT)pn z{}ZG~Jw9u(7@>n|85C(~B>m`Yo2R^vtHV^NMEZ@V@4(KVW;oPqhwjrbw_v3hV>~~=jZ*=C#0NVa{tc!U(qrpz zC5zDYsVz0wUZ)+hW$@npa;+Tn|WNJ)72n8=`k&y#K7>{3za9 zQr$?mzul+&QrGBDD4#U$zrkZ%Sv1l)d^y`PIQ;_ZxXpg=h{mIzy}u&W$;rF7hCH7h zuH*!6vO-bJ9iKDOor7W}Wn~WA&5zC6t=20Y?O;{|%!YxR=zsIlnfZDU%%1LjZMTLy zKaSJJ8Vr)stNVQIJ4SFk`?~es`_6u3uYL@GVq_+-Fe-|uKyv^fy=oW>qX_}6q>_(j zAx(MD><>@wZ<1OLJf4OGRxKGKNQ+udQ<}vLKPM;!@lxdxytnKvh7ZM$_m zXBEdYHlOEwwkZQN6*CoIfg>XpYkxxfo($i73-phQz6ydw1U zjX*k;YL3gmpQ!syUBZF3XzYl!pM3zn5G$kjBtxJ?&p^ zk6NetDosw^2;?GF33Wy< zn}3MrxLNDXAeNb5mdf=uc~nF{iB7yTZ`p40z6+zzE5@vwGA?_lumx^;hm9CkE%^%h ztpEIUjZ-)K-n-U(+<_7ftO$V`>9Br_JjZ^Igctr+X@c0<*%>?o@L)I{l$V$HY&83~ z5&icF-$TLZtundZASn9$1COpBJyDQi$<3F-vrE&8ihbPw!u~TTKSl!(B1_k&OO;~2 zlsc0N{nC;K4w@x<3D{67vO-LPwCuFSVjs|=>_cm$L5DE-8=m9vQcG3P3kWn%FIxas zpdW+GPcCESp6t&T)p!?u4ZCKcHf}8-#VDj@^*h}>`HuZq&8-d6Ry&NpX)FI;E!;Ox z|K8S;qrT!kX3#K|${nu+)D)Ncf|r29L8m<@cs`)yo?E(* z_8$qF>(F>tt!F{8IbGEMWSU32+AQ>f+S47c? zRe6MvN`@;hk$w3a~ z_;`N<^e)+L$?R2tAO%n&x3{+*;N(R2yn^{VIC_3>^l_S94LV@WXMBbPIuorD$S(iT zsnw#VdWOa7_}A9{ZE?KuZ*BE-B^b4d9$!svHbg&o$N*-IEx{7G2rbhcqW$#o*&Xj9JIlcvn^ zc{18Ip$PzVG~-ME$ZRx;>{sY}_t*ZGecr9^Qa$5rG8``W=HcGZ$M#f{qf12rCuM{> zZ^q8>(MphC5Uc?+u4anB2~Lr;c=3aAp8M%%AP=vr)XmNI_lACMIse^*Qi__U1$d%i{5w#yD8>jB8L-+ld2 zQ_xnoT?p`%g^YN0HlDkisobUezlfiE1TzeH&;D`1KUSYGO~qAdDJ;2Q%y-DQkl+K(9w@y=D zRn-wl8uLFD^pd-p|A~5YpcTgOzXxg!>$jJyYc|LIJY}d5C*tK`D=DM&M zWv(h(_q0$#gAH5j{I9F(gy>L?Nt=RUxTsqFhz`NG-h(4Wk6KsZ5>qbEJ6~p$>VBCC&JJKOGL+0al^HM-js1-D#BaLUOw7;E*J`j+ z*V98I>0Kq&%K1-B$?^r+F+|`VQ{&85rZ=R0xgB)Aua@SDO2YC5I;^ifO1U13Rg|e2B-@$@{2>@}$nKn&}&xU9<=_ zkSeG{iwgv(rK+Xc99%s^Lr35e4b>fPPB#FniA>>&&Gz!BH-^DcOkDg4L`=)g!vkCH z|LjGAi6q*B4T8(LkSw~#-N0y>^BF{UhIKnBUsITk-DnuP8OrKl)6z)6l_T4_?@reV zcwIyub&Pa&FX1tvwxft1-%7eU&^ZWx=Wx_BMg1(M!gRO!`@NHEm5D$LPY?NFar_D+ zmaY{0YX^YZwmb2u4d$1D!ANfThshp6KB}szguC-}`5l=^(y2HWyvlw#BaY)dMqbfN zc6Phl^Bs-i$y4(Uko+LQ`hc;)7bDvR-!(NMzRgOG0YhPON{(HyVS^mF#!q8AyCMD$WbYS7#ykn|`^u7?Sb?tKB8nyTcA7FFqJzM5)ysa2eFQYmJ$OYuf{U3#C z>vW@^zPcxU6FDmc$r}KH1IuA90LyMDWx8suI6gjpqjaQwH&<%qd3=)5-N*m(^2B*D z^bG^U#EzYSfB-ZUTyZGh1AB?K*wdragT0Yy^IuqX#Ou@3)7Nq-sA+Pk0y^#&U?voR zPUdnsV+1u1&cf&aAawV6i;T1_gb0j!vvSv#JXuVzuL#L8fB;y6qI)#E?n;~6Ocbx- z!&1_i*!2o7$PX`=z!ImFuM6zLBj=VE56nKV1(%Bgjto>rirK`<(30(xz#{?6Zu;VhYvODm&&Kj^|@v15~CqlM485jH+)oY53qf zH5x5TV2DY=lGXD@s!qOYiAjc-ubIvIZEtS_u)pPE)6JNiAOPs-b&9&cpl|5ky&|O( zvK;Tz^|)I}WE!$}jgEGah7COFu9F1({{Hd~$6NEbu~bj}0phy4<*igI+!{xYnrD^g z_XzQE(~EM0UP$13h9<;p|^t;3=2;j)R+N+rzl(RBHW>^J*^5=jbTuaXRTrD zS1NJC&=+#Vlm^bN2~JmDboJs4pNXfczYuWKTHfqENggMHHI{v_`u6^f*4pF$LqT}Vd6CE4nnT$s;+8B#A&Uq z7zHURjbPeNH?}8>n+wZ%p2-S-176oA@O@wH23FSy=(^j(PnC{KHZockq-~yDiIL2m z@K7|y3$81W>S7hMgRIZvnHCVWYrE$vkmRdS9v}-!iI>Ll3x4s zSK*Ws>#t$qME*H@X!6Y3O8HFgreNuDHNV9?wDOJRE3)BWRxEw`XAbLFscZ;+HNCaE zwA`vNQfHkkmCO<|JUiL#YOJLmYIy?^jl1G=Vs+#6?-p7vsMiQ5=LdcQ4yWtCQ#~J@frx$T<@GTo?ps=lCmeL*2-?sa)uyA!67jOAdv-U)TbxKqIz9;R@T2!#E`RyU^vN*?O~TmU5_f6#n5&sAO>m2r z0W$a5Ab|k!U$~{lqzA!x{Lo&+S;?&e0NVu|}A zC#I2*=8=3T5&!<~w+~?$^!nrg;aIe~QqD&kTiZDx9t6@a_xy-}d2;K>r{h1s(tUVcCt*QgjKG>Bh^D1ZWif0s?@r4pYJ8xDF@>jnyfg$VfdCDIuY@I2Hrr1mHs9tQDgo7lFH`;F-1D1>a^jFFmdduhml=)-ZldckBjJ9J_4~Ef7`0F znkP`Ge+bPb5A<;5g+L)#_#~fQD%&r->3G$;!q*C4(3IFc<)EG(X6aET__t@2XUAc^(TOS zLO|yXI6Qq3KAIGsWtcRirFmu0o+b%+edK8o=yRjB8tSO18vA@Sd_2`+m~^axl6yeg zL0D&ocLS+=;V=8X<*-^yA#|m@+>kOMc%{d??8E2nVX<^kf_lHIvQzxpVWW_-uI5D+ zo^uIg+=N;BDd93&w-Ev+cDMi^qt23yI9P>`(A@>AuR~~GYvcZ0o~g?vK{y$?E)bk% zq{t;Q?w9pX*o41KhNrYT5~2I~@GgA$Mx3_tiJ`tc)<&cr-;9w`LV+%O5^D6Je|!A{ zy%sV)3JIqWZIvU3!^Y{8$bTcq(fv;*QBQ0$iJI&j-yTFol(zF_Yc?$Yw z_e=8fBnu~8TwTwc_(0#t$OT4#|NFO`1>rt6#?3=@NDv;!CP7$0>CJaqtEQ>)NxCY6 zO*|l7rZ2L-vd{baXi0j{jMP{=lwT zxcTHUR-;dy+2kT(NTm&X4Tz-izGxbL0YPgz&>|Jae4o5lV{F4go44QLXVr3J2xP!9 zIqsnTnX9qTtTY?|`kM8lAzWM@>eC31Yzn58cVp49!b%>V2P9S6Byr4I(?#Jou;?gf zE~-_pY@}H6I@2bm+OxaKAdNpB#; z9Y!=>=%8Ay^b4X+bQm^xN1hGMuhQ`n%ifPQ4#@u$Wq>JXZ)f3z9b(DN=K0V;(v*@)(6cHo3&mErr=|yWXr0I(M za8Yco1}wX|#wub&cp5*SV}_s~3XIjO9Pz%NrFoCVPk%#;J!>-%%?uFNu?d8puY

|t(2e+W0FzSz6+1dHco%^*f2KZww0e2!mUUv;c0*0;fe*}Qpc)m;M(hrLv_lT)~++M&G2~K zvMqG+>VnXJ%pw)@=@}UC5Mf_L{sNv#17T!f?E)H#)AD zz*TKFdr8{Efuy|{hVj#ek%X9EisLE!0Aif>IrtmHm$&APVFaF?8921BEX0v~tceyH z9gil9H5C*_h6JC?ziQ~~zwlBnQ~|C{6UrtI;^dykL!JSnxCtuD5fl^^P0z&r7pJSA;IPuP6LLr4OCc z7l>XO;SY{xRm1OuJ(M@LKvxF>8o>-j7Hlgb|DKV|W+NG570M_C8gqmJlp*Kv^n!kl zj?|fi8ybZe!Y~kampuFHEqs6T&giCwya-Cf3;|~UoxWJ6DP#IYtNn>W)mTO?ulNJeKZDQ0K?ewF^Wu2g;#6OXxu?oYfU31vp(f z^vELuP9-co%*8J^?<8DniKPA?Rc{#xSQxAQtnXHJ#y;f zU@_V^*rNjEPSS~j_O6xZ^AmqP;+MKkPtNz5@mc9O%Lo6a-ZS?!QEaTW6`J82c9Zgx zyngN4^QF#YS`^CV--T`wCK>#xsbbwk`B7{r|B_N=wS{-aBd^xt-7CL*RX7k&lqDKg zTwDyixF-9nfyp|QTBT8l%0Mg@CsBbCf&i`aUOc4=kxb8U%3v_DRZ@1`wj0|KIvRh3 zy^sNWK$Cz6^!5_#WTSos8gq@!D|cr$N=f$%4==Zh+c9L-LKo$&SX>_~B#j)MoJYlJM@vlr{>0~LZniIr1=7hh|lrhezPf84+L zahXH$-GIXGNtb=FXL&66kd2g~%t5ykR~V&{5G+!kleN~L64WkkJR&aff_DFIgQZ~PrP!pBa%(XXh26$rAWEH+ts*{ay4 z56nkb{Q(ydhK^59N=Z&bMVkT|WpQe~o9eWf@zb(nHQjNV{SxF7(lB31yanvaTZ#(g zdUFf@)twWe43X=yWUO2elsl|XlLiI+BQYade`eJL4QWG?=4~ZKL4u?MUcmLPH&kgE#F$RE99RH zD2Ll>8d8AUFFyl>?3RGZ_!Zn7bHacZz{x>0L#ykl!JB&SB3e$BbbY?q zCKvtPG(%7=!oBl0NIh|I{1TQAy0o~rxlV8{gsMxwJdtx<##`O`ee)+(r{UK&^YYSgjwY9gekBXjtcRhifM-{j|?TlkeZZ|3?R&U#giXs7W}r zHX#R zTV}VI_vgy=F)sZcoq>TjJMSL;Jdk63{-}DVER7Zr!v!*+Pu=zaAXlp0G}S+t;eBU5 zS8WaftWjdk7Nk;0za=}jCEl_ODpG?kh5DsCxASgoZ3USqnl%=aXPX1;wo6v#a{$F} z0~1l7r`v6yh@#V|&L2S7mo^Sqz3}MdqppG2r)MGQzcUPC-fkr2V7urF49ECTE$o?^a`RIWci0FlKPSATD$7#l{X(A2ula61F~6E@)=O$%ed#ln zP+^xbc4h0B|K#J4uBJua+N5`yZ<~j{nWPHY_?v+L#IwVizvQdGDS^r_B=(o54p@K# zxK1+y(@zlp&Ah#(O2 zL8f>F2@#QH_yEkUw3Wm-zB#I!AQoHn9=LFDu`DJ@#K-q4O`XLC;%tI^ckGywjoo5U3_C%; z#(F>?+(vsIc8Yt-Kv7j=6-7_UGN?Um?F9O+Ipa~)VCkuA%eQIx>#|L~3Tl?*Ae}KS zKf&sDGe4)?2Wc2vK5}VZa&v!K=T-KvSNl92d5-`aq(eqB(_+C=0r3D~kuOgzt6+`- z7@4Vutb>B1Nb3V?rgoDv_@wa;x8>!G#8Il9%bF#tcJ150ijiU{*8jer@Fwu25cyZb ztuYx?%yf?&jsRb-D(?=8^zNKye47=W5O7T58PI-t^U}iL16Cop;+H{yW`7(_+tZz; z)OfC3##1LMztv)+6R_Aq#%Fz5A3=(I*|v+Sd8e5H`dX?Q-&?&g&A5zCfO+QO5JkN` zW8Jim7p_)tpzMM|y^hr!8O#U_BkQ|2Ju?0C*Ewrbs{kt?9@CbNeEQ)xRzl{`7-3YT zWM&=MWVu-A#(W)?{zqx^dg{>$Y_s+XIaZO}HM#NsZa{|t6e~DIJ ze{W9%I90hsiHai!AzMl@<%dFFCaQcTyERi#_^5oye_uyOl;vy1`ESp>Ch@*m1;K#c zV1q>QKXFh}ezOO0fg51<&|Z_I)2N#eKK z*5cdLcwe!QWc^gDWQ%t#kQqcl@ddsfZry>+ExLXNqLH_Ohc+dTjhys|$4ecMlP9VXKQeJ?vCr=#w<=~K9XDQH*RH)cJ3+Rd`kq`;w+6|~fBk0G-!i74>d zXncbD(GHSIA;=!2LO#v0o3*gzKhx@uFHLgg5#X>ia&2T(Rotrs9<9jB6A+gazPLf+ zm6ni@0J_jP<0(RfojIrd0>w_qS1>21f)cO%{F8KHV3jRnG{QvQ(yD!ZjUlfS`6;H{ z#TGerJg5F|+e=w3@)2AzV28T7HEe`ZWjTY|Q;i3e2BW%?)<52Dd{V;#Sq=^6GyhOJ zFF1CepSDs!HIYh%iGa7wb3Vud)Z+)~ydJF}WE%XjIFhE=8jP-e+z10Vk=FP8?vvVD zP)Q$Z%G|tvY+-mVp4dle(3cXwOUdO668XpG@V$!c$>cPCAPfc0lR0A!xZ0CJPkvhX66Ct`i?RH&^#oEyob z_=3<~;dI8uFh>B7j7>wf^2?wXRImVzhmXnckPO6;hc`TSC?nHf(2sJ9aOaQ?+{d^Z z=^2;ver!XpghCCWzII#rft>>J)q!q{*w@z_EBv9m)enPTk~?wn7*vLD!e3K8`amuy-U_2_XdL&FgFhiJabnBG(@&hz*3Zv%SOJaWvR+ zYny?YnW30`l&>Hm&1R#?zW{r+z|g9qY(RQ<d-)PghDZxF2(Ps+ z`63SE(?xPqL7nhD*A^E#8HJ#+m##SHkmAew%Bjqj>$YC>CmBys|6f zZ!5g<3WxDbM58wWJ^eeeaJ6RFQxMIlhJ7XIu^Nb@QEg@qsDywTWc}w=Q1?5O{#z)Q zI26+=J9>EbGcvkh4b&PG$=qtd@ysbB5#48nY@zU|aUJ%AN(mgfZ%@zpm&T;}+#e3n`t_Q0G8Rijx(2 zn=o%VEhZ{S%QNhmzj71xe)>tj$wNF+1HLeHScDegNNcoxpN=srj^*Lq*0(mm(_h^W zGa0f%Kf@bUq1jD)Do^>htvz!$nDjcRHB@K5LUt3G9uuC8pmU1ynD8b+Wy`yA-!R7s;09#~cMUjnyM&e$M#O_J?1C za&RE7z49p$l639zc&HAZajoLFzHg^c{;Lu8-`if_dEQ{maSP9(^dK!1S^g#ea_|bm zbQrL=JXF_7d%2iEtt<{OOC8{~PlFLj$aw|`UsLM5D2KpY)}p2nbhCh20pg`mHY{j) zB4bc9nZL5BX%&}DLASTO9pv@{`Odl(LL|t8-z{<=bVJufMPsC!~&zzs^N?JTheMOUqUDHn?ge^b1jKAG! zz!^xV;Fpf0Gxg*mghdEynWj~i5$KrtEh|d*1j=}Lh`3NmacjFeq}5M1eGq5ZT1keX z!(&5sV#C(xS3COer9OB=QxG$TkHalK*4XYSBP`3>-Z;Asc|yU`?gz8|)>AyOOAj)Q zvJY%e>*}am&QhenMY=f=20Za&KSIcVl_fEVC_8SsPLF%dl@~Ja*e~17nT3DCwzXw1*q@?XP zLZB>!hbPdrYq&J4`ROQvYtGzUhx49V)A33&EAa+9V>x#Q={f49u1|orWmNM|1kEvm zOYY3XNSwhqddbPO%+64{>+3!C^(9n>Pto!B*Qo*((ilHwR4b}=iImO6vDsv5ZerHC z>MU@L`%i~Bw}jn1S}CQtJ1xVU8SxSgePI$|^EEEK7hfx3OM-X54$UjGTf0AHb-Q!{QclK`jaRdbgIVfH&JP-9WHT|6M_0H;c z3^(Wgil>dfdZ`r1iTox-1O2UtC+pSnN1|&RUJ*3HqJEhl+A~M9p>5$%-#jxigKNrThQA4t>eDKOR6ad31CHsH(LtbWVH88*SB(!~HN_C7lok{7v+) zDrPpO>?X4{n6O%%v zLcj>Eu4a{@SUtaeX-(H|KnMTQotBvpi#uGj^U4IdxTt0;{Wat_dbX{#Zyxh_c4a&0 zzQOiaakEyTgt#t`m&qm3PsP9q`CV)6xQ##yXdnjT2){Jf+qJ8_f+$t=I^glz!bj%Y zX6icaVir-&_0B&I+F#M77B3c(fnwNZNOYms6qnts|G3P{f65XXBNs8{k}0DdNak#} zT3}K`MBYN8p`op)$;_vRmoZ?|b=2F-Q=dLwUzO%AIbLOW0i-wUE;=U0JUKEfZ2kQ9 zsx;@QS1GaaxUJ@}T2PMQ0-{hWUToi~JBd|B5i^$S!4rK5dXy~N8L{-4@7P~|{)Z|8 zgkNTEM{WzGU4Sx=&kpfY_l@cBni~X~9a9O52K=OZ%?o~&6csh{BJT$POx?1#W{yJ3 z`7k#aih0%y>uI$Rzj^bw+09YP5fD}Q@3=s3`wtVDzQX}8T-7qESs4CkQ=_?VyKTy% zS|x`e0Z*5IhKFn`W?-;r+I)^frc8k`eMsk{4-2Am_ru`DXFPoWdMngx%Qv8^@ub|p zMpcT|^jn$v{u>dOLfRrq4QGdIZM3a09grdbeV&jPp)BdG;s!P*Eu8fAf97!Tfp(-|I%QBIl@dK z7&Vog%3yhakCOs_#0Bl$5@|kspGdRrh3~JDqZ%(yNIW0$Q$GgrX#)Zb1g>A5w;7%h z+~@T8WOF?1oNB6T1yP7=!0L+>f#Dk;fC197PKMac=CSAY>hzpGmZrhH&(?s ziCh!8(Uq6-m@JVx^aXc>P#>R6XQ_B7^>L@;u(NG(k&{t~&H^=Yg^Q1doqk57Y17%k zk7mIxdEwBg&NW54|Hp;;V+iPq;Kaql#k~Q&@Jv&DGwI=1S!ZYGVNKv-a@eSP zeg4TYpAP7z0gUi_$^~C$$?%?&3c)sJsFNgb?3Z*WV`-d}o_=6cQB5op{ulxaY9dPI z4e?riNP|b~cS5y2&Rw4m;&EIL>3*lOckfiqIPFXqET^ZDOVNq=x6HVlmyGx>^ajXF zct)!1QKjU{J~#{4pWBjZ{QgPO?QU?sy?(v?BhC7lYmXf#67q$Q^dW9wUR!@1=a-*@ zRtzIQ!>tk}p=?i81OUV%*J;N^6Kgq|XdihrNjF??l1VnJ#>&veszs{hN)p5YKqK%$ zCi!CJH*k$^^aR!@SEZZg0Aa3U2KH+Cx^3P#3_7U*vneYpvv=~ev9Z~ly9KgG@VXEK zJ62Zo&L>a71-KS$ahD=o07t=`S!efob(UOK+f~=w(5LURr7PiidvQyYKyJWrbq2aw zqE^ZaX1z6`TDC;BkBTkfaLd|zVv z>TJJEo?72459=pdo~$4>?AMc%#)5%Uj&=SFu%Z4aGP2nn&)1c;AQo`Z(*_GmrVV zKGSs!6M~PMX#dbuwNA?I{C!8FYpsCUfcd2RL8}bZbq^!lk%lOrS#swDZopw-gdpY0 zP<*1##DBOBo0$6s_ou&=y`T4GBIENtt+n-&cP(2dUrGW5BGQ%+=Yp8TOz+ zAmcMWO!-V8GBl%MVZpXbu7AeK`wywXv0U+9gH-xhtzG!~JTj@YQ-FotE@7GHl>lz1 zop_!#AeckVc zka-8Iy?1tt{4Lw~>pfw;ES48IiHyHiW}-w*>jIFHd(J;1kFe=UiVa}a; z))**x206d?8B`okUw0v_C6*b*$`o#@z543b_g^NmG3m1Ncgt_K5f`jQ#%HSFb8-L# z3TDE({}6>>95ggW*AqQW6S03)&$Kh>dw>}ta}t0IOjb()t?000j;m_vtDnP7)AZEs zeiea2@1)5u){=TRw6FPiokVGo`Zc=PVEiY{gp2e`EF!wk$R8e+nB69|WuSl?KO#3f zJD_t_Eo!2~@!x~^`nCCVDbYF%APX-Qi@p7UiHWInbW^BM0Hy)pQB+XCmFqC60x&L+ z6ag4hPjBVcz#dO^@DgDQp^H$i!b3ze)X<%Ub0g4AblYb#4ts+{V{`si=K6%K){~nM z+X3^HW72T1vcbWhM@BZ|qd$k09JENbzGcISk>`)UJm=aJzSvkk{f^UTC}ZTLrV>?1 z#^5VfR~lx#u^U$k>L&Fry@-i<-&0sM80>KE`PqFNcbc1ZZHNSqqWLe>qLyu6)d1X4 zPn6+`01T}DiQX%%1NyLtf73pxdbe{EaJn2XwH#_oc&W~|FD?a6P<3M|#M$^vCK#yS zI~Bxit8@J^eAhN83VmIrj^y8;x<41KRqB#YnyAmxBKxyO2MfGSL-h)SuAjoee+*6m z@_e8zmDWEpl4s6EN}8$S61(cq&~0-DVs9#0d*Y4HKuHfCK)GS}@fgT)+u{zWTJ#bM zrX8GlV6z_OpJ6UgU!#&&E_-Y8`Fm`1`y>A#%>s>qVvtjRDPcV{E`FGks=PsMJ$Js3 z!Pu=Xxcrd-O{Hgid1I%W26wb~7Epu?G*)el$CaklS4-JfVuS}rc4GPKW1H?B<&`#i zGw`nUL(jTnBWrZ@d5t`A2f#@PJ6c6CSJT-Q2Iy57A7+}8-T#Ac+JM-q7L?xlok1?g zOEoTZmuXCPE(LH$5Y=!+;!=tDzh(yS95-dd8+<)1m?1t}`Q4I{p$jj- z+js)79s*Pl+ZH5S`yq5o=4o}&1Ekwz*;so z&l@<(h$Gf~7nx!t#bjLS{`vQ}2BvRXP?a5NAq4OYJ!{)iChPiiEy<{q4Xvu~8%-;| zj?$4!bR7lo!?jjPU{=vLl3>T1p}&wx)%JY84+wy`{4x`sU;i7d`X9UBzLgn=g@wfw z_OuA(>;l3U$LEJzeqg_`; z4VDULjmBd)fo;B0Awc&~2suWVHYaNCFzQu9I#*#p_Y3;p=W}u7e(PD>AOq3nr^BH@ zA~SzJj~=UxS_Y;MUQsQb$_&)B`b&3}N(f)q`_Q}_WUVavPOt$nP_imxr2Q%6{q*$~ zi3U+3V_MfWBWL4jVHNDr6q}6k-s;iYl-yj2il-OSAHPZdf22R*R=rfl3SI+kCOcq* z`9r1X^7M4|RLh>EFhNIXy}RBK-sdSqRj0z`<0a~U(_1UHCV-d&2Lf>ihqHOxHfwOe zmi-csDxBN{7dnqjo09m(Z_yC9y3=4Nj9iv0{sN^hHZQpn0-Ze{OUGoi`hCT0xg_>k zL%DkdJ`3fxr(ML5z4CLN=ppg(1T|0)G6DE^CII2j7p%5FPLJuH^H47Byv-3DHVRLx zwilaSv)ugVdOztL-s7J*_k|%y6?f%IyD(^xv({mpQhQXacI9fx4*MPaz=Z=VnkipuQAoqC#cwDonn)4cQ`AKK-k!i_iV($gAf7Hg zJsn72QNp$DiI}?bRiZAxlj(xN4FqPYnr6EF?>nO!;#D0v#pEh|qy-Y2wA7=cUY`5(fcFxuwh0|D-ciT$DY z#W$!8Rx3+nFb8uD(n#oj+tH5)xGvHqW-G*r& zyd|r1WE5#$e#6DA&n3UhhXb;}E`jb{Y(lFxuat$ZiXQbM0u)vfdQvGJ9H*%_TlcI8 zVQJrZ++ao5en96B*tgwgoufC#w^X82}W4{`hOGuA@(b6K!7%8vpY^XtkDZ}VWraSww~NAediJKo4N5? z%a-0sreBx7-gn(>QtRA9A0LS&7f(r*Ad5<0n}_>yJ3_mdK3Cj6P$CTAbx*=xv-qSS z00tlXKL(%YB4d*{9ggZTo{uu;TBq7a3G$AB*C5Y434C7De;0fasc(}L{k$9;L|8}u zlwHx7nm?35m)VMT%=Q<|?J7JttU8o2_Y!d>Q|#qxJf^V!kSquzQ&R#Lm*>5rvSe2K zT_^v@`A(wtL<=1ypxS_5&x4f5S*T;BQ2MroavS{lyr1>v;MLN6r`@+)%RM{rf^2}r_M8g=%c z0ZotA9~6bXGaO=N(SS|6H@_=$zK+RAF?@S0rqpLo(p{(yyfKH6pYKT&6c4o}y#T?- zk5o%^xz%gd>Iy`i4D|Pd+QaM1$%?pf0&i}cvP|(*GmkA0ETBW$$h3fL3w8su>X=&+ju4defwI_hxCC1wExKO1syayi!CcC6gW0P#ph(s6vIypFa7#Le`Ens-Awxh)?NqP%4gFd8 zwPHs6T?muiG<9}4T0QqZf(zhN5DGQKugbe^ZKi6U3w%Zvdl)=DVaY(F?=VW3KMzY< zcjhm$4++t$sxZfJa5&JGY!UqT&0pYkb~)B9RI3ISbJu!oyXo_nkd-}21)(i z*_EU8zDED+yV`Hr>-dYu3I2ZTv{`g9A1K#;}SO>AI}zO*@`Zf{?qQGy*JVq+7T z?Bs;dIhweqt@P59>?du@z^P+;!rai70#S%OUYDyWYJW|pFDMC|6 zzZ^G_btmOK9cOui?1k42eb+j&<`MhQB$ed27=Lbt+{@6}^r=9pLh?eFDn(^y2 zl(@8pJMW}Eeva|~^_A}j(mEk3|8uFK;CS?-lr>MBN>sRkr&ldpQIRO9%$$;lj|yPb zT#|0(uQFKTIHzHMGyP=n?&DZJtTkJmd1jj?-@dU{Rx}xb69v+6c`YmO3WD+7UDJVv z2K~$K->&iTb3mGFXlMZAs4M!s*3sQB;*o@qqjk2rFWMkl1e!bjVRS+%cn#EwQ*CeU z9-g}lcl;dun}%suCzN)9^*7^+0cR>kEI>b;F%pXbb3;jKTGdckc19DUKp_LoYJY2_+FBvR{!o>fBR8FR!|BS9{ODuA!ca7O|n+}>OSEfXDhjPNAMvH#i zp#dBU03Fvcn?yK0m5}TJPNZz-D)^;=#XvsS5qRR-4450EtX?~#WFFHBQ7`CHc6Rnl z+q}98#)VHaw4P(|$1Xu%p=FiZ$dwxk?i`YCIo7FdRly7tA!3$NhQ@~2FA(mCNP-^^ z9J&i37;3GAgt9T}RXn`BhuShNE380K!$6(;rE)i`;~U$~W}z{|ckfDX|fUU+0f*0Y|(q zjazU0beXnA*(b&ec8LKz6y;(&mxy++E^{MHmhk-nW56!)%@v08IYOWP?deAV@95#X z+4v|fv$?%J&PoJE3;iWNU)G&&M^Vf!|U2>oi8}kXc)Kqn1lGo2`G<5Y`_z z1y2bM$1rCMcRVWqVv$u+{tsh!wgc=$Mt}Q`@X~K5ggNU$C+t_U+ZhUf@sRv3`wt@eb@b>jm@V57$`{ z;m8Z0`0+4&)71#0niUS3Lu6EcG7l^)5>zwrv;ZA}5pjLSNYJp}z6P5q&>{{f#z1^C zz&qOcc4KC;AIt$Zn(4)oM{ln{lQZxw29p zIg5X#sF$<zkyty<6``XpRM9{P((M>MY<^`TNxey3?PygCY!FXmN2UkA zsk1(~_wYE~p}P!bLaFKB_~WSz*RyW#c&n@f|MCF_!(9d74a`wW#MyM^B8PT~AY(X5 z?fJwR8cIx%Fz_Qi(y#}3p#v2}u}0u`H14<^q-1tmVnV{yn3$O4WPAbw%VURwvj19e zLXC2n(5EENsKq|-jwlPc)E^bE2W-4le! zG8ud{N(GU_fFW1&c!|Si8`Q)NBFCn`$eF8th?88^@@@K@|LWNJPZJTD>bea&xv{*( zZ~foX$Ul}|VfjLl)8#!@cwat0UAIk4OaL!$j|3~9gmZa<`_X-530cR*_D7MRO%L2^ zGQ)M;7D;-m1t5M-yf~Q_d^9P)shK&H{3R~PiIB+EqQo3@*3HqXF|c8-rxIOLP1L=4 z$U1}``nwueDyOr7mi&XEIzPvq=zao)eDB3}F_rYl0voKrpA*{~$cRCTn^%ByH&;4* z${}-ImHhDwrGdfs>_9tle~uL1}}DFSk&op>UI0|cUpx1*T;95cnvNKfrtp0)kX&gVAl=-oK%z9 zY5;B!HlBz3mTwM@g#-Z!3H*v%7{KJB9s zBh7=-^#5BHUSzi&dGnSZJSBw>VPth%7tBM+%)aR-nC?oUjcH5tubP$DT!d(!X-}i6 zc3my~yKaT;-5O9g$EW{zB?SGK8Iwv7nu6JmF~UBY%&QZ8nxjScZ@LMe!?%;h2VQ&3 z^7C$c;1-FMs{w|tZCiwB*vVc|cwL27;5t8+Fxs&GQgdjvHfj5`?mHTw*3|=Axb%oP z8vE0?vZ-I0h=zOHGX+6lm~9J6No7$ufc0^Ji?jr^%YO20r)E1NeX-VtO*ibdjPXOf z)VM6cM2-y^UA+#{7}Rb2GUFQ?v`bFyi7^*;Zc*Fbti#&FT^SXMKf(pjdo zeSXt*_)e>A1@Je4mRf<0ogC}EcsG^0SmR(h}n#@h5f z!{O}2FK+({L;I&Zld9%>MFRn)M>U9L@dL6-GU)h z{D_M$xXYd|7ER_fbo>1=OWvWFw>KDR11gk1q~$cQFTc5)QjZuWr=)yw6$C&szsHr; zNIIxOB6&ZNM+49m@I1fliIip+j#7nF*+qSV=%Q}%8q8F#tdHU~FJNC$pm%4>Z$daM zlIUxe9;`Pkv=5988P>1S#snv0OKfsz6d%;r<2G^m??9>-rNv_h&j>i1FZ_#O67NJ_ zk6J)*0;5cdxT(3%{+m24l5qHvMHDUuaJgPARnMsfgAMdAM6uI>P%`X+w(Woi;i4Lc z5PLk=)!CuAb9F69!2CTt>O4nTb%#x9-f|BHf(xoz=mS{*ZE-5Y9dSY>=Ku)vjyM(DB+JOqI9a+R4Hw7EfeKs#h?0tgRb zG*=+P+=*RVUoX>bOHWNbSo8G&XQIq_i~HqUn#ZC)i71XdkBgle@uoUdO)hiI;ad34--I542^xvL`K!nel=< zPn}ld-h+_+spbqB9IGnGf|W1 zcIvtJN4<(MXHlL~6%9XrvGX;4Be$AiPPY}=ZHeIuRLbi$^|-N=a$pVI#SF6^Ekt_X z0Dv%Mo6sDFKc^Slub}INn8Y!AvEb}@x(Gi*sAB#>59LfZC{<wIUpb?Yr_p^GuU-VGGj z0TFA1BwTFHy8t$}<8<6wd2kaET`ejD9Ww9xI7#zl?65A{c&TId_{7A-*w|`|$wKq- zT+kmKc?Y&0A*t%dHEW`tnp>9i1i!t^1eSV3ehlL%yru0u$i`8{N7D%d%xsa+GQmhs z3*;U-GYjnjyKyZTK(AP!TMdtPImK3H3b!{9`el>Z`cr8wxwx*%sgNo?OY2lGvr`Ui z<6kJ{(k@9#l#KONfKIN~-`kOtM*3JKHM`(;6)a*$a5ccNfpJ2b7BZ*ec)BDgz#c-i zTHglx08(uZe)w#N6(+oUsh@lq%tUU|5=={>-2VJvW{jpl`JOKB0xj2n$B z?SrYYSQPOiP~9@IK37cgVzN=$^hEti3`&N3|7HZT*qYhl(2YLdNBFzv%t( z?mzG50w-oH`t3DmvcJZZ<9 zNwlV@vI&3gUQW$gHIG(D_E-J7Fp!YM>&7bRD=#;+5GP3Ae%TS!|1;d+yM-xT92@4U zG%5dku{#c|RyTo_Vk?MpA&d<3cCaPz<8>j{jMP>%Bkd^KlG{gX3|jqSB8qqq)V{_z zwN*Fi;Ea){wUlvoaQ0S6xA#3JA-Xz4AZSAi+wZ=P0;+$_WWCWsX&{B8O`7gyrtz3o zyA`r>$p}4Zxf|H9USO?>G{5MLe>Z=&PSkCD#)a>IC9LS}pZfqvECe!3k4CzW{-ve& zb)7Fv8T^RufdMH}Qp<0&AlP(Ej{mV5Y+9f|p?&LjtBydimDN`JI*XW!zSI@Od$KO? zua>n&zrjVaI}EnY0AZyaW52{>qN7te?56STR*2bjMcrS!TE$wDG~v^5MI(KUl)X8F z`Iv>(VSNwz#rROTJxjXGOkK;@^p_3j8URa??@*V?Ei4S?$TaD$&n&D;Ia<@ox0koF z<#tT=1wQMT{QrA&l>KOL`8)bk*wDZLSaQEu^8pXaA+V#w^W@EtKl*4O?BGISE1#P> zzv6vczCjLQhA_@jCj$vwhUy-^im5CqxL*g5n{!gCY=G>~8P~KfEG585$osx0nWGV? zM3G>I^+wy=SC)RP|2@|F`v&*8j(WSLejI})563`X!k>xnFdbX`Ue0g%L3CLAK*+f@ z!kLB677)rAQ!S<{2RGOB-JOn_+G3_$|HVB8 z+-^W(c%Ut-{o+M1LvX*!1?6u&9eo!}uu!g+sdf3b;sX#MdjdC302y4-XV((S^mJgz zTYN5s)oWyV0|7nV2{x(6_)S_JuqIP{lR?^|Jv;v)_UV?)q6lMakHp=Fku#6 zNr#0#d?49Qyzk2^ZU$%UE|BJ?;axkl`um^@WJ3VYx}@L$ z_nm5H-7?ySHX9i0QF#960@L+IZ-Jh~Xhc6c*-R%3ZS$Ws#%EpXcV`A(ZcOBLv}qg5 zQTS@=A4b5beH&B-i&7~NVqnkX2@dt7`P^^Gmmim<`Vi!Z`NI5Zo-`F@fSpzZ-@{4g zi%BUcjc&jY=;7f3yveke9&9G1&ZP^nVH3WaSebKZJ_Y7T4g{*cC?&x#y~XF*TS+Mv z@Gd@46KxUy?h8f@)mU4$F7~ObfVhC$0S#s6DZJWWRH9y$_;@D-!&eKUOs{8eMiUuQ zfbWG3dNRjlPT1F(E19xFD?fMFvy0W)kXQ+T|!N6=Q9Bg9H2k; z0Haml0)vXn*bdfc&y92a2VVu%m~G6nvDsSZblF`MNC&Lm`8E;zdvNS#|NfRyJObKI zb;ZOZ;xV?H+q;{uC|#?LK=7%nk{`3Z4;HCtD_ER-T0~`ZeRNXX(4kN=sx5$0v*r$K z4+@N*i8Kgn-=H|a0;T*;gTRUcru>$x_eE@>2C)3s_FGrx$yx9~%@WvBJ#lsI?y$P8 z9Xag$9o`8y9eIjf54oa>dY;HbT3{u_9w9)A_&j4aLn;=;Eg)oiydvxo=UBx!T z&k$Mf@p<`pk-Gc`IG;V?{->g^k(yi^c&6d03h8o;!f%T+aNI8*P6nnZ>#jGDOdr;% z`$`BLlTW)Ml6|hq?30@9KJkLbCWiZxiYO{*t0BI}# zMNK0q9lu)+@Ecg{(3rjHHuy*!`yK8``CVI~RYGE7z0dO#(2L5ZumPX$PVi!hUI4E& z2`OO*hpuNMW(YI{CKvj8Ef5F9v>mM;-m|mT6^avQOP;Re>De3u3&_6Vj|8(0J4oO2 z2)`5Ns|}-pTLE}y(YEXl@0se4+PC<<>v_oftKav@PTjTEUK{IBUIVVfKbSejGs)m} z%GD3;8=3TEayCRzIvZw}B-EpXoKo2uU$tqt5l?d~q4nBb2fgTr>c88zb*1zEGppN} z718{T+4%=h<#B*b!A9?o@jST~l;UMEo3@2AC%B)xw33I;bCB1~=;AHl@_MAy z$a}rRJ6qJ{sPe%w%#oR`1(p<)%-vyJ@8}V=->v)(6pHY3kQg9S6x2l=y0%P})u}MF z*kpF2i9y!LVe*`g=LugAa}0-U>An%7FK|fW38T^D4`1Ot;)`nC`d4glW(n*!P0#tQ zopc7#HC=bg&t(qGTsT*u%K2BCAG70gr2DdK@NG`JcyFl29lBp1ErMGZ{P4Cj<*SP> z%QY^XPQl=}{cMSVV0S_q9rGhLAUyoJJB3YD2x@Jeh7V+=BD%PM4(0Fr?7Vl(m7(KL zPaa)i#Jm^4WbfCcY}0yNtb|<0@5ic2ndL@bW3-4Bi$YQde{2?@85f7Giy2Hnl;A5 z``q^x=XsnVQq~+2{Dyy7C2ZI4J88vv7Jh-eMvfM?gIS=Dc zG%bN+3|5GlND5_qDXu+&mNn;F;F<)E3Di$1di9aP5b9HuD`{#ww8QkbX9GvE?O0m3?2Qsivds=zRr(khATB?bN89Q*N-B1 z+KH*kcC+eauTk_a=dr6{HlJj{tK} z@1}A=snb=FvF!#i5-j7FV$E0FY^cDO1(E}435iPgQ@cthLgvH=&E1LRNv)HwGl8?> z8?}B>8D6%lNKa<;ShqEIR$y}tR`V)Nh8yaAargBMnp#9k*=q^dCb-=U;`5{h3!YA4&FFOpIK20}fn7##6zxg%;s$T1hU63FI9fbONfuJ;4mXa1G)T zHOC6)XTSR*t5Oy7d03T#O2Q!sFqj;UFG?%J6Dz}`Z@U_PR8GlK5O>5dZ4Q>tRz_4k zzvZ)~QwkUuez?Z-&-lS@@^1%AJUg96wm=pER!;>5-2PiyN7sUTRs!!Ce*K*pIv=iK zmGeQ}8rqu=W^QR|0ZpUDOwHxthz{(x9p58fw0rb?EgKVP{^@$XUD#8|j^5 zZ5e0E9`mAhEpzqJpBQ?KO{+NSPM|+Atm-eFaZkaadp{I;^;xOBacyZ|LFJ*2ta@-aqR&Ef_f8<9Opf+knR?E zwI1q0u@vgZrLOnFjekrYgPc^)`NPy*OP(|%O_&a>H`w*c91Mjz5HL)xZ{bi(bOmoN z-|V<_sVkPeDx}_T9)oYGx~t67YU8AB>K^dnf{q6b!GF{K!W?UO$@0i-gGPg1@q6m* zgdGpSUD-fS2{mBk05X9>-!MiTIVA! z?*07jK(=~uT~?}I_k-0#Vpd2w)180ylR`(`eeOm}SaT>T!M>J-*UEU*r%!LOCWS6` zUb>C!DVA!LjXvo+Vf>Q+gLXYUK0=>!{N0OhIHU#hhcS0P>EMS49|?P-?R9_;kL5Of zo282x9#pRWZAy%Fc8V);B;~Q0$($hPYEZWm5ndL%zpV;&S2-BwHIP7=K8)fFQtYI$ zB4e3Y^hufIhWX~Vg+Dz7UNI%@C@Day5%7I5{I|A-38#OjfgSGZU_d63)ADSis0WNA zh!G%Gu!z1+=Nr-ZOp;B*$?{dafS&o;`rNMhwK4%`=xta_B?teo3XnQsZ={+SvRd|j zvnDp|rN68UJv43I@ebo7O5tZ*^(!rzWLO6bg~S`6zy#zpoCL+NrW~&0=nQo%Dq+Cs zm_Jx9sohXC=_>fHcQPHb)-<>%xZCPzn^%4Ghjp}0b!jTS4Gw%~@*^IJbtiIdkC&K( zWWo(t)Q}aXMahFP_pH66!+NqDxeoFzZS~F1c?byzfUAf5Tvk>V#*o;m)*-Q5pmT98E<^Nq5}!(6TBh8i zjY(7U&oYYNV5DHdc@8%}D7(Wd4NHAm3PzrKuI*THjHb~)t#SMvLv`WMY(wqM#Rui2?gXjR-zD)Rk%AQ>a@iM;;%C*%e10i2hB|r3z zi_yR+{)wD&Kwrj}5&a{Jre;{Bh`o4-C6S(<4ucF3-Bng z%-l4(&*qHX1`4ybcj%i!@=dHQnI%^sY{4)~_MK7GMuRnDjo9KU_Hfx!=c$`C0NrZ5 z6h|3!0BEG^(;DyucVYak4V%qcJ-I6IM0)tW7jSbvgfnnS<(1qpzo|iKfcYN%$C*8e z1|=2<_Qz!kZoKpQmianahmT?GJcLB&4WF+O8C0d;kFccsN(A@)>k^xibIwV}MVK7^@irBcj?k$qYT*-*d-sAL) z)T{G{A@1((y+kI!fvbcLV3pHAOL)_zRE$NQF z0={mMAbz4ojFWmnWa0zXUhW=zNxt6?sr!S7TSECVG2%(eopEwE)4>L@<|8B2oXiK7 zrc@83ZTSaSwbZWmF8-pS;nk6#_lJ?1Wi(Zd8fDk*uLjq6vOjKR4BMkV zT+@A-VtnIS4o8g_x!ZJ|MB(8>%Q7qF9mP0?{7~XWzF77xCiaA_x&+O5L$U zunU9XHZpeFaxK2ck6~asxN+2u?|(c4IZ30X*yl%c;~a}CFEe~pLw0OnXuTBM_uEm* zQ{)B`SQ~9%gbKgVRm|^|5jW$aw30K~JTV93TIoj^Js0WimGNa>A5ZZtB;+yD*tqKs z9mv)n+``Dbd^mO^!p-jpB-aw#4~|`zU82g8xVm%cE4bGj0ZowW16g+|M;nHDhLtGus&jaeRYZ05X zi*rCl<<3{5>tUxq^P8^S=f5(Dht+?~g8;|{CrItdd@!{{%*JRTqVwT}&Zo%>0|Ntx zLNF;Q$$hrY=iuO=eHXa(C;xoCe~)Tyy*>W4p%pEPMz{Z~S(V6_I)BX7smft9JGKdc+}jB>t< zV|Ybqlv6F)YeXR3a%bOOw9IL?cpGyKCtdr6Ra&>3%4kFPtnW$Oji{4SZ90lNm}->0#Qq#n@y9D;#_i+UYy>! zm&j_^jzA1too~Ye3eZ23@N}8r>E=skE2i+fumZDA{j$1FAx1SfPBK*(rgrURd zGU=_W5mC>Ohbus{+jY@1oJZVU-b9{WRLS$x3cpv;8dNs!el{iY z39Lexmj(%E^@;o$Z|=Oer=@>k%Yu62jUfV{f(yOMPx2xdl%l$37~BruQTDHziY7wA}T+nEu86rU(MCdLSB z?09n`OIGn~G+0^Sk+CruSr24l2QQ&}u%q5M*a}t1+S%(Ets#3EFj`63+PJXmdazmu z7wXGEoN7oNIbvFQ{n-?(SaCbTePdni8(vFvXhGf9`Iw_rV>*TFF$ z9KPCZ;UgZMm>yxc>n>Rto!Vv>SywITS8F{tvQA5D%$*}HT9)mU_;i zh9_|1bnV<+2ZE|VX&NWwdrF)9P)L6t6-l=-#>KxZZUj?P?1bGSxG%4M;jO>gh)ME8 z3eZq|6lQVH2r77h7dcYi?T}y}b+0cVM(gYhSaO;55R7P4FC=kw0M_ze%^z`-7 zuu1SKC}!Zl_|zfC>M*GyA?djLsA$()*UmK)ZEAg5cr7kI3ae*%`AEP6bC!l>s3z@< zD9>p3p|K~IcqD+)dCW=)t?nxeSw?C7Y~hzaAx`l^?i8u{H~E(tql1mOb1$Y!x|L>oGolw?e`z?(;rTq{=a=9- z=*0o#>KNoMC+W+*m7JZNym@;>JQG)d0C5vv)qm-&Wyy5%RY`6|DP@k*aU_Y|Pb=do zJ22zr?Bradrgnptp6ysghdTcJp18O;(x=Z&y|H;%OA*`+=Xf=T#lTFZ_pvjHsFBv*x+j ze{@*38)PPIK>)YFXn)FCk6JhH*3wz?RyJ0SaR3vGoHS2dLfh9y8_G;rmVAr84IUv! zWy!9I-vk+AFLQ5t*FA?=NnYoGTA}t1+jT;xt)_UkUb8|o0;{QpFtS+Q-kA}I(!e-DX(dwmt|^|tXxD_<0E^CXxMA4 zEg39&#gERPj(N8(_yw=_g*e*9SI%ritdpIz&+8FXRv>mf(Q!E|r zc}MqlD1v)-97&hntc(QZoAzU#5G63&0*?sk z&fU9(W<&H0Y=~uNTpW5DkY`$ma01d!oiU0O zjgC+(-f^hNRz_lbKIq0v?YPtmON_h$gG-i-zDh5RQ#^VyU$Qy70VdwSxyt=aKi^s6 z6q$0-7|>yC5uSy#^%afb+%MN@YaH|-=rFc(?i#^2M!AE^jMvq5#g3f_u~t|j0BH;_7OvrsUH(eZ~ZbSL3)~cRNy{{;?wCbFt}oK*;|BBm(TOJ z0yeQ7OV-tggx+AIj;x#F4HYdyIE~>v95#lI^}aDL(;nAH8-7Sy%GuiIE2vgJT>d0I zzu$xWw*E%d9tKDS*WDLno&xZPxLhWlwRyTkRY6wP28I++!NXR?*uX$B46~^(rE6Y< zWfyWHN-N6_qdqK5)A3i-@bCXBoG6cuzePepqyPFw+w1%6`+;Sk${DcLm7Hl%AO(p7 zmX90Zw3&w3($MEB`KsFO+CU}4*ehA1YjgKa@;=egkP444tShedyA;UffhDZBwwmeT zG!ema%f>^U!-9=5*m3hD%RSDW1~R26$X-iHRfCf$x(prl1_k0P6`BNucOHRQE~znH zjA!GvzlG%Mm#bPfol8U`)xb4V_qJ|rNVP2A3DaJbH(8n{s&LFgM`vY?Tnm#%I_U)B zC&>AnHU_g5V2K4o>sJDiIsw#Ajh#qSt*bl(!P@96K@z07FP(c<`d z8!vtRM?bHUfm1Wia~1lVb$3}e`Zx3oUm91l6%b`^Hb(Q)I+`4GHidIT~DHJbCT zf7MpQ@?O|gH4cAB?KD#_8>r?fdgqV?YMzF_ibh-3HMbL5cIJ+l{;)K)wkqH|9<0jc zDR<-)94)SHs}${BT=nPSx+la+fu+ETa?H(x){0 zv5TqJ3tp{jy#TV-hMy|_c3oGi`R(8rm3JOUvcc`~7$4A(GOsa0uImKbjw z=LhOKA1`0ZAsbl4w;*(Ch`_g`*BzVA#itrHvy$3kMJKkxO{7bB- zI$nA2Sj;|~KDlqNkU2YHEj$1PozT^X@tXUy4nX0ke~XTV<*;WgZ|)0S4s@G@jH*8k z+VI45P{ao*Q9^rgGGrq!-%c1H%@yR&qp?FY9USjf9>LEG;ntyGBJ6UQcH;_Rm<&zK zWIeKRhG^x+hIVAwmmf{ttg=*(gKA^x-LsjI$#(=V6MUB3rTo#;yCZU+H|!Q$P8>za z#3hE^Pv&>As|YUZ{?R!p7J~Gg)mh{H`}a*vP0*GC@+ea*ocxFh4XMAsA7nn)fJI(h zG>Fd8Qwm5-gu`wsMB^^>GXc#x;`L(14GEY-qin5@eiy+u^yU*!rk--urNu{o<2;ch z+IXGWl3(0MIesUr2=wk^X(?Os2`(Ayx@OG-3t49Z!EXZ2pX9Kr{rOneF8Cr*B>YmZ z2V08h991122t1tCuC+3~i>gZjufZ^1AZ_%Uc*&T=#Kfp5NL3{FuyofA`5P)Fj&Eql zZ9Tk#>HQpug5uoC&s4S?m|bgmin2 zgSCF|=_n~2!w%b>ngPMp=XV^zwEceJHWpU#G_gcR-=G@H;mAs=UplC&AKRB{y?F5g zlo9H<-dp0AK#^->Z(VYZr`=sx$$Tp^TCKg*49Ienc!6C&ISy{nAwS}n~m)l&fuH#Q7%_mBlTy}9d#hkDDb<{&i?ZNzlimG2C8M4 zq3EncSa2~%Wvnwl5*)wH)lL0@R}>^zHro3uD3tM)o1k`u5lQst&j={)?~C71U_yV% z=@e4&ZnySu8EiW+Gz||Ar{K1ED=tnDTW9s)u~VyW#?YTh9`c$mFA0q-TsvA$AKP;g zJ$x01u4aeW*ZCsY)*Nm8HbSvVVkH9A3h^;sNvc13iHN2y&v^Wl55Wfu!Aw7Qljxt8 zUIokL{fWu}g#{94A{lTT@bL{SBjs<$W3k@1vyX^s+<8GS;wiYdPvNE_j;>x7@B+Dn z1Zi?|){x}&GfbTPcXFyHs5244QR0s&876b}0nBJV`~&i=J0OqgpRqNLt_*CrdEQ5M zlJf8gA>ZM#Bh%0N{H9sOnJ`IH%=QGP?3|eMQYJbo{^KZ{Rf(AiHY>1M2(b)iQ{#50 zh_#Ez@UCZccDC-7#=plbBNan_%CxFBAm9j56qxU}&nk)euF!#)LXKWl8C_iYE$~NEiE%nBluO7o6=>EwxoNwHZ1kY+m*->qYniNP2Juf5@S7it<1j{L zJ@&^@GqGFsWO@7z{YMV&$3Q5%03m&yp}S3a*^uh= zT}9i)5E>#-^l29A`B!&PZTzj=FQ=B9(K!zg&c!=US{<@Wi*Dl;x$^6}hxER>xQSst z-le+EajiN5-^>IXYk?p!GbqWx-;J6HQ{Z9mqZ>#;pNUTx*o`P~QO=*VD@0MFsoa8~ z8C$8^iBJ`UP*ny*PpESn&~ZgPLjKe_g#ltUAS{!?bq`CWmjPJWq0G7#9UzHK`utf@ zQ`6#sLD3kr$!q}|peK|mGF)G&W;wE+j1|s6>k;bDn(9D0(d$T5l>c$d+C8;$1yga0 z=+!{{L{`rJHfPd7?CWdW425{;LL{?fFH8x`-8i?}<}pCu)*nr1!+$9imeNt5M&qcc zT|#U!N#9h#nAFu0&2Ms`)QRimsMNlaXIjl^e$HO7-1BRy+VYg%OhDQQrazP)T>Y9~ zyrm?bh*LbWDXP|*YZOqKUH)Slnk@cJ9tp_f)BfC%a3w)L%pt%Al0eE_Tl<$9ZSEn{ zitc*tpXuE~)^&QF$!8F}2T|a>m$A0$6|eB`QS`d)eU>(9s`AL(f2%p2uM$ICOb@^u zaxRn|#~7~$kEv%rS+3r2K)KLV$z`IGV*6$1K-9M9BaK*(;lhkN|H~~;ye0*N9=6>3 zbYEC5PAJu2OX-ccIJeV=s=T~B_N^`XY=khdt*s5Fdp&>te18xg7RDK{0i4tQU%SGG zIXgTjwv;rRq6t_g{Su>JRidqJG0h1skB-`}VHX6&Z(lS)=H-dm!Ndd|PUG}zc)E&# zvOj4D#5h3YCf1lAlo*JZl3Kg*uURNxVoYMT+fw7Uvf8lTqt3}$QNcrP4RVw26uKx; zW@?*0eGO(43zyh#ZwVeH8Hm^UDa6byi*G`LaTDv-PYcx>>J>kyCMr1@?4=F-&+nOx z{aW%yMnSY@plIldX9HpB9VgkG`lOeiW&~5bY^Y&l96Hf3ui-{3=DHCWX$GX2Ol;}Ix6k(Wv&RoRlkN4=r{XzaS^KTsY(;Q z#xD7Vuxuppmz!&Bp1%=nY!yAdc^Ex`-{}%&3h&0JuRhoi21`>)sM~p6qK~KH-e>=} z@iqHf{X@tY*<_~$*VAV%wYj2cI!%TFDM3MA!x9eYk0vUkr!spz^KCLy-W^SQp` zRr0)q*IBXG(BkUcdAUvq?e_2NLT&I?1N^V5I@gAiHGTsopheCECI1`|tmIvjrXfT|6a$QyIZ^7|G3C1$KoPmfe~0bDYDekBrFp^~jYYd@QESsT7chgJEJ zkj^&ij?~3kda2l7>~bx|K9*&9CI`uC#@yh|t$Umfwr4GcK-x~64mv$~sDJEr&v57> z{xO7I1%LeLgKhcz#J$GW$iTpWOi@Xn*RkRH3JqzcM}@51oW0!rJ`ycP@()98)JMM> zF58-#n;jug2wEKQgafPd7o5IpgI~@^ouNCe$)M}BvF@FAN9h#n`-itmJowEsS?r|P z>o9{H=Vz{L=+DxIshc;Pk@UwYd9Z2BC+P_JzR!e!Y02)`^Y6eG0sj@<&~yED4)@6- zrjEy&=;5spsZh!ac?#dMvPP76N_-LL@SEi>6cOENeh7l}HrQGowQz#=1rZPptfnvu zq3M{i#ib=+hw$_8xQyg$@$e8Nv#K&G8*0GoSBZ)0G`dpbfqvym@Pzzr2Zv?{S}JzQ zR_&!PZH`{k#@vfKM*HxT6Qbabou_cpf43(d*5V{{2sdfG8^q!N*X*yrKIfTn(K?fj zOw^ntA*8OzTa|3rj5ZW>toq(Fm)K5LG}4M9zoG$RBK^z@wyV**sB>}h@|~Q&-u9;n zqmUX8GsA}!b!(zj$z!hASVlx5-Z%x>^p&;;ND=h_{^}0F>tGV#wViLu8pHlz!+2^4 zABJBNUWCaL?elJMOuQ(}yR1#EH1{04Ec!QiL12XVlF@p9(SX>k-25rp7EZN3eFlx^ zDse!OTIK?*ewQ{9fFMaPBZb#|#K!ac9B0}Jx6qA@K+Ssh)P0@k8N|Af@r@tEG0SDc z6oboZ@+a#YplD&7kzM3!hJxrUn>&*+;dv`VOL+}y5jcr~ME&d6FHmZc^0jC}N{$^r zH+MN8zfsU|+<}B~d9mh>Ty&q%KLxwDNLb|h(}e#Ydf{wB3k=~DlUZzBCPAS9y-X2` zaHB0#AuQ_nN`fBLhGg>?Lj^*w`*i}CkJN|tUW>eeacqS}Qs?`x#e}tY zkYp8`5{14pnMkac@Obs?{@o!_!8f=hyMcETv<9@IA$4LDUw&Y@9nBt?s-A9SjV$c< zFlg8AOHV1T7>LhaHEF+_^9T0>P*4Hl#+_M@aV?Ky6YuTJ8SoXr7^0c*=imq~!ZzE{%})i!g^?kRG&mGJvx^ zXwcyJgA)XOswMm-?0+%2J_Rvthx8)dGxj7^rx}NAXc58kz}fRJ<3h+0h#KF5oQB(- zn2HK(z=UKV3$%AgAA%YZt%q&nrM)x%LIqKhmR5(*PnK|#69$(64ti(DW^cFE@#2hG zS|Dw}>plpV@Hi-DXQsxBDsDNB0ie0p)l&9aO}oprXB+$O%SQ1mB@;vc%0JY~Fs3q%W25abiE0m5yN*thTiyXlv{q^4%l zOQGKrO}I0-O<%Q?S&#k7YS%QzdXf#cLU{dI(YBDFQs}!S(CoSqE}GG*bbJ5lCo`7b zawS!GvTw-Q&$0xlkd&sST+AXLa;Vv^|I}70tj<=ZD#0s9L3hzj*_d~-w3VJ~bDS@K zJzV=L?&qyFL^#)@{bk*4ZOzJniL$ z4Nw1G?}s)~iGgOcfJWWG^R;bf(?uL7|MSdf>)oJ7Vg-Rimg%fzGD@$lD*f4U$=SEN zVoZ7*W_mxe6xgV!YR_!}KE|6%;~~qK!>6ZrK0;kHQ6?T)%;?%cK_k{ta`Nb=zWRui z59*vE!mW{SwxwBKF}D!zrCQW-?_HF^Ryd?;Paq;Qp=*R*d1GUveHZe7Acu?irIWF% z&5y!@!_Mk&EcUT8qhhSi61;&dSbG;FJ18W%``e$5HFrL+dXVh*;1^@KH;8PF*+KmZ zuXaa(=H+AKXI~V=3ChC3$F)Rv&f$MQdcpnLL|3wkmS*~bO5q*?j5NA;E`$qFfFw|AgfPL>(%AEBQ?zmUo>3U?d|Np%#udOdjG;lqikopmVj+) z@~0z%>%mX+io;}xE25{raR(3YA-;Mga$<6_mby9yB`a%WkMp;s@}XnMi-RQ=QQdk$ zt(8Z_c}plMCMG6w6;x7-GDE_q2Y|(T!>VBCvYx2O(pO;Ev=79`XJHHMRvmB@L& z)jNmNVwy5BljJb$#b>T9qQo$?gX9D+o9Kl5@#)rXf{p+doKgO~1 z2#15qo4eS%%B1gua<1@NL@%Hd%)ZGXTO^#zSnVbsk-%6RuX#1gx*A00$n&D`=WAv; z$*S+CNGaAFp35G5Rm$(|^7!FXevaOJa8Leqc5|iM&ZhlidoY9uqu!hwWdRzPQf``J z`p-LVM{(VMCx|*?Gn5$I23N#u03r`|1&lg?CI#YBSQ#!u$ePpkH1;eAYz|A!bp#4w zXA5qr8}NBcJgoD8ZBcf1HWDO3fP)L|u<_<(NgY+jVcVh}sHHOZ8-N^DO@#QPF^5LOg&d)rJRW_Ew4?%lF% z_N5>k=_-=rg4f}@S{1+}*JY?R?m{Xz*RsIN^+BK=|L9>H`qT-@Nr4aX=R25LJa~_` zTkHM)boeP^I6I@Frg^ww5kF4{!p~Y=G`~enz(#T^eNq12Wd#Gavz&|9@kR4!*}u)j zbJn3$HHu{s^S2UuqJPS@HN1QGkli7P7!Y^?<_9rtU0njU^RIx7Cv<%gm6&M$z@Shy z+H%b8V6_j72_P8xW57!EdLq<}-afU4qT{?$b9tI4gvy49b5p92`KE*Y zZlq*nKC8J^6!-H7539Vzcw3UXU&LqLG8<^$hfKlPESgwA>u4k?u)HapBrU$j5lqz5 zwba+4*8;?EBn%VLj9Qz}xs?V3BQ z^=WD2w0n!Ds;3@J#C}Vbo8(y@n&*+&R{Hx%C1}no-JDn+gOV=K#}#YsSAX#U0hvDQ z)p`7i>rHqZTQDyfVe5hXd9zst0j85v8G{usC7^g2{$jDeUgjyLjQ=-+^}UjW^g~2j zHI-N_Ou=sxCgwoI5H-~A2I&{5;MzL&6u!If=C|}>{lk?)6Zoe25sHH#;drJABe@;B zH6sZ~5xHW;H!^qiO-+W_L$~@uj{2T%i2saxFlBS|HuhYkkTB}*d&H%Kiu9O-;yJ;9;?CpxR-s9_kpxm z4vC4McD##-C!1PC!jE$MkYOdwH(>Hh=}TtdZDIdD#aYgnuL0V`sdK9jq5BdXaaCwD zg5j#RmN8(l2d>}TADpSy6ma{myCpPWfuy)|f1@_|^{{T*h~MfdxEGFGmF{>@mC^yOcAeig9|Y?sl+)y)@4Z7*Vf{?3lD zQP*VR5)>qVZeZ~BFdnErE%A^alYjZ!>?Q&}`Td#sFe4I3pg^FHJX;>`rmmgAJcl~^~5J4ma!rz#Yf!1#f!^Xe0l z?Vwt_-dgBjV_ukhazFWn>vrH5P^H9MlVd*rQqNZjD+&;k!aqj+cJ8(h07p&FTN#gV z_>?uDebd_7x@l-?{7z8!Zh?nD+TAm*oT4}DWG!S0j_~h&(sI7PVcFp%S6HS0hS3f} z7_A*8yjgYcaXSl+xU_96>a^&i``NV&!^dFpx?p9)Nch)Y=jIpLxX%UyEAvKO31i$v z)BoV?u5Bkf;eRIQv3m^NBB0`M$@#xODA*t#0B!(~{3m4oEbRVv-mU>p5a<+eDFmws z-{fzH#Gf~5(f*9AC|Feh0CK(O51XUT>Q|7Jmd09X#Ia{G>i_f(oxPQbff|1*N#&a% zy05@Fgc%5&(Ci}Dmz}`w^+)VM-$9yAsRmr6Pj~Ib5-Dv)xsz^{koQ?z7ArG@#?6iQb@u7FiHpR||jkkieihjr9)__?;JVG}1om08b-_ulL3r|u&;Bgm~vxK#l ze?bp&mC{tfpL#3U!^klgo?ym9$aK%w^LI--rBXqkgqhs;+gIWs0O4F;xI0zBxG6c; zc8JgtJ*fWVXO35FaKdJ4&jay(8z4e)C$42o&&`hDFXMrLZfq%;YhY5rXsbi0qwl7 zisGdE9CPIyvv=(&`8U-EJv0Im`J3{Syo)0)iv#Xde#&aD#|9!AM`*G1Dued#kzxCe zcwYO+{4*c2PVq#o9`N7$APwD50P%HDy+Y_tpRkETFG-F^1CT*Y4B|yrN~hK0drvMe zL)Ir>FT;rfuPE~K{FXy^gU`?9ZzUuDWld_kfdu&q@1@*!tMZ=CKKpML#d+6G&|kI! zu2<4i5mj$s^H*YboAHOuv8@jz!TwP`nSm&k{56z&Mql&p)4Wz+p4qnyGCVuAgxMP+ z?e=y^3n-P}Oz#}n1rB|v&ShpHsx)w@x4wPHPoFD>B$OVC| zF$aj#z;PNK?lJa|iVC^T2L&zVN-->#B>vplkF=&}Kz>>9(tE%NmfIKhm?RxOd`NOd zCon8rq4Apn43{Fhj9v%+;}5iR@S%hqQO7$S*p zZMw)mY>wVEjXx~4NVL3Vhut|>h+EN@5*D&AzWihrE+{+e zh<+RS`Ln}yO^HXxlATL3!Ar$h(QpChpO?J-5_S47GmOg{7Ecumlm3%GVMW#TQv2lM z&=@i|N^>0XI}YpcNHU?JriLN=I#`The937TV#*jKxR8#~jr7=K&CkRxa6mrdErNK03;s;f<*aVRz`CFywUOd%OG4`pGb-`owu%*-Y zrUq*5lca#+VU%L~E+H|{t>_TacCu|;^XqBlPc@w|G3<-ZbM#&&RI-P1_*UjVAPhiLBv7v*3O}atZE8Jc<35_+58qYJ^09&2~Qbs@g{FUYDCMYOIXyX zTQ)0YWn~$|@MU3P0U=Q&CDoWPRD?YP0R2H1kzd5DE_DA`HuLpp zQbn!<{FM*`>xQlyMbuO=w-XPaBH(3_2JqJ1s%G5}D%1}FMyI;YE*lUXT}7SqSBVGG zrUq2HSJH+WOE;u0>s;6JCHOhV1JeWs?A!ek=ZYFf-D2lHnJx<&rh*iG-!!_~P#keg z&HaG*hr#T7jg}*CbUY4+z*e#TgM8&DTtVQnP>=708y_@^BWeP#qFIA>hlM`ne#yNe z=b<6Di2oYB;=;Lgchq@}kF2+;fM(6!JtQ$xU2SfQ7dn2qy!$ttgSxO+*?87_)LhO9 z|H)A))q%02f`bBmHkh zVfVb?$4PvaYSJ}SS|2k;Id&cq(Z2{sKd|r~7IrLa|0n{XK(hEple*kz&+M~;x~*!8 zT)n?_R)_raL6Xjc*M9i;8^oB;yq?w80!8%I)s-^M&oP58dx6M|y0~Q7@ArpozVBJZ z7;6qj6B0YXeyZsZ=g?v_dckz}TJtp214gV++Gn&_S>5Y&y^L3XIvMc{#wCl54Vl>x z@L7iYpM({N&5EmZ{xW|Q@!x#hcwZJsSYfSpMxSrvmYxNWc``_nQM_5~(PS0k-8?<7 z5b%YlDDbu>#>cDiXpgaE!ngBb#COq};d>Ax03{npk_4Q$G(qdJp&{upDkm5ZCe^p5WIKtYPExc5($n(&!daxzrDOW%|)PeCHwlbNSnUcqEI zC0x%%)cH0!w;1?jFD%lRQ4k@DPw$-G66xGlK-{Hvo9O+dtN}M_dg2B7_o!F#gVX@O$G{3bo+~bO+hGRBBUm znM5cfO40mLt=&PNBhLtWl6)f_FGw@rQ0&Dl8qw^FjThn_7amgBc>F_Om z>kS1i>C9C_4YuBpP0vWM{#(E&i3Q=mJ_emW7vOhlD#~+99}^*o(c-LebyObS@qGRW zsaRVh#xs9s@yu6YU6>T%wNZ&-PdX5a^YC7~=Z_q^wlnelI4I6p5)#S@ST^G5XGgD# zUXx|Oa8mC|ZooF|SsmybVJ}Gix&xYSHbhQtx5m3>_P{6T^FmBV*0&+g@e5?)K!ufV z>N;6&i!Y+4v!Xo~a|xzz81%LXb0%v2rz{YxmB#R*Z#mk93xEM+zk4|p41w!DByE$- zOUkI(P8Ioi8^rd!n1%@?++Ru`tE40-+F8Z|+(1iBx0$v%$D%`eUD3JrzJY8Ezu`Ff z|CRzS9I`HX5C5l2{#ek>KfU&za}r=ZaiwmroGjQ4aa$K^1!TaJR;0@XJRf)7DkoT# z-f~pi9ZEhGs{srCX`emD>B(1PvY~BSVif1R7dQH4mhbj(w1g8ys34+mt&Qq;Q{mvl zxz8TELaJ-$u+LG2kK%NxvHSAQAu6K#`>AAS$LbAcwiG_+u);D)Q`5g-pA6wS2P+#x zE5ih0oG>ynQWnMkhbT|K|hL=!f@JoWh(&!Oo*#epwjl zf$sB+wn_@A2@2|$Nf#p6coH(6%agdI`%*Ig)9IChCKQgKuC}&#FjPPuBQQqJ z`@|?Lr>jnZoT89B1fPllvyzrJ(1pXuk(}FR_TPvd!;ywmWq8lPcnj|tK$RO>I<;)i zSCb1;&G}uz;cQ((+8O=x)L-*v33&=X>bp7(Srn0+|1BAOTT8#WvK9+xbym^W#{UqP zQl1oivyLdx-DP@KyMg|)9peY>^Rl(UF0hQ8lqPw9lsk@QZAvJ4QsH1)`t{M_!+Y3C zaajB}($b=Bk}imzzo_jbmX}O5!HE+IP*X;(1HPt@Gu{+X(yAa2`FV8rvBmA-5f#0MqP=v@cid^U3 z!KB6h`E$~OG_OakSD#+oDM3IOghyXx^gR&rOiKR_J9o63H~$`ylI0 z7%3c^@Fqr@sR`C>VIK{84~MWO%FgJ}_x9%t%DT`5GPr~b6`p?`ylD!XDq!XCFL`UL z={@+Wn$#Y~0-fPv>^C4cW~1y-m-lmY8Y2+i8nu(_$#jPeT`QVP6=h zSA=@sTUuDTJkf69tt#WNHY+KvId#w`b8VpvB4TAlh=a#93q6aikE1Fq=rMZhKlphI zJAjYDk`&Z!;FUm*<1inFqy2be33Lur*Gi|MYFx}##;yTs$EHfLN}=L?Z-al zre5&nd{tOvu%ZA@Z%4uQ5P+vz8TeX0Bpe%KzA8aT8XpUVqW@-;t_t(y&iN|XJ!`_Ui`j3`ynfiD+ zkf3RMs)go{OM%KL!FM?tf5;shYHMlsL-9#nl_^jY`EE~A9Glr&)Ete9)`$wD;4N_- zEm3F^5MTS8u9Rb|Am)6Xh#%fd0TL970R}Oc{v#;VUS8KAMJEya?X+pe+RB5-{VgvC zz10K$cQ$ay1H@Y}$7s1GvAIB$)NUax)0}y(Y#ji@%EIAfPvz#^abPho3F%2P`%;R~ z)x%mo$E4$G7H>7^i6=-iVQ7U|Vl>10{7F?lZ1+2M4@U4ab20l*uKEbGY@g+CMtS(3 z8zz0}K~I~2v2p@(6C{)VudlTfm;XQvkkvwGM=bM*8TG4Z zyT#ce3Jt^bm}#~e8%!&!j{7I`0gU-|X-cL`cz(YR`qtM%B1!UwcGX7NhxBH(A7MWw z`&>YJi>vvFG;^VWrkX#!66TXk+$Dl($8HdAyEG5swkYf0#eHok|6y&>EJHmHW+25H zWmpr?XIWC3PfN@67?}$B_WSo7m}=-_Z7E|T_R~T%?+xsX zehCzL)lyt@SEQa-tR#pmcWzIv{9fs~Zf5o@w3&P1<0d8zlB&axMq79LdhxKI?$+zH zqA>?^rI7V(g^HCnp(M^{6OD7#^WU$qn93wToA_0rHCft5tG)4Cn?+xH>A=MhZWDzW z%$PSSl9g67`a;?26>k?ej+avLSc=)TSxyy&6bpu8DzfBlkBeOLYvL-hj`%OC9m{H6 z+f%P|=6{%nr_k7=t!9AF8|)Ld$-kUUB+w3?xUFSOo!?PkKPnNRC1yV;j}iZd@g~q9 z(fQRYiK&|O#uP=BmGv~%PfIg%)4N}?8_{-fjz5&2UYv~Om~@p=P}pC#j(F`KGGA<^ zigtU>^gU&-J$`kue>kN`bwG8)d3N+@duE0(6Va)WbyXZsyMbKVxF= z{(ev`x6$QH+~lhMd(U~k+EDsL?AsUWnhP8E!#NYdwU4u}xd&r_GL{}QUTx`@?NBda zIhLiJ+>ZZbCjv)-NB^p()lFjKj!cYpty1)lziYnQj?xY}JtQAboS)KZbMc9+-(kHtKU; z9u((gbm63RzDvbs&3NCmHnf7vqfL#yh@ zyr7+PIH@Vnq$@>!JjL=ywt9)pI$2r%S)fG9)!^dF^|{A6`T1*!&FT5O#$n}W)y6f) ztt;32-S<;9Ij;^=3zArvcZ&rc()ZK|KFm>OZa3Ud0ukAr?Ia$`>FBYTirU|PG{~0m z=Q|xU@XKpCpJNa8TnTO$mv&wjT574#AU%%^6O8ztR-V2oT$){aS%Oo{NpA5~RhIYU z!?&};u+V!$388E5S-jQnOw3ZAOrlf-x+OYyhVTo$${t)jr3n2%R(sy?#S?^V4{Nq% z47h{p$hb=vZV#M0&ywGTN-7l6%Lxx0sH&%$>URqY!XgY$3t~b9&Bw)LIP8VwDl8}exHkHg~n-K@)ExAQ)OEu^~VY*odVf(I{?4b;t?D0(p9 z_k#b??>GjV=R$r7$x7I>xEkB`AnaPR^xHQlYkDo&Puo1TbslR!->KC!<^R8SGP)Eny(tOq%#|yS+ zpSq7Kh{6-b1>)Tnwy-OSyxbbgW=@)PuyhV_V=bx|hI5oKAH_28UCy&GU*~31sM*xl zZY1y3>ma_z&5ydd|At3OH;3Ha4U69mRcV#63X1UCv(PllvOBB#@LfHA#rSXB@evz* zW3iKsx0u~pcMY~W;P3prfGeLhA*CGHyh+4&jREp(#IEyMh>vdAOuqzab% zx!wBe;X+!jvK^$!sUY|;+UmNPFFB~bt+ujc+hwJb-!J?Bu=n0!O=eyDXl5McRaAzt zpdiEn1q2Bqy+%h6l{R!C6zMf|2tAe&LRV3G6Qnok9aNh1UPJF4>488vE57GDzwi8e z{yf)k&2`CWvY-9zvi92dy4Ss4ep7a|@q@WN`qrh1$=^UX?$pwrAh4``;j<+dXZA zuq`74BQCm_Id6xfkuA&gF|DJOBlXP78j?rRDPGa~2L!hEtO&kbhla{#M@ZgQaa%%~ zOKa%}Ntwp8ga-$F^~JIuY$$9jjyJMllB&yUJ-9pKYL;KvYUFB*?5f9G;w*O72FHJY zaH@OllM@$ZU67u>W+@?_{HfS`4NuCQUYz&#^M+yK)rbi0;hHWx;thHqj270F;3PgJ zesU+l?(ihb<(_t&zWJ^ie4`c=;Czm-}jBS zC3~SG30I^%Nv|3720J?; z=OH3{8T|O6U*B$@Y{e$FSzP)O;>WwAWMgR_`uHdSy z{~FmyA#HLSwtw=p3Ojd8{OFyIoa)YSy{x`&`Ru2F)mo~lKx|~Bzm;-OYDlv>&RYE% zJnsF`?YLiYZS-iOW&rCg!Rqg$c;)U^LoM$)lwW}lhqk$Xv7xNz?4-nW_Ky17Czmt= zB@Vhjzu0E!Y1iey)qX9?%(FL!&V=jXF=aBymfp(7X#WCQy|> zKtC*e&xyyYDdoh54^p=H)wmEKLD73Cva&XOAYi@AVlZliuuskNt$)St}(ilFjMxgoS-g)UufuNkE* zcLc@lF4c3kiq+|BS zkaSg~ln3F>XQtW08<)+ToF~2R8OeE4zCQgd#i+fh^xXvG*miDlYS-f>`}ttx_{FOg zDr~G%;T;X*M^YWGImsKO<6$oD!1UVb;$<3*T6yy%U-8aJNECN~bdC!giYuJh5C)I- z!d1%JcuwVJGh9BXbpzpYoAhwj4aw@Jeo^*5)t7LYPNILCenq{&rYQ;^C%F?gUhENK zR-Bh&T3bsKcR2fk13y$sE_*P|TVxW?mz!{VoF(vrK$Za5gz%scZl!>(ro#6jgi_DH z;=WXEuIv->M`e}sDK@!&ZR+;gzk1D)@TdsMep-ACgP2{>{~ zczyhsvox#3M)r6X@z8ZTXJ>~P=QhW07817?{s46_{f@6kWl_F3J;$XM>4GMWR)tV( zXB_DHU>mT+70XI%8C05T3*-N&>KZ$69p^Q|Cd;f|{;BUN;f-IPquTfS} zap+Um9ChrF1b1#ddi-!M4wc$5Sc>+iO)BH-NN&(wX2RKiKg%d}G)+%y6ECxVF^IV?R8k`}Y(5H;VPC zxj~69OO4d4Thg~bmEeVAZ;kDIDG81&J8t2g>b8FyFsOHT1t?i`=B|k;*e3UCmAR@Yb?AdV#Gu+%DGl7Gv$MpOxL#l}~=yaXk3X0DkgE z-xL0gNUM+qTJ#-ea{}&=)ur#DoRHpAQnIxX_EWc!{!Y50O;eG;8fg?QBb{P6^L=O? z@1j&m&LMRS$Y>ehE{$SLx;MhMfJ5(Uaf7IHyn-E&k?!j3Y4;pg5-Tg2d@aayJk3n6 zEVbW!T6nZLRcdTMfE14orZ1o2e?zLcupp0#kixBv1hWeW3QGR?aw1*LvOPw0^r>b@ zBqX~_?u`^c{_zX)1`)%+?97{~U37<)%e0k;MRGN8@33Pyx3aQ`@4(NvQXh- zrhi~MMm<2eqFt4VXeAl3OFce~CKn9*NfDy#{$dhmMXoXg1th*Sx0E!z^Wj#8$a2&P zrBU4?%Smu7``5yfF;nMG2-<}Z)avy0nbXz4zKyk{``PXf5PEZHs)yX>DDySo`{h-j z?k+w`X1&za%UFMs&r7;hlz%S%YVDJX1Jz#;-`9;a>yn6uvd)FoB#E-m4z1f55s5sPeQH8tsi#Vmx7(F^)`=Wy$~MGVFK;UUpTd31ZK zrXahhgC~d(HY^!C9)ZomMn_&1kYLR(OS255I})Rica-l;=wCLR_`UQ5v!$h_cBQL5 z*N5`8^24fkY*Rpo%SlfcU9a3~2*%dPmFQa%SMab^!29)j>?kBAhDwFI3?VH>N|==^ zr9*O=_p&5;cE7BDj_}CD|4D;9QgV;CSFH+ZX+8IiDiI<0T$UTLp-mBGRYsyG-M3RMBr=9`-LSI9^ zW9y~9)$RoG8RoorU;0g^5NwE_4-Ha_x>7p zza2+p;K^=`8!Bt)cXc;A{EjQr)!5yTyqzZ4{z@DBEw)6!0T3(T-_uiWrD{*pD zuhPfNQ5u<@2OcN0SI;i9<#^(X(``nD^)TRwbCi3_2{B@(@bUh*v8yzUig`~F&o8)W zn;b5jvmZ;lAa2Tj2`0THjzQmBCLAZba-q6dAWGcz!D^F5Q+)|i&f%+6>P@C`oy+Ii zPUr5&&OS!{rz-Lb^TOYll##~~dg|&$)iV56c1ZZKjt14{($ za$~xN>?``Pjwwj;rPz%R8wXc6_TBOpRyU3Y8hud#Ee*0MxWh1U4`T|u(50R^Y3ZE| z3ACJCiHozc*8|Mln1L)=?O?ma%WOsv`H10z$*FSz1h`jN2}@~LY;*yN5Su$v>WC$_ z4wsh~c}&g4H;x^A%A`Svg#CGQV|4&FPvgWpqxil^e@>o23%03>+@L-Ey9wgIv*f3u zU`1p%t=0z<=K4!Lu)Q}Kh4*;qB=FLj4bp|i(*ssp#|Hm7Qd%dlJ|8m!L9-Ca-KWaR zU45GRqg^rJ-?L(Oh_*riscJBv#6G^`}iqm)8LU^BXVQoHRWKH%7rT0~oUloz> z5EAaq^0=e2Sea`0P@3z~d{D5G9y6}y=9;IY=jKub&h$OQO*NcDcY3L@PTWRw0kOP! z=JZIs=bx6*!7MBU6?%N1)?8c^iKC>0G?U-GF)vd`OKXEU3JK4qG`4J32iljmp%3hc ztv(F>g~mpj*vfUy)sEtmh=o(>1Wl!&@k&7{dz02H^si4U>s_pm49^KOO|0a6a@T(J z>PDYt1HMKoWoLmX?D4^)ANTmP`kP>yxb>ILWP-jV@n){Daree&;mx~u7ADWn;MS}5 zii?Ze<0L&g6V6v;745`W5H}?4s46#*4GcUx@9i$x+|nt3a3*YB_h(4C9KnzH3);>V zEhCq1$cGT3oaOS{c1%+BW74lg;{H+=v%#C3UGh3j?lKJu@rbuVKjky>{-n}pwcb%A zkaAac<%MligFmxV#YKwye>6YwEhDEq4-ew z{)n9h{MRc~-y?1`O&Qch2JygKC(+dRPV!+vkHPJ>J1TE&)i)FC?;+g4opPhbA^yi; zF-ohrSQM7Ufc(Zi0PSa^4f2Gr+BRW|NqM^&qSo_3*u zaD_@v)v-xR45S~kCOWuNke{8na$*LBVQWVS{@L-&V0NL~e%_SH%1TJWb6XudLWc|V zT6=76?RRq7s6H5V_&Wm8D3Hc!sz4BqWkOa8P&Q3A#sa3Dd!|?3cJChcuPkPKh( zsj)We(kEk;D7it`G<#}I^TUgV^El|BKw0PoRfwjS1K+Q?xmgZX_K9hE>C#+B{BcpP z7xwGRlkt@8RFCqoY6E#U9XIWf<3qX8OPL`_FFg7(PSPuPeT_+c>AGHjdSJ+zU9ExC zJgD90UFpzpc#y56o~!-0y#_h9Z@9Fi2OvpS?{~O(k3Sf-r?vv7Wrdyl4iJbNY31o# z8q;N?blxQeEp4%}lLaMG`DHH#Iq@FO7gLfxzRCpmF86p2iF5F4P-GketDh@+A;FrZRD|9I+4-WG>S3RnY!$?jx1x@#hLTz^bZ z*Axl7>Ic5eW=^daR56x&y;$wHsN1*V9cH^U1I|p9Kjt%eI?y{T2#ZNP_{<2mX{(39 zWO#-K>dIbuM^Qzgf&NNXkTP?z6C>;^WX;{Ef{lPa-JL&+2kKyvO-AHsBN5L(t=JM0 zodj^bD(vAN6pwY$#d=y+%c#VB(jY%MGD%H=y2e}H*4RLMH*&P9>2y@mNr8O07NZ^ZpD7uu9|<0AxkI zYi(yOkAMA^gqiL$b5?cp0!J@Ciuv_o&hY$L=O1XdhZE-!oiv4}Y~|K8?p&9Kau&0? zQfaFDR$c8y=YW7Yv~0=7=Wjw$$P@I0Yf76iPm+o8Q} zB{(#!Lu5K+b~0q%wuC8_9W2~AdQ;5v<5JJo;qPI_Q{1_M{!-mlM{ndBWe?KKRu>cV zH~IB7j#k#K;*O5q(CUwaTlwprrwV<1DVIxc-IPKTZ(Ljbt7z7N*Z7KG5N`tWzlD$8 zkCx@~njEkcE2{#JHWY~@cJ+nnygygE=O8P6cFjo@KiRoqb~IZRE1yOz^z0kQksj`M z|FVD61mUo7s#6aY4r!`nKp~FOQ{#p~@|3hOovIMsAC$bq+O8le3eR?+SI=a4*w{8i ztQ?%FI-)bMF!0DM?*9{Y_Hv_t{`CL(87H zpr8t2<5TB&qg^LIe*N|`?RGG@2B`Q>=46-GTHq6Cv_>F#<9;W$j~zU%Daj02%G6k0 zS?ME$m3y_3OI$WGhD>zWL zSQ>7#K^5^WXBqWehFgPE)Uzu&sGhK&ni#7}I_E8dTw~+7-h~I^M4xVATh#Bz8?NN9 z`F;#=j$4fsRon0RzzwmuqTERiDb7?(T*+EqSxP~AKI@^AvUA`rF*d@b2An{2%IWa^ z>0QjVZ@L`m)G8%8DM)_P!ck{CaPwG?*!`_^v+xtcYrUrPxCu_$%bzSQ8#-c!x^_}h zQh*JRs*(;H(#c4xDmdpZhrwb$Lv%q$1o3jpy!y`6Ws;M$GCPWqdU5bvob?ii+ca&1 z^rCXEQ)>4~@JH%^Y%{D?Uc|Jt6e@-%|49EnmzdXbnFewF{(zF-JCr$X+~dX={&)Jt zxvp)6D2w7a|I)$pxKpRZM_#ZA3f8~7`SwY@^MJE}$q`$~+2+}Hkv%BRM6+$%^5BJs zP_#m7mA9Lav|QB+{uaTfrVE_V&cxoFK23%4=3MYW6MmnRV0 zC;1ztO_X~DZ&t2Yyqa$Pcsh5;S4T{WDCXV=8{KBe%Yt0V#33ov+?L$q36q;9&M!0dv;$yn6AS58JfnAz)&%` z%;gvpW)oDd(1NjaVF-!Qkw~m9G1th}yF&lLOg~<+Ugl^`;bOsNEJ<6yQ)T0OQ?@gC zbFIuO0T6k7WTm7d$b@T5c5PlxB@2_aGEdCRB)wG+>OHGGw0u$6B&YyBV zK>n|E0}FO32RF6L90iP2*k$4ogqrBC5lmVV(>Qag%ZdI=MTPcg?=pf35iT$<327^? z9v+p0&2aQqI?C?U&KrmN&W=lt?g};$8;&MqeP_5i> z*f~6Cz2Tr-j*E4DULBk?X|?R;t*N%9(Y%_EnafKaD3DGZnh94(ooe>$62#2^f>`(? zmCmoD-R%~0`}=cXDZ*|cy#tBei>(O;fEAr-_9;B~-WcF*GDfK-RLJsg&sBBhC_loZ zOBaD-gRSMo6W>I}7GVPktqGG@emKj6;8>PV3+(9F`Yrl}3>|Lb&fXYPb~c}f%h@H; zt%i;5n5%buAb$bsjsdWW1|j(^PX)1^@BQDw2hYKCsx0~!WzqoYmuXx2JwH#_${;7zdYCV z&U{5L#xJ`4vBP}?qWr6K=u|)V^cLO22XZl6Lw${oa`zw4p41<9T!>GOB#r3!axhO; zDubt8?~A{1E`93p`oY-7h>F1B_5=O^em;vwo?AYg%Tc(Lzj94{#qA;>;&yUP*0N=Y z0oB@b`kz|Kd_l|q<8MkOCRxyc$%xmC@^h4RHu4%Z@Bc@FEDpo@UZGNCpj)lLW}~a* zc3*>JJWl`ONk6H#k7WY6Lueasl(8caqtiYX8}-XZe|Me6vGB^vn%H|D_1U*A>Z)q# zyG%xq)(0B@`Ks*x@}rvtyB?n?W!hO8Ovi`&yzF)~=N((`c(sH*Enq)I7c7TbEKYP6 z#g2r?Itpo60^Ue)# zBE)Ys#fMJGk1W}pK|GgQHn}jBY8%+XE^WcC(%4mZBi8?&ypH%SZ%PWFhd|~MR=5Uq zoClTUZ=5aH25vnudCm9nE(OH0O9r-yHH!(3u)}0J&`7I+hBtrOgD=@$HXlbIEawCS z`l!+9I`>f}8$-|(QjTtgJFM{KCT8XFKh$Y(xgD?=J=F(2LJ#e_Af8uajkP>?E^P!cO_^LsOuK&S(ySZKg6q;N zfB2sqQORm@IjPZ&uk;hmlhp@z7hMNhNo{Q#X5n>p&753>O}6pJu#PqpIprI(Ha0>W zr{`_^V|;&6Fg{h8h7H+`5moNou<8uBEVIDj_|Lm{?=o}BEy0cdiP4U2r+^C_u3avu zP4#@eC3K(OHQ&6%tdOZ!#OW{uU=Fx)@$ltRS(+u z5$5WI$r@tzSV|OSk~ztjcpG2}INP%}_#TynUf@gP9COgCoUI(hAeGhw=ji~kgOl>p z^@jJ2GY0nUk1)f3{xxyFawfvS9mN1|5h!}18!8Vn0F{agYkJ7C3^77%;~@$oHM`_w zU?JNBp>KZzKs!Dk8fFYepX!%XxawTIB(1tk|0-QxxxRM@@-^gYwXy{<{LE~?0_oT1sM^I)$p^~C}#P2;R&KO;uxo^it7yBt{AZ>aGx?@Ggl$`eY*<(7Tll1}W& zmOK<ujeGi0i+&mqLkz zjk*hYP>|f)T|RbrGNzbK9Xv)jHMmoh;wfbvUN#V0lGJ^~+ZT2bdA3LV{0I{++jgYt zPkwXPp*mXL<$)vP;Ti0-_m7cYbz0VND_nZ{Ee%oj1S5!QK)i+jVaz?bJ$W&Ien76L z(fS-%8hA4B=C8BrSx-pez0Dklf5jac>lFgYLlWw~5=(NoEQYL$v8L*M2+5tzuI#Q- zM_m9E@4oU0j}VZBoMYyvWT+P87k4y*^~@cVy|Of=C1cVfRQAjX&bx?w zOuu!RH&~4;ry>W2VD@3)6?%HevmJvO;^={_YGJ4gM<_j5%0#+Oys+WQ5!Naf%+M%# zy|~5NXHcjGAv0+;#dvXxM}esI>P`1%QMROfkqpL=YYNF+X01dZmSk$6IIj|`O~|#F zsZjAgzD!qI3F5&(Nl$59WH&oIi_)}{|=_D@}71@71$!97rtno0uB#B*!nXsfzQ@eeBem1|)YAt}e zzELd$R>{YYQ>Ui#?8h5+r!Vo(t-F!P5JC@(B2T)6$GQKx6s444(tOWl_d8rsJV~1b zLe&mj8q?Lz@&u_UdBVdNo{UMKlZN}{9eJc+My=>UlbuSKjh{|&k$YQJ*P>s#b97iq z?+S`Vw9K_G(k(iAPp)9o`9r#d2Nh%i`p7`H&7OyVnNhv+e3pZJ?GqzUlfcY3#V25c z%>K6aCE&z_V>QdkY|ligE{IE_b8g1@JsKR zj}zzO@-I)XWWi}e7ryiBx$PbTLRvPlAV+7rxReO(JrCuu^Zf-%3_Put_+Q@4Fr%gp z{i{>XMkd>CR(o}E{>Rr|AqEQO?AJxTsptZrOLMx zrIu1^Go1upVsLf2H6~p1B(xTD?S=SRSM0eF@kNdczv2|T*)WNwt0#u$eExg+SvJ?+ z2{<<*$8T@bNV5kb2f+bO8As2`UH{&X44==>?z8g7Z}XIcdj|xNoA9=|*)KdeI8tne zFLp>VJ@Bc!8SaEp-agSbT5pY@plEkd6&kZuk|QKYD!TujWSZp@Bs- zYcXBzWHnP>ej6H``1GFtgxl7Zb(8f@@o*r;=*<=lx?qoU*O!p8>v1c$CavFFW2n!dS69t&a>^&mjOr>)5f7q5>=Ac{{utqGfh!%!5trTu;0! ztIG<(?}E`%uT5sA?JaI@@`5aSxal8A40S=ATI*BDvmB6X8xoJ+pNfIYs&cCD`Tx9L zgy0*+u2(s2T5qqc-PYRN&nJx3x<0+vQGZ+|bf(JU9K57^R86}9!sBpbu!vg`Etw*} zXa{hCE0HLAKg1@;8kM2R>#wLJkNtUpb_5@~MKRiK@%aiz&s=2}2j14paioNAjND@0 zsRu_1H1~!1)Ms!fiF2*X*1mVIt-j6f>c>k^PlhRmuaVX^O^CHux~Rt|u|r+Q&+)C>Zf0lwx@Jc;^>R0xWb$$;6Vp0Y zj>YLHqFT6>WP?`4P*?+lS+TUVs+>dtclGWgO$J(ch|@zl+?6jmm3MP0^9xS@Klf9q z*FFqqCB!WadtQV`72rg8!?V42_vn@RjK)kZlxLRe&Eb}(^H#eCqrRw|YugAlGo(b? z?|%PH156u2@g?)xy~gd($xpXO{{TYDP869n(ePj-IHeD(J*HAn;W{$|_(Ut?n{y-4 z+S37a50ChE^W&d4gpo#0z*Q5Ph~b2re(+HjQbrow0!dvOuU1%eaPg)R{FGJU0^HSA znDK!YfZ>M9mrgnY#Z1e~f@^wA3XfN?=o<`q$q@QOCg>|cTMPET;;y9S4?WFejq?`U zUGekrxgsXOt{4cw+Mf^fq8yuU+Be;l)cDg&6=gV7oTgWFos}yUx4TQopd!!Ua5z4E z=%y_EVIcFcBUCwjWOr9+rwtrH+7Vd431+bEC(<+gdA<3ncd`eIGLMqw*>fsTQskl1 z!_By~K*}??^I?uvBF4H3fy1$S;LG|UM`U^U#gLMz8P+;e(R)az4k;vSC3Hq02*&TZ z4b={t?r)Y(`V3YdB||kiPE_y-8dg?qZNslGpO)T{+RY<R%EGW5!D+EC-M z*Y*6&ZFkmY$W4V7Z4KpBpyUSg^9#(+ou%dJY+K2Q;+i?ZjU;6KB&Hz1->^L*CxnHO8iWlghou`0EL`DI>7q;_>jWx05N7C5(X_ZNJw|G8%3fLIdUQNQ8OwBh zHF1Y)v=x`}nW02XhKq|+`p28axcdc+@XU#b-`4ItJ8Z<)@pni|w?@#zTU}(BkKYX| zshexFU(Tkdk0(i2t~oQd*d4Nr)9>&o9~n|75CY!L(MTnRu(MH~^(H6s;dESHCKMyepxoo+Q1UB0BUKuXzJ}Ejr00*fJ@7s5imeh7dhOqMh#j_ne4kW5A&K>@3qsiI7*OqwwvbtG53bxj9)GJJOuk^AA3; z*ATnRh(m{86{uV(j66{cgBv5Bk@@RhiggTszMKZtGKi%npFMk)yvyu)$7#X74Y_L= z9RhnJI;fCgexbE}7)aNo@l@7CrIfbF2h;vNh8tU5F$$(%-^q`7djAB@ph3Gt*aLU2iE-~NriNHiE+}2| zv|HF#6KNG@2|D)T(jSg%>9_UDusH4yiyDQHiG2O{?mROyu7}L!aVRb(@={F@uviv0 zZL&&B4l=oo7W>U@o;*ue=ry@VutDzMF=iWyh@f!s)mT6;aWxRQP7XX zig@ZnmO|u-(Yw|o-h1;@c7j~n+x5gp$#C$BZbs3at(l5V-VyXV-$ zoq|0yIa%~=%R?@&;ppnSOXXvu`fjvXdpSi^$|_QHqbl@=b- z7tdeC^~+u^WRBGaLSnV-@!pS2qSaJ-tggD<_+3Z&k$n!hk0*Y*^Mp2p&+Tu6_YCzk zyg|tE8`SIh^RaK|aaW%8X9s9jarNhTS=@k;dzY4rxA^q=j!gxR)b_`<+~BdSlv_E+ z-U3A|LixKd1dlxxq%WR}c3nHhL^nIRP!`v2j=NFF#~iGuV)?8NvgweFN~u#tJyW)( zIQ1bfWd+qkQ!KE2``3e}+-Unz--)Gf48{!>+>~1 zlP3~8YH-HdlUFxJ9O>!HM&v9!w6rRBi#Bk02D8|{SAyN*fM1@W4gSx_9@<`$_-Zn| zCVLBr%|5yZ9MSkghM|V2;rTEj%~j51)o+Lr{4Z)EAk;vhw;#5!ufL?M(%rMu zB_~-dxfB(0C0*$e;cbzhT~5qX)^@G?p1^NfB$=jFG80iUugz!`k1rezqDeONG>OB& zXAuYgZMmQH-8AINRnN7|VU`uI8Jf2(b7k{)$jDYAveZ{WB0i+wTPhvDiShp2Vkvap78MasAlnA2}H*2Dsy5l);@tg16!VI>!hWN%e;YFI=20auGiLWs`vKLrNYH;Y>rfV#^UHIoX+P$TuN6rj zcRqjAap|G69oix1A{pU}t!lyTLVZPQ>#apXCFd?{1V=iwsA#+U`|mS> zY~aE#cXuN>ywPO3BHa|e|J>%f9nHi)f@af6H375Yi68g>SyzyGf3abHzTrdr6DkOD zzyKr9!4@5mi)KW-ivbUfgnxU{EHRO@`p`c@Dv{QTdI?(qOOH?-Qx%_H_eP3aC9OTh zjMDbJRcu5m1fVN!H=n6U7NI_G?It|${R}J1$i;CF*0|xT^(O(o&mICElQC;-usoL@ zKhK!EULa$y<7?`?JMqEOo6@lUjkvlc$-Mo0E14nRUS82<3H5DoOEPNy{AkAs0AK_{ zSK;SiA`qt^?Kx4G8sHd67#!*^*TLnd{)u?>{0kMzLLmNt*QWmY{I`EU0>kj{xcs{q z{@o_*#^TWroWm5eyZp~9CJ zq2XuGEG#X{clt4z85zN5n?@m$LJ-ab;#%eL(R$5XlvRpiY`N27cTUdl&!-{L;z~j_ zsh$@|z33_+J7#2NT3K4!RPFTVdaYVfqaPmSC)0I}~#Qc~vjYL1V9u1gmLl_=bS;R=KbSD|RhxdSS^3-SCr5GN*ptTFPS)0fo{$~^1- zNCzkSSQ&$*+Lb|eajN4qK@R;i~^eBWQizdMXoHFtcAuO8cRb>R7a>p z%5U0Qx|kA8&B&yV5@@8x=Az9z6KGMT6P;+JI{*Yp zY7RH8a>`6W4;pl2@Y0osv%EFX1J)^j?wkl%E!ibw!~3!|3yA?xux*&dtYF9&>Fo+a z9G5O#(%l*Q)edyW5LE*mc*<4?{%~4dT^(u$)j)-i@vXQ$;2fu{cH;q-_MR6Xcbk08 zP<_ys`>?KJY$r!OQzQFn9`zL=BgbRPkHe;7wRn2}cc}JqC|tb}MCY~eVBNJ*T#EFS zu6pvE?ZUSX*xCoLfmA7r^m2mAk~HV9kydT-9zbcvPhE&NXTq;q>0_QgB|$}2W>6H$ zYh)q9Tw}&I!-^}UHs6NG$BH>a76q&)kkBbz$!}pboNfLve$ZdSY6zVu(^(roJ{k{6 zeO|Fvz8s)`I3+lsvjqvW#}hQ@g?y!p&!HqV%|cZUq!rKs%(CcIo|U!IqEB&fbllR# zjrO@L&PCf+Px>%H-2*|Fl|fM0rpyV~?EmmZO8^y&Pzq&_^*8)A4_D04;&F5v&@_Ip zV*ChXJ(Qt<=deX;a*sFM_`c+MZ3O6F6SmR$IUo31rZKxlW}I{#kmKU#yf|Hwe|JmaWw825=H5FTd75_&|$Xug4e0z-I5wFSnaqmH?zC5zaqXo?{YD< zxPSjXv1bSJzaE4Svy@00!E2A#SoUSm;YqbMN2|8HKy(I5Zv0duvyk;54Vv^7)Tbzu zba;{aWW*z&NhjErLZ!s$s3F`gVUTQ{mRao1P>1(!6Gyy!vI_cW zQHgkp821m7r3W_!C25*w9egQT7z`7=*n?lUSttQ#J3U|pKZDY1ZEbCI5U?B;AG=OKOhnjD*P!CsXze!1I^E+Em zP!M(GY+-k5)*SRfsm2gOuIDT_ET^=L40q6)htX<>l~tTPyxTki!adNJv2tfC4x|%U z`EV#+%{2DI2h8i*P{BO(WgpHANrP|y0HZ8p8Eu3JmYW+?MJ)UYrD5Xk82m+?rW!@@ z@qI-tEv>Q0_DS=m^hrRX#cI_tC)`JKZik0=llTo|c zbH^LVV|sd!R)JAC8VK>6VZ-9UjOTj58XDgv4O`__L16;hve__8NbBqE|OSDMP)mqpLvo> za^GG^iVvW>diTcq%*O{Hn z!@rw^x&{#cS_bMU{JR*aqww!y_&EyyE{1;>!~Zu&>3UDkNkpd^BtGwu4K=Za#%!z) z-`6j`nlAkMR&mG4ggUNO5aoJq^t43SyZr8DETMdkvsKzkNW0*zq6|Cpkj@M%P^N4n z=))EM^Ofqv-FcJjP^P0a0P1T+2Kt@`kAbimg-I%!)@Mj3FR$obKHiPGqB?f+0~Kc8Hl#*_J9`<|$?6gn9E=!4&|MmW_@#7U)YiwB`5$9P zcD}tN<_8tMRSfa!8~>!r_vr?Ry+Ar8?h=(_+er(Z5&6c!&~Ox;n0J%aunn!NUO@Ru z5ZQBF_Lo&$o5|sj63R$+*ZkDYfG-eaJ)^>x!|F});dBuZhVS2b_S3a>f2*GxR3A;3 zvYMJG$RNHv6+m}W`2zg=J>;Jdu1ttZA*IqJRf|UULG-g^*>E<;_$Tvp;Rt-)YuiU0 zNy&muCz&wQa`;EoG&10K$WNTV2YQ`C-rG(fqft8Vkmrt*s6jUgQs3L12L^|pKEx&< zM?|JVkf}y5{4gK>9#QoMW{yCh5qda!EB=Ff;hgpD;Wz)Ue`+koHG$mcpvonlq5sm{ z5;U8(A>g@vhPT(r#TjHso74hVjQ`3h`*aIpIW|Z8 z`tjS%Cl?3D{~HNCK=YU&2s+ZA%I$Wn2Lv*y-CR&#v7@=JLLaFnfV&nDzZLmGhOK?U z_;o79-B4~Pr!w4uKKXU()9dijdq`;JI;-I$i zkw8aZdg6C_KCG+R3vxOqcVP1rN-MJ39PVZy(}|Ooj}fs4sifFeof_{Wz-ZW}0CK4S zu%{wj3cfA^Wq1?t&2v+Wu^ThAc@DVBzb}9oM3f)o-|wcCK68>s(l6#%X^jc%O7ewa zLwpoN6eUlm6XY6hRX!BP%G*!u(I7oPW9Q($XaDmaIny$LE6 z{~j-3t_LCIb07l%q-*mwP@OuCN$EGY3?h&wdp45Hrg-KXj>|;+&y*Lm>RB3V>D*xt z!-8~(qU6<+>7@>aiQGRq4jNQ`()FtyYkp{o@<T+8$Enns99Bpe1|@Q3Wi?g)QKmB5OF7Fs!U`N8x3eQn;=qd}Y=a zMw=-^(`zkJJ-))cwq)#0i;S-0;m~NFi!Dx#*mBgiaz!noRpn+RaK1RVJ*b4ZD|g`5 zcu=hCyzzFNMV`o(=-mw$t`y1sbVrJk4{0+D;Z#-`)dan$UJa#9n*5FU zeda?znuULdEw){H;{x90G0;gg)qYwr z56JV8vfcnT>3nJMBd}xH8xtw6mS!=+T#+ZqX+B|trN=kc+dd`TVU90D&BeVne!MML z;j*gz`PqG-tO8(d!%cnPKfpj7e9o1)w$t_)H8{wqugeG)?#951W0-A7O8@RFP?6d> zK9GfcM8>U6C21}t{arO_3jQ1t;+s<^7+noS#kHf7SR?|DkThlMHgcTnB zBdSa%Yvd|1gT~4DaG_t~6{uiI{^%W5@DK`itIw9z=aFwbX*6}LbCDrrd2#sv+gq8RMgeMFiQdsqezNxjlJu;V8dsP^C{jAa{H~oqNw)u0&dB z!25I2$8wixwsfbI!>l3Mafe7D$izk<=m99{lwHjZkr&ez8=Q=5F&XfxDhO3_%#MvM z(k5Qy8Tx+qyXK9p-OzNm-8~px-~nEGuU1^~-oF$W(9pu~Kt)Li$*}N$src)L&f1sI z8ZprP=vF3Pd_`j%{oaJQdA1ldjammlQTE3bz5f4Z4sD-ZV=bhv|w})4JBiOtY4*<_;>4 zt24X(Nj0OiqA|bXC1mNeMSo}T!Yzf#o z09q?jg{aMFUPU}U-KnIDdzdxOppbo<7ZV1V(Kjni<3BrSstL|r&DHj@b^5(jU+4~F zsV!*Cwu`R^5+Iu6EaeEmKbBvAD{8<=mg;!i<7I=*kP)sFyq@#Od#Ima#c{L7dc8zI zA02ss?GRWW*A_9>0RdcDeP=^1j>-HMRAzQ|5J7(KiqcgMbaKM2fc)AYf;;y^tlRjXR#51&O*x8J(sX4UYG9LPEZWdk^8dxjH)abXmHNT+m1>S8+A~lTM2!%ovxa?>%;@C zzd8FtymLM%lW<(gN9o|5zGoD(+kh91!+@M zrI94wwy4fNnXY4=r=PF0&OvIwKXpTHE5p`8Lz1ZXwhyW9+tVWMrRWeoQR3536v|fk z>F5l92de+y2IG|?Gpi)dHe}w zj$4(9RM^oAl9v`ZeBRfU*bv6E0(d1aDh#DrHKVa`YJEQTt7xZetKLjX1<@d>eDht3p<3wdhG1utQ7gv|GQeVWye+D?YaBnGF?7yy^qp1)3w{ zl=C45$)NgRE8t1`0oCfA?;3#D0|@_GvHL;cO}Vh%{(f+M3buHu9QJLV6FZ*w5{|j# z8$kqgkHVQF!PC*#Tre*y{eN-wmQhtkUDxmd1W{U$6cB0Y?k)joDTzZ!NlSN1NvL## zf^>H`NF&`T4Tt8?d>ilk`QGP!9m6sF;ehL0XYaMKhDgI4f3*60s@_(?Z z`rvGFoH*)WE2!Q*KKt^j7hKQDQZIEe*)A|kL*{ihiZIif`k^W{A^*QW0eH%^a4{@N z@3m8`$#=iCoh}3M`{#OeiMh+!w<08)Yv)B2*yEZSr3Pko2uccwr0d15-aY`S#95)Ud?{PEpFB)pV}EKbwk@9EPkyKI$T z3b9{jb8<})VrOs05ru-z;Z>2Wgps3Lqw?54Yb#(rS)j?p%Wvo7DnHL&kleS6QC_Fj zEHvyok^dP-C+VymkF5gCCuQtWIdW&C<8-r?SbIJ5fauJ5_ecQlbmV_u0nn8F z$))|>78xV%@?Tj6-#aVd*=wnA-3CU2ofqL%;H&9bJluAUpM-@9Ik7bsf(Nu8-V4j` z{weKH7XUn(EtkQFYEE&HUxPP0L=>KD6E+v$T`~!T@q;shxR|MbPg}cPKUk&+^WHf- zza{yT%7uvvCiz*gdW3cbZluRsE+T4ejRhO|hF;+Na0vWD-yI@Gc($y^FY3e10Og;b zq|bKl=m61VpLzXNob_&GyL+fi^Bt!2QqMdc*{|PQx81ix0D{3@#A=~ zLXCR9at#jf!*x&Qq8QCP4?w1V4%}ek`m4tUJ?{V1{1uX{Z0Wo11-{^fq*k^ibYVo4 z4fS+ab(`rv-V60k5<%#7piTbp^#FJ9iKN_oRys}nw`)ET&AABEd+Ng5WUhd=zH%mJO9_c;a&Q5;0=bd(iRiV z8g~qqg%7sC#P0A3B1+2F>ivCSlFmd&x3&EqhywPeEdS#H!U^++)g9dQIxJmA6TmJv zhiw1p&Ig+0eUz78L|K1nxk&Ybj9=~~Mq2&Y8uwGs!Q%mxXK!KG_*2jrk1j^XrCM3f-2CkTtf+!}%1nHjv29Qdt^ zcwZ*ws{?b))GA>7^pTZB<~I;E+~d3aIAhY$w{%Kr^rxp3{zOmkP*9o8CFEY6NRQ`!q* zxup=sz2n9A5|$F`z>^y7ag@;2PT>Kg36Vl4u5njgJGIWL zy6nt;6DUcuzb-oc&wWPIQm*1I(sO_?9Nb$lK)R)h=&~hMUU$(8wmnh)aep`D{YGuK zO|MtPoyNP79cYnnwxv|E*d%&@k91e!`Ea$`_S-J)DIgCY0wF&bdQ|LO!?-|f%U^T- zdXL^s>21+JBhcfsXd)f59CcuU+4KjPWJGb0KIk_thg_N~zVvU;k@?&lfeosupkb&6 zW`iG&o%e17!;gCUvS@CS_p3lg?Q$2&LzG?$oXM{?IyEfKLx*pKz0ZFgdO_Uzgyu7A zrl+tE>NsqCs6Hk~S)z%mS#nl)-U~jry|S<>-T})q3xVtM%O#o+#aZA)J9$6+cSeVN z_Z%QPSgqf6>-?f(`RrBi^deZ#le+T@yp!meMepB!-4_d2R0JN?<|se37^iCrsEQd-2ncsvHC@B*Rtw&tNl>h>q3APY{tn`9a2n{sQk#&rR9gx@U5 zi>J7HI4%`&_m#+IlFa&*EG3-wyJf)J16en!Sqcdr$p~%s1cDt~w|*V>`me$nOm^u! zEW-?7N+Yz^L*dwRlB>r@IPIqVc8*0uYSrV97p1STm^{&zo5#+oo=bQ0)p<^_SuzPQ z)G5}k$pS17uz&F%ZA(1<7BEy>Xf&Gwuy*{f^&i#ri}wW=!z92jYeCO5oz+s@bN}0U z000EfG1A8?&5Um+bL41sM}Td0k$qbNn7o$}{9fYcahBxaP&Bx%R>DkYu_QqA+&-_h z38^CpL#NU82rO|09bdGkoUS{{YHDKvSi%WFdNGhVHdY0J+)fTpNlJXOev3Kt{y7+H ze(QG30M~RWlD+Uku?D%I>5Q$A^D-9U`zyO(vdN?f9dDAy#F202Dk8X87;oYqBF$uw z;Ghvu?0=hT^x0z&iOnN)GcRrCyW4|ZY?J(K%q7W(84nSYNyr;PC9aS9wjCZk$H9nl zB<4K%;0z^?)&%tVTiJBqj6>xSbNu8wr0;aM^RzD{(YuB-o_E&eE zMK^q~_mwoKM-tjw((L?oE8~c6J6mINwh67?FTS6PtIlDUqBb68PWLnc7kW&}1Pr%W z%-3x(Fo?Jqf>9K#1yH_!4ENEU-%l5PFbk(%I}XLJhQG4W`D1Uh;y?Kjk%G z@frt_KZ-A<$E$!#nIkaTk}c~Xbsq(Dn~S(IFTTyb_gS9tY5oNq>_X^XuzSy2iU@#p z4wzhDd%35`U5_<&e2#j-lxPy%R?lIM%j|wI3|JV?7IQyT!aW=UYbh!Vx1p!rAgcLe z>_28O8~F0B{+~m{mE#JIt(?_hxAEL+lI((pK}}ynQxn)-5VT+LRPHs3LjCDh0dcL1 z&E3uAgLn$KGaf!jCV+3?!C7>AqxW1j(4cu4D-j?h9~nWonx!iS}sF}T5y0VJ#0&rnSkUxRn7vUr?`wMv@Ov8^X#`7MY7LD zW_4wgWBa9<*9Wm*t08;9bBG^&+}Fcym-Qu0^`;BoC+lyAz2Mek!snt{m}Jsp)6by# zSNAgw2Zz7<&asx4q9-`5N1NpPf0^_$deHiYC9f>{lg!uJH6gwZ$;hQ^zPi)>ZRdx| zxi^Ez)PO`c(j+rVV=;Mo`%Tr{<9pn9)5Y}NrbPzfO+H!|3en?12iW7K#noK$Rxk7~ z>x6h0!E#2nBY(4}Qbk@Wm^bfmXSW(7xeTGe@;Q1TSxq$To`w|?;%UJyl`Y=j46mMC z0?|iFLBYw%iGwp=ac(`ag#~sf>!+-!3QLMWZ1IpD)ottb#OQ48uOrXrZ%q&L z)I>>AiYg~s^)$a{Gg#bjRC85&2Vk$xZjnC~Pmwn3+^AsHJ##K?KDCnS8-}=wFWES7 zbIQ+=9Cel3DBT+Jz4x$5-x;XxmSFs<5`-ApeXz*fM{bYsVy%4fsqRoxGGENnA1S`z zM5*^UJ+-eL1Rxf#WE!Fnz8z*Cm{~tXM}NU-{#CyOs8rG`EbUe1YC1l&Z~e(QphN|a zJZi6nU)tQBO8fmH(7EhL#FD&?@pV-~71`tCJ!my8eNl&hs+Lc8_W_ctuy@go^hNNj z>(j~Z>?ahR$jbiWA!Am3Hh0pQR`4l z7%NfRN+3!G#re&kjkOl~C(9%(Io#)6IwBe-R6Pdv6%ut^bnhtN?_?am*my_(jwwE{ zw2&Ws6zv~B*6C$+;g7$X;yvwJ=?DfpVsqXmj$TrvMKZ2PhGzSSPdXvXnhQ*T%u*iz^@an^u z%wKN^2`MArn!Cj~zqLl2<(c4qI{ySb{3_&+>R}?LPh3-7LNmTRW`^R@%J4e#xo&&7 z(}iHwS>-K1o9I+)q}Nk%)H=n=_SCPKX6%#=&+;zc(6|2iv7s^f?E@>X}Jp zqg)XG9Hl$Nf9*83jwV%3$FZBI-gYfB<#nlOPs^|)hr~~cWiH$8-?(A74NUZ-UHDU;2DOB7xGvyo2JE- zHW?(LIuSmo6rGpmp9LsLvqe8Iaj-%|L+^thd-rVSyH2N8}h(1S=w zyf%?eKC4LeECMWxHJJf>@pv2X`N2>CR%de(3&c-Xlax5mBOb$)X0B`3B0d6M-$xZ*jfUQ9s3z_dL=#eGn7 z*LU*CT+Q?aq@Zt~kYVFWzxHzr!nwwkg0R7JVLHgOTudLBdaFx+s!-BlGKpCWZDE6k z{&?RYRPu!*>1daJz8b|+v8q}!luI+`-loS((by#9ux6?Yl_E<*S)NF|IDRMum--F8 z=tp7perxM48xqTpTTVTPvsaI!aYBfPxVW*-A|~TUJu0%aJd-Cqm7fWSzQmZ))XirR z+QnV`IrAq5@$}P4&}&nCl8QsO*XX9O5}!&bGp&Fjp8P0Q-=8>7_Y-EFBm4yV%h4s^ z$eae+TKKnW%Zd-j;BhSzLV-@>rY(6uKGo*#HaZmB>BPVE$?)_=RyShbi@pA?0G{Pc zlD))>hKzAU@Ul}hnu8#|^lp()B=(QV0~d8`$(jl~mxw{nPEg_=qv9miUB zd`LWz__q|_?>f^{&^4grX=RHzm%gmD4Myc856gE)V!MuVISKWXZb`_Gn?JIXe(P=t zU~8bHl+<&4eA5pfPGJjk;IxMs_b6)wUAQ_P!1h!hKISU2zn8r{%S|dq(~&!iNpVSR zCzgiU{(z1^$xW+|z@Qe5LV~$*^H7Lwq>&nT8aayF)UKB^L5$kx?8o1}FI~O$QrB+_ z(qxFbL5X{g?6exXf0Eg*6iC0Y_lX*OUeR&Yps$uA({Xy<>N@AUvU3<*QqP0EKSZ2C z9(lK61mu6`PP2K(RoRF8#=nHDgoonY=v}@bVS2FGw-;;ibF~hRhQ3jm_s#ht z&}sK_H4-*_vyVHgp6v6=V-L730b{;Zs zOq6&PDYN;c<;P)iWivYUL^%Z;Vl554dD&TqM%I__Ut)0N_lH-lU*&tMC^N{?T5^9x zQ$&PxoJ8#VoKfJAKg%SQJA2b%RK`**W8x3X@e{Sn8~bnufaZ`-M#m^ zUFZ9dv*?F66N1$1S*jeVSv|A4U?qC5^PwpxX8$h#@Bo>MmOF3A3XSCY!>Kj-p>^@B zB18Lai}6R70g^}qs6fmLqbdGhGmq6)USbwAV;O!K_gGw8G9Au-`CW9VB7f9}W$Bs;0^TZ<-*x1d1UnpD0T<7% zG$Syqg5Cj!B-Bc#zDVw0q5ZBHpE6z&W<{r&t-nor2zH%A(w#==-l zdFo5{D;|y7^}kIorHPOy^rQ0}ozI})K;voFX|{FRj(n~zGbOcjY_ql1)25|oZ*5w3 z$>^-td3$?w2no43zi4~0`-UQptaYYu((L1>vE#|10-**1Uyv4a64R@6w>sb$mFQuV zxYkewLTr;ni{4$YM_V}lQ_?k?GA{$MdyKWNt)DA|Q0nD&@BEy0!a)?S4BANK?Pyhk zG!eo9>1B(5tEOe&F|1qR=lF{v}5hsnfRsr zS9#p^Q8HsfKc%&szL<388!(mbtrtYy=#0$`w$0t2=}m06AcZvVi>UB4&Fs-dwF#`z z0pG$C7CMVRv?8{H4%q@NAB^ZqL;mY>(xD#kw4(;SG_JZja~1z!!}Rl2`z6`G#h&wP2Vwy%-aqeh1Z#sm}<6@LLigX$Ay zB$tQx#oKEffK3pB8KXF zwd=SNN+ea$^@;s#+PG=>({~G88OkKxhE8`0F7E)9*1A(C)F7mKGr(1PhAgjmMPsjFu%U1RE&F>4avLw z&De8xPh>DCZM|r({!2AA^PSm&sRBm-8nQRVXkci$WF4o<3hrz+Q+&SM+}Dba{E#5p zkOm+1ty~$Mp*+4adb6{IjVpdgs;M`=aPP+g^Y@!W7X5sURX;B?WOIb?j8L`CgG`qD$a61O%DbAFNH2# z@sQn&*3{bQfJ;{{B7O-0%1=1t#%r1RGVVC&=UNLR(`?dC?gg?r<>>5!ezrLz#Qfc- z#7pdBR_b^41oAQcj8V4@5l_kPe4#f6&CpWWf>HdGT>cxK!Mwq^pJEcGPF^>fbE#&o z==k9soPF~ps(D>8CBLOvPS93)6rN|w%Blloe$Lu?azB^X2(d)Sq_ehtv6 z6%aP!ZSK)Ua}xX8X$LKxi>q2wdkj3yJl}qanfp~-%uGeqY0eoJ8;gu=zcjQ;ou7}5 zkKzZ3js0r3U@Z9$v#@HfU#t+G>-vAiN-gX4cM0;7gai=j`5zki{BC%q`B@2T*}!`@ zenNAd;Ot*Ky8I7A}4ta3*Ztj!E!EWpb}Qq3=4HGw%iaA3KI_%Ef+CNtKqQO?~&#+XeA zC$e|;7C@lg8E?7DZ|pu|AT_>vTh^rGrGsaCn|pZRqGjAv^#nbNoY{xsd??Dw>d#n6 z&+@`iZC;NP{<;cGd${aGX{Foc3wINN@X@7WMI4U+9xQke&X-%g%W2HS{Emm*3Vpso zq~d6NPDml?b+gv&^#Vs+stSoVaKyVfEL)?vP$n<0CITB7for4>m}CQkBpu)sk6oQ5 zup!~n8eKd8x5PjM+7Y{ayc{|E;%Bk%6SOa$;E;!ODx-&gT$KJaOwA}1f~dY5uMYN6 zUt1S*-}6E&hV9EZM4}yuM|QOJ5RX>hgoju=8TGs#TRy?N@u)tFwWd)}KZ=Wzt7b8d zaBrrf`?O<;6RmIX=+&IrC90hZRFE6{*-ETf(~}-~@QXJYRI-u!0j?bKdxPGUL8qyE zr-VvjEi?1P9xL|!z}zR35)xzUIx%&`){n_M{peg>g=LFYLUlH175Zu(cfR}*d42Cd z79~Dl!s~l=;}IT9-Dl!u`w?GPKj$}n2{KlqdgJ=fr0C>Rb%i)})T|W*uV2!NUPVms zU9R!r)dfA)iprteFvGGJehq~+Kg`EG^27heoyhOnqe8x@3Y@n>@Zn#L?7sxMZm*p@~Y^2|2k-6YP^osC#%)@((E+z=5?ws?Z)*F1_f6`h>YiloC=!;E-|Bl&N`HJEvWI&iduEr^n&;B9 zf6Tu$%2UQ)!JQoJ&UcRfmBjMIiqFRM=yKOo6q=o`^o5B2Bg z5=c^Ae(%@N8y=lKo&06o^MiWjB2t;kbf8%u+$V>LS39;kbEC7{_pYXLov{d^N1o2k zmf^Gb(fOP$Ev!4Z19#vwXM+@Vm8TS}d>q zaBT((kwW1zwof}ZA+jfgeo+xQ;8#jq))w%jkVs6c6Ppu znckKcmlhm9rZa(QlHff7-hh)0=t?j5`HHVDmUhDTDJaQpocl682lm!V5sO|cQ-G9- z%=>jJ$cavuFzuyt_h?1B0?OBhjZ5Jt(XKxx8!VHxQi{xn$J}x#B!V72ew+?0t$~_F zufEcv31w^)j8D$=ph!Tan4*2_&(pnp{s>&|wXSN@V`@J(7iLVNGxNKv zc!2$1UwC<6HXra0UR17gt7vj0lx^TuZ!U+n)e2>Hki?tC8gGkbJ+Bg0gT`uJY$k(u z{pjV>9XzjVA8-VxceD|V1ciTB@sERKMX9o^IN!QSPukG9kfk!oQ)F;Z% zkar11Wn=NTj4#P6yV}yrT22*xuNzyyL-e=azM%*=MSXveXzTNwIE#R?3Ud8P<-J)j zTHmwhVgY9FNcD0`YPC*>AG5hIe(cwdeJ>zb6~BCP38v*he0-RYySrG65@>j_IbDqb zp;16gKlo1_ExwoOLa4D6w$BGLU6?iZCp?+cy}JQv^&obieL?G$ZBTQ5qwX^{^WGq_ zwtS+Lh=K-R9e&#=`0UoY>W4)OF=?|x$Lv_q(o4(Y5{AWd+5cdJ;T{(8qfdXwF9i)5 znkJA1-yTHJ2Di4vHp9S?>jg)ym|5wwgZg<3BPb_NB6%FcduO|nNS=B5K|?qVe*l1~ z@a`gT)=)2B%l8h45I-PGiz=}FoZzO0+CY+)Q6NO9&R}L^w?yYTg%6IY!(EUj^W7n; z*5oWd9PTV;+nyRaK)PKY zuc0E&-8uPVI&b-%WRFLe4dIv4aO*R?00|iT5#iI%t6<1mNm229w$*Ej8Ir)++iUVK z=uP7w{cbRFd~tWc>&-jaC&R7%18j>uE!TtM1KDA0=D@{p>(_5lo%45@ts>*y+Gc%+ z)6j(R=O;mwqf6bLmd2dM3q*zd{_m3qw-9_y3PvY4OFU$uv5$kE5DQW|Up-T?(=AZ? zh8GYo^P_-tG9O1g#N#J`NA;w95gswKe$|JSI|CYkU74-$7;uj;`AUm-4SzukaL}{o z-)sH2`Lk+pqQpwDsk)4`&`~7C9hnLQI&MqfM6SNSNepG$RMtf+!!|H9ZDTbc+`_N10uT?}s=JR%5aGvzERnKzLb z^Mj1#ufHZm#UN%8I9ataJq?SfcM}6&h*mU(?cj+JbpFo{eWVrLHUi#LWM42znLKDp zHcaFq%{#X<;d)_sYTMLA`>(!F#zABCV71x(92;DASy+^a4kZ+}usJ+@9LC+GS#4=@ zxoDd|HYu~v_|mGq0)2Sru@t`Yh5?kBtPueVtF~GxCPfvk^e^PoY-vmpY<1

I5(v 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 literal 0 HcmV?d00001 diff --git a/docs/source/_static/loop_figures/loop_monomers.png b/docs/source/_static/loop_figures/loop_monomers.png new file mode 100644 index 0000000000000000000000000000000000000000..0b8d39609bfa987bbf4e3779210d5ebca689202a GIT binary patch literal 21313 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 CDNP6f literal 0 HcmV?d00001 diff --git a/docs/source/_static/loop_figures/loop_templates_template.png b/docs/source/_static/loop_figures/loop_templates_template.png new file mode 100644 index 0000000000000000000000000000000000000000..55da3f72bce5efd82db3c54385fd4c9bb269918b GIT binary patch literal 283741 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

TKE%WD*yXJt@gUs3zcgPwp~r2M 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

bH{opKE`*$w&hoG`4xdBL^-Orhrm>Bn1JWqy4mj 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

-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 literal 0 HcmV?d00001 diff --git a/docs/source/_static/loop_figures/wo_loop_templates_template.png b/docs/source/_static/loop_figures/wo_loop_templates_template.png new file mode 100644 index 0000000000000000000000000000000000000000..f99eca03abe609881d1ae13f41ad817b77fc8b1e GIT binary patch literal 107678 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

niB15DP#}q(2M+im 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 s*0w)>wip0REtZq#{cMX9tim;e610Q^4q&j0`b literal 0 HcmV?d00001 diff --git a/docs/source/_static/wild_cards_figures/REACTER_wildcards_Diels-Alder-example_ed.avif b/docs/source/_static/wild_cards_figures/REACTER_wildcards_Diels-Alder-example_ed.avif new file mode 100644 index 0000000000000000000000000000000000000000..0f0dd51673b1577121fdd08abb8c08cfa6c1598a GIT binary patch literal 19151 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 KC`)WN-(Dcf_3g$0 literal 0 HcmV?d00001 diff --git a/docs/source/_static/wild_cards_figures/prior_templates_template.png b/docs/source/_static/wild_cards_figures/prior_templates_template.png new file mode 100644 index 0000000000000000000000000000000000000000..85f396ee53e5bd1ed43ab1b4b7f9ac27aaf55845 GIT binary patch literal 431550 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

|P)h5*Vz{^`E%G*lF^0AR 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%0A$;-xv4mLv% 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
^FP5`LP|}R|1qH9Kh24 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 Wm;2KOMe{_#3g2RuEAzy)o?^NRQ{sh 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 C9Q{B5 literal 0 HcmV?d00001 diff --git a/docs/source/_static/wild_cards_figures/wild_cards-templates_template.png b/docs/source/_static/wild_cards_figures/wild_cards-templates_template.png new file mode 100644 index 0000000000000000000000000000000000000000..2d6b09248f60b6c1231e8c4d06f489581fdaef0a GIT binary patch literal 310704 zcmeFZcT`hb_cn^6U;|VH6a|h*QL55ADk{=DNGOrsYv|nq2nZ-h@4fe40tg~fLq|yH zy@gJI5V$LF-uHgrZ;U(cU-zFozCDiPpk(j0_F8Ms`OIfNGXaY7k|futuMrRskVw6K zrA$CT+>8HnWsaG#lUEeDit*T*mVQs!YijiNR-==51`iQ}{%mxjgoTTG_}$A6w#ofBuKy|9t%atjzy81pmJ`4+|A40)pqTa*Gj;DkS@pXV0E-arK|h zaW)?JTUW`fj8#}<$tO^!iJkd{-s9pH;4L@{t7if`!AG_`IVWpiCI#UeaEvZu&KtK1 z4OYB=_EFQs|8E^gzMKvir+X|#!hfvNYSmlb%*<@|4&m9@vD|q7c3iVwiHxnibUt&g zUS*=Qp9lzi2;Tb(6A+xB?AmBV-F7#{7rXf@&kp{3Kl}OpJ3YdZp|tDXJ(28M z|9KmBqko@5@c*?J{dZ?}k9QDt+8k0>uU@T?Pvo^2CgDf@WA^LItrtZ%&Zfen!PN3J zw)Q`7M*tClbPy0I26c3FWOAIl{BnXzXaa&k{odpkkKTO!gFx7{8F{| z;4kaR2G7Nwgt%JDvtRb+m*98XyMJJSF(WfGw)8+h#S@!E+1U$nuAh(5 zozVXDYi8jE0w3d!We2CF-s!FwZhummm7zQhm8gFgme;A8kYH-yckq2gykK~IyzCh1 z*%QrQPmvP%D0D_~M)4SR{K(`u-?j63AG{(w4_AuLyC6U{)upDUhR_H@*dkT3LSl;N_>d?cvPfm1isJBSddY?Bixzy^D-E+WpdzuvgdjjU~QxeyL1ER6K!{ zo82etgD}qU?A4x+_W>JN$wlS3Q?4{UQ5)1VsN-Y`rG3*NW;+)w{cy$@yQemv|i7S0O!z)HGhddBf+(e)id9#)n|3 zA;<1@9l0M%OOd@j1|6)V9W$m+slk~BmyaL#0D*VN-%t0y-0z>s|EDmNsCd*8Y|z>L zdy?RYpX7_PwOpAwB8}=NyJY7%IFcyp9`Zo2KSL(!=O<$R{|x1O_9Q+!wG7tkPyvrO zYUnAki;hu=i5zCzbL~vwIXM>p?#m6Zpa-zzr%Rz%%9j4bB#U2moHLtBjEo!}^gSEa zC$ep9@G`;kGIdp@&d+e~devMb)^g;s4Mn&Vvkb*#WkbfpO%_(xkwP5{t{5h{*ulYy ze{b{$>wcV*Tafg%F1PY+18GM*RRht*_v5vW85tQ-P%l?-&wqWz_RVTSA91GeIZW?h z^vRQj-nXYgKMaeUBe1K~1}R!DJ5$Td+^*Ym|26Hmz$Hy77=BrcIAPj7K_3^(2b@r~ zAM6yDwje!p`JV9Qzi55fYc4Nq^&jgB`jwIcZpq3{7H?iwu8IaPTOs6ie9)61{D_{u zuztHEv+(lS+{@pt*%IHp1MEFw$uQ;tho-Fg{S@@GYZf0S?TH-wKfFAZGvfH6$MYsX z6v7T|Kt26>m7M9-t5-b#*?`yPAC{?njMuVtWXg;>`+g2wtN5cIsrQGWhD5D;@R_p4 zUjLw1ZN7{O6~shie{lOjgwV%>EB-Re#5{rzzl1*5aiOlx%E;h#e0VmWmDo)t&^S5rna0bkMy*=&r+c5RdQ0RUe%BlpZYtu zG=*M*r?86c#mW1oAtD3O-pL>^&hJ_){ zZz<&O?JYa#E(}Ix?cvDw+E0=xsQz&#Rr$iWq>y93y4cx{it8#h>ST~h6d5%%-!H-k zVsQKy0-I=_w^)hg)=_3>r$*|mH{A7OiFaF3={^UVX3;PPYZG%^--42z-YeF^BV}W6r6UF7i&%aK2Q7 zy1rBPEbxliS7KK#jHCbkS$O^K@fy+0)Igw#Bi_O$XcelrzJi3JViohVwO5 zballXmU=U zXumyXhZ;|`lX(>f*{~Ac{hck=!szRqC-!aUSMFl!QONF%M8tGI!YWqy^`lziOqT;m z@q1^hdGjWi`-;_k)R@LUS;9@7>b1MOOgL)~A27fw(VwS0?rAJ{CRT+xhjG6-G)}iy zPxrd0u7}j)k{L^_`XxFaxs&a<$z-U6vJIees3+Dxn!nLW&&raKmXWdek3Dt1k-0~( zH_OLkV&GF%Sk8j~m`_7fX<;D8$loLJuGaKm zi_D&@ZVTP#S^=lEzv%J0wA9o$p|s=w^&G)qQ*o9;xicN_+0jm`-8w%ZB8q;_1O8R! z`cPjjqi4K^m%~T<7yXMW?tA6stvM_Vm>Kz39>r=-4@$^XM0ANpM{?+x-+d!3E&c8t zY~AD>4nVE|_rAAtq8p($Bvzo8i-J@`tslKxC6gUq|BEJWKE^NcPb*Vc;m272x*O}PR~85_GB*^Qa7k5e ztUAv+t`jhpt5`P{|15F`6J*5d=`mgga^GFg~5k8iZ<2(@T>aKU=gx9de4 zj3b41oAlQOZ~YL`D%jn1kkWv9I{qhwau5O6sYuo)qqe-upR!a|6~wK60R5$=Iph5@ z5#Hd)YjI1xJ0TTIWl8z~zC9#|p~ z8lZDIohxTYyZSB&71{o`{o}2@$+an33j=4adq|u0k{VgDD5bbr$D%QC@p1f<7r~QJ zw#Jy5Er+x}>1x~n02Z_)Ni(Yt+Vwc0!Pb4kAkDvtV*+-IZgOqU9e ztra>O$@Uo_G!)4)$Bx?Hr3rtoT%Gq0$;;0!ostnJ?|OlT3^1fh@Y=+pwbJ2Y)C*M5#*>w6QC8N?LCq!Vg02Z=c+E)6Lo38czon-N{__nvAIvWJsOFB^e^(H0y1Qh6l`~LJLV(qo*8=OC-qHhU=H5(Kmm6 z)Z&TKy1s95q8_1^gL+c+P|9f1Lp<%hb8ULZM7T*q&NKLK)0MqIi$KVkYi(-%D4}v; zP$J6I7xMAs$As0#lP{UK$ssb*)}+B}&Zi$ilnzNviz!oKxo+>#U9Pdx78Id#7o3UO zab|}W;n*@I=1x_JT0&(KqJdvWdCsRjf}=n%+omx~@IKBn@!TY*=O z1&YIak(<%k4UZUWZm3o7zVNel)o`V9yKx>NOfvvR86yzY2%O*(-+*3_D>IrcWfxrTNmF zh&8^0eb`xCk&@2f?1cCnJpw00oE%GpQ5=Xa4ywtJ4X&Ja)APH1Y>3uV3LxVMk+1K- zKVCj?cJKw1`+BD%;w6`})Df15y<6Q?ErAJ%;fT5u7w^OgKq#p<1yT(t$Jrqn)pF%B3+Js;)E|=eYRWt0~gt1|lcbB)*>z6vOzp z2l=gWDNeWC?ED(L#&6$>60p!zO}YgTItC%1Bb2ack;x1@-FA4|VR>OYaBtAhZEiNh zzfvej!LM?Id^jg*YVM6K||IDcNC)vt}DmEto6dWsOyJ} zvpw}u{|o{IoCKX-e#uw!Vohdy`u?q2-1hUrQDqk{XYmb^cl0y2O)@0+8&YRnj2Gg6 zT27$-g+8o#ckv(SM3>_ijZncc=dM1q3vg&)>l%UZCk|JHxD=+9SQf^~W5CH96U z)$kf>IcJ)(J0bVm@R4YaXL@2%A#I5m^E-MZgJ`)(DW*7ZHYTPFXM}E(alpKsugvVi zO(NBllGfLOSL%-sW-4RMJiTtxxhwvEmZrIAe5xxGr^{r)}#NE(XS= zJ{o!$yWEc23H+pN0#i}XkdrhTG;w#|I#Kh>W69lkEMvIty%=xJ{&#Y7`~2nd^to0d zlnI(Njnt%FUvpr53(56{X32R|6bPhiuRLJw)46_ZG~Y854jv!5xE``(XV%}sn%_s` z(Y;1paL7Hx&h*%kucq1Fs&gb#yFe_vdHZPGeQuptA>XYK+0|CtbKt47;2bdAY{Q@a z_H4}FF+lnNjF#w}V&O0fDe)rj_(iq z5;QA}@aHa|KY4IefF)tfPPS;R*E5J`i(Y<+1u18MeWr{l{xdw(euamM>rQov4=d<}1 z&D)*{uE72=FIaPr1eW}?-LP=A@xpljR^)NYdAefCg9obgjj#L>F8BCRg)_K3hE|3w zH~7}@i&}#(`Yj(J7#DWluQSoKgBumOzU!qBvo+;*TLo*>A@JEZn+E`oV?5^Mq9U2k=fjzkWZOXp?C~ z&9Sgv+dzruOHA$*`9(V}K7H+Xsj4#QO_2axK*E``x1DQ){3RH-M;Z|yuIyy!jt^60 zNVe}2lhhzX#jp(?-&^VJ;=+97S{KMwoe$3vIH z4+oFDEAELr+7El;sNG?C&DQE{AEr|A4(*}GUU zjEsVDf!vn+o|Pc4G*snxuX^MBWjX0~!c(T&$!L}PP|=c=(Y3`QJld%KIbfkPpsy}# z>a%+80jU`Ah;xB&*EJC%vkzb1rl}5HyH%gc0fEo(c>AGsm-u1c4r&XN%s&<^JKT)T zXY!3AZ8w+;X+;X^;vU0_Y*&J2$KvzYB`Z#Uph(1a2JbtoxsIk3FcS0KG5H(FJ#x2@ z1yL=?!zDD`5j{8f_d?EhxZfXDPk9%^BE2v>{UMm(j?D_D>0|VTaC6UB8j~h}{V zr}y4GHy|S@XrgM{YYByat?Q8A@F-8~TIgJi=kkA@Bt9K{f3Q)ax3liCYw5O%7zkP+ z%`Guy%&L?g_Y!Q48tFLqB5Gu$EwiYMv*oI_ttr(1O#euC`W|>?m${guitG9($NijX zrwF=Hy-5?+p5h3Q&1XbZD{;iNXBI9TyWq(>;PvaPq_VQ#J zl~aom#ma=Qkj^yhW7_8CNn@yUywF{+Rd&P5MMcJu?hQ9hcehHP550;Y;1~K&ZEsd;-8?&2Q zm?Z6;kAggp!ZI3nh#jRf!$B&36`&C+4{-2P@L^2`nW$g zo%F~cu=dbYUgce()!~rv=uY7M{hLYgjF$oQ0GrM!Se&xftFfW-&OoS@AsDk}NM<$3 zOrXH^Rl)|PQjBJVy;E%@rUbtdUv$fUO*fetBInu9cDCuJx6Tky?x!QO+NiA#a?LvL zIKyCb@6k1K-Yk{jr&2+UGUoU0f+->Zr{O7|E%LnrENSk5Ye{>~RgAYjX@Ke9Pi#!S zkX`Im>EI&TCwcv7@*$HXG^^tKQ{1%EkBA2c<-pB>6DnM<^JXtgXrXv%=|IT@Ax6WZ zk_`Rv6h(aM-j*X*6x)(|n@;;dfWi|8M?L`?+J;o=&@DzmRk7s<&UmJ8a6l>97ic?o6^sh zwsRJr#<)+Olp4m5?Lzip+~jo9p)11uFvef`nvXsm7@n=6?RUTiDvHN>Ttb`NuU6Q1 zt3Z!8DN*5sRWUG3M2)|*ytJF4(Zbpt_ut!u2xy$`WE)8*icw8qZ@R%RYGp_Rtd^W} zMAFuc*sjPw6D{YK`v!9#IrZ^=lVRm<15Vse?~b*X=xWT90J03py?eKAr3!QGj4GX< zv?-7B9~TtKB-d(BtT<==kTpBg`-RuAQ_Q6PmFuo2pG~sNcw*d>*M(AuDf0%WVK4FM z#yd&TNSxBWeekopxMkNBtViNEID9{FA$%)#| zWTdyAO6x4TD|QU!7F?z}d;LK|e1_rTTy#=7(di;JJO;=hy1w(aCqs%s>Jx>w z6WLcka)zvaXl2RU7EGD>+t4-oL~Y-|?o*+BHAW(wH~&^%c-g@#y9H{5yi;4wC*IkI zb~^a2z`F&9iV+3V*uZHg8jnMF-y}H2?a|-HT4L7aQM2CXDTv2I0zyTy2I^`g=4h3f zyPVa`y;yrp6Ct+~1(yHbHvqI3P*NsNoPwLpBv&zBH`ltxbu^X3%9htgvycw^209iF z{vh4zyK0aM23-?nD<%uR(U&YwJ*vZ~=4KJa5>KMt26m!xr{dAW-+c;`4Nj2QZsYrW zY)u*e=9G8u-Sw%pui5)I5QXW7;k}X+cg*|R^0GuYgp6Y=rbcqNnrB&0Yat##nV!Ru zs@V+>;VF}EUbAZhUA%sIwRd2qh7QdU&)RcJ2$dhXlWe&qTYu8*k~Yt}CCXD;=jRl$ zw>BnGw?f4y7@uqJ%{$t_4`;B@sj{HMG#bD9;^$n(rg^eL)}XT0CrJlb;8Dv;P=F&U zwmd(nx6(3h_|yUfCVup*vpO%|bTN&_s8U-jtM>t=Jt)Qq zn$hpP{6m^@3oo#yN#4Taa-qw>5*akY&uaK`4`n?YWDZ&a{SVJ*|u z%b9UvhjZb8#w&bRqQ5!y^TIL9*{qvd@x-N0_o?o8>~^GcggeLu}T|Bchg7c_OBPKhJwCMIz(C~0*^M6-@B@dOMXQvsws~C<>+tf z94GIwuqx`p+{6))Vb|Xqj|x`qWqluaRI||;(=@iByC(P`#Kv<~>pB(3+F;H=M+7Tp z&0Lt@$hjdwF5qXbU!=N{XYY>nD_M<#)A;&_dzXopF3vAPaRz~zj6`)ps=_)cIYphz z`}|pJo0VNPIfbREl^Q4%=5%5+qDENenly|r($J=Oqb!1E48m<4ynH8|XQC`zwA?ev zC$fldni?e)<=pp$7Vsv2D;SsIn29=23yzmxGzi5_V;WC&bgbdS0iG7lHz=T({pBWw z#!(#ksDw$ zAc}R!mi=IP>yGtMMgnhX-J4y-)BOqOSmKUg{)xxSl}Ky%wUS9KwuQ;#1^$YO+tk!Y zC)kZi+ZK`_D$Ya!yO~_Iys+@_Pw(i@j<0DuKE$>!q)oJ~yALpeyup=3FI*^F!ccLw zng0Q6j*)wvr0VgKm$+^iE;Q$LQlkOs)m5J93)qv0)_avR`Hp^NLIwOW1-IaSs!5)) zJSWX$nz-7cBu_V2DqqOOYA1H<`mHxrNL<2($6{3@uAtrUXs^gyXO&$~PY)FSCqSK7 zBmdnrAboD!?Y;7^!=eP$qvr{hJ$qu-h<6-MoZiQd4`;kKbIGcvi zr(eN5gc}dLZMuwiIK2-$AvOVDz8uVjD;W30*8p27FE0l*XJ!Tlo|idiOO$MckDzrD zSrHm*Mkre$0K5Mf2FmTzR)?l1$#PRBxTw{ApA@Y?Ck;o-ulr3>bHCS@?Y{)9_kGgL z)ltsX{9B@fC8PCd+fMc>RaMpFO@Hy@p&~CMt{AVaAn2f*jG^J&$II7^yP`|LN&4~Q z2N=Jtt&RUb<6k}-Ury|({l|m9Q-y2+AT58ZJpwW=;~S0mZ#|YogV1%4Are$x5&f}-WOC2 z8lo+R^S9Pu8^|h~M?dhwH&A-L1Wdak+up*W0V8ul=uBPB-{7^bs;M^8-Wp?Z!^8+s zQNv55B<}I8`RPso!I3WKeiJgmb+?guA4q^vYF7(2%Zy`WGl^+kl83cGjh~Vo!ecd7 zUSTof#)T2{Ji62fv~}R>y@)4}TdCSq7uZ`IBkuqQr$>4<6wN=p8hi;I3{ttVH!Chu z2~1QPbS|s7o!d}ZWrRS+ZUMTBc6j@gcia0EcCYHv6@^t-^`{yNkUew|~3 zoT4NuQl4EMQ(Ndt1Z*R*oA~B%)YH6)8Y!}n-Y;k>i81t68XeB`y-S!wwrh4D>bkAV7Aiga6z8qHr>f4F=8$&$xG@blHbG6K{u7Otq70Xk=e2b_O=?BXk+9mIY(o#z2}4QfDMbJnix{!^t6r ztI?2g*Tn?bVh`_)S>R8+w_2%I?PavJwcXr~Hm6(4N=ucMmAALIKkCf28X_yL;`nXA zQow+X7lfCUm5GLv(TdzXKIhm>tAn2LUbrb>!ctz;gw2?_5obCzalC7#lEp0}ibR5x zDw^$~BNSymOvYj3V%3ex*DMo>!FpoGG5s=}L-Ujh3tp`h8ZKOzV-LEvb8Udn@P{TE zAMrTYJYW6SsKs@sJ2WH#>$m%?dJi?anMgKhcgLnW6^ioVqcVil)&B2(^h?5LIMT}( z&?)}3vD_vhdUr7s?i+bU4Uj0Uv2wFAkHc-f7C$3n<+i0BYPmWd{Yci~m zl`>HrG$JmWK$ZdaCxlL%c8&flm_FwQbV*ZIJUtEP78klO_i;OfIs6Hq;LvLDqh;oS z!RCB7z1n=r4UMy?pu^RAN)HGOz_qKHY_~`_ASh}}O`19_8@#r|lSBY8;)q%$7C-n2 zJgjDvmXOn0wSH?LKpj9dVFNS=moJOSi=SBn0Tm~(bg{z~W|c5_&-&w_HNjuh1Ix#G zx710{4^YjDR0(Mm^RptV*ok>ONOjjd14$>lAPU1f=Z{Xn z|A)0~&W}VpW0VItmN_{&Ky!A@>HFDu$(q1c^O2lKmxVk?VA!GtEMLh8l z-#y>FOB*|^f$MwM-oX6L``um7K>v8J;->fUES>jG+@#BXjrVS!B-lS-Zmb%Gvhwm1 zB?iPX=X_&9U`5V#f?ioGghtIkr%MFR#T8Ap(EDe}%bExUW}?47&v}!xW^XMjJfcA^4=h0@&`O zA7i(1M2vq|4vNE zT6TxG%p0NXRunJ{3DeHA>5Ef2{`00$8avs@e|BqP4a4 zCr4?k>wJVp$jHL)`!<#Bi7?YtxW2Xz_SY1 zO-KD)(UyTGcqG-GNKPon6ZURw`S4l*bE3=UPhuLF!x;Pe`hpd$284iHjODekR7b z1CeZ+w<#!wt_<;&a+~yk5MN3r#hp z*VPmkj8Hmix?%7aOfXsRjV*c-RNU1h&c|z-Op{0?=X!p&;<6FMdIQ^wxIgc5+`DF^z& zIIH!s3R3?TZrXeI@P{Sy>>|C#^~*9d=qxf$%>W2DrQI;*9c5T(rx5}88IbX~oDBWB zNwRVW?{KXpk`Aw-@}P>FBMNUWp&bplVivmNOz!>;;%pEw`2F>D5T#u7)0E-5+vMb; za3ioU6(hRXtv0%<-mdX^`}MyiK(kN)ZS?An<>mGN351nkOI=^?=M~nnuzh7x!7q-_ zurGdb06Q;;Y#Mhb6;7?ow|s9!v`>+p-3)U5)au>NZl*F`CbN$t_eDQofwZylU?vD4 z(`N?1FO_rzeQY;$J2_k&x5mhD!spsiZJ~6~RUO_KEI1=Yb?Dkq@e=_Nk@{P?Bwym= zA0XuS!B*X&q#XVVfVBI|eV}=4Yi;G#J6E;w;1#-)-(01W7F`?X#BH+xjGtb;>bPOOmU(JnBf(EI#_ z!*xLOC;~SEQrEM&h#h4MnxNZ4Xtb)V6S|GHY8{rRTl_74i$26gKQmBPQK@rW9sW#l zmXG&(0MGU?}KT7xwx9BhzQT4<*dYSo*>{@ zJMS^u0996+Waz%b*Ly+^+3kkr&FB8tbm0o>gL*-8&ScSWmgMp4b=rM+Cu8fuUph}C zgin;8-vOHjX;hRQAnHKzn*F=gBX{WZ-WvtUWX^^IdU5eacMO`4nDmBm4An!01+-Hg zh=$$Zd~iY=JPtOeD<&M5Gor>UD+dP$8D%0-PDrbb`W^YVU!us$KV~hgsl;_xT94Ou zbVwtrhsi8a@hQ$3f-FZTA1fj@$LuIQ1!m z=7Ea__`9HLV%rd{p*@Y84KAu%EA0d(3D#5Wc(X;z2EMmmHEI313%;;6Fy9#klDaW& z(~@^U-LhcTDW=!_IXXHzdAQhRYo=D=WR~vq0OT>xTw3wdBfx8#p0gSi4X)GWB&(`T z2vsJft!+A)Yz6f0!&`)z6TF8QT6tCqwGZY%@{pDEHI(X(`O${^MSQ*%-Ky^j5XFra z7wme~KtD(?k;Qr~=I}fw*y+?KGHbx0fCLn2PIBCs0JFCr2L28B3E*7j7Z!%Uy7!35 z$;l<~m??vZbMZv`Y(5Z*i_Xcs_BD>D`V>Ego>+}&tT)1KJowU+*hY~2>KkEiRN6WF zrnz;0lT_uooSI7kW>VK?m&cZqlXJ3I@6)JdB6#3tVEvNoevO8zst15oiCyCZ*IOGw z{{d=1YXOIuYy{lSgxhL?k0F{_AyFIdR$;=71qP+bJpteY-ih(@I)ac4ciXGoBtB=N z$nf)W+k(-sDMwTpPwFO+pggTT3T;=IJ9k$|xL}F;1EVg#urA9{aoR?&r*()vJ1)7O z4BagAbBIU>BK#jwQDk&t^#J_;WZRjcx_x`QM|cC}Fd&!YvE4qHqXGz#XD*vlkPT`s z!#}{%Ra8_a-8V$bMvp=GUz>^7-o<8@jJdC0R39Y6dh0cwd&NAEGGBMP!So7g7@W&Wn@nS8Wse`g&f|{tqlc7 zUCMmR)3l(yF`Gze z@|;|RPyf4pkiGjJqxR*38m_IS(T04T41(ifgOAjKHuhHoHA-`>n81hW#T03|koT!- zgyRH~Bgf^GrA6}|h4>itd{HB;Mg`%Sxs0RuiHXRZ;@gcuG>tgv9~77!Q+(smeeV<8cl@fy;#|4E7cVE7KD^zx_eDcg*9P5-wA3d}yo*{-#F7 zW}V5_hB_|9jjn1#ORqZN8ICEsr9R#a$)p{y&iF)Bbo}Yp0CMKiheE~XTo`aF+_^Aw zb90c5+U*Y3C^k(lU`VIOi$LhT4DbWqME~#TnAzIa7J84{ctdLw^d|agL8sSy{il3~Xutm`JIsx@nFiVzdl6CP6cFDbo#G}h-ye6z| zU$faD?dWTE=P@~B2d9z-XCKGMPG>@A@1&@&XeFEhKhE$YGaK6)ARyxeVG97+fwbJ` z0--tFqAU8@bxO8qKpA?8qCP-9#VGBL2~@pwcl6@Ik4O#Z7DSX%FmAHu*l8Bq?- z-YJBs3hXtGAC)R9$YsKB5bzLPbe__Wv=~{?wrU?*NMmv0F}#dT%m7I(a}1z2Vr-rP z7Qb88{7+f$`wY@`!D*aw$z;fLpmwybatBaz=GS2I{{u5Q=r#g4CR(q9>8wOI>HccF zSrHloKT;ZVt`h#M1O&-y+4idquRBCCq_a9mJ-y}<{24Uq^|7MWe@}z`kP(NNtwe7$ ztc`UgdQ&set5VxLsY}e6;EE7_#;{UZ;ZQS~!eP4Mfd1>CuHhQD$Xe8oo(0^Pl}sXr zii#z~M4i&ZEEs)r)MDvSL(YT{13*KPfL*Hd#sm(FA+ygY(D+%2|?pEXN?-p)#op;E<0R4;esP28VXFE!f69jUss|DNVSWqlZWRsTRP~=>XZ) zDqRBr=s9=kQL_3RPkngTVMpHXFhI>2opqNilL!Vs5*pzy%SJP!9^sgHx6qlWn`QRl!np?YOj2D}&7DyRR{t z;3iQ0JeQfVH5;+BY9BDE8G|Vo9zF1eu(qtTh?llBAk^daSle|s3Uj|12BYUh!l4JF zNWe}*+8j|Ix=)ni>h)>%_9369ohUb;>`$2R%uk{h7pTgCTrj6qA0#*Wn}M%_0bBqu zXl`MFiJ2Ljq`9+jK@JHf1&OP2>bzAAUxzx^z6>f`zIct`1z?nToUJ9W3TAE3)daeuxVlr|4!*UNbEy)&k)UqLJFX?;A&0ImjA8YnoEp8$j%GL>tYpmYiJ` z^0VD|$2QzPKWrhaMjPJ*&zC+OlLlQgFJ3(*;!&w_vg#R%1hyC<+A9aim0yf_@b^8U zc+{EG>5k`62t&SvhpfH1rM)?*9}H)&9Ply}TAVbCKR8BUjJSZ#T&p0+Iryq=#U=uH z5e4yk8#s)=lUlW!P~3`qqV@>7LgP&22%rVE9$dYK@Z%Ih%@0|sRoqA~Lh7Qvcrcvz4(sxkk=LEe? zmTA^r0A@ke)%gtneB;m&7y!{W*|B6kn@s?T6wTF!xPAjt^N%1k+ibHkZF}aKm<5zi z8mYJa8D75|VuXAWGJnUf(&%{D(jyHD z38AA1kEa&?hqrV@acKBqEt1#!hu$3L$-vK3kI4tOCxDXPquZgzF_Yd0dcnM8_0=A< z6IR_32#QOe~^Ch#Aziv$qRso7L#!02X`MQPk&s9dvipL3T&%C&XOOO|deyd`4`?$~ydv7)GL zCIT>1h21rvxa=4=73gBn>cCl~%*;7z%!?S!(h5;uTqD(Z9>j;5KfITbSP6uHH7sk1dZ64j>i%xc zXAmgA0Q=YdaGGlS8+rt%$rZwWXwf6X&xpe5qB6MQ^050yEz~ixv5_th6(kZY%@qkT zN}_YFIUk77-2?wys(s$VWU2~!yNtI+lz;0e#S5C~v*!&~N;LFmTr=6rktgtJnu%lG zB!NB{QRr8LWON8sb;0iE+O70UDY!*Qqpb))RY%I^f9X^^i|lurHwSv-UguApbaz|tnyT)w5iL`!^k+?Gxpa2F;(Z0(f)Yk4LQ*AYokAc-0T7S?@h`Sq!LP zZWDw4wo8{MwLcWG_4GrBb5dVq4OF98V5?gdW6si(wD}2b<%}AuWUH@|p+xzmbe!!F z3*Zwl9I$vHRc_kbBfPbffAKc>V&Elmf3vLl@`_grd6=E$XgKkLH|umF*$j~aMyNZy zCQdGP46*8XsVP#s2EMMH^9Nyjhn6&8{lVyL=}u8>`mJ%sdA^oPobb&u7X;dH-9Vi(|+5{+7n;XUJfq0hGlnsfkj89Op-OODKw00C3x z0Hh+HG#*knJ-rdv%`}0hxlAKcCEy#mIeG!6u+jL7r$KkE7c1Ry3H@^ptSsdhhAt48 z1HS2PzlrORSse)IdK1izJ71lpU3--&XZT-ArP+&V4_2QbqNQR;{ab&;+CN=;f>G=2y|{>wJbmG z(S8JqE2HjVXtOC@ZS8uy**AGZLU#IA#2hJh_%_sj08L_R@p>|z4~ju!l0*&s%YtsL zmz_NcOuIpa9#@g#i6qPb^n?3vdyUcM6{T>&`qieD%C#ujlFw~Kn*mHuQWAt-FPDj^ z)lk<5;-}aCRKC#lq5DLa7a7~v<)j(M)PVx%-`y(J;EjP^lWCDSkKOPmc!co37nG@_ zAT{kZ!Ggsw{YQS?~a@(?_4xmlf7frKV2 zkmYrZ|3wrCg+sxTCF+%J=&n6JVi6))y-5dlGAS!fJygcaE6~(PnS@jZ z05!eB3Z=8Op{II1Pp^r4XN^Z4M`BzS!;jb5Lkb2j0eyOZ?)w5deKqN%_w1zL z`$;4%Ff;0EeClKWZ}FB`;G6aRLcMXIVd25c zNw^t@%SYz)=YWO-n0@#4%d4l1ElW6f)JiD=j&as~n%kjZ<;K1`Y6f~&0zmJ|>MM{x z4;luq5A_z2grz66sjh5tq1m217A|dhaGQ4ACjX4C1>MJ>0t^Z$+<-#EhwU>kM)0ot zsOLSrl>0GU;nB<8mWLmplmv>O@NZJvQW`sNYD*5IyHQnk{6`+dxmHaJ5)(%*bJBn> zXnrOZJz0mwl4nx0a*^K%#0K@%m4$g^zd0cYJ(WF zPn>oQUA})}RS_L#?cHw3r&crX;90iQH4@VWw>b^fyXzYVMI`cb+YOh3ULm-AzWu66 z=bj;T4EFNYsDknTtjTLFua(4uQX*v#;}^Bm6A>HQ^bA+=P5f6I6#R1L7>cV?z4bXF zO~O&`^q>6e1Oh?$w;F3ap(Kw$UB;-!Wrvma>*1 z-hZ)hrm_qK*$L}C-?+&?ZpP9x63a@SZ(I_VZI>7MKv&(ZanAB7_0Exi9MIVk4sWYS zbNjPX`N`xyZ;mxAJT9)z1d*7Xoei)v?^&m^sr2`UN3Ci{17k%(-bAme)x4wsu@J2? zxj?W2AYsAS1o;Q(0QHbqxfNNyYv5IXb+uSaXCd%_`7Y@rcEGLXQZ zxgUT%h_xuxJl+>47nTHV)gy*nqA{6C93w>DF<4fvug&Z>#-gHvTPgEOp7qXbISwn| zjbeq>TIw!moCG0buC23fdgTbTWR6i+*J&4mj4|N9fqv#!fS%rmV?#V4z~1-cQo)h( zDrp|q^I)T92?rhTO3@3?dv8^zsj)uJGinZqKt#VZ4=C4(XkGluaO&hg;zvuBs`J^; zX$W|oaTT33!n#TYz=zOzA8+An8C~3nXxYpf*rFd~*Dx3KO|pwYVx!MmKv`OJK;EQ@ zkd=2cbv4{zt?$XVU75~sbIUFK2Ue8TU1RUQx~`H~g;a9jVW^aORrLa>yyAH3>lmy? zOEZd#pFVk#1L|up3h(SmoP7_4$2gseLtEQX>08n$Hoa%JL^;9@1HR<76fhwSr51Xx zNa?BTj7f!lCDjLw^nhn9*L4*1X0rKdK=Mvd(ahcO3z1{47}nuA@#URpwm8G&Q?b4e zFJHHYQXe2`9P9fGD?L2zL3fSt@^TIrf4fZtL2pNI_4R_Nfpy+UOMN}{;HAPkzvaVa zh-)2apF(nK*pp|h)2d|39&WafwKO*`^dw-H(n6)LRhbt~CM<*bZjeDOV51dre7@E708g89FVt>bmhK;WP<0%|Hg3-m&& zWp8wQuT87VDGb5}?wDUylp`Q${5u^o%!*=(s*4l^Es~X=hx(fsu{HOA)R#&*U^M+? zoj27V_{@2o*xAq*;LAa9V21ee1>lFGyB7e}0@??%vdo8-t@bJq3 z4?4`S3Mr0VEBp5C8vxH*d-fF0<0F%>f0X|7(aX5@wN2wk(&ERal$WqU}%nhXj6-$n0`j}`M$ zBS7H*2ZR#iprQ*%+DSR40l+(GCe(0l)!>_D|JM#;L3{`CG&9WGC1ycxAX)y!@oh+9 z{!7t@H_$}&nvKRnFd0-xDNv&qJkve7`6wR{v|*NfS^zN|Y|R=N7<^Laq;3X00rM!> zjHw4uN>@7ZG7F`jN8Y}b8?(H&p;!9GTO0lG8d|oF?c}vtd8#?-H5Gs0dFdIgnA1mBC+2a66-DxytmPo;wGU-pOaQlu#ipE)Qv%3OO+9oCF zxPBzFmqe3m+mUTm3Up!Ve+@UJ+~fekFnJr4RQQ1sFE>B`ftZI2sEWj%eX$M?Cp2+i zOgAy<;s3?fTZcutc5U1!TTu{9L|UYjR9aF&KmYKjqc}t-uL^yee8es;js^A=DzOhTGu+y^SAEQtUM@Gzq(g-1uym-?n7?W zl3wn*c$9DKg;8QZ)N}eyGtKwD*PMrc%5?^WA)_)a9}Hp|JQzOV*GO{~GMBE@$9Nn~ zqQOcJSwfSZ7!7c%S{MgNU^s6%L^EV*mqeM$CbGnrDHOofs2AHvML|B<>w#${2@C&} zkdP1&F#wJQ5OL0wYUtdSFUIx9)&1rme`8d$>{yVS_ZN8BPhI;g@bO$F ze}<@8JyzFzz3+3nL}t3S^d4V7e=(&^%?8+4ziQ>zW7lkO9b(x)lA#(iijn>Wc8ET_ zJroNdzgyJdExZ!b4yvA4H=Fa~v1G^Xb5g(9+h;7w4&Sn@d@S!QshzwFWg=v;^_Y*$ z@JUOAnX9uEe7Bh^~PB@R1>?r+}UG1>JQ19w-xNJQFlY0&295l zVT>V4wz!l_dd^99Ty;RfIJviH)kt2XSg!NOfFwR&#ZacN-lmTS1F%6Ay*Zcp;Vh1cT#rU;WhaniHNvp0UQ*#KS?UDJSbw-xYRM9;y4YS_1z_n;LUSDL?4 zsLpwyFL^5YKD1ICt%^C8(x1sTT<4LoYTQ|0e8oNzKM5!<+@k3QM=w}vO_IFSlq^3d zCS-cA;eMkaNWe8NHrxFTunmS+ac=HknUieS%RUohU%Bic>m){=G(Mi2WyBUeXmMM& zF^(*{v&^7{u>TK;VQO#U7rbs@etA#=Eza)@P}DeIEu^oV^d6 z35HxT#$bc6nG%-ylXPXo{cZ09Y3FVW$KPjev0F|qjPaYRHhIC?F%fMzba-fQ*J{6S z^%M20eU7NQ_(QeZXtmP{2=WKJYjGbx_WivLxZPJyX|(5@fs?8y{4^MgAIDiQ=zkzm zN4!r)p2b^-YVBkC$X)CqMcIdsLwSA9wVYndpBKcU-dAd&pB{Jf_0B>#kpZv~Q>AK1 zF7(MU`b5ujLsAADxj%7T359vl$>~-?SyxNQp-JsfF9|r^-dZZn8K|l=2Dy(@fuL^H zIOD5MIThAH+pD@l7L~IZzDmp$^YTDpo4Z?8O~rZ90X93f7dot~KL+CeTxp?s5cl^= zD@1UV^m#cgN$&Lc_^D(WusIG1O0Rsd$yT70e5(byP>*AJ<+Zq}{C;ZT2&f6hBp2r_ zc)uvq500-+fbDc^p*MQF0smsndLvOd{9y~ZH#g>eWwT~yDo8xSVYNQaPllF+^|?8R zyP)m+e?!BLl2|od-?@M#bXlZ}VxYg5N8QNmkQHqzv}&wux^0}~(`9-ZWS2isnTCB3 z;sI{ckwl#UX`jd@(il3Ka9s%h?vwQ<-Tj{3#_V~fRDx?&7b zUgLW;bC&a>HJgvr=Bc3e&E}e{e=NQB@C(9DRS*)koK{2sCt)0XHs872*Mr^8%5w8Gnzel9`p}!N8Z~;f)9;kJ{x03@6?L zdhi|A(KY8uORYq%@Z{w-<`oa``dluNxl9*mlRK)+V-jf4M3K>9Yzf|EkV5MYQ6At{ zaO88q47_Z+GRkD9<_`5Oh&#q`5ID7((0Hb*xNusA#UREZ1g$rka(MmD94-_MpFT?G z{v=s-F|%!`Oo6n?Zj%YecFMU=(3(?IRsBH0%feBxi&BNn*3`-~@$<6Toq-__S#o)~ zGp{m-%;lZ_Sx(azs=X^gps@1BtC$*`n0}h7bKwK*62-Bk22q{)mx5Y%`ib!!%@#5X zD(|~3ruc)a01U1uQ0vy$*U?bItkLfrIZl=}n5bC?SVn9=bN|bLG47F<0r19S9rZ%) z(C9^!pS#(+>bA2RvgbbOARtUFTL4(BBKn3Pb*f(B+BNKEP3?T&dr15_)%WX>|9sN- z95fI!vv@-s;fvGWv;5O2{hb<0!1g8I=OUMC8oPm)|2><_h?J%N(JrA(;5kL)4aQQ{ ziqDw^dE{{-9=i(On^%KcHm6UHaYt=I`V3>WMT)%_TEQjinj!qKi3rx3&R6Nu>VD16 z8@wg5rFyZWawkVyfjgQ7<+DpAI;2qqt{W_e8{v6nyBFfT&|GcV65-;%t5rr7wz2id zapL;?kf73_X9t+mIyWeoz}&;iYBAILAx&y%h8_plD?Qsnl5vFWtSm`?4go6Y3rHju zCHX9C$bC`6-rQ?Bh35&NyJv{qFmu|`LCI2{P_Qe#xPkL#`mDd9g^Lg_Ad!&93jt-V zYKI0pB z9w7WV4tmd2eeo@^G~)@1fjgN#fr_ej?h9=o_9Pmb^B)aYv)wR1Z|i6J`3=EEVm5bF4wrDkIh^mYU#2>R+!;u><67VLdcNc|7}IpQMDEsx**SDC6I|nCK^{ zxV#kwuU*&uJ797T6Y*ydwcLV$J6D|H;{{J{q7neO4dp>NZuhy&K_0_t<(J$3@bv`2 zv!ZC42^9ky8?FeOfcqT;Qc%1|odH&P&Yr$WBFEycLw35NgsUbQCOtBDgo;I0mP*t8 zt)d>I5xh0K3Wbg`95U`Up`zdWX8#f4QL_7W9LUCoEcXQ0LMy$f%QXMzlJsQPlbrC? z9l#EJ!bRq2AkQXfrvqZ?YQvqBH4pvo^dK*&lcQdCCJNs@X?^P<`kqpF@~@23Y4~FZ z%Q0(Kc@vD#sYw@Li}Jkfw3uE|Itg`yk(e>bhYME7m7`q6l;uYN^n8lLf6?!6C7oE_ zXw^SCK*m{D<1%<)(=aX+z`ZorzcfhC(?AXRgFctbMB%nj&7Y2CNz~Ao&YY*Jb$h- zys=lUrS}6=dud!Zw9jK|&;Y){vczQEF+@FW9{4Y|^nt@Chp|I66YNs6_wNlEik_HH z^KFOz^D0vs&}bi)$?Er7rjK_k`uh4X(>^|}!Q|m23B!{_UdE_!DoJUs6Va67o6IcU zjyUYY`scG^A`>~ZIt6ImoP@Trna}WolzZOC_uS3?pAPBD1$c@RR97xf+Q_Lieg@U= zWq4~G8=bG`GC#}RkeaQTtGS8X{*Sgjo<9T~yN)UL>A}FGr}F32=+@`9mj(!pobJJ&OnaKa)E)Ob{vYaYL688{fUJs?xlWJAVdJmqU*SA5E6r9Kf7uhvwf_G zWVLHuQmQWLCwNtx#N;-j$a!Me!)pCoNFL+j>=3=8`dyLsH2Jffh|RwLi%Nw8Z&8ma zUMx!g5{L%K0BcaGGM)u7ZJPyGKYIz@82K!RqrHvvHTVMS9hiXZe=DJmfNZ=zD%g2V zE#cEXf~I;&ujoqqMAp-|;j9mdahV=u%cY?+G7{rEPuv}M01yG0YqMRk0{Qr|L8{?~ zska3Ul54zl9vgL$JwKHHlQTb97NXT*QZCd^ig*#Pvn9S;6N9DExG^BsvhpZPyS{YE z#*D({;pB{>7!(gYIJx%~XWeN`;886oUAn(_%su0hN&mt7!VOml)6?%>2=D!Tvo+rx z^!~lZ*XQ5h_Qhb7_@g$+u~mAWqup+~?|AeoRTc?E?Bn)k7>Ro(I3GdELuOdZ<6U2d;XHV;@PN<@bLJj5CNRbEScuZ zzeoKtoT-^93$mCSWo_x-Zb=L>YWer-Xau=632e8DoLSKW)X0vqMM2cOB-tAlR6hp3YE)BpLwp)+lT3H0f}*{)x2u8hm^P zi%DOy0)@(xmmvS&?Ql?!jE3#a{<(zRyLxz+=(zXbRk}2$<+k;Se;enS2*HD5u$zYP>Az}Drpv9Z7gf9TL)Se$7VzoGm}U$3*f~>Uhez4A(4m_c z0SR5$woy6D3A;=sWzZ1(+-wJZvj;Q_FZi;3JpL#uPLR{}-eO)Ts@-0ZuiBHP$|_I&K#k(l(4q50J$oXoYO;8@*`t zAJ6Ok3Bk{^94?!T7xswa4u0YCZz~={B5L#qi$^ZdOCI^E#YFid+)@M~lcCB|xLG%z z5k)#t@a6>j@Yg(&{j%L(1O>FQpbMU5`UrC%hVS&#QBcTn(RRKorpf;zW_7gW519CY z!**!5yHi&5Mj9GBySF(yS%6hWn$?S*EWe?5Je>Q+L5%lI2=0JSd)J(&p~X;Gcd(4) z#^^Ew5k+-xYFO9K(+Ai+Dx;w-dR)A}rY^2TR;eenbGGZ*{4o|mcPN{@@cih@vvQ?U zW%aKL+k;5LpbC<5M1D?O);Yn~pM1wh)9-%>##b)Gd$}F#5?tiPv5XNNxwE@i>PcG! z$??LWpY~KKj+9m^oYQNo&)t;&M=}{gh!2`W_G1Qu5CXP80R;SS|3>*D=TLQ%UTaBG zg0nFu9FAgB?%9K_!k(DM7&*K?HUODF7~qcU2L5{S_?kBu@J)K+V-gcZ!Eo~};nNRo z*?ges*Pxv!^*5XP{xZGw$zu=sL3{Q6eopAq+ecjk=L1ld2o?-c z*3z2oz6wGA0X#vgQSr}8Fn z>S>Zm5?>}^7L8U;FV+wOpHM@K*3Qt&8jeFT2-K*9Sn?M`-0BvlNC2S`f|bo_b)?^* z2r@KMl9IfC80n@VyQGTmffjJ|heK=!vp$fno7h zS$!pQ51$F-rMizLs~lSV~AT z#J)5KNZqaKi@Sm)6WN-w-zV^m!L-g1Z2|V6zgsM0*7rkK$tgXV%en;awXrxigDD?e zadSmE$Ol2RQd1|vCKCem#Qfyuqu! zLa&V542o)Y$1LE%z{+y9GhAVtB__44Ztiy5orgr5z)&S5HsJGi0pdT}mjV|pF zc5Cp~oh-a_NP=^rj^?a2tDuD@?%yNDi@oR$MOG#iiF9v2f5OOa0B>emQaLkk$oM>s z7ba{st!{cDME$hVga68vWzAduPpGSXikuHcU59N2Nori1VswM@?j;Nv$Jxp#QXt)?vx~) zK&I-N-DJfY13`pC4g-!S25TE(RdIPKa7FO>=||bKs)sYn!KI|;c#k8yxun;t`mFN> zgKzBp%Wn>_=J$1S?Dyl0r{g&80K1MWrZXp<1#49+I+B&8G$dLa_5^C32iyy`OJ62C zE8&{rww&C4<;rmOG>`<@m*q89kxPVLr3$oYF+P$#u4-nKAIGM zCSnj*s)omogR0J3I3|77#nk&a{?f0O!}^`Xyeladu*jFo1Qguz;k6PO?6}3Fiyu}C zIuSaSA4G+P2G9VqWv*4YtJ(A$?Z$an6$74KXjy&UUd&nNz_01~Be@u&rq_=a+_!=p z5N)nTg~ty}?YkdWDSId^&SSP49U03m>V1GGV|tGyF=||!@^#?R1#;ASPdk(B_kDGb zw)P*56@+ILiX^tg2K)~hB3Kf_XZPl%$fHxha|+C<`bl@6P$|qHecI?cN%F6~s0+#a z6a%s^Ui_LY*iXA(8YR-uqPYSaMwkdkt~$m!LPmY})7qi?+F20+akzw9njxeeP1)~M z{bk}dU-+zHBo?*fs5RG)UuS$>2v)t(wSO{tt}mdImh*L;o{SS`r9r7DmpL+PQ{(%~ zu~RRF)+^QPC=5C}4N%p9lfujK)v7GM3oRejFt5#WlUI(TYS!BE{mC3hvq`$iqk^e1 zMyr2G4U zF%@~{ex30c>&{F|2ge2A&VD~4mgKD8|8=ZRds_q3tHm7sFYZHh@95&&3xF`ka10iO z|GWk^-d9mg;PW7D$~FoBS&NJZVghhrv(3+=@}|6f`X{V_Ktm2eXAj6h3&UQbWY zx?~h`@J0PI11Re0`!A=6nbmt)k5==6uwI|kg(O#sQNG9?+1cisi+lEro@=0_j#$@V7`d&%ReO%^b)>k=)O^3vedh0wtH zS7t*z*g39>!brzMOQtwYsGIJx;(7I9uetA+x+&aJ=E~TLUL3UXOd|RgjvW=|6QR@w z?;ya4!)bJ>hf@lXF*sasm|ncy#)&Q3Q4puHsn3wZHIXthy6(^W6c~*T)zWTVKRO<4 zRcCN|;`VhR|76`~CMJQ1q|V+y{k`>@v&Y`*8OoYj+Yyc;4rN`LKarDcb7N&2Uqm~V zol|-~<^EvI)x7s&nLHQlWjX%gLOEr}qj;hqikJ@H%5!%t1>5H)OOit%cU0$Hg9C-T z{*MOjG;=la1_`s_OU`j^nF*xuoVGHOY!4NF6|~E#zdbXbG2SUtj3s@r~9KqAH}SQsO8ij8Psjt z=(TDG)92SM@90>w3nibdKGQ3b6U6kEjHJ{USan0R^_uxmH@;KnP4BQ%b>g@xVRD;6 zcX)K#F7t1Gb4t{+?r!e!C;ML+Wsh;a+U~G{bRr9dS1zS!nw-16u0&H?my zTPRs`ckt;dwucLdj=A8=_Hj{*uGO|ZZz=KuL-%lYQu{Jv|0*dnYk!Ys1_{>KsNsim zsC|~+sNKfVurgT^O@DC3cC)*eX8Mz?UNMC%ZMcoFz_;X`A+A04n~3KodTam%>GfZQ z+0}Ep3AcBgyYC+He;3uSR8`2xR#y4BY+?3C$vQ5!$H{JaMw$u=93qvBAiEuh77&^Z zOs;_KMbszrp!~dE?L$YPXaE*y+_HRU1&N+SRQ$;#LEm2%Qj=UpParR4(Tb!|QWX)( zM`FQP?tr$ z@kFF6RqLs8{2sHN|AiQM9V>Mk#9;K@bra%gJ9Mcco0Y2L~BMHO(@qm6T(x7__|Bz4%4jLXvt*+U#0uQ(R%b;R?8#KCA7B0Tk zdFPzemyxi7!7Wdne?VJ`O`>Z@qJ{oJ@vcU?yA-nM`s$C~Ej{_eQ0$AH4teAr!Gd~WVkE;?&0MDC? zyZA07Qv|7ovfUm%YKHqdwEeij*9i_E|F>`B9bW!R*^LXyNl#Qn08)Pvw0pWDT`)!G zbRIp);-i6nHSD4v%PJkN|haPmuZy6-qZLeg=x*vQ#qhs^A6#(1<{6uvBobPlMT^P^&&12KU_EDb;lQCekG zHpf2r-n2AaE^Ib(M&ueiL-w%3hRFdXrazXO){665581n=4^L0jVplGhHNCj6b1YA0 zQ8n?-yGEr=cGgk$M~sLp(Qqw8c9W{h5KZNR36=J4dOA>XfPmNhu_FgKpjb4M)B6kF zOMkTbV3)% zon%nC{#EA$O9UN~vaRnuWUEx;r8@)|okD`3DmM)+ZIZj%c=>|$KP=EEKUz*$b!$1r znt6bqauC1h(cE@|vvF5yfStT7VG7@+X$cf+D=zIuL0o>?Kuy8I4c{Yxu`3M~|yiHM3^V>F_5OvtW62IrYh!T}WQd2SYQQ=qtoT>v#H1#z7PX)-^>x6vjGw-A=z$;dwsZHTUDDlQS=-jhT; z_5Iu!Xc-jhB8H7iGP1I0g+X*M2pN`0AeOp&63iP*3+U>P5` zpb|`DsShiHJc}EO<0MEx{%~ZOQ6|Tpb?Z~o3j5Hsn5ya}Z-P68Ke*$ZoNgtZPvHfc zLf^!Fov|o1R>|qjs_)dHlg=o&tEBGR>PHp;sa_Lv@G+E}j}MrWuKyk%7rXtP(Bc!u z!FE&D@#Gfh9`cH(IEumL4pc8nK1-Ml1sJvL9OzL>OGlLPVpJ= zAA0o{3yVo8x$>iZ56e9PZeZbfm(cQs{HNhf2k&1|{30eEdhchZ1QW_l{d-Nd>w3x9 zI6e+!NNQFmK1G>&;qKxtLLqL`8;V9^YG9|Ox=uC645iMbps{(5-$mENO{jt3_}RHo*KM6mPV#>xzoG>Oy%VJ?2@psvPB z)Ot(&bg3>CnCro-c)!i^)k{704Tk%5WVtMh!*Vw#xT+{{Wgp6u*R}$!$I=93af9M_ z2|i`o!R{O0Mp&m0!!=9Q9=;f5b4KtB$m2l0@t^*~jmPPew4%zB+Lizh*aPW&wR58A)6&KHV3UF+V|C4c2_b(U0 zv;^WJWbY0~elUZ%^$yqnd;pF0lAIq( zGrhw4nZ^o!nh^3Q`6rU{UI+Roz8(ae z%*gWR%uiHT&!Onqj3JF_7VyoBux|pVXblr~M$YZ%P&9ot8F}=RhN|{=jz{NS&jf-2 zI>Ru&1o-sDi3w2x7BP%R6W#MP{t7GoM#Wllds_N8aV8-9>OoN@GhIT1O?9j38gGco z0GuX2W&m98b~CL|ddVjWS1BZkF0g6;8YKHS*nE<$MWH{8Q}?`NDhcG(hT}4+s9oq zh?2A?x345MS3B8_{gf=@HT3JXHuc%&-)u$+IV*|3f%E-t;PNot6xFYD`rvLxlPKME~-i--?fVXDXm@ z_4^-mNx4W3YUgg8|VLnGh^18P%j_iB-+hI6jbGKL4cv^oTv~o>Mb^@wG?vuihd|=OMG} z?xO0H!BeEB|6*_H`GVvfH` zjc=;{%JV8-NbdYlHFglDG_zB}N=izxdfKQ^#kxp7DkoX4s->fB#W02>X*ed(olObn zrhSAQ!*`Jow3kB2o36J+oQ0`85=fXoS9u-C|T(K&$`Z~u#-NBM-mF&rQ{;sfX>&>Zsvw zxbUfj-H0Q*)3B*;Ov0X$EAF+Xvct|c6LlGZ9rpVrFHG^xf@y|Z5{CEoiJHgt>|`q} zj(_@uaU-tNdSNb~{Lk|*^yX@b$t4Eb>~z@hZBF(ZY2uvaJ?>9AiV`5Z;z73Wd5W*p z3!UyCg%iISJiLZW24E_{?-LDXv3S(0jJ5xdo`jyh>n|zY7AokmyYwuE0?U5|lA{&C zAo)+M5kE+fA+$a_L%`kO5)gh zaXNr_alGzg7LnKjw}Cpl4%3V+O2i;hhvQ(ugaI{cSgs=9>7*uGA=Z$!==N(<83i^E zDVXN2W$Q=mX4_nWyZw9t>3I-oIN%_ zSBjf~7+a`CQF$?bb!YiIsyOzIx(aLLpx##IQk`V+p+J*po^m}jEXKryGXBcxvVR5} zJenE4?X~qET}lTw#D0s%JEK{+KwsvR(F?AfgWWAuP9Tg>Y4^5vZ%g7l-omu;+Q~qL zkqQTrCRUiM=>ORglo&_9^Vf1s$zF*%Or3wG#ebK;517w`oa{g$ec`tyk+C;h62CJJ!; zl5`>XejSHWvOAnCuMX5M6>M_*jOJ1#hgXf*N20T8lL~U!N%}{<3MVpX*H;7|}VnQ0P`x3mx#^x4vEVWL? zj@PL3zxRH9+x7^Y+&fb8a>R+p)Z0gnCx;WbL3l6#=QYkQuuv#liJp1YHo^P% z)_$|J7dVVVgmeETDx3E{Ad%QH_9PwJt$w)huz^}g)dDbv@kj)`kJ1< z%NdvsvF32t8P2A-#-Q14PL{IIea(5}oe4k5VBPBjEQhj-aRk#&#tf@gS`fzL?5pcN zF8COr>_)&W2qO;<`p2l`tgPj4j4V6-^ISC!Coq`{{M1EgO=tMo4ks~T?G(d5+x}*c z6M;jo-Cf57qba`ZDfVMq|M+7>^1!V@N}l>K0meZ{Z9|{!c#OBTV(7&BhX;A=NmV>* z%tr-gav3NZcwh~J57b?_OJVRXD?nlYLhZnxadAW)w3oh3uhK$a&TD+66=_{|%OBI$ zZFfR;l>Kq529}SXzXb`opg-tiV|6B`h{P9bhi^;Q$j1syOyg*FvAObjpFQ^S4a3p>ujEZpd9{*1P*w;C^thQmhrx}A z3y0?W}%tp1@^QVK}&S!$=Aim0d zVFsc&a68|`u`nxt2jY3-@|x^p2#>g>U1ylR3hN3O956Wrx3q|Qj!Uqg3wQaWzL!G_ zQ)1kaXzdd1@I6rg-aOW+_!_d2vgRJwwUEd_<+2pKSVvD%x7qaCiBolUEuek@`*Eb_ zSXOYLE5w^PTp@I^rPoU@U!c5K)w@;w;*aWc6)YK{-Xik9$UH2s8w`u6FIKVpPS0BN zT4+?LxxD54X;P{)$;K( zC9?vqXrn8g(gJ5VBz=b3xANb_(xQZ~o#8$|?{rqbNg|e5M_e>2{&nn3Hi4>{-bA(H z<^)6G3D)XIs*S3G_3hVw*JM4?f?g62Sl(?tFu>q5kS*@rzjB#2h|&!0AzqsLT8J)P z^v6WQWEYxrcxagKt~Hm!vta`AvDT~P0%cYksP+-`+1cs)mrlkRLiwHRbsP#mduiQp zD!zU2sd#pJf#Nv9Ys~&@LxWsJjCz;o+VA%qA$Nz2PSN5qh?kZ~2q9Q#Z(j-6MNJC9 z$ZZLK5@Kq>Z3qbEYgY{0*}uIcevXc~d-B3Lx1XPB)47A6q_A}y^m6P3p7aE&N6y<( zGu|zA^^UG?9-A=>o9uY%-)lf2Sh1yR&uxvZ{O!N+vTkkW`Za_87iZX7c6j`H}CvUsOYVl9)P!c^$1yX0=8|KX}qyki4y)5=op{@lYYU)f4gC z=(K1Z`P<|-w+AL27?kKl7fC!`CM10P_%7q#@iyaI9$WLX`~pNM=7vdycNCS#;V92E(U5<4`NcB# zGsA+JEYiFS{Zk~mRQ*llU0v7#VES;rnhG)(a`$KE;&J`9-MVTW~8vWBu)t5`shQDuAz|DNiymp>eY0ha<~+<}AAF)| zyjr3fmYoow;Bz(URHi6?vsyuQcb`t+FrTT3KZpE!*)WYh?faJB-~|0Z$&dOTMo-G? z0_@gm`9R!SN$+7WU2zP%yzA66#~!P2t5??hSLDQs5Mg7e=*g27=N%uHZ0(b+Y2)3W zL)dpFiO+uXy^JXG_xaJ|M*ia4oTi=iL+wiQ4m_IqTkCkQ2~uCuFIVrck?Jgr#GSdh zusqD1<^A*gBb3eRWo-cmKXz0Ao_=jQGMRYy(Tn?P`tOv8qh-YIhn_%xJ~Nq=O)!Mt zhWj+$o+sW}aYvWda6NbV=#K{<2vKi8x-Xa$9zRr$OY-++z5 z?3pLKA`jStCj={8F)CgBwJJvYfk!-b&EH4T#>Gk$gcf)4gMBZpt@V#y)}`v3$ayGA z%yK>GWN#+4=w%y?h#`g(bCoP?P(JW$u0~oGWmp`ww!2lFd=v@TiS>AFIoC=W&)GEY^TMuIsu;QVm~B_e zwjiomUuJ@j@>S<-858?~t>05~$suR?8Li(2TpUcVnXjoIFA>w|HykdshWcJQ#a`4v zOS~>|gRXiI@Ay95TOM9yB_T?Y6l-|4sKD9I@?*x(*{9DU>poqvxG1Grz}8{Dfij!9 zUhC%ROTz8uy=x{U^xnx0RlSinf4q?7vx}ZS0lT`212en^j|b9sMC$s!hjaG-xc5vo zwlExpX8~ZqMff;tlNLL7EeNr&42D-RkT;lcWF_v4ZD*6iG?akFHG94?Okuh$nuOg+*R^3K{Gshd z&ROK_K@>5tD8gr$Jbv zMyTtNv2j|zmKwD6cL}bs6sCTk8osU@-`Dl^9dj=F!i5VYw4%ZW&F_KO2?IX%V3rTK zMVu0@;TGf5)4tCE2}62fWo=!+dkp38#`g9q z<#`IPiQ!!ri%cb5k+X}B7n!>LO^M5Ow5J`iVZ6LwLSRm z3(;}@*|NQVaa7V0JZ~%#tEPm&E77t1-iB7jEu)yCxzSL+*5P*?Yq^f+`5io`Xhnyg zx-W;ow+1+$zSquBiAk^8;Dm^<@Uq|?*oz;b2hDkt6eelUjg3BR@0U%t4mhK*veZks zBA@w{?``e*3#CI^#-$QPrxCQta*6{yY(ffAWA1JFl)6Xj;*Pfby;c4fsE#UM%aZP` z3rsD(=NIG)<{zn_Y}^p&89MUt|3SiuABq;W$a+_Jkl(Y|UCbRAaXAfPU`by+#2M!%AR@54jdoWz0trt zvb}fZrM1akF2_@g^(f$@3s3IdNNENvJ|#I_GT6yDlO1`^c zPE&yA{EA*nxZdZ<%ctrVf1i_97Ev2#E&bX^dv*OGzXoN)W0f?{22=SzD-&DmRBpJPo*5lgjCr_kx=*ZM?7uE@JN=kn9|_ zJX*RM$?U5^=a z>k(-tqbzQHzo)@_seH%j#9M?x`BvKJIj6|HXNgH2WHK$oY$EI#jR%Jx|DkhwkJ`R0 zz8v(0?b>$@J@s}%*((KGd*WBob$J8_%J>*T-sY=5t-p;aW~rL;0#oH*9iBR)c7;xj zIC*VtwX3TOW*&(GN*$(vsBb&C*xG(sNyi<&)LR$~W@qO^U?8x)DMjN;gt)Vx{)!p# zBtt6Qypk-pk)%hf$@spvY0mK6-bccFQ)E}QzkydUSHbK9J{-e?Mi2GB`xg=)AVb>) zJZY*0MG~H>YJ@bOo{fB1@LJ^@t3>7J#>YoI_DFnBAHNbLAzq1^gqLVF4NS2#+noFo znIN)o^kSlhU;V3&AE}9**wrBSMK2*AMlT0){`<}br@mL!++SJMs(ZYAACo-tdMoW` zYNDx4R`fPS?w;_jm`ZW!xwkrgSMGbfkS`FAIqhb2?tELWP|*h8 zHS>hIo3k?rb;qjq1cDoZU+rJ@$bXT@yi!{J&_?~j_5%g7J*^XMD}uXKq~5M)m<&)e zr?Rbx(09WpN>WNI%vP_MYSeQ zN*eEKg_3F`RR57(OT2DC{AkbZ23wWOhe4Ccgv(rKt>layg~<1g2^VsNneU;Z@ucolP#>i@g(52(s|8JytUt28n5C|oK{fvQ z6kfaEXFI$FUMDYPTInq|;hue!w@~3$c;^)_2AFkz3wfz#pU~WLA@}TX^ppTG5vF+1S{QVXED5zP56A0^B&#RPG5zR(A}ZKfAZcAm5TE=li2s zo7|_cYtO@|XUIzHqRMq6)qhMN;Hj7^OX`ZgQLtj&cZlbbM}1cL{G*{9lgEBv?}>lE zQEIVAT=$f5&+N-CrZ-AAi_Zu1>HA>8-A&iQ4vu0+R0#Wn?9;SV(%*F_jWq9P5Y~{r z6E2U@!)v&EUiD)o|7N@i`cLL}OzBpBcxXCUaMGV&iEGf7x>xKEb;kg81Za zD+BG}(FLC&_vF;OX}1J+eqNEvKm9DTnV{`{r`u59FbM%uY6WGwxJn%&{S`qrUX%9o zleet{1aEqqjyU#e#F|$b7qfyz5QiMKW{YFlN9}2gs>k~n5{q+c+EgO}_ma>@QdT%DB#Qep>aLVe&6c>mFSs8%T=_-Z%$ zti>?8sLb2o)fB8n7;_GBgmfnY|7U4U`Qno7t)uO2JQ5NC>y?f)qKHQUX!$8Zfg1|! zsEDuMyvZ%MGt(%~{jB@E-(J;Z#OB7Nt9~J#2k{F!kxwk-b{~$>nbaK9^J8#&o(Q8baZCTE=|!Gw$r~o_vC1;G zFLnQR2B?=8Vf^VntPiiDy(;vJJ(bsAZIEq2l?oSmJ|j39pZCFAFSl-qPhddzl@khK zp*SM%zq_xaff<9WreiYEpPj@8k>)0hk?U;D7=3r*$m~pS)y>CnI<3?)mX$SJT&xPB z9$5Lg2pTtFA&&gNV{f1^rfdw>79sm*g9oKGlyrB!-Cc6j*2CY3*Lz^l&cGHLFupOv ze<9m@U%s;eQAB#~j*qPO+Q%CaMqn^+XV(Y4Y5mv?r1kPG9+~ftrUs!F20!fcwnKA| z*y?%UOZD;Ja@e1)hbvBmu%ew_XMT32Cg&2j*zMo#o3T%|tEJyuS|9q;$sA$O&hmvL zjP9$NowUjFstB#WoxVB1h2?idBwM%rfl&eFV~aC@k`q#m0ZN+S_F`JPsJXik2K6i2 zpc_-GisfzzN*hjV!DmPCN3Es^Au`Gn3wPJYp5Ro2O}!aB4*lcf)#b6|;QN{vgHeCb z%^2wDPhb|(he#6b>0Ndt-k%Oy78S1*0aq$*?r%)Usjuo=OZN6wFPjt+M;EOKAMh*_ zoeq{ET!oO}6~$MgV5Z^qiok{Ud>M;TV(>4@NUYLg+zb-wDdy~!$g2F=RGn35mbiTK zT2IVTzU79^5Yh9(mIt@=$D}pr!c1&Zsyuqv!7gv|1Xpk*T#ZY)enJ4YjtgoK+uBM? zjwU(+F4I=fA%>I3nR^%?zs2gYZ<9 z+EyPmFPsPF_Rs`zQsXk+OC4u<{X?A;cPiI-&yPPH&^m2#64HD21`ZfLn3LC|9tYSw z>KQ17-01ejoAkYMvA0Wa^WJ|m6>#H-_~xRs(zt;tUmPZi=ccM$q0e2o;UDMFH-T!I zU&X}F(4Z)od>j77&FwTN6x?RmzIWto2~?Q5!ar&!t@J;|mX#fX@`RtC|9GL14WQf> zzQu4V3h>?begTF^jC>4KrEILMdpwD~$6Dn0tsF)PCDzo)w6$%+vXB!mg2R&s3;G*W!Q)-i?*f|G zk|>StvnCB4jf~h1?4UP8Ejl_lC@ZGf*9(Yd-~W4}w9UD~*f0&FgUMJX77v%namY~F zMJj#~s(;FPc=eVK?;_I}or%ddST^SD>NwKkY)H@pOlfj5zeZrKlg)(tCf%9GCY(x|qJo>!A@_U7Q`i zwmY9&_Sad1UkSl;CB-*>un(KB{U%tBeD07;52$kLKWKl%Sr`y1^4WASvT-!)=WqMf zF;jv7{YumIAt}wx&39lUN70rHxFT7vz_i60;~^40XKV1G0Qg}UpoibSmn4>FY3ORL zNZv^(dM=386XvM#v(#&KmPLMQVm4ZHAtkB_4G__a2n0`AeB110aotvRQ^=sbr2hx2d-|9pXLCfEQ3ZK%vt z8T9tjkAy-g^2z3_k8^!0obgi=G4aBp!4*k)x-4V@)uSn5LzsRK zNgk)(CLc%dH_foXBdz*aPUZ*d(3&9)v|7?CpZzzM02j**d{$F%S-@7zfk+U8qa_jl z53D3w=GyYLBoHWOJgAv|wb)rW+EgYPjlcRZjjll=XZri`U2AI1BP;pS>e`wu@V$T` zlR8cIW?<710PNf6yQ}ZO^Pwro$&ErE4k*{H+Wv}@>t%kIFfSB>7hiwjgbA%I?j z&=q6ki`J|Fhf5^V7G{tvPxUoLCE-fQ{CNNImXRd$+gfbV^JTMFNK(aqcKXG=#77xQ z)>MA4zU{sBn+X3wes7CSH(XWmIRBX1cV^H(fHf81IuxNK*@nu({S^iET(&cvM6S>+ zBO?P)_co4>89;F_R?E-B!@~#t*TQ!?x_`cOb6&N4B+!07#iXSdttP< z$4zM_Z;z;9A;lUE@Gc)UdB382Rn+F=w{_3h4UWdUNwa=e>Gsw_&F9K2S$cx^VC$JisVM1~z z6au1(bBI9)V=h4<=(u9doE0D5Ho^ocRDam3*_-z;vYe_sPiW}MrHKB}n_Tdd;nC;M z$JfBO7B~z-pEh8D!8Xr;0NGIbVm?0hVu_ccBaJ zaLR+{6wLvp=0dBR6L8IgFIonIAXSmvKt3OA!MpN5?@R?gx~MFyFBh027Mf#YWz)SA zpJB!t7+$$BIC@PoV)=_axb}naufc^cyc@HT{7VZ=thMXNo(ewG=B;cUyGqp zvEg4-RKO#mue!brk-qMyE-lF1#L@3}H$on(?_D8{_n~QDaS4%Llnr2UgALHNP2>qVh>g)35?R+!bD zUXbn0ygkMSA1qg+w6qj#6?6n!kiq&V=oUwZbQy{bbDg5=J&uj{>C}5K(UZnr$mFYe z;2JF~TY?YSCS}=OL8|-G?VY28)%0$=x?_4TU`ENDPMHyW`EAIMoc=^J`Km#(Am;GM z92*OG3NMX&%ZT$55;Yt$XG@Ry$}8X1sg0LZ>rxc)9R(LfuVf@idWIs6g;`2q3Y&{~ zqy7=WjQ3}S%b|BwI29Bx8+ZL)%w9o$qkb(Uiz2b3qsNbt7)nJ+Ur~Zny%vbqv7UO1 z`k6lpbm~CJEUNoQo7H_STIVCAF<>dZxR*;4^J(KB8=YzT%d0oV zZ(M{^-IofhD1zs^YKnvmX-Eqj8D3T5v+e(`FPASW&n>x;QhXRDiP^5_!^boWnt%Hf zx{W_m2*{l=x(^hUK89P%N{7Q-cPjzpo=pJdu3c5jyALQNn7p;%lwD3+(ZA9?s%GF6 zT+Ymp!Ye=D)>+gz?ayiHkJu!0?U|I#zgcyu%^n=hYaQ+0+Ef<7oSWI>WC35sk6j
xdYuZSv3?TEIp!(+i8$ux+F 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 z

7&z}Z>d_dY>hfc!grA@95j7ktotN4X`Z%+c37P`OH)zzt~DM%P=Q?=D_0wMog z#kh(e;`sIRhOU>@aZ?|B0juh)q|K!et(S2^S+zzfKB1RSv-l&A3>|S|}J66wqvK z_pY0$HZ|~hT@jU1ODKiLUvXEFk{|D|ab6W^1daqMpKqv@Yf(=f&tw!H2{EKy^qWrq z&NNWtevg4uZtPsxwlzxeJ}W|*!(d9Z;*|f&^rVF*G28s7 z7X#u7MqF9)bO=ZR3k9Dw0S|ZJ_^j<J4@4;Xh{zBnv3*=!hXM5Da@;?Q)HlHOTvc#<(kR zYjfV}llOCO`H%)zN)CMV^y~cS*pgzGrIgp%)%E{_uXv72dUuRVP9SCO5>j{()n_|x zQ|_k>!RhG(xD<9MhvnBepD3KDe!WopAf!niC^o z2%Dq=M^}UFI4s3A0jpzTi<*-Bm~AoCQhVHohpk%&hH8csiY*Eb#&x^hhqK?i=yTt7Yq_bM?d?+_F3w5Za7fXdAG40k;i}X zk?r}yTY9$YPK_rL$40ux8_AUTbsQEXtXjl-ncz3@AR`@Ycv{U#rSS{|xEaAF1~bSK zJIE4~kTTzfeM5*4{oPvsN!s*YX4P6e#xS}2(M+mvfOt3|YKhJl(DOjK1v-s*{%fD z)P~k>e{wA0-nJLaCh~f5uP%j>{h`84#{Sn#E=fIe$88Wz^8VK>XU3P{&vfsdoH9sc zONi6)^W#?hI_Jv_iG`y^DJ=muFSQQMwQ(bLJ7l{tJ76JrvFa+;Znv@&uiPHyzD3A> zJR!__a*%q<$r7py=!WK(P*Dr|fR#~DC>G$yva$SQoO{-uheQ!;I$G*9-MdOl?nH-~ z&~I1E-IFE$!RPdwp<~=>uv7#s`Mru#!`%~^qQUY1yXk*&^TO-tA|NJxY3E z5hQl#fdk_)e>tQTLaE$;Drz;2+p^udw+mdQ`%od(@x~P492yAS zHY(uz*|-ye1wG(AVJzLR%m)sf)zXfSh_L4fkHdktQonqDm8naDp0_G(%d|Liogehw zEnk1-@)?xdM)eDHFIJ_CpX0D8gX|h;G&L~Hgv1F5>4eBd`nWqrrvIAE+_yBo**>am zR;#FVh>yjv;Q-w($N8Y)1Hnl1`U<;VlQnqcJrRa){&Va1gm^}t)0 zN<|qJ;BmrvMgK$+;P)OyOW@D(C#FZ~CyZitcV6Xl?ViB@Wqvs#AVb{{!bSby#lbLl zG8ol|(~ugSw@#rG4PiP0JEfQjTu-JvF5O`IgMbK_^y^r7kH0=qk!p}w#G4D59`NX!gP}pl zY?~TZS8mR0z8oIPZEUNRlRy})0j5w%1%tA*mp_6te*TPvxfKNX{6Ad@(F0UhlDTGx zJ{dT}mHVg8X03+f3QrlX){>3;u=_hAFkI!Ud6cXC1^<9z;9bXgXD}5VGWK>w2{y{= zwWE$P_-7B1Nm2zE}PH;u>F8BvPFhAGbf z3L9+E(VGP+x8l=M8N!>vf_YApuqC5f2zW#ljTL=Iz}AuHYkQyXK*t;JYV|f6&jgtMyT8k|J7S;3_4M4EaO-Zvw`X@cPwt)Fyl-0lp(?c-&p=a+Us~p? zIr%W{@`6`oPc0?Cx2vHFHdbTtf#Jg0JZbIa#c5LjJ}dSv;LfXf)u^sKB@F;+R1|DT z2#edv9x$j>xZ_Sr*~tWAIeXKNZxp(4-s3lCg4xie9xl~w;!nj7DD}~)2Yam3{ne~) z)M>#2qpR|;@n>?ZKG4#|B8gVOQSQdE;f~_t)9C;YPh+=|6FKnVl65D``BO(_Yq)qD zPbJ>=l|nR@=gc;#pkL+T7wgq$B2#0`JQU!HmoT|eD=`GzR51BVku?Io7LbN!R#b96 z40sd#_nd4%xRo)jp>vF(81tUbcluIUZQCQDlWVq`q z7l(Bu%%a}<>o2iGorl%CiB&Wg3XIE%=WXpv2|UZee|ml*qt=8Kg*LDnP(BHxwbYcD)5w#ss;4eADa+?GH>n?s}qIe7w< zybc?!Jx?OO68#ANeS=~kM6OfA%%Eg-XRHOm<%_dWo$r_TypQsdM(Jfc=bmcNzmZRS z+@`OhzIyffe&X~{@Qt{dEZ>Y)q|*3v$O=#jw|uSQc-UhF%rID~FhXo8rFzBq=%S}` zG_eRYj)@WE)#8iEjjzO5-3qLp!8M8eWEDH(af`~lM*mGw?t}Os z4r$A>2Rb4c_jF&2{~kk&tG1+xnES4_`Lj3X6szl%4c<7bm=)D6QbP%|d;0J8r4+!> z8hRvi1}tzK8mqSc!=LZ4pZB2KR*#R{cG(h`#bBU<%J|l*a|auw)4i2GhPeAi!~c%0 z@IICCmZx%EhVyzrV1e2x(?HnOHfiX~{^Od)qpZiM>5P(2NF6aam#_A62|lWPm4JQo0(gzocfmrj%FQhXNf-F- z*RTr)7%FQ7h2PZs(*TCAYjHOvns|%?q3wU@HCGe7qb$35f9`s9A*$1GqO9HT#NS=F#vBD&s6a zdFV^OqHn-U3~mlST<&S;T~WS!)s^srL20tGzAIzWm-^0*jEPSnSyi7q^A10`78!fK z^2{X}yYEjUd~G_bk3@}-;KQGivG1UZe-N+HpkgTy<8x=NXPk`6i(EE@ zzcjsNo$TiHP$5d1+U(AseSHG95BVgbA<7aaA})K&1%^FIaKKH$Ob{q{U%vDo#P_4S zDGFgSOC~p^k|5>&X%Yl0PXF$iRz8iQ7s~Z5bq=5cwxhq&PZ7mvk9C8U2{FX`vBCi0 zXF`i?e^mLW=Dm%vZQMr#70euOB)$8yIiVeYRMez0LcYilNkGplJW8AGf;} zQRR9FpzG*U<4QNl0R{ng4SKxag6Qk*mOg zKbrOeA*EJw4~o(aVv|M55Y*O_sLL|qedFHF?k*J-6(C=%Q2H^ba%p#Pm5(VNmVA|~ zx&twAVATUSNvCJc-!$>y$i|=VkaIAMI_gq=a4^aK%=h!Nn>hE0NW^~)cMMAjOr_~2 z3N#K(5;1o9W4x0K{aE$Y@8W`8Dl21ks_qg(<{)p|e6o53bOEsEDFevAg#!6?Vn4XE zWGlWW?+>P3H1yuk4@iu5m6lrVRFN%Wp97;D#8KdBJ2QO*U{1AL0<{a-p9uWMbL)jh-whtp>|qkWbEWe7i>h!vzl{V!!A|6UAyd;R|ynU z;@2l7;)ioZ8tl0$UX$UClu7=c>VvGgX1}D0ZL1VKyt{X;_m*YA77pcM2P^rePZGD1 z+u3%@X7%oux2e$pG6Qd~J&qc6&-t$KFaZ6u12QrIn?*%MseJ|9xRkD!_xZ`Z^-G)E zkmhcSh{u)rGFh|B&nV@n7&}Owhm5}WOdmU2`UD0Y?gA?CTSMmEo^?>QIDR&L>-UV? z5uckpge2GxAJsRIX?JApAE+pVB!9yL-In*4cu-G7TxIahV#dJm1I3No)-MdApv5pH z%_sqn+P4aNudY)3BXH`xs<^v-t6VCKhA296w4ufI%^mX(jM6`|h}FYyUk$f2Wc_;Q zlgTzcFI&zXrcgx9NT|t^^u2unzT>C>-h ztw%zq8&Rc#7ap^N2(16}zLPXQt)Q)7ow?9=t>p9a%8pl3-I+G^|Ly6Xc2vFtCH zc6q;!n4b27@C5i4oSbE-!xYf#0rk?YmGlG{rpaf>OGdMys?0^n!fntGJppHKdiv~6 zCP!gmA4X-mut6bnRKL9h@l+u1c&BoZl~+r|tm6%9!=4vi=xV+*Hm*d=CHgOw-=zAE zwyPz);|$DlA5+4610*Uslz_iOZ|cuELF!+!I`4l#)=caT?yl0I{u$U;J!p-mHEBVo z@Z4@y9+XOwK-vMo_o-4Y>Z3>e`{=z3+*um9XfKQHy{e2JSnn z4&362f4?Bm^c~w#6TVjebtbja?0>;lvRLp9&b0*RWoN_qaS`s<7+iktiZY`gy?@kl z6Ayv?u*J6AIK6*3rfq6?AeR%gGB}EAw(eJ#d|WJI z%B#gzXAhr#RjT^+em|r5X!iSxg;=(P4Ua4LwYwjF5U7~*X7Vu)h0pqU68!mdCN$z)RgMhvp#Yzzn%f#RrDZ1_#^My)2-U~2cCH5^JU3NQPA2h*3<*)v-mLJ@GY9-TkLLl4KdViQm z%gg`mKzh%tF{A8faSsC>vy+l~F+S{p@vOSv6C$33r17z{VylAmczK#NCsmuZbK8z> z5ljgzdT;ggQjz@t-a$XW_WgzKQN4qaj;l4@(r(zjjtuBhczW z`dg-o4GIy4l;X#se?@}H+~zTZNG@r!ha8*6r2pF)tdowfC7shJvBP@Bh{0+s?H9B@HtE{B00*POv#M&ntDmqp{h zy{J)HfDmbIhR^f~2kAwnzd-pbgx@z@*f6a3^LM#-jxbNd85hm^DbM?Q;G8qzL*BhK zj$U_`;5A4O1|u~H;{YN!x7&$rkjVSJyT01)a1sH;^hdW4run3N&c$RqDA{B7ufL(R zkVuQ;s|^CpfgCkXvGl%toUJ9YIG7Ze^Q8%0F85QdJXVTkWtHWt3T^L|5)sX5nqf2i z=_TCvjN<;3z;)5>P~r%3N%4JLjO4=xQVMc=N=Onb;)&wvNHaOwngNs>8wbY?S+V5E zo0)wVcW>U~N&kO8FZ7nT_3-#LI_{{2y3D%BG01(XwU-RqRRH$Tl?bjoZ z`%pJXPftbl{$F8<8tH;Ys02RC_^*C{ULfWE9kI3LDp}tZ`Lg;Satvf=+?i{=|7X#- z$w-j*;g9<2;D>|B0i5*8~wvA4>(1atr93k9lR`NUev3 zoO4?s$TOlQLk=(-m&3tnd=s7841y^G6ZY6{M;ak(|u3r1V%m@#c>!-&VdSI7IiM{mnZjdU3+`J0^x( zAZrNBEZ`&rE}ScnO0gTxE>1T^9I#f6kuU)Pq7Y>2?Lm8fa=57_FoN1f_upge8@Hzn&I)5eq;bQQF164PQN>sOo! z%hlr}Qebq#Q@-g`;uV|>ri0dQrw4qN)Ai6k!>80Vx2>41tX;g=3I73qEL;a+AkdZ{ z+`EU0Wj*;D4kdpEClth!S{~;MtE(q~Mu5@*ATf~zuxR>X!jTCc6C-L`PsO;C{tHMX z$`>FEsEpy`OOmSXfBmawx}W@d`o+&VIqRpZj#qo7x1E;PeL}LYA&9jwO@3`VASfC? zcQ0vq-!@ORre0BbArnu4;dR|X2M60+`W@*<3}#n8QUfru-Wg*?JPIURoEuKLOkEzz zn}Q7l1lW)<77W6=4|*!e5nIP+AUBmt;IGNfHU%2p5-dtTUSh@ybxrd?RkKnwT~y^_ z4u>QPsC@Bo791e|ZYol|NY(%e8P-TH^z72Dan(+&Ls}t|GrOD2_??Qej|^&m zWH+8Xz{6WyS{fT0J3T%|xhj9UgR;^4y#Xh5#Cl<@TI;MSFnfa>#xf0@uq%%v`8Z`s z!8pp(EB-^-6|z_w@CQ~aZArQEO(>{1&gdpAs5&6~gA4<;;$Yn!j9Fm6*Tu(3=nDSw zMPJ1p3V-+=;P1aO85bUF6~m(UIaTfjFqdx?8)^Qf&5riB|&Au_<%HE--S>CR<^ z0(kO%f;|Y9RNfBJ1#V_Fk<-Jb3e&wb!C0S9f%^)DyPNt``iV0HBQ?apTf)93-Sst% z9t<2_fH=R06M*M{e;FMyGuAopkMc9~cF?@b8+_3Hls^bQk*%oo_=gXpPv7Sc-2ENl zGCNW#O&7)#$J_a=U7D^OoC$GBE8!S{+san2=xuIZgd>#I`9?w)ME3+KW=#|uh2}0! z!Y;mR0I@jUkv+hn05py&>}_&V5*~x9E>u@J-^|LvIY?UwD4hSCgXF+DNC9U!Lj1Zz zfK}P`1dJd>3r{y`fvFo>M73{z{hb0clnEmO{d?hGzak#e)3+N^Q#8(^4yhUY3$nv) zzv~WsYsnc2fni)RIGqelz3oq7I6=wjVYNG`(6!@4FoBMcOyJj$k?8@&qJ@RU?xRu5 zS0W-vU~WQMAPhnH8lJ(!&gl_@*#dkf%Hb&Dfv&Eusj2BuuErY0fG-UtWs*<9qwi1y zfdNrYf-BtJabiYGfEqE8`r3* zyo>#-XjTXykT-m-FiC$qY2R9kTkgE^kgkBNb~p7F5Jx1h&Ett=VVnl0OCg`TOw&(60J?Ze<{F|ix1)j{dR%| z{LV;bFVw%RV+G;xQ0u({0yvBSp5O(*T73U#ekS9gX=RgDD|quvP9@-LjH3K>cni+& z8KC@hwC{$^(Nlnv8y{rbVVao3rjN>)CH98CL@fP9_7!#nmA7U0kW?DwLW<&(lKqXx zwtLymgCd^xWQ!7k@)%g^e`fdZ^85XAQgB;h^mrb-9h?@` z+ah+1cW(MX7fT9sTPv$=a4-VplM#|SM?zI~6s$mKrQ*THaTm5b)qep?CEFdGQ&5MH zb8v6~+sbe<*4SO2^N}}nOim`Jo|7O=*dBmUXT9>g zt25>+uP`Z^QO<+EUwT|UR9+@3w^>;=b5*{bf${hHBMA?I`6gJ#tio6vd zKuZD~Z+B$sQ=d>Q{Z0E9)z;gB@hQDfLLWXco}PTTd|I6X>P@JMu$F1^=aw&)9|}6MB0hoF zhj9sf-(>|qGQ`J40tpI0Xa*+Bt`K2>-2im+@nsrHaPNY`omO%j3fiv}LNFq@OGc)7 zD`PPI5<6g?cdP@$mF&g2Zl(cLa!?aQgAM|wV@3uBhp@X7*Sw;>YX+7NzrAlj z*GbIlxCOW)@h@NL40&f@Gl7={`~t|@xa1bC&&b%=;ra+GOod@f0U0ay`_2VTIK0}^ zs;gb$$3sdI;G|id0``sGBG+bGcBK_FCU-^XSnawd+aja0-jCvg+Pm7x$=csrDLPJ zcO={CoAI|Spe7$?c-%yaa6Ddau6`wAJ+$zb>fR&qVQ35bGvrXu-B)|kWs@&Cf;SV@ zZF+#>N%RYe(I=+p0poobw%7?Dz{H2{{>=$1V&WL^Wjfp#L-&wFkqPJn2f9> zCCVKTv!l2(9e0tqk0qg^qeJ=651bZimw$ZJ_>?k=H#+ot5hkZcQA|{_S0ik=6a~?M z#?iJp1$OHjXH_%y0s?`J}wU3b;X znZcI`pz}l4{e%@3ts@Tt00cq~Q-Xa&MjGgG|0AO~Ou0p9N5ThASOal2i$HZJVmI#p zMkNX?$6!((Jc2(xo&!X@bcN*4ty93H`) z_}4Ul)H#B9O5t!1x6SK2sIH7vgENj}F74Pa_2^%` zL5(k*tJwp_aI9W{bmbZLE|gEiHI0LV_5fd@`YV`(B);_eLdIvz$9@P{dIFb~U|9$s z71dmi6&T)YR7FBa;^}cuI36k;*d7iq@M6FwV*At5^5uH;m9F8Q;{ZYww|HndtT56j4$eCbq{nv!-;{nSx_BNpEBftzVNYey= zcx*Fj6AhCj`s(!VH2ts7-|~O7O7tlzD#9i6`M>JTRCtQA1C$2L4ZF<> zUJ>|Y`RI{f=uIP${D$3$AlU+^orqRO03cq}?DdL46Mz6ZCR6hDLoN4XJ=ly8nr{0F zCoxk*f&W|^Ce%hS_Or@ul8$yb4*6{|!Oa@tikpTpx0Vd)xj*q-e{u9olyCC~7vmnp zwz&_pzH0ZYB6TPCS+v&|`_6V7#MJa{zTVzj$FBc95kQc7Q)uvKQ@tK5Svs7%j|;$Z z2s80-T2Y&1tZ{jxp+ap=Ms2_JcxA_FdGWl`R2vL{or zu;t{KgHL&Nd)sPWL4M5)AE8FE?(JAbep1F}AsDx(2mXkMd#svSG- z-_{*)8BzM?s-6`xa_j(9^f~NucXCprH^r$&D(d~5%nC}Dx7d5@&%sS45glm<{x&2) zG=cgJ&ebUGNFOYGqMF9ePILI)!DtNHJ#sF~Y48jX*R=6qJ7t3*TKUmbu28Ukf{2I+ z_w(mb2S4Bt#bowR|F|{r{0mM7B+=L`L1I=?KxfV&*=}7XKC%wjqAv`?Ym8GWM>$#s z-*CkQu@70!0d?e$e7B;}g3(j(byH-F93i`dHr*!`#4A$v8_JS#NN}%-jf>M`Aw+z8 zt;;qH(VQbAgr1P$RB?|g92Mvooh0}~lV5qln8&m5n$Wo};>?|p!hHGV+BgGU2BHa& zQ6eWNy%Q%GBw>;@I{nChyA98v^nT{- zpPW1g+8Efhnbgal*)Dg(XHB?KU?L9^4$vLX&d$Q5JTfe7fB7hx@)VlIiE+b(=P=>X z*&u0Jp1NygM3O%4Ec_tepAj;|*;j>p4|Q#pWS>hK=p=gZ&A$#@UI@^veXKMqiwk*= z_GmX#{zd(CpufyD-1H~ow=5~JO=_fTYH9IOZB^!+@S_|k{^zo%6wO4ag9AO-Yq{d} z*Eos@~J1=x(Y z6<$Th{^@5=88iuV;;zDVET-yw!yZasZ5Xi&Cr5zWSyN*pHYxYsY*Rp`I}#vZb~p2v zFMmO4B?YiLD7oN^7T`wC%=FZGcuc&tFDlK38yEcaJkYp7!_vWULTj8}di!As)UGYv zpEA*0LLnPTnB*1M$-KM>@AP7O{NTX@kQq~cd;IKKH!92VpJ6=Pb5Yi>M+iDIyEz4# zL!ijRLUMZ{brs@k-MNAtPGcSl$?`Z8mlKmXjx}I_s~9>mjl*J+H%h$JaeEfl?T%yh z@$M3F&Ad#?Qp?XL_YbBg?jPa5vY zxf~%7ZG~1=R*4_0-k{)N`nKAW)ht+c06&B0JBzb_QIQP;~={J^yw4ivSRuO-t!PceTxO)fIpK{aKPR21jgr( zX~<%?ewU45sZb^@dxS=WxLhD< zKxa;(dNRvC;~RH{WAOX$cnCdhUrGTVi#46G!lz3kXuBM=g{a^bY`wP?-5S~-^ zFb8Tk6vIwr|0a@-;b5XUi;ukYF@TC%0#Ut3b!c3^BJy#`*Av57c{k7=K6->+54@@N z2<_1QQIos^`qO4&i}rZF80|=~BZPVfBJJRt2IHs-r(J#6#N$B>6oAhJF_PJdiPJLT zj*dsrR6*y+@~$31OZx?R2ABTl9t>D$LjPj7=<4eaO0lG*sdD`=vq6#unb#x%h5Y_M zi{W%Uij3)*b~3@&Udd`RWMpLjdfR_@LL?A`_gA?5YtZhY<&0)WZkWENLc|jA_ulf3 z%CD)=hupk9n9bo7QrSILuTl2$Wmo-JeC@4Ep`m)WW$79lt2Y{F0xpN7%!ax)>P#xPN9Ou=G+NH@$0o)JkJ>-3FJIZk%Z;IV!rV=vdh*1Q ziGd-G(;~h@pP0|t7BkCq9EK6`e&p`MYx|m3O%FEfF5M-}jexK+|2I_Z?OXVu&RU=5 zp@2?6G*N7GyCDtHQC!3eDmF%io)4w%Be4Y?Cz{koQ@_iuP9AOe*4JR5y($k02>}8F zS6pX*f4}9>m1(a022w-moe96P0;azaRpTG8PdvXsN3u^Gsm~}JXkx_&%oSR?OmEM2 z1XR;t=#1J1n~y9EXGzAK6o;n3JQQrTT`Hm<1mm|OCux6^L~u8nX(cC>OuP(Fy%iqMOTQ&nsqdB=$$KWi^%uiL_{6oAjL-QMOr)#u5G^0-Nq-*Rd|Rv&5k7Bn zVZXsxXsxH^WYv>)-M1rt*iF7;b9AP(5WT-~_TeU@yxa6fhS`Iq@9wL#toEk+W+zr3 z$(-izRWk2^o84=4BUZh{58RL)y(Tc^n6zp7$O!*sD{QVWe zFh%_3XCsp8$|R&D*Fx*QzP=9OgCKPB$$xwHTkB#c0-Oq$mzOiskEeJEICIlzA0rT+ z=w15D+2+nRPM%^67+Mv(SpuZ$+fnI`2~@RBGD z9qWd5p+_K+-lmoHW)YcGp+2Gd9p7=h#@=^jmpbiBzA!C`ONminuj=bwKr$ryNZ5_# zOOBc7w3|W&_9X5}!Juhf6Jd9q!a6if)*dh+D*QC?@E0TX$IxJtm=F%qwix# z2&HQ5T78$A@!LJ*WF=S*zer@(;s#vD8pq1w-LjW<8NpsjH|tNS{FauO_zu`d%*@O% z5x{a_Kp-A|v^7l%9W!3YMMS7#*Y?)vpVVHrxQ;z;bL+87uyYBnlMjMkMpLsEjs?F4 zu;Il+sv=0p;VMPMjkNsV(k*O1p?J%nqn9V+5;iw|YeZ?i_waaBO=o*H45=YZyjTfW zF5s?a_3reWmB*j>uiT9TR1G6+mI=$={XZtm;|gbvZ(QG<`mViZJCdbf8&p8NI?_5j zE8{bJQ*ZNzYsTt5x$|>f@xJ!f*1I_4R8so-Xlvnq0Kk(fC{v>BIr(K<4JeRkO zgkuDoFr-V~M=58{PPLGw((s+jb7SJ#O{RguI6sHN&Bw*X&VS|PrDLn|4d+}BN3%n6 z#DW8P?yAwI;T&%21{?QOJQAa^B@VZqGl)Cs(xQwnNj$On>Ye%Ra3Qb4~|c4WTiD_u+D|4!xlq7}5%bsztT-Y3|M6EMd=Br{B< z3Uqe=xEZFX$lCY)^Hb`TjWB165+rdZtK8MDvxSlLHhc8R5OtF}-qT{s2K7EUBsr() zm*FpNX9fw6(r^S0FpzT#Z^=Wg`|x8lxgEONmvo1@&sJC7v9j9e5uCLBY|!|9hx?_J zxCX0+td4UxI?^4EE%;OxK^fHE)@A~r^5!I(COQTJY?>G>r^%-5q{XZD3gez5*Nr43 z`A>&$c95 z!dhZJHS^VN!90w7DSF`Kc)gFkuO`*+%*(ff3^pDCU8&ckIyS1~=OY6)rmaB<7S6}j ze5~=z*vaQjmzW$jCy#{3_FHCjkrc(r(oRUkTw0f0xq0cwgh=lE8tMo5_)N|}JW-2v7rsb8+)z7Gtgm-ldpW_cK$a)D znK-qlIAu@4^x(yYu7N?o|9lY*)%+6)sXoUoai!!ksu|bE>{ik%6VnwpdP7_*+87wN z)4$dj&hZ|O5{6+okPsdwxUIhJvP?A?o{LsF>%UxBWoKMy?&7GmokV7*)4+X5U5_~) za3=I6%OIE{%{NV?B|6Ez1~@|%s(JB=c2Lebq4c}!TA8BO(V4z3q3 zWRR47a^_rL_)WI|h*jE@8d}wIm+#d-la#$qDXFKo0MQAi9K`8nX#00Q@H~8zwpTCC z@JB966mG`U`PlW+aWszAwC9GxRMkqV&C^>OA>UnRLf;bCE+k$Q)VGfE`ncR2>H^m- zIE};cP5D`nwj~nF9PMH8Gu%e5_3G@l>NTC>728D;ObK;7Yve3}2l(fF!|hB%f6bR~ z8GQP~cmLyI=-==2tAyn;;tBSjtzPei`pbhH97>!xZ35_saAC9d^i8yws;B*l@jV)T z5v9DLq-=javEN*XpcQ-`^C)$KkG6K#GgIwtw5(Ao$9mtsmWhtTgcG-fz9(iOsB&9d zTcKJTRu0fo!;r?n97lWO>=w0X!Bbr}vGnBWWMQL#xpUSOQnS#^sp-Q;NOjX`PG*ae zruz4)t@I+Ph`+pNUd2>D^jwEt-pCNr;A5HP-Y;6UD(Rk2+1AKAmO`4;O~xI6$5uPV zO2FpWEh^c0a|`=@LRC{W|9L*uRw@yP<>4WNHnCkw6sLtI7*7I71{5J;I8YET=HI@R zPq0@lWvx&3{!YQJ-uS(h_ry3(5jog)ub;ZP^(I2^d-_H)L!aRKuun~ zx6#k5<4h;VR0l3iaZ^S{*wYG5)eti=98r0lGFGTTZjHk@49Xm6eKBxJ2wGXJ#?Q38 zw-(V5h@XQaMwj=>BNp>=hs%Uz<##0uHl%V-CR@FD-j*_i=>~jO3YMwBusvRKUgBk^ zvB983!2XyD-RN|GJlx(j*!s-&@)?Um8$Ir% zRP&zGy*`oQq`BalQA){-4jLn1TZI7QYr|G?KbLux%z_N+B_g8Gq?X0ZUWX&{!%lZA z*o0pjKi`X%jHpxGuYu}kv6kbFtZml!(2K&Jxq(T_iKC!NekqxQ+e0{s0DL_U>Fw)l z(7^N@eP}8Ap3|o2;CuhR(78bZobfk@I=9Y}?sRk+Bpi^K1e@t>2!(18MP{S@CHhJ~ zB!zY{jaz9G&4E-hTIgb}p}{D1+p5CF7g%_meQ}hc@5a<$ayfD~O2boo5^7p%e~%0n zP#=l#nBCCyz4M1#Sd;Z`mDEaIiRZd!Q%+x3Mbe;T%~LI*V`Ma6?*1{8dmVvzRVnPW zqacu#M&~wa|5~bZ$m_#Y=rw7FGoEpm{nZCZK}0|L2Ogp-rHIUw!V@Ff+}@fj!v=K+ z$#5PQ&y!eF_iJYv(&NRvY_2{0*7kJ=X7xePRTpaf-~_C9FVU>thoQB)CIrw%`J_S>lXU z#M-x!9o5Kku>~@TiJvzn`pe?N+OBXhk_8(;1;-JS1G^vG{R^|(<;gN*&eA+sLglq( z+4+vUvke9b<{HkrlRUN3r`31!E@li4F~|3a2%rqm@bkZjkw$zAt|tu| zjm_CXf6E}{y^`@*owKjTUPQYyFr+$+<<{kW(_piZNDkhDmgPpWvAFP%gdg_7UyD4MxGNftG0>DqT4V1+OoI4wmea%H-1(oi0hmX5TadBEe{GZ%%vop z{EY?QxgS}#OWsB6D=LO_F+V^cip9nVV|AqoEV2&X!DY-Kb`dRY~8kzRRh5>ta7S}|~Cr9aCDsVs0fcBis* z2~H;Jzuuq9H{<(B`azW%pF(jG&dV4Kwm~Sw z22OP1S_O-0CN^96=rS=kv^WvhLPJBTp78PUjr$;e(p+(1)8v;!?ieqcI=X+<&eC6V z)SHP<7U9-7X!XBupRF4qX_PECW^5>0lG{LL4%AeXP~*=xDy3{?m;rnPo(-@$+9bof z`fUQdCI_tlD1=n(PYsz}ZkmPkIL|Y{nkbSjkklCCq;BGT_v_^EeY5Dzr%a#CJPM26 zc*^A_k#eU7QFlbMXB8G&|M^NG5zThvU-eQS$9W5myMfPi#S^5XqOV5w8*qb`Nk-EV zn1AXTYLu7))OxP`WW9zotZwCH!OmzULpD`lt!2h0vj;0o*+WM{OXHh$vjk-HfJ;+} z1S;3M9)q?9NZ*iI&vAVJje-GEsg13y)@9=0@}l#ZX^zPFebdFK0)M{dQrHNP4ZsQ* zzo^pU5$2(mop`OFs>30^I!zIEu*_goeYn%OT3x9dw&8K~;x@ z0TqKdcA(=&w6P!G4^vz%(R;ZGCl687;^1NK)WI(XmO#Y@3)u4$P?!10ChvoF@S^F! z*~W*w%A)i)nUx8F?l;GuhqLwqtesw5T4vi)gIQ$T**knHCG+y{ z!2=EhaltZeG^H&Jq#8V)d~G4%;J|R1ywX?(>mt3 z@TVruU&BX86U)fR0AJmxJPTndh&kTlID%b~WS2MQ~)sThHxm8Q5sW4r-0NC~H7#JW& zFmi{?4D(f{jMesY`#!c^{z{v%Q_hhj9X0G|64S*1G2PHyu7Q)*wY>AxO0&#T66vV) z=qLqFOY;5;OFzm>4r5r#MesBK4{ijQ9^&>2yyd`5mP2pzhRmaku{_7N!|OI$IXWNv zG^#|kE5!uz zP_u3(SC!Vfh3OU(*gEA$buoR@{^RlZX=#<+K0Y0NUYcmSmbPSgCiXauQ_Unu_WbMl zc2KsCY#p%m35yOjY|g@_F=33CMNswD%i_-`qrRGjZj(&SMzT<4yXi@~T>AmEpCa1Y zGr%yW4hs)ghJkq+V_BW=GT4&}DSQE6eZxu1*l)I10 zWly>1da;X*i8-7pTRrSrF(!_&?JZEkF{)Av38z;ngijPcR8RvcYcNS-{=+mn?2IX0 zK3&pTuznw8DGr7T=LaP`+QEv9Q5xSJG~do;g4X>8YIb%z*g2poC-54kQ7#lIQu zAu)M*?(tCq{vvr!LGAjPE=82@6d{uNN|yad-KG-i;>=PG7_S2ln{~ zWc|dLP3|u+G9;Iok*l-+;RZVZ&I44%+N06WqWNR_>HD&kRym=3^TyX=VlmHc^ueYo zO)9~i+NRFnHG7l`G&W;#=U-QL&7F34&Zj(Xn?^t3doD%J+1l=Q&hJ)Jdm<+ryrmHS z!0brU_gf@?1I(q`6Dr`jc{ev z&~IE(xG0JE$`DT_gdN*-Vt;yLW^8iPpY@i_-HA!c8uIvYH+1%)`0E7Nn$;0-kG@OQ6Tiz#bI)orywZ3L?lC54w*mDg5>ec1 zA`@;4G8!tj6K?ZgU>r}K=&iN(I(`Ie{S%=l=HF*$WQF+eltv5-MlZ^^VGHH!?bVia(jVo@z4mNd>TQ2 zk~p0K$GSt8u*hM0qy&x{k{&^B!_Rz$8JTf{=L>2$SBJ^28A7$Rz>QXcX6t|ag0Ath zt8VBSibl7y((Vxqb?pweN0f6f&l(hSv$m!Y3iZh{9glKZt_4{cxaJWBW^=cd2m-#% zifNlc4ux?|*KEEi4FJd_6AO)JMhi1FBdzvoB&DKBEyA1ItFoyL1@i+gQJr2!5CNiM zR@*NwHQD8*ZKcJm?!gRncdyxs5TWZfOzvPapayLTL(3X7F*b20s^}o+rc<+w1lXK> zr)8a<$5VcaZ5y3_tddJw+%%IYpEe^8=QFkSx8Q@ToW+s{9FG}YGYQ=8`>oKq({`r3 zsD(`4kP(!6$e%`I!n&;bglFn9WdXj|x zMZ=&${S%QB&HZPEM&*SR-3R)#QgwN9Z)*82=Y07V;#<%q5o&lV@%_CkiczG)CgC5g z(38<|FXb{#r_UYVIQ561-w<+9D5H^gQbpgA_-bVh6HcUYVP@JT?3HtUaXf-4o#(zI zny@omK(@4%$4B9@)v2F9RjD@>a_n;d1A-Vromb4|YXBdJ% z-LM^580wVclutZqEE?TOtYXowsO?w&!kNu7oq;Z6ns!obc{|5x<1{}JaczCQ8l=YS z$1ihQJO#H1g<5MfeU+2{aL82AFhSLSTLUfM95iO4sP+{(H&O12o^F|Bc_cB+)UL#F~WzD$?=!#SSB8jHbw&3A{{E*u8e#={&h)C=}~0 z&($fBJ=Ygys*Jg_Wate2v*tEMz1+@G(+9TigfzmZt4~`gt~K36`P$C+7Ycb9l~IEA z>H}8(Ks!za9XP+Ja}jXr@tlmt@9K^l0mys%W7RD$$-t6Cy8A|CN$9|jAL8KfQ+jCu zF_(pf1*#BMT7{{|JePpY%5}w0_;DSLWE!2ddlRdxvwnHbQnj_5`99tEnq&_`*F?%l zTG}=i`Gx{G4F)Z%GN`!e5+wY5W)$25;Zk^DFHx1 zrf6_bD5-aiEu}&>VrqM9Jc`>2)4YDpXK8z5@!HmkU+gBFOg8S)bjDEaFM6d;-e3Aj zxG`X__4jMZc-k2CRSBQmlEBa_Y8RFys>>Q(sA>M9I1Obn978TFApAhUzuTghT?%3> zcEx+GADAU2hc1m#R!wnEp9q^6oI6wWysRXkpEIPD<^b7<-< z)j&r3!fM}8k}+b_NaY;M{n(Bn14_J82>%!)*LRu(`Mh{$%2*TAiY(UND=?F9o$# zKvF^^;Hg{|A4o_vfR2ZDcF+EOIU>!*!HdY49cq1<8%u}wtVi+mlLogXpY?is5c2X3 zgeK7ZntCS{n_51x9&E66m!Y=nC8k%`HlJ8}BpQNIz}?<(g^i!!FBh5mo7UC#H~&7K zPLDTHb}J?mJ)T*Yyzl#&({0orAMzXnz}F4Et050j4fH@}o= zW-|NZ3nc^}Sewb@Xq<~EN%XXBr!KX%iuk682bbET`Quj=P7+Y=V)BQe(fd9~L@?uz z0*T+g+r(dgYU4?GHuY~_&(+`sbAU^ntv$n9Axaey-vx`@buY+Vg9$zm+$*xVs5> z`ER|nTD}dt)5Ik2dO>8rC?06>ELeZwWP-*^GxGSplZLYo_6md}&fPAT(G9lhZolip$@=23zM5cPr|Oa_rh`TiPX)jimVxm97#iDiA4k>#+NuGiD; zDSNbF;xh8pEMH1=%I>U+V7V;mlj3dCGj}4y!H)w84EAbz9l4e1?z^Zt~uB69pm^0%34QQT>jH}}o0md}wrkEt@Mg&K!!rC_eFsTkd|{hh z@xr#6`2N+c#Ly;&Pdlj$ba_>o(Wkd%3_B>dBzmScD3zd+917d5IInzpe1eaP6mn@O zRJ$Or9NnEA3;4-cjxX$QiUzI&tG{DCT zfPn`~X`<2sm(!w5p%O-^NwYLtOfqh*Pu^CFfXjHdckT#?j!U%fka2uq27w9>O_~J; zUwUc(e?rjg}g{o@%s|=w|Avib~f@;&Y zv4R5)uwvkBdIMzk`EI1;FEXSmnrkw01!zjuzkczpG_ZKFY)CYwaa(h^?u3?;rC4V%jV3qTZbHfcjrJbdNm! z`oZptFKTv@A{2oE+&Q8P*^!b#(u=einxk@NyCyK`g|MY}+TFccy9(dJv@$~*TVCl0 z6naViHMkIly%K_<`au`n317xCPM}3Y%*YkdxW0;(7VcSl=sEu>k$UTeIg`nHQ@N{f zV&TEgfr*2iNiQbMGD<3~`inTdqH2nBHfu)OJo);H(#BqbYTnAC)H=nR+`Xp{9O}>b zaxn6(&&dlvoBf$Hk^%c-l?f1kl^q#ih7=DjPA7&o4@IpJkUie<-KR8}2%Ww8q0sAn z`HLN(U_*KynNQTWi!XRQiddjm3`iC1maH^6PlV~?S8dkt?_a>Q@c)|jOWAf49#+GT zC|yxJ2x)+L;oE)~lVQGowe5^@aZ;$FQSU9&?o8tyqiQpTT6FL6Cr+y=E=1IiB8Yb{ zWif_MulV=HjS?0`@1uK?T+=w)SAVi`8M**mY38)`av)5)_FgXpk3aO>3Z*<_aXlde znG1{|AR5I&8Tj4~)sQ$jcBEG;FBIS;%LDlvG$fjVgI@wl;Jx?WL7z~%U$IHe?HKtr zA)>Gy^Pwfh5a4%gZR`JvANW87$TTKebD}l8v`9x4Gt1uz`xIyrXE++zc*plGt0ufL z-IIV@HQ&1;tHhTpCMgx(vKGE!trd~uyghWbD#YanA&l<3k}UfGkHW)w+rJr&IXh>p zJA{%+dhBIjD=$tMS;zI&QTY2=h>&k+#Q}{pPi8MNkno_Q`4?7Q!tT3RkD+>6li)d+n z*YRNGjNSMNiaNw(I(b{8Bm*qY5CXi1wAFPHC@7F_&taG5_0GTu5t zQmMsO)S}}j3L*L;GL3XMSmOxBbvL_DHIQWtq!$1SfS@AmvcjE_dIm;PvXv_?5koT_ z$)C?N>#x{QGIn!-t)OYfsJ%qfJWVMb3Q__hBKi`1t0i~AkAySg0Bd?G0!p53+TulF zDDKL?7z%$>)3fggL-51yp|5p#6O)taej^Jg#LCr3|; zLIee2o=kPa&}wH?QrG^2!Bg>U)dKfCJBhl*4}@k0)hxWr zzi+TdU}C)}eQc+uEsGp|-1-T@WL^li+M|iscl-g~%h!XNAHy#6a;3|7^`k;O zckUgVFt_bzZInTzL%L7BoA}<_Cfk#rmFVAKpA zOXVUXC;P@MI&SW2Sn*A?eA)Ck-nl)_>S?1OyUDMg?51fnftB>pOlu3yY!-Kbng@h(IsclK z(DL2!7r2xG3JS3iWpF|tn8VpMbJ2b_(n}_#+?P|VSDk~Ajlhj41CM0DINOK4iC&ez zMonpoiqC4@@R`%&XZhNmH;UMOakW|6OW#Ntra`ve0=JsW*rsdnVriLzmU%#xjHRw= zbg}slHMPM))kMavmou_41!9{t! z@+!#Ho2jNAS~IQv>EYj>(A!T7q(s`0dE%$E(G?enXSt!oWW7ua5Qr-ATRInzMuj5u5vT`)c2X1wEDn#y z+SJIotJimDl*{QD7)obS(h>__UyDax~{$L+xZnrYNBbs3qfw9W41XJf|9 z_rQ&DGD3ZNP%%e4g9irBoBQk_@9@4x%nU_u{Kk`}#M(}`WMa!1v=UArTfwW|TPok4 zeihP@XJvmB2r#Ph^-SqNbtbWQf${E{ZP~sryI3~!6AjJwHgdOO2K0S>jCq$sp0W%* zNg?&hnALyKxJeDQs!+21y7)YH@aHcgTlm4C(`-5j-t zXz(-(cIRNaZvL`*N3Vlzil&BY$Lp7cnWnA_PNEbvr7cE3CE*Ayv1&+8n0)|vGd>|9 z*P!(o+$QX51qbw4gNeE(APyxTQ}GVyu|IaOVV>NZt*=HHq@`DK(lMz8zpE=9BZ`n1P7;O_E$baiGUy)-jL zZjkSHebRE8!ApZaOl_!GyAL=2_dV6K~SK zbtr3Ln)~xz7I|V!6wQCEXV(-!_-fU$(ARf`sa3R8eOiZ5&g*9U`)@TjRaHJ+1M=6w z^RpsKLv}vass(w~W}K3VtB)1Kc5KUh+AvguWf*>r`fs`1quWnew6--pV~3(I`!JJ# zjy&Etkow56*GXpHipyjn56fYHe!s zOtXnop6K>8+wN508^Ci-5H^#b1_U)~R7;i_z{oNt`=I?!uC4ox1-${IyNM z3HdN%Cf;682Dt?iQ|y&aMz!cQXfV4v#`G6MWKI2Lt3n({iY1|(5t2vBrGg5Eyz&aM z9ujtb5nsyxkQI9g_J`%o1;7(mE`-Po@&kwGGy(#pxYnR7UFzvnT&QFF84d8Ad zw!K2Z9m%eNR#x8NeQ|O2tr~7>f7-!5sf}R7_l-?DF*}#F#gP1rfX2>}1L|W*VQmME zq1sb_qGRcD%Wkhsg)`=20_y7N@r4ySf`GjOR3El0vTp~PIPIcHLVw?5eVfUI9YFHI zQRj`~jk&^MX{tuI{cYV1+s2*MjgBV!%vx60!Po8Dc~hvQ`4Gp| z%Igdbcn=Pj{^nA64Q24B2V=}D{Kv3S8q7Dj?7M{nzWeXBE{_pIe7!$NKVML(C0c-=yP~%J$o`25u`?5E!1(Vd+a(48@Yvj&$n;KnA?`oEv zb(r=2s%7H2&#Io7LQ4({%6Gs7U_6o@cN&lTNX}>2w)52k?UK09D(-2c=lZ)J4-XGi zy5@!&%0O^@C8_Ed!d!9LT!d^p%%#nA+jw$u9j|Jkn(xY*Y+jw8zH>1`I^q}hlntuT z2t;R8J6>+x;-oyhwy)!Y=ew;f>NdO-enohiWLCi{E;{D3l4WOzl2#8s?|s3<6myP~ zVcMh=ZhK#!&xfrE&eM}5_3tLo^Dc%(^T`u51~#^Ie{AVcbEc-I2B?0~YYwUnH?~~% zm!JXy!aQhekZ3+s_Uj<}*f21MV?xFZEz6YVN_j?_t>RiMXb`7h*j9D7t8}m1H?Odqt4BRIS$N8qCTOsP^RP91#g7yUr7 z__9)Ovd1W3G}OO23{mwRU5`!xv`^S&IPJeuPKGHEotjA4g4^S3GaE>YdC z&ml+XIxo9!Vb+2~3VM1I;N|bVvMVkHF=>E(kP|Zs7~s~ffm@ej;|29amSxKW#GzxfgIWb<2>lQkA)W(akdT_# zpj7sEz>e>{EZpbqILG|OgU2+XpcGi#Nz-xBvGl1AmKLlt7me0KuCm~N88z1oY$zQn z&02bsEpNVci^@lI~T}%(uH)5kF{3Tp@V192mwtTe z3^`oane#A*BKF@TX4g*?Jq=gn_)YogN?q3FD_)ZRx>Flr+h)cAWY}c&7M<7zgOfh^ z*S5vBVuC=km0H!Gm-g%U_JweP5QG>@EJg&~YY-iYFn((E+qZ8KEj7FK6a?=ffN}*u zdt8-5o^Ri;jtIS!5hYt-_ZVSyTNlWejCf1UvETV#bKChH{Q-Jsy~(Y1RmrYsH8}kF zyzFi*J~EvGrPW%q#~v0{J1(E-T~P}!FIsMq(npVV+Z|i~-iNZOW;+GJlB*eb*K3 zJ9(+WwUL;p3(71MiXG}XebWx-+tw4Vw|KlkX}zM|zCIkx<@r{*MuP#jUBJ^y(QNi= z!>2tP2d919!x9VKmx{@wDY`IuhKjoLVcX?Qm#rehikm0Z%3KP|8FrxF1We)HD3JIX zfBztz6=oP{PL)?K`tG^{B1BYQ9-tcIU*S0f6Ec=wnqH{as!gE zu7-s50L$o;+Ns5~q%=2~4Ps*D!&`XM`EIr%oH*2@Ey4i$tyy@%WOti%NsjpFQdKKd||FSU-YM?l&&lEk%v%xgk!fEu!7L~RBPF)yD4aT< z=u^{B4Ui|t%kj^j?&(RwW}1*1Fym}+J$bA=Q~n!*gE#y;^kYKIw5By96hA@sWP}IK>vVA=SwsN$O(xzO z*K|don7|YBdcVbHjT>Fw>}uc1|2#XleDT093Z2bn$b%jA8j@b}CeDeGkV*s+xaG0T z=#ZOU48ufMybQeH4z*W^Dm+-H(9-SsK@^ke{wt<%BW>i5-{u6LbQl9SU+nDkzUgRV z@j52LOr1+)J!XGktC>$D(4JF2b5V6E#qXXgbzcau@s)E7%Xpl_^BY{pgdht(IrHJe zr|1s>-0c%N%eOsl(Y#-9YIL{K+F6^Qb`OOT4!*7WG)pNBbWLT_p@&!W7zyIjD$`oc z)7lA#+rs%{)WgfUF&R(Z8s6|Lby_&Tm#UncW_+jaevxac+o`}papuzC!c27+i*XXa zpGt=I4c?OT8dbqi@%JU%es?@?NyV!uznvnJzwOlAU)qMYN)aa;$3zaWf+^itUk zpi0h9viMC;FgUeEmRA+QK#UEXr>wXFN3>gdL}V0c2;r)y0=> z(Hz+8SZN>v3Kw|RsCMv$SHBbT?d5W_pLTS7FB~SEFWJ#X$80bCXg-aEN_{HS@>2Q_j=Ko&W~xiQDbRSoLmB67qlDbUTmf4D>i&Usk{qeMqO9_c5)sns+b$03=}63gSjZu$3Q&V!lFNu zXPygQ%xTXXh=XnlZXF=vst5k9hW1VGB+snSpDbIBi|c<>6YV-9ViNp`y)rl&*6jkA zse(FVgp#jg=C;SdQ|2P#*}4{qo5}M&hXUDG9!@|l7Z^KpxnPI9Aj$uW?sWyKJHwY73AHJ1{%-po#Z z8m!tgaOEc0J-z5Aa!D+_j0aVs?daD<0b7OK6^$F7GO^_LS3+uug3 zJ4&ko-mK|A_A>`#Ik!erW1tY)($#gFNO3BJcAE(cBz#0TA6`oCqc*vs#nyTh&*u}H z)rwr-IGZ9yt@W295za(`da(MKsbHoWAks-Tr^0|}vIZ8@46DCvVD`xeB#*w_g zbpKrv(yjScHZZ4HghRSD<9hH3?%sS=rgMASH>oE|0CiQ~aw)3;=1kene0H85cD`gn z4QO$$3ZB5wWa~j8NG1!8CT|Lxp|b(?!|6Ati?+zqd&nJLf?;u52_@HxR4K5V@YJtK z9AM)qQuLwr&$yqH4drRDQFm%+iE!Qa7j6{kb|LsTWSaeD{Wgh1?$3Jv*R&D;wo$}C zrS7qs`wyt}>PLg~e`#sga1$-GYdwa&C~F|qz=q`UYh)f&Pdyyii`HiI&hf=DZ&!a9Fj!4fZjAT@8~4l!}>(1 zt5=YeQQX?jYJ~K0xX#3s`diicnrq#MM!n75=3a9&wbGgjX;R)KQku$-F|3dMOb7@d zc?^G=#ok=99!1-HGzA>9v&!qiBqZZ^?=;j}Wj50F#W!Rjy@AN;|rQzBqkNKy8p$-X?Wcmp2xdv@?X&y_x177_LGF&E)~PXP~7m+yh#7*_IxBcEO0Jg)-1t z;W6?7oBQ)gk^J}zzo@UA0kFZ}BfiY+XAh2x1zq3&EMJy{40F){yJ;1Rj!(Wz`9yQl zm7dzWw5gBumHk`aPJbaR_O~kPRZ-JiQ31Z$v0CoZSH09w>8O7Z3iK@Pa82l!)PMd?Rhw3@*Fecn1PkBv)?g zpG+KOTvjG|xkJ&P%KqUHig$OhiZ5mX=y|2kB=u|+(gdJ@{?HFO#`^KgIEwYu?7E@5 zp~oR_>Ux!)^c)}a@cVz}wOemKrpf;x`zlP4%7I)WM?N%0J+1C?9RI;qGjL=-1A**&CJ}X> zt55R6=dvE3!WU7hxz%A}wGndVPS0}bh_~1rU)%(J4Y$qYG>wwF&?*R%tN|F7nVej( z`Ny{$1eh#B5ADG|lEe~`odKrR3&uU0XEOyJ%D8RPx4!PP3brazp8BI1p}SpjS_8K) zj?kze5uL#&dO5)4f#ca`tOGG$oEaDQC(ifo-)$9#Y}HHR_Q{pxPfMN+bwa2BB{rkn z8w3uc0?&HB&2*|OZ^)V~HtacoxRqR_ygQ}#Bg?bxI{v(Nu$Q)3Ho$J&>L16>qDK{S zNBKNG+fR^xFwfNc?Zj^z9yUd}XCkwLYZ-H2_J5SG-)`V4tKj{WGFg*m_>MY(O~s#o ze-oH zlWxuaDzVM)m@e8+GmoyUJS46?jc(a%h|NT2qvI>H?e1>B;; zl&x;v7aaPB+=qhs9zSMt|HFwfy7)zzCe=M~yn{``Q~N#;o=nR?6syBKgyqTno~@Y-0OXlcduP$k>pY${pJQWgpjNSulTlt z+tgGwRfY6Oe*r7RV)Q*n$j6Tok(`!LKyh?fJRU>Mw7^3Zbz7W`tC(_WvoucqDIY;e zQ=WJidk;&r+LIhNzj&aZd2saNS97+1Nr)!TO!}32+O^L=Mw^teZ1c}qj(!*tNpe6+J zR^0p=1L0nIB`2Hjy@T4N+R2qt*n*&fvyO00ApvVag3WOV===o#X(TjT*{kmOJLmfT zYPAqjcHw6m7mk_7zi@u75=rGyaxm~3~B7N!Fq`#nj1{}XJuo&4*+z4ub zXa5Mhfmk2II#n`u?@v`mk|pLdL-iu>FWb3}TTC+#$`?)zuNfM4&?KHT9OesH5Wl0F z-7^UMIk3E63kn>dxeJJ3o%{Pv+}L-Ta*XiW5XOCL9Hh%4sC>!DsDqM7@gGu%i|N6L zT08_XA3TQ}jJH*q%<>WGW%#x!eHcm*4+9zHzvl5h9-O&*^hkXjoVgr+ZVMdyKfR|e z%vJOORWqy%xPT_DOEsFN7m_Z8*S_``FmvC*qqhKX=;8ebXmCNte#!qw|9K-_uG^U*QfB#7$=I0Nq~*1oW@k|oWAxfzi-HKG74xf zTPzz;qI>P{qN>2zJ(c}*(iH0M#H`k?=ycE3XkvOLOfL$mk{JEe$Y67RrLH;(xL zPFybV`UnF9RxyoaxD7}fK?ePfMiJ}ZH@l5}v(ydY;+J#&i7^tec#JV*PfJWD!+mi2 zqOf(sT-Z9{GmfV3Bi&+b_!jGM{{KRY1?;xq;%1HgU$at>YA*up>g< z`E$zt80zvDX8$tHq=VgL%zOo5KbK&#y4o$s^0m_H^Lhb3Q= zf^$I#F7ZcDO@cy`o!|U?Kmd1ibPRM_pL=3DybpKa9!yt=O`mB# zhxzctbgxvO-o3zP_d7uQ!Yy`k!u7=y!YB+?@CLYv`eb=!+{Vs^$2Zt}GQw{CU(^zl z8*WH9hKrEf=~paGe4pv8tgDpa3Fc!MAlqz{e!;_d^cTP0fIZSs$yLjjkQGgkh|wRa zwBLQzxUKQr-%`@!R`CP)ep9=O;iJ;n{?R=P|GN?c{SZ73iPQD5VVX@Wo7BR{XhOfO8zJ28m zy2$m#-A@xp@{>^hbU*eY7r;TBnAhu}Gec<#Gv6Ja$aBjiGIl;GxnpEzsX5FjD+Yyi zjuu|%4)#2aOr6YL{I$uS3fQ5wSRnMeSbHValKegIK(W0QFBt|uBZek|`}0t!88{oy zqWceLZ=SF?o9}5u4eZ~bMt;VopaiRD(fVAei=IY%R{q43kkI@1T8Qlh&))Nyw_xd? z0Si;H843_32QFcEga8f#=qrR^&J@)5FjEJIXGK@=;#(0I*vo>4r2C}Rvyj;Y_$N4n zBEyu12+zkN6#H=kuLL1bi_Nl#5Tgf40$PSTypiowdL!!<_{sAlo$bb(BSMGUP~M4Dh7V zqE~+3@RtZE8d5L%-^N-O-`Mv=VKufJm8|T5% z;_k2Db(N?{0|!6=%KOOgJr(G%R?RVx<)}WKVH9Gzf&*u^YsXxzn&0wOwZCX1)WE6H zt-c%Vbo`xik$vz)X5OP3nt1$k4mVyL?SVyvtEC_~ApNU(G|e|@*!!vL%0LhLc{t?% zkkp!TA9b=$(7$$=9m0;HJ0~E;yCzUqWJMEESa>8Ch?>9yW67DpF z#SXvNsTh+vf@{u`Az2g!?jpf`?=uAN#b(;$?w>HZq!5@N*H#L$J3F89c>PL^SlVMM zuo*HG>v6d81a$?nBCqZ9CO(S%6A5LBZnOscVQgsXLZ>LQMWak5s}obRhk5>%7VNBD zqZr56ePvr5I}#;Wz~}c&Onezf%PJG}ZN&Z+X<}#j>PzhJL&bRU-u=4R?9^!#0ljH= z668%r%X|U>h{BKHWpcHtApd)2ZahG?BmQ(&5D|G+c39ufH2pN#`Z_0OY2*vs@}_D1 zXSA`Zv35oF`)|FiPQav2fd86yqX9C9e<$5b-g29l~0yJB2#`09o@f^;W0RD;i5- z{o`^rF55Wbdmtjmt>|nXnl`i&Od{@M)G8|XP6$eD&^@dglP{w`g^!vK^W7Tm`0?+p z_Y*PoB)!yA19&!79K9OP5_63i+J5qmIBT0( zGb9Ra=cjE?I9kK=cEA(oX+5`RS;>2 zou(NDJ17^VIeHxOgt-^vz)!=jp8)ndbV-?g*|-a?*Y=`tV-Fo!U<$Lp3;&yi)^l8@ zbQ{US^uQG%(;(6%Fs^e-C+*?ydjAhL)2P*Vm^%Wq`o`VXdeIDd3W1bev0 zXKHV(_4Ym=o3CO7aDU{RJAKCUlTUri5ZDn1sHo1@*NTLU-TB$ZhhyePC_U=^SwmtE zi!3rR(~S0skqn$44ESx*i53GAX!+;>=5ETax$d;Lu#f5fwT~}zU&leEUMzXxoCq#E z)3MBR28?}6(eFVA4<4CjMQFcqA}s_tFKQvNgMIm`AogWI>d%;aEJ41$ z-YzpA>dF?FuMWS*R>i=ty+6+j_meP7Lbc=eQ(MqO+s9x487Ip_x%+`sVEoSj;=>sH z{9Cy2PzR%46iy}?>mkWGa(V$=L_7Ip?7|T8nwVo#45;@(+TlO`TtW$q%FVO_iL6O4 z*eNw;j)C`Pm7f3UZ^3(1qc)FeX6p|lQEv;dh$xY^=w})m!Ry3n_hr!QIz2iO|6H-} zZqJMgK040rBw&_Mm^*DmG1D@IC47a}%;PI!J`2ph0c4vY7tg!9b_o-FY2X$^k*=~R z!=Fo3MB6@xyXZOrgD&dxcly+pc>mmd6;1iTkbx^YPIc6_<@TC_bpfdh1B?9*NG?Tm zlCRgS@>O7@-2k6R`8?5b*3mn>XXuBcRXIn%l2g8F(d+hyuGGoxd)9_ZHmDxJBftx6 z2h{uC97)wOaU!Yv4+c}Pvb z=4Av%*Vax3s};coFXykR_Uo2C_RU)gVB^7SO=7e8`BWopYXhA!42RbD{0mr+&mTbi zXvasWz|HbanL0`3+R>mv&IQFP=ewfoxp_g{-gEcxHbH#=n}WKWLS>iSK-eoxDi_Uz zl;tCj_Z2^Ie^96V`*AuXZujIhe7%$Dz9OqvSW=6Kts(KUu!E$n!Nuhy>wfbnTffRva)g&ygHza_&=A6cWvebUS;cM?tKRE@j$=VI@a^8&S*I?RK zWSk8>wA9|uk&jD$FWpgVdP#ShZ-dl}via#>_tM5&2=?txp8?zZ;Kn%q^UtD+zLz`Y z=jpK>4#?@}JxP{+_@7D>;n<8#iFqqWNs8?ywXKrCi*jB-RabP?Sqh=1+@KT%Oy*&} z)O*{Rmo@`T$#;zom(iOQIaH#(PvU3G+V(F7I~x}Yz7tZ8PBq?ERXyC80()@%qBy_C z%lS98_G9SM?w65&nFFR=<`=dCAp^R@1y3fx8U`Ip;%=U6DEQu@4<9H*Q${51CD5fj zn4{DUy%rUf7=innh+_NC(Gmc{iyAga%y}9ysFglmd`VY1Oqg=$K*HO)j)t1k#;oY> zOp21FHr=5WzZwXK0PNg~!5ZcGTt^5_uNqy9w51d^hityy%)n!ch}Xq@N9%-~#ly$r zgvrR=qn|-b&*R9)fq%h6-tO>udJOi-(Q^lU-=iNrP9Wdu@c9OcZbv_&h`}2>`ndw} zm5v^j|GfEsrsZ%i{AaiP=MWuPh5rw2i-1l(RHOl=QCUgJ^RTFg?OFK5%M*BcW&@W& zQxOYCc>FR3IvjNMbQKe;gElMH*49-Ti0Nz*DLvTV0U~*FZ375++YdS>K}$fS%K*S< zLh2-_;R3Ahzy|RV@Hn9Z%MM5~AzG*4AADIydMm{6m)~Lm(JiF=D-^_+!Ej0=OUAS5JA({vyE{Q+tN-~0MHAM9-)wMkyPh+;A7Y&A%RLB%T6f|o&~`_TH1 zY<=kif-&K_{z4WS8X7vfRN&=8TZ{6N98mtJ;IRYEGd>0e$u^)lL#vg1pj!foadU_p zX^}|ezYpcD&=vhU2q2=j2~MIowZYl-IJE{{0-;UYiYK`l==$(XMq2kmzv?EgNf@;F zHe~4BAn&ea)A|UyCy{a6B==!LR`bjE(xJN;XlIdfn5jc2xN-n`Q@fyNHusFMJ2H4S zq*)J$AbbZw0wl?9m=p!bz$&N;Y%@aN0;CupMhLyE{(#U`P+%a^c#>IFQE2`fNC`EN2qyqA9lASr?n8GP5R|h;>R;6h<=WsK zm_UCEDCbV4gYU^X230wKj}=3jGT`hzeflO&o|vg%&tPAdvU^AfK8>%9oCy2#d8 z6e9e2=)t`Qee1VtqNFBgGs~kRBO}AZ>87DwEz)6Hh=BKbb`MO9S^3_2Nl8hyFNs&S z4b1T85pDo-7>lN^i-P!$`=7To{bu%{02vSPtvyJ3hHAML9?+~nMcv37^qEpuBLg?!lb`|iJ!mx zkuNcP20|`Q2-T!B1WLWF);$u68)_8UfU4Z9 zcz~thA-K$H0PU#(T#N3SOz6m86-55JjXnb zy|&=MPoa~V89DN(TA^4PYTn>vl+7|0sAm*q62ki$nCvz_haQaP**$Xd^5rl&H$stq zYqqnUpe40)z{JP5??a#QyP=^3U|RnxiAJQJje09vF1A`+s0u4^w9dCePDKH9>A@br z`okG=N9Gtus(2#Y7@Dv-0tFlCcmv|m&PVGw zS3wChk|i2?7N0~3paAME&nTKny>ZYDlGNpU81wxP{JSFr(!6U5j*eT5lL!|EX+*-$ z>$&Wy${h;Kwx^a z0oB0fN$15MxQIkjRu(g|s+*Ji2VB~f|A@kyFM#5Q{F5isRKRW8@H$5^qcsLX2cPac zX7yqG{QZZ(3aYECe-nmj>VjStyW=8|-vR?j6i#pk#c75tPVDXrXDKPa=1FVrD3E;> zZd++Yrj~hrAM`~fB`2SaDFjqehs2&c3KZYW@^_N=1DBSTK;bZU zO8~xv01jfqfoHJ*mD#<;_U52h2g>qJ?XRH)iDU%(BVpmB#Ke6oLJ6?;V6Z993Bx5M zTY9~|t_~~@+yy#1I&kS=nrHpnzy>8JCj+>nb*|SW54wt|toMLT@D!3ib~O%~K-tXq zZzcce?pAS+cDv+N)tar}tmOy2ZNN$t)-*{-N)CL}#*rLEj8!ia{tftQ@C$Jhx7}U$winh<3CU{u7J*Cl)!{3jaH?h`^VSurNbXPi<0g zS2FFgYDSsdvf!En6;vv%4>>eId08LmV_(6$J*l|LM?Kq->v3y6RH`Zeh2l+18Z`qxa`bc!BI zNubsUyb=+Uj6DB4GkW;m@aDqM7!37V9-4F^q)Jh^B0Hq=dQA3f16A`($a?Dze{qJq zinY*%kb>ItFC9zED})+QCA2L$~*0YDA1AUPboOf!-I+pmdx6S z(l^(jmoy>-hCJ;oSHjPrHp7}H#YIGJGcfQvEItjoC0U7$`ry)bg@#M0ie@WoYjJV$ zzI=0O=qQFf79~g?jeiATw~jRB0=&c9E7=|Uuk}q$#AlB#G$SAhpcb@~Pfw5B zJ!Fr5-beP&Zo`nAC&kePm;3ZnBH27--Y@)^Tq#t~08bsfIyPvN_?Pn4&VqmnSMtEQ zgcre4`2cYX^0XgEHp4x4{xHo_r#DBE6&_AN5kpz1*xBVFeMXQ+Mh$LLk1A*gaT7u# zumApwpUM*uzZd(9Mm2wPu+6NE;9Y=s4eo3{xYHwd54Zj2eJH>|2?XYu4{55XbVCTz zW{3S#k6z@PiGV))f18+0WMTrrTV*&x0a1}i&928yXp$o$CM`{Hq!oi&1EpA$z;?=i z8BF8f!61GwIQRXz#>(KSRU%E3;1MWAh*loUD=P$)_q*dB;r$(nDnRI{EAupHaAp3r z53r}?zm09RwDzgHA%Ax^(7W-;W&Lht;m9rzbAvkStJf8pi4Is|gq>hqCY3Z`E!NYt_=d zrB(-20_?vG|AV9$bbwli{okjjk50&`2#HON%59Jzal$h7}!c>a((V1;db?b;8Fowb1x!<{B%w5 zkF*O`nCj-28I4@tZjXI?D<hWas`voWY3%ozA$7)};O}tfSA)3j^2s;f?X=aR-KZG3 zUwTW7F1P%ldw4oeVrugBkB5ko$0F=kk6-jOG{SODPEG}QDI8*SwpCr*oNBt!sI$*g zLF24?D}4349q|(_a_mQ(;!&*w9I*OrN=-t;7vu7_5FEOVx~QNhc{=aoK>-WeHDylx zg1$w8TkLxgY3*Fyu zu(Rhu;o3+>0;Pj}g3=scWL^wsru2^Z>Y|CU(xIWafFunrr_9ZnpjpvqGzJj}duzjU zX01*xxO3CHJ^c2Dk#_WidA5}#c97>akF8P!x%Y9{KGebLHT zVHal=Z*8{B7US^-{_g2u01sApXad|vaI}vvm3NY0_5w)<3>^v z=^v!61Pe}=7RW7Roay-UVWO5M=E{9&p8Dfe3@G>-(dg^yZqZ1Gv!r742cmd=l?^3)RBOD7TSV3{j}<-joQsEgj~CXD z`K;k)gg8F_U%P!_|GZOK|>yu*T@WgrQUJ^h7`eX{nSclhi?*r zWAu!4{NDyF9-6Zkm94(g+|}IcoenuRGsx^R{y2W%kyWVI`UP1#hM|;^D50H0a0lC& z=<_iU828enb@mtIeL?eaUi}98onc?qH?BI~z#K&V#PGTPo?G(8xS6bO@4P$#sR+T# zAbUyY%n0WXdCnet!85~)W`)F&@IfZJtu5|L+H^gXXsfBK-+`bl1yU;4G6|BcSMsO# z$x;`UY@76Z{7gi@W8BP!&BSym8@s<&Z#kKjIDPBT2+SEs&$_Cmx(S@0L7vI+R1(@I z4TWmOn3S_S#>qt@Ld@Z1Z#L(({6aRdzBTz_O7h$Phpx8($};S>hLLXR4pES9MY=nryFnW1 zkdTmW5Rej(hKKI%Zb3@AyF2B-(D(h$nKSbnF`!7T`#M2f2HLc2{U*T{XIrMUmUA@LYX5D@HJSu%l&fE z7n8baDGpp9T;Q$_wa6iR;FqyYqwh>6+RITp33bTly?!iHl#2x=8%6FhKygr*_A}Ss zyYSx)@Dl>Ti8GudpQcEJo0$O8bsD)lS$HDYO#5WubePk zr`gHWSC)T2YmPCqf(~^7+KDu`HssFDQNrZimZudEAB zF>39jD)!bnGCqrD-vCHiBC=?++6MrP6LPG77e@n(n}gbImUoP_^#YFo_|achZ1oda zT-t9d&Q200Uvx>(atUdp2OMMSrMuUnuiRpqgE$P}7l{9fD>XnRA@~=frb&7)T_%^i zCcxy3pAx?#-r2b(>?w#LPS+9>jcG=TPc1XPe*Kz)0>qgc8yldF=YQi&wI^%(sHmm2 zd*Mz6fCx^K$@|xu00aRO&Om4?E+H{3_PMvuaZuOGvld(j(4H*rL>n{~)f4+2Ra@mg zYPQ>+#H~QoA;C%7u)mH`LZ0+mKJ96;s|w$i-*f&t&_;SU7tDYHUq!;pk?ip8HPD6L7rS|D5mqC$>B<#SXya|A6Lhdzmf93`b`L6UA%m0xp5+Q@O`ZNG4 zLUlzF)YaDhF+Q-Cs9$4MymQu5CG(Et?ZVe1)@pn2ER^|Hy~oG>1!oPF9ejl2BTA7x zC!}B>#u_76{F=nVlKQzQtML)LAq52~ay?yVJIhkY5>nZu#gcnaEm!GD0OS)x#;i2$X`53}w5Q@z# ziykzEHjgW+l)aA6UQBnmqs@Rac0hIRmN9~{8OotLU+14BTxsx1qm zkdTqx&ok3-3njhc_avHrIaOz5iBV4GQ|WnqV;$(4a<|)Aog7Zx)k2OKoHM4E z%D==5(EZeBF7#l1vTSqhWh-+4Ky15x>Y%b&EEs4P$9nu>ekQ*I{Ftfb+v!`WqQ|`J} z6EW2ESj(~zaCg4uiDGu4ZdPuPp{m(3VC<7KeX^RmDVY|6CR=r2If_Z(2-_1{df~Rc z{iU0<-6Vli?%x`Ng;r4l)35!br71xZAQ9GwwGMYnOS(=P+esS(>k)$ACqw%;YBuiG z^Ph5Ec$GbxwQM|5@bOZz&T)R-HaE32lUHVV8yab>pQ;`HiX>>LR*J>#eDMa3jf-=# zS-j~0lc_78H~H*5yNYG7LRGLIe#^eicqN5nTfNqQ2lL-UK$-!AQ>;^uB?!W15G+n0 z2zXptgTBU4oFwl>MMb%?B@oAg|E|dj-bcRU{~qv-AAMA+P4F%0|mBueSHn~Px& z+1TrZNhLtXBceEiE((t-sP`lJE9}kFVUmbuZhWf`{0LAD9tJL9$rWlo|4yb78<yu7@}+A=b1Y%p!Mc$dM^@$7l` zc@)YX7?KTH6nMKL_?lTNP)7tM>i5>yC`M_%*42xV5U{PO5+4o9RsZPKox!g~u11mN ze^mQAsOnIzso{y{uu+Kkg0V0B_Zx-RLvL-lC+cjdRsCo#f2cBu{apJp>Z^cEEOK5P z=Id-|@*}JZoU>@U-2Cl__q5QyJ~^Yv_dyYDFTC9H#$$P5t$ ze_q|zGpMj(dx9pN(b-pqOX26yg7&6ObL$TzFzl))NL&Qor~=Ny9tmG{O2!9p4G-OL zg5$|e*2ibs3^S|DVe(#=V7my5S+r?9$0ibC5Q)L@O8 zvH3gIUeJjGbAMH-*=rV&BHJ`pItL#9$W|yQAmFX#gyd&WfcD!gHX#{Y>`sDmpD{PD zzqTYt91L?uRI~v(H@n#g!=Yw*c{!K?tL#~vSW@ED?*yP-F1BdODazl6yAhQ?}8r zsn0z~9QrqJoSBHdog|cbbg4A?7=YAyEK^Ji{tC3F0lgczhlBoO+z@FU|6aQaka{!$ z@oIfT!|d$rx4DijFX!?Tp#pIh2iv{sW5c0bp@5U;uM%pD_$*2-I=vuYHc6-6%7>k%Zsl3M2VL;Gq&kHN`-H;Sa%nxRfBYhzioTLtouRzfl;?Xt|USBzkOBn z>8CF1d;XbM#&y9V;cJvFli=x2N$pWTl^APEkmT98tY-rcs#b|5hKKR}I3Y<*$=9Mq zK&Su;iII`�r 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

e+5r+Vs+3E&WPz<9ySa2pp&Ob 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%0A6PZKiqdTRnjV#DTUZkm~^~DTei0+ufH` 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 + + + Option + Default + Purpose + + + + + reaction_iteration_depth + 5 + Controls how many reaction-product iterations are attempted. + + + deep_search + true + Controls stricter RDKit/NetworkX template deduplication before atom typing. + + + deduplicate_reaction_templates + true + Removes duplicate reaction templates before writing LAMMPS files. + + + wildcards + true + Uses LAMMPS wildcard maps to reduce edge-template duplication. + + + write_second_reaction_stage + false + Controls whether the second LAMMPS reaction stage is written. + + + + +Default JSON block: + +```text +{ + "reaction_iteration_depth": 5, + "deep_search": true, + "deduplicate_reaction_templates": true, + "wildcards": true, + "write_second_reaction_stage": false +} +``` + +

Important: These options affect template generation and LAMMPS input generation, so changing them can change the number of generated reaction templates and the final LAMMPS workflow.

+ +--- + +(reaction_iteration_depth)= +## reaction_iteration_depth + +Inside AutoREACTER, reaction generation can be performed iteratively. First, AutoREACTER detects all possible reactions from the initial monomers and generates the corresponding products without looping. After that, if reaction iteration is enabled, AutoREACTER takes the generated products and checks whether they can react with any of the other monomers or products. + +This process continues until the maximum number of iterations is reached or until no new products are generated from any combination. + +The default value is `5`, which means AutoREACTER will attempt to generate products through up to five reaction iterations. + +This step is implemented because reaction templates are generated based on both monomers and products. In multistage reactions, products from the first stage can react with other monomers or products to generate new products and new reaction templates. + +If this option is disabled, AutoREACTER will only generate products from the initial monomers and will not check whether those products can react further. If products are not checked for further reactions, some reaction templates may be missed. In the case of small molecules or monomers, the length of the template can be limited by the size of the monomer, so polymerization propagation may be limited to dimers. + +You can set this variable to `false` so AutoREACTER will not enter the reaction-iteration loop. You can also use a non-negative integer to set the maximum number of iterations. This helps control reaction explosion. If five iterations are not enough to generate all possible products, you can increase the number of iterations. + +The examples below show this behavior for an epoxy-amine reaction and glycine polymerization. + +For the epoxy-amine example, the input monomers are: + +```json +{ + "monomers": [ + { + "name": "bisphenol_A_diglycidyl_ether", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" + }, + { + "name": "1,5-diaminopentane", + "smiles": "NCCCCCN" + } + ] +} +``` + +```{image} _static/loop_figures/loop_monomers.png +:alt: reaction_iteration_epoxy_amine_monomers +:width: 100% +:align: center +``` + +Without `reaction_iteration_depth` enabled, the reaction templates will be generated as shown below. + +```{image} _static/loop_figures/wo_loop_templates_template.png +:alt: reaction_iteration_without_loop_templates +:width: 100% +:align: center +``` + +With `reaction_iteration_depth` enabled, the reaction templates will be generated as shown below. + +```{image} _static/loop_figures/loop_templates_template.png +:alt: reaction_iteration_with_loop_templates +:width: 100% +:align: center +``` + +For glycine polymerization, the input monomer is: + +```json +{ + "monomers": [ + { + "name": "glycine", + "smiles": "NCC(=O)O" + } + ] +} +``` + +```{image} _static/loop_figures/glycine_templates_template.png +:alt: glycine_polymerization_reaction_templates +:width: 100% +:align: center +``` + +--- + +(deep_search)= +## deep_search + +`deep_search` controls how strictly AutoREACTER compares reaction templates during RDKit/NetworkX-based deduplication. + +During early reaction-template generation, AutoREACTER has not yet assigned force-field atom types. At this stage, RDKit only knows the chemical graph, not the final force-field atom types. Because of this, two templates can look identical to RDKit even though they may later receive different atom types after force-field assignment. + +When `deep_search` is enabled, AutoREACTER extends the graph comparison by one additional neighbor beyond the normal template edge atoms. In practical terms, this means the comparison also checks the “5th atom” outside the normal reaction-template distance. This extra check helps prevent two templates from being incorrectly treated as duplicates when their immediate reaction core is the same but their outer chemical environment is different. + +This option is useful because atom typing is not performed during RDKit reaction detection. The extra graph environment acts as a substitute for missing atom-type information during deduplication. + +For example, two reaction templates may have the same reacting atoms and the same four-atom dihedral-distance template core, but differ at the edge, as shown in the example below. + +Using the following polyamidation reaction as an example: + +```json +{ + "monomers": [ + { + "name": "4-methylheptanedioyl_dichloride", + "smiles": "CC(CCC(=O)Cl)CCC(=O)Cl" + }, + { + "name": "heptanedioyl_dichloride", + "smiles": "O=C(Cl)CCCCCC(=O)Cl" + }, + { + "name": "m-phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + } + ] +} +``` + +The input monomers are shown below. + +```{image} _static/deep_search_figures/input_monomers.png +:alt: deep_search_demo_monomers +:width: 100% +:align: center +``` + +Without deep search, the reaction between `4-methylheptanedioyl_dichloride` and `m-phenylenediamine` can be treated as a duplicate of the reaction between `heptanedioyl_dichloride` and `m-phenylenediamine`, because the reaction core up to the normal dihedral-distance template region is identical. + +```{image} _static/deep_search_figures/w_o_deep_search.png +:alt: without_deep_search_template_deduplication +:width: 100% +:align: center +``` + +With deep search enabled, the additional graph-environment check detects that the two templates are chemically different and does not treat them as duplicates. + +```{image} _static/deep_search_figures/w_deep_search.png +:alt: with_deep_search_template_deduplication +:width: 100% +:align: center +``` + +However, there can still be edge cases, as shown in the example below. + +```json +{ + "monomers": [ + { + "name": "branched_alkenyl_diacid_chloride", + "smiles": "C=CCC(CCCCCCC(CC=C)C(=O)Cl)C(=O)Cl" + }, + { + "name": "m-phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + }, + { + "name": "extended_branched_alkenyl_diacid_chloride", + "smiles": "C/C=C/CC(CCCCCCC(C/C=C/C)C(=O)Cl)C(=O)Cl" + } + ] +} +``` + +```{image} _static/deep_search_figures/edge_monomers.png +:alt: deep_search_edge_case_monomers +:width: 100% +:align: center +``` + +In this case, the template contains double-bonded carbons. In one molecule, the double bond is part of a vinyl group, and the carbon bonded to the alkene chain will be typed as `c=1`, which is part of the template. In the other molecule, the corresponding carbon is bonded to another alkene chain. In this case, both carbons will be typed as `c=2`, including the carbon in the template. + +Even with deep search, AutoREACTER will only generate the template shown below. + +```{image} _static/deep_search_figures/edge_templates_template.png +:alt: deep_search_edge_case_generated_template +:width: 100% +:align: center +``` + +The following template will be missed. + +```{image} _static/deep_search_figures/missed_templates_template.png +:alt: deep_search_edge_case_missed_template +:width: 100% +:align: center +``` + +In this situation, deep search is not enough to detect the difference between the two templates, so the templates can still be treated as duplicates. + +With wildcard search enabled, this issue can be eliminated. See the `wildcards` section below. + +--- + +(deduplicate_reaction_templates)= +## deduplicate_reaction_templates + +AutoREACTER first generates all possible reactions and then generates LAMMPS reaction templates for those reactions. Some of these templates can be duplicates. The `deduplicate_reaction_templates` option controls whether AutoREACTER removes those duplicate templates. + +This deduplication step is one of the final steps in the AutoREACTER workflow. If `deduplicate_reaction_templates` is set to `false`, AutoREACTER will keep all generated templates, including duplicates. + +We recommend keeping this option set to `true` so AutoREACTER only writes unique templates. + +

Important: If deduplicate_reaction_templates is set to false, AutoREACTER may write many redundant LAMMPS reaction templates.

+ +Example output: + +```text +Preparing templates and map file for reaction ID: 1 +Preparing templates and map file for reaction ID: 2 +Preparing templates and map file for reaction ID: 4 +Preparing templates and map file for reaction ID: 8 +Preparing templates and map file for reaction ID: 9 +Duplicate template disabled: RXN_8 +Duplicate template disabled: RXN_9 +``` + +--- + +(wildcards)= +## wildcards + +

Important: wildcards requires LAMMPS 22 July 2025 or later. The wildcard feature is not available in earlier versions of LAMMPS.

+ +```{image} _static/wild_cards_figures/REACTER_wildcards_Diels-Alder-example_ed.avif +:alt: REACTER_wildcards_Diels-Alder-example +:width: 100% +:align: center +``` + +More information about REACTER wildcards can be found here: + +- [Type Label Framework for Bonded Force Fields in LAMMPS](https://doi.org/10.1021/acs.jpcb.3c08419) +- [REACTER website](https://www.reacter.org/) + +In LAMMPS bond/react, wildcards allow LAMMPS to infer the fourth atom used for dihedral typing from the first three atoms. This is useful for reactions where the fourth atom or edge atom is allowed to vary. + +When `wildcards` is enabled, AutoREACTER generates reaction templates that include the fourth atoms or edge atoms as wildcards in the map file. This reduces the number of templates generated for reactions where the edge environment varies. + +We highly recommend using wildcards for most reactions because it can reduce the number of generated templates and make the simulation more efficient. + +However, if you want to control specific reactions during the reactive simulation, you may need to use templates without wildcards. In that case, keeping explicit edge atoms can help you control specific reaction sites more directly. + +For normal vinyl reactions, AutoREACTER may need three templates without wildcards. With wildcard support enabled, the same simulation can often be performed using only two templates. + +See the styrene vinyl reaction example below. + +The following templates are generated without wildcards. +```{image} _static/wild_cards_figures/prior_templates_template.png +:alt: styrene_templates_without_wildcards +:width: 100% +:align: center +``` +The following templates are generated with wildcards enabled. +```{image} _static/wild_cards_figures/wild_cards-templates_template.png +:alt: styrene_templates_with_wildcards +:width: 100% +:align: center +``` + +--- + +(write_second_reaction_stage)= +## write_second_reaction_stage + +`write_second_reaction_stage` controls whether AutoREACTER writes the second LAMMPS reaction-stage input file. + +When this option is set to `true`, AutoREACTER writes both reaction stages: + +```text +3_reaction_first_stage +4_reaction_second_stage +``` + +The first reaction stage usually uses a shorter reaction cutoff and is intended to capture close-contact reactions. The second reaction stage uses a larger reaction cutoff and allows additional reactions to occur after the first-stage structure has already reacted. + +When this option is set to `false`, AutoREACTER skips the second reaction stage and writes only the first reaction stage. In that case, the post-equilibration stage will use the output from the first reaction stage as its input. + +Use `write_second_reaction_stage: true` when you want a two-stage reaction workflow. Use `write_second_reaction_stage: false` when you want a shorter workflow or when the first reaction stage is sufficient for the system. + +Example: + +```json +{ + "write_second_reaction_stage": true +} +``` \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index d3c289ad..6d3842e1 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -15,7 +15,7 @@ Welcome to the AutoREACTER documentation. AutoREACTER is a tool for automated reaction-based molecular system generation. This guide covers setup, input configuration, and supported reactions. -**Note: AutoREACTER is currently in v0.2.2-beta and under active development. APIs, configuration schemas, and core functionality may change or break without notice as we expand reaction library and force field support** +**Note: AutoREACTER is currently under active development. APIs, configuration schemas, and core functionality may change or break without notice as we expand reaction library and force field support.** .. toctree:: :maxdepth: 1 @@ -28,4 +28,4 @@ This guide covers setup, input configuration, and supported reactions. supported-reactions.md supported-force-fields.md change_log.md - contact.md + contact.md \ No newline at end of file diff --git a/docs/source/input-configuration.md b/docs/source/input-configuration.md index 2892d721..89fc160c 100644 --- a/docs/source/input-configuration.md +++ b/docs/source/input-configuration.md @@ -167,4 +167,12 @@ Each monomer (or molecule) must include: **IMPORTANT**: The `monomers` section must remain consistent with the `monomer_counts` defined in each simulation. All name tags must match exactly, and every monomer listed must have a corresponding count in each simulation otherwise AutoREACTER will **raise an error** before proceeding with the chemistry. +For advanced workflow controls such as reaction iteration depth, deep-search deduplication, wildcard template generation, duplicate-template removal, and optional second-stage reaction writing, see the {doc}`advanced_options` page. + +```{toctree} +:hidden: + +advanced_options +``` + **Note:** You can use [SMILES Generator / Checker](https://www.cheminfo.org/flavor/malaria/Utilities/SMILES_generator___checker/index.html) to generate valid SMILES strings. If SMILES strings are incorrect AutoREACTER will **raise an error** before proceeding. From cbd669fe54ded4a7185dfee39610fb33e2b5c671 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 12:16:56 -0400 Subject: [PATCH 131/176] Add example configs and docs assets --- docs/source/_static/Overview - Copy.png | Bin 0 -> 719721 bytes docs/source/_static/Overview.png | Bin 719721 -> 109342 bytes docs/source/_static/nano_cipher_logo.JPG | Bin 0 -> 29748 bytes examples/co_polymerization.json | 35 ++++++++++++++++ examples/doc_1.json | 39 +++++++++++++++++ examples/test_epoxy.json | 51 +++++++++++++---------- examples/test_styrene.json | 1 + 7 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 docs/source/_static/Overview - Copy.png create mode 100644 docs/source/_static/nano_cipher_logo.JPG create mode 100644 examples/co_polymerization.json create mode 100644 examples/doc_1.json diff --git a/docs/source/_static/Overview - Copy.png b/docs/source/_static/Overview - Copy.png new file mode 100644 index 0000000000000000000000000000000000000000..af88afae71c0419305d9ac088925c60f6ff37cf2 GIT binary patch literal 719721 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
ZY` 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

jV`Tv&mFth+j}tA&y#D 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

lQjODgkz$LjL35pZaTuoL7* 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

Q7Zq)}zAW=h!nazz;aNIAqgRZS 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®#RE|%TxvFeS#tgHBE}gKrsW01zJWK947{b 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 |sLIua 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

29A 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�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 YNBmgI-XBlKM-eWbQ0Qo7w5&!@I literal 0 HcmV?d00001 diff --git a/docs/source/_static/Overview.png b/docs/source/_static/Overview.png index af88afae71c0419305d9ac088925c60f6ff37cf2..b9e454af896a32b5666d89fac176feb5eeda2449 100644 GIT binary patch literal 109342 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ǭg5B7D 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

K2^kN=4*Glq9p1dLb#NWT! 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

-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 U(DVNZ?fuvJ|2N}D`D^-r0l>KT4FCWD literal 719721 zcmbSz1yGf17cO8@(xsGyAR(xv3LB9UY3URsL`q5|H;PD$ASIm=f^?T4s7R+Y(hUNe zuDdpP&hh;Jf9K9zXU?1v-1~cD#j~FEtj|Y5P7)vIJPrm12L4?sF(nL))1NRfPCPh^ zg@J)Vb9mzc{14MsNm3N!V+-{x{N<#{ZQ0ux7`cJCd-|u~@7PbIG;A?2&V5Gzhxyei z%@70QFy*e;ZRKaW3q#oIWJV*1Up20G7A({jDJ7&%A1w`MZ6^8`nO9_-x4{_XiQhWc4*}pv=yL!bHb!$+wJ4X zx~}!eb=xWW>dpPuO=K%xXXbr*QXJ-C158*E`VWr}(G(FYskE5*CXf5Z>`*!XiTKS( zek(Zw%$bzoO6Sf)2lNIDXtBgdr3a7xkv`=sTC6t2qmvj|mGCQiiL-=?tkx7mof!RR ze)wX*&(Ar**NgZQ(kCj6T`5b&EFkzuhS_!&gBk_jslBRXw%tau^} zff@7xT@`ir7WFBgi9OvWT%vkXgc0LO8!r6Z;3Wo;C$U4j5PrPtldQAu5*R<@Dd6XI zXE7OYn3ocr&x`E-)Fi?P!1#2V3x4jc=!wz(t*&V~5+z+CL#Y(6z`Drs->XnLOPICD zB)Rv(6Z;g7XGi~ke-9B2{f#m@;!C7(K4yMPrWlJJX5tt;SQuyi|MtC4LVx~zl;x%{ zNmMldquyuwqR&MW3W|PjSoz*<%&4$0?~`*hG*F~7C*e8IbzwV%jG2F)m+D2Xz@ePy zi=AE;J^sAh4@O+x?l1E5F}xVY6FV1xA@VA28uB(^PAqWH@VMBVCKHoBMdvyf8<1MUO;f^T=sy3KQAV)6GY! zd?~JQ>9t6R=U$_7-r^o8FJ@2~Ec6?u{EtWRXOraFZBLxqaBY&59?#Ey+4ypx%T;6G zZblSp{VLrog`K3pN41og!$?-LzaBt5J8OQs264DQL$o`e?dx#mx_{z%UISU#zB^uN zLLv+QSlQ!?A_YZn>n=@e_{U1C9@4Dfl3U*2^u)+D{?|7$aI*V>p$}D6);_S~aXz@^ zJcW0Gx=9$RtB+%c^^ZL*p7d__5nL=^=jY)|S^A|SX7eL?;?-Du+Oul2jt1O?hL8^D zfCh{F+lng#m95`8CUu1m9=_)c`(pC-(sXlQ#cv2TG)zldYW$mloD^SG36 zQklB&_0>0it#&OwF!YTU6r}pN<+mIX%c<7&V?yp#Iqueg-upNB25;9&M%;ZfY`%W4 zx))mg$vDQT>>2HN)wt)Ih})mPtRXb(t1mfNc5E%o)KNc{RCXo%ed`4&_xh%qHPS<9 z&&0fvz@R^lcFMSz21Z7Y%+GVk{q3U~ zunzkdlC54DM{#9i--&56De4FI+=2FJkSFu4%t>|j>iC;`93Ay*ln565uuE{@veD%k z8mX~Kmzo1ZjM7Ld(}xx79TfL*;X0meZ`tm?j^sHMm69opweiMK9Pm93di6MoNo2DL z9(O!zR&9#X(rVAnQ2*lw_@}*@uo$<)eTh$dYx_=5*}sqh3!$QolD4^`-;`?XE*1Jq zpq5Ayc+&phvS#9ht_f=Hjc*JY{V@5ob^fn*5zYXPGbRb#OcEB!9&&SC95kH!mEn)4j z{Ay6vWu44h;*xQ#)N2ImpvY_=&b{^5Y*l`~dhwIlhX=OGPxJYt?S7l@SoIZM<%&y_ zGwnDYt#SD}Wvp0Y9HL#O|Kzzye8SReJbW|)=FySG+-hOSN@@3RL-Nf-W*oO(KM_-} z)mGY??ZOcw6O8v&%1xSEP8_4yx{biqAM_!1{++(I2uh>(CrCEtv-`%zaK_nHb2v3~ zu4#DQZWH|HLFe(%sY#f^>Pg_h{MAn#n@Z|gC%uF6@Q71_6qI7Z)86c+mo|TUT}$RY znwvh+?pApkf3y4&+3)~69$~|E!fm~^nQeuG>xAr$m@47EG%84n?rM=abNm2Vi|AV~ z_3n$0QhE2Q{tlrBpF7`L^uEEz{lLBT>*7EjvzdvSKA|1a-~JV3e4_3|Dpu(a5^$Fl zEB#Ac3Li72F3n8Yi-ui6j8Vww;?2M?z@i9!S4PQff4@N zXMMIGzNW#h-MUEQFwr}4YqxnZ&&lyJtq&!&Hk=#9-{(ezRkw3_RY7#rmh7&gmBZ}> z<)e5nIg(A*8mlsxx-foU{}=4X)?_0P!G`xju5(iYV~Y;;pCGBSN|l4da2KUty&p!a zR~BM16e%ke|Mj-RtUV*fum4K;GwX$8?`6%CBo-D2$WAYhsNEvAUhD_YnMaioVLbaU zOoiIiyebs4*c%ih_?DJVFnIsxiH&VrCu+OM13oMf@#EaM!y?7 zOG%a~yIHd<{%i#a$GPWQJ{HXo0XDyg%7+r9(`ZPJ7|J0LapYa?17_k4iQ-<)>js@2 zZ2r0>@z0pX+LOpm-zJ!`V8l>3UK2{*{n)1BDn7+l40<^GoN4fRnPNPg+@4qTwrj~0 zb)IK%IWokh24bKU@*OcLRqCvJX5h9Igt=O4GI6B}_R+kJp`EuxcOKriR48!`O*yd2 z%c~|)7CJ&Fl89_FtC6aqoVz4no1@tM$tm)UjTa90^}r|ycKXg@i2l9Vf6`OWCZwmS zF>FSX>ui$u5mp_Kx|d8{b{k2#=nfCalNthrPOI{I<->AUIzIc19cDJ|*Oz37OJ|xJzsBv&j5+$3 z7xuLE7A*f@Eae=kkb5#q>2qG^R$ve{8*H{MXC>@mR*6_szuXvdO*mYTZ@#PZOM{2+ zhmh0Wuy!swO!y$8f$7?l6Tpbf{x~%(01U zrse7Kb?snQ4mYJQhgJZ)m@4NU3SYa$7fL7;Yyd?Iv99B!{T;X4e)HnMVrtb@S*FsoXqf=g?E$yz0+c z2PO7bD@niTu}Fpb^14dj`Ba8Yxb2Z$g|(sr=M*%pX3%b+b9`CZAIVbXV)_&Ac=`L| z9sKOeH^IlllZ(C8KzGtLNi6^)9_zRqdQ42eah0xNC}Ys9?a5)(W<#U=H|1mwkBSt2 z^~g{4>L zJanIIUrX3Cp%1odcD=t!OqNnDr0-4%NJ;4j`0}pKTUE!R+J{QjO5G+O#;Ck`4;HNl zc6D*at8Qjk9$~R0#1CJ6eSQ23d~k&~kvTazzmful&)=|n0DPwe6%O~R*?;Z#Z$vmO`Z;qV>vg;jh7ywH#Gg;?WcD}=utv{G^3eY zQn7Wn;VlcZymaHe2C1i}8zIS;gIS23I&UcI>K-)nkDwL@ic3l&5LKp~?r&D>~|rqa?*QUMOuv_v7jPzkxAW6{kY~yUpK3tPHEMNEx{{A)J=T!Y0!Cl zSbm6f&ff^jpERvEl_(Byb3rjy-iZ-#La~14rr^?@Ab9`&eUaG@%Z-J;z1wZ_g~Mkt z7(9<1_oR24COdfOKMxo(tIzDnJQUvIBKeN;TP$WZY7Y)!jvLzb$9~9ntM69@YFn$L z_{*2Tl+E^v7cX9Hjv$d;X^LH2{#4idi>>0q!XyGbXfuW+FbKJh&E52&yOiZ)^5H0d z(S(;rxicLe(idoQJ)vneWO8x=5lG6x$rXAl=;Y)nqcFoBHTRjHKie`j@@Hlq9Xv2J zG#vjDz;DrC2R^M*9)Llwdu$9HUoaF&>XCNwIVHvAkM8=+n=7tsq2qF#W`(NE6*)_q z?*4^X4Mj&Hp|5%A_37)x^k3@hD-U+&*;O;+zZ~w49J=kTd=(d$mLo$ca6-IJOE@B7 zr1a4Bwc1e`eBbYfZ)#kOacu-yx}CD*uM>5(d7_T*D*9CpR*~f2KTNhF4te66!{7NFqMbxlI+S@DWw&lzO}(dQJ8I0!zG_ydm8!_gijK7MoVx78VI!7= z?GFqGrJTl?EzS}y50-W&-z9nYaC~9G-02)j>yP7@Q8^(7*a?V+iONqCLp4k?U61}Q z_uFmOZd|+sOhxaju{W=V;50v;6=ej4RBNuew6%2Q z8E=lpE9yBv1NeuZ?QLBZ!raLs2Yl1@8}nsg8sy6fLFs3WO8`aBaUD-#sp_Y~g_&3w z^U_6@kt9DSBBWo3%^QPAW&9{^bS)JcDCjEWYc=CB;uj-^4u003=)=_z(REh|?yev7 zYrPle5d8E!4I*+l)zZk=xN3i6;O!;ZL>7_iZc9cCZ;Id1{h|odhc&4KadIX(*wh!Y zyCb}pO9lB^*@gjT$^_xbgbF`zoWw5zzWtwk1k`ylzpw&ntK=PtoR_^00|ukM#LCnwW^|!269Zr+x~xNYuS<$rgnII_Uoyk^kw#>mpb<{(!!NA-Bj>*~6F(Pf3{TS7vR zr9|)CnZ<5<_(xz$>c=Jw4NJ&1&Ea`|Z^j8PXF}2jXd8*|*R}{`3aHJ*d&n||71wdZ z%x?OG2O>wZC4=dHBO)*vVg+C;7+3TZly6~^m#zn^xTVdZSC@Spp~p0@W^-^cAtoO5 z)KqFXXHV$dy)37%QB+bPP(i;}<97ztWB)NZd7@Juu|M}A`}_CrGlFeukx*h?6+L46 zf=-_hgDZSsT3c88;pP40K|pZ)SQpMm(F)N?uhy|SWO9h`T)T?v>z_1iVIbHu=dH($ zq_C_sq+1Ju>eg_V4WXRm`S;b&Ocxr6h+ur?_9CEr&my8XYr=?e_ID`qz+@=C5;#ao zZNuN*Vo!k#8~i4tx*ZfD-%P`fOIW%a@3|?UMn$i>op7ELg8BI)ra{swn@lp0*22Ib zI6PcZ-d(q2KmsHFxT=!M2kzz7m-mq7Nrp+yEm%s4uZ(jcluf>V$3pwbD2~|Z6+j<* z<7fZ9$i>1jk23_C1&?wcce6QRp@N6`urN*?hk`$U=ONQZpfmAt*@ zy2!uGXr(`;yR!i7O~ul?!Bv^l-P;Oe=wsJAuHdH4>K7Ik9EKgIi$~m&SVRtIY@zu4 z``{BJjVxG3xe#5g|5!F^PqV$T(N90((19fwaTLn0}s!15exIp zusm`G_((1olOI>r)@mcyJ!xq$CKe~i!M|Gv-CFK5&X@fU6Ajnn_@L6?`c2*#C@3g+ zoW_TweMjD1`1ap?Kt?h24n(`9f3q*&@)oSB_ct~MtW1oI+DYR1|KXDU)vVA63-I$Z z>&^(x%HkBlbUN`j3;Rd9_^BC`Q(SB{Tu~}>3C;rneT=imIs9M!4dT{Vq51y8`I+`4 za9e`Me4=-;cYk7Dp!gaV-g%#+5%~Vi<@{5pPy)=H0RgX#uV0(7zD9PTacZ)CJpMBd zE*VmpfHo&31=Zz8;ai=SoQ!m9`fjj1bbn7ifr5)vQc6boAY6m<@dmn0^N8$U{6tHQ z#~G?ur7qjoU=t$E5>odbjy&^N9MTG6Qu^N5r-w8eC^q5JO-^N1RW&bvx?mEQo1QNH zzQ5R{H9FzzZ7*@L9ILAIt#Zxk*jV4!s(V5%n?neMG?On~Omtcn>C&(Y^~8s4(z|2q zO8ICoAo8IL>Hf&jV9G((iCOznv}l5Y%295BzEJe)>gvTiuUvL!Q<-a@oVAOI40sdW zbj_b({_>UgsjwQWYL%vgeSRTvDk05Ws?Rz3#+T!6JoTqNLqkrz*E-^naM5{M&NDrY zwSJ2wZf|WoL&cZQ!ko?gj+g`+)RGFBCNAQ?Pa$-N;IH1!IP`8}ev?N*Ts%AlPyofo z#-dKn+~B=%ky)Imvtqw!6~lT)q24@n{tR+I6sRyDSSYnB$n#rifqO8~q>HzMgenaw`CZ4tK z!Xw<@Cp)ZkDjcgu9%xvfDG)y6&81t>Tjg2~>wo%`PbhU>%6)6(knP|muSzafuJyx> zIhFcA=@WITS!{cYL5S+7i=_AC+4L&P28n$*a;QW)Gq(-8-}i~uUoXm*LXs| z47*JceGtB5mpU)Ws^j8{kKIuzf9hMTpGHNmTamW4Jg8ly##JB4BFF01)rzrF>xt{S zgVNV^+8lBSq!tvlO6c6eWN6GQe|p(%Zw$96Q^xvX9=C|gvQSS)UM*d0N{WH=i4#3d zc$f^(EsgyH3zw)WXA~54)z&6DEDw8Ty9u5%h&N_@!lkHKCSc#oU2hK5LYR?!jM83j zIsfjS;O-B-9Wwg&$;nOcuBYC8duh3HbNHi9`D>b+62WzfNfNWI*H5Nl{!5|O}#X`rt^`d&7wzj9(~Y6CTU|5|KRR5`2}9$sYHX}rBU`R?62RO}5e9Qa_R z^_`X2C0e20wP~_>oOBH9$?wSGiNR8jqsz!P6?cDD$E7atS~Q{Suj^2W;Iq*5I!ANu z+O-+%G^>=!6h|Y+`pJ5fm@Igdw!1pV*2JpK)0wvOr@bM1W>>dVt(?C3B;H`I4qIGg zdxi+f5@R#f^bYgHX&%eLXFI6bm6a6~PouE&hIw~}$|A(;;mX}uA?F!WouD`ITX%49 zlTN_VPPeMzX{xhg)jdCPNX3Mi7^CCK>66BK(in%;g;R_Kjg&?@@CqOVvIGL~UQKyDtsLlP@AMlkd*5aL^888f zm6e5|a&z6`YQ|cOAR`SEllli9r+rgdceZl_>GElA=2aiIe5qIIm03tkN`lg1AW_^8 zo!Y(xTtL~0UwgLzHHj4@u+mb;2M_3lIE~ZO7sl#+DV}(F=C-#>W7V<9ld=<1Nhs>M zZMQzKKOt7Cy+SJf&c9l}yK4d6jc;RHr-T0eKQ5qRYi(@`#jCP1sSu|9SXcgi4}&v> z{*N2Pxbdxc7uXi(-c0>UTo8X?NpJhM?@iV7;RN(v9-s0Kq`j=`+mX+*+j7(V@L-|T z_RyalpKxuh56VH7JGUH_h)yi_*0}w8K1Nf1?wqefmbZ?v@l-JLJ%4|H;e)O5B+0;z z&d_q3Nnh9vz<9UAeFqKu&)kdmRo`!gFZQdfe2=l8Cnc!DBTyrz&*PY1)LFyGt%w$K z)6RYP{A?FS18+NQhn2`=V(~mrUonB1r z&yv?e@-EM%o20rqq3$RBlAwsw!(%^d2F29)+W?d>Z;CPFEw@amCwTawXS_Ymup2k* zhBUB;HaGRo{~&W<4Wvvcx%=*=0F%ir=c2KL%(3SVOx!o@X5xYt%%9FG)!!%tqyOxc z-YlM!miB0KX-KEc&T*}oe{pefZEbCqGeb#Ry8?2>6`isI)6Oq7H5XY}yoN=Yu&_vx zOq^P5!(pGZIPr0m_L6KjFR!^CRvKhDEF;~ttF%|f6UDn!afpa~)34}|emJN15oI{y z8m?2Kkh}M5P_W3+w&%NakWR*(W;C;bk@ezFg@t;`b(0ouJlnah%T8E4m-Cs{7H?Wr z6Rk@u_^BT}6R{L=({NMJeRKQe?V&T?r%o-z3N7S5{GLyVMAnneK=3WVjz>Qyp**g$%hsFNkFQzeV>xsyN`UkMN_8}dQSy6e6}FbvP<8f}qmk=aUdQ0`zzX8(~{}RD`(!@3E4g6D|g5q3mBeQ7w+rxb;y5`nbo&BqUJ#JArcM5 zF*Hy8sUK0K8FAellB9E0-kQs1!6>9@5Ud@1V1D0X)+Zdx=ENMcNM^40S#kH7Y01D3 z%S}{8@^tkU8P|UFI^_33E^Qi5?&ri?QK58eVvVU)B87_CQQdK1vy7&Yx zmkzm?3o$q>ENpai6jiX%@Lg%pZZIR1p?09~-u7-euf>M>#(3bNMzlJ!?B)@g!}^z* z-dGweUF$c??(6LZ@^9C82#0{6+G%}mdu{sj=g;+p6LVyoavDu9ud1zm>>%ONX{coQ zh+#b{3jHPVFcjN_&C@mG`bL!-4#v#H_G|HFn+tu{ot<}qEs2PTc;@IB8WPf`^(!Pa zl;+m6wz|4x*WC>wA|jL>b4#qyKs6G{$e2WR-I&SNOt?_SG~HnT0k{_G$+k_s^k=7) zg?D3jBc-ieRHZwQ4mXniJ4XAaQUr(2(u~_To6JxS9om?P&XnxZC;9!H_^yvay=Zt% zt44U!(Fm!k`Nn#*(Kt2b#kVPq1kpI=BUuP4Xu&|Mo=w+WXVNQCO!;@WGQ)K1*C^iS zf@kTDG>`l8nAeohxPN&>J}zu2GD0Azv|%uGB!xwnSk3*}9O*zNRk;rl$5`(_|DBR(*Ms zF;Mh?S27d(Xg98QeNfZD#VslD?G)RveKul)brIPS+9*|R5x2a15xlLWh@7(^qrB4>ZbOG(5jI>0R?&k zNG=AyfIeZ*Rb`J@*@gA*{&eCESXLCDMc5Uc^GbABCr<3|@5{={-n5?!2@1L$7yUXi zM8K!CL26P7Xda?d-jacN*_B^z+~^q3X1%7gVh|R_Np`rlVc}Gy`|{;Wm;Lo0oSFrc z{Fd4>GI&BdiZ(W@fD-WW@e#WV`L=_&86UU=1s%cUnxpuayFY}7-Ad!R_&kPBHh1pH zCyb2_W~ZVn4U@k7+jg_H!=-oR)8k8zVo5WRk^3VH79ZJ`d`hA2Z*?3TmnP8_y{i3F z)p4c$1l}w5=gfc&p`<_mE@E4|q9*Hxc~AN@@Zvyf1s|&J-&2^rqiFC~rvIR)|K z)8>Rc4Q0Q`=U4bcgM%~JG=&WIr%1kNH&sf>S1|daqdkbCT&HQCZdy8J6m4y>>b65C z`zG?Bn#(-h*~iBR^2X!d9DN|^xSnM1rHS3X{rtm+c`d8T?n1L4K;@C*>OInN<+mKn zDJU?cG@ketG&gcaXMS~!?5?%fxlAAI`B6ng;LV9|hQ7s1c+}s7oy6qR-}@ZxS(e1i zof53ON(*^Ro@tjzxP_!NZr5{W&+|Uof(}o|mN}4ge1fge(~7GK8hGAduAsa}fK>OY zPkv+Mlz|8d0UpoP<*A)POT7NLCrf6cGF@0m2S$*ljZ_cWDg{$8M$ll3Ow~0Cu8g$= z*4)3OLn;hb`UhILmgF&lw#Ma87nSbcpT*X(o9d&wex$owb=B3HJDwt@k$1pQJctQ~eS;LV9O?+UqnD z3X=ZqjQ%Pc(yYu+*`b`e@wM2r&Lc-PH)bE5dIIywuP5D4V{&N`eP&(*7axevYOHjBH$w2DRD zc4m1#=X`#ZtEh-FuRMEBb+58HE_(|%T3AQXc8YcQed24)Wi<3kJK;o1pV8X{&I7ub zLxvy-AdE&-b7#EIXGNa!rVusIz7?p09j=JWsd(cr6-UO@++2T&^>~_Zx`?BrqoQIv zE=iV!xe!1|T>F|*|3{|AIOOEI$E(dWK|w)?y(^%jSC=`4K^ZBjh#U492??VVdM=~cK1OkeZ-axcne}9baYnfvY|~M2&3(Jq zVV{I13{U~Ir@TSDf^g;aEiV+Duw?yL;j^9#jVXe!j)Yc7s|_cp(X zdN}r_f_D7|NeefTe{R=S>q|tZZzlsTgX~h|Gb5+=n_VI2ctux$FmVPFsmMZ0OKTuH zn%e20JNdYLvY+pPTfGS#YzUU7rs-Z@UOql|!L(wc(bUEaC(mquq1lMbnk+<`FaA`v zhX<}sJKdy^Lx#!QNiJ2d%u1-iu2n|({mc|j{w7JoP7VtWW@}H>t)vLVP zReelr(yrjXS0z11&DXLVsod2n!Zh9F=>gJ&?PcXrEHPq^jJS)zKQff(%aeY0u1i!i zWu85ImLw5SWH}@)|LFO0^CTf00W0|SFEfpjDBw>`M3 z_g24$vZL(mqi;Gay_FX>h0+y(^w{|L?5wZB!-rq}sX8khZEV)(XY9!uC+8$jd;4yYup^^y1Q6hQ&WSoQ;EIh2nPeFvIbA26L|7dMM;V?^)njM z#ecTDF5U5lPoHl1lCeWebR~RS?UE;>ja=0{JUr329Bo4HUG^Cp8yhNjc$-}WSXdL8 znOxMqh|Vr;An*?T!EwQ4-vyZqSd0Tfs`lH7SVN+s27omKNFEg1b_uu$nj3ZyIL-@Q zv{5Q8n9X`W-}$4HP!HNVwxa;gR_`@@Md=gfyIw&Q>t zo8)W-ssn(vl1no5TsrC3@S9p&^{U-mf!dLgkpbgW)YO!= zx_BCx!1GrPPJZV8>_tF;kI(E;T3QMj#dM&E)6uJN&bin=uxcGjCU;AbKW7M%Wg>af z{~}upI)J>Rd?g5-exZw^5DhDr*AH4hABNFK86TOc5Cf${`= zr+TB`jE|4cV0+|5;XML$Q6O@L{!bnMs^`m>Jm$S^pFexVwi&=luQ@MQrtSz@CjLC= zsvOOFMRbY?B^J{*ARz@A6|f!9uzC#&*@t+=o`-T^ViuhhOUIc+7g5hKFNg2}4=x<%di5 zzxXFpp~Q6B*Ce)3o$|=tMSiD(#EFRsjeO%m=%oV;6ty~AJ z1KlPu%pbng;QuF1c(Bp!zxNE|(C7f;fBEvHljyCfTd`|SUGtz$I9?zn_k&Me>Gx;b z4;{hyrkbP5?Pgbdw5%)!OLB8^-VBSXap+Z5fIV$*Z=+rc|FJ|%T^3jwTB7It7NqT4 z`RGFI)DY1Ub6G|>SK^L?Rz6yUr4)7*^kAz=0dFPk49+2Npdyvgeb8#LFgc#xLhAb$ z1Q)Zk{OIG;0Inx0?|mCW*#IzcKnJvuFj#B3l{aKv`Y5kG>vJP{I^fs#bew!7j}NU; zUvO}6XR3VEyLW}ahyoXR`SN8Hd6`jPo>3ei#kJ|yS!~zD>7$mRQsR*y__*;8Ws_%p zGBs!tTYK&;z4!UOU@d!;OIrO*`b0HI5M8be|D5(2%=EoX`q!WYG1_0+6YHTZIfEV4 zTWA*k{CUm#{Eu1etCTxWW+boDk%j%3F5?rjdI`NvHMJk$qW+Xu88|rnV@dKmIyx#U zZjH`264583k&BpgCMJVMt??uCIp@nw?fZmOEQsJ;!_u+r1lyHcUjhJ>U*zuycD9G^ zc!N;Uf9UPU$R`EM=pv2Ap;;c5()jT0+Jd%2x-iFOn{m*2!*9M14@6L@ z?Tdq^rKf1akIq5B(uzg#qx_9VM2}h z3G(KQ;)tthiy7fu#BN0syv5|XP8Jkv#i3Q8b>dNx&y4318$dtKW*1b8i z7c^jx7A1E1-%4(^$s}_~%_@wk15wnKpNy9&v41F2hoQAYpj1a6iA4osPrvz;=iqC@ z>u!S@eH4l}n6)EQQFpopwYs6)3EB(3i)zqQJ}P$<`=Q*~9?FOiwf>!Op?d&a?*Q0Y zOiYZdy!ZF+4{B7e1fTrG5K5@G=^KnCa6b1IUH(KL?JDtOnf3S=00M41DAUK(m<&f9 z;$#%_Uyb+RYcNqVL9TOfMO&=G*bC__M8LGavO=gTq8ppg zv$PwCg3j=dYS!u>*~(Xne#;V_JqKkohseCUyfO}$yNp&^Ww&&;K%&q0dm%~FKYRgD z>A9@bL(XeNYZQn8DCzr=bDCRN%wlJSgoJdh1iWs9zI}_ekk!eP-Y2odj=H&0v-jMk z$njL4W`Deanb<+*4T4YwczVbe-M^9hUMgnK5{}s19hF1kxx6i0>~#Ae_~l-BnlfKK zB7{RnH{6f4Fzcv5b#lv^nVhWWZVF{ro560^EVW4i#Efns7X*fec3)T=k&=~3VVU!Q zZaJ11)?ar8*b6UEmRWuV_=FNrsoV|c_^P>mYG{=9(BzT%_wjBznYVQH*>}DnMsHjjUc<7|wiN7JRPDQeQh`J^7_|Kj8xtf+ zB(__Emypk=0W%%=-B*^ewu&NhbEsrHl57g=u^Ss1+0S-NLT4eBrHfShX4>6jDG>$$+Cm2^wPlO`w|E8x75B` z?Glz-%pOc%#)cosRC;R6>fa4YQh8dM1CT(VR%j<- zC`KN-z0$|R!kWRhSVaQ+42eFpaS|ma)IKdC;{NTnyZ3Px8^R+rs|*o7L8P(_vWE7x zNw2enw@FbOnkxXq03_&DI`Il!bOV!uaC)$})_SB=So}FY{`pwX=ChMj93TPC7*ba0&+p2Q(eP z1|vF1)}^g3JQs170`zdCry<3v%kV==a*wfv6dg?xp;hhK+NHJJ{>8=c;X9XPB7UJ2 z4#vjtVT++Md#D@&e0&mE=0e^0u+CsIJjWn9PAmW5I7xzRGCw~*#6GGsyJ|<;Z24Cf z88$XHy0ctlP9>z6O-w?f=e$^W3YWZ%WL=iv!gGTE>-RV;_IE@1_2vzsljyX7fB=ux z@E%}1l-T||KgNP0~zSj*j1??(Y? zSWQ{k(9&|a8hJQ2X5b`;JEO&@Ku8Zg>vnXp$^cVnJ>NH#D2KcJGj@-Z12f%)2Fl9H z5G;DKv?S$c3Lr{-X==(GrrUb9(0lcje%0>MO()TtGb)T{K~eVCl}iH$yqv-fQvCM) zH~$vt?QweEFVrohrO!CzHB*2bc7o9m#_gWpe-1-z6qfM?Fi`=1+kl(?p^#D9_9*JN z$C=f`$$>H^5g;v4Jg8_nT4oee&+fg^!S93!~;$igzLcQMhG{)Y*9%>%1RSAUdE? z5^@tp{wBw{1|`%XuEEHeCd}=*QD3*njl7x2qj^Nl@0Y5ge*JntX$*y3*E0|)YiLmM zvg+2?*Ncmbcf}VL+QTo@vUL}sUQ<@%1HR0DUKOe*&|V`Cwx@xN@b&SbLb&anp>ufy zRbh;NWoMj(0?r?H_CH||x#i~(^<+$g!m9T>MxZ^hT{(?hp+}G_D|S(!nIvET5B1_f zX_07Oi6o+;qN4vfH}{yG+X*#uk?bm7zVoK#j(6E3Kwx;E6}a@=4)(T@Aa{k7wR%R} zVy-LwUKmHhX#zUoCT@RVe6n>bg)>Q@a$EuKxSm@EcqpyH$3{>O7&o5}GkR!X5XomT z_w%O+di`r{C;wQ!0X`wb*nWq3t4HQ+71qzf0`hr;wZg6h0#|N3R8K&N#t#ElMzgE9 z7q5D}3Sb!@6sjFLxaK*Scp)nKYgRjBig)XQ!=|Nzas{M-KKEp2!{{3%Hco>q!DHma zHaCMq-ng6;v<)W9IEb7mfSv=WDF-POQ(xXY2gIs^o~kL;yNFZwNJ`RzCVWc#N{2zU z>mJEKlmL8D1EwUvJ;QHrAi`ZQtm)|qJGiBT`Zf9)j0<|OfqONHiHSgUR_rd73knME zSqGKbOyYdzhMYY`Ff~05>iuyjjHKk{Tbr6(G+Dq@0pX(Cw?L#Ipy;}I@%ha-aX)f^ zyO)H8W0Aq@a;yHK*eVahySn>eKV;=QL?$2L*_Ie+>GgHv7A~Yjbuql=l@53O+!5jjxO{fJ&CQzqP zk))L;z*(>g+3KTpt;jXE2QL>yrSK5X#k(Iu$*mw5An`I|_O3ff#enZQ&u1>hDe8in z2?9bBK;*UuIuh{wVxDuoeD2)2=15+@fPhJY9()9%8d~ph2xKfGA~bXzsu0;|fgptX zGU^u3?SF!Ih}^@U;rDJW-%0fsi{#buAe(uwAkm4J;*TNt*VW;kU7R zKlZ`0y$+xwXLqAdU{StmFDiTxc^{@MAc&$rQcw_rr~)p6oKv&wUY)8RFrJ+dRe=Rt zJ3~TDjE9dOensayUFN+Jft&+`J5i59N=z09xT>+1ig?&OSIsfS9r4> zDY!9*>0Wg&?x)I4PP?0$nxec^;;MAmb*o(7=||l0I=6Dh*47r5al>*@;2^%_7N}}~ zbBX2F$Kn;%uYFlO?8FWn(fRD_O6diFcR^;pR|6F}YW|1Sw>K9d5bdovC0hlE{O5fz za^_Wl5h)9#IE{QKKLKh>pe8@6TIx?dtsuVgA!^dA)+*y*8iy|S*-R7fs8y8nE5@UF zjJ6Zd*M(L+<0d_bTVl>(u}d=40<-g``vnt2rbpp(nDY`aZi)c*XKHeCu z7B)3MU;b=m4D@?I7x=fF3WXO%Y`(d82f%Z&#ek|7F1DErAc%(#A8H*-UJo8vTd%-B z*jb;4bX!M9;R$lxqDSquKs6xLb#;ZG{rZV+_?PLGFBusc+Rb&{jga5pna>7h@O4;4 zmBfD_j52c2i{f4{zGMk{)xoF`bjb*s)$%vR+_qd|OpnxCA~&{i$w*^; zgOnchT5SZ0y2oJF7vO0Ou$#Z`KdTtTYhd`s+(K~$5 z!1Hyg2dGi!U$FrZ_@bSNx*{aYhB;9ytL1Osq;^>Q(IC&(#--ykHe&Z8X8LF z=cij+Je}=eex;x0{5(G|4^5cD96=~pj4uGX?TNR5R^C@sL?bK#3Pay&u4UdSAuiz4 zA6@{Ea))blsFQ*7;6jR`J+zcOdef-R2N%=s?(Fm|H-FaSmq01gFQ;NS9q3w#W82Q&b-J=Q-~RP0U1A^EOe zP3U+Bp#LhKZE2NNVb6dB{U0s`{L|5UMsyhMo}O~@KNwHLKYt^W_2j8jRFsqp1I2*| zbp?fAHD~DjsRe@(X)&?Ft{JFFCK$Mx??~|@ANFJ=Dhcq>Vlw^Tg^s z>8){lnYas>m<)ivk8AJ0C^@s2EpJ2u+mY0Tx9@n7`9Z+lhnUv#{reaJEy4{1F@W_} z&J?!2IEAYV_gM zdy8Gbqbq_~MD2rd&tIKmC%3k?2H2ICn>$Jn79NfSk;8F8v}c`V1Cb3FAV6u)5$e!q z%GRp}ek-_)OUv2N$cXB~g+nMYP<3(0JU~IhuF`=&$o^e6|0RO{;XM`1NJ!MYPxWXf zhanF*dN?5jNPG~Kw6w#}mjsUdAbx|DoqZPs8Bq1WO1{#K9P?Aqn&0y1H{SfHgZDW) zLGIesAd7C_tcZyo=6^p7paat~t+gG(5R?S~sN|a3pQ};MKOK#e0r33qT{8f8jBa_M z>AC>Q*(f%SJAd6dF4OKz(hXFBz<^`x4M-yw9U4ZdAv<{GuRaP1P=62iR<+w_i#9_lR zv^U#~V1UBfOw6`{$lH7B0FTE`-FjtX!#05=xrR=rr`2x{3y6UqWI9% z6tu7{bb5J)ccDc`LPE0bp~=P*0#fCn{M6b9a_4prb{EnV&Fhy{`2Txh{c^;h`M>Iv z5#*zxF7utJ`oYoK0#1kp9K3}<^mx;K>_1o3z6~QC!ob%Y29C58-da+YisBH#y6rc{a!x`cDx?!|F|w*5r4TR z(~+!dV2!~2VXg@TKunuoPK(#WKr`dLaOdrSwSlR|!vwac%KHgdV!wXVg*xhZHpliWQ~BEzM?*m&+2}zZ^7$aTy9KE`;UaF`gA^CVId_tTVE{H{KxY;~ zRSk5@-SK=hM^a743u%SnR{Q}Fz`Tj26KBQ5Y>}rSRLs15_3Au?ir!ogM8t75hEH=N zL~~v(5C~LI{&7G2g7A6$q+C>1kjPGjNx)9sEMw`UgzOMzZpdI%F&dKsJYEB4BAB6&!GXcl*VZa ziJQ5PjJx(taS&*IPm2X8y z%fE>VNdGn~VLCH*s?>zH)g!EN6nwcf(86tPDx3%fl&pBrG(oS}FUx zj&fX92cbeezY0QRLX{|Zneu3iDf~%PKj)o?or}XJFz5d`$5PS6cWL%~ySB|qhQw0D z349vWWNI23P=+04!3R*EK(CsK7#o?R%NlSETB?>09y}TUf`1VI=$SKn&xO;cRVm>G zNCE!6+wkU!#}WS~8d0nwq+j&WZ!zh6hhFK-nSG9z8nHRb$&vb(*j<0<=ga1A)r%g9kWK-MxchI509|{q z*9jYWCYYdFg_jmAQF*iFT_?MlaiH*6ay3VEl(VTDzaQ8P{}7`mo4A{l4@wOe`Ia0# z*;>K|!d-ZY*MfkZ-M;s;iefwD_psFnP~Kxe9~|Cs8Fto()d+q~UuCYF~EAuk6n zQoWi5WjLg%G>*)ioVMQH2>l4Cihq5*3^s2>`5s;`F}P&-6;kID+?bb)qJv*Ai!Xj? z**4QuP$2xw4REk2ZD4@qgP0o&>X8N7?B=&t#v!{MRgOVH?NzSMqaW_g`DvDE@4Vfg%vGb(KVDSGSy}%(>~HN*U7FM=PXWv)N4z0mBuS@N;eL@UwAzw%3yG zQZtT6Tw%!4N$G_aDVrXYC9KrpFIx$xEV)hXElMk!@Bxo*%X9j?wVm+@l zjNXD4y&d?;Ef4!I-Q9&y?>Q_DjuHTSQ4A{EmX?;i+lo7D@*sY#XC&H|i#4QrMV3j_ zNqE%XsyjnKtKfi|Kb-c zK*5>#m6NkC5Mew&vCa!Ka4=^Ggu6w1qGv!r^II1A8NsWKt*wE+@ZKd)Xf?;VZoGS< zo&EdfVOS_+rt#=4c*^_rQD~Xi(T4sHU*8?iW#7L4X=*4^8WciyR7jGMh>%ezBT}Kv zkUc9(8bW9xNn~YYWZoGeWS1>_Bzw=_anZV;=llHpalf8d51-FF@FqmUslOn>LGd!$=gS$QT}eGG(VN95FCT?L0(en##?lq~1~m2aMw z`1xdh=gJZR?cwpH2VBlzenssgBPS<^n*250xRf6D!wwpnhz-kL4$iWlIB^0Dc4h%h zpZXxAu|*~3$&wZ+1F|M6bo(zzoH$VkX+g?u@l(nBMw}bcta&Dmw&iTPeAh!^B`$Ndhp7y1;c7wy0J zQ7-UE?Wa#3LF6Eb7^3cM4*?CK6zyM=1eC6jsHsi5NY6(%V|hgJfB-lZa5vQDaFnX@ zTh5ak96xrudKuN7S9teu%5+l5gc7~_7>(oyqTzz*jVw%+Iu{ogqYRyDGchr_Ps86D ze`S~1Y)WhJ?QPu3+lz}X5^g}3Z(&is#+(D`L&j6}8l(V3#R{a5pq-*3@4ga1fVE%& z_4Fp6_6a1o@h;MT>I=N43m@FtJMw%pcwK|Ky)sg+c?Jbko4JI~PmOrhc+vl3#>qBS z#NpeNU7W%8ng~Uur)U_wQy$jeo6gwO{>8MV@apYTBSxGdpM#E;piDXZ;x~nqlZU6v zlSeZpRwYt(|Ni~6M>o_W!VLPBp=5wBMG(K?R%gX+kNgwRO@i=GgI?fauPqb$jN5R# zbztJG_f>e##mPA`I_iL&4~mw)A3spYckj*ZLmwJpoqzxS!s6mrU88sY>&~7QZn9k9 z+V3=L!*M5sN|?&t>)~DccL>%ucy_?JSB1MBS3rpl0d9Mm_-Bo9yJ2 zhtEQ$6b>p+v(FyoFHJhozU}887I-dbaZBehmiC$G%)ht=dL2&V+cJbb z4}7)K9zEJJ|Kh=#^%pm6P@@l8heO)v!pl}k&ZqY*QCk2DE-oqAacjSTK$h(Yi}1N} z1SBxi>%gx=e{i8J_?YE_daycB;gIqWDPHo61_mhoRP5AC|Lp2TL(yyZl?4P52+hsS z87F>FWviIZhTpxU119IU=FeQ@pIwF4Nx7zwl-NV92O>nAMNDkJ;lNaBD0;(Jx7q1v zXq&Gwi`)udCy#wT(ZfcZ$DF8_&Q;4}wzgBa4D8z{=q8j_`+%woh&Jv0`|{1H!RgO8 ztkp?KSeQ~`xfmv=gY&eZu6UnOn0(*6D;`HTh%up?GSHNf2KET}R?kHo?Zm~GXGlt( zdNYbQ-w0=qb+h9(f(>{#7pW~a=NQl{XGAhu0h6jg`L|L(eK*qnrwl@!YlGtjqBQ*a z3TBQ*=79m{1Ltniz!z4?7ygZz`J<;#Wwa<59jNFx+fhia{`k^y-3o|`J0-(5!k=K&wha2JZA^*7DFmW$J(AsYEh@bWpnYJbuPyl z(3b@6Gx|}sccp=olT(nxFj0vjTF*@mU9?lb>+9!7hcXA%HN?}^@w!Ff$ z&i!dU1*V6)E{Ib}c5l5Vl~Tm%=b;c~w$z%?t2xB~y(%G}B)eplS@j%baFA{k=FRMuAt_vS3|7P0Y1UHjSh>cSrt^55vmS*h{j9g?>W zT?@YueIZ($X%Lz1XJ{x9lt9j5w_Km42z(Qfn?T!;$r{(h27fA6qFqTww$LTIptHRb zXw!oS4_=3j(Jra+N4ftvUK(7wuyw1Cc`nc6XBCPr;jNnuH38f@u}BBJ_fSKn00?(7 za-(M;MdEg0mB~$uTz~#ky5c<3(rw`D!d4*>BYW7r(!l`YCMlx~vx! zL!S71zQ)dWvCvHdsE3X zj~9c<&D~~xD&z;q?Z0moo;N64BTi87L>z1g(l`8HK%_0Jqz(-YErGQPtV)PJ7|eTm zu0#)E2XJx%`%`xuE@Z9xe&?sztCz^?Kjxerew|(mVEjx;`mOVx`M<3*m}F;Byw)0) z4OX5BDbNDxiPmaoaO;s4*5M-Pi1sR(>)i4z0ZwmHIC1mfp4N6zasyl4^ zp*JViDpy!v@ybTYm)yo1DI+cCcZR+dSEc!Z9g%`O{nLRmg8*aQh*{q7{W#b2L5_Tn zq!B!fQHfpZvFDfN?Bh^B5oXjJBfWN_KQv#>uQ5w|e@DN(XBG{gxb6db(WWp3df+pV zUY!}wYCVK*C%k3Q`-H-TP{K985umuj_s_O3rkfVIHso@W&kOzS-vW^c&kbJojk zpY?itDvx(V^^y8d;XiZL2kd+I?%H==47hTpePR4Y1imQ5Kcw8?_QLg{^147%gzlJu zq)hm=>nI*Q*!eF^7#w8^f9UVu)!tr(Qv>gUt&I&>zBig)GSbrrQHajQ;#FI}ja%;I z$fVW&jbI8-y^6akF1PHekLbv#)$LM<>x6P zhh#F#X|4(6%x0$(f~pB9nMQhy;wpcDPz;J94^EjM{ntziF%Q* zy@4iJ=D-u9*4#TAX!yFpJ0s`^Js!g&BLd)kBFn>i+1c2jy;7l3WLZ@`qDNPVi4LL7_({2hsoJ_0jxv6 zyK%?~4{7PtE~T7$K?4Mmr1#ufF+ zRd>#iQzAJOnQ}%}O3{0)`iMqo0r$^kxEC2|n4nkE``xb?NLF^XxSevcm&W6XfiS!r zW8%W>mrj8?{B^e~VJ%0J$>n}y|8Ug}`6;-f+1tEi_-i0V1?3M#P7f)<@+n_mci_~7yAD*U9M z>r&q&53wndL1ge`xI6&rptU6x!dmW`EBgl(t+z*W=3-8qaDRPRtZ$J&`ayU_Tt2A?4sep6 z4sd8}XN#gavZ6e1<@oTWxkS@#BTvU9(do;Kxbg zJP$kh%>qsa7IGBjznBNK+Suf_Yh$l``l~Gl-5}%wwEvMQ;+lc?>uVU64*jehY=M69IrH` z+v@4*k>|{U8aukNI&2Bj(sxDOY*cdZJsae7P`rmC zBrMDgIBU->)E_rpGO>ZRON97uUBhC};D);LsZ-`Ch2azM(3xkLJRfCIqz#Wn;^qEQ zF;qVra1tUcM8A3SMw2_N>&3=~ln+ibd+SpZTLX1(Db3yv)s1dWmwT~ED-Yyz0O`DF z9cIl>-%UR#<5p8sgGL?b5U+_s34+d^9-6{}g0qH)?o6T|CzN#l_*0n|c)S<(^GH=)1AM`-?Uiiq7CWny{NPQ0- zKHS;aS)ri}L`xJ+SmZFUJ$#Sk#qH%wMjjp>*n$yy3-v?}A)#kY%OifCSih)Z|H67V z7L=6CeY;6Pxbi8uaEmilc|f&Y93+~BM~m+K8}m6!HMLsUun~PNe0$Wnv~ir7qgz$b z1)oH30sM+duvmp{23-Pg(Ja~b|1xa<_bsmY@>aVU)kWG<&9T*WEAA`aCFIa>odPTU z0yy`JQe{b?N}y>Oz{3GN9Y}$?dt{E-jb26!#t}ISOCb>D#1(QlmyGED&u`+iLdZXU z{5U=beqmDBT#Y!iW}6wnksSV- zN$SD1?_WxY(&ZxyFRxGFt-Al;2Uo!yjP{^WcT3Ar1($wtrpxl;;@Ma*_fA!LOD!yu_sNKISlzH`)m1rE{ zw`+K6NzMA%@=T(he(fQ$;{_np<880E{?2pc5HU{TUyqMd3wQun9#ee@r82UzJ%VND zF0VY92IK%&5(Kn#7AHfs-Mh;dF0^7@Y55JR!W4p#omNyT)-Oe&SJwX}sXmjfn{BKW z2kzP|+zo@^JhYYTF ze2*Uy8N12Xj&7gJS0d0(uTO9l{B0U#dD-=_Pf$=6v^h|CBtT0D5)21BdvLN%57dB= zB^p+~E`fN5(EeU2+y3)WUi?dw9M9+3ptf@hbr!5CA<6G(69vr!!b&4^I<;IWKT6EG zSfb-^ZQ3SxfBg!H-py}L6N+27*~u60;4?}ebgd>BOC07W=A*6_5>$JWql_~5Bq!d{ zty#0?F|WQnx;ow6cXbY1^&J9+093(_KKx9IYCFLRK>0u~;vlWy0{ZHh^kvQ?2 zG)#_^iiT~SB_J=Ns{RsH3&I%_Bje<0MY2Cny@F9-TN*s-cEF=<7UF1_1$uq+bag>0 zgg&8#;RM=M(pw-pZ~3_7aQ4sh2wz>wu{cITu+wgWK|?&yW}iXSe9lJc6G&q4iyI1P?BD=xd*ZGzIP z!(aOV`A80hDEfT_j}%N6AOcDVIfS*2=?2T+gHfpSvI_mzSD_CAgWHD8`mBjQO$~%%`TNCa|DXQfnSY2|VAYa|8Um4A#p#G&#+o zZCv;)G=LsF?90f?){KR|dX-yP_y)BYc@CJi=|^v_1{!2L-nS!TR~7ZrR@g13{0QXr zeY!$+BG;xX#%6C*c%Mp*V~N143{zW9jpXoaes=1NCOTiPzqD6}5NZ~5$V#|Z9Ojt~ zLPRS?sAFb!ZQA^fI)?fVj_w2G3DyHzFm+o&6YNxYDIU<^16qN8V4$NrtM>luTa%*2 zKolKvd$_$fB=R}`f&Fbkv1t1a?%`;E;>kf5;a(Ae?{sBkVnPxoY}s3dOr=t1cPY+s z&2#4l8q=f(DAXywdTgl&{P37e`I&x96YW`&1>&{LNAvkUR`<4w<0))TBHlZ1PqvJNwyZ=smXFV3t z*wD~WM@Ol4Mqv_sp#v9k*MKeP;zEkzt2&XQsu_2INb=}~VPNpLRUYiYRC^X3*q0Yk zqwpm6EZtDqoyVfA`(adBiA#>U31a*q`|<_ex;pMyx4`{m1*(o&wid+&>|b?+3; zQgs;ob`)iT>RYXo3NC@rko_6ebD>(&#DK-^>V{Bb(3y)q=I0X>E1m5STHD1;;|oB` zPtV9O){c*j-3~icJft2)#ZXYrmlY+1^FHHx08#8!ZcC*|bKEi7P4#`~8$ z;1VW0>m)BL`;1qAv2<#j*deW zm&!&A^NRd=c*!lg%Xa^Vm*P?fqM{JQS9}Zl=;3$CbiwR4#D8w2cBQ! z3#WU6paebcXyn^W4o=RHE?6c0@wi`_WkkJoYiepL^o?E*CJa{GS%as4z_M2vYhg}d zE+$5z(_B;i5|k?;tG>(F?w2pan8@ygDeW?s8-J%2QNmGXF7ED>y)I5#oJgXr`WtL3 zUY)=`;RM@^wENe4NQ_&0<%2#2+OJJ=wn2e(C_)G4|b* z_9HAB$`YoExBHti>XE-7`KsLfBEJ`&&+q7d18UcP+0iz`ScOky2GgEWHk<*J7JA}I z>@Om_v+sW^`L-3Se7_s6_AmF9Y@QgqFLm+w#c_Nv;y5Fy`P8&4rW+;SJ&c&zT8C0{aL;P>jC!y zt$VKH3W$E|@179E%%p}}S#kT=Ppdy&L+SQgxfeMm8KD7)N7=!wCCcm0lhQoeS(V$f zrzNkv>kjPvU_pLV_A)#*8_#)dcbeMseW3JXUL5Sr=;(}!{ET2yq8w4fzyJA(e zMsbYU)IQE}%0{PfnI~t(`vEh6hab6QIr~c}2B>Lox<4;Z-`&B7isk z3yp61!(503R8==8{0^V6GkV7UY}VLDnN4AT`{ z4yN^-_=KaC;JDOR;QK9$Vm+wcRr(`S3wC{CeiWrTJn6CQrN^H8*=opSs{CPR9L#t_ zqMBfUzHsETkM3>>KI@bMzo5_Yeb&u!B~LLV>6w52>Q&V*`n9v@uKiGdXa_XG3gHvo zGd_sxi36|DrK!>grov=P8@xW?+SYw~23d!v4R%T6Ib<0|+24_@OgEGQcvM&3{ruU3-n8)ot9;ba zA81px!r43WBG5LJk;cuLbLgMi=&yaz0*85uzmJ1O$H zzr?Os%~p{!)K>eF(e7diCmWj$ik%^Dy%(3$VP^h2ul+UfFN`~ex~-Kk_Q`ZaonLF+ zq?0wTKD4eAXm>(t{8IkJ;dp?lJ2I89g#Nwk)9j(8o7-hdlA~TI656`ne)atV{wL-2 zDl2Ndsq7+5&`R34ecw0uxV6!VJ=-2{P|RfnF+hbwPk1in&a}9 zb*7zt^dyMWw6wH9s!??Nk0xy*vHg0Te$O4muWhHNZw9}I@L~U-zXo9;4F@5m%(vcarD1pE6vNdg#f17-;B0(m>s6)q0RfqZ6_kakHz94ZCoo-k|a#*?o zDnpkVOlE{W*k@bK`g|p}pQ6h^ZBF#l+;twW@8ZEl>!b7fYgi(cwM%!mlQe8GdsG&K z2w|O^p6*caZFkVbT)Kpoc?O{= zt2^B)B7d3Y>ejL=gr(a~l)xVV>r4A*coO4AO8X5o-1kc}skjY6=DfPqt-|NepXGYz z9`rKa%E|+qZqq;R$afBj<*t+10$rE;@)+v1UDvu`dfvd94(n~FKRGsT&s`t>lZ#8I z$w~D-^nGJU+QMKr*<#W0Yn0$G1P8M#KO{1C*?cx*xgj_)yA$aW=0W}(hA5r8>}8kN z$iJ2r6Dg-M9Vd;0>>WKm-Nk)b{<$y6%uq)n?O7$6XH6i_lEI@9i!lz>>|HkZ%MOu4 zo%c$RW*z>Mj>GtX?T_%By^<=-GNp1i+&u$He+_s0*CxHdF*-X(=ER^UDQVZYh+dEXAx0DN}a)p zge>gA|1}9q#y6oOM>j|G-u$3#kA>aFzlMP+36l{H4}Z2do8>R9_a})@Oi$K)+8uSalVNYm~#7U`$sD!4&E3PU}`qn zT3&pxdfaY)?BVRg4)!7qiFdIl64^O;4D8c>(64nan{iq5=V4Ym6DY*hMWvSFp5<8mTPCrp4SzNz+*mKHVq7=I zu_y+`ILCG6Zsn_6R{I^0wQCK1UID%J;Xgj*(wxgBj;z?^_H)Jnz9{?7^UcK@KC(C7 z3AE`^>*4*^um5{5x$Sx)^mw11!WTL?39fWc{SzO;VR2i^)WymZyX`@U;_oLfNo}Ry zkEtI4PlVu>Ny*UrXGCbo^nbrhe?9-_&Q5{vKSW8N!)Omzl9K;Ym~gQ|lfr(eb(Qcs z(x51eq6r^bl+25RWL2cuWG>rAc7(+R!Q~RO;r1*o(hE0mi$NrzBMMs*X_n$&=9%j{ zjHcRi3+33_rgMEo1GW9MKlzF9*gqgC>HqxBq!Y5TvL{dO<=_BeDWr=;nul29&wN>> z#C%E5nda}MuKSydGAC?$<5(?9XY)szGe^d~o-^ecncXee+SZz1{`=vJWpJ{ypHNU> zT?p{@rlP0UR#&(C{$+1NHaUsoUsf=x?1_ggm4;tZ^gESxtA?!Jw4uo_bI!2gt{R~bZ@J-0qu6=Jiq6f$zV;70^?;C#_=r5wM zSN`N)`4aZIu7y?FpZ!F69JzUXDxcl>xl6?|>e2YaM_KpPvtkS9qUKO2)ep!mX_x-?8b0bCYd(Nn=T_UD6S_)c1ZYf`-c`0qu}(F*d87KkHNVw z_8^ycba2qr)cg{24(G9~!U~cyhF&tV8w#z(GmGf|&%Y2x%M?Brjg5^MY@@8HDTlup z{MQQp8X_ERj!X*j7}J{A56#U%fh$Pgpy~hbp~7`~zyQD*R7IVPQgog2rf4;gd&qlKxrvKficyds|zAS=(_63JQhN9~5*Fm6aqC@riN2rdj@+ zi;PbU4Sk=ILg;pMZ??_f3}cnspf*4?GJ1s$53f5pbqysVC5%sr$;7AGw)9f}=W?i^ zp(BuaNnhW3yl?IIRb*UF?7Ku_jJm_WXFBJXYpiggtF&>syy(or1;fb;qsoM}`l7(> z??K6zso!h%x3uUO8q)6AQ5bJzWz}@pUr3uGqai{2>Y2(HCG}=PyrkJ z)ia)oZX~5fV-hYVnQ)!smi0%M7^`)DYWKR(_luba0pOCmH1Y1+_u@8bw8HRh#_@&b zwWKnd!ootJhVVt&v&T(RGSo+}k@mb7ukpvEXF6Zc`jwOvrI`<&A0?yTLc2Yd++v_B zsAq1Om~}Pr1_bxU;q-?$0IV6k(EhHfszR@9_@YVE`mgt!sP0rkWCmmR_z!uy0TNWR zV_!Y%67QZ%KP1ZU+eA;gw(VCSTKojDy|zP)XIgs=7Q7P@M!cyxAG}ZNf|;l(87Xz+ zuYj}on=i(hSy*B;-&fSu*5>52ZF+f(sVfM{$Q9Znf?n#_$mv4fL8srjyXfdM^u6(j>2@s5eTIRKD2L1+VEPDjH zAT`o}iNVMBX)cRH4H*s!nxacIe|z18O4sIRmc2a~JlKahm#{KI|Ko^&)w5jysTSVeU{J5x_&rX_2NlC%>34>%zKwIIHkhu_Y1$*cm)M>ZdxANTzcIlY+}fyvkwo>GRJu}mYZ z_b@PNb`y6Qv)6@2ybOOW&Owl0u*1!V+Y147q*`=s6bOWR9!;&NC@yd26gW!%EB?1iz_Icmgt|?jS1ftm|`2CnELJ^*KX!CXqw(x zH126QehlwRC;@^j-e&j)_~OID554FKybx1&H)yBZw6wKZK(OWF;<8SN=Jfk_Y{@*K)|1(8>wd|#sN8iX zV&qPH9(%(BbTJ9oqf5?8$<8_}aoY`4_z(0t*?+Un!}49O{@`W|8MX4MqrL%y$zK64KIU z&_u^SZ{D;?spTw*!D$Vpq$2R&_+hWqdKx!zmoSi3UM) zpG!n24;d-Yg`+j_vMQfd_a&|adB|Gq#z?P-u~r~zxauRpSZQs zyL);Fe{2M$ouW<+d3m~MQsA)w985?~X02sp6%?$^&)0{H42!ajTl1U3vcLQZ7eB{F z7o_((+z`APkdfG<$pffcNJ!`{?Djxn$hMB4Oq&>JPP7QCIK#WbrREpweJMJpKSdg5 zRQIkBS_+F&x&z)`UM>ConSd@J(yY+PQhx5=_5DYN?e{MyQ`~llZTru^MqsrkyA2Nd z56#T<^jEIrpblGNeW~s+3kdkvWp)?(G?-?tg$YC$)?e_Da*_n#JEUq$Y4PGMe5=+> zy>?~nDSu>N-;vDO_LnOa(%0g0BuS&Hl8n?|&R*)pci% zg$AEKWmW^f<+&UEYpiYaP7U2*Bg`s@sSzZS7GdrO^#nHjC)A;}38%78idy{H@j8=+mQo7@P0j4J!|VECXa$z|<#REf@B^GB5H-mZ#2c%>n>#skOv*d=-SbP^<`dD~kyR7J=xA%s)NqbJgT6dG&f~AW_xD@?V-Fn!gb-egXLZEkg`UwXZr5CLnuA&ar(5Oa zAnFB%`$I*SU6^aiwEvQ{SLlsi2Y-n0fM!dMdz}1SAB%Zv?#k15*o>hj`?>blZ{N-@ z_D4)fLW5ww3LA3Qu3gY?2l)G2gZ~4yj-M{Qs8e5OOWbkB+DyZ*Q2A_y9>;FX0I36v zL%S~Nrx-n;IlxtDFdwoxtn#^lq~n1a=O4EokB+`7D=Wi7&VRt01pYyGPR`U#(u+M3 zI~XF^{)eo#9&rBnoE>vAal(10{j&e#`a|V?bX>jycJKAp@T`Doca`%Yf^ABzQoBx~ zy4h{ksetG9tT?y}SA*iii6o!+aXIs?r6ms6OiTL=^uuWFfye$c_nsYgnoU6o1dFbO z1Rsgk3#O*dp!R_s1cAN|tW%&6hf!B85>fcK-~mG%o)h0EGB6{&8bbzZn~r&i&d!<% z`IPC1YCrJspv?R<1)2>U9iYo0?3uQZs)TltQ|4Sa^@n+$vPbl0+if#Y&I+bR_tWp7 zdsc_>4ah?jFYTn>1~x@RbGsOq3*4x9@;l>sZPJ+5)!p9S+sol4t$8lsYjmQ8 zm2hv|jG4m)EhncB*{dvA6ap{n>l^APJJeRVX(Xka4Z<}A0?hC%?8CGmNStziIeq+ItVaD&QT$T%gnrJYhI=dKJKyIY2-oEWZ+HN9kzQmH!>1y?oMBMiO3cSvExVb>ThqL&wHMP7 z&Fg0e;14-O?Ofl^Uow_9O_fIgBa0Uw(W7?u?5Bsjqplw{uY8>*V6=ujWBi-Wbh7Ai zilp@Y#_|BK`X}g~*U$M3a?{g2y<{oF%|kPCrc-J~tK5w7Oq)XF`!BpkMn+38OQI;E3&=mUZl-RntAs+a*6a#y2$#%o2SO(L} zckbQ8OUKcFd3D)p7}Rce9?sH;{}6ir{Iv>%(UY-qTV&_(aeuUt1W;`$?vZl~~2deEww@-FL) z@e^kRpZAnwe%ip^kbJr4I{cO}F@$ei4Mx(Uvj?LWvdBoa)6&!CutMJWgcYN)I~#xdS)+Cu7m4zH*7UAgTY*~DavuHD|7 zhBvkQ=EA*Z;qk@%EP*F|dC{><*4!34wJ;Gad=^mXhpcO@!i)F{38EcPs&?>m18r#G zlw#Jh&}KKg^&{|yo849v&TYPP%;&W7E&@ee{HgYeGu4i{e!VZmv$Zs+l!INV;pFp} zv&@&LMnW<>`{s|GxRg-t9Qw@R)8P{rtoofrYz_&Pc3!_*pR?QVXhNst+k2d2|m8kBXlB^xX}Z$}IBK;!z()+DnhQ?c&z3;qtnautn_!w_7*eQp6= z2Q&~+^{jvg!JHdTCD=a)kmw*+9xST!iQDVT#B8o*D%*Cq?e^AldT3l8( z>o0ij0s-9(``o){KQWRyBlv!Tay+bgVAql9?(1BYj%RM&KQ{EBaT8b3t!5dE5$S&3 zLxsa(Ldm95qV|58s;a5BBYp%sA1Dn>x#0T*ikzi|g$5FHnSE^*4TWYM0y*3h zI}4m*_!ZIehpqX71QS zrwSJ!40ve=!;eK{*IW+AP^8Wf!1B5FXBE}sWCF(Knn2*dOMR^nK;|l*K}^70Ty;ezJhp<9va91ErJIj0*jm?rCbQVu{C&bQ zs`iZMK%+uwq0=cg9%&heLuS*}TH5iiZ_>rYT5ec#$ho^L7{U7O*|=6P^|*QVf(Qfm zFvyP)ggxEe-S6D7#bJyDP}thYe(2P`RoI#e5xq|0T@e ziG>|NKR*{qG3%GccPWw?wBz*xmlvt8=Yt1#(gQx-7cDFhwe4&Pk-8%($>ZSo09m?i zH_wE~&VOPWuO_F2?-La@1w@CGeH1P#YDq6%e1r2jt_l)O;11Qq!~i75sPn*X1J4IU z;EJzbS$TOg-ZA^{OvfN~=oE#(ph5m%Kip2HrFCf*YGk5T1i5W+s~*YN`A`>XB zAbu+Zg2c-s?DYK6-T5>Ljsf*$l7?T~fWMnX}4crn6 zjdwP^1KP6(N|-UBcmt_w+e-IqQ(EgRu8A_EpYtx^PiZQ6Cgzf5?`ZnzFnxNb?Xj23 z$LD6?141~0Kyd(Va76QID@476A|d;6DaI^7{)QU#?5q%Nk4ek-|f!3 zYmpE?dHVgEHxw|0pgox097a(TKg83P2bs?NL6Ra55;PF)FfU+t;xy4xTznI%Zapt6BMT79=fC{0F=eRm&FMX9*7kOG z{dI{&@DG5UjczT%pB?@MhAv0u9u9y9j?x>x@FF52RVc6DWM+B_Sv^uayJdZ#>Ej){ z<}ObTzWY(H=66z-a6yE2C^%`EODa+4!1k5voQUmp$3-l4$r*@-12w>p)$U`H=M+=_ z!n?W(3wHzuzX?;20!Oj8uNDLW%n+%@HGTZpiJe4sC%3N74s%!VdW2bl#@LD|0a?E% zy{P=jO@d}-Zq)wt94d;6Vie2794Y^r$K=aJeuN+&9Y3b>ec1(Jr)`f+ejg$<3C;`i zkbKqD*WbpEt7|b7I?(ficQu2?HX=IzAe3`X32zm ztbz)BstaG1CIKD3fy?ceZ~yd}%q=4N_X(t0*f9*5J;pFVFH%!iC&LU>Srz7NHRa`) zrRj_OL=&3?5S2o};f`y^O~@hZ;&K>l(t)yLWv3E*Pd#$b-X-3qBSC0?FB3 z%Us6G6G>hgiBcvzHokv$xhqxH0C#;eoguxZUXlxZ388KcBhTJgwCE_f$Hhh%9(g9Wc?Af#7HtR=< zR(!e?4@lBa7Zpv9!Yb0<5X@ZpIg+~#d}Rru)4_qPSZ%0O>d;;BYJ!Zk_>{thb#-;& zaE7BKuB`$?=b@R`)uh?Y#k}km47#v3O5v7Dua(z`sOD=DpW0GWr$Zwm~3ARtMG;s%@i;Rl?zvdrE{p9w-K zT9ltZ$E2h@)~$u2g_@dL^7wJUBO?^zM+yt*53=YEmNn!^<&*}FjSUV`X6mjYz4M4! zg+ncq@akRsF+gxzW$SYS-9n7<72x(S!aji0VBwFC&mk&>DPL(*(>!2~ORq4v2%KRw z_2QC}v|`VHKtB`Q-a^jD$mu{MrQNkF`r4Hi6w0gBnXSH`Nxf1(R$^j^S(^jRSqi2r zNp-O5{R`I;+kp3>eHTl6IWa0}Pc3~>Ja)C5tSqSGC8eeMYDw@E1jdCL8i5&thn5En zzB0nXM90Muh!e!G=$k-p1zNdRv54cea!R_=klIkK;W@go8J3YYp4y;~=giKgeQ_#T zH{7pBDkFjnn;FqBT>R-REGaoDEsf!{SD-;aM80|RrUWBVW56L4rlVL0&s{=E5b^^D zBH~a($`Jex8ZwcVK+(_$?>wBa2sqG&o44k!1&#`D-gQAAMwo?lN5&s7+xjNRA?N8v z?wMHUYlQZ`Br)@pzSZjQ% z#(32WAF;BrBL;aQAmRI(lTCwse0_}s-syxB z>suJk@QZLoWcJ=nI!DO>HxqQqqNU~K_0$e>aDe&n-BWb_sF=0jT4Ne{ccCysMHap~1Kr)7ok{Qp-W3>F zghLw|=Bbfw=H~N`8tc8hxikPTB}Jp)C+WviG=I2%04ZhanC*%;Ysq=HV;F3!ct%NUBD=I!HyH$zbO)0R6D z@wjc`N>fvj%0U`+5*3jKaL}`{=jZAYzkE?Wc3Z(IYhVoTpMs2Cy7NL4BAC!&!960j z-dVcq>tkDdmaQmQW)XN~?R3lSn|gYsyu3XWGeIytA%LpI_COK_%;2EeJE-8Y-R_{G zAGc^%ym43_+}>xM#FH*|C0DI||AkK{aF<>Ur$_36>wzljG8Ac%+bj%s3!hC`7Z}t3 zV*-2H~wBW@>xo@NODp@@%uk&tuyi_ z@Ky>PG;Ml^Jf&=KFzV5xR};Ag})MeKR7}=vpm2eQSP}Lri%gS!#Lir%ZOisNUwl3TH)wi=ka1pC8C9 zxGD#E_MRHDemNc6`#ieBGy?yarRN*=>fO&5%cT<$hnba?jEoF%zPY;E5|IL>1}$^U z_{NQB%p`Fd{pkCWlA3CQTo;r2pr6rI8}IoXu!r2IDqeSd!Tg_w$w^o1raM;}4waXB z&XefgD5t`)8R!_`y$TD`i&gV$DLqRyrWpjS^PRcQBwse0Fu5>TD63hJ7;^i<{p#1B z7cOo6{FZlO*W(MKhkGbLGWz~tBd1iD_dhWfzVGEr%{oq1^G5Z88UdBrlrW0ZlLB+) z)#r-yJln0tD*n9+joEUJr~6}l=f*i^$f)P{D0YR+KadekjvrAvr!pU)Y;~5uRCV%X zbwgbI+c&L`IDWq%WXRxQknp3uozHpx1~sQ23|-Y3mD+C!S=+&cTX)>(dzM0w^Eel) zh+wUCo`>s1)7_~#Ym??#WFA&OJT{OAYNjZ*yr9PEA}Az8yaYISk%o`*k*boNSLDvD ztsOVk(x^@`>#qIBg1cV2ATeV1W@D+hEE<)sdM#BrtX?h8RoOr-xZb(>T*kaw&Yq}? zoigHEPe`#0*tnI}Rm*N_c-ZdF;Xi(_cqk~uS4(+kuUCRPMy~8qq4!&OU-i|&H)j|( zSARM#B#6m(WF*&Yws7>^q~b!Js4PB3kedroSEdfCCk0N1y7YYe+;P&ccxg z4A|qnpxj3 zJD#1FIvqC3ak~RHkf!Rj4>0(B;pF=q4&m3hQ3GBBZGP)5^J|AZ8II6bhkkCpQ;`$l zoK)4{J8-u4>lV6%PrpL~?4UzYc*FptfvBIIy)ZcVt22##@x`xmY*)M{%4;mTRxmP} zz+af?h9fm=1myRztffj^Q36=* zDYkp0s(U+BBp^NZMwCRG|5X*5HykT+7w^MKNqac`QNcEsb2L=ND2-kB7AAQU*e{?GJnzp5t z@-(Z2OwayEt`?r7HkEPMLbgfSjX$scaRgesi;I7`085CW+5>podwZv6r!3}`4b-*F zWsa)b;VN}boiaFn{FWRGIGTCrtP%Ac)a$_B@Wi!YqX#85a*#xv!|0BeRgx5)BQ{cg zS74+n9V&TH{> z0(SY%ul0)Pb5K6x>&)uAOSL3{+UYdEbyS~W#G%knpq?+@WmRgslqb+YII`gm4E6O{ zeG0qxa(pVVnMQ#>+zhOz3B$lpmV!GKUIG};4-;iiof5x)`o_(hs0yG~Ri>cute_E= z-9+LG?!}-ZMFG8e`+@c!dlvL|vM$Irs}*WZ3HY5#WlCJ`wbRwE!@akae!M5pnTa;W zHL^72rIvz&{T)V=XH6+jUWG88r)t{sDIj_=yi+x=c35`uBzA7cS7k>TnO_gH>SfrOw;$nV{aJM3 zou!plyiLDQ(KQvImI`+!Y1@4eZ)gLhoPH0kRyrf-0H2LZhOJ!E9Ip z)|D{07{Oq3;_}?Oy)8P08aJ!6EKXa#S>QVy6E6KgJ3ArTY$&TUa;M*6jWK8Ys=dX^ zUO8XBB}@5EcZJAjOi!^zs|y-sI71k;xc-V7!>z51_wEhT3Wzj@&=>OsoOtwKEjhT$VzMKgziRK%mpE%t?T>|P~Zb4F1 zc*iKVrAdBQ=0TK&#~l;VAP;d_3RJ4DYz(BE`Ds32;Y%Ss>ZvLoU+)L zODtYg_+Fm)`2Gj9)@{#BTgUqfiwY(!I-{Fbn5IZSpx)YvfvgdmXE$M5lfN`G@=CaU zHk{YgBx*7cQBK3hLB~)RlT`;6p#;j!n~#+)6B91?BgHw%ZZ9+o4Nh?M&A}ME>QH$X zcPgb{(Qd;I{{EL81ulc`8fRiOy=6j2uXSLmFj4lRn+x$C>Q*RO@$HcCxw^T{iP}#r zqf_w}A$Mq4K<+YS)u^KMHPOX`kxg>bQ8CJ8oE~mXLa$hTF4+xa=(9ZG^L{9AXZmVF zi`Do*p`7;#7TzAmOxE`_w}T;d@1GJLNbqd1=r5r(7qD&;>~chD7Ok(XaK_)SlSg9D{$?t7n@s&yq%+^+(T0h>t?>njWqhtj$rL+Drs-=yD z2iL$PajQ3a!%cc;6$9ZxS@^ft8YP8uW*}in)-?-sVjI1ds5ElhrasGpZ&uHufRxS>gG1eXmFDgx@vA zMn!=ts~S=cpJn&F3s2-&w%!FA6RnU!N1I|*t;*|HVIoW-{bRb4newQMP0GJN5@eN3 zk+RuwJzkGjadc@P`}(4^-eTTm(9@^T3g66WL3BMFV4@>#VZrMru5;jtudnZ!0NWK@ z!FnYJN7!dnzoS9o#FYFT^g&U8E%lwoU{MB zl@wZu;m!>~8wN!EfXBU~<9!Ci%ii9em4&5P&jMeM|9$c#MkP|9E)G`YqcJuzDmKp) z4}MshaKwg*>*&|CpvMBvO%-J}_TTB3ky50b;z!*KldR^2o2GTs>!CElT+WDuL3j?Mhpvc@|1-x{~t zOH zc;WmLDJOY`TSB{^9wws>a*%Ooz4MgDQcJlvaYqjA9!h#=lP6_e!|dCJ|Ih2CdZPTT zW%tO?P~2gWefuZ@^!WIMoO-i$V^U%w0Q*h%k6Rqtc}L;^KfkW+r<$7WL8TLegKNmi z-yJb|6P0e++*58D^t8EdpLzCcoyyOB0$(i?R$7jY?Ezf&B>{`;*-7PY+tpd&=GP_0hITDtR7yNA!{j@THl&LC0Ic$uL8q?Oa3t@9b8DuTEE^N``P8g zx?c6iphfI_4&SGXbI`-fFCUkZD$%nzaboSp+s7CvSKs{5`v|0$gU?Q~`0TZ~`>?7? zIapCTtP-ak27Ped#($_bx9J}6oC|wL-&aQFX8E|J^TEatWu;RZ^?ZjegDLRtIR)t- z$JIh}$yuY*|7>3e&tPTRw6wDqfzx3{>bPc zKvE4xugTBg@k+Rtz=lr=JSIKBIVif@(V5J zW5WZid9QbG_Odc=U9oZvWtK?Pz!K*Mm*rBA;d}dFCVc9R97|>Phu5!J4hQu2^~r@* zBC*_hH?*?H=-{)$OBI*-w6&Wfxrcl}P`w-)tQwhkM1+q|f`O89jcZz((9I8&ck__- z;d1d`yg8yzhftOz_3 zJwo8EK)+=|z2(F3JB(gfPh-IyBp0$zd#lCLZ<06>o>D}09DjDhum}yC!VPp_6)`z^ z=-v5;rCm&3(j2}V{zU-sx9V*qC&y-jWME*xxq6Qi)wXS{zA`=6QakKEK7NeYF3#x1 zrH}6Wx;<2{Z%fHvdDCG=BGIu~td*z;atdBQvTJ4d^)<_L=hlAz$&AJqetSSpK_P&i z&9!Twx{FUqu=v~&56&HFH-F#Jj{ccQkV3FxOnuXGpvuaGS)BL?M z2R}1&u7P=YvbD$klUseRSnkBV;eFpkb~El@p=qE0%9U#+C>iKx{}px$FiXYUJYItF zdQJ-vODvQeOMP7(I-{*uQ!wPGs1W0fmR~0htYAg4=qJ%^Th@ht3RYx$RMdf<81i~) z=6IN|80gVHF>)GJs(#9^n!k)>b9MHySh`6=^vaj|(iQ(BhL}`NPNt|v8Y7iK@zUFi zTE``IFVr4zfH<`Cffz&Xg`wi&dmU7T zg}CiEKQK_bH#KP$J<&^eFL1zoyj-e&e#kR8@>vXtH25tgd2Mdi+{BN9s+WBpN&c$F z?+*?wTfWj=oBr>Y(zy5gceK%NSndBlHXR$g4-C|m%RlHP4B4cMF}UP_RNB9H?_NLs zlH%fm4s($p9{(b^%^MgR&dki@fBc9;L{@hF|D)?Yz`5T4zi~+_2}w3dLL!nRSs^4v zl9>o0BeFA-BS}cIvXUb!Bzq@GHra$EWY3R1{ttbB|NB0_>wE65b9J55>GB!x*LXf3 z>&fVkX*!roh`)&pOuTI=Hi3w`Z{}t!uhdfd%C_9-Nync(dCy2p^kc_;tAkJ2q#ovX z{IB)*7VTzfX(?VUH&+;0WQ_i_2M)xkCchSajO=A%&xe%;;BmB~HLqWniEoCqjD^Jl zv?P#lynTC7U3GO@Z|QP_Oq>(@f`@Dhpr}&eK6>_ILhP%K#nMud}pMDVA)PEHb z)BZwXG9VyWMyB16Xl88}HQtZd_y6^Fk{>@NEw~v_X|S7=6dw_3C`z1z^DB7xYCMO0 zDzqGK2uIfAE!&9_zMu06PP};X($LBIhE3prw2!@{IIA-O<48;)QSTZ&`_x5|!z_ zH=jR%XXW(df0YzR<>H%LT7oMEjEs#>GQ)v33l3)w3AOKER}-%%w?dA|&+n}^9C++Y zumTO8Ns+R{9gk9ZnL&rDN|V3eaze^*WH<*GCSh0I@aE>`)YLuhGXR#%&p7vE^gC{Z zFJI(B6hp$o!Z4b*x%rf!px~)f&E4H*!jXxIiFnvIZX~oly`0tcz0}Z$fz*6?(TXD^%exW(pr!_PFNX(39v9 zj*aBx<;h$=fVY=cHAUwweSw4ez6f)W!rv;~%oJRRg-3E@X66Ai;?oimeLXFAe@}li zJI|{;aW-O3Vp;!JW|gR`8(-kgkJEj+3T&c3oa%ey@eg@dg1P(!RHw@SC?$XFXzJ^0 z7_d%K8PM>}bJ*6ORifYer8$9QT=O1KgyZi-na6yYCU9S>1_ zuJAWLo2L{TwXc&HtG^rqv5$P$ZRXY>Js~yL#&fOpfm7R;&wr!;lRiPa%T*%eYM_$B z`@(LplrApk)eL9zJ`LIYxs*QY3qWWDu7v-@iAdBK;qZ;n#=eW6Uu!wd#HY-gnxx-6 zdXtVWP0sMa_nMiR8LM#CT@PIbPI6GiS$~}UPjT?ibBOXG2z_`o1_sLY1z`Ha)RP8M2>w9*!!A0Oy{rJaVdTRpW6hYOf| zU@+L!>b5uUcRLCP9+~l$8&q&{$&ib`YhkfKARJQUP_?p3tqy%AXQ-^Kj1mMVHQFPw z>^~pK=lnk|b5?SDdwV-kU92N->4KXlsrI0$%hpc2npl+kq0j1$lT)Xu5I|^rATknS z)5{q{f4xwxFH8%Q+& z>3ENdr#@##Mn`?i_1|kwpyvDTT-O)#RBnS(t<6kFTbq$7L%YPZ(nxTWu-Y#cNKTZu=f9elAFPq#;XtJFzRx-z z#VkekpeI)o!SzCU(9m#ooPqL1N(xV$iY9ttXsMf<)7!?*M03)_{YW@;$XuA@gC<<; zrnM{hiq&{RlsNlM&o55=P8y4}suSoWA%ANunC5esTsy7(KC55li|W5=1kD6mL*6!K%{>bY)S=uW zS$%s$LnH7RxlZ7Yk6yd~<H0xjG-MTm5RZV50 z^con@Yp6#T6W45tMvI25(m3n5(L#0B8%l}e=WTMIHl&p~B~RMCD}0@lR-grTvbU>i zba3z}wQr||1FjiD&hV8hSN2m-;4lI{1rfsdKk4Lutj6xJ$?2JhqCBkQ=w7)j1H4=pSFg-)O}*&^y|x% z+Sj|_c?l*TUH+YP^4x>^6-3MUG~*Z3wZX7hRj=tu^x|`jY?Kd&e%i` zJK`{7>1{J71A|YEjmo^VS(@+0hp9kT&(F;vjc~mYX8<<;!0R9Acu;F_B>=4_rYEy??L5 zL46KMz@42cH0PxeQ9Xj2`v=Z_Z^|sYKRA|MFNE z{N;k5KW7V4Fcs47Ym10Cw|8)OD$6d$+TYiAPkfPR-=01C0`$4L4gmpN%2A(q-IR;W zuCHYdo@5y_9#5Xfhse>k^zbMne6*T`R1o>xqPD~2{&ENRkdTvlDJJ}z1E2}C`$kR%L=%}dQcB?>|k<2sk z^QSZib(~UyD{ELSdL4zo=KFT$cl6Eb7Jo44+Wq*W%6mTsrzTGl_B~XTj+*`dBT+!h zV2R=j`)250k8-&tCw zT|D+GB$BjmQ^jK;-~8I`0K&wB)2C142er$4T*r?@d0-*T8$Ja;lRjRd>OH^1jb3uk1Ich211VwyJpmQ|QmMolE9|1VE4 zrMmi3(zkw$ds5-%2vUH!R*3ORoC@k&k7w=f%?u^u zaT+pOKf?Tcmc&XJsv$KEjc$=I7Ms!~78}dEd*%wnSUn%2xnmDL&Oz;~#EB~$M~y`6 zVHz4E`&G2@%F2Q0XA~+~km7)tL~UnFvpdidW@@dmzfJi@fJG<1zP zdQ?V+R#%-Vd{90oshI)L|MUxEoUm`Aq9#U1j|W%(B^?(Q*1<1q?r#0tS;?nS&As$| zN`C&kjEuZ@?_NrOIj|Q75RMSVJK}5Qr{RNZZ#Nc>yuowh!i94GLIK?9)V{L9k#50# z{AaIq2ow{>eGf5d58YxQ^QNcpp*wVlf&4Lw!t(NRjOvCk8&JiN4PTMA&Z}^G6Tygp zdzY9TgfG)jmY=01nvy1N-ce;f#cDalx@)`7oAUTy3zRcBIWe(nOkY`(?KR1d+k_*xP${#TEEhrlt}bl>)~LEHR!C$Izt0tr{M#{(gxz z44P$$C4_|+v@fyjt;tm2U|Kjo#yYJrKb8;GBn=BzbJIG;6R<9`pyBUyHcy^ev=M=y|=SUY4x?1>@q&QMLE->2GxTN&^u3dC^&L^#eR zeRHpfW+Hd~0TrhH0V?E|eM2-f*{;AUG-&OH^Jo*ZkLLi$be?cO^_Mqcy7N^2JzYYW zp7Yu=x0@Rx$qFIdf{yKnH9iv`RSon#%aeIUXiXl7#aOd?N=dO%Q5SsQ=Up>D^S<=A z%v6Kfb@j^6U$1e~&_+hRs2i~U{{8#A56@9$;#}Rn7u;5byvkpzCNop)_LarGfNP75 z3P-2|D}@hwSGZ;k2M6Wi?*nqN?(7Z8xMv35!zK z);5dqapT+6PeH=xgGU1;v~%r_<1HEpfGCr&`L!o|;Fa`|ih+}hixjRB8oa|Q$u#7o zM?(~$*UJ&r4G-&B-hDWGlaNs#6x80a5qkEB1~wbZ4gptyJUE(0qo#ooOK$h=YC0UJ?FKQ%E{fhd)LVbM=5|O zbkxvOm6z}EDi?^blb3IuIy|E|ZJncCVm&qUQEDTUZ&>42vUawDo|;{o{gw$tq6k8X zs2}!>J5upOU%^^{nW9Qxz*V9j-d|_uZkxGJk_$~u&k>X1SBW@;vB}9Z5lXm$@j>t@ zz$w-k`@QdMINNX0Q|k63pt}Ho>dt@JHwkz4TdaO7zNeFO%cD&&dw1wv8$sjJoPA#9 z0BE2;yl-o3C_s-7A$`P|hyQf`igtAK7_Zy)>+_LTueKHv3p2`c8CO}b>tmy${@Qc_ z_5~WPv{ZtZx2~t>yog9X&_(2#R~zAE*}letM^L6HCa4NA_ToZ+0ATa+75ytK6g z)=y*&5dCUt+51sS?}1idYpcDw;-YTBx0Ru=?#p5Cc27m%!Qx`<>jTP~ZEbC4R`Wr= zzT`AeIspOwHVMe}U&*o`*z*_Ag5L`0gH^bVGBp8{NXD)Q7Z-~qsQOk6yc^>KG>`LM z7_w%2dxGpm`;EcF#`N!|tUQ>CFEG^a!kGpv;A~3nUZSOj#=W2aftJZ^qh-5=|9K7{ zWpdgYOKV|Yv1(@-QpaGEq2XchTlhe)5N?GX`M2uvAO%RS->9d0FZQ%|bab?}X~k|K zXNBQzY=5VYhQ?V@(J+~)SFZq6!`6vYwLNQExa5{3B?~~(Q0|V(~ zwHhNq!HApM+N<*`^Qh{9YylQ&yASLGtrkEXu~_o9ks*7x<=eG%de0)1+UL`ag&O!M zqPHG@59H+`;>|bP_2z#V4F)nWFk#HFI6@8Prr9oSE4f*2KWf zJTX0uaNiIG4%i@o?GbxQansm{FpDs|-*xA^jU#dBI8JWLt1^LTde9b_=HTSYDm46P z5i>Orb$MizP_lpj{!nkm=|YqbrV+Q%&3kxA+Ns1hqu#|w(pj^uz8v4o9i;Hf<{U1j z#zr96X@I%Y()f-a$DX$n6`!YF_?Iq;x{~YFej=%Z#15ynF_sxIds=pPrGCk(CvI7r=59&{cz| zo`BEI6IG&|ba{rW|lo0AMYP?Hxyx?yTO zZGbgCt&fi04X!q7V_0bjS9<&C(IeD?Xv2Ohpyr_UJ4WrR?%RQ{=MUzBt1>c@$$%9F zP@D?Ng0?nCOP@6W+aS4t2%DQ{vF?26viH9`)?19g`xF(IhxO-C&z)%RxZZWf$hhUj z8FB7cTJg;(ZIkM4Q&U;qkK9mL;+g_!g5$E<2wg2S3eanp+_G|O*qM>-{$qoM#mX{# zW7)j-6jMdaV6=sMRGk;)h3+?oyw=!w8yeIb7skJzq9-Tz zq@tsPn3#^1mh{-|H0mcR1u_vz=)7gwgT6|lD!rYl35ZlZc)Al1KHM`9ZU41kWhIV$@Nl9O;s;X+QyH32E-Wxgm^Bb!v_c58^ z$bRw-M|1PkJ3anu#s+q+PIE>b-8qB{7kWi?6->FkrH=$xqdVgXkq`;lZ&f?ds+JdQ z+c7)n{`6;_Fd<{r)V01n`HT)1vo3Kp$IEdsyw?Hi&jy*&ad?0@+HlWF$AJP8;Nq%U zeR}o|N*}W`Y9>@*@z5}wqJM^M3gifkGHW2$Hk5QsBl?`)lnQ6?r3BUBYN6#|1We#R z*r?vs91URbKS-O(Y2_y!Cl#l%Eflf-L8MkpO*G||O8ul(a{WVL{d28v>#gI{dXb4l zJBUB;r2hvT@7VLC{CQ|l`Oy5Rov2^srvYnT&V<6%6q;|Ho%)7`@#XqxgtlRAnWZXg zE2~=D#w#E7V+1-2lqD-wxtmh!tE(eoVsc|Pp3|SDcaC}Bj5Y3YDF5g6`CQ#A0|&;Q zKWX^;<=pyu6tD#}3z?cQJrHeG!`%c?g_XIvU%5W2e&p5w)K}|7snBX9NLX3|P<%H> zJ9V;WW5W$oLR82)=bW^(A`r~wdyuOkRucM=hgE|Y*@FTD1Bap@jDTig&Z!u`N&2s7FWZVmPHn{5bCqs2_N6)|hA{jr(O5_^Eq055QD<~>T3~+u|7sv~Aswcu~ zaTvC?(g>v$7vGFi!A||1b4Ez$SwO(an?|m##fS+iDRBdYWM;+_Q|sTKml0mEvQqn< zKD#Cd&R-N`RaHI;9B&g7b(D!8x=g41A0F{vZtk#Wc6JLsK1>S*1zgM$qnLQ9I;8lh1zcDXr^!Uxw9jTFN{f46hNh4@f-F`CB-B0ZIk{eeng`i zoWJ-3$B;f>^fKYH8!g`p@eQHrrX%G3w8MkJg!0|bFw!eV!ucop{n4UJjiu3BvypLp z9;>zzq<0GoQ(mj5UW{)>!*SxozHV96G2c-|{~;(oDSpHbLD^Z*@U@^IO?&cP*Y~%R zABr1@OKvp=E9&}w{*b~mo;iNk(o&dle;B{KLV_xpH*pC$QT`TmCYzIGR`UN>LGmx( z0zYUQ9KGy8wA4>Xy)K*#0}2TOf4pl+L)LCyKDNWnkxezNbbh!P#}Ga$E=RBVHOoj6 zVnaQ>uv>Z?EsS+*IL5JPC1R(ircQ<^VuC`N$@+^Jja#U5Rc@|KoqwB`r&%}X^n^eE zV<77}*`tGZVjiRlcksD663rj^=5^`EUT<6xP3m_5%N;%(D9i5k=n+g}plnm!YgQjP zJHJukrtrCr12ZbBE_P&K+GDgXVvJJaH}%ZC!He_G9=HD5Gdeb=h-%WNz?6KLcBxF` z##!?H3~sLL0`#qu!Xcy&i+-mZ+NMpNe*c4t`*90AEGmBz;@d}bMFa)esrKOf$=NS7 zmDn6qZbkWbaY5gDMUd!tX3r_%Q#%eZSWJ$Y)zq51uME`;R-JKkyV2IhvgCNc;HJ&o z=4q3O0c#U3F05pp5XHn6nMYpT-RXKeXA2kZ-xuXjwf`a2vDBYPhO6RA-*)ZmNOLcVP)AiMqTp$f{kpHlm|Seo>v?3(t>M(4T_!W362_6=Aa2oxv+Jv zUb%AKZB_Q;#m1zhT2@vY!HBxSS#I`gHQhPG$Sa$(@@Nw$#MVtKQ|zb6aU`!iMz|!t zueg|ogBmT0O~Fm}piVGC8`>GCgjz=)@vLl`E)6To9yxNMy@JU4@V`KnmvKCTm6nU= zv(sT^VF{@=a+TQ1o77R&YRg&osu^M;<@eUj8Cm6g-R-I_|GLmcg(CB9Zm5BY<7h2^ z?Y@02r%&^3wJ)`P{rcp4$I{o4*!fU?$F-^R=S@aFe*9R#oA#V5#MymQ_W*N?mhPHi z|F0gwbLU1qlFiq`b_hm1Q;@ajq}{>ws;BjBU|GuM&oy2Ny*lI5VDXtL^0Knjcy!s%xxQhEZRK#hL4L(oU`r7cI`uMm*kNGH_Zd5aAV_ldi^)v>S*gMv06QtJ5--) ze?iZ!$x931&&IN86ij^M z$nISmq2`|zYhC&^d)60+BeDY0yu8ZR&oVMF;4U#0DqKz^J#N_6=62ZaZ^NuOx2}X^ z#{f!xG9J7uM9zpp*RN_25;v5+gq*1qC>SDcx-T!^FZbBeA@bVw?pCj4Kf?o%A#9TS z(r#JK$I`}-$?R3pJvlmQz19Eyuzrol9K33gXYl% z?`%U9$q;3+2Vs615QS`s0e4(bvoq>tIi(&$wDSX5mi2sPDh5_gPT}SH$P;Wb&HnQC zZSv@7jN4jWpv0>(gNxG6t3$s{g(Ll=9Lv89k7tx^P8Cf<9jZIUMMX*FvHh{`8Ve1^^Gws@Bp-xRPb?9XSw-~-bI!dwk!D(thEEjqu9n_T4Le{z zr1)vL-k4r#{_{b;szAz{(ZMV%4CMRyZx&rC`z1afIj$|aC1-4I7;pBfRu`291SdFL zaUN_pg|Ywgh40SR$SWvd=zg^7hmt3 z*3*L!bQ>rXCiWD8JFnEOAMVdOV8mTr5wh$T?#jY14qX=h0KWsv+}v~@=eItOiWsGU zkzhn(BG)Uq%aU$|(?RlM$}!n7XRWMFTN{pTWe+y(s(LpSGrm*?c=b2%a7)X{-@g$) z2Q)#8o)Ourbzennho9l_VD$fCgMfKoF;?6^1G7#vWI!gI#>k&GP=TF+-5IwLL=8bt z2yQzq+#9|`@4Bp>Q%vxDT*Fg5cKKC3XK?u;hV}N<01b^HQj-36jW(H5D)WIJQoXv2 zdd|nc_Lp5tc;rsAvF`e}YIELhzrOxgOe`8tt@CoSN+1S67Y}zJ=y;!sX0x=lU(e|M z&(?$zf6Vxoa_&4>aEJ&P{nh=bOpJ|5ckj-)vI`^~R+EXz$nx?sl4&E9O)u6jLLzSgTo|NG?WOm^M7-_JRCxd>uuO>5)p1@#gQUBqA zp`nox^r>>}LE!qlrD=TKyolWn>~R!fo`S0sq!(xKifbuSwN$t*%*@6jP231N!eU~G zWJy!wsWdp{bu}X`H8MJyCFxz%=H1x*E(=y*lNMq>2lZZrq_sPoY413Dk~#bDHZ!_m zNL5izL!J%88OC$rlEStCRDviO96yJ@yPHkp_@y#M)V(*$w zc`0Aj5C8sc%INQa(TYfmhKQ4wcKqj0RTUK?f0X^eyZ{*MMBB&SP@|#V3El}NGO;1@>Gl178mHkU8^DSZ9lSl_?=z{J(YN>7h2unO`Zr1;1{ z0{BN|@&{Gj0{^L@yX4T?-oA=oD=Qc#=PiA|m+%7QA&Pt8P58YjD1Z6WE%UWh%Q9++}neKs!N!=N{1T)cj@CD)2{<0N#ykY(+;a|Cb! zCRxeJ6%+Oq#xP`caj`$T$a%iI$MC%-w>@ZNNN^x=^?gF;w~WGv)XP&Y9*fOe`kdYG z=l=fwZT6gBstB>J2JQ>ZkMsIjnOJfdcReg3Hg+RgW`P_I9@MJ}3h!B=p!}a-?y9=F z0DKzs1&|&@OMy7$tAAKSodzsrKJ*mz_4fDgZ`*GXWzZOX9(%(0+{lh=$kJvH0t%3= z&6iCvtBtP^lGXC?@$Oil^aW2Skz~B5$I%XsfmQ zsOGcOgWpfgD;C{^mhxQ7jRqmyUpTeU4Ey$#$aGSekDuQ7RC_PtD$ zzmv^#*(KM!<0L)#A`|WGuK)j0InCgvfUGt|5#KhQ!?v#-x7ZDJb?t^$vmBtGxX(nR z11bjUtjz86c+;1pl2cM_tgZKukv)C-^aE>TSVTni$aWq&1Ta!;Po4(k#+*`aIp;Lt zI(R;E0q(}$)#F>OcZ$11^kHVPzIU# z6JIu-#L?D)`NgYy&9g+HQM$-}gqgx5>l`$u+S<^Qz1QURm3>6J6O2IWhi4#+v6mom zq$f9q`X;`aY6Mz0Y;$^gk$!jQkCozeEwyxB<-QyP^E!$9v8<%nM9!T<>QPN~^#O0` z;~}?PCHUArrk3@Ct$KYU7zHn$bG>oZ=g*q%y-etm{%Sw;rLywEWC(;)jQ+PYmoRi0 zayz`WI7x(Y;48zFVkr-lBDy6dJ4JPuPGr<=4p2@ytv80DSK1GUNF&_NX9CC4TqXy zx=v`MZ+~wqD_U2bny{*I+WE>7Z`?OCODQWWL#qimkehptU*(%-Q!&;?gUmf7;55<* zE0PRMOg%1dhU#+;o#>FK3E2$qQ@nJ^ljjI>37F42kasun(fZM?Uhn@rGxJ`G4avDr z{7b&~w5Z;=LB{u?2-W`4uv&<$<>D`0xk8wo9hhH11%Z8r%K(@OAYK}>U48)lXrN&k z88HdzWWl>f)HVVtGBuegMqtDn92|5Ki)kG3t2AKrCr#kI_%tr3r+%@)lX~yv_np#IHXgzwbMxZ1rQs3)#t@yJWiZsq5Zeg)S0N5CrnJj<|^rS((Yp4 z@gsfb-p~D~(Q4q!pL$weej!Bh5HqtYHY>tix0cGbK+bF}_it@3c~MF%V_+<5SV*zY zFxEGni9`rF9^>u%vp+AQn1LGPWEf0{7ky>Hiwyqyh3Nnm=dPq~C+?0BoViC(Chg_Z zaUmk?C(kAjd}+woJs--l5B~fqc=|N95b(}v0M{JUcZC>f{ZQQj+Qs=_I|NdlX+xO* z;zR?YRz+dRSE-4KgoyZrbk` zm)4T8R`{~KeB-WsOR=Zt4(@{*T3XO_G@E9llTb|ts0al~XevwG+p~~~;mx8b#Lf%V z@XC!%9qwUzE1|HumfEs z4yQa14-IvI8Pl8n8IWvU)s!TkkSe;%?Knkx`|Vn6SH2N5$UXKm9Uv$K)?=T)-1TeMAjXE2{YZ#noa(T_615v*yUj0 zK=KyCEMNwJ%rGhO>8*^6)YR)d;$0S;%Hc>x8XZait_%%irNKE-(Z_%N6<$B=P4=wm z(FM-nJSmZ&&b zn3^h_44ZcvryJN8&6cJa<9+4T&hO zSL`=3Z=m}C`+zqCq(@^0iCAe~9KW2Z$ z#H5Zs07h=NAIL2UCd zJi*l*!PWRtG-Maqs9?c~Q~5nP866(3si9#)$UGLJXyfQeL9rM~e>mn9BV^c+Zm=>j zwU`QlfdOd&>K59JuNc{aGcH2uam4`s5L^fJyNz_qtIjCXK~F=ukDdsAr}$=An{nF4 z?Rp%lcLHb{XYjS;R_|{SDt9gc_Nf?%Py%!9Razn!pZVsEbZT2l+Zf;~=(gd77_vc) zN5`WU5E!_&x{3u@OTw-u{QG55KWOi*In(!_*+P&;O5QwPl>w^KNUr#LFO_d7x2d$Wm{`ybb79{@qrQ$Le?RL zqRs3~D|u$=U5BbA877HH>YAb)ZF}4WFr(%i3V<7QKdB5>tFP?p=GruJT^BHbU2<(A zE7o-m8c^JTsuwQoP`ksty|~;@Kn{RI1*Zs9GJhxvH2q-r2WNQ`ftq|9wL{ygr)Twm zSx{UYjp8xtORB0b2%Wvgs>$79yrb?@1vb=o?@3O47cA++mjjIjPDnK#5K8`XhJq2G zd7yrC-Gus4r16h(=6+t?6>W{B4}Ft)cu{1BNASE4xJ zt5WL$gcb49UQSj6nTD2Wz#0|=3Lh_3n{6L(rY0ozkn-Snz#jF+E)O0Y52-;7m3k;y zytnrr_si%=Ca-ECBK8zYqB%5!g+fwEXTqZsG_Z1V~|<8{L>EsqI}xf zzh|os>lHchk$FG$_xG0I%KH@Nz_-MX2Nx#axPOGI3dM0}Al}(qH?wqiOXuoFxtSn40e5ByRef^5e zc)<|GoXpG>EOkh3&|?%JA-WULfm)Z$vqzScNV+ro5vl6O7bk1 zdo7JkWYYulV9yJ#F+N(l6|=TFep9|G>ctB0N%>4U#-2pB{L~+jg2|DuI87{KHey>6@s?<$bm~y!6t5# zEHe^)WFm#X#w&(r!h;rbIis(d2rwd(C%*?X@u@nT+w$;^NVbBhy`3BP%1ZTPTt95k7`YRY;+}eEw|b=%^EVBoA_h zl4+x=p2&Ll3zmk42eFxv-d%wC0hZ$7D3}Nf3+Q3vRg!=XuVM+h652HMoCdrx!9GfX zLk=iMNC^7V@jn9ZAJ8S6k0ab|Y6|KbbZ4lY%;XTFW_$*6DVDLuB9$fU@?XFH{)2c& zL`0~|EPYC$s`b2zqw;aYojC`LeeKD zEG%wDNpXC+b{w%p${+RXWq(erzsiT=8cHUJS~ZsDRm<1kOf5;Y7nj_h^UtyL(^xup zwAS1lqE?-_#g;r%8=JA2h{7|6BhR|2AA4bP@ObOs+G3}u2wTwCZ6{~w(Xc^L4GV#L z8!5Lp&l$NoELIWwK_Q8Dbq@)WACXiaT#YpchJ=`8b#3D<`mdXRgF(XdnCj%@Oy9l! zS3AOk2eV9rI@@VwI8Xm}qRaEMdUvLD_Evpjzq;GZ=!Cg>J$+4}DOA6&41X5EaD?z6$YbkUvQf zS`jg}){iWa3vnvc)YNz$X^q8S;6buoudB0gDE~|C+~3o&I((fS9eG%UFz=6d<;4T+ zK6|zUZ@awwHcmzUl7(+i51q)p*XxX_7Q&Iy5a$XpW~{x$iz9X78)QVNvHOd`AL3t= zn$uLc|8k$@YZ|pvX)eL?sU4g@BSi|MV{rY|E6N>>j$hu3E~PUuv#N8`;I`#)ej>$& zx(nLejG`k_JRzU$A07#VEvB^G5pe07%;$z+rw5?nOSj zZ?`rTns+ur<6VY>HKcG`v&)la=4VT{?h}}%HTe4(FY6YF4){tQbeJM9etZ73Uw^h; z^n+<%^{fZZ)=ik_9vK^pQ8S}Ie-euy5koH&C^q+Xo0(}iKOH6ZU=A^P+i8gND^2lN z?d*j7kQ0xu0-#MFe zNSw4EqhY3y1Oedhzn>MeTL&IVu_e8G2U)|TTymf(;9$`|;f#Zg2)FT&jg}H;gj~hX z+1o)uobwjuH*PG?4aJe|@~W-8-Me`BfMsV_p;1o5eybms?XNx=gCGn$F}RwBii&6> z{K7?js8->fGB-2BjS7E{UnP!lJJH_ST9i%KPlkbsru7>d9IP0y1{cKJBdT*D*euja zsH`XLv8fzH7|Nq0+o9z66POKEU9R~x~n zfw;l{lW1(UBVuJl+DK=P({N)DuPBKMBM?-_NAK?l-wD*J~QU2a?oxO;vK6TLX zT|xp(Ku39a$S8b}&0>pr;u)o@V`x~j0n5Sp!^ETmr+%-a{Pr@l)_55fc6#{GA+05f z$LgL)A%NQTUi3ZZu`1r%*9}8bi%#gVm;abObmInoD0GhMBYpOOKUDeyzkdB1>001z zT&j^?mm`ciSTTVvq(MGL-dZj?)n zKr!5puFLOLlgaV%BOMohHy?IizKtkLgkUZ&_E-&A=R-#6NU_h`&fU>=Q-`U}6FFeB z+R535OH*-gIls83P zp2+TqjLvm)=?hJZnET;W+O+l2JzZhjlWga#qjOoobm7B|zoUvtvmWrCA|WpDXNB-@;l2$A^yw9<1-z{x4VHRYbdtS3DVJ9#Wi|ocv%o!UO;~FJ)gQ z_!TT1G$QZWKLDP`YUT++)4$m3*zdMFnn=kk@)4dQZkpIe{*xzJ85jzxADeHloP1sM z3((mkI|I;Y9P|x*9;^xknpcSa8s6X_ z1*{JtMm`!cOzp(5Hfnn7=Bl!<{7F7iG%|Oht+M|HVgYS87Wv>TMpMd2OG8%)4Pbn{ zAxwJ%hD-%iG^799mQhv-iNvz5kgbWbg{{?8ip8qh6B@RM$cQ8A31{*E&|c!3gB2$FDjnH&PXOGOmlk?U zlHI$rG85+-BUgdyTHF!ei zr)~ev`=Gocht&twLx>^@teZ~H9v7;fM4!-2@)N}d-ghY+(UYy+^rXNXt1f(s*IPmqp7%l(bDtlO1Y>&;qZhL~} zwY!l!7Ssn@{a@a9q+W}Tdyl`j4FF*XPY)x>Ew3u-g@>v zkL$UDZ)RqDV!g*_gw8+?oqKPCioy{(R*dEV9s$0ia&VTO{7YNgA%8iHSA}%W#ltPD6#MrNVXRwjE<)jvmF55JS$Ms%ug|j2lE>>!`;aM0k9HPu zf7zF7k_tPScY^ zU{P@-ORxoH+^mzB-EnS9vK(uO<#Eu#M*M!6LKli@(twlYE!{P>*nozsYc55F+4v#w zmq;wE?AWB+uB}@B1DwL;p0-U*JoIS?#EI5RL17!KkzAjt0IVU2s*)d5kv2Eh05X8^ zxMTGh#5k&LyKl3$8%1_rr35C9SJ zlJj+^!GNs)^y5cRCjPJ1wQHwDMVytkEUs;jjm@Li+p1q zTjsUkU`cf%W(I~qn{xpHiziPyNKRbLFFduEgck-OIJLo*U;SP6cH66it_&N71dsd4ik!p}Kj^T_JY=$L0D@WPkd%tAQvj zo%zW~t0Tqs`Xc)^d?RW+P){E}aUwM%0};xwUm@NA`y60{XlEzf0qUVkT_*U#dJ(2N zzp-@Ks%Nn~H3OUdD;y|1ArRjIr;Ae&6Bmz@e+L{Dl1}d18Y(LKf)TW=Q3zl{;e_-m zI#vrvKbAkFhxK1^A4rp3xF1`+Qg->y9YBL~Afl={aGWB;As9j5;MJfC+e0G8s*L(= z+X^x<6~GpJpIJEQY9bCDA;z=?-;^W^K*FItypMf+fPP5J$T+*W#3jB16(33C3;W`$ z2v&d%aC3usMR};CppakfN|bL8?Djm!bT}-L8sni!i6=@#8HuZ*rltliAn-qD%-hAV z4*h8Pv@;DV^ZMPP^2Mj%U8C1#U|}Jk&g@*lnU<%3_x}(x_}MgMDC-R2^~uZxkEl#Vj%bNhM2C{RUrUn&7o>BD+t{A7E{2nW{ z_!NN3br5={p6V|b-$wC0GxHQQ5P#y3@I63+o!Zv%_CUrjA=l+(=f+tFGH;B%iw+6N zd2dbq<_`i1lkQDlnY3J7770Z~k|)e*Nl#bkU-wwk>F_yBD|<1dqaB?Mrs-fz6TnnR z<3cM2NOtW4>2;Zd8dQU)6eiDINNmZ_?Zt^)@cxi?8iS4WXvd^L*@q8zwyGa_b8V+} z(fZy|J>paG{(IhS;YeE>o7berMVK4lIN5t4UnJjYQu1eoe%&DjJDcK}A7LN?x z$nZ9@(9?rl_1>jr7+w{n5v`VtnPr zV|6G!fne5a5R3)r;pS{`Si`A^62I0+5Nw7N+YjqyOb7^3OsF=>F8%?BYb-xb6><0{ znJK~)6IAXWJAv1NoERZFxw-9aZ2+X;sHCTN3g*&IQy(7~@T?jH@AL=z*mp6SHc2f7 zUr{3mp8X?>pJ2Kee%bA`!o9TjXHs)&^KM!U4 zX|$*Hg}eX!Re%uI7?Jzy+lL(>v%snfgG@a)LK`d{nIcgqd|zfe=RA;@7AEszxL0@% z1P#b@oF&^sd9-uJ&{~~eI5i@F*zMQE1T!@?4)pBzFHT~ou(Q8Gy!#v(NM-3bxMW~j z!tn+z6$x>0H8~mCLV;#zNRNq-KVeM1QIxWztflyN;@kY}Hq(hVQz3D2$+HTm%oVR* zJ;}=p)g#&^@%h&1=$$1cm}XPZD6X;gXp|C9_J!xSVF?oyM4bd*tRfo~j!>N7 zsJdrB0-?vu)Wj|yMpAoGem*zNQxsOv(ABmd^WUFy)BW>WPZe#3nXTL}Ty%GZEVZ<> zu*hvC1z3qS&NiIeJ?{SymdmO^yhf7U(YrA!QWAHsua0TY=dF32vk;{9`c7aGKN~p zIYPz~RC}GjH9_DKsK9}7kIRtKLCI}w{Fd-cM_584CO8;18dys-36<=j!7l5kBCj&$ zadBsty!mii;$(M4g_jf?7I>u6Tb=LxU`VACTR^Ya+vgBEi_zBs5Jj^#Jx$3{@PG$_ z7B~mm+S_?(oTN!1S*gt4U=Fa;B9f~woJ$rFRb4Y26lWI_)KQZlJuWG4dUmkt8u!aAzuI$LiP;&YX8rHuCX1$p z)W+)CCgtIWXfv}{QGp4u6XOuxT=d(V3o8>Nd_9^`wu&Y-71If>T{SZ{hEEaN*xE3U zKIY#4aUi7l`0VzpL_i&A2YAG|f1RM2Q!bnKaGU(P%3>Ki+5B#;wb(+}MZ5jx#ZO4# zK-fl`!j&}j|G2@kwo_)di;jZm?T7%yoSeL>pR-5}C{+oEs}WlNN&^hy!0|qUHHlq2 zGJlTwDwY8Jk$7R)bJdSxK<#Eu$1N8yq1z7~ItR?<=munR?wl6e58KXXN4aQjm4^85 zzmt}hlAeCj^s-=V)qO|#^sT>VCMow%j-|F=!^MuS=S{P%&U>V;jW`$z33GB)wTL9> zO-|n|$lRPc#p!oZE{^KZP=cG=hPU^w-rmAuVtX?=J$=(!N}o5k^in-WC&yZ!6{K;f z?7f@SbyG*joFJ=qqeXep!D2mov8}B>BaLS-dG0ND5x~1}VN+547#}x3Lqb#rTeXMP z>&@Ef;`xC8K++E*P)DSsP?LEh;@K6`dt#l(lEKSuA!f}Vtsfp$>yDZ9-grrk@<(1QHy=~xyA=?j+Zs>K;HAl)rEc>Kan!4r_O`jy z??LHP0U{5V+w^NG4(!93B1Edv+NcUfd~awEZFnvP6HI)3vRaA?_p>KY-b+lTKN=g~ z78Zqu;-w%j0;~>30fSzxpmx1kA;Eda{Yv(^io>SU3c@1 zj}JzkE=j8M-O`$E)^Mh?i^x+A4X0O5P{qli$&2#?V4tM>x(F%-dwYLh|1wG8xFw+$l_-sKQ5GsINVl#0lI$oP8RpisRX5+i zw77^kA5Hg|l$KG&%a>s@KyQz3`eodC3>`uL(K}oYB1-pWl&nA{;U9z#_wR;JOB2+8jJm8)SQh2F2^oc-lMvC1B%Rd{yNFWS6^ETgz$S>7u~L;Y?faz#PN+e;J8i=41U@# zu`Cg;d_5F|q(-@T*d>q(8Gp^2csR_ZCNw?LeSYVB>U4c6Vc^#ZtC6z8Piw!lE=s$q zp+~Z^;$OJFBaNL09%h#(->&ZjPCP=caZJ1KRbbof zD~2RifF6$coZ3=*391ifew5SQavI3+*ckWYFU>cue}z$c+j2u8#-xdW zX4AUH#xjSnDHfokwvhCotZg=>VINW)J2cMF0S(9i1X=|G)(G)JxKL(h5L%KFv6gSO z@jttZ3Z37?%Sf&Y4fI}VK6g&C)H|Q=KVVSf2%s~~z=(Qqr)UhG`1z&cFj`p1cFiwS zH#a{KT#agFqTg+VmrREzDa1Y#3=eP4OqAZ*iuAL?qCh@v)Sd9BR z_j7vk$ohL$Ryt0%=lxFXeyvx7zYnb{FbH%I>B%EcqOIg1xl{a&;rWi`$ zt^G>zOdbzdU+{g~GlVdR2~i^ZG>o&l=*hpeFD}UUT#EevSo#idtpC0LlS+~#L=pN) zl1)NpNhm}@GBQ$R&umgj5<(IZl7#HNNs=Uc@9e$z`oHd;|8=hGobx>A*Kpt8@8|P= zzh=%+WwxbC-yJ)VZ5UUf&Xbv3h@ScFD7G`!5DQeP(pBDq(4>18tQeMm9{iLjE5XGp z!~A}Qp?GT|F(_1hs5GsphNf3rJ-mAOj}FYE+No_vj_htJ3F?a4{4kypia48;_$y2S z#+N}WVQAu|nS^@2l2bmgs@T9xOM!`%9p^IV;zH7 z0>rp+%r_3gDI0;12_ANK*ea0>au-V@LCl9`#{jJxY}6Anev05?_7V|s(u$Iyuhma! zSz(D~g@s&EXL-qq1JWqQ00+!*=?<3<)oa=2EOf262B#dQq$Cpe=Q#-l{5c+;QJefe zkKHQ{4!H%zaS*Gvs3tFwJMRwuYSB8-lsWQ?tH%>^Z#+!HHh3TD=n)WVIx(4~rg$O$ z;yHt(uz`%*^$^^;KGKMwX+699-BSeVoNM->+Gj;-Ojh}ql^>8bfaN%t2_TW6{UZBakJw z0fP=aAaX2>$k4ADhTscOuE*AVRh{^1_q_n|l{$|dThz<} z$z*Gz{Ur6HN25>-e-Je?HO2MP*(2We_`b2D%8V$laH&ZewjqE??L>-;TrDc2KF4+}T$QRk2~8m8dN8POj)7i!Kie?%_T8Iu z1GsyUW`O8bGnI!a+SiunC>TTqbBEvGh=*FzCa)Wdm`AZG!aozfeib-Q#;$hD&W_jj z>gT2e{xCBOUBO815V`N9`?a`@TpZclT&;ws+S_@yc$L1iI6F90glKL2Jh8@vT>DZE zv|m90rp?{ zE+*zb7)~hW?r;+O{rS{%LY3}-Z*aS)OH}S6e4n5dq?w_&^OCx$shQZaqbn|VD!6*Lfjdnl6`17L{YJ&wSR>oztE zcwzzS?<}|J9`gFu+}!L{oL>5+Aisly_cceT?I#uEYq6P`Ph*3-{8On0#uj2n?PtyS z3aP3ZRR&`}j$}N;Fb9D;*kb$*airIcRt(G`X9oZG;lt3tA~*(Hl(=|EMDUH+qZq{d z&=QQErm(PclR3{)x+tCg4iW6>U#R<^;QmIATS&+;Iy#6RFzFyS009+HhXc8VR`iw3 zV7;=3)77>G`}NeXU)}FJ4aMsQm2?yn-gqlvSG-)##f-n+Vtqtl)}&p*+?*B6*DRC> zgvN@})7|aQDDJ$o<&?zq{MD;h7?B8m86UeUJ?);JsiQMFB+t$hd1BZVK8a(1<gzMCoyH_h+8oqVbhEovEQpMtm)Xf=7oGV-73D9DZ8~ zj~!&@y}r)k8ut6J-_Ax-Dw?Q)0Pi)o_0-e>&V%f(kn0yulKUup&eZsHuZpN-OJ%G4 z0HuiHsSz)4-ImFYUr?k>uS}1~GMU5TJ;~SaaU3(CJGSTwy|gMOkFD0-Spx8s=Zmmc z0jOn(AkPMx}%o-E4yy_ z{$kA=^_R;BCC8_x5I%@(DfQ(_1jyjDh5;n_X>deg*X{pw#myZzoGKQ#9_?gz{MZkL z8_3hnVY`Xub6B=nY-TRPgKFgHs1c`fjG7wSTJ-b$7x;61Rb2 z3MHn6(5h25tKhNwbE38&SCCA%dNaLc7ItZwSfqp$C+iM7)BrR<*g6as5JrFi2DqE9 zfpJWeViYI-*cc(g;P&lYytQ7L0Fd#Y#ALR|RuSW?rgki}2FN-sw>HWQ#o;ZNV>wPX zf`Tg;9wA1}$Y{*So==9cvk-m;m=_$KgU-Eq{rdIL8)_CGyQQgl@dIqB$tgM+iB991 zO$*DBk|*cz5Kl~R&ttp$piFN7QjUcZ3CYM84rXeg+l(%N?ZJoQ?*e^6W793l zVBe$dS%af0x{l|kLvo+Ex7&7CR`TIOgBAhYEd~?>N~7zfqGE4noct*Yz*YG6E?v5$ zr>BS6A3<`)0?IA-ScNA2R@v|BoX>Nt{W;LIUx1zb>E*7Dj>|3gkRXl`=@2O?;^qlf zG3h6dBmtqr)-*9uFn5&aQ)1#T!82fS^`h|i%R85aet-l(;&eE@zQXn1H1Bycpo_!0o>p|~Pn8``1xrkLlB zm>*=~3z-AoFuBj^7I*HH?b$~z8>51$E&7OJ%r9OuK~Y}bGz9Zu&dn_?Rg9_M9XRsf z`0vGFbN}Y>Y2A1`V`9!-nzwXgOESm5k`gy*7Z{2YZyh0+KLD3Jf?pJ8F`>@nfBlF| z7r-orrw=3VdX?nP{8Ez=de|HnM`|%{ad1F@bmz>1g%`UJ?e27Ly#L8_+X*EXmROR_ z+dle@-Ts~WGuvj;b_C|XtJ2bVFklKXzx^8Y3(7ee#2jBM8f8|SIZA9vUfEr*`|k14 z`Qz6IQh2_AF^(?+xGgN)#2p9H3K5Bz6cG@C*05$1a>aF_2k)CaF+jD{Hc_qF|Q%vw;<-u5K#+3fR~44~w28 z53XKklftM7Bl+AKhbJyI`enGiCktW1}w4eZ7V&ho>}z+k1P-Lpq90 zCdA(Yp`xcRoU6jQ140LP2B7C>&z=$ZnSJ}xI;H@?p{*!NffYI)uaE^G0l-b+D`KNI z>4S;cW49RYShyd`pB})+aFrP(CNL52MB>mlze8w?LMY3W8K7-3gp3?+166ilDF_CY zY8e@MLDHKL+c#zHW_j9Ucw9#+xil|dlvQ8y$$?D}tF^HMud2Q>#QV|! zn|YJflbXgKJa_=IB4(Mdcw;_%j89@xv9em}$rGQ?cIe7n_+5DwsiIpjLYbROs#|_dNI=*Z#K-s;_4RFe z+|A5hRSo)#+>yACu;b64K0(9bBhAmtdwcpQ9Tz+Mw+3TJ_K=!^ImhnTdPgWT?U&UT z!@0I+zbfez{Ic!wuIhEMY)QBk9~2aX_Y)RQ`-x^iBqaNYyesfL{}b(Bs@0Fa-U|I> zwc($*3q9S;-zuKgeF*s=S=VoKkeW22d~E8ysj9hP1TL?b11w3u9+}-S~9rqe0*BI;D0imaqmtpfgq6v)IvrKN!ZSww@j##?KX8TmOzUv z3?-R$5-!;P^?BQCz#(t1_QC7}W3_IW93APQr0up+BKbo zU#yNGvQJG_l`Z5~VV)q~sJFjYa0;E7Nc3IaHQpk93L$?CYd?x?8z zO;!y$a&oS{AY^yGit^$S9~zJJ)YV8u=#-W@gzAb`eNJ3a2zqfsjs@|Z+$|PNv?S6RA-k9gP8C_lLH)?d8i4& ztSuqoK48xcC+y$rd1vc3+;SYumOt~CMz>D6-qJHRQa09cc7~!C!!2=GdB1iZ#oBoM z(^I+s(Az=p0&{xPwSMQzVFsq1UVQubR4sH zb3^%5O>kvX`A8!oDt0M>J5|u{uE)a<5ME_=81mDlv?kZh+b^}!*F z;m5lo{XHy57*9T_jK@XgR6*v~ZzYV!-8e4(7`Q`Nd@?(}&P}>m7CKeUwBl$Q7(iy= zzBu*x&!3G2Fal^@E)U4owfF>oS8wl!8}U%Ga)(B|JI+I$HfpN;C%FU>5l=RTAhr3Y z0-7Ek-k)rVC=R{fzArbN`hL{cQ!Eid6dPl?Ka2V%8X7JX`@Hz#<4d2A!Z%8wtpA!0*5_EdX1&P-fb zoHT?oO86E4yCO;z8cO1)doDEl`vuJ2N;2a5AP_yP4+zLFM^~G4;cVbf(UNL+%dVxD zN8)>X1v00uEZ*KMywC6B?Tw11qX+lV8;xcKQBI!s+;t*&_tFr@dYlYx;pG1}kKG16 z2viKqCaic*CE}e1{e+OT_HA$;V~J(@g{o<~wn@MJ`!)TDy($ZYMWOP?6+uPv3`ZNB z$-WJ=5ASBZDth%H;RA(^T;G}+M-TWrY+|05e(okX{>=vI5|iSuaWdyqo}rDQMgC>) zgo@l2(dZhU_)i?%F@=c*PwPgps{q8Wv5lF;hmo$a1t;)?T>*lsF>9~}-%(ZF*Wx_^ z%M&Kzna%h6af7)PyG0hlzG$%!T6`798&Eb3e1~W);f`dlg^8nRx~c&y zs9zLVPgA^r%m^}C`z^5Xh$*0LW0b1S0HT149Xdm3?Izug*d@1Bk31c=>}aGqc0r`n z@$hwB=xCBW-hi*cP8_-kK^cv78JJymYfHf7X<|J(ql{<+YJTiS|;+FwOr5*V+$|CrFH4x z>Y?%R>H(`cM_23lx-NInme`;~MMR>NNRg3vpZ|n+#r*PewnFdn$|ST%4!IF+W+o#a z&a4Qi3ud<*qxrPH#&&`X790HBi{c4Ah|ROfxOLCq+lzfgNl9ISr)AMi3)*#iYYV1< z0;st~T{a2H9Hmx!yrkgX6p6eG^WS>Mgp|=JKCqgnZ}IQ*j?J=BXG-%eY!*j*beX0) z?4x(HbmF9$DM_JYXTmSE%A+?o+Ordi!RiW1o++1Z;LywC_&;qKM&s$Jsb1&FWWsPk z__qGPY{xkGPo%kGai#-5RH}F$@!AmNd%eXj@GXw!Y!G|<3V+;s9h9|U^PQS2@juD5TV>yV1lJFL_O3GJwDj<#*BxG!YyY@Xg5 zH!Oa1;Bx&BBr~>Qly7atuhG=h1fzu5Sv;prN|HKv?f??SU7e!6ZcVj>u?3+q=*3zp zbJI}{vbNHzFRaLrZ;#dG8gb@g3b(Vc4kl< z^%>ja?EptWP@*l^*2@~B`~@$YNMs85VZHw6;>;E)pFTaS8CGF?qou9vp@h`~s}B-} zq0MZNW!hfE2!|VZ1Ej7SZYD8C9)wP1B;f5q4}{QCmo0`Md@X5dsM*WT%7UDaaK{r9 z|KS?G#Rh#T9+da*-z&2ZbUtD*n zW)5IZ8f?Ssg-mtl-nF$CXsO*f?V0$Xsoi+@=TAMCLd}2q>j*TA+Yh7#R!Hv(m}Rhj zK-`;ApV?sitd$YQE60B!R!n_KG$~jbam+ir)Ew#Dr!0{h;dt`x!a|L9Oj(6|`RF|8 zMxPgh*41Rh(_8CJB-E=#S4QSD%U8(RWMvDVf{Yh;esd%Kijsp=pxocVro zlQ68EbMr|>nOl`D1NY70@!u|+6CRo|7leu z{CIqVTzMDE<*)GEpE#fV2kR>Wdhm)JO2`F_jTa61KX6oIXB@kQ^e!XNQwLlQWF2xY zwcEY5zU#;_HJI%Z5n3#?vh$XOTT+{K04xYNF@Q-i%J_v?v=KW+MM()QDD(+X589Yt zUB|tLtUG{F5v4|xP0PnrX{Szhug{KqL|qpvn3U%!`Si=?8}2zC?t9N9)}c*sXkF^K z4nuvF*q4~|&93Wn0~LVH0N+iJI}QH|iP$Z+NP&9~Q%tqt2Y7zKVE!8^oyX&pB)6OK z%p+a)?AZe>RB$)w-nxAo85HPb_i;AGSU)exz7E;$1j94WYXW z3~puz48X0yGwHp(y@+@Yl(QSFkAb>ywZ6OtTqenD}vfcRk z@c+d$B_N=xs@nX|cS(p8MAVa!Q7+<&p$OvqDhex4-XUGr4wXsfb!nnxxvN($f&`132L(rvqxxgZQ&P@ca`v{4mwkBS)JF;%cGR8 z%m(1$_&b*${5e?wX&k=x1eF+ugmY}9)BNIjQgZSBuv(P6t<(B*PjOlKBA_X*6m zq&aE)q?wV&y}G)(`A>-kf@RQ*g5>+Rsw@~BaHSxhjg|EW>M+XnzJLGz3Sz5l z1Yim*!L2PMq)SSU0PFjicg|$rhXo>BKMnD6YcrkORSW|u7W;@M)~+>wp1xdCvgcw) zVBhR0qj2EJ6S)Fv%DPco#2U+&-9sAmrBhb2%<0_R`bf(%&4zjS-s#ieU9f*u8=~}P zA5l8t=o58Ffu62(cY79AB@ArScu)ohZ>g()ZZSz-@EJZfk$EF_QsSXzG2e7i=7ZIk zoxD%(nd?<&dvQM@fpyphVd2Af+Mbv^-3gCB-9JEtH%-WRaRE}r|C5Q+BM}4CDE?>+ z(~em0!BvM{1toMRW9Vn#X;5GQ!GzWyZ_9|-6|_f+n(iz{v2fou;)Ssj!WOCODhy~{ z=Ilf*WmqyWa!)))1QaNeD_5kdjTd^eic{a|c61dvJb3f~A_gSV4CJRFCl~K=$CTGG z+j=SV4&foCWnx0YAMBHe0JE_{#+XzI@5FUgznH`{ZPVEYI|CZG5U6KmwU5*bPcNL_ zQZZKf-B2I{MJ>MD*WHbzfqLU5oY1K60NBQP`+m3rD|i;Q2kwT3ERMZWai0>Z&zZ-! zR`oC5Z=rRH+pl(vq3yv#%bn_rpRgj9miA4ES2G}}^i~oQ9f$&|uzxaKv>5^-jC%$Y zm-0PXurR|m_Y4dGr$T;-O^<<7{u%620;p_7xCsht!0AFd>T1+`Ti5L>fX|iIQVo74 zLc|Pi0+#ni;#M^n>4BB6x$fY8i#fAcpZcGl4BB7ZwRU-WbTt$6tzx!^Lo2#_oJjYR zdxKfR5rY_9Vc|7eNs_EB9oIt8A~@zSn?d0~m<-}SI8UTkF}f^NpKVLla@fe4{%oFA zSNfw`tO(g$PB;Z6qL`SNJj|2J;7O{HBtLQlFF=5wA1>7^)!*S0#Sm=FnnhaI(cy&V zdU#Bg-dlD)5TL{82^t_ZA{wDcSnb<-UN!(*44Jj68knm4z@?q>>3$83v0U=ZyRZ*m z5;yW2NSpg0b%~IP?Pza*FJgb4I~2tG<;aed8h+3A`g-6N^~QG2&Kp0Mnx8q5p1x3; z-&C~pv@>p2(B@h0MwkJx1Q(aW>MsHQGuj(>Yw1n9?%wHGs4XF*i^Ng}CMZ#r9r;C< zPC=Yb0NEWL#Hmyxa7x<(Cl6j?4UKnT0U~c86bI0|#m=oE&!2KlR7ykTdV2!I{$^Rn zo~J{FB{11#w+%wquWW#Ng%ZB@iO{>w$|ne@_IN! zp(@fvFohv9?v>dfXhfm7BJjXuZ}Kqxw8pbhL#HXk(uG+C)uBDME5K)IN@ZATi~>P? zeU%1K#z95{EF?kId1q){T+l`RaEi0VSpKJ(e3i?}39(-HA7k%ET2w$4&sWyRy=SpA zT$)V)#FuBl7f=N@;84_x(&4(|qC`5yhj%7_rp0{vgnn~t;ckdOVEl9Zq8mGoc@VNB zi2adr1%wfC9NOIQrS~j2VEIr6WJE~lf5?IaC_>iQnpEu2NY2RT=d6C}w^G=3-aR^i zH4x&()a~9!CbbfmGvh*R@ASh6@ZrN<`01DbOb}G^h~+_G5!|fEjBx(Bw6X#zKQa%v zLlN1f5T^n>8iA4S^V>sQ*h+kSeNj>cF?d&=^&sKkg>YuJGrI;5M@>yqUfxdQ%jvwFb}2|CX*XvvFfi zjs5)jdEF?|RA_v!#x_`FsGu~(8mS_!@+LUUjI%otZB67k*I^Vz;KTx8*r8GqoBux- z!eeB)=iBVpJm`3?XmmK2QdgU1cs!Prbm4S=4`TAciQl+^G3L2@o05OPDwR)XfFxs< z@e7a=s4I)E+KbSTrg3DJF0DgF`Bf(N94IM-r}M~xmK_6_Ban`qQQpTNl z=cJ{d!Qu#I3M1p+_4soLT}00kcw026UTIo7crbi-bvH$9<=yVRfQ#lGHotxl(d9uO>hCGxhlAELG?exv`7RhIEMYs} z4)J`w3olrKvq4c?^@WiZhxpr;iPl%ojL@2Vj`t|>!2^n{Mr2{Zv(ob)--QcmT3T3b zHC0rIBo?;%Al*2^0k;rZ3wM1dus$-|muj0mG3ha_1Fh7zt}plVjBkP&Vi1~nQ z_vDh|jXx3zjtf5wrO!S$P20kt;9#HypqMnp+oV?g4};nhn}3GhVBM0Ukn0Q??E<_a zBH^!JKQ7lph%fO|G>ItNK!}il^#XCKVAeS~IYmSY@NSIkr^1|KVUZ%ujKI!%2<8{T za!eC$bm+Su&2&RlNXfu}PS1zyruPl)Uj8}%wd>;M56$JqRn51S$HfQhL!9EcPM;>Y zKRC7zcs~!<(kfh?;*;FTTMv}Yx<0I?yKoktEtc-LCkmj0h6fZs^h9|0vuA6sUcde% zVDD-Wqrrl#Tto>~3;_H2j(izIL!6bEcX1pnudHBwL;ftVS`^EHZpqi486HOb67~oL zH^5Vbb)SRC|C?=ZUr>gr?tI4TWN2xW5$~3^fK^Jhy%`cKx}*+-=o*Gy5{Rg^y?P9} zPrhm;HpA^vjOQiS^G*=olicm;iV81nPoiTep4JVVW_T)E+Ger-(Y7d&^#JiXQIvHZIfFrn&E?(e*LtYT{@+}wxuM~{#J!Ff$uTrSOX7i)49H2)OnwDe zev8X1JouCDU!AKaDk>KH+`IZ3_}DnfLsNRCQ;y}QB`2F>ZA?y9WDns#PKKJB ze=y4j2e^&n!p>-}SxGBxRF+xvjWWP5wnU2Ch-c*bD0XS zWJY<~X*3Pd;S)h{AlOT^;bQEc`^9|8D=95ag~-d%?#&-P;nNh& zgH>+ES+IHM*ET<`FYU>aX}ZDkmyH@}$y9U|Vh+8CQ3MT&$q5FuFLAwiSP-y<5L_Rh zJ8PPUa5ckz0Pg_)BB0M?tGZb!jlUoTL_(q$Dk(PVzt%Urm590A+ln?SIQm?R;eU%H zP!;x_|Sbz{1wu_f4IrmkC_fe zYv-g??@y+qk1#Vygf)_yG!Fb9a=0NRZujeb&NVhOenatEpp*08Fa;r6T9{D=ZHoPw zc(gOW-A}HqkvGuQZb@7!Z7H~jE_Oph>7*9qZT%KEiBJGgj7o^Q(JK+Yn8oB+{?1qi zxbF;m@swOH&iQ}l zr;wA^VL$6UY$Ey)Fk~XFi$EF>jDK&DY>8A6Ogji$ zantQH)QMat4!iyW-)_)-#YBs!$4sk3KUhsl+PlV{zg(W{KeX=&Zn01NP-Xm^3A@wmbHtSQ? z$Rm$qJ02^4_KN-D*V*mJoSZ0_>^#OvLh|zPxLN@lDch-2#Viz*jltJG6WA{W=h^@8 zEnyB`GHi4i@ld?$$M@!{!|v$&p7W)qsl`?!5j;&nvreX9ertGCo`mx9@pZInrZy=)%-;6*zd=F5A||FC+kim{0qLkVc`~bk z%LL&kHHIg`jSLJoNahO^_GGk!v>Z;M}^fny)`-!KI`n~W>}Ez^e`hcH;? z&^{uH$Z&MRsU!eF9(=?Hbs)+tfli|46DJ;CP@sk|W1%!L|0E)>sb6-6XVf3yis#Pm z&a9rEnRp-8Fq=6Mp;A+WMH5PYDFmq;{|%u*0BWt4C)ALKN9x5)>9gciFZCaUdK4ra z9%-Jtc4S0t)s+ZSH(NF^ce1CS6_P2rfb^b&B!P?Vkt3 zuKL9574S;vNGzXT-k-mJA9Z;}#i0IT$uMj}PnwZTJUBaBXUGp1!Pefr7l|&{$48BP zkl?z>)_(E^B#*YH9KV14nwin@%CxrPd`vY*dyWi7JVt|EzpG`w9IQf0 zOY;DLRQzZ6%rck|Y<73t5CSN5+)3;MMwdK9Bm4rRf&)eP>(i3Q!!J!dt~`}FHFh?T z)k83LE3~P(c?iJH(2yMxuYnks>}*Ujxh*xo34D(FIuxRy*k(2UqvzEtEAu#u#9BF) z3}~Xcxn~~c%mc`L9~p_LGw8MXjRjjrxVV%i_eZ^X!$RW=1rTl(#Lfk7 zqm1zCtRUtk-e+h@SITJ2a>)x=&qh;Ip|F;_27*VMun4-iEN#B2DLjp>MUDMfMD1HS7J>@& z!UbILB0UOj!Q@XYUin`OuE_%c#?5VkKmzEIY-}jku0Ao6kG*+~r9gR%lVZ+G${jXf zIhJo38uPOL&2ICRJW9iDh+ss}djC&XOl??>QAljakMCYzUmx&@X0p3fA9uTcHiC#E zQD%3Og>sMN35e#x!|ALvu3mj;r>bZCMPkGP=DdgBVzaW|)Q#eZiBZz1}}Yq&5HgY^u!2=qRF(pVKs$WY@^A2POn6g-bd) ztmrIiE|O2j7VCTl2I&zQ0|gBnp=+*?SAP8`E62Wr)qSHREkReXV(<3e5YqcrR&!L} zGb$5Ph>*`=}UT8hxqx-PtB^##1$^9IwKP; z7vkc2OG@BiL0xQVDboud&=4@=>5uX$8twjx?6538^MLn-fJmSmd_7B7kNZLhBofI; zMRiL@hbvUxT4Sl$#Uc6Y(siiP8Sv^37X}2>5n|z3PC=~8UHmqEolhvaD|fKZJ$kc$ z@mu6cPR3Bo!(#Ghdz9R^Q}Pf}K9!>%Cz+qbQkFMqA)Cv?K023xt4wE396tBfk`Rt*yD(K?74ds z`T-0O(9JTf)VaOGnuJLaZ_n5m8?(G{Ta}J8ga%jmf-nPNtvLJa2R@dA^3XTEti1;ZUO-LL`YLNh@~?}Ke0q%h)ufg-~*OhE#g6o)Lf z!!j9O><}MIB-B_BZB#G`$jI2oE2VCgOYWt-0kV=&s0UgH;>Po+RWM1s%bA27*D{GE z_w8{qH!_2JB2;Zx`1#EOD?gpC z!G;D`DmfM+BuH5agD``&oB2OkW*PwK393lXM$D$nR4# z3?LdtSm-?>f7k>N3c>aqP&u@**ksFc zX7wLGCfV`;eh%}bkF=)s&B@tWR8DDc(5T(s-5Wd%maRl0*{61_B)EV}c0{sW-083P zuaAFUCbAckg@Zo*2bdsT{HHDf?$Oix-;`2Y3)s;%Z6SIW5AT_=aRavZ6%URUiS)s2Bh`x47<#FAv$A@C1W`2ec#; zTV9T%9P1E%$>88U{Bq1UfT#`9+c8?fw*WpUP>wM`2u8|pf6+-Ij0wD|>VS6zU)XPu z&jb&)Y3tVxv;z=0H{~ygb-~huj+li4XLo~-dp(b9C?p8ZS^8bRw6z)y!xkJ&WvdiR zT>oy(-J?)zAkOvRzHi6?*oBx8c)xjP);JtYkk#?=%^#%yfSU&sRN2UEZbr10vK^aX zmW89yOym`N?;vM&lS`c+Kjt*WPfBi@*>$WVR}e6~#`&Ly8F|8Pp9e@awX~eX7$JjQ zXm(*ik~zL(AT1~6(QSLt zvXp`0q=G&_>RMIyjzCn2cmTMSj)nBUegAqNH(gBXM*b83&;IFw>7G}iQtv@+Qv%d}=;aj|>P1pk-h zN^Man^y9rC*3BI%MB;T}VBkV_cEZDlD%s(z{S@irX9H9dyFD5()zCZ^SE@Nb7qH~tE3Mk?u#RedIBqHaRvVdUZtZa zPITa{LwIx6fyFo7g7RH%Uw<`?HaG<#GXgR90Q+l%{D_E%5W>@LwlesP-OZpqV`Kx1 z*S|Ap>OTtH@#sl>S`OrPy%E>I+_yug_`)g%;8Ec85ymsy+WJg)d+byc1)m7NFO`*lsf$_9vnA^uL^E{RHwduAQb%yP`g_B8MM;-~7t$$qm zn`|O4ilQX@&6Qg4iP%W18yb$1+CQn#ClQwujHno0>@X7q#zW}?#S&1Cx>1+KJGG$TGe?8lXL`Rf1gg0<- z6c#3_vL8Nlh=YsE+`JuG+QhWmJ2DE^?<6dlu_+Jc0s zUJM^Aogb@&1S65>RA=@iVd1?Oh>!+cuy_Uj+;C%?BW3&(hth5QAOW2EQ9-JT6Aj_9 zN%l#(p=JR-etRbBmT<%8I!tO=j_=HQhv)V-{ww{0Aq!vI&tV(P=^@uIkLMWFLC7H} zde*xfT<*zy?UJpOWB4;3*B>GG-s>q9B6fGIw>U-D9UqO;a%c7?4Gn0*$l_ug-FWR8 zsIRAIb9qcAci*eR8+1w;sQ1)DCf-bRg?wXndt;?J(w{HdBWT4GCav0iYq)KqO}wFa zOD`=q3R3yd&@0T=e{?8st8On@;BiD?BDuFnecv7tigMTbw1|iqOAk{h2r>CuxRdw2 z?7N*=r!`poH|sG*3ooh5F)H~|MrXg?Htpis;2ERCMC5GPAbH`!nI%dQ14!2yk{P~c z+GK+3INvyUkR^5T_TG-7v==WZ@K|6F$=8MjWlzpu9F^rS1%!*7YRXd%cU>6emi=8P zX<&1bx~ipRnB&1O%3IH8G;#}_avdIaLWqMyhxKgKuaE8~hK8;k%1E+SfD%2l#_he# zx~OBg`t{c-!5=kA(? zIgr$8TSVpAv|H{$&_dy^ME+-y*xd5+F_L`%PD@3W+J67}gLKR|xS#j!!%PfTbk}P5 zSD1Y0Ojjo$NtEh94}LAKaoGB<+@7d3V;4HY@YikubX>i4{Q9IYPxBvM4 zN-Az-*VeQE{14LI{{GGQyRyFSL^avVP(`EseWA0U_17;IU0ny(VE4MER;0ljJ$Mv) zsf^+vFLmQVpJyFiqJ-k!KsiLEJ5w^8Jo#@`_1FrOk{PTX@GhB@bjkiL6#XgsR96N1 zoNSg?kG$~r|5HCF{wp-V3{dSL2adj_Liu>;I}|C#(-Z#KpOA9lM`4!r>75>yf(=WuQr6Z zYIJloH!BMzf}reh9$}`(_c1htUeV&>WYsgVFl1bd@U{xSjE}^3n1tdEUyRP zqsf1Lo;ETvKY}M;Vf@td%-xa!kwfE~J$7r6s>QzP&xeBF@2dp4BwjsGy{B`}t!9=c z_+#A#+`NyLt&9xnJ1k3kfP7xMRvnbVO1OC#@x?Tat0cgV<*@FwVQXXZ=fmNP5HPdi zVZ&UNdqFaxh0vRkkZ|o3b?3K%jGn>>zgPTiU#kxvinWEb>WLf+GTGqD2iuXLDk3b< ztf9k2Lo&s1^0nO1%d*$eW&h)r{~s+W!<#_w(%B9hy?3PzA2)wr%$l4oJy7Z?cbQZ2 zxPUG|f`3+cKbZWDnYi4PQBx?-B9z#SnR%v~GeNi=kJMWCgJ0gWOT|>a{ z`Q-uEQjxaOS!u0HR@Y4BximaXvOD934bU7lMv9?&eZ`<@)O+;m%eNs$y6_-nq$+7? zXq*?>@J)BSIo@7fGZ;~NJj3hl@DL56n*;=!S5^ZKlkF@O{HV%SR4i@3D(;Dr8N4-? zmZe3xaTys4=M=*kKZEY#3uwu?x^Ht#7|MlloQJKlKAkbQ+99Se6& zAwFP;$JavZ`}*nztRO>yIpTKjsx&qC;R8yCr#IPk|8|E2wpGY=1;VA7r38 z85yMD201wqd6u# zQ1(OK0Cl2w1*}&gZ{B>u$&UO>$hKgX!)cDW8N@<+dv}37`ab#(KI^~Fv|Ry(BC__l zbxMrRo^>tmPK|Kp|sRuqtSWm>ob>dVm{%bzLA6L;YClPhvO&^F0`2SHCGd$af_{%Xu zTt7Zk?7%e)1(!eJJ$-0l5ma+VojiTBlY`r0>iqcDa5G?0KvJ1^1sAP!^WE(OrENNbDGx2e++R7Y^WawA5eO7X zmG_f}J{LhOUQdGL9Qi}u(olX}&u_)&gi>jIo;bGgb)(V)hyL2yW0%p-@rCnit+(%< z;N$bee`pNKEVKuxE$MvE+cJ6A*w~ zDem)UR3bm-&;9h3ETF1sd?~K_D-@xqG!G6|dmUxlmi~8pTAay^&)DW{toiKDiPN!V zw7XWLn@TCC{k&y7ZmObg5TbW@EaAa{Z}qjDA<{^K7~2{ft+%uXM-Pl{2}ZG$tUqv5 zQ!{AQSE%N<)ZAPA3T5ZYd`R77NQ{;x2sD}{iFzR0&DVl3}oWnmda?NmetAvND zM0}F*_#2=U%SkNn?+*-uS=%@ zYvFpAm5~7?0w_p>)4ki)od~xm<`SEHF@AoVVK-mho)97Nmv|Gg;Xu%bDo7*?13U1j zczzh_`HSvbFyrcg&A_Me@dXUX&UeqIj=9= zPf*p=)+XD!M9j%$PcPJ(s;kRH75pwpiiHy6Ger?XL@+Z^=;DU~;*a>7ljLY7*&g=U z35Ojv{e{t?o6|cPo0}XV`Rk>!Lf5We2R~_&?TjQ*d}-%i=EmB#H-8?fuU^>ts9Vqz zYY>sc7}lHR()>GRe4;oZvdTVUW!$3ouwmvLGIal`i}23jJi_G+ZVWEJt*s|>b9x74 z2XZC9&#arw4Q^*L%{02ZNAs~1l@uqJBqdE+ALMGT4OHeJ85tJpQ-Pdk&fsAOi1;0_k~FhVr2(#x1Xa>c70;hX@h9xTM+oe) z#C09=OTu8O!HEgu?Jq;JnEJ&(k#y%Xt7R{|lu#&8Wk212l#PV$@Guxn&;OA{jz!T& z&00JdK|p2C>g?)OS%*gsNXdgS`zVRAEZb^#OAyy)P-OIRl6?z<0kqp&OA%Gr_TUF| zJpj}IM*?_dAt47lxJi!#+nbuw#=M7vyu}2A*V~j%3~pdS|4%cCO%PWmhha7bIs_9? zkhr=PH=Bgsiw_Ej{1c-xe&^0ZHMRSLg8|2XGttwVqFWwO-!;S7eH$C`C86vDM5 zfRmm$De-{uhy8}DA(v!KK17biBwLd`1o@ZAVzbQ9nWLTf;>8o+w-LF3Fi6PD|A8=s z!qxnCl9TQes$5<~j6~mTfrO#K(#NNoKmd8{ZX?0l1+6=9GM?w-!}tC;QYhh6joGCBfMixz$%q%u{f zkoZaO2j1HGeUFtexp~ORp>PL4f}Sijkte66zzfBRF8i#%!QzMebjD{V?&Ncnyodh@ z`czQYafvV(`&Y$%>*wSUbuv>J>TfsJ8B}6;gb!0bq8;Bgb0CRvD13+bkr(gXW8f+6 z);E0PG9(u(&3{)jTSoBLq}gNB?9Lw>Hf$2x)7$Ax(3Umpvu;A(fJB1Lxi3v@$)ei z@W5D3*MK$d@P{qypUs~YPK7oPjpnqrtgo$yMf7B6WJov^uT+TJ@@jAP_Zw%g26ohOD@t?-%)Mp;$o_)ITDad+G@@%C)Yqb85>){;=JS8 zR8ZrfNlfD%fjwe$f>AkB=L2TpN9sts!}Owvew!E+7Q{E(%`W>*v%JD}3?SZ=v} zoQzdaa3!#$db_gHuPbMKWo9`$o1xhRD-TdYyr;nlt5gWYhFla68!fVgK(&(*BNuea z`ol5!i=^&!#JiXZGQDqql*W8!Fy1dIz6yACdyBopq?;Vn0iOLWjg1pioIeb#laotd zTC$!uZFQr`w>BE6lC|Ib<0qmLA-){b*} zNEM8Z{-5DakQ@tua-0RPUn6)3HGD9(Lh=bLJ;!bVuMyr5X!Ri;gwzRTnlQbdiBCnv zlZQmM3Pe#PtHaB6 zlw`x0PWYsMr2!UmoFI=dnc)SGQwc*K`j$NK3?j0O@?9YT0Zxw`(B=4m@J~xKR}b5S z{JO(NP5DBB_^H3t$Bc}{%Yywj=DC=3@WbWgsGp+XTy{s!DQrq=YUudGBdgqkIwy2g zLe`tqB0zT-3H_jfs3(v$FgTCwtI$9B-{F+Sk&FI;ZsvY9$Q0{O!>0lmRVC)st%R8Q zdHDdMpfMZ$EJO;TyR5FRuDW_0f^ICy9CG(N5Os@H8A{Q2%6BBn^!q(1uxd*x;5l7j zMmNUqu=7dk$wUP)fq@N>!#%!T{BMNNI*;(5_V%%v8TaLh7K{L{2xTmD-ol}ZSsE@T zrSp3>41vdjeZbs_{1@yHoj3z>@#puMZywDvb#{i98Rb7%a!?F^a32w=*T=q= z)kTh^WWU@TWL@5HS)2PFeqq|O|>x{lNUK5>yMCLx}09KoAL=ald^fKI3Rq)sVwvL7uhh zujm&bUN-Q>*J1+Kxjav1LP9m{ELDThFZxJ-RANof7z|$HqyuFXkBim8N??34Lge)6 zW%{bxQzr!863Mf&i2pK1Cz1vsWQ+8lHWD%n1y&$XC<_|%fvXhk6Fnp2%(%t!icL(z zQel(tp;yF;Ms8+ilpoYLDupVv{KtMPyXlmd-;zBt+F*S2+BNEJnu<{vT7{ z9nE$7|9>Y*QbuN3NfENkDkPOqBw5+no0LtGBrC~YNs>)6A|bORTiGOgWkmM(@$Pee z=lt$-?)%(-G3C0=Qz7jYO!Te)7Kn*g&Kc(At8nGCWcOcM zl+c;}tO+1Q*27_g69zw)7cYh!qJ~DvBO>;|@%G4nWWfb9GS2rWwLfve`#YbTo|<|n zYlt9c4Ay#j1BWt z(ZS{wGt9ukV%l<2-`ihjCx+Usx_ViB;KWIDw0s94_rjolGiNS>@ z121A4E5ml5zi>e8*~+N+?CW#d8mq5-wpWsqFY9O_R1W?sjTvn;mLLxpWsRuk>lxJ1 z)djZ&8iADbziSV$#5Ira&aA?OlAL@L(pub1DA%STJLq5LzM2EL?bk03RAR06JL9gC zkdy@B3HAlBCe%wM(HNX^Hj!yJMfG^@VrMQ3dRFOv8(UkfMTCD2y43FaH*cy>Tqxkz z+#F;HyQf4wF9plUq_!7GZ@n9d(2#JRvzGAILuAEXU+7oDL*kGl)f)jbwIz(~N04mEE(!CJ!NlX1UuRe=t@61fo$bk&3d44*aSM%!|?wfC$Xrc61bykT@Jz%Od6B za^<*3^wqdCIPHD+h2ag@&W?$X|N8ket^o{#2%96+zp0}G18>Z&Vq0WnqU2Ia=gv+z zuHE|yQxNzDUn)TG6r>p?4U0zC*-rJBoVwlqO+qNs)@?m%9JLVY$UH);f{zT!0djNg zaD%j2Tcnw`?Cag`_Gt~4bno(t+^ky3Y82J|VJ+cb4SYNhEiCxJPGQPmAisob2aXp6 zQU}%&nVB6A`;qT<_j}TI$M%5xY!u(A<<%&29;E`M{pr~rKaX*hiex_W4ORMWo& zLaAO}K*55Y2|-hD2!)KKPtZvKFbaT%<9msV>ukoFxiV{FXFqLti|a3g z<~Y08anXPM{lqgn@%Sll4wE7Y>f(uTbRWteCEvdv)j{~Hhq1e+;S)LQW0w-Y&K2@3$$01q7bdl=chz8VNMKe96f; zjPzv;u4uf2-Vp!b2*i#sHD!r(M4+lhj0J=dA)$z`R9fN|c*DTfn4rrN9$Qj)L+a}4ka?iR+XW4B2(#qMWLgp-7XiJn5Rm|Y05kOH z<9`I@rtQ1n;K<(M!BV#fB@RrYhZAmSW{Eo8szSh4n^NWGW}i)9&Z*0HLnb0F6C7*! zvukVdHSS_GhxyU2{7)Aw;<$m~R7gr1JjP$L^YrBxg@4GS-M|M68=I|PS7RaAfie)% zR8G4vqja0HiY_h5$=)WfLztW}hPB_hvk((=b9T1y+_|%<_`(Zbyr}%AH9}bcIRypG zMA#IN`*rBXh+zV&F5_u+GGpnkh^CwyD;g?s^xb z&P(TtnrFD+J<^nCl4`k{-?d&kk9LaTfC*6A8> zm0)7}S+ft%3SA%$W<(dpD6K3nXT5pj^1$kHnL?-6vbnw*O-ZCr-!u5hMvt3E$-UfI zN}ASlO|^134A=N4eD75Txc7*u17uT}=Le2UO4OyjjubuP$UzOAclc)r&j`84q&Rp1 zQVN_AM7;z6F*;+1@FIoD zHyAsj_^mA%-x;vT!0HCu_43d0@yQ(>Q?ZB7_*a{TSDd9SwP@}b^S!}3+pb%xdo;p+ z4^g7moKMyL+X5_5o3gNAcRA><$ngxb>QynOvZ6g0h#cf2QwNS2tOmBCQJ^RSll zKUFQ@Pl%d9)&tzi%cxh&(JC;730)&s52b!+8peLDyd5F(JNFYC+qSa`rhnAoJ$oKi zVA+{b9jH_4v@ft0U(cqk@ZEoO1FIR*U{P(#9u_Z6kasj;QYHjs6x;Tb`N-gcfvuSJ zphBWqqqVCo%>+2#D8>EWJ)DLS^&_1f9lRCLRKa9{-fsX47&TwNt{WRWOu{)` z;CcG;HIw)637{}Ge9TKQppQEG6qx{)0&lZY4KfZR;vS+Zw2U>ci0X^pt8i<)yP8iX zI^Xq})YB;eBbX-d3F-hmY)IkjLen3#l^b>+gr`I+9Kn2qd(tF9aQrwXZn8c6G#MdY-~SGb@o~zjTyePO>3Q?Q?bWsE?rEvuA3HaT)cUoxfBqmK`f#wS z#zs5M$}yi2NAHrEX;PEaR~(oKzy=o;~?VbX0g|8 zRqbVELXiU`V@Sb+mQQmi*CU#+wVi#G{|$YzO`ql~locKyyCGi}neAR-d2ruOdX$lu z?d#&=Onk}Mnius278P7u$Fgz{(R8)P+z`$ zsgp3VznP;L`H>?qsPO>G@~?&@AWxH*oP&fZ#IEZ zZ*In1g*Hx1D*~tRY>+XDFMqMVo|usEzA!=@CRW*GoL|I5!wByHB69D6?8QJ+W~?Ll zF|Nmwg@TL+W*3?joA?!uxBu-6i#4Ih!T1&@y5Y4l81&=`#wWIV=wbolob@BBH~Mp! zGvWmGf}5KJ4iI>7j2c;JAIbFPz58Hj`Gt_pPW~@;Vkl4>FhTV&K6to)mIW;r(X=YAM-WFk{r&4>EUEiAxwG=2Gk8eRiHpwk*yzJJd7~bXtPZO*0Fb!dPumuRQrZWRFF9 z)Dg`_5dJ+88>3aa8mxQ`IinjaX9{-Tg{d$zDM=sO4OVxI7>@_>6yWyY>G_E395V@= z>)k}>-xe$(q{P;(G_NGO*2u^C1akBPZ+@>lD@vaoUuq)jj7=0dqraq+T-5i;h8pEolE_A z4YVL)gWl#vu?k2^X11CGzsAXgcNHJB%b%}f1t#dqy;+p{EFoj;XUml`VV`~ayxx}*iX9|RomZ(LGu-Za3l2^*IjJFwd@ zc~F;;{-OMyU$`Tt^lvEveWN&V0QCb1mVkSWNy2FY)$w}R3|mt!LqLQz47R|Q`U4CC z21EP4hJ;Sj?bLL3hp4zKj@{&8LGUwK68JVKjx>aAf3za@o=mAG(4GGz~ zTiTlF;-M#0a3Ml@13AAlXz0UzUt7B;x*pk5K$=h=ZfbgOYyB?b$*BX(MJz2o&#y+I zT@yqw@IGf!O^T7J&Of#3Ytyf9R#*%k$6Kk8c1u#M236t@!&)DQwZ03x-doVDdWB>0 z<$YZ3GGF&2^|aL-9;9q_VZTpAG1fzc-+KnV%6Nnvt?v~j=R3H#pq_gw;wbm2qml(> z$|+6<*(ohvzjmJQFB>2F?|cfCsvvEk!+n{VWR=S|+9g+&=KmQVu0c0U%eu*i+Xb^H z2sx=Fe(C_3ygHzBy1M;snQ_t4V4>EZ9*nUD&4-ur{d+#a_fymJx^{h+r~)*fjv3;I zZf)(c_9cQfSKnVI`6MGF214vdn7+|!ELyI?(|~T9efxk`P}E=W-DS@grI^x+Wdqzo zp>{SxET1aidy7$WwEsmn*?T+f$l<9NB|f6yL%&P5>qFirN{7~sBnvR$1xQBF9Gr>> zNKdLYLR=*_$*9IwbG)SQ5HdJbsRj%{Q%g&yB++Hni*K)K{U-xb4(h=A(WO1IVLvr;<GP^TVp2;o-QDOH2I^CQPjxgkH<(TKzpXYDz;lM)PYNISX9B93=v4Dal%m zg&YL$oCTNx92eQtY?SbdLt6!;x_TIjrpMu4Ov6+$E02Y4rIn->;@%>BsfvpG|8Db& z=Ocw09v?i&TOmFqPq(9@qZ>vR0R1{6!Y%lS=*O*B|y7g1#BYB=ZdSAfJ9^+LJX z*}7}@>s16)e(QC+Tak5j960x>U^5K2Gdvua!t%SV`J&219->Fx<~u@lZWJFeoqI&B4cl4#H%guG2A*YGF zrhcm%^v_b9e$c$RjSbojz*phhxCaM+0BC9SG03n>XiGTVC>@9#Ko)1n z#nyWUFT%eK*=(>cKXH%-{)5Qe6z3Nn&&`yXODgsv1K z(-31JKn2zs8d3N8Up(caH#Yk?sw;kveKzn=wrLkdv=R%^Fs=z|DyqYjL)j|wwMJBk zCvkH6aCbTqynS5Lx2C2}yTr8Dbg&tG+t0tuS1NU?6*y>1%Tt82nwjnW>4b28J43_# zv+-^L;Mt%y#6C+ymQM2wLo+%afeR`GX?+7;0WTXg?RV}7gJBB)OrhU}@fk2DW*>B- zqd%I=kC!ep<-+_lMXXSzAqD%fWP7otKJiJ(`IZ5X_RTM}+=0kH({hSzyYbm>_%gX1 z4FwHF@Hvaz>;Kx{00ZL-^6j)%QX(%&#nt&yFX`EPr{6z*FxZpYSnG(-t@0aVO#wH8 zAIm|1@3qk=xW@+GSsY?008t9!^~Imtqt&314Gb8YPF)b4zd5^Yd9OY{Cj0VTtJSHN z&E!a*qM8pMDu)bkx&lWc7;eY9E<&k=TO2D|lzz=F+%&)<@p@z3Ek*+RDd{!MnhK>N>da^sFI-@;30#P4Xv#De=(ljHlD6jC)qkh*7d^@j0_6C; zcTU_M`9`nT;5J)0Bs!=z(+8Zy#^QDg{qA(N7G`w>`=AO%OY8HCcHREIXrl9%ZRZ+{ z*wvktmBA)MFl}=+SS{J$I#<TY$DH277!5X&zoKoNyBM^SfBg zo3$otCxTAZ#mrpmgm|WW&Bx(~4*Oxg$Cn3W0U1fWt7TL9 ztajwc8S2l!>{YlP;^<#|Yy7HAa#xnPYVX||}?gvDhG6IZ6&jiZ8QoUYOM76P6=JAL2k(~C&TcEB_Lof-H1>Bhc z13vopN#(y&m+Dq#cGQbUn#Cinwgse2gSn3c%D6st(9~p56UYHa!AtIR&-iJ z>?o!h+=85(X#k&x3Ec{C06^1UhS?X&eLUhw|A>!g`n}&|sMrY7{|Y2O?k0)Ucbh!U z9kJd#6OJdpvT}z6Bo)9(8MYG0V&m*SuJzq%w)v4a4D~qRIe@l!Q?Tpsur7s0L#I|c zGu^41xx44jy&h%A1U{(@!c6l}jvGLeqLGfODq^6B4!AXbZfx8gtbxU=@su5M=+4&& zU=fGx*JTS1_^R4d1-ylWA92*NAk(o%eIdYL0DT?7ZMr@S{9K3U{ZZ#&~fGH=;-9M zynI3G8Q@PYksd^~V)OX)<;&E-xwMOg4(T6mX=*YsGG6)G@Ki#g$mU0j!^TR@PhGr0 z21S`KUKpfbX+rT}VC|GIX(yj$p`x2x-SV>Wl`9q|CKtWE^;OKNV!pBug>i|jCHh4L z#FS;mWg@*O{4+=RXCy5md~5h8yByoA)%pE$>~IaRQ6i=V$^$SZf!}1?o;rV0nwh+| z+H{>uZp zPgIldgWXHaii7kR>n9YC1c%Wuk{ih8GMbxAu5*3InK*23Wo1Qqj|rAXZR3+?i=l7O z(Y&drHx!AC7%XY10ZH86Mp*8q=Y|uqoIB_G1<329xy&JYMbz+*0{NPFcRI4YYK`OW zDbB1{Z@#a&cefBokjdz{SwxikUSh<#v_zv*3Gr>uA|lX--PO}WcJCX@%7+{~^M!a*sJuZM>hIB$C;5y0 zWN@lS_KuWnIC|%9{uU#`XW( zKR+*zjha+Vf;prL_lE`NiP+dUMG96u0U^txx7rdrP@=)&it7q(89<-Q-B-;;#_(VI zJNY)4B4YN$@hD}#N&oiVCE2uJA|~~C1fe@VCug0A{MVFmROD*~j)M8}G-07HdIgt| zL{MY2D=uNF_43UlqUx`Xzu%~5{VU;B9XX@C^3Fy)tGDD9mhj6dEuUnod*~rQWCFRj zv8(Co_bw~nPi47re>}Z3Ih|c=8tOi6%IaR#g$!U`WMw(%+BMV$POf&Iq@ke;EOQZju5b|)1|3~wWTay9*P+x&o{Fj}1^TFuQF?8R zjD?;%TQe;xnU|3Lg=joK*lW3tBm z5_sOT$aP1!*+y)Ad^~R3y2H*`q=F$W&VJ*}CFdc*$;arx|DM3le{XypeB8fA7 zdlphu;v;gWJz8{6}}_ty6xKSYJ74^tUZ_#hV#mTMwr zV?)DTE>epwXMrrKM5N+K_pl6*15)-tj=j_JG^t@6>}u#VS(+(8!UWf-V~)(z_;~V1 zsNLmDsuw62nh{gYpKKAh)sx+R730u~MWJqLYPI8F`#%#*QT76(a7)U*4T6FR#4ZWqu0S#p9Uo-U689{MzaRGrA%q3JzOw6nm zvT1X(of$ee=KBj?JiVeuvinIbd%kAHIrk^q+s?noFjeQBMBo8X@haOSc@CpHV)A0~ zk7VAxEA*K+L(*ufj6nNf#pb5Wz+FejPe%FHXHK0fXeFVpHE2Py2#lY=Di_Q#tnNO3 zoSl<1M5V#BfZ$oPwuS~dv>qg*+QItZ+BWOH=!GwhvP4zF9CBO{J+aYhXIFJn!ovI` zVh$*LoRyjBQ6Bm3O}FzoCoA{klDOwU`+(2m>f{$-4?#-W@Ubx_^oejzhLlhQtgO7>zBRDxxSpuf$+*vGxQP!Z-jE!bMBGX(x6+Da{LNa#2GHG$4#bCnS+!fKmYcS&`e#O_!lbf?i)XA|5QFz z-=F0XIh_Fn6dZ%+))tPt3l0vuGu0=9f*!G+H9x{odHXjx`|bnhZ>Z3)1ai{sLt7`z z7AYymkPj8cWlqlQ&wgEyM#{f=*b$3aW+uBR2*T392IVba}wB~?|048Z9s*aK`+Naa4sb0jfV+x1D> zg_Ks{vrfh@Fs_bextfzWy+$pT&hnSmnB;oI7F{kPdtLnNOT`5sS8jJLXMJ# zzUxXZzto+v&eI9aQoYOL(or8a9hVZ%iFZPC7x9a{5$(=L`MZ|I{@! zq?=f#(4eS}43zAq#>Rre!gA+%7RtrMN^}LGpM@YlIt9At`9&G$I7A;Jqhjt8PB3yl zg2fnD8~BdOWx|~8CyRFjPa0V;9V2aop-sQnWSjk!D{9(@$$XKjhnyHVnkq?RW!Qf2 zA?FHma`fkw(DNQeChp|Kq=l~xVc=fd-l{m;IQZ$ukb$8QukR`G#jBNLTiHo0Ewhq> zGA~PwOn#YcPxy;)A37p|EuXkzFDW0X-{(BuKeH9M_&pcuWps;7f$-7F3xL6yDBjjm7k_0ViTH5%bFF#{q9L@w1`*%a~_Pwi1 z%JrD1xbTwjQQf1iJs%>R&pwJ-W4v^Bca^NYmJXATCXfep^%Hb~u#b?F>?b8f%pDIG z*MEEQTS3tgP-H1AyYa|Vt{)jzDN#FlmGP=Y^j`})ytO&-%V4-JF4lk#NDC^@wp7a# zf`Ul(#08vplzhcy)X^1#78Yh@XJ_?$k=fU0YChu7rc9}ay$-*SnbGDG>*s;w*D+ca}nqm8^O6x&E zBHo+Fn!4z&azF+gqeMqb+lgcuWSIW=(O@6|q>57h6%f7lt&KIr@igD@vfWnLiujW~ zt>~|K!|29CB10XWK7Rh&Vff}^CK+26^IkCnup#x66*=sCUQ(-f;bVo4$BK6EY-Z~Q z`|8f!F@E|!ez}c{K=ctz0D=~?I4>Ps?l9*mCaYi*qonkIw9E__R>h(wq|h-*Nx5kC znV&}&J93_mFf%8Byl8Glp*uEcc&D;1p{}fu(D`iB=CeEBdn>a&f`{lmq@ggwOP>|m zS%#$yjYnVTTpxUa0{*dVa#nUWI7A3bBW>YxfNO7e#eM{HP&B@v5RQ)Q+9|F$jU)MM zg~)xAeF9wQ$RUIg(9^rZ-T~YCh{R!nL5US%b6zN``%qrqtjkf6U+31e?zy)scW|@r z$dT{al3Udj2USoJZFTo%@+WUH#s&yQ=j4e_b?g-yXTK;*8vUn2g}`hDQy=H4weJnwno> z$EX@DtgKSnCvmZYbH#0q|6$_=(}&C?*eDPoNi_PUu@RgW&S9t~Kq9Mg!>9!nIQkZ! z3&Yr<^I-=2@|*BOt)JM>au~xHj`{j8(e40C!IIr^k&$)4Cj~2dcY>~0PlgwEiQaA?9{yAv9u)LI-_>OCyH`83R0oF=8L3~27U&Umm;wU+7tUZmvfT09w2>|$ z?0T9~(dN+cm({KX{`*`&h%!-E(lRfy0lLm24{OFoS#vMvp5c+#xPN>)>&}A$p zvYwNkKkenq2bWR;Yh@wzuYyVA5*AndW_XEjw?g?~`~f?~OBH(>GM`JgDM>jJF1=Qn zAZzBn+?IE!Pm6CPpvH(P;)(cOh4+@U%M)Q6MReo*!a>=kUL|@9vlN1)9KqK(&(l}^ zv_B~S%a=lW#%r7zF3LIo(qmC5Qy^x3to(HG&<)8mwgKIFg)~oEH98>k;-W!ja)8na z-`(J_5IjNRt2O+4sW}e*0dj8z3*MhEUud1UEUIk_ zhdB*BjXOlnP9dmffFb7g?F(#_crJbv!<5JtwwxN_Mda6n)fmJc8|8g&ofA>FuW)SS zR@`%+Ox>>7&YquWt=UWQO4jVQ=*Z24OzOQ}r)AE8$7^pFmLLR~i=R%VfA-e#w7!R~ z%TS!QhqPb ztE;!7eL`(EpLjl@r@Qm(ik{OLzoQ`x$2vMX>grvK%Emw*MMR!M8Y$1=S5{UKidpb{ zZ%T+evv>Alp~keH=gp-I50!!M-D#>BB|0IhlTYOKqd>6x)Ku5w+<|DTg7ZvCMXv8G&I_+3Baw&Gj4SBWGXOi*p@t5$Wg<>lV4U6W614-O5*Q|99Cj&w$}T_IsW zC0$L73EBxbIF1e+)-^QD_MCpLw4$8h4^16#!cVoX zsiTZ1Ly3)z_?&Ht2n_YVrfkc?3(D>Onr0@at&G*YXL~9(SKUBjz^4x7wT}!zEQ^yUcve9#tCYrJI?cqzI{&LlK+BO)=326`$|kkKYqMb_fYCO(e8>lltft z&QIqYNaEBNwIV08Vm>_O_3L@vh&c*PxVcd+K(TKh{;ZJvd_i<%`=8_Ly9jYRRF#F= zHlXP-Ye7kkF3RO);yYOg`s(RfuM0i`sT`Cu0D@Gwp4X2coZ$!j^FMxYK;(G(G`U1GD(xX~-BE7<-RVMo8P;@Biqz@tNo+E_whi zs!k#%-}$~`!C3!GLq~_%n9q}|@*~Nz8Xv`7Ep{FrkP(O*5bzWN^XfG56yxT;03EL% zLF&Ep^U~1?2~@PThXPP1($t)!ZDxitxsK+N7b*lZ^}X4{s4YV*4Lgz#s@mEX*MpBl z<>=%~-N6j`N%X&>qqXuAcl1PTR}32`oQw=E5ENIxA^kA;)1t%Vg09X zi%CRRCP%)0y}HVDbAjI;bQ$%Ae z)~v=+p!mQFMo5Wi5^OE38eg`zGAOCvTTxxx62K7nPn3ix2jo#AF@}Qo?WXhjVb#^v z#E@V~ZQZ^<{Rs%tcws{QW(OmY4xdK48VT{)Y}WN-K#CFY1=|3u9fVJm2X5u4ip|kK z-}R+E{^sFV z2qEl;mWEJ3Qf%Fg*fK__!qPjsYuMcfzn7PNoM}AiB6oGASy)6wL`n)>q#rtr)a5zO z*mggAP_NPT9ZF;*K;du(zwsg)AT6Rn^02M@-%wK%0i*$JLQoK@hbm(ssP{bkJif6v z=h$j(8MgV8)A=?JL*xyJ5*sqSOfbI)bR#hU&kGZ--nVOjJA7nRxFaA3|Md{308EU> zDC1kqYr>9g1B%}+o9~K_EfvocQyZ9j*FS%^T;uF=sJ~E#)y5DP>LgAK?X#we<4X-J zVdoC{^78HSc>S<}%h`?fKR=bF82Na3G7fLeDfC8G?`Qca9sES`+zEb$Y2IwzH%jDR z_evD}4$sSE?)dig8!!KhT`(LW`dW^w=lo17!#k-n8k?gVVe_ny#q5QKUfI3Qjq5q^ zgR@gqWG~6_5eG3kA205SUy3RGN6HwhPl03O73RrA|BAS{RAP6iv&$12j09_b?xmt)d)z%ZC=GQufDv|f1Sa^9AM)JGPW;JO2(gv} z4_g~~60g~nd+T#alvk_?)bw7jp}pQfvo#=AHyIM+)c)*}o;HKCy^&FjV&0v52fU7%-@uhFa$l;*3z;W_^^f-3{fYcMRtQ;xLvp-xM|1$aKeC#b5}jn z(>QHqrtd?*pC6IOB*>;YkBtoa*r|*sx9>LNOOs07+gOcD2XBK)dPnM05qz~R9NS{Z zw~}Lb)wF~)gk+lmA#0b}!^lZSFk@n3#-<`B2F31gm$TCsBjaWM1B?cWZ+m+i4?dC< zBoBj_2U!TyGjz*zfwfct(Oq4;<}2pQobA?**zqzjcFuP1W|8V?56`<}*3muxIF(BQ(-H(pt%}v>xHzPpi{c~|E+8E&&K;f#+nn6NN`o$x(-+9z6 z6FLRIeWUh~H$LbWD>)%5R>k;64NsC4wpqx(kuW&2fZGLM<5r*^U!(GADXDKp`Gkp$ zN~=CpdJ5a$%1R@}5&L^x=T`e#Sa&qHd#tW+tPIZ$^6SOB*_xX}#K2Y=3?~8NxlqDj zYHEtH722TYW@y;w&^sw=JMhlIKHA0TvNYuk1SYrWkDqCNN=Y8`b<7^n80K^dUN*KN ze0l^Cjq`k>?9pf3Z47-%lAMEa#Q}rybsl*I<4e1l)vq;OcbFX+k@gh9a87>ah;Oax zNi~+xk)JP7nQSbyfJ<7D+c2-VcqjYT+~v?`VoVK2Gk*@PTV9Zr#gwAS`_EI4&CUkH z0y-Okw&Ni{wpYOoecI@5y1DJQ)g3yj`nle@fE-oRmp8@TC6J2P(OGel&J|-WLal(o z!)cA;2SOG#`jzxthW#)p#70LyuKk(TY$;6oxMCj!am{UgedH&i!1(>YFzZCZu?>ZV zYhUFeq>gazmX(!(1EtrWLAu3;5-*BAwhK?&H> zlGjm8dxLJtbU1EW_50BU`51Y`@b06&R#^_fjh2=ce=YzijPrP75vl_LEKW*bzmVm^ zlYz`{E*b+)x#U)shmThHOfzVrB1=o&f0h%Pzht)~wbQ+p_TSKKRwTuhl1Qv*W3G=wa>Ro9@+epUj@wQQJNL z^W4JpG}SCsc5GLEaz4(W)Dkr6S+t~!3JZ^nPn+2pdNX-?+?py%xqG?k98!PCsgz%h zOcE8{Zybfa7nM}VaG;{V%YEaUA5F z=}7-5y)F3rE7cRpTiN!>*DdgoZF_lfN049my|Y;MmBP8p<3pL;Ys-n*N&NvM0kpAc zYRaDoANgqnA^O`pM{a4yYHJ@h@rVg%Gxl!xGGcUav~+~RH9!A4EHUOHEgrGYo}s-| zo@n2rgrNx& z6a+C727AmoTfeI*Fu|{`^xCn)6N4EUeu1M$4NoqRBP;H*Nu6#C}vumcEcV`tYqI(6$u;!tZ+Obo`ZkDs2PE1Wp6R<*%6MCGwevXYH;7N5?WQn$kE z>1Y%C*3c#UIebvJ`Jtg8m&oFjt~9Hb!`?8lg*y!c?Ughk)=~mV@m*3n*Y(lX?XAiVfo^XUy+KUC%8o?5*Xe>k>eg#-1Z=?*{ ze{-;+(mq!2?_a;y>ThO>5Fi`_zE$S>Umf_~7NCgqe57yn;_XLEi`qqY^S6}##0Uzh z#>P^Y=)@>Jl4FOe5&A0eGo-{n*Z)jo3`YyEVu}E2*$@ilTPvmIlo%gRyfg#!H`~O7 zYS6>Cr|7`XUo~U)_F_yC3c-Pa)3dYq?`}`jnXK#1%*3;&DsD&mUOiG&qf)4ks49gID=_3R^b%yb1(@+cEwqY)}$N@`ErJY&O6 zOE#^bAmQ$&zIaMPj~GWc^)^Ovbs%Z-h7G&LUdN5Th| zkD_D54~`q;JAHB1AS+^K`CuLIJ){`JTyu`?-Tn)$Gdrc5UuGLx@*cOnG}@*An{8uP zN_c*u*>rHn5!ztd*=)Ds^9EHc)YMQ+Bd-r+JmgPIHq88zI#NHqjFl%?i0O}-D0Y*d z@o(Do?XriIG;k3Zgc#KzO-5r8b>hQ|w_9Ck!es7$n)vwfd{ff_GQY=4Cser9a%7%s z>15?P-@4_#zG3F(=H}sHdijz_e?P==FgEvn1t1J*7+zSMY5xMV@81!J#6DyM8P)ym z!lZtS`N;86vzDlDYO<;2vc2Z@ecfiuUpZSR6%a2_(EvJ|0Q`_Q*4_LIJ*%rPpq`q7 zokifJ(uqft8TK}omI}(sK%Da4zQr;8qW&lha>#7)O*)qs=P_gbxxq#UFSFgm#&J8V#e@>mwNEvjCzNPZRngs92lPB73BEkg)5!|#1 zRgd=tT&Lr<*|3?v8>2T>?&$GXtxa?N$v8!HVp8ORM!q23zdEaHu%)ErUw%){=liYZ zdb+K?XXo;#{o;|4kYQ3HdIm}aI(2nZ=lRks{rT;FXYRsMM~5~A$+LB|XS{drItulB z3LG5{GhI42a?Ux-xoNJio;m=IHlBH}$2h3Bx4q!*BPN2nQ&3p=hKfq1X#q+QOAyIJ zk9h{=vFDs7D47nfE-l>(vwDY^R&yvtwSZ!O&(bJ$d(I@dqh&M-PqgmADpTY5fLxU z5tw-bFH*9Kxk%5KFP5#$6vs8?($&shDXnTJ+P9=7X)H}{-nU4oc)1||q+ipgfdb?H0Bd1qFB1a>o3RlnbbB z`r3Qf*LsPnXyW~o2aB(vVgIX|=w-pJ#&7(ENpr03^X+|G^&?`R;ujZD__=#ICBL;b zV`e5JHWnTb{BnS5^&_rl^=4kKv9)BQ`MYw62-LruxjE^~j!&i@#D0&PqoiJyBCKlJ z)NH)JjNW;IlF{$y@3r+{V={C;-aopGS_oW)CML+~!y1^Gkx^LyPzem2$l+}3Zl%g& z&}ydZ@w#&hFnDhN4di!>A!m;Wl4bu>)EcOXq2tIAq=oMec&M#?yV!HVpz&k$)v_-+ zgP&s)JZnsJ)7pKUX*acL>F97l;^9Ed1iJ}W*EasKdjCFPz86OvS{0pt=f6Tucn(kl6cEWE?y0n5#b_#wbx$rXy~VbSX5k-ScivYWCF|h%Hv*w(Bp& zk)DGg-D|n^vO#QRXD5owom~@m7X+=HZ`&Ky$A9&zw8it?L!+Y?Q&q7mK*5SYgR$5+ z|0K^M&#m?Mlapwo8mdxCRzXq?Rt9gG|CHIYwU&y$HJGm}ds})e1v@$y&kYY(C6&E- zU6=Oh_9u#Z=7B@yY46QaNeks5m*PT7Dl+gJ|Cw7(;S)Z25|z);!5cj72BrcF8GxhG z#|i}96h1+m;8y>u97Un##Gw)}a!s+r8=rNq2?S8N0uq zR1MQDwk%d)lpw^nD5PS4JV;KCcG4cnABO~MWSV6d$VeO>pq2+Ujzuk_j($2Po;Hf< z@Ksj}8yL&=wx}S+J>NV_ldCH(SF$HXg_Jjv%um=sjG8Xc`Og06xTK`mSR%zT7Wa+M zW{HzpSs#2K_>MY?tK03m<_s}ofSggj7!OY-Qd*kF39k0=D{Pc-2V*NX5KzJ;8NNV6 zcE&$EGPd;PyUyZW_k#P2I$p>#!!uqWTrk85_#Jjl;E;$a1e$?Y4Ude5hA31s|MFn} z9MdL#slt|p94DA#7Z=ff2N_v=;I{=lzHqHJjy_x?akOZyTYbwvz}tWC%@O4ti}`Y_ zhKMQ_5P%C!C|arJrw+C6`H>|*rO0@ti=+R!DkQi~%Ovph@N7m?p`+fbM)Pi7d&+}Hx`oZ2iW%mSoHVmIE z1_E6m^F66o)IpG+ZQuI9gfSKQy(n@ZOvD5d2t7#zp$Po4SP21=Sc$}rDi)4@ZE8BD z|5gu1St$HTcC{jH``G- z9Im4it%C`w#z+wTP4XNNa2z-wy(a~B`Y`#L@g;1uaQJ{vzQWOlu)9_Ca(Hd6I}f;y z`%*~#Kwu6rk;9!kjkudFEVKk$O4S7LWJ?Qe7JvK*)mwLOuXJ$Cj5N}E;$+x>P{Esk zkQUJf9W}LA75@n`3^B*y7-3}8Qmp|a20PzB6-~QYE)^+G4BU#CHK5nJmWDj4tStRt zf!&acVYDYEx{erOyS?MkT_8;lX-aT)BiJ6PoT~f$o5q;LW84Ol#f6<;rN74lD=?vU zQ2C75xqcOm?@KPn$=-i4`HHqB5(KgleV@J-A^Y72b8-~mZ3^bXY2Pr6a+r_88 z@5ko|F%AG!$Q_0rzA0WwQIQjhDI-v^_0{gfNB1od^F>``AAOyguB$^scHF<3#CdIF zW51s)DIRbx9PUx`F()Gw5FWu2Dt!76g>mk-kI%$IVlxgQr+$gK;c70XM{*}5fAs2< zXCwtZLMi06Yxun6*b^H~bVVK3to0X;%+q`1ojS*{**f)Wd0C`o6r^6&k1~jO#*7?w z&z~P|cq~;9+vO8}zDw;KE)v~U13>AY;Rj_d^1m!RQ)i3rN-LY<7nJ;U=FJ|0(d13lIjXf_ABsl*mS?GeZg`V-dgD(=%RN1j)d~q zc|HcB@%HVr|GblyM7gCU--MTCWzl1K0Q~PD)`!`hkQYKQ)AkfjV>5-Xmy3g=RA5D7 zZk@S6QcGNmhovMQe+JmK^8FP4yECpRvnKt1`m{wciaWg{vP->C8^&mCLBvFmiSG&J zK4tS^EoS#x=X^op#;dJR@7cwUBfUNegr-h_<10n?$YOr}no!f3VlyVz{M zoL;&hY;EXy%U$0NK6RVrp8UeHQs=8p$|j+|dLCBGtG(7q*3piGpBXJCJ~B^1N>Nb_ zBb?B*07(}yB3rL0NPKTx*oqxJB(aloN1y|~r*_Y)8NfM^4n{Rrc~CO+ zgWE?O5khtTyPF}Kd>=6+RhLp)K}=x&IEQe_wG&H!|Drsu9cspg$_CAyALfG-HGc__ zNC@i1M++Z0q=@04F)Wvtmjm8J3=Z;o{A6(uphK#w>kN+f@Ni!lwrHiX&CSife@kSO zu@jy;a7ui?_#3_w^)$H9b2C{pvZfH9jOx~_%F6Tvb>rhpDd$M{yHiqAv#^9*N;$>* z^$N!axtGqrwe%!>&yYbK$bFM_j)|Umm2Kp_!5st5TP}}}ymYBfn&#ikgE|2x(zA_c z)e_Ytb<4sVr~aG*CnUomCs$*+9(za1wZP=hbhYx=X>cbf07K{}prPFL0~BWCW8fj{ zK}aI?d5w1`oO3!TC|1{u#B;Je z4S_gY7_c@+`MuW`8~Jg+AYNgFNR_bMYC@sY-oAT#X{s|5os9kS(Xv8><(C=JEcp2F z=0XSzr5->LZzO~m2t-4c=p*wVogHF(n#cKf8gG2>I+Nahfc(J8Uycwve)>+axrT|6 z&GznO9S*mQ4DQ3h_fR=S>EW?F(Mln`X^(_S#HWe5{C)xNDVlLYLXad%FzDIY?ae?~ zoWqP;|%=y0`yv=u9R`DA`XDy-f9e09p5S z6m=l?%h_4<>3K|QaGe4l3I8m|Mu~X|aC3kh8nt;79cI7n4jxOJ9mWF!z7#5bjAQ^q z0Z#En-O|!}&k+et*gij5l#m13hj<=_rl`hrwP%F~re=<>-Z1Ny4ZCx>Y}-gpRrQlW z3zd9yXw>(w6XuO0X?amM^jfo=R!;Kr20Zy@k{^w;)?Q49i>CDbq;9m&Pc5)6?XXVF zK<^d_Ar2I-R8%CF^C~KItW101wuL?t&gpWa<}#anB8w8&JCl(E1A2)2Lw`}cHGUfS zxjKn7B*d{CZqv7cMhR+|HzN6U`2@52bBn~$z*R=(dH(0^N(wL zWSM!h-f(^!W!+FWG;|njlTG>or8T^E=zUi@k(ry@$Zu}Ez>~#h;prKAkJ{S80&YNj z>R&JWzK{PGOY!{wXgcq3to#0rM;X~kNLCU;NJ6p+Nl_%(A$w+IWh6;RNV1cVhLI?n zgvv^`WM*dX?RUDL#&j(m zT{mEcBaMmY;DxTg1W~j&GeAaXnIHQ&9|*ixX$(m>ejCtx-fJUaMLL1-F9uCj1JgZ) zrg%6I4n-Rbm`t=Pk%tRF)R|f!#<_cVK)p>*=33-3zB!ugK&-8TvH+J2FYm;DuFxIY z|8FEN1M&^@>6>eBw})vz|EB~GcgCNb;bd-UYs*P9E5h5h|FF-~>XC6E+?Bls&n3kO2{?_ zRU|FqA;Fp{GSCDEA&;*=wefXN&(Z3T_qE~bC);J^224f2#nvYb6cnWY`0;2uYZysMxPUS7^fRWARx<=(fso&Aec{AEDq`$w35kJWJ1-Xpw6 zDtnRm)`Hc-|kBoh1trFEdRYsIo3B( z)+>mZD-Ni)D3^%Or{|V1a~d(<43GV&4kZ#aiwd*xL_GKIVoXh zYa*`@Eg+!AwGfd~1Sv3P&i=A6Z=6?D{Ga^rXCI=@7Q0Op_h|?rrW|1}S9n@8H8TqA z|Eyzt1fC$Gc|>oS_iBaME7jr-#Qbz$O-}L%gOSInxH0U>ZdqawvG; zi20{w7V@3Hb2q$S>6-jCT?!i1(|hS zZ2cV$-SX_(?d>bj9LG1ns0EkJ^MC$_^^jkw$bm{6+qmPjC&C`Z)csLXV*AsURbEy# zuuf(++Bn>y3W-LczQfg$|C}c$Xh=`cVMFZYkydut(!~t(QV1nsX^K`Io|t$fpMu93 zl6O#hHLubhP@#>~h*)ai;8h!@c>F@RM8^bE|H0m%7e1lxzA&uB(@iX}Z>9_j5(b{o>xKpc4Yb^jyc zV+n93L*^V3%vb0kXjAp99su^_X&Xns^SfK``}ZL*3+OU~K3I}9J6Zllj~vNkf*1Ty z-BkD@>tWBuvN<)*pi#YMJw6`bDt&^G2{m(h?ONS_eGIX~;^w{w9bb|f& z-RzMfGudH5 zPCP*;Po8XUzCuA9Q*~(0JpndiluVe@VzQ2zHTEF`CT2&T-$tE-+a0CozwvQ2pkq^0 z{3mSAIo%vgl}aQ!v_6vgte_n|aoWDgbe4s@#@?SMi zo=X@ z3yJsO1jC#4T ztc1k2@{`zb^qYds+&=mHld)OrLLR}-A!yF?fKSc)P;7H&MRwI+>``y$^98E}(Obh# zb-SC0j2~o>slWLLx2oqS)?_h$N`M>DH zud^cT+kZy`m>(6+UwAe55mo{jz1xSRSq(yy3KL|YJUS6vQ2uYuV9T@lgAcYQzKWqj zcvN+ zVie;2RhQXXMD!T@B0X8#j5Iw1Lmim@ssQ`Q>TStfKvHRMar>7qJv|BXDUy?aX+XL) z&zs>l!P{tJg7B|rBaR>nV*+!Asp0F_eGlnyePM^>VEG!Y!|>dyIJ4U+9!5dh{jI!Z ze(F^RgRjQ&|EH%r1+8kZqNj%kYBh*G5CDhi$8JGKPri8%_gB<~&pz>aD_=WD0`iVX zuk^jlXCr6{IwJX*b5 z8*VE1!!i%+XOZHGd-U)jJ8dxPpI}9_miRYu(*6gSu|l%In2UtJEKP8Ai@Hnscvx`r z;lr*lcS}C))Xnf+FJ*IIGSoWntYGJ?2{UJMc-_+Pk5jej(!Iaq zqWYvHe!;n+mf8$a8zu|#DUgkz-5+-m4Y9r1ux%Oc){_WA}_;%&k$kJ63V%S$89K!U>_g zN76TjDQ3c*j{#f+_#PAc>gw||Y*S;HE@BCcd|27j{2C6BEdy^9Qmv|{2G5rAV`dLH z@{+u!yWlyUjt2b7Wp(zt(cNk@VV230jRvxItCEVGbxdP3nXgwfM_0-T@TB6ZS;Q{7 zuL>&-9RHv|ew^P0VKA4x?vbeClo__>}l;H*HvbFV)i`SpX7&@z~ zHtKmitIn50C=;?HfhP|LK+S>exI(~IQD7##=IJ9@uUAh+d)cVZeESdVw18Qsqi$?+ zJYUm~$hU2S)iq*5cPR!JFcE|CHLpuJmO_LMR~axS!HR@rAN>6Z@L~_m!R`(pAV|;; zgrSLh@ssV+rNnocC-?=P@kE=EayksvY%&;y`b=G$*&=z>DK6~LUvPefq0fy~GUDJ7 zBiNuJm+wQDy*_m3Vyt9*Eil++l;st-4;H(Qp+~v(BpWBRGg4t_Tj#C z6|B09rSPsZ(>%4C`F1QqgLGeOV{`LFlGT^dYv~JiFl^b*H?=yOON-B{%A3K^J*Pj)W$Ub3ous2)1I=0oijdp*0 z-FbGJ3SmGhN!~Tc^149b1r>b&2{l#~D5AA^0awEF^^p}fHZWGmOuHw3o-FV~>&;Wr z(jlC!Gm?=Unl(YhHJq)AiQhIn8&=~wT(a%PyT4?QP*ZJ+DE9pRO>QX6Oa*(=o#`G- zzCRS?7CJ3)IE`A|{9SNuWQ0SAQ8+dsDhlm4YGC~mpAVVk*}k6cx?*pWztfThqO<0T z0^0*?_d^0Im6es=^gFb}kpV#pImtfxPoBJXNU)k=)Gi)R=dz=<7@1{sB3MP z5?Smn9`h{Gq!PNSoz$0qH)3Yy&A zfA2qu+IBjkd54w=LWz9c(wF3bx1k0^BuO79J7(-yeWbZ_BwoJLU*Qiv1sL!S(Oz91jS(PmKj{bi3pemS{F$tZW zn>)1&8WY15vM&6F9H4mdm*~izD=2hBuLoiU+;p|6S1jjUO&NIR<<2|FDHzy6F7xCO zPzabBU^RoL5Wu9re}B?nwqnRhh>_0!e$`F4jmMr2J?}Rr)G`ANHd+1=2Nt0y_V!%Q zcs~a3H?~vD%T%TBM*3ybXbcR7nSJ_|&#`KBtv|Hb^IQ?n3vq+z8c}{#RjRt<4t^*C z=Plz`OrOX03>4?P&i)QzITs#&u6UfUKJ)u`7|M^Y&^qP-OAEH5oHfqbtGomIR(DMF zPb1dq*)uL0QqmBB8|lbgp@atZ(;6-;*!V_v>7S!AG8^kQf(|{i%Slq_1QK={dn

ZY` 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

lQjODgkz$LjL35pZaTuoL7* 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

Q7Zq)}zAW=h!nazz;aNIAqgRZS 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®#RE|%TxvFeS#tgHBE}gKrsW01zJWK947{b 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 |sLIua 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

29A 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�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 YNBmgI-XBlKM-eWbQ0Qo7w5&!@I diff --git a/docs/source/_static/nano_cipher_logo.JPG b/docs/source/_static/nano_cipher_logo.JPG new file mode 100644 index 0000000000000000000000000000000000000000..e8eb7496a18ce274afeb3d47e29661259b7c6b6b GIT binary patch literal 29748 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 F{THQXC7b{N literal 0 HcmV?d00001 diff --git a/examples/co_polymerization.json b/examples/co_polymerization.json new file mode 100644 index 00000000..e0502b87 --- /dev/null +++ b/examples/co_polymerization.json @@ -0,0 +1,35 @@ +{ + "simulation_name": "Methyl_Methacrylate_Triethylene_Glycol_Dimethacrylate_Copolymerization_100k_500K_with_wildcards", + + "force_field": "PCFF", + + "wildcards": true, + + "simulations": [ + { + "tag": "MMA_TEGDMA_100k_500K", + + "temperature": 500.0, + + "density": 1.23, + + "total_atoms": 100000, + + "monomer_ratios": { + "methyl_methacrylate": 14.0, + "styrene": 0.7 + } + } + ], + + "monomers": [ + { + "name": "methyl_methacrylate", + "smiles": "COC(=O)C(C)=C" + }, + { + "name": "styrene", + "smiles": "C=CC1=CC=CC=C1" + } + ] +} \ No newline at end of file diff --git a/examples/doc_1.json b/examples/doc_1.json new file mode 100644 index 00000000..223fec4c --- /dev/null +++ b/examples/doc_1.json @@ -0,0 +1,39 @@ +{ + "simulation_name": "TMC_MPD_edge_case", + "force_field": "PCFF", + + "deep_search": true, + "reaction_iteration_depth": false, + "wildcards": false, + "deduplicate_reaction_templates": true, + "write_second_reaction_stage": true, + + "simulations": [ + { + "tag": "100k_300K", + "temperature": 300, + "density": 0.8, + "monomer_counts": { + "alkenyl_branched_diacid_chloride": 2380, + "m-phenylenediamine": 3570, + "extended_alkenyl_branched_diacid_chloride": 100 + } + } + ], + "monomers": [ + { + "name": "alkenyl_branched_diacid_chloride", + "smiles": "C=CCC(CCCCCCC(CC=C)C(=O)Cl)C(=O)Cl" + }, + { + "name": "extended_alkenyl_branched_diacid_chloride", + "smiles": "C/C=C/CC(CCCCCCC(C/C=C/C)C(=O)Cl)C(=O)Cl" + }, + { + "name": "m-phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + } + + ] + } + diff --git a/examples/test_epoxy.json b/examples/test_epoxy.json index 0b2eea70..325e221d 100644 --- a/examples/test_epoxy.json +++ b/examples/test_epoxy.json @@ -1,24 +1,31 @@ { - "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", - "simulations": [ - { - "tag": "epoxy_test", - "temperature": 300, - "density": 1.0, - "monomer_counts": { - "di_epoxy": 200, - "primary_diamine": 100 - } - } - ], - "monomers": [ - { - "name": "di_epoxy", - "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" - }, - { - "name": "primary_diamine", - "smiles": "NCCCCCN" - } - ] + "simulation_name": "DGEBA_1,5-Diaminopentane_Epoxy_Curing_wo-loop", + + "reaction_iteration_depth": false, + + "simulations": [ + { + "tag": "DGEBA_1,5-diaminopentane", + + "temperature": 300, + + "density": 1.0, + + "monomer_counts": { + "bisphenol_A_diglycidyl_ether": 200, + "1,5_diaminopentane": 100 + } + } + ], + + "monomers": [ + { + "name": "bisphenol_A_diglycidyl_ether", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" + }, + { + "name": "1,5_diaminopentane", + "smiles": "NCCCCCN" + } + ] } \ No newline at end of file diff --git a/examples/test_styrene.json b/examples/test_styrene.json index b14e0fc6..d93173d8 100644 --- a/examples/test_styrene.json +++ b/examples/test_styrene.json @@ -1,6 +1,7 @@ { "simulation_name": "Styrene2", "force_field": "PCFF", + "wildcards": false, "simulations": [ { "tag": "styrene_10k_298K", From d1dbc0fa602c34db9b570ac728a8ea953cdd63d5 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 12:32:32 -0400 Subject: [PATCH 132/176] Add unit tests for functional group detection --- .../detectors/functional_groups_detector.py | 2 +- tests/__init__.py | 0 tests/unit/__init__.py | 0 tests/unit/detectors/__init__.py | 0 .../functional_groups_library/__init__.py | 0 .../test_oxygen_groups.py | 174 ++++ .../test_registry.py | 190 +++++ .../test_functional_groups_detector.py | 769 ++++++++++++++++++ 8 files changed, 1134 insertions(+), 1 deletion(-) create mode 100644 tests/__init__.py create mode 100644 tests/unit/__init__.py create mode 100644 tests/unit/detectors/__init__.py create mode 100644 tests/unit/detectors/functional_groups_library/__init__.py create mode 100644 tests/unit/detectors/functional_groups_library/test_oxygen_groups.py create mode 100644 tests/unit/detectors/functional_groups_library/test_registry.py create mode 100644 tests/unit/detectors/test_functional_groups_detector.py diff --git a/AutoREACTER/detectors/functional_groups_detector.py b/AutoREACTER/detectors/functional_groups_detector.py index bff0448d..1bbef474 100644 --- a/AutoREACTER/detectors/functional_groups_detector.py +++ b/AutoREACTER/detectors/functional_groups_detector.py @@ -229,7 +229,7 @@ def detect_monomer_functionality( # Convert SMILES to RDKit molecule object for substructure matching. if mol is None: - logger.warning(f"Invalid SMILES: {smiles}") + logger.warning("Invalid or missing RDKit molecule.") return 0, None, None, None # Create pattern from primary SMARTS and validate. diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/detectors/__init__.py b/tests/unit/detectors/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/detectors/functional_groups_library/__init__.py b/tests/unit/detectors/functional_groups_library/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/detectors/functional_groups_library/test_oxygen_groups.py b/tests/unit/detectors/functional_groups_library/test_oxygen_groups.py new file mode 100644 index 00000000..cab539c2 --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_oxygen_groups.py @@ -0,0 +1,174 @@ +import pytest +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_library.oxygen_groups import ( + FUNCTIONAL_GROUPS, +) + + +# --------------------------------------------------------------------------- +# Basic library structure +# --------------------------------------------------------------------------- + +def test_functional_groups_is_dict(): + """oxygen_groups should expose FUNCTIONAL_GROUPS as a dictionary.""" + assert isinstance(FUNCTIONAL_GROUPS, dict) + + +def test_expected_active_groups_are_present(): + """The currently active oxygen functional groups should be registered.""" + assert set(FUNCTIONAL_GROUPS) == { + "diol_monomer", + "water_monomer", + } + + +@pytest.mark.parametrize( + "group_key", + [ + "diol_monomer", + "water_monomer", + ], +) +def test_each_group_has_required_fields(group_key): + """Every oxygen functional-group definition should contain required fields.""" + entry = FUNCTIONAL_GROUPS[group_key] + + assert "functionality_type" in entry + assert "smarts_1" in entry + assert "group_name" in entry + assert "comments" in entry + + +def test_diol_metadata(): + """The diol definition should expose the intended metadata.""" + entry = FUNCTIONAL_GROUPS["diol_monomer"] + + assert entry["functionality_type"] == "di_identical" + assert entry["group_name"] == "diol" + assert entry["comments"] is None + + +def test_water_metadata(): + """The water definition should expose the intended metadata.""" + entry = FUNCTIONAL_GROUPS["water_monomer"] + + assert entry["functionality_type"] == "mono" + assert entry["group_name"] == "water" + assert entry["comments"] is None + + +# --------------------------------------------------------------------------- +# SMARTS validity +# --------------------------------------------------------------------------- + +@pytest.mark.parametrize( + "group_key", + [ + "diol_monomer", + "water_monomer", + ], +) +def test_smarts_compiles(group_key): + """Every active oxygen SMARTS definition must compile with RDKit.""" + smarts = FUNCTIONAL_GROUPS[group_key]["smarts_1"] + + pattern = Chem.MolFromSmarts(smarts) + + assert pattern is not None + + +# --------------------------------------------------------------------------- +# Diol hydroxyl SMARTS +# --------------------------------------------------------------------------- + +def test_diol_pattern_matches_two_hydroxyl_sites_in_ethylene_glycol(): + """ + The diol SMARTS describes an eligible hydroxyl site. + + Ethylene glycol contains two such hydroxyl groups, so two matches + should be found. + """ + molecule = Chem.MolFromSmiles("OCCO") + pattern = Chem.MolFromSmarts( + FUNCTIONAL_GROUPS["diol_monomer"]["smarts_1"] + ) + + matches = molecule.GetSubstructMatches(pattern) + + assert len(matches) == 2 + + +def test_diol_pattern_matches_one_site_in_ethanol(): + """ + A monoalcohol contains one matching hydroxyl site. + + Whether a molecule qualifies as a diol based on the number of detected + sites belongs to detector logic, not the SMARTS library itself. + """ + molecule = Chem.MolFromSmiles("CCO") + pattern = Chem.MolFromSmarts( + FUNCTIONAL_GROUPS["diol_monomer"]["smarts_1"] + ) + + matches = molecule.GetSubstructMatches(pattern) + + assert len(matches) == 1 + + +def test_diol_pattern_does_not_match_ether_oxygen(): + """An ether oxygen should not match the hydroxyl SMARTS.""" + molecule = Chem.MolFromSmiles("COC") + pattern = Chem.MolFromSmarts( + FUNCTIONAL_GROUPS["diol_monomer"]["smarts_1"] + ) + + assert not molecule.HasSubstructMatch(pattern) + + +def test_diol_pattern_excludes_carboxylic_acid_hydroxyl(): + """ + The SMARTS explicitly excludes oxygen attached to a carbonyl center. + + Therefore the hydroxyl oxygen of acetic acid should not be detected. + """ + molecule = Chem.MolFromSmiles("CC(=O)O") + pattern = Chem.MolFromSmarts( + FUNCTIONAL_GROUPS["diol_monomer"]["smarts_1"] + ) + + assert not molecule.HasSubstructMatch(pattern) + + +# --------------------------------------------------------------------------- +# Water SMARTS +# --------------------------------------------------------------------------- + +def test_water_pattern_matches_water(): + """The water SMARTS should match a water molecule.""" + molecule = Chem.MolFromSmiles("O") + pattern = Chem.MolFromSmarts( + FUNCTIONAL_GROUPS["water_monomer"]["smarts_1"] + ) + + assert molecule.HasSubstructMatch(pattern) + + +@pytest.mark.parametrize( + "smiles", + [ + "CO", # methanol + "CCO", # ethanol + "OCCO", # ethylene glycol + "COC", # dimethyl ether + "CC(=O)O", # acetic acid + ], +) +def test_water_pattern_does_not_match_non_water_oxygen_compounds(smiles): + """The water SMARTS should not identify ordinary oxygen compounds as water.""" + molecule = Chem.MolFromSmiles(smiles) + pattern = Chem.MolFromSmarts( + FUNCTIONAL_GROUPS["water_monomer"]["smarts_1"] + ) + + assert not molecule.HasSubstructMatch(pattern) diff --git a/tests/unit/detectors/functional_groups_library/test_registry.py b/tests/unit/detectors/functional_groups_library/test_registry.py new file mode 100644 index 00000000..8cff03b3 --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_registry.py @@ -0,0 +1,190 @@ +import pytest + +from AutoREACTER.detectors.functional_groups_library import registry + + +def test_load_functional_groups_returns_dict(): + """Registry should return a flat dictionary.""" + groups = registry.load_functional_groups() + + assert isinstance(groups, dict) + + +def test_load_functional_groups_is_not_empty(): + """The active functional-group registry should contain entries.""" + groups = registry.load_functional_groups() + + assert groups + + +def test_load_functional_groups_merges_modules(monkeypatch): + """Entries from multiple modules should be merged into one dictionary.""" + module_1 = { + "group_a": { + "functionality_type": "mono", + "smarts_1": "[O]", + "group_name": "group_a_name", + "comments": None, + } + } + + module_2 = { + "group_b": { + "functionality_type": "mono", + "smarts_1": "[N]", + "group_name": "group_b_name", + "comments": None, + } + } + + monkeypatch.setattr( + registry, + "_FUNCTIONAL_GROUP_MODULES", + [module_1, module_2], + ) + + groups = registry.load_functional_groups() + + assert groups == { + "group_a": module_1["group_a"], + "group_b": module_2["group_b"], + } + + +def test_duplicate_entry_key_raises_value_error(monkeypatch): + """Duplicate dictionary keys across modules must be rejected.""" + module_1 = { + "duplicate_key": { + "functionality_type": "mono", + "smarts_1": "[O]", + "group_name": "oxygen_group", + "comments": None, + } + } + + module_2 = { + "duplicate_key": { + "functionality_type": "mono", + "smarts_1": "[N]", + "group_name": "nitrogen_group", + "comments": None, + } + } + + monkeypatch.setattr( + registry, + "_FUNCTIONAL_GROUP_MODULES", + [module_1, module_2], + ) + + with pytest.raises( + ValueError, + match="Duplicate functional-group key: duplicate_key", + ): + registry.load_functional_groups() + + +def test_duplicate_group_name_raises_value_error(monkeypatch): + """Different keys must not share the same group_name.""" + module_1 = { + "key_a": { + "functionality_type": "mono", + "smarts_1": "[O]", + "group_name": "same_group", + "comments": None, + } + } + + module_2 = { + "key_b": { + "functionality_type": "mono", + "smarts_1": "[N]", + "group_name": "same_group", + "comments": None, + } + } + + monkeypatch.setattr( + registry, + "_FUNCTIONAL_GROUP_MODULES", + [module_1, module_2], + ) + + with pytest.raises( + ValueError, + match="Duplicate group_name", + ): + registry.load_functional_groups() + + +def test_duplicate_group_name_error_identifies_both_keys(monkeypatch): + """Duplicate-name error should identify both conflicting entries.""" + module_1 = { + "first_key": { + "functionality_type": "mono", + "smarts_1": "[O]", + "group_name": "duplicate_name", + "comments": None, + } + } + + module_2 = { + "second_key": { + "functionality_type": "mono", + "smarts_1": "[N]", + "group_name": "duplicate_name", + "comments": None, + } + } + + monkeypatch.setattr( + registry, + "_FUNCTIONAL_GROUP_MODULES", + [module_1, module_2], + ) + + with pytest.raises(ValueError) as exc_info: + registry.load_functional_groups() + + message = str(exc_info.value) + + assert "duplicate_name" in message + assert "first_key" in message + assert "second_key" in message + + +def test_empty_module_list_returns_empty_dict(monkeypatch): + """An empty module collection should produce an empty registry.""" + monkeypatch.setattr( + registry, + "_FUNCTIONAL_GROUP_MODULES", + [], + ) + + assert registry.load_functional_groups() == {} + + +def test_module_level_functional_groups_matches_loader(): + """The exported FUNCTIONAL_GROUPS registry should match a fresh load.""" + assert registry.FUNCTIONAL_GROUPS == registry.load_functional_groups() + + +def test_functional_groups_library_exposes_monomer_types(): + """Backward-compatible class should expose the merged registry.""" + library = registry.FunctionalGroupsLibrary() + + assert hasattr(library, "monomer_types") + assert isinstance(library.monomer_types, dict) + assert library.monomer_types == registry.load_functional_groups() + + +def test_real_registry_has_unique_group_names(): + """Active production registry should contain no duplicate group_name values.""" + groups = registry.load_functional_groups() + + group_names = [ + entry["group_name"] + for entry in groups.values() + ] + + assert len(group_names) == len(set(group_names)) \ No newline at end of file diff --git a/tests/unit/detectors/test_functional_groups_detector.py b/tests/unit/detectors/test_functional_groups_detector.py new file mode 100644 index 00000000..ec5b3d86 --- /dev/null +++ b/tests/unit/detectors/test_functional_groups_detector.py @@ -0,0 +1,769 @@ +from types import SimpleNamespace + +import pytest +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupInfo, + FunctionalGroupsDetector, + FunctionalGroupVisualization, + MonomerRole, +) + + +# ============================================================================ +# Helpers +# ============================================================================ + +def make_monomer(name: str, smiles: str): + """Create a minimal monomer-like object for detector unit tests.""" + return SimpleNamespace( + name=name, + smiles=smiles, + rdkit_mol=Chem.MolFromSmiles(smiles), + ) + + +def make_session(monomers): + """Create the minimal Session interface required by the detector.""" + return SimpleNamespace( + inputs=SimpleNamespace(monomers=monomers), + monomer_roles=None, + ) + + +def make_index_role( + name, + smiles, + indexes, + *, + is_looped=False, +): + """Create a minimal role-like object for index-based detection.""" + return SimpleNamespace( + name=name, + smiles=smiles, + rdkit_mol=Chem.MolFromSmiles(smiles), + indexes_in_template=indexes, + is_looped=is_looped, + ) + + +# ============================================================================ +# detect_monomer_functionality() +# ============================================================================ + +def test_mono_single_match_qualifies(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCO") + + result = detector.detect_monomer_functionality( + mol, + "mono", + "[OX2H1]", + ) + + functionality_count, count_1, count_2, matches = result + + assert functionality_count == 1 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_mono_no_match_is_rejected(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCC") + + result = detector.detect_monomer_functionality( + mol, + "mono", + "[OX2H1]", + ) + + assert result == (0, 0, None, ()) + + +def test_vinyl_single_match_qualifies(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("C=C") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + "vinyl", + "[CH2]=[CH2]", + ) + ) + + assert functionality_count == 1 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_vinyl_multiple_sites_still_returns_presence_based_functionality(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("C=CC=C") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + "vinyl", + "[CH2]=[C]", + ) + ) + + assert functionality_count == 1 + assert count_1 >= 1 + assert count_2 is None + assert len(matches) == count_1 + + +def test_di_identical_two_sites_qualifies(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("OCCO") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + "di_identical", + "[OX2H1]", + ) + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_di_identical_one_site_is_rejected(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCO") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + "di_identical", + "[OX2H1]", + ) + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_di_identical_more_than_two_sites_qualifies_and_preserves_count(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("OCC(O)CO") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + "di_identical", + "[OX2H1]", + ) + ) + + assert functionality_count == 2 + assert count_1 == 3 + assert count_2 is None + assert len(matches) == 3 + + +def test_di_different_requires_both_patterns(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("NCC(=O)O") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + "di_different", + "[NX3H2]", + "[CX3](=[O])[OX2H1]", + ) + ) + + assert functionality_count == 2 + assert count_1 == 1 + assert count_2 == 1 + assert len(matches) == 2 + + +def test_di_different_missing_second_pattern_is_rejected(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCN") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + "di_different", + "[NX3H2]", + "[CX3](=[O])[OX2H1]", + ) + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 == 0 + assert len(matches) == 1 + + +def test_invalid_primary_smarts_is_rejected(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCO") + + result = detector.detect_monomer_functionality( + mol, + "mono", + "[THIS_IS_INVALID", + ) + + assert result == (0, None, None, None) + + +def test_invalid_secondary_smarts_is_rejected(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("NCC(=O)O") + + result = detector.detect_monomer_functionality( + mol, + "di_different", + "[NX3H2]", + "[THIS_IS_INVALID", + ) + + assert result == (0, None, None, None) + + +def test_none_molecule_is_rejected(): + detector = FunctionalGroupsDetector() + + result = detector.detect_monomer_functionality( + None, + "mono", + "[OX2H1]", + ) + + assert result == (0, None, None, None) + + +# ============================================================================ +# functional_groups_detector() +# ============================================================================ + +def test_detector_stores_detected_roles_in_session(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "test_diol": { + "functionality_type": "di_identical", + "smarts_1": "[OX2H1]", + "group_name": "diol", + "comments": None, + } + } + + monomer = make_monomer("ethylene_glycol", "OCCO") + session = make_session([monomer]) + + result = detector.functional_groups_detector(session) + + assert result is None + assert len(session.monomer_roles) == 1 + + role = session.monomer_roles[0] + + assert isinstance(role, MonomerRole) + assert role.name == "ethylene_glycol" + assert role.smiles == "OCCO" + assert role.is_monomer is True + assert len(role.functionalities) == 1 + + +def test_detector_records_functional_group_information(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "test_diol": { + "functionality_type": "di_identical", + "smarts_1": "[OX2H1]", + "group_name": "diol", + "comments": None, + } + } + + session = make_session( + [make_monomer("ethylene_glycol", "OCCO")] + ) + + detector.functional_groups_detector(session) + + fg = session.monomer_roles[0].functionalities[0] + + assert isinstance(fg, FunctionalGroupInfo) + assert fg.functionality_type == "di_identical" + assert fg.fg_name == "diol" + assert fg.fg_smarts_1 == "[OX2H1]" + assert fg.fg_count_1 == 2 + assert fg.fg_smarts_2 is None + assert fg.fg_count_2 is None + + +def test_detector_can_record_multiple_functionalities_for_same_monomer(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "amine": { + "functionality_type": "mono", + "smarts_1": "[NX3H2]", + "group_name": "primary_amine", + "comments": None, + }, + "acid": { + "functionality_type": "mono", + "smarts_1": "[CX3](=[O])[OX2H1]", + "group_name": "carboxylic_acid", + "comments": None, + }, + } + + session = make_session( + [make_monomer("glycine", "NCC(=O)O")] + ) + + detector.functional_groups_detector(session) + + functionalities = session.monomer_roles[0].functionalities + + assert len(functionalities) == 2 + + names = {fg.fg_name for fg in functionalities} + + assert names == { + "primary_amine", + "carboxylic_acid", + } + + +def test_detector_rejects_di_identical_monomer_with_only_one_site(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "test_diol": { + "functionality_type": "di_identical", + "smarts_1": "[OX2H1]", + "group_name": "diol", + "comments": None, + } + } + + session = make_session( + [make_monomer("ethanol", "CCO")] + ) + + with pytest.raises( + RuntimeError, + match="No functional groups were detected", + ): + detector.functional_groups_detector(session) + + +def test_detector_raises_when_no_monomer_has_supported_functionality(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "test_amine": { + "functionality_type": "mono", + "smarts_1": "[NX3H2]", + "group_name": "primary_amine", + "comments": None, + } + } + + session = make_session( + [ + make_monomer("propane", "CCC"), + make_monomer("butane", "CCCC"), + ] + ) + + with pytest.raises( + RuntimeError, + match="No functional groups were detected", + ): + detector.functional_groups_detector(session) + + +# ============================================================================ +# _functional_groups_detector_for_visualization() +# ============================================================================ + +def test_visualization_detector_returns_detected_monomer(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "alcohol": { + "functionality_type": "mono", + "smarts_1": "[OX2H1]", + "group_name": "alcohol", + "comments": None, + } + } + + session = make_session( + [make_monomer("ethanol", "CCO")] + ) + + result = detector._functional_groups_detector_for_visualization( + session + ) + + assert len(result) == 1 + assert isinstance(result[0], FunctionalGroupVisualization) + assert result[0].name == "ethanol" + assert len(result[0].indexes_to_highlight) == 1 + + +def test_visualization_detector_ignores_nonmatching_monomer(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "amine": { + "functionality_type": "mono", + "smarts_1": "[NX3H2]", + "group_name": "amine", + "comments": None, + } + } + + session = make_session( + [make_monomer("propane", "CCC")] + ) + + result = detector._functional_groups_detector_for_visualization( + session + ) + + assert result == [] + + +# ============================================================================ +# _detect_functional_groups_by_index() +# ============================================================================ + +def test_detect_by_index_returns_true_for_overlapping_atom(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCO") + + oxygen_index = 2 + + assert detector._detect_functional_groups_by_index( + mol, + "[OX2H1]", + [oxygen_index], + ) is True + + +def test_detect_by_index_returns_false_when_indices_do_not_overlap(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCO") + + assert detector._detect_functional_groups_by_index( + mol, + "[OX2H1]", + [0], + ) is False + + +def test_detect_by_index_returns_false_for_empty_indices(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCO") + + assert detector._detect_functional_groups_by_index( + mol, + "[OX2H1]", + [], + ) is False + + +def test_detect_by_index_invalid_smarts_returns_false(): + detector = FunctionalGroupsDetector() + mol = Chem.MolFromSmiles("CCO") + + assert detector._detect_functional_groups_by_index( + mol, + "[INVALID", + [2], + ) is False + + +# ============================================================================ +# index_based_functional_groups_detector() +# ============================================================================ + +def test_index_detector_allows_single_di_identical_site(): + """ + Index-based detection intentionally ignores the normal >=2 rule for + di_identical groups. + + One matching functional group touching the target index is sufficient. + """ + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "diol": { + "functionality_type": "di_identical", + "smarts_1": "[OX2H1]", + "group_name": "diol", + "comments": None, + } + } + + role = make_index_role( + "ethanol_product", + "CCO", + [2], + ) + + result = detector.index_based_functional_groups_detector( + [role] + ) + + assert result is not False + assert len(result) == 1 + + output_role = result[0] + + assert output_role.is_monomer is False + assert len(output_role.functionalities) == 1 + + fg = output_role.functionalities[0] + + assert fg.functionality_type == "di_identical" + assert fg.fg_count_1 == 1 + assert fg.fg_1_indexes is not None + + +def test_index_detector_requires_overlap(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "alcohol": { + "functionality_type": "mono", + "smarts_1": "[OX2H1]", + "group_name": "alcohol", + "comments": None, + } + } + + role = make_index_role( + "ethanol_product", + "CCO", + [0], + ) + + result = detector.index_based_functional_groups_detector( + [role] + ) + + assert result is False + + +def test_index_detector_di_different_requires_hit_for_both_patterns(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "amino_acid": { + "functionality_type": "di_different", + "smarts_1": "[N]", + "smarts_2": "[OX2H1]", + "group_name": "amino_acid", + "comments": None, + } + } + + mol = Chem.MolFromSmiles("NCC(=O)O") + + nitrogen_index = next( + atom.GetIdx() + for atom in mol.GetAtoms() + if atom.GetSymbol() == "N" + ) + + hydroxyl_oxygen_index = next( + atom.GetIdx() + for atom in mol.GetAtoms() + if atom.GetSymbol() == "O" + and atom.GetTotalNumHs() == 1 + ) + + role = SimpleNamespace( + name="glycine_product", + smiles="NCC(=O)O", + rdkit_mol=mol, + indexes_in_template=[ + nitrogen_index, + hydroxyl_oxygen_index, + ], + is_looped=False, + ) + + result = detector.index_based_functional_groups_detector( + [role] + ) + + assert result is not False + assert len(result) == 1 + + fg = result[0].functionalities[0] + + assert fg.fg_count_1 == 1 + assert fg.fg_count_2 == 1 + assert fg.fg_1_indexes is not None + assert fg.fg_2_indexes is not None + + +def test_index_detector_di_different_fails_when_only_one_pattern_overlaps(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "amino_acid": { + "functionality_type": "di_different", + "smarts_1": "[N]", + "smarts_2": "[OX2H1]", + "group_name": "amino_acid", + "comments": None, + } + } + + mol = Chem.MolFromSmiles("NCC(=O)O") + + nitrogen_index = next( + atom.GetIdx() + for atom in mol.GetAtoms() + if atom.GetSymbol() == "N" + ) + + role = SimpleNamespace( + name="glycine_product", + smiles="NCC(=O)O", + rdkit_mol=mol, + indexes_in_template=[nitrogen_index], + is_looped=False, + ) + + result = detector.index_based_functional_groups_detector( + [role] + ) + + assert result is False + + +def test_index_detector_skips_looped_monomers(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "alcohol": { + "functionality_type": "mono", + "smarts_1": "[OX2H1]", + "group_name": "alcohol", + "comments": None, + } + } + + role = make_index_role( + "ethanol_product", + "CCO", + [2], + is_looped=True, + ) + + result = detector.index_based_functional_groups_detector( + [role] + ) + + assert result is False + + +def test_index_detector_preserves_template_indices(): + detector = FunctionalGroupsDetector() + + detector.monomer_types = { + "alcohol": { + "functionality_type": "mono", + "smarts_1": "[OX2H1]", + "group_name": "alcohol", + "comments": None, + } + } + + role = make_index_role( + "ethanol_product", + "CCO", + [2], + ) + + result = detector.index_based_functional_groups_detector( + [role] + ) + + assert result[0].indexes_in_template == [2] + + +# ============================================================================ +# functional_group_highlighted_molecules_image_grid() +# ============================================================================ + +def test_image_grid_flattens_highlighted_atom_indices(monkeypatch): + detector = FunctionalGroupsDetector() + + mol = Chem.MolFromSmiles("CCO") + + visualization = FunctionalGroupVisualization( + monomer=mol, + name="ethanol", + indexes_to_highlight=((1, 2), (2,)), + ) + + monkeypatch.setattr( + detector, + "_functional_groups_detector_for_visualization", + lambda session: [visualization], + ) + + captured = {} + + def fake_grid( + molecules, + molsPerRow, + legends, + subImgSize, + highlightAtomLists, + ): + captured["molecules"] = molecules + captured["molsPerRow"] = molsPerRow + captured["legends"] = legends + captured["subImgSize"] = subImgSize + captured["highlightAtomLists"] = highlightAtomLists + + return "fake-image" + + monkeypatch.setattr( + "AutoREACTER.detectors.functional_groups_detector.Draw.MolsToGridImage", + fake_grid, + ) + + result = detector.functional_group_highlighted_molecules_image_grid( + SimpleNamespace() + ) + + assert result == "fake-image" + assert captured["molecules"] == [mol] + assert captured["legends"] == ["ethanol"] + assert captured["highlightAtomLists"] == [[1, 2]] + assert captured["molsPerRow"] == 3 + assert captured["subImgSize"] == (500, 500) From 302343f9851932aeafe2fcf0f6fbc11a67318a05 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 12:39:53 -0400 Subject: [PATCH 133/176] Add detector-focused functional group tests --- .../test_active_centers.py | 119 ++++++++ .../test_carboxyl_and_carbonyl_groups.py | 284 +++++++++++++++++ .../test_oxygen_groups.py | 287 ++++++++++++------ 3 files changed, 605 insertions(+), 85 deletions(-) create mode 100644 tests/unit/detectors/functional_groups_library/test_active_centers.py create mode 100644 tests/unit/detectors/functional_groups_library/test_carboxyl_and_carbonyl_groups.py diff --git a/tests/unit/detectors/functional_groups_library/test_active_centers.py b/tests/unit/detectors/functional_groups_library/test_active_centers.py new file mode 100644 index 00000000..f18a0c00 --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_active_centers.py @@ -0,0 +1,119 @@ +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.active_centers import ( + FUNCTIONAL_GROUPS, +) + + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == { + "vinyl_chain_end_radical", + } + + +def test_vinyl_chain_end_radical_metadata(): + group = FUNCTIONAL_GROUPS["vinyl_chain_end_radical"] + + assert group["functionality_type"] == "vinyl" + assert group["group_name"] == "vinyl_chain_end_radical" + assert group["comments"] is None + + +def test_vinyl_chain_end_radical_smarts_compiles(): + group = FUNCTIONAL_GROUPS["vinyl_chain_end_radical"] + + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert pattern is not None + + +def test_vinyl_chain_end_radical_smarts_matches_trivalent_non_ring_carbon(): + """ + A neutral trivalent carbon radical with three carbon neighbors + should match the active-center SMARTS. + """ + group = FUNCTIONAL_GROUPS["vinyl_chain_end_radical"] + + mol = Chem.MolFromSmiles("C[C](C)C") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 1 + + +def test_vinyl_chain_end_radical_smarts_does_not_match_saturated_carbon(): + """ + A normal tetravalent saturated carbon should not be identified + as a chain-end radical. + """ + group = FUNCTIONAL_GROUPS["vinyl_chain_end_radical"] + + mol = Chem.MolFromSmiles("CC(C)C") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert mol.GetSubstructMatches(pattern) == () + + +def test_vinyl_chain_end_radical_smarts_does_not_match_alkene_carbon(): + group = FUNCTIONAL_GROUPS["vinyl_chain_end_radical"] + + mol = Chem.MolFromSmiles("C=C(C)C") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert mol.GetSubstructMatches(pattern) == () + + +def test_vinyl_chain_end_radical_smarts_excludes_ring_carbon(): + """ + The !R condition should prevent ring atoms from being classified + as vinyl chain-end radicals. + """ + group = FUNCTIONAL_GROUPS["vinyl_chain_end_radical"] + + mol = Chem.MolFromSmiles("[C]1(C)CCC1") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert mol.GetSubstructMatches(pattern) == () + + +def test_vinyl_chain_end_radical_qualifies_through_detector(): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS["vinyl_chain_end_radical"] + + mol = Chem.MolFromSmiles("C[C](C)C") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + group["functionality_type"], + group["smarts_1"], + ) + ) + + assert functionality_count == 1 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_saturated_carbon_does_not_qualify_through_detector(): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS["vinyl_chain_end_radical"] + + mol = Chem.MolFromSmiles("CC(C)C") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + group["functionality_type"], + group["smarts_1"], + ) + ) + + assert functionality_count == 0 + assert count_1 == 0 + assert count_2 is None \ No newline at end of file diff --git a/tests/unit/detectors/functional_groups_library/test_carboxyl_and_carbonyl_groups.py b/tests/unit/detectors/functional_groups_library/test_carboxyl_and_carbonyl_groups.py new file mode 100644 index 00000000..069b49af --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_carboxyl_and_carbonyl_groups.py @@ -0,0 +1,284 @@ +import pytest +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.carboxyl_and_carbonyl_groups import ( + FUNCTIONAL_GROUPS, +) + + +EXPECTED_GROUPS = { + "di_carboxylic_acid_monomer", + "di_carboxylic_acid_halide_monomer", + "di_carboxylic_ester_monomer", + "phosgene_monomer", + "diphenyl_carbonate_monomer", +} + + +def detect(group_key, smiles): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS[group_key] + mol = Chem.MolFromSmiles(smiles) + + return detector.detect_monomer_functionality( + mol, + group["functionality_type"], + group["smarts_1"], + ) + + +# ============================================================================ +# Structure +# ============================================================================ + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == EXPECTED_GROUPS + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_required_fields_exist(group_key): + group = FUNCTIONAL_GROUPS[group_key] + + assert "functionality_type" in group + assert "smarts_1" in group + assert "group_name" in group + assert "comments" in group + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_all_smarts_compile(group_key): + pattern = Chem.MolFromSmarts( + FUNCTIONAL_GROUPS[group_key]["smarts_1"] + ) + + assert pattern is not None + + +# ============================================================================ +# Dicarboxylic acid +# ============================================================================ + +def test_dicarboxylic_acid_metadata(): + group = FUNCTIONAL_GROUPS["di_carboxylic_acid_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "di_carboxylic_acid" + + +def test_adipic_acid_has_two_carboxylic_acid_sites(): + result = detect( + "di_carboxylic_acid_monomer", + "O=C(O)CCCCC(=O)O", + ) + + functionality_count, count_1, count_2, matches = result + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_monocarboxylic_acid_is_rejected_as_dicarboxylic(): + result = detect( + "di_carboxylic_acid_monomer", + "CC(=O)O", + ) + + functionality_count, count_1, _, matches = result + + assert functionality_count == 0 + assert count_1 == 1 + assert len(matches) == 1 + + +def test_ester_does_not_match_carboxylic_acid(): + result = detect( + "di_carboxylic_acid_monomer", + "CC(=O)OC", + ) + + assert result == (0, 0, None, ()) + + +# ============================================================================ +# Dicarboxylic acid halide +# ============================================================================ + +def test_dicarboxylic_acid_halide_metadata(): + group = FUNCTIONAL_GROUPS[ + "di_carboxylic_acid_halide_monomer" + ] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "di_carboxylic_acid_halide" + + +def test_terephthaloyl_chloride_has_two_acid_halide_sites(): + result = detect( + "di_carboxylic_acid_halide_monomer", + "O=C(Cl)c1ccc(C(=O)Cl)cc1", + ) + + functionality_count, count_1, count_2, matches = result + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_single_acid_chloride_is_rejected_as_di_acid_halide(): + result = detect( + "di_carboxylic_acid_halide_monomer", + "CC(=O)Cl", + ) + + functionality_count, count_1, _, matches = result + + assert functionality_count == 0 + assert count_1 == 1 + assert len(matches) == 1 + + +# ============================================================================ +# Dicarboxylic ester +# ============================================================================ + +def test_dicarboxylic_ester_metadata(): + group = FUNCTIONAL_GROUPS["di_carboxylic_ester_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "di_carboxylic_ester" + + +def test_diester_has_two_ester_sites(): + result = detect( + "di_carboxylic_ester_monomer", + "COC(=O)CCCCC(=O)OC", + ) + + functionality_count, count_1, count_2, matches = result + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_single_ester_is_rejected_as_diester(): + result = detect( + "di_carboxylic_ester_monomer", + "CC(=O)OC", + ) + + functionality_count, count_1, _, matches = result + + assert functionality_count == 0 + assert count_1 == 1 + assert len(matches) == 1 + + +def test_carboxylic_acid_does_not_match_ester_pattern(): + result = detect( + "di_carboxylic_ester_monomer", + "CC(=O)O", + ) + + assert result == (0, 0, None, ()) + + +# ============================================================================ +# Phosgene +# ============================================================================ + +def test_phosgene_metadata(): + group = FUNCTIONAL_GROUPS["phosgene_monomer"] + + assert group["functionality_type"] == "mono" + assert group["group_name"] == "phosgene" + + +def test_phosgene_pattern_matches_phosgene_once(): + result = detect( + "phosgene_monomer", + "O=C(Cl)Cl", + ) + + functionality_count, count_1, count_2, matches = result + + assert functionality_count == 1 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +@pytest.mark.parametrize( + "smiles", + [ + "CC(=O)Cl", + "O=C(O)O", + "O=C(OC)OC", + ], +) +def test_phosgene_pattern_rejects_non_phosgene_carbonyls(smiles): + result = detect( + "phosgene_monomer", + smiles, + ) + + assert result == (0, 0, None, ()) + + +# ============================================================================ +# Diphenyl carbonate +# ============================================================================ + +def test_diphenyl_carbonate_metadata(): + group = FUNCTIONAL_GROUPS["diphenyl_carbonate_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "diphenyl_carbonate" + + +def test_diphenyl_carbonate_has_two_aryl_carbonate_matches(): + result = detect( + "diphenyl_carbonate_monomer", + "O=C(Oc1ccccc1)Oc1ccccc1", + ) + + functionality_count, count_1, count_2, matches = result + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_single_aryl_carbonate_side_is_rejected(): + """ + Methyl phenyl carbonate contains only one O-aryl carbonate match, + so it cannot satisfy the di_identical >= 2 rule. + """ + result = detect( + "diphenyl_carbonate_monomer", + "O=C(Oc1ccccc1)OC", + ) + + functionality_count, count_1, _, matches = result + + assert functionality_count == 0 + assert count_1 == 1 + assert len(matches) == 1 + + +def test_dimethyl_carbonate_does_not_match_diphenyl_carbonate(): + result = detect( + "diphenyl_carbonate_monomer", + "O=C(OC)OC", + ) + + assert result == (0, 0, None, ()) \ No newline at end of file diff --git a/tests/unit/detectors/functional_groups_library/test_oxygen_groups.py b/tests/unit/detectors/functional_groups_library/test_oxygen_groups.py index cab539c2..9af0c41b 100644 --- a/tests/unit/detectors/functional_groups_library/test_oxygen_groups.py +++ b/tests/unit/detectors/functional_groups_library/test_oxygen_groups.py @@ -1,157 +1,229 @@ import pytest from rdkit import Chem +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) from AutoREACTER.detectors.functional_groups_library.oxygen_groups import ( FUNCTIONAL_GROUPS, ) -# --------------------------------------------------------------------------- -# Basic library structure -# --------------------------------------------------------------------------- +# ============================================================================ +# Library structure +# ============================================================================ -def test_functional_groups_is_dict(): - """oxygen_groups should expose FUNCTIONAL_GROUPS as a dictionary.""" +def test_functional_groups_is_dictionary(): assert isinstance(FUNCTIONAL_GROUPS, dict) -def test_expected_active_groups_are_present(): - """The currently active oxygen functional groups should be registered.""" - assert set(FUNCTIONAL_GROUPS) == { +def test_expected_active_oxygen_groups(): + assert set(FUNCTIONAL_GROUPS.keys()) == { "diol_monomer", "water_monomer", } @pytest.mark.parametrize( - "group_key", + "group_name", [ "diol_monomer", "water_monomer", ], ) -def test_each_group_has_required_fields(group_key): - """Every oxygen functional-group definition should contain required fields.""" - entry = FUNCTIONAL_GROUPS[group_key] +def test_required_fields_exist(group_name): + group = FUNCTIONAL_GROUPS[group_name] + + assert "functionality_type" in group + assert "smarts_1" in group + assert "group_name" in group + assert "comments" in group - assert "functionality_type" in entry - assert "smarts_1" in entry - assert "group_name" in entry - assert "comments" in entry +# ============================================================================ +# Metadata +# ============================================================================ def test_diol_metadata(): - """The diol definition should expose the intended metadata.""" - entry = FUNCTIONAL_GROUPS["diol_monomer"] + group = FUNCTIONAL_GROUPS["diol_monomer"] - assert entry["functionality_type"] == "di_identical" - assert entry["group_name"] == "diol" - assert entry["comments"] is None + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "diol" + assert group["comments"] is None def test_water_metadata(): - """The water definition should expose the intended metadata.""" - entry = FUNCTIONAL_GROUPS["water_monomer"] + group = FUNCTIONAL_GROUPS["water_monomer"] - assert entry["functionality_type"] == "mono" - assert entry["group_name"] == "water" - assert entry["comments"] is None + assert group["functionality_type"] == "mono" + assert group["group_name"] == "water" + assert group["comments"] is None -# --------------------------------------------------------------------------- +# ============================================================================ # SMARTS validity -# --------------------------------------------------------------------------- +# ============================================================================ @pytest.mark.parametrize( - "group_key", + "group_name", [ "diol_monomer", "water_monomer", ], ) -def test_smarts_compiles(group_key): - """Every active oxygen SMARTS definition must compile with RDKit.""" - smarts = FUNCTIONAL_GROUPS[group_key]["smarts_1"] +def test_smarts_is_valid_rdkit_pattern(group_name): + smarts = FUNCTIONAL_GROUPS[group_name]["smarts_1"] pattern = Chem.MolFromSmarts(smarts) assert pattern is not None -# --------------------------------------------------------------------------- -# Diol hydroxyl SMARTS -# --------------------------------------------------------------------------- +# ============================================================================ +# Diol SMARTS behavior +# ============================================================================ -def test_diol_pattern_matches_two_hydroxyl_sites_in_ethylene_glycol(): - """ - The diol SMARTS describes an eligible hydroxyl site. +def test_diol_smarts_finds_two_sites_in_ethylene_glycol(): + group = FUNCTIONAL_GROUPS["diol_monomer"] - Ethylene glycol contains two such hydroxyl groups, so two matches - should be found. - """ - molecule = Chem.MolFromSmiles("OCCO") - pattern = Chem.MolFromSmarts( - FUNCTIONAL_GROUPS["diol_monomer"]["smarts_1"] - ) + mol = Chem.MolFromSmiles("OCCO") + pattern = Chem.MolFromSmarts(group["smarts_1"]) - matches = molecule.GetSubstructMatches(pattern) + matches = mol.GetSubstructMatches(pattern) assert len(matches) == 2 -def test_diol_pattern_matches_one_site_in_ethanol(): +def test_diol_smarts_finds_three_sites_in_glycerol(): + group = FUNCTIONAL_GROUPS["diol_monomer"] + + mol = Chem.MolFromSmiles("OCC(O)CO") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 3 + + +def test_diol_smarts_finds_only_one_site_in_ethanol(): """ - A monoalcohol contains one matching hydroxyl site. + The SMARTS identifies hydroxyl sites. - Whether a molecule qualifies as a diol based on the number of detected - sites belongs to detector logic, not the SMARTS library itself. + Ethanol contains one valid hydroxyl site, but the detector should later + reject it as a di_identical monomer because at least two sites are required. """ - molecule = Chem.MolFromSmiles("CCO") - pattern = Chem.MolFromSmarts( - FUNCTIONAL_GROUPS["diol_monomer"]["smarts_1"] - ) + group = FUNCTIONAL_GROUPS["diol_monomer"] - matches = molecule.GetSubstructMatches(pattern) + mol = Chem.MolFromSmiles("CCO") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) assert len(matches) == 1 -def test_diol_pattern_does_not_match_ether_oxygen(): - """An ether oxygen should not match the hydroxyl SMARTS.""" - molecule = Chem.MolFromSmiles("COC") - pattern = Chem.MolFromSmarts( - FUNCTIONAL_GROUPS["diol_monomer"]["smarts_1"] - ) +def test_diol_smarts_does_not_match_ether(): + group = FUNCTIONAL_GROUPS["diol_monomer"] - assert not molecule.HasSubstructMatch(pattern) + mol = Chem.MolFromSmiles("COC") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + matches = mol.GetSubstructMatches(pattern) -def test_diol_pattern_excludes_carboxylic_acid_hydroxyl(): - """ - The SMARTS explicitly excludes oxygen attached to a carbonyl center. + assert len(matches) == 0 - Therefore the hydroxyl oxygen of acetic acid should not be detected. + +def test_diol_smarts_excludes_carboxylic_acid_oh(): + """ + The diol SMARTS explicitly excludes oxygen bonded to a carbonyl carbon. """ - molecule = Chem.MolFromSmiles("CC(=O)O") - pattern = Chem.MolFromSmarts( - FUNCTIONAL_GROUPS["diol_monomer"]["smarts_1"] + group = FUNCTIONAL_GROUPS["diol_monomer"] + + mol = Chem.MolFromSmiles("CC(=O)O") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 0 + + +# ============================================================================ +# Diol behavior through FunctionalGroupsDetector +# ============================================================================ + +def test_ethylene_glycol_qualifies_as_diol(): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS["diol_monomer"] + + mol = Chem.MolFromSmiles("OCCO") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + group["functionality_type"], + group["smarts_1"], + ) ) - assert not molecule.HasSubstructMatch(pattern) + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 -# --------------------------------------------------------------------------- -# Water SMARTS -# --------------------------------------------------------------------------- +def test_ethanol_does_not_qualify_as_diol(): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS["diol_monomer"] -def test_water_pattern_matches_water(): - """The water SMARTS should match a water molecule.""" - molecule = Chem.MolFromSmiles("O") - pattern = Chem.MolFromSmarts( - FUNCTIONAL_GROUPS["water_monomer"]["smarts_1"] + mol = Chem.MolFromSmiles("CCO") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + group["functionality_type"], + group["smarts_1"], + ) ) - assert molecule.HasSubstructMatch(pattern) + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_glycerol_qualifies_and_preserves_three_site_count(): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS["diol_monomer"] + + mol = Chem.MolFromSmiles("OCC(O)CO") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + group["functionality_type"], + group["smarts_1"], + ) + ) + + assert functionality_count == 2 + assert count_1 == 3 + assert count_2 is None + assert len(matches) == 3 + + +# ============================================================================ +# Water SMARTS behavior +# ============================================================================ + +def test_water_smarts_matches_water(): + group = FUNCTIONAL_GROUPS["water_monomer"] + + mol = Chem.MolFromSmiles("O") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 1 @pytest.mark.parametrize( @@ -164,11 +236,56 @@ def test_water_pattern_matches_water(): "CC(=O)O", # acetic acid ], ) -def test_water_pattern_does_not_match_non_water_oxygen_compounds(smiles): - """The water SMARTS should not identify ordinary oxygen compounds as water.""" - molecule = Chem.MolFromSmiles(smiles) - pattern = Chem.MolFromSmarts( - FUNCTIONAL_GROUPS["water_monomer"]["smarts_1"] +def test_water_smarts_does_not_match_non_water_oxygen_compounds(smiles): + group = FUNCTIONAL_GROUPS["water_monomer"] + + mol = Chem.MolFromSmiles(smiles) + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 0 + + +# ============================================================================ +# Water behavior through FunctionalGroupsDetector +# ============================================================================ + +def test_water_qualifies_as_mono_functional(): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS["water_monomer"] + + mol = Chem.MolFromSmiles("O") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + group["functionality_type"], + group["smarts_1"], + ) + ) + + assert functionality_count == 1 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_ethanol_does_not_match_water_functionality(): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS["water_monomer"] + + mol = Chem.MolFromSmiles("CCO") + + functionality_count, count_1, count_2, matches = ( + detector.detect_monomer_functionality( + mol, + group["functionality_type"], + group["smarts_1"], + ) ) - assert not molecule.HasSubstructMatch(pattern) + assert functionality_count == 0 + assert count_1 == 0 + assert count_2 is None + assert matches == () \ No newline at end of file From faae321d235f558560943376b52502b0dcbf88ee Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 12:41:53 -0400 Subject: [PATCH 134/176] Add functional group library unit tests --- .../test_heterocumulene_groups.py | 121 +++++++ .../test_mixed_ab_groups.py | 323 ++++++++++++++++++ .../test_nitrogen_groups.py | 297 ++++++++++++++++ .../test_ring_groups.py | 146 ++++++++ 4 files changed, 887 insertions(+) create mode 100644 tests/unit/detectors/functional_groups_library/test_heterocumulene_groups.py create mode 100644 tests/unit/detectors/functional_groups_library/test_mixed_ab_groups.py create mode 100644 tests/unit/detectors/functional_groups_library/test_nitrogen_groups.py create mode 100644 tests/unit/detectors/functional_groups_library/test_ring_groups.py diff --git a/tests/unit/detectors/functional_groups_library/test_heterocumulene_groups.py b/tests/unit/detectors/functional_groups_library/test_heterocumulene_groups.py new file mode 100644 index 00000000..acb16e32 --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_heterocumulene_groups.py @@ -0,0 +1,121 @@ +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.heterocumulene_groups import ( + FUNCTIONAL_GROUPS, +) + + +def detect(smiles): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS["di_isocyanate_monomer"] + + return detector.detect_monomer_functionality( + Chem.MolFromSmiles(smiles), + group["functionality_type"], + group["smarts_1"], + ) + + +# ============================================================================ +# Structure / metadata +# ============================================================================ + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == { + "di_isocyanate_monomer", + } + + +def test_di_isocyanate_metadata(): + group = FUNCTIONAL_GROUPS["di_isocyanate_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "di_isocyanate" + assert group["comments"] is None + + +def test_di_isocyanate_smarts_compiles(): + group = FUNCTIONAL_GROUPS["di_isocyanate_monomer"] + + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert pattern is not None + + +# ============================================================================ +# SMARTS behavior +# ============================================================================ + +def test_diisocyanate_contains_two_isocyanate_sites(): + group = FUNCTIONAL_GROUPS["di_isocyanate_monomer"] + + mol = Chem.MolFromSmiles("O=C=NCCCCCCN=C=O") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 2 + + +def test_monoisocyanate_contains_one_isocyanate_site(): + group = FUNCTIONAL_GROUPS["di_isocyanate_monomer"] + + mol = Chem.MolFromSmiles("CN=C=O") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 1 + + +def test_amine_does_not_match_isocyanate(): + group = FUNCTIONAL_GROUPS["di_isocyanate_monomer"] + + mol = Chem.MolFromSmiles("NCCCCCCN") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert mol.GetSubstructMatches(pattern) == () + + +def test_carbon_dioxide_does_not_match_isocyanate(): + group = FUNCTIONAL_GROUPS["di_isocyanate_monomer"] + + mol = Chem.MolFromSmiles("O=C=O") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert mol.GetSubstructMatches(pattern) == () + + +# ============================================================================ +# Detector behavior +# ============================================================================ + +def test_diisocyanate_qualifies(): + functionality_count, count_1, count_2, matches = detect( + "O=C=NCCCCCCN=C=O" + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_monoisocyanate_is_rejected_as_diisocyanate(): + functionality_count, count_1, count_2, matches = detect( + "CN=C=O" + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_non_isocyanate_is_rejected(): + result = detect("NCCCCCCN") + + assert result == (0, 0, None, ()) \ No newline at end of file diff --git a/tests/unit/detectors/functional_groups_library/test_mixed_ab_groups.py b/tests/unit/detectors/functional_groups_library/test_mixed_ab_groups.py new file mode 100644 index 00000000..a8232079 --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_mixed_ab_groups.py @@ -0,0 +1,323 @@ +import pytest +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.mixed_ab_groups import ( + FUNCTIONAL_GROUPS, +) + + +EXPECTED_GROUPS = { + "hydroxy_carboxylic_acid_monomer", + "hydroxy_acid_halides_monomer", + "amino_acid_monomer", + "carboxylic_acid_acid_halide_monomer", + "hydroxy_thiol_monomer", +} + + +def detect(group_key, smiles): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS[group_key] + + return detector.detect_monomer_functionality( + Chem.MolFromSmiles(smiles), + group["functionality_type"], + group["smarts_1"], + group["smarts_2"], + ) + + +# ============================================================================ +# Structure +# ============================================================================ + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == EXPECTED_GROUPS + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_all_groups_are_di_different(group_key): + assert ( + FUNCTIONAL_GROUPS[group_key]["functionality_type"] + == "di_different" + ) + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_required_fields_exist(group_key): + group = FUNCTIONAL_GROUPS[group_key] + + assert "functionality_type" in group + assert "smarts_1" in group + assert "smarts_2" in group + assert "group_name" in group + assert "comments" in group + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_both_smarts_patterns_compile(group_key): + group = FUNCTIONAL_GROUPS[group_key] + + assert Chem.MolFromSmarts(group["smarts_1"]) is not None + assert Chem.MolFromSmarts(group["smarts_2"]) is not None + + +# ============================================================================ +# Hydroxy carboxylic acid +# ============================================================================ + +def test_hydroxy_carboxylic_acid_metadata(): + group = FUNCTIONAL_GROUPS[ + "hydroxy_carboxylic_acid_monomer" + ] + + assert group["group_name"] == "hydroxy_carboxylic_acid" + + +def test_lactic_acid_qualifies_as_hydroxy_carboxylic_acid(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_carboxylic_acid_monomer", + "CC(O)C(=O)O", + ) + + assert functionality_count == 2 + assert count_1 == 1 + assert count_2 == 1 + assert len(matches) == 2 + + +def test_carboxylic_acid_without_alcohol_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_carboxylic_acid_monomer", + "CC(=O)O", + ) + + assert functionality_count == 0 + assert count_1 == 0 + assert count_2 == 1 + assert len(matches) == 1 + + +def test_diol_without_carboxylic_acid_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_carboxylic_acid_monomer", + "OCCO", + ) + + assert functionality_count == 0 + assert count_1 == 2 + assert count_2 == 0 + assert len(matches) == 2 + + +# ============================================================================ +# Hydroxy acid halide +# ============================================================================ + +def test_hydroxy_acid_halide_metadata(): + group = FUNCTIONAL_GROUPS[ + "hydroxy_acid_halides_monomer" + ] + + assert group["group_name"] == "hydroxy_acid_halide" + + +def test_hydroxy_acid_chloride_qualifies(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_acid_halides_monomer", + "OCCC(=O)Cl", + ) + + assert functionality_count == 2 + assert count_1 == 1 + assert count_2 == 1 + assert len(matches) == 2 + + +def test_acid_chloride_without_hydroxyl_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_acid_halides_monomer", + "CCC(=O)Cl", + ) + + assert functionality_count == 0 + assert count_1 == 0 + assert count_2 == 1 + assert len(matches) == 1 + + +def test_alcohol_without_acid_halide_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_acid_halides_monomer", + "CCCO", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 == 0 + assert len(matches) == 1 + + +# ============================================================================ +# Amino acid +# ============================================================================ + +def test_amino_acid_metadata(): + group = FUNCTIONAL_GROUPS["amino_acid_monomer"] + + assert group["group_name"] == "amino_acid" + + +def test_glycine_qualifies_as_amino_acid(): + functionality_count, count_1, count_2, matches = detect( + "amino_acid_monomer", + "NCC(=O)O", + ) + + assert functionality_count == 2 + assert count_1 == 1 + assert count_2 == 1 + assert len(matches) == 2 + + +def test_amine_without_carboxylic_acid_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "amino_acid_monomer", + "CCN", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 == 0 + assert len(matches) == 1 + + +def test_carboxylic_acid_without_amine_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "amino_acid_monomer", + "CC(=O)O", + ) + + assert functionality_count == 0 + assert count_1 == 0 + assert count_2 == 1 + assert len(matches) == 1 + + +# ============================================================================ +# Carboxylic acid + acid halide +# ============================================================================ + +def test_carboxylic_acid_acid_halide_metadata(): + group = FUNCTIONAL_GROUPS[ + "carboxylic_acid_acid_halide_monomer" + ] + + assert group["group_name"] == "carboxylic_acid_acid_halide" + + +def test_acid_acid_chloride_qualifies(): + functionality_count, count_1, count_2, matches = detect( + "carboxylic_acid_acid_halide_monomer", + "O=C(O)CCC(=O)Cl", + ) + + assert functionality_count == 2 + assert count_1 == 1 + assert count_2 == 1 + assert len(matches) == 2 + + +def test_dicarboxylic_acid_without_halide_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "carboxylic_acid_acid_halide_monomer", + "O=C(O)CCC(=O)O", + ) + + assert functionality_count == 0 + assert count_1 == 2 + assert count_2 == 0 + assert len(matches) == 2 + + +def test_diacid_chloride_without_acid_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "carboxylic_acid_acid_halide_monomer", + "O=C(Cl)CCC(=O)Cl", + ) + + assert functionality_count == 0 + assert count_1 == 0 + assert count_2 == 2 + assert len(matches) == 2 + + +# ============================================================================ +# Hydroxy thiol +# ============================================================================ + +def test_hydroxy_thiol_metadata(): + group = FUNCTIONAL_GROUPS["hydroxy_thiol_monomer"] + + assert group["group_name"] == "hydroxy_thiol" + + +def test_hydroxy_thiol_qualifies(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_thiol_monomer", + "OCCS", + ) + + assert functionality_count == 2 + assert count_1 == 1 + assert count_2 == 1 + assert len(matches) == 2 + + +def test_alcohol_without_thiol_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_thiol_monomer", + "CCO", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 == 0 + assert len(matches) == 1 + + +def test_thiol_without_hydroxyl_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "hydroxy_thiol_monomer", + "CCS", + ) + + assert functionality_count == 0 + assert count_1 == 0 + assert count_2 == 1 + assert len(matches) == 1 + + +# ============================================================================ +# Multiplicity preservation +# ============================================================================ + +def test_di_different_preserves_unequal_site_counts(): + """ + A di_different monomer only requires >=1 of each type. + + Additional sites must remain visible in the returned counts because + downstream logic may use them for branching / reaction enumeration. + """ + functionality_count, count_1, count_2, matches = detect( + "hydroxy_carboxylic_acid_monomer", + "O=C(O)CC(O)(CC(=O)O)C(=O)O", + ) + + assert functionality_count == 2 + assert count_1 == 1 + assert count_2 == 3 + assert len(matches) == 4 \ No newline at end of file diff --git a/tests/unit/detectors/functional_groups_library/test_nitrogen_groups.py b/tests/unit/detectors/functional_groups_library/test_nitrogen_groups.py new file mode 100644 index 00000000..70c51c3f --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_nitrogen_groups.py @@ -0,0 +1,297 @@ +import pytest +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.nitrogen_groups import ( + FUNCTIONAL_GROUPS, +) + + +EXPECTED_GROUPS = { + "primary_amine_monomer", + "secondary_amine_monomer", + "di_amine_monomer", + "di_primary_amine_monomer", +} + + +def detect(group_key, smiles): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS[group_key] + + return detector.detect_monomer_functionality( + Chem.MolFromSmiles(smiles), + group["functionality_type"], + group["smarts_1"], + ) + + +# ============================================================================ +# Structure / metadata +# ============================================================================ + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == EXPECTED_GROUPS + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_required_fields_exist(group_key): + group = FUNCTIONAL_GROUPS[group_key] + + assert "functionality_type" in group + assert "smarts_1" in group + assert "group_name" in group + assert "comments" in group + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_all_smarts_compile(group_key): + pattern = Chem.MolFromSmarts( + FUNCTIONAL_GROUPS[group_key]["smarts_1"] + ) + + assert pattern is not None + + +def test_primary_amine_metadata(): + group = FUNCTIONAL_GROUPS["primary_amine_monomer"] + + assert group["functionality_type"] == "mono" + assert group["group_name"] == "primary_amine" + assert group["comments"] is None + + +def test_secondary_amine_metadata(): + group = FUNCTIONAL_GROUPS["secondary_amine_monomer"] + + assert group["functionality_type"] == "mono" + assert group["group_name"] == "secondary_amine" + assert group["comments"] is None + + +def test_di_amine_metadata(): + group = FUNCTIONAL_GROUPS["di_amine_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "di_amine" + + +def test_di_primary_amine_metadata(): + group = FUNCTIONAL_GROUPS["di_primary_amine_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "di_primary_amine" + + +# ============================================================================ +# Primary amine +# ============================================================================ + +def test_primary_amine_matches_ethylamine(): + functionality_count, count_1, count_2, matches = detect( + "primary_amine_monomer", + "CCN", + ) + + assert functionality_count == 1 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_primary_amine_matches_glycine_nitrogen(): + functionality_count, count_1, _, matches = detect( + "primary_amine_monomer", + "NCC(=O)O", + ) + + assert functionality_count == 1 + assert count_1 == 1 + assert len(matches) == 1 + + +def test_primary_amine_does_not_match_secondary_amine(): + result = detect( + "primary_amine_monomer", + "CNC", + ) + + assert result == (0, 0, None, ()) + + +def test_primary_amine_does_not_match_amide(): + """ + The SMARTS explicitly excludes N-C(=O) environments. + """ + result = detect( + "primary_amine_monomer", + "CC(=O)N", + ) + + assert result == (0, 0, None, ()) + + +# ============================================================================ +# Secondary amine +# ============================================================================ + +def test_secondary_amine_matches_dimethylamine(): + functionality_count, count_1, count_2, matches = detect( + "secondary_amine_monomer", + "CNC", + ) + + assert functionality_count == 1 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_secondary_amine_does_not_match_primary_amine(): + result = detect( + "secondary_amine_monomer", + "CCN", + ) + + assert result == (0, 0, None, ()) + + +def test_secondary_amine_does_not_match_tertiary_amine(): + result = detect( + "secondary_amine_monomer", + "CN(C)C", + ) + + assert result == (0, 0, None, ()) + + +def test_secondary_amine_does_not_match_secondary_amide(): + result = detect( + "secondary_amine_monomer", + "CC(=O)NC", + ) + + assert result == (0, 0, None, ()) + + +# ============================================================================ +# Di-amine +# ============================================================================ + +def test_ethylenediamine_qualifies_as_diamine(): + functionality_count, count_1, count_2, matches = detect( + "di_amine_monomer", + "NCCN", + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_hexamethylenediamine_qualifies_as_diamine(): + functionality_count, count_1, _, matches = detect( + "di_amine_monomer", + "NCCCCCCN", + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert len(matches) == 2 + + +def test_monoamine_is_rejected_as_diamine(): + functionality_count, count_1, count_2, matches = detect( + "di_amine_monomer", + "CCN", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_mixed_primary_secondary_diamine_qualifies_as_diamine(): + """ + di_amine permits both H2 and H1 nitrogens. + + N-methylethylenediamine has one primary and one secondary amine, + so both sites should be counted. + """ + functionality_count, count_1, _, matches = detect( + "di_amine_monomer", + "NCCNC", + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert len(matches) == 2 + + +# ============================================================================ +# Di-primary amine +# ============================================================================ + +def test_ethylenediamine_qualifies_as_di_primary_amine(): + functionality_count, count_1, count_2, matches = detect( + "di_primary_amine_monomer", + "NCCN", + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_hexamethylenediamine_qualifies_as_di_primary_amine(): + functionality_count, count_1, _, matches = detect( + "di_primary_amine_monomer", + "NCCCCCCN", + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert len(matches) == 2 + + +def test_single_primary_amine_is_rejected_as_di_primary(): + functionality_count, count_1, _, matches = detect( + "di_primary_amine_monomer", + "CCN", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert len(matches) == 1 + + +def test_primary_secondary_pair_is_not_di_primary(): + """ + N-methylethylenediamine contains only one primary amine. + + The secondary nitrogen must not count toward di_primary_amine. + """ + functionality_count, count_1, _, matches = detect( + "di_primary_amine_monomer", + "NCCNC", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert len(matches) == 1 + + +def test_amide_nitrogen_does_not_count_toward_di_primary(): + functionality_count, count_1, _, matches = detect( + "di_primary_amine_monomer", + "NCCC(=O)N", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert len(matches) == 1 \ No newline at end of file diff --git a/tests/unit/detectors/functional_groups_library/test_ring_groups.py b/tests/unit/detectors/functional_groups_library/test_ring_groups.py new file mode 100644 index 00000000..e10aed07 --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_ring_groups.py @@ -0,0 +1,146 @@ +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.ring_groups import ( + FUNCTIONAL_GROUPS, +) + + +GROUP_KEY = "di_epoxy_monomer" + + +def detect(smiles): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + return detector.detect_monomer_functionality( + Chem.MolFromSmiles(smiles), + group["functionality_type"], + group["smarts_1"], + ) + + +# ============================================================================ +# Structure / metadata +# ============================================================================ + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == { + "di_epoxy_monomer", + } + + +def test_di_epoxy_metadata(): + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "di_epoxide" + assert group["comments"] is None + + +def test_di_epoxy_smarts_compiles(): + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert pattern is not None + + +# ============================================================================ +# Epoxide SMARTS +# ============================================================================ + +def test_single_epoxide_ring_produces_one_match(): + """ + Ethylene oxide contains one three-membered C-O-C epoxide ring. + """ + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + mol = Chem.MolFromSmiles("C1CO1") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 1 + + +def test_two_separate_epoxide_rings_produce_two_matches(): + """ + Molecule containing two independent oxirane rings should expose + two epoxide reactive sites. + """ + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + mol = Chem.MolFromSmiles("C1OC1CC2CO2") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + matches = mol.GetSubstructMatches(pattern) + + assert len(matches) == 2 + + +def test_acyclic_ether_does_not_match_epoxide(): + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + mol = Chem.MolFromSmiles("COC") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert mol.GetSubstructMatches(pattern) == () + + +def test_tetrahydrofuran_does_not_match_epoxide(): + """ + A five-membered cyclic ether must not be mistaken for an epoxide. + """ + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + mol = Chem.MolFromSmiles("C1CCOC1") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert mol.GetSubstructMatches(pattern) == () + + +def test_cyclopropane_does_not_match_epoxide(): + """ + Ring size alone is insufficient; the epoxide oxygen must be present. + """ + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + mol = Chem.MolFromSmiles("C1CC1") + pattern = Chem.MolFromSmarts(group["smarts_1"]) + + assert mol.GetSubstructMatches(pattern) == () + + +# ============================================================================ +# Detector behavior +# ============================================================================ + +def test_single_epoxide_is_rejected_as_di_epoxide(): + functionality_count, count_1, count_2, matches = detect( + "C1CO1" + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_two_epoxide_sites_qualify_as_di_epoxide(): + functionality_count, count_1, count_2, matches = detect( + "C1OC1CC2CO2" + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_non_epoxide_is_rejected(): + result = detect("COC") + + assert result == (0, 0, None, ()) \ No newline at end of file From dda17fc50b6288980b2285da3d4613dfee6d84ea Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 13:00:55 -0400 Subject: [PATCH 135/176] Add unit tests for detector behaviors --- .../test_silicon_groups.py | 129 ++ .../test_sulfur_groups.py | 88 ++ .../test_vinyl_and_alkene_groups.py | 208 +++ .../detectors/test_non_monomer_detector.py | 1156 +++++++++++++++++ .../unit/detectors/test_reaction_detector.py | 937 +++++++++++++ 5 files changed, 2518 insertions(+) create mode 100644 tests/unit/detectors/functional_groups_library/test_silicon_groups.py create mode 100644 tests/unit/detectors/functional_groups_library/test_sulfur_groups.py create mode 100644 tests/unit/detectors/functional_groups_library/test_vinyl_and_alkene_groups.py create mode 100644 tests/unit/detectors/test_non_monomer_detector.py create mode 100644 tests/unit/detectors/test_reaction_detector.py diff --git a/tests/unit/detectors/functional_groups_library/test_silicon_groups.py b/tests/unit/detectors/functional_groups_library/test_silicon_groups.py new file mode 100644 index 00000000..8ddbb8f3 --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_silicon_groups.py @@ -0,0 +1,129 @@ +import pytest +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.silicon_groups import ( + FUNCTIONAL_GROUPS, +) + + +EXPECTED_GROUPS = { + "dichlorosilane_monomer", + "silanediol_monomer", +} + + +def detect(group_key, smiles): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS[group_key] + + return detector.detect_monomer_functionality( + Chem.MolFromSmiles(smiles), + group["functionality_type"], + group["smarts_1"], + ) + + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == EXPECTED_GROUPS + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_required_fields_exist(group_key): + group = FUNCTIONAL_GROUPS[group_key] + + assert "functionality_type" in group + assert "smarts_1" in group + assert "group_name" in group + assert "comments" in group + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_all_smarts_compile(group_key): + assert Chem.MolFromSmarts( + FUNCTIONAL_GROUPS[group_key]["smarts_1"] + ) is not None + + +def test_dichlorosilane_metadata(): + group = FUNCTIONAL_GROUPS["dichlorosilane_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "dichlorosilane" + assert group["comments"] is None + + +def test_silanediol_metadata(): + group = FUNCTIONAL_GROUPS["silanediol_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "silanediol" + assert group["comments"] is None + + +def test_dichlorosilane_has_two_si_cl_sites(): + functionality_count, count_1, count_2, matches = detect( + "dichlorosilane_monomer", + "Cl[Si](C)(C)Cl", + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_monochlorosilane_is_rejected(): + functionality_count, count_1, count_2, matches = detect( + "dichlorosilane_monomer", + "C[Si](C)(C)Cl", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_nonchlorinated_silane_does_not_match(): + result = detect( + "dichlorosilane_monomer", + "C[Si](C)(C)C", + ) + + assert result == (0, 0, None, ()) + + +def test_silanediol_has_two_si_oh_sites(): + functionality_count, count_1, count_2, matches = detect( + "silanediol_monomer", + "O[Si](C)(C)O", + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_single_silanol_is_rejected_as_silanediol(): + functionality_count, count_1, count_2, matches = detect( + "silanediol_monomer", + "C[Si](C)(C)O", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_regular_alcohol_does_not_match_silanediol(): + result = detect( + "silanediol_monomer", + "CCO", + ) + + assert result == (0, 0, None, ()) \ No newline at end of file diff --git a/tests/unit/detectors/functional_groups_library/test_sulfur_groups.py b/tests/unit/detectors/functional_groups_library/test_sulfur_groups.py new file mode 100644 index 00000000..6a2a6cbc --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_sulfur_groups.py @@ -0,0 +1,88 @@ +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.sulfur_groups import ( + FUNCTIONAL_GROUPS, +) + + +GROUP_KEY = "dithiol_monomer" + + +def detect(smiles): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + return detector.detect_monomer_functionality( + Chem.MolFromSmiles(smiles), + group["functionality_type"], + group["smarts_1"], + ) + + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == { + "dithiol_monomer", + } + + +def test_dithiol_metadata(): + group = FUNCTIONAL_GROUPS[GROUP_KEY] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "dithiol" + assert group["comments"] is None + + +def test_dithiol_smarts_compiles(): + assert Chem.MolFromSmarts( + FUNCTIONAL_GROUPS[GROUP_KEY]["smarts_1"] + ) is not None + + +def test_dithiol_has_two_thiol_sites(): + functionality_count, count_1, count_2, matches = detect( + "SCCS" + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_monothiol_is_rejected_as_dithiol(): + functionality_count, count_1, count_2, matches = detect( + "CCS" + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_thioether_does_not_match_thiol(): + result = detect( + "CSC" + ) + + assert result == (0, 0, None, ()) + + +def test_disulfide_does_not_match_thiol(): + result = detect( + "CSSC" + ) + + assert result == (0, 0, None, ()) + + +def test_carbonyl_attached_sulfur_is_excluded(): + result = detect( + "CC(=O)S" + ) + + assert result == (0, 0, None, ()) \ No newline at end of file diff --git a/tests/unit/detectors/functional_groups_library/test_vinyl_and_alkene_groups.py b/tests/unit/detectors/functional_groups_library/test_vinyl_and_alkene_groups.py new file mode 100644 index 00000000..6732ab64 --- /dev/null +++ b/tests/unit/detectors/functional_groups_library/test_vinyl_and_alkene_groups.py @@ -0,0 +1,208 @@ +import pytest +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupsDetector, +) +from AutoREACTER.detectors.functional_groups_library.vinyl_and_alkene_groups import ( + FUNCTIONAL_GROUPS, +) + + +EXPECTED_GROUPS = { + "vinyl_monomer", + "diene_monomer", + "tetrafluoroethylene_monomer", +} + + +def detect(group_key, smiles): + detector = FunctionalGroupsDetector() + group = FUNCTIONAL_GROUPS[group_key] + + return detector.detect_monomer_functionality( + Chem.MolFromSmiles(smiles), + group["functionality_type"], + group["smarts_1"], + ) + + +# ============================================================================ +# Structure / metadata +# ============================================================================ + +def test_expected_active_groups(): + assert set(FUNCTIONAL_GROUPS) == EXPECTED_GROUPS + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_required_fields_exist(group_key): + group = FUNCTIONAL_GROUPS[group_key] + + assert "functionality_type" in group + assert "smarts_1" in group + assert "group_name" in group + assert "comments" in group + + +@pytest.mark.parametrize("group_key", sorted(EXPECTED_GROUPS)) +def test_all_smarts_compile(group_key): + assert Chem.MolFromSmarts( + FUNCTIONAL_GROUPS[group_key]["smarts_1"] + ) is not None + + +def test_vinyl_metadata(): + group = FUNCTIONAL_GROUPS["vinyl_monomer"] + + assert group["functionality_type"] == "vinyl" + assert group["group_name"] == "vinyl" + + +def test_diene_metadata(): + group = FUNCTIONAL_GROUPS["diene_monomer"] + + assert group["functionality_type"] == "di_identical" + assert group["group_name"] == "diene" + + +def test_tetrafluoroethylene_metadata(): + group = FUNCTIONAL_GROUPS["tetrafluoroethylene_monomer"] + + assert group["functionality_type"] == "vinyl" + assert group["group_name"] == "tetrafluoroethylene" + + +# ============================================================================ +# Vinyl +# ============================================================================ + +@pytest.mark.parametrize( + "smiles", + [ + "C=C", # ethylene + "C=CC", # propene + "C=Cc1ccccc1", # styrene + "C=C(C)C", # substituted terminal alkene + ], +) +def test_terminal_vinyl_groups_qualify(smiles): + functionality_count, count_1, count_2, matches = detect( + "vinyl_monomer", + smiles, + ) + + assert functionality_count == 1 + assert count_1 >= 1 + assert count_2 is None + assert len(matches) == count_1 + + +def test_internal_alkene_does_not_match_terminal_vinyl(): + result = detect( + "vinyl_monomer", + "CC=CC", + ) + + assert result == (0, 0, None, ()) + + +def test_saturated_molecule_does_not_match_vinyl(): + result = detect( + "vinyl_monomer", + "CCCC", + ) + + assert result == (0, 0, None, ()) + + +def test_ring_double_bond_does_not_match_vinyl(): + result = detect( + "vinyl_monomer", + "C1=CCCCC1", + ) + + assert result == (0, 0, None, ()) + + +# ============================================================================ +# Diene +# ============================================================================ + +def test_butadiene_has_two_terminal_vinyl_sites(): + functionality_count, count_1, count_2, matches = detect( + "diene_monomer", + "C=CC=C", + ) + + assert functionality_count == 2 + assert count_1 == 2 + assert count_2 is None + assert len(matches) == 2 + + +def test_single_terminal_alkene_is_rejected_as_diene(): + functionality_count, count_1, count_2, matches = detect( + "diene_monomer", + "C=CCC", + ) + + assert functionality_count == 0 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +def test_internal_diene_without_terminal_ch2_is_rejected(): + result = detect( + "diene_monomer", + "CC=CC=CC", + ) + + assert result == (0, 0, None, ()) + + +def test_molecule_with_more_than_two_terminal_vinyl_sites_preserves_count(): + functionality_count, count_1, count_2, matches = detect( + "diene_monomer", + "C=C(C=C)C=C", + ) + + assert functionality_count == 2 + assert count_1 >= 2 + assert count_2 is None + assert len(matches) == count_1 + + +# ============================================================================ +# Tetrafluoroethylene +# ============================================================================ + +def test_tetrafluoroethylene_qualifies(): + functionality_count, count_1, count_2, matches = detect( + "tetrafluoroethylene_monomer", + "FC(F)=C(F)F", + ) + + assert functionality_count == 1 + assert count_1 == 1 + assert count_2 is None + assert len(matches) == 1 + + +@pytest.mark.parametrize( + "smiles", + [ + "C=C", + "C=CC", + "C=Cc1ccccc1", + "FC(F)=CC", + ], +) +def test_non_tetrafluoroethylene_alkenes_do_not_match(smiles): + result = detect( + "tetrafluoroethylene_monomer", + smiles, + ) + + assert result == (0, 0, None, ()) \ No newline at end of file diff --git a/tests/unit/detectors/test_non_monomer_detector.py b/tests/unit/detectors/test_non_monomer_detector.py new file mode 100644 index 00000000..dcd36c15 --- /dev/null +++ b/tests/unit/detectors/test_non_monomer_detector.py @@ -0,0 +1,1156 @@ +from dataclasses import dataclass +from types import SimpleNamespace + +import pytest +from rdkit import Chem + +from AutoREACTER.detectors.non_monomer_detector import ( + NonReactantsDetector, +) + + +# ============================================================================= +# Test helpers +# ============================================================================= + +@dataclass +class DummyMonomer: + """ + Minimal dataclass matching what NonReactantsDetector needs. + + A dataclass is intentionally used because non_reactant_selection() + calls dataclasses.replace(). + """ + id: int + name: str + smiles: str + rdkit_mol: object + status: bool = True + + +def make_monomer( + monomer_id: int, + name: str, + smiles: str, + *, + status=True, +): + return DummyMonomer( + id=monomer_id, + name=name, + smiles=smiles, + rdkit_mol=Chem.MolFromSmiles(smiles), + status=status, + ) + + +def make_reaction(smiles_1, smiles_2=None): + monomer_1 = SimpleNamespace(smiles=smiles_1) + + monomer_2 = ( + SimpleNamespace(smiles=smiles_2) + if smiles_2 is not None + else None + ) + + return SimpleNamespace( + monomer_1=monomer_1, + monomer_2=monomer_2, + ) + + +def make_session( + monomers=None, + reaction_instances=None, + non_reactants=None, +): + return SimpleNamespace( + inputs=SimpleNamespace(monomers=monomers or []), + reaction_instances=reaction_instances or [], + non_reactants=non_reactants or [], + ) + + +# ============================================================================= +# _same_molecule() +# ============================================================================= + +def test_same_molecule_adds_new_molecule(): + detector = NonReactantsDetector() + + reactants = [] + + result = detector._same_molecule( + reactants, + "CCO", + ) + + assert result == ["CCO"] + + +def test_same_molecule_does_not_duplicate_identical_smiles(): + detector = NonReactantsDetector() + + reactants = ["CCO"] + + result = detector._same_molecule( + reactants, + "CCO", + ) + + assert result == ["CCO"] + + +def test_same_molecule_uses_canonical_smiles(): + """ + OCC and CCO represent the same ethanol molecule. + + They should therefore not be stored twice. + """ + detector = NonReactantsDetector() + + reactants = ["CCO"] + + result = detector._same_molecule( + reactants, + "OCC", + ) + + assert result == ["CCO"] + + +def test_same_molecule_adds_structurally_different_molecule(): + detector = NonReactantsDetector() + + reactants = ["CCO"] + + result = detector._same_molecule( + reactants, + "CCN", + ) + + assert result == [ + "CCO", + "CCN", + ] + + +def test_same_molecule_invalid_smiles_is_not_added(): + detector = NonReactantsDetector() + + reactants = ["CCO"] + + result = detector._same_molecule( + reactants, + "this_is_not_smiles", + ) + + assert result == ["CCO"] + + +def test_same_molecule_modifies_original_list(): + """ + Current implementation appends directly to reactants_list. + + The returned object should therefore be the same list object. + """ + detector = NonReactantsDetector() + + reactants = [] + + result = detector._same_molecule( + reactants, + "CCO", + ) + + assert result is reactants + assert reactants == ["CCO"] + + +# ============================================================================= +# _same_molecule_for_initaials() +# ============================================================================= + +def test_same_molecule_for_initials_finds_identical_molecule(): + detector = NonReactantsDetector() + + reactants = ["CCO"] + mol = Chem.MolFromSmiles("CCO") + + result = detector._same_molecule_for_initaials( + reactants, + mol, + ) + + assert result is True + + +def test_same_molecule_for_initials_uses_canonical_structure(): + detector = NonReactantsDetector() + + reactants = ["CCO"] + mol = Chem.MolFromSmiles("OCC") + + result = detector._same_molecule_for_initaials( + reactants, + mol, + ) + + assert result is True + + +def test_same_molecule_for_initials_ignores_explicit_hydrogens(): + """ + Explicit hydrogens should not prevent structural equality. + """ + detector = NonReactantsDetector() + + reactants = ["CCO"] + + mol = Chem.AddHs( + Chem.MolFromSmiles("CCO") + ) + + result = detector._same_molecule_for_initaials( + reactants, + mol, + ) + + assert result is True + + +def test_same_molecule_for_initials_returns_false_for_different_molecule(): + detector = NonReactantsDetector() + + reactants = ["CCO"] + mol = Chem.MolFromSmiles("CCN") + + result = detector._same_molecule_for_initaials( + reactants, + mol, + ) + + assert result is False + + +def test_same_molecule_for_initials_returns_false_for_none(): + detector = NonReactantsDetector() + + result = detector._same_molecule_for_initaials( + ["CCO"], + None, + ) + + assert result is False + + +def test_same_molecule_for_initials_ignores_invalid_smiles_in_reactant_list(): + detector = NonReactantsDetector() + + reactants = [ + "invalid_smiles", + "CCO", + ] + + mol = Chem.MolFromSmiles("CCO") + + result = detector._same_molecule_for_initaials( + reactants, + mol, + ) + + assert result is True + + +def test_same_molecule_for_initials_empty_reactant_list_returns_false(): + detector = NonReactantsDetector() + + mol = Chem.MolFromSmiles("CCO") + + result = detector._same_molecule_for_initaials( + [], + mol, + ) + + assert result is False + + +# ============================================================================= +# non_monomer_detector() +# ============================================================================= + +def test_non_monomer_detector_identifies_unused_monomer(): + detector = NonReactantsDetector() + + ethanol = make_monomer( + 1, + "ethanol", + "CCO", + ) + + amine = make_monomer( + 2, + "ethylamine", + "CCN", + ) + + propane = make_monomer( + 3, + "propane", + "CCC", + ) + + reaction = make_reaction( + "CCO", + "CCN", + ) + + session = make_session( + monomers=[ + ethanol, + amine, + propane, + ], + reaction_instances=[reaction], + ) + + result = detector.non_monomer_detector(session) + + assert result is None + assert session.non_reactants == [ + propane, + ] + + +def test_non_monomer_detector_all_monomers_react(): + detector = NonReactantsDetector() + + ethanol = make_monomer( + 1, + "ethanol", + "CCO", + ) + + amine = make_monomer( + 2, + "ethylamine", + "CCN", + ) + + session = make_session( + monomers=[ + ethanol, + amine, + ], + reaction_instances=[ + make_reaction( + "CCO", + "CCN", + ) + ], + ) + + detector.non_monomer_detector(session) + + assert session.non_reactants == [] + + +def test_non_monomer_detector_no_reactions_marks_every_monomer_nonreactant(): + detector = NonReactantsDetector() + + monomers = [ + make_monomer( + 1, + "ethanol", + "CCO", + ), + make_monomer( + 2, + "ethylamine", + "CCN", + ), + ] + + session = make_session( + monomers=monomers, + reaction_instances=[], + ) + + detector.non_monomer_detector(session) + + assert session.non_reactants == monomers + + +def test_non_monomer_detector_handles_homopolymerization(): + """ + A ReactionInstance may contain only monomer_1. + + That molecule should still be recognized as a reactant. + """ + detector = NonReactantsDetector() + + styrene = make_monomer( + 1, + "styrene", + "C=Cc1ccccc1", + ) + + solvent = make_monomer( + 2, + "ethanol", + "CCO", + ) + + session = make_session( + monomers=[ + styrene, + solvent, + ], + reaction_instances=[ + make_reaction( + "C=Cc1ccccc1", + ) + ], + ) + + detector.non_monomer_detector(session) + + assert session.non_reactants == [ + solvent, + ] + + +def test_non_monomer_detector_uses_structural_equivalence_not_raw_string(): + detector = NonReactantsDetector() + + ethanol = make_monomer( + 1, + "ethanol", + "OCC", + ) + + session = make_session( + monomers=[ethanol], + reaction_instances=[ + make_reaction("CCO") + ], + ) + + detector.non_monomer_detector(session) + + assert session.non_reactants == [] + + +def test_non_monomer_detector_deduplicates_reactants_across_reactions(): + detector = NonReactantsDetector() + + ethanol = make_monomer( + 1, + "ethanol", + "CCO", + ) + + propane = make_monomer( + 2, + "propane", + "CCC", + ) + + session = make_session( + monomers=[ + ethanol, + propane, + ], + reaction_instances=[ + make_reaction("CCO"), + make_reaction("OCC"), + make_reaction("CCO"), + ], + ) + + detector.non_monomer_detector(session) + + assert session.non_reactants == [ + propane, + ] + + +# ============================================================================= +# non_reactants_to_visualization() +# ============================================================================= + +def test_non_reactants_visualization_returns_none_for_empty_list(): + detector = NonReactantsDetector() + + session = make_session( + non_reactants=[], + ) + + result = detector.non_reactants_to_visualization( + session + ) + + assert result is None + + +def test_non_reactants_visualization_passes_correct_data_to_rdkit( + monkeypatch, +): + detector = NonReactantsDetector() + + monomer_1 = make_monomer( + 1, + "ethanol", + "CCO", + ) + + monomer_2 = make_monomer( + 2, + "ethylamine", + "CCN", + ) + + session = make_session( + non_reactants=[ + monomer_1, + monomer_2, + ] + ) + + captured = {} + + fake_image = object() + + def fake_grid( + molecules, + legends, + molsPerRow, + subImgSize, + ): + captured["molecules"] = molecules + captured["legends"] = legends + captured["molsPerRow"] = molsPerRow + captured["subImgSize"] = subImgSize + + return fake_image + + monkeypatch.setattr( + "AutoREACTER.detectors.non_monomer_detector." + "Draw.MolsToGridImage", + fake_grid, + ) + + result = detector.non_reactants_to_visualization( + session + ) + + assert result is fake_image + + assert captured["molecules"] == [ + monomer_1.rdkit_mol, + monomer_2.rdkit_mol, + ] + + assert captured["legends"] == [ + "ethanol", + "ethylamine", + ] + + assert captured["molsPerRow"] == 3 + assert captured["subImgSize"] == ( + 400, + 400, + ) + + +# ============================================================================= +# non_reactant_selection() - no non-reactants +# ============================================================================= + +def test_selection_does_nothing_when_no_nonreactants(): + detector = NonReactantsDetector() + + monomer = make_monomer( + 1, + "ethanol", + "CCO", + ) + + session = make_session( + monomers=[monomer], + non_reactants=[], + ) + + result = detector.non_reactant_selection( + session + ) + + assert result is None + assert session.inputs.monomers == [ + monomer, + ] + + +# ============================================================================= +# non_reactant_selection() - one non-reactant +# ============================================================================= + +def test_single_nonreactant_N_discards_monomer( + monkeypatch, +): + detector = NonReactantsDetector() + + monomer = make_monomer( + 1, + "solvent", + "CCO", + ) + + session = make_session( + monomers=[monomer], + non_reactants=[monomer], + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: "N", + ) + + detector.non_reactant_selection(session) + + assert session.inputs.monomers[0].status is False + + +def test_single_nonreactant_A_keeps_monomer( + monkeypatch, +): + detector = NonReactantsDetector() + + monomer = make_monomer( + 1, + "solvent", + "CCO", + ) + + session = make_session( + monomers=[monomer], + non_reactants=[monomer], + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: "A", + ) + + detector.non_reactant_selection(session) + + assert session.inputs.monomers[0].status is True + + +def test_single_nonreactant_reprompts_invalid_input( + monkeypatch, +): + detector = NonReactantsDetector() + + monomer = make_monomer( + 1, + "solvent", + "CCO", + ) + + session = make_session( + monomers=[monomer], + non_reactants=[monomer], + ) + + responses = iter( + [ + "wrong", + "N", + ] + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: next(responses), + ) + + detector.non_reactant_selection(session) + + assert session.inputs.monomers[0].status is False + + +# ============================================================================= +# non_reactant_selection() - multiple non-reactants +# ============================================================================= + +def test_multiple_nonreactants_N_discards_all( + monkeypatch, +): + detector = NonReactantsDetector() + + m1 = make_monomer( + 1, + "M1", + "CCO", + ) + + m2 = make_monomer( + 2, + "M2", + "CCN", + ) + + reactive = make_monomer( + 3, + "reactive", + "CCC", + ) + + session = make_session( + monomers=[ + m1, + m2, + reactive, + ], + non_reactants=[ + m1, + m2, + ], + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: "N", + ) + + detector.non_reactant_selection(session) + + status_by_id = { + m.id: m.status + for m in session.inputs.monomers + } + + assert status_by_id == { + 1: False, + 2: False, + 3: True, + } + + +def test_multiple_nonreactants_A_keeps_all( + monkeypatch, +): + detector = NonReactantsDetector() + + m1 = make_monomer( + 1, + "M1", + "CCO", + ) + + m2 = make_monomer( + 2, + "M2", + "CCN", + ) + + session = make_session( + monomers=[ + m1, + m2, + ], + non_reactants=[ + m1, + m2, + ], + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: "A", + ) + + detector.non_reactant_selection(session) + + assert all( + m.status is True + for m in session.inputs.monomers + ) + + +def test_multiple_nonreactants_S_retains_selected_and_discards_others( + monkeypatch, +): + detector = NonReactantsDetector() + + m1 = make_monomer( + 1, + "M1", + "CCO", + ) + + m2 = make_monomer( + 2, + "M2", + "CCN", + ) + + m3 = make_monomer( + 3, + "M3", + "CCC", + ) + + session = make_session( + monomers=[ + m1, + m2, + m3, + ], + non_reactants=[ + m1, + m2, + m3, + ], + ) + + responses = iter( + [ + "S", + "1,3", + ] + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: next(responses), + ) + + detector.non_reactant_selection(session) + + status_by_id = { + m.id: m.status + for m in session.inputs.monomers + } + + assert status_by_id == { + 1: True, + 2: False, + 3: True, + } + + +def test_selective_mode_accepts_whitespace_and_duplicate_ids( + monkeypatch, +): + detector = NonReactantsDetector() + + m1 = make_monomer( + 1, + "M1", + "CCO", + ) + + m2 = make_monomer( + 2, + "M2", + "CCN", + ) + + session = make_session( + monomers=[ + m1, + m2, + ], + non_reactants=[ + m1, + m2, + ], + ) + + responses = iter( + [ + "S", + " 1, 1 ", + ] + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: next(responses), + ) + + detector.non_reactant_selection(session) + + status_by_id = { + m.id: m.status + for m in session.inputs.monomers + } + + assert status_by_id == { + 1: True, + 2: False, + } + + +def test_selective_mode_reprompts_for_noninteger_input( + monkeypatch, +): + detector = NonReactantsDetector() + + m1 = make_monomer( + 1, + "M1", + "CCO", + ) + + m2 = make_monomer( + 2, + "M2", + "CCN", + ) + + session = make_session( + monomers=[ + m1, + m2, + ], + non_reactants=[ + m1, + m2, + ], + ) + + responses = iter( + [ + "S", + "abc", + "S", + "1", + ] + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: next(responses), + ) + + detector.non_reactant_selection(session) + + status_by_id = { + m.id: m.status + for m in session.inputs.monomers + } + + assert status_by_id == { + 1: True, + 2: False, + } + + +def test_selective_mode_reprompts_for_unknown_id( + monkeypatch, +): + detector = NonReactantsDetector() + + m1 = make_monomer( + 1, + "M1", + "CCO", + ) + + m2 = make_monomer( + 2, + "M2", + "CCN", + ) + + session = make_session( + monomers=[ + m1, + m2, + ], + non_reactants=[ + m1, + m2, + ], + ) + + responses = iter( + [ + "S", + "99", + "S", + "2", + ] + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: next(responses), + ) + + detector.non_reactant_selection(session) + + status_by_id = { + m.id: m.status + for m in session.inputs.monomers + } + + assert status_by_id == { + 1: False, + 2: True, + } + + +def test_selective_mode_reprompts_for_empty_id_list( + monkeypatch, +): + detector = NonReactantsDetector() + + m1 = make_monomer( + 1, + "M1", + "CCO", + ) + + m2 = make_monomer( + 2, + "M2", + "CCN", + ) + + session = make_session( + monomers=[ + m1, + m2, + ], + non_reactants=[ + m1, + m2, + ], + ) + + responses = iter( + [ + "S", + "", + "S", + "1", + ] + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: next(responses), + ) + + detector.non_reactant_selection(session) + + status_by_id = { + m.id: m.status + for m in session.inputs.monomers + } + + assert status_by_id == { + 1: True, + 2: False, + } + + +def test_multiple_nonreactants_reprompts_invalid_main_option( + monkeypatch, +): + detector = NonReactantsDetector() + + m1 = make_monomer( + 1, + "M1", + "CCO", + ) + + m2 = make_monomer( + 2, + "M2", + "CCN", + ) + + session = make_session( + monomers=[ + m1, + m2, + ], + non_reactants=[ + m1, + m2, + ], + ) + + responses = iter( + [ + "wrong", + "N", + ] + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: next(responses), + ) + + detector.non_reactant_selection(session) + + assert all( + m.status is False + for m in session.inputs.monomers + ) + + +def test_selection_preserves_reactive_monomers( + monkeypatch, +): + """ + Discarding non-reactants must not accidentally change a monomer that + participates in a reaction. + """ + detector = NonReactantsDetector() + + nonreactant = make_monomer( + 1, + "solvent", + "CCO", + ) + + reactive = make_monomer( + 2, + "reactive", + "C=C", + ) + + session = make_session( + monomers=[ + nonreactant, + reactive, + ], + non_reactants=[ + nonreactant, + ], + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: "N", + ) + + detector.non_reactant_selection(session) + + status_by_id = { + m.id: m.status + for m in session.inputs.monomers + } + + assert status_by_id == { + 1: False, + 2: True, + } \ No newline at end of file diff --git a/tests/unit/detectors/test_reaction_detector.py b/tests/unit/detectors/test_reaction_detector.py new file mode 100644 index 00000000..4b000acd --- /dev/null +++ b/tests/unit/detectors/test_reaction_detector.py @@ -0,0 +1,937 @@ +from types import SimpleNamespace + +import pytest +from PIL import Image +from rdkit import Chem + +from AutoREACTER.detectors.functional_groups_detector import ( + FunctionalGroupInfo, + MonomerRole, +) +from AutoREACTER.detectors.reaction_detector import ( + EmptyReactionListError, + ReactionDetector, + ReactionInstance, + SMARTSerror, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + +def make_fg(name: str) -> FunctionalGroupInfo: + return FunctionalGroupInfo( + functionality_type="test", + fg_name=name, + fg_smarts_1="[*]", + fg_count_1=1, + ) + + +def make_role( + name: str, + smiles: str, + fg_names, + *, + is_looped=False, +) -> MonomerRole: + return MonomerRole( + name=name, + smiles=smiles, + functionalities=tuple(make_fg(fg) for fg in fg_names), + is_looped=is_looped, + ) + + +def make_session(monomer_roles=None, reaction_instances=None): + return SimpleNamespace( + monomer_roles=monomer_roles or [], + reaction_instances=reaction_instances or [], + ) + + +def homo_reaction( + reactant="vinyl", + *, + reaction_name="vinyl_polymerization", +): + return { + reaction_name: { + "reactant_1": reactant, + "reactant_2": None, + "same_reactants": True, + "reaction": "[*:1]>>[*:1]", + "delete_atom": False, + "reference": {"test": "reference"}, + } + } + + +def co_reaction( + reactant_1="A", + reactant_2="B", + *, + reaction_name="A_B_polymerization", +): + return { + reaction_name: { + "reactant_1": reactant_1, + "reactant_2": reactant_2, + "same_reactants": False, + "reaction": "[*:1].[*:2]>>[*:1]-[*:2]", + "delete_atom": True, + "reference": {"test": "reference"}, + } + } + + +# ============================================================================= +# ReactionInstance +# ============================================================================= + +def test_reaction_instance_stores_required_data(): + monomer = make_role("styrene", "C=Cc1ccccc1", ["vinyl"]) + fg = monomer.functionalities[0] + + instance = ReactionInstance( + reaction_name="vinyl_polymerization", + reaction_smarts="[*:1]>>[*:1]", + delete_atom=False, + references={"paper": "test"}, + same_reactants=True, + monomer_1=monomer, + functional_group_1=fg, + ) + + assert instance.reaction_name == "vinyl_polymerization" + assert instance.reaction_smarts == "[*:1]>>[*:1]" + assert instance.delete_atom is False + assert instance.references == {"paper": "test"} + assert instance.same_reactants is True + assert instance.monomer_1 is monomer + assert instance.functional_group_1 is fg + assert instance.monomer_2 is None + assert instance.functional_group_2 is None + + +# ============================================================================= +# _matching_fgs() +# ============================================================================= + +def test_matching_fgs_returns_matching_functionality(): + detector = ReactionDetector() + + monomer = make_role( + "test", + "CC", + ["vinyl", "diol", "primary_amine"], + ) + + result = detector._matching_fgs(monomer, "diol") + + assert len(result) == 1 + assert result[0].fg_name == "diol" + + +def test_matching_fgs_returns_all_matching_entries(): + detector = ReactionDetector() + + fg1 = make_fg("vinyl") + fg2 = make_fg("vinyl") + + monomer = MonomerRole( + name="test", + smiles="C=C", + functionalities=(fg1, fg2), + ) + + result = detector._matching_fgs(monomer, "vinyl") + + assert result == [fg1, fg2] + + +def test_matching_fgs_returns_empty_list_when_no_match(): + detector = ReactionDetector() + + monomer = make_role("test", "CCO", ["diol"]) + + assert detector._matching_fgs(monomer, "vinyl") == [] + + +# ============================================================================= +# _seen_pair_key() +# ============================================================================= + +def test_seen_pair_key_for_homopolymerization(): + detector = ReactionDetector() + + monomer = make_role("styrene", "C=Cc1ccccc1", ["vinyl"]) + fg = monomer.functionalities[0] + + key = detector._seen_pair_key( + "vinyl_polymerization", + monomer, + fg, + ) + + assert key == ( + "vinyl_polymerization", + "C=Cc1ccccc1", + "vinyl", + ) + + +def test_seen_pair_key_for_copolymerization_is_order_independent(): + detector = ReactionDetector() + + monomer_a = make_role("A", "CCO", ["A"]) + monomer_b = make_role("B", "CCN", ["B"]) + + key_ab = detector._seen_pair_key( + "reaction", + monomer_a, + monomer_a.functionalities[0], + monomer_b, + monomer_b.functionalities[0], + ) + + key_ba = detector._seen_pair_key( + "reaction", + monomer_b, + monomer_b.functionalities[0], + monomer_a, + monomer_a.functionalities[0], + ) + + assert key_ab == key_ba + + +def test_seen_pair_key_distinguishes_reaction_names(): + detector = ReactionDetector() + + monomer_a = make_role("A", "CCO", ["A"]) + monomer_b = make_role("B", "CCN", ["B"]) + + key_1 = detector._seen_pair_key( + "reaction_1", + monomer_a, + monomer_a.functionalities[0], + monomer_b, + monomer_b.functionalities[0], + ) + + key_2 = detector._seen_pair_key( + "reaction_2", + monomer_a, + monomer_a.functionalities[0], + monomer_b, + monomer_b.functionalities[0], + ) + + assert key_1 != key_2 + + +# ============================================================================= +# reaction_detector() - homopolymerization +# ============================================================================= + +def test_homopolymerization_is_detected(): + detector = ReactionDetector() + detector.reactions = homo_reaction() + + monomer = make_role( + "styrene", + "C=Cc1ccccc1", + ["vinyl"], + ) + + session = make_session([monomer]) + + result = detector.reaction_detector(session) + + assert result is None + assert len(session.reaction_instances) == 1 + + rxn = session.reaction_instances[0] + + assert rxn.reaction_name == "vinyl_polymerization" + assert rxn.same_reactants is True + assert rxn.monomer_1 is monomer + assert rxn.functional_group_1.fg_name == "vinyl" + assert rxn.monomer_2 is None + assert rxn.functional_group_2 is None + + +def test_homopolymerization_preserves_reaction_metadata(): + detector = ReactionDetector() + + detector.reactions = { + "test_reaction": { + "reactant_1": "vinyl", + "reactant_2": None, + "same_reactants": True, + "reaction": "TEST_SMARTS", + "delete_atom": True, + "reference": {"doi": "123"}, + } + } + + session = make_session( + [make_role("M", "C=C", ["vinyl"])] + ) + + detector.reaction_detector(session) + + rxn = session.reaction_instances[0] + + assert rxn.reaction_smarts == "TEST_SMARTS" + assert rxn.delete_atom is True + assert rxn.references == {"doi": "123"} + + +def test_duplicate_homo_functionalities_do_not_create_duplicate_reactions(): + detector = ReactionDetector() + detector.reactions = homo_reaction() + + monomer = make_role( + "test", + "C=C", + ["vinyl", "vinyl"], + ) + + session = make_session([monomer]) + + detector.reaction_detector(session) + + assert len(session.reaction_instances) == 1 + + +def test_multiple_different_homo_monomers_create_multiple_instances(): + detector = ReactionDetector() + detector.reactions = homo_reaction() + + monomer_1 = make_role("M1", "C=C", ["vinyl"]) + monomer_2 = make_role("M2", "C=CC", ["vinyl"]) + + session = make_session([monomer_1, monomer_2]) + + detector.reaction_detector(session) + + assert len(session.reaction_instances) == 2 + + +# ============================================================================= +# reaction_detector() - copolymerization +# ============================================================================= + +def test_copolymerization_detects_A_plus_B(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + monomer_a = make_role("A", "CCO", ["A"]) + monomer_b = make_role("B", "CCN", ["B"]) + + session = make_session([monomer_a, monomer_b]) + + detector.reaction_detector(session) + + assert len(session.reaction_instances) == 1 + + rxn = session.reaction_instances[0] + + assert rxn.monomer_1 is monomer_a + assert rxn.monomer_2 is monomer_b + assert rxn.functional_group_1.fg_name == "A" + assert rxn.functional_group_2.fg_name == "B" + assert rxn.same_reactants is False + + +def test_copolymerization_reverse_scan_does_not_duplicate_pair(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + monomer_a = make_role("A", "CCO", ["A"]) + monomer_b = make_role("B", "CCN", ["B"]) + + session = make_session( + [monomer_b, monomer_a] + ) + + detector.reaction_detector(session) + + assert len(session.reaction_instances) == 1 + + +def test_unrelated_monomer_is_ignored(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + monomer_a = make_role("A", "CCO", ["A"]) + monomer_b = make_role("B", "CCN", ["B"]) + unrelated = make_role("X", "CCC", ["X"]) + + session = make_session( + [monomer_a, monomer_b, unrelated] + ) + + detector.reaction_detector(session) + + assert len(session.reaction_instances) == 1 + + +# ============================================================================= +# Same molecule carrying A + B +# ============================================================================= + +def test_single_monomer_with_both_functional_groups_can_react(): + """ + A heterobifunctional monomer containing both A and B should be detected + by the special same-monomer A+B branch. + """ + detector = ReactionDetector() + detector.reactions = co_reaction() + + monomer = make_role( + "AB", + "NCC(=O)O", + ["A", "B"], + ) + + session = make_session([monomer]) + + detector.reaction_detector(session) + + assert len(session.reaction_instances) == 1 + + rxn = session.reaction_instances[0] + + assert rxn.monomer_1 is monomer + assert rxn.monomer_2 is monomer + assert rxn.functional_group_1.fg_name == "A" + assert rxn.functional_group_2.fg_name == "B" + + +def test_same_monomer_AB_reaction_not_duplicated(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + monomer = make_role( + "AB", + "NCC(=O)O", + ["A", "B"], + ) + + session = make_session([monomer]) + + detector.reaction_detector(session) + + assert len(session.reaction_instances) == 1 + + +# ============================================================================= +# Empty detection +# ============================================================================= + +def test_no_matching_reaction_raises_empty_reaction_error(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + session = make_session( + [make_role("X", "CCC", ["X"])] + ) + + with pytest.raises( + EmptyReactionListError, + match="No reaction instances found", + ): + detector.reaction_detector(session) + + +def test_empty_monomer_role_list_raises_empty_reaction_error(): + detector = ReactionDetector() + detector.reactions = homo_reaction() + + session = make_session([]) + + with pytest.raises(EmptyReactionListError): + detector.reaction_detector(session) + + +# ============================================================================= +# index_based_reaction_detector() - homo +# ============================================================================= + +def test_index_homo_fresh_role_is_detected(): + detector = ReactionDetector() + detector.reactions = homo_reaction() + + monomer = make_role( + "M", + "C=C", + ["vinyl"], + is_looped=False, + ) + + result = detector.index_based_reaction_detector([monomer]) + + assert len(result) == 1 + + +def test_index_homo_looped_role_is_skipped(): + detector = ReactionDetector() + detector.reactions = homo_reaction() + + monomer = make_role( + "M", + "C=C", + ["vinyl"], + is_looped=True, + ) + + result = detector.index_based_reaction_detector([monomer]) + + assert result == [] + + +# ============================================================================= +# index_based_reaction_detector() - co +# ============================================================================= + +def test_index_co_two_fresh_roles_are_detected(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + a = make_role("A", "CCO", ["A"]) + b = make_role("B", "CCN", ["B"]) + + result = detector.index_based_reaction_detector([a, b]) + + assert len(result) == 1 + + +@pytest.mark.parametrize( + "a_looped,b_looped", + [ + (True, False), + (False, True), + ], +) +def test_index_co_pair_is_kept_when_only_one_role_is_looped( + a_looped, + b_looped, +): + detector = ReactionDetector() + detector.reactions = co_reaction() + + a = make_role( + "A", + "CCO", + ["A"], + is_looped=a_looped, + ) + + b = make_role( + "B", + "CCN", + ["B"], + is_looped=b_looped, + ) + + result = detector.index_based_reaction_detector([a, b]) + + assert len(result) == 1 + + +def test_index_co_pair_is_skipped_when_both_roles_are_looped(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + a = make_role( + "A", + "CCO", + ["A"], + is_looped=True, + ) + + b = make_role( + "B", + "CCN", + ["B"], + is_looped=True, + ) + + result = detector.index_based_reaction_detector([a, b]) + + assert result == [] + + +def test_index_same_monomer_AB_fresh_role_is_detected(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + monomer = make_role( + "AB", + "NCC(=O)O", + ["A", "B"], + is_looped=False, + ) + + result = detector.index_based_reaction_detector([monomer]) + + assert len(result) == 1 + + assert result[0].monomer_1 is monomer + assert result[0].monomer_2 is monomer + + +def test_index_same_monomer_AB_looped_role_is_skipped(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + monomer = make_role( + "AB", + "NCC(=O)O", + ["A", "B"], + is_looped=True, + ) + + result = detector.index_based_reaction_detector([monomer]) + + assert result == [] + + +def test_index_detector_deduplicates_reaction_pairs(): + detector = ReactionDetector() + detector.reactions = co_reaction() + + a = make_role("A", "CCO", ["A", "A"]) + b = make_role("B", "CCN", ["B", "B"]) + + result = detector.index_based_reaction_detector([a, b]) + + assert len(result) == 1 + + +# ============================================================================= +# create_reaction_image() +# ============================================================================= + +def test_create_reaction_image_returns_generated_image(monkeypatch): + detector = ReactionDetector() + + product = Chem.MolFromSmiles("CO") + + class FakeEngine: + def RunReactants(self, reactants): + return ((product,),) + + monkeypatch.setattr( + "AutoREACTER.detectors.reaction_detector." + "rdChemReactions.ReactionFromSmarts", + lambda smarts: FakeEngine(), + ) + + fake_image = object() + + monkeypatch.setattr( + "AutoREACTER.detectors.reaction_detector." + "Draw.ReactionToImage", + lambda reaction, subImgSize: fake_image, + ) + + result = detector.create_reaction_image( + "C", + "O", + "fake_smarts", + "test_reaction", + ) + + assert result is fake_image + + +def test_create_reaction_image_tries_reverse_reactant_order(monkeypatch): + detector = ReactionDetector() + + product = Chem.MolFromSmiles("CO") + + class FakeEngine: + def __init__(self): + self.calls = 0 + + def RunReactants(self, reactants): + self.calls += 1 + + if self.calls == 1: + return () + + return ((product,),) + + engine = FakeEngine() + + monkeypatch.setattr( + "AutoREACTER.detectors.reaction_detector." + "rdChemReactions.ReactionFromSmarts", + lambda smarts: engine, + ) + + monkeypatch.setattr( + "AutoREACTER.detectors.reaction_detector." + "Draw.ReactionToImage", + lambda reaction, subImgSize: "image", + ) + + result = detector.create_reaction_image( + "C", + "O", + "fake_smarts", + "test", + ) + + assert result == "image" + assert engine.calls == 2 + + +def test_create_reaction_image_raises_when_both_orders_fail( + monkeypatch, +): + detector = ReactionDetector() + + class FakeEngine: + def RunReactants(self, reactants): + return () + + monkeypatch.setattr( + "AutoREACTER.detectors.reaction_detector." + "rdChemReactions.ReactionFromSmarts", + lambda smarts: FakeEngine(), + ) + + with pytest.raises( + SMARTSerror, + match="failed", + ): + detector.create_reaction_image( + "C", + "O", + "bad_reaction", + "test", + ) + + +# ============================================================================= +# available_reaction_image_grid() +# ============================================================================= + +def test_available_reaction_image_grid_stacks_images_vertically( + monkeypatch, +): + detector = ReactionDetector() + + m1 = make_role("A", "CCO", ["A"]) + m2 = make_role("B", "CCN", ["B"]) + + fg1 = m1.functionalities[0] + fg2 = m2.functionalities[0] + + reaction_1 = ReactionInstance( + reaction_name="R1", + reaction_smarts="x", + delete_atom=False, + references={}, + same_reactants=False, + monomer_1=m1, + functional_group_1=fg1, + monomer_2=m2, + functional_group_2=fg2, + ) + + reaction_2 = ReactionInstance( + reaction_name="R2", + reaction_smarts="x", + delete_atom=False, + references={}, + same_reactants=False, + monomer_1=m1, + functional_group_1=fg1, + monomer_2=m2, + functional_group_2=fg2, + ) + + monkeypatch.setattr( + detector, + "create_reaction_image", + lambda *args, **kwargs: Image.new( + "RGB", + (100, 50), + "white", + ), + ) + + session = make_session( + reaction_instances=[reaction_1, reaction_2] + ) + + result = detector.available_reaction_image_grid(session) + + assert isinstance(result, Image.Image) + assert result.size == (180, 100) + + +def test_available_reaction_image_grid_returns_none_when_empty(): + detector = ReactionDetector() + + session = make_session(reaction_instances=[]) + + result = detector.available_reaction_image_grid(session) + + assert result is None + + +def test_available_reaction_image_grid_skips_failed_visualizations( + monkeypatch, +): + detector = ReactionDetector() + + monomer = make_role("M", "C=C", ["vinyl"]) + + reaction = ReactionInstance( + reaction_name="R", + reaction_smarts="bad", + delete_atom=False, + references={}, + same_reactants=True, + monomer_1=monomer, + functional_group_1=monomer.functionalities[0], + ) + + def fail(*args, **kwargs): + raise SMARTSerror("bad SMARTS") + + monkeypatch.setattr( + detector, + "create_reaction_image", + fail, + ) + + session = make_session(reaction_instances=[reaction]) + + result = detector.available_reaction_image_grid(session) + + assert result is None + + +# ============================================================================= +# reaction_selection() +# ============================================================================= + +def test_reaction_selection_raises_for_empty_list(): + detector = ReactionDetector() + + session = make_session(reaction_instances=[]) + + with pytest.raises( + EmptyReactionListError, + match="Cannot proceed", + ): + detector.reaction_selection(session) + + +def test_reaction_selection_automatically_keeps_single_reaction(): + detector = ReactionDetector() + + monomer = make_role("M", "C=C", ["vinyl"]) + + reaction = ReactionInstance( + reaction_name="R", + reaction_smarts="x", + delete_atom=False, + references={}, + same_reactants=True, + monomer_1=monomer, + functional_group_1=monomer.functionalities[0], + ) + + session = make_session(reaction_instances=[reaction]) + + detector.reaction_selection(session) + + assert session.reaction_instances == [reaction] + + +def test_reaction_selection_selects_requested_reactions(monkeypatch): + detector = ReactionDetector() + + monomer = make_role("M", "C=C", ["vinyl"]) + fg = monomer.functionalities[0] + + reactions = [ + ReactionInstance( + reaction_name=f"R{i}", + reaction_smarts="x", + delete_atom=False, + references={}, + same_reactants=True, + monomer_1=monomer, + functional_group_1=fg, + ) + for i in range(1, 4) + ] + + session = make_session(reaction_instances=reactions) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: "3,1,3", + ) + + detector.reaction_selection(session) + + assert session.reaction_instances == [ + reactions[0], + reactions[2], + ] + + +def test_reaction_selection_reprompts_after_invalid_input( + monkeypatch, +): + detector = ReactionDetector() + + monomer = make_role("M", "C=C", ["vinyl"]) + fg = monomer.functionalities[0] + + reactions = [ + ReactionInstance( + reaction_name=f"R{i}", + reaction_smarts="x", + delete_atom=False, + references={}, + same_reactants=True, + monomer_1=monomer, + functional_group_1=fg, + ) + for i in range(1, 3) + ] + + session = make_session(reaction_instances=reactions) + + responses = iter( + [ + "", + "abc", + "9", + "2", + ] + ) + + monkeypatch.setattr( + "builtins.input", + lambda prompt: next(responses), + ) + + detector.reaction_selection(session) + + assert session.reaction_instances == [ + reactions[1] + ] \ No newline at end of file From f19c919487603de0e5cee4e62187420346c358b5 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 13:01:41 -0400 Subject: [PATCH 136/176] Remove deprecated detector workflow module --- AutoREACTER/detectors/detector.py | 259 ------------------------------ 1 file changed, 259 deletions(-) delete mode 100644 AutoREACTER/detectors/detector.py diff --git a/AutoREACTER/detectors/detector.py b/AutoREACTER/detectors/detector.py deleted file mode 100644 index 1f101470..00000000 --- a/AutoREACTER/detectors/detector.py +++ /dev/null @@ -1,259 +0,0 @@ -""" -Module for detecting reactions and handling non-reactant monomers. - -This module provides functionality to analyze a set of input monomers, detect -potential chemical reactions based on functional groups, and identify monomers -that do not participate in any detected reactions. It also includes an interactive -workflow to allow users to decide whether to retain non-reactant molecules in -the simulation. -""" - -import warnings -import os, json - -if os.environ.get("AUTOREACTER_SHOW_DEPRECATION", "").lower() in {"1", "true", "yes", "on"}: - warnings.warn( - """This script is deprecated and will be modified in future versions. Within v0.2, the whole package will primaraliy - support on jupyter notebook and the CLI is removed. Please use the notebook version for now and refer to the README for how to use the package.""", - DeprecationWarning, - stacklevel=2 - ) - -# Attempt to import detector modules. Handles different import paths depending on -# whether the script is run as a module, part of a package, or standalone. -try: - from functional_groups_detector import FunctionalGroupsDetector - from reaction_detector import ReactionDetector -except (ImportError, ModuleNotFoundError): - from .functional_groups_detector import FunctionalGroupsDetector - from .reaction_detector import ReactionDetector - -from AutoREACTER.input_parser import MonomerEntry - -class Detector: - """ - A class to encapsulate the reaction detection workflow. - - This class provides methods to detect reactions based on input monomers and - to identify non-reactant monomers. It serves as a structured way to organize - the detection logic and can be extended in the future for additional functionality. - """ - def __init__(self, input_dict: dict, interactive: bool = True): - """ - Initializes the Detector with the given input dictionary. - - Args: - input_dict (dict): A dictionary containing the 'monomers' key, which maps - monomer IDs (int/str) to SMILES strings (str). - interactive (bool): If False, automatically retain all non-reactants without prompting. - """ - self.input_dict = input_dict - self.reactions = {} - self.non_reactants_list = [] - self.functional_groups_detector = FunctionalGroupsDetector() - self.reactions_detector = ReactionDetector() - self.reactions_dict, self.non_reactants_list, self.input_dict = self.detect_reactions(self.input_dict) - - def find_non_reactant_monomers(self, reactions_dict, input_dict) -> list: - """ - Identifies monomers from the input that are not participating in any detected reactions - and prompts the user to decide whether to retain them in the simulation. - Args: - reactions_dict (dict): A dictionary containing detected reaction data. Expected keys - include 'monomer_1', 'monomer_2', and 'smiles' for each reaction entry. - input_dict (dict): The original input dictionary containing a 'monomers' key - mapping monomer IDs to SMILES strings. - interactive (bool): If False, automatically retain all non-reactants without prompting. - - Returns: - list: A list of SMILES strings representing the non-reactant monomers selected - by the user to be retained. Returns an empty list if the user chooses - to proceed with reactants only. - """ - # 1) Collect all unique SMILES strings that participate in detected reactions - reactant_smiles = set() - - for reaction_data in reactions_dict.values(): - # Extract SMILES for monomer 1, monomer 2, and the reaction itself - for k, v in reaction_data.items(): - if not str(k).isdigit(): - continue - if not isinstance(v, dict): - continue - - m1 = v.get("monomer_1", {}).get("smiles") - m2 = v.get("monomer_2", {}).get("smiles") - - if isinstance(m1, str): - reactant_smiles.add(m1) - if isinstance(m2, str): - reactant_smiles.add(m2) - - # 2) Build a dictionary of monomers that are not found in the reactant set - monomers = input_dict.get("monomers", {}) - self.non_reactants = {} - - # Re-index non-reactants starting from ID 1 - new_id = 1 - for _, smi in monomers.items(): - if smi not in reactant_smiles: - self.non_reactants[new_id] = smi - new_id += 1 - - # 3) Handle user interaction if non-reactant monomers are found - if self.non_reactants: - print( - "\nThere are non-reactant monomers/molecules in the input.\n" - "There may be reactions possible with the given monomers in the user inputs,\n" - "but some of them are not detected for a reaction.\n" - "You can choose to retain some or all of these non-reactant molecules in the simulation.\n" - "Non-reactant molecules:" - ) - # Display the list of non-reactant molecules to the user - for mid, molecule in self.non_reactants.items(): - print(f"{mid}. {molecule}") - - # Ask user if they want to exclude all non-reactants - select = input( - "Do you want to proceed with monomers only (no non-monomer molecules)? (y/n): " - ).strip().lower() - - if select == "y": - print("Proceeding with monomers only. No non-monomer molecules will be retained.") - self.non_reactants_list = [] # Return empty list if user declines non-reactants - else: - # Ask user to specify which non-reactants to keep by ID - self.selected_non_reactants = input( - "Please specify the monomer IDs (comma-separated) you wish to retain as non-monomer molecules: " - ).strip() - - # Parse the comma-separated input into a set of IDs - selected_ids = {s.strip() for s in self.selected_non_reactants.split(",") if s.strip()} - - # Filter the non-reactants dictionary based on user selection - # strings only (SMILES) - self.non_reactants_list = [ - smi - for mid, smi in self.non_reactants.items() - if str(mid) in selected_ids - ] - - return self.non_reactants_list - - # Return empty list if no non-reactants were found - return [] - - def filter_simulation_molecules(self, input_dict, non_reactants_list, reactions_dict): - """ - Filters the input monomers to include only those that are part of detected reactions - and any non-reactant monomers that the user has chosen to retain. - - Args: - input_dict (dict): The original input dictionary containing a 'monomers' key mapping monomer IDs to SMILES strings. - non_reactants_list (list): A list of SMILES strings for non-reactant monomers that the user has chosen to retain. - reactions_dict (dict): A dictionary containing detected reaction data. - Returns: - dict: A filtered dictionary of monomers that includes only those participating in reactions and the selected non-reactants. - """ - # Collect SMILES of reactants from detected reactions - reactant_smiles = set() - for reaction_data in reactions_dict.values(): - for k, v in reaction_data.items(): - if not str(k).isdigit(): - continue - if not isinstance(v, dict): - continue - - m1 = v.get("monomer_1", {}).get("smiles") - m2 = v.get("monomer_2", {}).get("smiles") - - if isinstance(m1, str): - reactant_smiles.add(m1) - if isinstance(m2, str): - reactant_smiles.add(m2) - - # Combine reactant SMILES with the selected non-reactant SMILES - combined = reactant_smiles | set(non_reactants_list) - - # Filter input monomers to include only reactants and selected non-reactants - monomers_dict_from_input = input_dict.get("monomers", {}) - for k in list(monomers_dict_from_input.keys()): - if monomers_dict_from_input[k] not in combined: - del monomers_dict_from_input[k] - - # Update the input dictionary with the filtered monomers - input_dict["monomers"] = monomers_dict_from_input # Update the input dictionary with the filtered monomers - - return input_dict - - - def detect_reactions(self, monomer_entry: MonomerEntry, interactive=True) -> tuple: - """ - Detects chemical reactions and identifies non-reactant monomers based on the provided input. - - This function serves as the main workflow controller. It validates the input, - detects functional groups, selects appropriate reactions, and identifies any - monomers that did not participate in the detected reactions. - - Args: - monomer_entry (MonomerEntry): A MonomerEntry object containing the monomers data. - - Returns: - tuple: A tuple containing: - - dict: The detected reactions. - - list: A list of SMILES strings for non-reactant monomers to be retained. - - Raises: - ValueError: If the input dictionary is missing the 'monomers' key or if it is empty. - """ - - # Step 1: Detect functional groups within the monomers - fg_results = self.functional_groups_detector.functional_groups_detector(monomer_entry) - - # Debug: Print detected functional groups - # print("Detected Functional Groups:", json.dumps(fg_results, indent=2)) - - # Step 2: Select reactions based on the detected functional groups - reactions = self.reactions_detector.reaction_detector(fg_results) - - # Debug: Print detected reactions - # print("Detected Reactions:", json.dumps(reactions, indent=2)) - - # Print detected reactions - print("\nDetected Reactions:") - for reaction_name, reaction_data in reactions.items(): - print(f"\n{reaction_name}:") - monomer_1 = reaction_data.get("reactant_1", {}) - monomer_2 = reaction_data.get("reactant_2", {}) - if monomer_2: - print(f"Reaction between {monomer_1} and {monomer_2}") - else: - print(f"Reaction involving {monomer_1}") - - # Step 3: Identify and handle monomers that are not part of any detected reaction - non_reactants_list = self.find_non_reactant_monomers(reactions, self.input_dict) - - # Update the input dictionary to include only reactants and selected non-reactants - self.input_dict = self.filter_simulation_molecules(self.input_dict, non_reactants_list, reactions) - - return reactions, non_reactants_list , self.input_dict - - -if __name__ == "__main__": - # Example usage of the module with sample monomer data - sample_inputs = { - "monomers": { - 1: "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O", # Example monomer 1 - Trimesoyl chloride (TMC) - 2: "C1=CC(=CC(=C1)N)N", # Example monomer 2 - m-Phenylenediamine (MPD) - 3: "CCO", # Example Non - monomer - Ethanol - } - } - - # Run the detection workflow - detector = Detector(sample_inputs) - print("Detected Reactions:", json.dumps(detector.reactions_dict, indent=2)) - # Output results - print("Detected Reactions:", json.dumps(detector.reactions_dict, indent=2)) - if detector.non_reactants_list: - print("Non-monomer molecules to retain:", detector.non_reactants_list) - print("Filtered Input Dictionary for Simulation:", json.dumps(detector.input_dict, indent=2)) From 7e71d7880b074643769a4dbbb26d4aba80f83827 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:33:42 -0400 Subject: [PATCH 137/176] Add unit tests for all reaction library modules --- .../reactions_library/thiol_ene_polymers.py | 33 +- .../reactions_library/vinyl_polymers.py | 487 +++++--- .../reaction_processor/warning_asci.py | 2 +- AutoREACTER/session.py | 6 +- examples/test_styrene.json | 2 +- .../reactions_library/test_epoxy_polymers.py | 338 ++++++ .../reactions_library/test_polyamides.py | 456 ++++++++ .../reactions_library/test_polyanhydrides.py | 242 ++++ .../reactions_library/test_polycarbonates.py | 220 ++++ .../reactions_library/test_polyesters.py | 399 +++++++ .../reactions_library/test_polysiloxanes.py | 126 ++ .../reactions_library/test_polythioesters.py | 144 +++ .../reactions_library/test_polyureas.py | 76 ++ .../reactions_library/test_polyurethanes.py | 108 ++ .../test_thiol_ene_polymers.py | 87 ++ .../reactions_library/test_vinyl_polymers.py | 349 ++++++ tests/unit/test_session.py | 1040 +++++++++++++++++ 17 files changed, 3957 insertions(+), 158 deletions(-) create mode 100644 tests/unit/detectors/reactions_library/test_epoxy_polymers.py create mode 100644 tests/unit/detectors/reactions_library/test_polyamides.py create mode 100644 tests/unit/detectors/reactions_library/test_polyanhydrides.py create mode 100644 tests/unit/detectors/reactions_library/test_polycarbonates.py create mode 100644 tests/unit/detectors/reactions_library/test_polyesters.py create mode 100644 tests/unit/detectors/reactions_library/test_polysiloxanes.py create mode 100644 tests/unit/detectors/reactions_library/test_polythioesters.py create mode 100644 tests/unit/detectors/reactions_library/test_polyureas.py create mode 100644 tests/unit/detectors/reactions_library/test_polyurethanes.py create mode 100644 tests/unit/detectors/reactions_library/test_thiol_ene_polymers.py create mode 100644 tests/unit/detectors/reactions_library/test_vinyl_polymers.py create mode 100644 tests/unit/test_session.py diff --git a/AutoREACTER/detectors/reactions_library/thiol_ene_polymers.py b/AutoREACTER/detectors/reactions_library/thiol_ene_polymers.py index c14641e3..59b9a9da 100644 --- a/AutoREACTER/detectors/reactions_library/thiol_ene_polymers.py +++ b/AutoREACTER/detectors/reactions_library/thiol_ene_polymers.py @@ -5,11 +5,40 @@ 'reactant_2': 'diene', 'product': 'poly_thioether_chain', 'delete_atom': False, - 'reaction': '[SX2H1:1]-[H:5].[CH2:2]=[C;!R:3]>>[SX2:1]-[CH2:2]-[C:3]-[H:5]', + + # Thiol-ene addition: + # + # S-H + CH2=C + # ↓ + # S-CH2-C-H + # + # AutoREACTER/LAMMPS convention: + # maps 1 and 2 are the initiator atoms + # the new bond is 1-2 + # + # Important: + # Product map 2 is written as [C:2], not [CH2:2]. + # When reactants contain explicit hydrogens (Chem.AddHs), + # [CH2:2] would add an additional hydrogen specification + # while RDKit also preserves the mapped atom's existing H + # neighbors, producing an invalid carbon valence. + # + # Map 1 = thiol sulfur + # Map 2 = terminal alkene carbon + # Map 3 = substituted alkene carbon + # Map 5 = transferred thiol hydrogen + 'reaction': ( + '[SX2H1:1]-[H:5].' + '[CH2:2]=[C;!R:3]' + '>>' + '[SX2:1]-[C:2]-[C:3]-[H:5]' + ), + 'reference': { - 'smarts': None, + 'smarts': None, 'reaction_and_mechanism': None }, + 'comments': None } } \ No newline at end of file diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py index cede3a3e..a8c24d95 100644 --- a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -1,9 +1,15 @@ REACTIONS = { + + # ========================================================================= + # Vinyl Addition Polymerization + # ========================================================================= + 'Vinyl Addition Polymerization Initiation': { 'same_reactants': True, 'reactant_1': 'vinyl', 'product': 'vinyl_chain_end_radical', 'delete_atom': False, + # H-T self-initiation cheat: # # tail=head + tail=head @@ -24,8 +30,14 @@ '>>' '[CH3:3]-[C:1]-[CH2:2]-[C;!R:4]' ), - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None, + 'notes': ( 'Self-initiation cheat for styrene/vinyl. H-T topology. ' 'New bond is maps 1-2. Map 3 is capped as CH3 so the ' @@ -34,12 +46,14 @@ ), }, + 'Vinyl Addition Polymerization Propagation': { 'same_reactants': False, 'reactant_1': 'vinyl', 'reactant_2': 'vinyl_chain_end_radical', 'product': 'vinyl_chain_end_radical', 'delete_atom': False, + # H-T propagation: # # chain-head* + tail=head @@ -53,6 +67,7 @@ # Map 1 = existing radical chain end/head. # This is forced by the loop-detected # vinyl_chain_end_radical index. + # # Map 2 = incoming vinyl terminal CH2 tail # Map 3 = incoming vinyl substituted head; becomes new radical 'reaction': ( @@ -61,8 +76,14 @@ '>>' '[C:1]-[CH2:2]-[C;!R:3]' ), - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + 'comments': None, + 'notes': ( 'Head-to-tail vinyl propagation. Existing chain-end radical map ' '1 bonds to incoming vinyl tail map 2. Map 3 becomes the new ' @@ -70,144 +91,235 @@ 'radical detection during loop progression.' ), }, -# Users can uncomment the following reactions if they want to include vinyl radical coupling termination in their simulation. However, this reaction is typically controlled separately from initiation and propagation to avoid premature termination of vinyl growth. -# 'Vinyl Radical Coupling Termination': { -# 'same_reactants': True, -# 'reactant_1': 'vinyl_chain_end_radical', -# 'product': 'vinyl_terminated_chain', -# 'delete_atom': False, - -# # H-H radical coupling termination: -# # -# # chain-head* + *head-chain -# # ↓ -# # chain-head-head-chain -# # -# # This is intentionally the only head-to-head vinyl step. -# # Initiation and propagation remain head-to-tail. -# # -# # AutoREACTER/LAMMPS rule: -# # maps 1 and 2 are the initiator atoms. -# # the new termination bond is 1-2. -# # -# # Map 1 = active radical head carbon on one vinyl chain end. -# # Map 2 = active radical head carbon on another vinyl chain end. -# # -# # The D3/v3/+0 constraints make this target the methacrylate-style -# # chain-end radical center instead of any ordinary acyclic carbon. -# 'reaction': ( -# '[C;!R;D3;v3;+0:1].' -# '[C;!R;D3;v3;+0:2]' -# '>>' -# '[C:1]-[C:2]' -# ), - -# 'reference': {'smarts': None, 'reaction_and_mechanism': None}, -# 'comments': None, -# 'notes': ( -# 'Head-to-head radical coupling termination for PMMA/TEGDMA-style ' -# 'vinyl chain ends. Maps 1 and 2 are the two active radical head ' -# 'carbons and form the new 1-2 termination bond. This reaction ' -# 'should be controlled separately from initiation and propagation, ' -# 'usually turned on late or pulsed so it does not kill vinyl growth ' -# 'too early.' -# ), -# }, -'Vinyl Copolymerization Initiation': { - 'same_reactants': False, - 'reactant_1': 'vinyl', - 'reactant_2': 'vinyl', - 'product': 'vinyl_chain_end_radical', - 'delete_atom': False, - - # H-T branchable-vinyl copolymerization initiation: + + + # ========================================================================= + # Optional Vinyl Radical Coupling Termination + # ========================================================================= + # + # Users can uncomment this reaction if they want to include vinyl radical + # coupling termination in the simulation. + # + # It is normally controlled separately from initiation and propagation + # so that vinyl growth is not terminated too early. + # + # 'Vinyl Radical Coupling Termination': { + # 'same_reactants': True, + # 'reactant_1': 'vinyl_chain_end_radical', + # 'product': 'vinyl_terminated_chain', + # 'delete_atom': False, + # + # # H-H radical coupling termination: + # # + # # chain-head* + *head-chain + # # ↓ + # # chain-head-head-chain + # # + # # This is intentionally the only head-to-head vinyl step. + # # Initiation and propagation remain head-to-tail. + # # + # # AutoREACTER/LAMMPS rule: + # # maps 1 and 2 are the initiator atoms. + # # the new termination bond is 1-2. + # # + # # Map 1 = active radical head carbon on one vinyl chain end. + # # Map 2 = active radical head carbon on another vinyl chain end. + # # + # # The D3/v3/+0 constraints make this target the + # # methacrylate-style chain-end radical center instead of + # # an ordinary acyclic carbon. + # 'reaction': ( + # '[C;!R;D3;v3;+0:1].' + # '[C;!R;D3;v3;+0:2]' + # '>>' + # '[C:1]-[C:2]' + # ), + # + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # + # 'comments': None, + # + # 'notes': ( + # 'Head-to-head radical coupling termination for ' + # 'PMMA/TEGDMA-style vinyl chain ends. Maps 1 and 2 are ' + # 'the two active radical head carbons and form the new ' + # '1-2 termination bond. This reaction should be controlled ' + # 'separately from initiation and propagation, usually turned ' + # 'on late or pulsed so it does not kill vinyl growth too early.' + # ), + # }, + + + # ========================================================================= + # Vinyl Copolymerization Initiation + # ========================================================================= + + 'Vinyl Copolymerization Initiation': { + 'same_reactants': False, + 'reactant_1': 'vinyl', + 'reactant_2': 'vinyl', + 'product': 'vinyl_chain_end_radical', + 'delete_atom': False, + + # H-T branchable-vinyl copolymerization initiation: + # + # branchable tail=head + vinyl tail=head + # ↓ + # capped-branchable-head-tail-vinyl-head* + # + # This intentionally forces the rare branchable vinyl into the seed. + # + # AutoREACTER/LAMMPS rule: + # maps 1 and 2 are the initiator atoms. + # the new bond is 1-2. + # + # Map 3 = branchable vinyl terminal CH2 tail; capped as CH3 + # Map 1 = branchable vinyl substituted head + # Map 2 = incoming normal vinyl terminal CH2 tail + # Map 4 = incoming normal vinyl substituted head; becomes active radical + 'reaction': ( + '[CH2:3]=[C;!R:1].' + '[CH2:2]=[C;!R:4]' + '>>' + '[CH3:3]-[C:1]-[CH2:2]-[C;!R;D3;v3;+0:4]' + ), + + 'reference': { + 'smarts': None, + 'reaction_and_mechanism': None + }, + + 'comments': None, + + 'notes': ( + 'Head-to-tail vinyl copolymerization initiation. ' + 'Maps 1 and 2 form the new bond. Map 3 is capped as CH3 ' + 'and map 4 becomes the active chain-end radical.' + ), + }, + + + # ========================================================================= + # Currently Disabled Cyclic / Legacy Vinyl Reactions + # ========================================================================= + + # 'Vinyl Addition Polymerization': { + # 'same_reactants': True, + # 'reactant_1': 'vinyl', + # 'product': 'polyvinyl_chain', + # 'delete_atom': False, + # 'reaction': ( + # '[CH2:1]=[CH;H1,H0;!R:2].' + # '[CH2:3]=[CH;H1,H0;!R:4]' + # '>>' + # '[CH2:1]-[CH:2]-[CH2:3]-[CH:4]' + # ), + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # 'comments': None + # }, + + + # 'Vinyl Copolymerization': { + # 'same_reactants': False, + # 'reactant_1': 'vinyl', + # 'reactant_2': 'vinyl', + # 'product': 'copolyvinyl_chain', + # 'delete_atom': False, + # 'reaction': ( + # '[CH2:1]=[CH;H1,H0;!R:2].' + # '[CH2:3]=[CH;H1,H0;!R:4]' + # '>>' + # '[CH2:1]-[CH:2]-[CH2:3]-[CH:4]' + # ), + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # 'comments': None + # }, + + + # ------------------------------------------------------------------------- + # Cyclic olefin reactions intentionally remain disabled + # ------------------------------------------------------------------------- + + # 'Cyclic Olefin Addition Polymerization': { + # 'same_reactants': True, + # 'reactant_1': 'cyclic_olefin', + # 'product': 'polycyclic_chain', + # 'delete_atom': False, # - # branchable tail=head + vinyl tail=head - # ↓ - # capped-branchable-head-tail-vinyl-head* + # 'reaction': ( + # '[CX3;R:1]=[CX3;R:2].' + # '[CX3;R:3]=[CX3;R:4]' + # '>>' + # '[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]' + # ), # - # This intentionally forces the rare branchable vinyl into the seed. + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, # - # AutoREACTER/LAMMPS rule: - # maps 1 and 2 are the initiator atoms. - # the new bond is 1-2. + # 'comments': None + # }, + + + # 'Cyclic Olefin and Vinyl Copolymerization': { + # 'same_reactants': False, + # 'reactant_1': 'vinyl', + # 'reactant_2': 'cyclic_olefin', + # 'product': 'copolycyclicvinyl_chain', + # 'delete_atom': False, + # + # 'reaction': ( + # '[CH2:1]=[C;!R:2].' + # '[C;R:3]=[C;R:4]' + # '>>' + # '[C:1]-[C:2]-[C:3]-[C:4]' + # ), + # + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, + # + # 'comments': None + # }, + + + # 'Cyclic Olefin Copolymerization': { + # 'same_reactants': False, + # 'reactant_1': 'cyclic_olefin', + # 'reactant_2': 'cyclic_olefin', + # 'product': 'copolycyclic_chain', + # 'delete_atom': False, + # + # 'reaction': ( + # '[CX3;R:1]=[CX3;R:2].' + # '[CX3;R:3]=[CX3;R:4]' + # '>>' + # '[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]' + # ), + # + # 'reference': { + # 'smarts': None, + # 'reaction_and_mechanism': None + # }, # - # Map 3 = branchable vinyl terminal CH2 tail; capped as CH3 - # Map 1 = branchable vinyl substituted head - # Map 2 = incoming normal vinyl terminal CH2 tail - # Map 4 = incoming normal vinyl substituted head; becomes active radical - 'reaction': ( - '[CH2:3]=[C;!R:1].' - '[CH2:2]=[C;!R:4]' - '>>' - '[CH3:3]-[C:1]-[CH2:2]-[C;!R;D3;v3;+0:4]' - ), - - 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - 'comments': None, - # Disabled until branchable_vinyl functional-group detection - # or explicit reactant ordering is implemented. -# - # 'notes': ( - # 'Forced H-T copolymerization initiation between a rare branchable ' - # 'vinyl/crosslinker vinyl and a normal vinyl monomer. The branchable ' - # 'vinyl is placed into the initial chain segment, while the active ' - # 'radical is carried forward on the normal vinyl head atom map 4. ' - # 'Maps 1 and 2 form the new bond. Use this reaction with separate ' - # 'time control or max_rxn limits so the low-count crosslinker is not ' - # 'over-consumed at the beginning.' - # ), -# }, -# - # # ---- kept commented, unchanged ---- - # # 'Vinyl Addition Polymerization': { - # # 'same_reactants': True, - # # 'reactant_1': 'vinyl', - # # 'product': 'polyvinyl_chain', - # # 'delete_atom': False, - # # 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', - # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # # 'comments': None - # # }, - # # 'Vinyl Copolymerization': { - # # 'same_reactants': False, - # # 'reactant_1': 'vinyl', - # # 'reactant_2': 'vinyl', - # # 'product': 'copolyvinyl_chain', - # # 'delete_atom': False, - # # 'reaction': '[CH2:1]=[CH;H1,H0;!R:2].[CH2:3]=[CH;H1,H0;!R:4]>>[CH2:1]-[CH:2]-[CH2:3]-[CH:4]', - # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # # 'comments': None - # # }, - # # 'Cyclic Olefin Addition Polymerization': { - # # 'same_reactants': True, - # # 'reactant_1': 'cyclic_olefin', - # # 'product': 'polycyclic_chain', - # # 'delete_atom': False, - # # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', - # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # # 'comments': None - # # }, - # # 'Cyclic Olefin and Vinyl Copolymerization': { - # # 'same_reactants': False, - # # 'reactant_1': 'vinyl', - # # 'reactant_2': 'cyclic_olefin', - # # 'product': 'copolycyclicvinyl_chain', - # # 'delete_atom': False, - # # 'reaction': '[CH2:1]=[C;!R:2].[C;R:3]=[C;R:4]>>[C:1]-[C:2]-[C:3]-[C:4]', - # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # # 'comments': None - # # }, - # # 'Cyclic Olefin Copolymerization': { - # # 'same_reactants': False, - # # 'reactant_1': 'cyclic_olefin', - # # 'reactant_2': 'cyclic_olefin', - # # 'product': 'copolycyclic_chain', - # # 'delete_atom': False, - # # 'reaction': '[CX3;R:1]=[CX3;R:2].[CX3;R:3]=[CX3;R:4]>>[CX4:1]-[CX4:2]-[CX4:3]-[CX4:4]', - # # 'reference': {'smarts': None, 'reaction_and_mechanism': None}, - # # 'comments': None - # # }, + # 'comments': None + # }, + + + # ========================================================================= + # Tetrafluoroethylene / PTFE + # ========================================================================= 'Tetrafluoroethylene Initiation': { 'same_reactants': False, @@ -215,51 +327,128 @@ 'reactant_2': 'tetrafluoroethylene', 'product': 'vinyl_chain_end_radical', 'delete_atom': False, + + # AutoREACTER/LAMMPS rule: + # + # map 1 + map 2 + # ↓ + # new 1-2 bond + # + # Map 1 = existing initiating/active atom + # Map 2 = one TFE carbon + # Map 3 = second TFE carbon + # Maps 4-7 = fluorines 'reaction': ( '[*:1].' - '[CX3:2](-[F:4])(-[F:5])=[CX3:3](-[F:6])(-[F:7])' + '[CX3:2](-[F:4])(-[F:5])=' + '[CX3:3](-[F:6])(-[F:7])' '>>' - '[*:1]-[CX4:2](-[F:4])(-[F:5])-[CX4:3](-[F:6])(-[F:7])' + '[*:1]-' + '[CX4:2](-[F:4])(-[F:5])-' + '[CX4:3](-[F:6])(-[F:7])' ), + 'reference': { 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': 'Initiation of TFE to form the first active center' + + 'comments': ( + 'Initiation of TFE to form the first active center' + ), + + 'notes': ( + 'The new TFE initiation bond is between atom maps 1 and 2.' + ), }, + 'Tetrafluoroethylene Propagation': { 'same_reactants': False, 'reactant_1': 'vinyl_chain_end_radical', 'reactant_2': 'tetrafluoroethylene', 'product': 'vinyl_chain_end_radical', 'delete_atom': False, + + # PTFE propagation: + # + # chain-1-2 3=8 + # + # ↓ + # + # chain-1-2-3-8 + # + # IMPORTANT: + # + # Map 1-2 is already bonded in the reactant. + # + # The new propagation bond is: + # + # 2-3 + # + # Therefore this reaction must override the registry default + # initiator_atom_maps=(1, 2). + 'initiator_atom_maps': (2, 3), + 'reaction': ( - '[*:1]-[CX4:2](-[F:4])(-[F:5]).' - '[CX3:3](-[F:6])(-[F:7])=[CX3:8](-[F:9])(-[F:10])' + '[*:1]-' + '[CX4:2](-[F:4])(-[F:5]).' + '[CX3:3](-[F:6])(-[F:7])=' + '[CX3:8](-[F:9])(-[F:10])' '>>' - '[*:1]-[CX4:2](-[F:4])(-[F:5])-' - '[CX4:3](-[F:6])(-[F:7])-[CX4:8](-[F:9])(-[F:10])' + '[*:1]-' + '[CX4:2](-[F:4])(-[F:5])-' + '[CX4:3](-[F:6])(-[F:7])-' + '[CX4:8](-[F:9])(-[F:10])' ), + 'reference': { 'smarts': None, 'reaction_and_mechanism': None }, - 'comments': 'Propagation step for PTFE chain growth' + + 'comments': ( + 'Propagation step for PTFE chain growth' + ), + + 'notes': ( + 'The new propagation bond is atom maps 2-3. ' + 'Maps 1-2 are already connected in the incoming chain, ' + 'so initiator_atom_maps is explicitly set to (2, 3).' + ), }, + + # ========================================================================= + # Optional PTFE Termination + # ========================================================================= + # 'Tetrafluoroethylene Termination (Recombination)': { # 'same_reactants': True, # 'reactant_1': 'vinyl_chain_end_radical', # 'product': 'ptfe_chain', # 'delete_atom': False, - # # Two growing chains meet and recombine at their active CX4 centers - # 'reaction': '[*:1]-[CX4:2](-[F:4])(-[F:5]).[*:3]-[CX4:6](-[F:7])(-[F:8])>>[*:1]-[CX4:2](-[F:4])(-[F:5])-[CX4:6](-[F:7])(-[F:8])-[*:3]', + # + # # Two growing chains meet and recombine at their active + # # tetrafluoroethylene chain centers. + # + # 'reaction': ( + # '[*:1]-[CX4:2](-[F:4])(-[F:5]).' + # '[*:3]-[CX4:6](-[F:7])(-[F:8])' + # '>>' + # '[*:1]-' + # '[CX4:2](-[F:4])(-[F:5])-' + # '[CX4:6](-[F:7])(-[F:8])-' + # '[*:3]' + # ), + # # 'reference': { # 'smarts': None, # 'reaction_and_mechanism': None # }, - # 'comments': 'UNTESTED: Radical recombination termination for PTFE' - # } -} + # + # 'comments': ( + # 'UNTESTED: Radical recombination termination for PTFE' + # ) + # }, } \ No newline at end of file diff --git a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py index a1fbf330..468caecb 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/warning_asci.py @@ -5,7 +5,7 @@ def ascii_art(message: str) -> None: message = message.upper() print(f"WARNING: {message}") print( -""" +r""" ____ ____ _ _______ ____ _____ _____ ____ _____ ______ _ _ _ |_ _| |_ _|/ \ |_ __ \ |_ \|_ _||_ _||_ \|_ _|.' ___ | | | | | | | \ \ /\ / / / _ \ | |__) | | \ | | | | | \ | | / .' \_| | | | | | | diff --git a/AutoREACTER/session.py b/AutoREACTER/session.py index e1172d5b..cf69f4a8 100644 --- a/AutoREACTER/session.py +++ b/AutoREACTER/session.py @@ -2,8 +2,8 @@ from typing import TYPE_CHECKING import json import shutil +from dataclasses import dataclass, field from pathlib import Path -from dataclasses import dataclass # Import internal modules from AutoREACTER.initialization import Initialization @@ -15,10 +15,6 @@ if TYPE_CHECKING: from AutoREACTER.detectors.functional_groups_detector import MonomerRole -from dataclasses import dataclass, field -from pathlib import Path - - @dataclass(slots=True) class Session: """ diff --git a/examples/test_styrene.json b/examples/test_styrene.json index d93173d8..bf62433c 100644 --- a/examples/test_styrene.json +++ b/examples/test_styrene.json @@ -1,7 +1,7 @@ { "simulation_name": "Styrene2", "force_field": "PCFF", - "wildcards": false, + "wildcards": true, "simulations": [ { "tag": "styrene_10k_298K", diff --git a/tests/unit/detectors/reactions_library/test_epoxy_polymers.py b/tests/unit/detectors/reactions_library/test_epoxy_polymers.py new file mode 100644 index 00000000..4dd5d098 --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_epoxy_polymers.py @@ -0,0 +1,338 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.epoxy_polymers import ( + REACTIONS, +) + + +PRIMARY = ( + "Primary Amine and Epoxide Polyaddition " + "(Epoxy-Amine, First Addition)" +) + +SECONDARY = ( + "Secondary Amine and Epoxide Polyaddition " + "(Epoxy-Amine, Second Addition / Crosslink)" +) + + +EXPECTED_REACTIONS = { + PRIMARY, + SECONDARY, +} + + +def run_reaction(reaction_name, smiles_1, smiles_2): + reaction_info = REACTIONS[reaction_name] + + rxn = rdChemReactions.ReactionFromSmarts( + reaction_info["reaction"] + ) + + assert rxn is not None + + mol_1 = Chem.AddHs( + Chem.MolFromSmiles(smiles_1) + ) + + mol_2 = Chem.AddHs( + Chem.MolFromSmiles(smiles_2) + ) + + return rxn.RunReactants( + ( + mol_1, + mol_2, + ) + ) + + +# ============================================================================= +# Structure +# ============================================================================= + +def test_expected_active_reactions(): + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_required_fields_exist(reaction_name): + reaction = REACTIONS[reaction_name] + + required = { + "same_reactants", + "reactant_1", + "reactant_2", + "product", + "delete_atom", + "reaction", + "reference", + "comments", + } + + assert required.issubset( + reaction.keys() + ) + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_reaction_smarts_parses(reaction_name): + reaction = REACTIONS[reaction_name] + + rxn = rdChemReactions.ReactionFromSmarts( + reaction["reaction"] + ) + + assert rxn is not None + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_reaction_passes_registry_validation(reaction_name): + errors = registry._validate_reaction_smarts( + reaction_name, + REACTIONS[reaction_name], + ) + + assert errors == [] + + +# ============================================================================= +# Metadata +# ============================================================================= + +def test_primary_epoxy_amine_metadata(): + reaction = REACTIONS[PRIMARY] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "primary_amine" + assert reaction["reactant_2"] == "di_epoxide" + + assert ( + reaction["product"] + == "secondary_amine_hydroxyl_product" + ) + + assert reaction["delete_atom"] is False + assert reaction["comments"] is None + + +def test_secondary_epoxy_amine_metadata(): + reaction = REACTIONS[SECONDARY] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "secondary_amine" + assert reaction["reactant_2"] == "di_epoxide" + + assert ( + reaction["product"] + == "tertiary_amine_crosslink_product" + ) + + assert reaction["delete_atom"] is False + assert reaction["comments"] is None + + +def test_primary_and_secondary_reactions_use_different_amine_queries(): + primary = REACTIONS[PRIMARY]["reaction"] + secondary = REACTIONS[SECONDARY]["reaction"] + + assert "[NX3H2:1]" in primary + assert "[NX3H1:1]" in secondary + + +# ============================================================================= +# Initiator-map convention +# ============================================================================= + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_reaction_contains_initiator_maps_1_and_2( + reaction_name, +): + reaction = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + reactants = [ + Chem.Mol( + reaction.GetReactantTemplate(i) + ) + for i in range( + reaction.GetNumReactantTemplates() + ) + ] + + products = [ + Chem.Mol( + reaction.GetProductTemplate(i) + ) + for i in range( + reaction.GetNumProductTemplates() + ) + ] + + assert { + 1, + 2, + }.issubset( + registry._atom_maps_in_templates( + reactants + ) + ) + + assert { + 1, + 2, + }.issubset( + registry._atom_maps_in_templates( + products + ) + ) + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_product_contains_new_initiator_bond( + reaction_name, +): + reaction = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + products = [ + Chem.Mol( + reaction.GetProductTemplate(i) + ) + for i in range( + reaction.GetNumProductTemplates() + ) + ] + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +# ============================================================================= +# Primary amine + epoxide chemistry +# ============================================================================= + +def test_primary_amine_reaction_executes(): + """ + Ethylamine contains a primary amine. + + Propylene oxide provides the CH2/CH epoxide environment required by + this reaction SMARTS. + """ + products = run_reaction( + PRIMARY, + "CCN", + "CC1CO1", + ) + + assert len(products) > 0 + + +def test_primary_reaction_products_are_sanitizable(): + products = run_reaction( + PRIMARY, + "CCN", + "CC1CO1", + ) + + first_product_set = products[0] + + assert first_product_set + + for product in first_product_set: + Chem.SanitizeMol(product) + + +def test_primary_reaction_does_not_accept_secondary_amine(): + products = run_reaction( + PRIMARY, + "CNC", + "CC1CO1", + ) + + assert len(products) == 0 + + +def test_primary_reaction_does_not_accept_nonamine(): + products = run_reaction( + PRIMARY, + "CCO", + "CC1CO1", + ) + + assert len(products) == 0 + + +# ============================================================================= +# Secondary amine + epoxide chemistry +# ============================================================================= + +def test_secondary_amine_reaction_executes(): + """ + Dimethylamine contains one N-H bond and therefore matches NX3H1. + """ + products = run_reaction( + SECONDARY, + "CNC", + "CC1CO1", + ) + + assert len(products) > 0 + + +def test_secondary_reaction_products_are_sanitizable(): + products = run_reaction( + SECONDARY, + "CNC", + "CC1CO1", + ) + + first_product_set = products[0] + + assert first_product_set + + for product in first_product_set: + Chem.SanitizeMol(product) + + +def test_secondary_reaction_does_not_accept_primary_amine(): + products = run_reaction( + SECONDARY, + "CCN", + "CC1CO1", + ) + + assert len(products) == 0 + + +def test_secondary_reaction_does_not_accept_tertiary_amine(): + products = run_reaction( + SECONDARY, + "CN(C)C", + "CC1CO1", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_polyamides.py b/tests/unit/detectors/reactions_library/test_polyamides.py new file mode 100644 index 00000000..41a151a7 --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_polyamides.py @@ -0,0 +1,456 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.polyamides import ( + REACTIONS, +) + + +AMINO_HOMO = ( + "Amino Acid Polycondensation (Polyamidation)" +) + +AMINO_CO = ( + "Amino Acid and Amino Acid " + "Polycondensation (Polyamidation)" +) + +DIAMINE_ACID = ( + "Di-Amine and Di-Carboxylic Acid " + "Polycondensation (Polyamidation)" +) + +DIAMINE_HALIDE = ( + "Di-Amine and Di-Carboxylic Acid Halide " + "Polycondensation (Polyamidation)" +) + +CAPROLACTAM_HYDROLYSIS = ( + "Hydrolytic Initiation of Caprolactam" +) + + +EXPECTED_REACTIONS = { + AMINO_HOMO, + AMINO_CO, + DIAMINE_ACID, + DIAMINE_HALIDE, + CAPROLACTAM_HYDROLYSIS, +} + + +def run_reaction(reaction_name, smiles_1, smiles_2): + reaction_info = REACTIONS[reaction_name] + + rxn = rdChemReactions.ReactionFromSmarts( + reaction_info["reaction"] + ) + + assert rxn is not None + + mol_1 = Chem.AddHs( + Chem.MolFromSmiles(smiles_1) + ) + + mol_2 = Chem.AddHs( + Chem.MolFromSmiles(smiles_2) + ) + + return rxn.RunReactants( + ( + mol_1, + mol_2, + ) + ) + + +# ============================================================================= +# Structure +# ============================================================================= + +def test_expected_active_reactions(): + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_required_fields_exist(reaction_name): + reaction = REACTIONS[reaction_name] + + required = { + "same_reactants", + "reactant_1", + "product", + "delete_atom", + "reaction", + "reference", + "comments", + } + + assert required.issubset( + reaction.keys() + ) + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_reaction_smarts_parses(reaction_name): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + assert rxn is not None + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_reaction_passes_registry_validation( + reaction_name, +): + errors = registry._validate_reaction_smarts( + reaction_name, + REACTIONS[reaction_name], + ) + + assert errors == [] + + +# ============================================================================= +# Metadata +# ============================================================================= + +def test_amino_acid_homopolymerization_metadata(): + reaction = REACTIONS[AMINO_HOMO] + + assert reaction["same_reactants"] is True + assert reaction["reactant_1"] == "amino_acid" + + assert reaction.get( + "reactant_2" + ) is None + + assert reaction["product"] == "polyamide_chain" + assert reaction["delete_atom"] is True + + +def test_amino_acid_copolymerization_metadata(): + reaction = REACTIONS[AMINO_CO] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "amino_acid" + assert reaction["reactant_2"] == "amino_acid" + assert reaction["product"] == "polyamide_chain" + assert reaction["delete_atom"] is True + + +def test_diamine_diacid_metadata(): + reaction = REACTIONS[DIAMINE_ACID] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "di_amine" + + assert ( + reaction["reactant_2"] + == "di_carboxylic_acid" + ) + + assert reaction["product"] == "polyamide_chain" + assert reaction["delete_atom"] is True + + +def test_diamine_diacid_halide_metadata(): + reaction = REACTIONS[DIAMINE_HALIDE] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "di_amine" + + assert ( + reaction["reactant_2"] + == "di_carboxylic_acid_halide" + ) + + assert reaction["product"] == "polyamide_chain" + assert reaction["delete_atom"] is True + + +def test_caprolactam_hydrolysis_metadata(): + reaction = REACTIONS[ + CAPROLACTAM_HYDROLYSIS + ] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "water" + assert reaction["reactant_2"] == "lactam" + assert reaction["product"] == "polyamide_chain" + assert reaction["delete_atom"] is False + + +# ============================================================================= +# Initiator maps +# ============================================================================= + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_reactions_contain_initiator_maps_1_and_2( + reaction_name, +): + reaction = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + reactants = [ + Chem.Mol( + reaction.GetReactantTemplate(i) + ) + for i in range( + reaction.GetNumReactantTemplates() + ) + ] + + products = [ + Chem.Mol( + reaction.GetProductTemplate(i) + ) + for i in range( + reaction.GetNumProductTemplates() + ) + ] + + reactant_maps = ( + registry._atom_maps_in_templates( + reactants + ) + ) + + product_maps = ( + registry._atom_maps_in_templates( + products + ) + ) + + assert { + 1, + 2, + }.issubset( + reactant_maps + ) + + assert { + 1, + 2, + }.issubset( + product_maps + ) + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_products_contain_initiator_bond( + reaction_name, +): + reaction = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + products = [ + Chem.Mol( + reaction.GetProductTemplate(i) + ) + for i in range( + reaction.GetNumProductTemplates() + ) + ] + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +# ============================================================================= +# Amino-acid polycondensation +# ============================================================================= + +def test_glycine_homopolycondensation_executes(): + products = run_reaction( + AMINO_HOMO, + "NCC(=O)O", + "NCC(=O)O", + ) + + assert len(products) > 0 + + +def test_glycine_condensation_produces_two_product_fragments(): + """ + The SMARTS generates the amide-containing product plus the + eliminated water fragment. + """ + products = run_reaction( + AMINO_HOMO, + "NCC(=O)O", + "NCC(=O)O", + ) + + assert len( + products[0] + ) == 2 + + +def test_glycine_condensation_products_are_sanitizable(): + products = run_reaction( + AMINO_HOMO, + "NCC(=O)O", + "NCC(=O)O", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +# ============================================================================= +# Diamine + dicarboxylic acid +# ============================================================================= + +def test_diamine_diacid_polycondensation_executes(): + products = run_reaction( + DIAMINE_ACID, + "NCCN", + "O=C(O)CCC(=O)O", + ) + + assert len(products) > 0 + + +def test_diamine_diacid_products_are_sanitizable(): + products = run_reaction( + DIAMINE_ACID, + "NCCN", + "O=C(O)CCC(=O)O", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_diamine_diacid_reaction_produces_byproduct(): + products = run_reaction( + DIAMINE_ACID, + "NCCN", + "O=C(O)CCC(=O)O", + ) + + assert len( + products[0] + ) == 2 + + +# ============================================================================= +# Diamine + acid halide +# ============================================================================= + +def test_diamine_acid_halide_polycondensation_executes(): + products = run_reaction( + DIAMINE_HALIDE, + "NCCN", + "O=C(Cl)CCC(=O)Cl", + ) + + assert len(products) > 0 + + +def test_diamine_acid_halide_products_are_sanitizable(): + products = run_reaction( + DIAMINE_HALIDE, + "NCCN", + "O=C(Cl)CCC(=O)Cl", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_diamine_acid_halide_reaction_produces_byproduct(): + products = run_reaction( + DIAMINE_HALIDE, + "NCCN", + "O=C(Cl)CCC(=O)Cl", + ) + + assert len( + products[0] + ) == 2 + + +# ============================================================================= +# Hydrolytic initiation of caprolactam +# ============================================================================= + +def test_caprolactam_hydrolysis_executes(): + products = run_reaction( + CAPROLACTAM_HYDROLYSIS, + "O", + "O=C1CCCCCN1", + ) + + assert len(products) > 0 + + +def test_caprolactam_hydrolysis_product_is_sanitizable(): + products = run_reaction( + CAPROLACTAM_HYDROLYSIS, + "O", + "O=C1CCCCCN1", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_caprolactam_hydrolysis_produces_single_open_chain_product(): + products = run_reaction( + CAPROLACTAM_HYDROLYSIS, + "O", + "O=C1CCCCCN1", + ) + + assert len( + products[0] + ) == 1 + + +# ============================================================================= +# Negative chemistry tests +# ============================================================================= + +def test_diamine_diacid_reaction_does_not_accept_simple_alcohol(): + products = run_reaction( + DIAMINE_ACID, + "CCO", + "O=C(O)CCC(=O)O", + ) + + assert len(products) == 0 + + +def test_diamine_acid_halide_reaction_does_not_accept_dicarboxylic_acid(): + products = run_reaction( + DIAMINE_HALIDE, + "NCCN", + "O=C(O)CCC(=O)O", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_polyanhydrides.py b/tests/unit/detectors/reactions_library/test_polyanhydrides.py new file mode 100644 index 00000000..a80aee90 --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_polyanhydrides.py @@ -0,0 +1,242 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.polyanhydrides import ( + REACTIONS, +) + + +HOMO = ( + "Carboxylic Acid and Acid Halide Polycondensation " + "(Polyanhydride Formation)" +) + +CO = ( + "Carboxylic Acid and Acid Halide Copolycondensation " + "(Polyanhydride Copolymerization)" +) + + +EXPECTED_REACTIONS = { + HOMO, + CO, +} + + +def run_reaction(reaction_name, smiles_1, smiles_2): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + assert rxn is not None + + mol_1 = Chem.AddHs( + Chem.MolFromSmiles(smiles_1) + ) + + mol_2 = Chem.AddHs( + Chem.MolFromSmiles(smiles_2) + ) + + return rxn.RunReactants( + ( + mol_1, + mol_2, + ) + ) + + +def test_expected_active_reactions(): + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_required_fields_exist(reaction_name): + reaction = REACTIONS[reaction_name] + + required = { + "same_reactants", + "reactant_1", + "product", + "delete_atom", + "reaction", + "reference", + } + + assert required.issubset( + reaction.keys() + ) + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_smarts_parses(reaction_name): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + assert rxn is not None + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_registry_validation_passes(reaction_name): + errors = registry._validate_reaction_smarts( + reaction_name, + REACTIONS[reaction_name], + ) + + assert errors == [] + + +def test_homopolymerization_metadata(): + reaction = REACTIONS[HOMO] + + assert reaction["same_reactants"] is True + assert ( + reaction["reactant_1"] + == "carboxylic_acid_acid_halide" + ) + assert reaction.get("reactant_2") is None + assert reaction["product"] == "polyanhydride_chain" + assert reaction["delete_atom"] is True + + +def test_copolymerization_metadata(): + reaction = REACTIONS[CO] + + assert reaction["same_reactants"] is False + + assert ( + reaction["reactant_1"] + == "carboxylic_acid_acid_halide" + ) + + assert ( + reaction["reactant_2"] + == "carboxylic_acid_acid_halide" + ) + + assert reaction["product"] == "polyanhydride_chain" + assert reaction["delete_atom"] is True + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_initiator_maps_are_present(reaction_name): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + reactants = [ + Chem.Mol( + rxn.GetReactantTemplate(i) + ) + for i in range( + rxn.GetNumReactantTemplates() + ) + ] + + products = [ + Chem.Mol( + rxn.GetProductTemplate(i) + ) + for i in range( + rxn.GetNumProductTemplates() + ) + ] + + assert {1, 2}.issubset( + registry._atom_maps_in_templates( + reactants + ) + ) + + assert {1, 2}.issubset( + registry._atom_maps_in_templates( + products + ) + ) + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_product_contains_initiator_bond( + reaction_name, +): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + products = [ + Chem.Mol( + rxn.GetProductTemplate(i) + ) + for i in range( + rxn.GetNumProductTemplates() + ) + ] + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +def test_homopolymerization_smarts_executes(): + """ + HOOC-(CH2)3-COCl contains both groups required by the + heterobifunctional polyanhydride definition. + """ + products = run_reaction( + HOMO, + "O=C(O)CCC(=O)Cl", + "O=C(O)CCC(=O)Cl", + ) + + assert len(products) > 0 + + +def test_homopolymerization_produces_byproduct(): + products = run_reaction( + HOMO, + "O=C(O)CCC(=O)Cl", + "O=C(O)CCC(=O)Cl", + ) + + assert len(products[0]) == 2 + + +def test_products_are_sanitizable(): + products = run_reaction( + HOMO, + "O=C(O)CCC(=O)Cl", + "O=C(O)CCC(=O)Cl", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_reaction_fails_without_acid_halide(): + products = run_reaction( + HOMO, + "O=C(O)CCC(=O)O", + "O=C(O)CCC(=O)O", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_polycarbonates.py b/tests/unit/detectors/reactions_library/test_polycarbonates.py new file mode 100644 index 00000000..a80549c4 --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_polycarbonates.py @@ -0,0 +1,220 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.polycarbonates import ( + REACTIONS, +) + + +PHOSGENE = ( + "Diol and Phosgene " + "Polycondensation(Polycarbonate Formation)" +) + +DIPHENYL = ( + "Diol and Diphenyl Carbonate " + "Polycondensation(Transcarbonation)" +) + + +EXPECTED_REACTIONS = { + PHOSGENE, + DIPHENYL, +} + + +def run_reaction(reaction_name, smiles_1, smiles_2): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + assert rxn is not None + + mol_1 = Chem.AddHs( + Chem.MolFromSmiles(smiles_1) + ) + + mol_2 = Chem.AddHs( + Chem.MolFromSmiles(smiles_2) + ) + + return rxn.RunReactants( + ( + mol_1, + mol_2, + ) + ) + + +def test_expected_active_reactions(): + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_required_fields_exist(reaction_name): + reaction = REACTIONS[reaction_name] + + required = { + "same_reactants", + "reactant_1", + "reactant_2", + "product", + "delete_atom", + "reaction", + "reference", + "comments", + } + + assert required.issubset( + reaction.keys() + ) + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_smarts_parses(reaction_name): + assert rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) is not None + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_registry_validation_passes(reaction_name): + assert registry._validate_reaction_smarts( + reaction_name, + REACTIONS[reaction_name], + ) == [] + + +def test_phosgene_reaction_metadata(): + reaction = REACTIONS[PHOSGENE] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "diol" + assert reaction["reactant_2"] == "phosgene" + assert reaction["product"] == "polycarbonate_chain" + assert reaction["delete_atom"] is True + + +def test_diphenyl_carbonate_metadata(): + reaction = REACTIONS[DIPHENYL] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "diol" + + assert ( + reaction["reactant_2"] + == "diphenyl_carbonate" + ) + + assert reaction["product"] == "polycarbonate_chain" + assert reaction["delete_atom"] is True + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_product_contains_initiator_bond( + reaction_name, +): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + products = [ + Chem.Mol( + rxn.GetProductTemplate(i) + ) + for i in range( + rxn.GetNumProductTemplates() + ) + ] + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +def test_diol_phosgene_reaction_executes(): + products = run_reaction( + PHOSGENE, + "OCCO", + "O=C(Cl)Cl", + ) + + assert len(products) > 0 + + +def test_diol_phosgene_produces_hcl_byproduct(): + products = run_reaction( + PHOSGENE, + "OCCO", + "O=C(Cl)Cl", + ) + + assert len(products[0]) == 2 + + +def test_diol_phosgene_products_are_sanitizable(): + products = run_reaction( + PHOSGENE, + "OCCO", + "O=C(Cl)Cl", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_diol_diphenyl_carbonate_reaction_executes(): + products = run_reaction( + DIPHENYL, + "OCCO", + "O=C(Oc1ccccc1)Oc1ccccc1", + ) + + assert len(products) > 0 + + +def test_transcarbonation_produces_two_product_fragments(): + products = run_reaction( + DIPHENYL, + "OCCO", + "O=C(Oc1ccccc1)Oc1ccccc1", + ) + + assert len(products[0]) == 2 + + +def test_transcarbonation_products_are_sanitizable(): + products = run_reaction( + DIPHENYL, + "OCCO", + "O=C(Oc1ccccc1)Oc1ccccc1", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_phosgene_reaction_rejects_non_diol_alcohol_free_molecule(): + products = run_reaction( + PHOSGENE, + "CCC", + "O=C(Cl)Cl", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_polyesters.py b/tests/unit/detectors/reactions_library/test_polyesters.py new file mode 100644 index 00000000..97bddbc8 --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_polyesters.py @@ -0,0 +1,399 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.polyesters import ( + REACTIONS, +) + + +HYDROXY_ACID_HOMO = ( + "Hydroxy Carboxylic Acid " + "Polycondensation(Polyesterification)" +) + +HYDROXY_ACID_CO = ( + "Hydroxy Carboxylic and Hydroxy Carboxylic " + "Polycondensation(Polyesterification)" +) + +HYDROXY_HALIDE_HOMO = ( + "Hydroxy Acid Halides " + "Polycondensation(Polyesterification)" +) + +HYDROXY_HALIDE_CO = ( + "Hydroxy Acid Halides Hydroxy Acid Halides " + "Polycondensation(Polyesterification)" +) + +DIOL_DIACID = ( + "Diol and Di-Carboxylic Acid " + "Polycondensation(Polyesterification)" +) + +DIOL_DIHALIDE = ( + "Diol and Di-Acid Halide " + "Polycondensation(Polyesterification)" +) + + +EXPECTED_REACTIONS = { + HYDROXY_ACID_HOMO, + HYDROXY_ACID_CO, + HYDROXY_HALIDE_HOMO, + HYDROXY_HALIDE_CO, + DIOL_DIACID, + DIOL_DIHALIDE, +} + + +def run_reaction(reaction_name, smiles_1, smiles_2): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + assert rxn is not None + + mol_1 = Chem.AddHs( + Chem.MolFromSmiles(smiles_1) + ) + + mol_2 = Chem.AddHs( + Chem.MolFromSmiles(smiles_2) + ) + + return rxn.RunReactants( + ( + mol_1, + mol_2, + ) + ) + + +def test_expected_active_reactions(): + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_required_fields_exist(reaction_name): + reaction = REACTIONS[reaction_name] + + required = { + "same_reactants", + "reactant_1", + "product", + "delete_atom", + "reaction", + "reference", + "comments", + } + + assert required.issubset( + reaction.keys() + ) + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_smarts_parses(reaction_name): + assert rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) is not None + + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_registry_validation_passes(reaction_name): + assert registry._validate_reaction_smarts( + reaction_name, + REACTIONS[reaction_name], + ) == [] + + +# ============================================================================= +# Metadata +# ============================================================================= + +def test_hydroxy_acid_homo_metadata(): + reaction = REACTIONS[ + HYDROXY_ACID_HOMO + ] + + assert reaction["same_reactants"] is True + + assert ( + reaction["reactant_1"] + == "hydroxy_carboxylic_acid" + ) + + assert reaction.get("reactant_2") is None + assert reaction["product"] == "polyester_chain" + assert reaction["delete_atom"] is True + + +def test_hydroxy_acid_co_metadata(): + reaction = REACTIONS[ + HYDROXY_ACID_CO + ] + + assert reaction["same_reactants"] is False + + assert ( + reaction["reactant_1"] + == "hydroxy_carboxylic_acid" + ) + + assert ( + reaction["reactant_2"] + == "hydroxy_carboxylic_acid" + ) + + +def test_hydroxy_halide_homo_metadata(): + reaction = REACTIONS[ + HYDROXY_HALIDE_HOMO + ] + + assert reaction["same_reactants"] is True + + assert ( + reaction["reactant_1"] + == "hydroxy_acid_halide" + ) + + +def test_hydroxy_halide_co_metadata(): + reaction = REACTIONS[ + HYDROXY_HALIDE_CO + ] + + assert reaction["same_reactants"] is False + + assert ( + reaction["reactant_1"] + == "hydroxy_acid_halide" + ) + + assert ( + reaction["reactant_2"] + == "hydroxy_acid_halide" + ) + + +def test_diol_diacid_metadata(): + reaction = REACTIONS[DIOL_DIACID] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "diol" + + assert ( + reaction["reactant_2"] + == "di_carboxylic_acid" + ) + + assert reaction["product"] == "polyester_chain" + + +def test_diol_diacid_halide_metadata(): + reaction = REACTIONS[DIOL_DIHALIDE] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "diol" + + assert ( + reaction["reactant_2"] + == "di_carboxylic_acid_halide" + ) + + +# ============================================================================= +# Initiator bond +# ============================================================================= + +@pytest.mark.parametrize( + "reaction_name", + sorted(EXPECTED_REACTIONS), +) +def test_product_contains_initiator_bond( + reaction_name, +): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[reaction_name]["reaction"] + ) + + products = [ + Chem.Mol( + rxn.GetProductTemplate(i) + ) + for i in range( + rxn.GetNumProductTemplates() + ) + ] + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +# ============================================================================= +# Hydroxy carboxylic acid +# ============================================================================= + +def test_hydroxy_acid_polycondensation_executes(): + products = run_reaction( + HYDROXY_ACID_HOMO, + "CC(O)C(=O)O", + "CC(O)C(=O)O", + ) + + assert len(products) > 0 + + +def test_hydroxy_acid_polycondensation_has_byproduct(): + products = run_reaction( + HYDROXY_ACID_HOMO, + "CC(O)C(=O)O", + "CC(O)C(=O)O", + ) + + assert len(products[0]) == 2 + + +def test_hydroxy_acid_products_are_sanitizable(): + products = run_reaction( + HYDROXY_ACID_HOMO, + "CC(O)C(=O)O", + "CC(O)C(=O)O", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +# ============================================================================= +# Hydroxy acid halide +# ============================================================================= + +def test_hydroxy_acid_halide_polycondensation_executes(): + products = run_reaction( + HYDROXY_HALIDE_HOMO, + "OCCC(=O)Cl", + "OCCC(=O)Cl", + ) + + assert len(products) > 0 + + +def test_hydroxy_acid_halide_has_byproduct(): + products = run_reaction( + HYDROXY_HALIDE_HOMO, + "OCCC(=O)Cl", + "OCCC(=O)Cl", + ) + + assert len(products[0]) == 2 + + +# ============================================================================= +# Diol + diacid +# ============================================================================= + +def test_diol_diacid_polycondensation_executes(): + products = run_reaction( + DIOL_DIACID, + "O=C(O)CCC(=O)O", + "OCCO", + ) + + assert len(products) > 0 + + +def test_diol_diacid_products_are_sanitizable(): + products = run_reaction( + DIOL_DIACID, + "O=C(O)CCC(=O)O", + "OCCO", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_diol_diacid_has_byproduct(): + products = run_reaction( + DIOL_DIACID, + "O=C(O)CCC(=O)O", + "OCCO", + ) + + assert len(products[0]) == 2 + + +# ============================================================================= +# Diol + diacid halide +# ============================================================================= + +def test_diol_diacid_halide_polycondensation_executes(): + products = run_reaction( + DIOL_DIHALIDE, + "O=C(Cl)CCC(=O)Cl", + "OCCO", + ) + + assert len(products) > 0 + + +def test_diol_diacid_halide_products_are_sanitizable(): + products = run_reaction( + DIOL_DIHALIDE, + "O=C(Cl)CCC(=O)Cl", + "OCCO", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_diol_diacid_halide_has_byproduct(): + products = run_reaction( + DIOL_DIHALIDE, + "O=C(Cl)CCC(=O)Cl", + "OCCO", + ) + + assert len(products[0]) == 2 + + +# ============================================================================= +# Negative tests +# ============================================================================= + +def test_hydroxy_acid_reaction_rejects_molecule_without_hydroxyl(): + products = run_reaction( + HYDROXY_ACID_HOMO, + "CC(=O)O", + "CC(=O)O", + ) + + assert len(products) == 0 + + +def test_diol_diacid_reaction_rejects_hydrocarbon(): + products = run_reaction( + DIOL_DIACID, + "O=C(O)CCC(=O)O", + "CCCC", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_polysiloxanes.py b/tests/unit/detectors/reactions_library/test_polysiloxanes.py new file mode 100644 index 00000000..3a6f707b --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_polysiloxanes.py @@ -0,0 +1,126 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.polysiloxanes import REACTIONS + + +HYDROLYSIS = "Dichlorosilane Hydrolysis to Silanol" +HOMO = "Silanediol Polycondensation(Polysiloxane Formation)" +CO = "Silanediol and Silanediol Copolycondensation(Polysiloxane Formation)" + +EXPECTED_REACTIONS = { + HYDROLYSIS, + HOMO, + CO, +} + + +def run_reaction(name, smiles_1, smiles_2): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[name]["reaction"] + ) + assert rxn is not None + + mol_1 = Chem.AddHs(Chem.MolFromSmiles(smiles_1)) + mol_2 = Chem.AddHs(Chem.MolFromSmiles(smiles_2)) + + return rxn.RunReactants((mol_1, mol_2)) + + +def test_expected_active_reactions(): + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize("name", sorted(EXPECTED_REACTIONS)) +def test_smarts_parses(name): + assert rdChemReactions.ReactionFromSmarts( + REACTIONS[name]["reaction"] + ) is not None + + +@pytest.mark.parametrize("name", sorted(EXPECTED_REACTIONS)) +def test_registry_validation_passes(name): + assert registry._validate_reaction_smarts( + name, + REACTIONS[name], + ) == [] + + +def test_hydrolysis_metadata(): + reaction = REACTIONS[HYDROLYSIS] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "dichlorosilane" + assert reaction["reactant_2"] == "water" + assert reaction["product"] == "silanediol" + assert reaction["delete_atom"] is True + + +def test_silanediol_homopolycondensation_metadata(): + reaction = REACTIONS[HOMO] + + assert reaction["same_reactants"] is True + assert reaction["reactant_1"] == "silanediol" + assert reaction.get("reactant_2") is None + assert reaction["product"] == "polysiloxane_chain" + assert reaction["delete_atom"] is True + + +def test_silanediol_copolycondensation_metadata(): + reaction = REACTIONS[CO] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "silanediol" + assert reaction["reactant_2"] == "silanediol" + + +def test_dichlorosilane_hydrolysis_executes(): + products = run_reaction( + HYDROLYSIS, + "Cl[Si](C)(C)Cl", + "O", + ) + + assert len(products) > 0 + + +def test_dichlorosilane_hydrolysis_has_two_products(): + products = run_reaction( + HYDROLYSIS, + "Cl[Si](C)(C)Cl", + "O", + ) + + assert len(products[0]) == 2 + + +def test_silanediol_condensation_executes(): + products = run_reaction( + HOMO, + "O[Si](C)(C)O", + "O[Si](C)(C)O", + ) + + assert len(products) > 0 + + +def test_silanediol_condensation_has_water_fragment(): + products = run_reaction( + HOMO, + "O[Si](C)(C)O", + "O[Si](C)(C)O", + ) + + assert len(products[0]) == 2 + + +def test_hydrolysis_rejects_non_water_second_reactant(): + products = run_reaction( + HYDROLYSIS, + "Cl[Si](C)(C)Cl", + "CCO", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_polythioesters.py b/tests/unit/detectors/reactions_library/test_polythioesters.py new file mode 100644 index 00000000..2af4462e --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_polythioesters.py @@ -0,0 +1,144 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.polythioesters import REACTIONS + + +THIOL_HALIDE = ( + "Dithiol and Di-Carboxylic Acid Halide " + "Polycondensation(Polythioesterification)" +) + +THIOL_ACID = ( + "Dithiol and Di-Carboxylic Acid " + "Polycondensation(Polythioesterification)" +) + +HYDROXY_PATH = ( + "Hydroxy-Thiol and Di-Carboxylic Acid Halide " + "Polycondensation through Hydroxy Group" +) + +THIOL_PATH = ( + "Hydroxy-Thiol and Di-Carboxylic Acid Halide " + "Polycondensation through Thiol Group" +) + +EXPECTED_REACTIONS = { + THIOL_HALIDE, + THIOL_ACID, + HYDROXY_PATH, + THIOL_PATH, +} + + +def run_reaction(name, smiles_1, smiles_2): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[name]["reaction"] + ) + assert rxn is not None + + return rxn.RunReactants( + ( + Chem.AddHs(Chem.MolFromSmiles(smiles_1)), + Chem.AddHs(Chem.MolFromSmiles(smiles_2)), + ) + ) + + +def test_expected_active_reactions(): + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize("name", sorted(EXPECTED_REACTIONS)) +def test_smarts_parses(name): + assert rdChemReactions.ReactionFromSmarts( + REACTIONS[name]["reaction"] + ) is not None + + +@pytest.mark.parametrize("name", sorted(EXPECTED_REACTIONS)) +def test_registry_validation_passes(name): + assert registry._validate_reaction_smarts( + name, + REACTIONS[name], + ) == [] + + +@pytest.mark.parametrize("name", sorted(EXPECTED_REACTIONS)) +def test_reactions_delete_leaving_group(name): + assert REACTIONS[name]["delete_atom"] is True + + +def test_dithiol_acid_halide_metadata(): + reaction = REACTIONS[THIOL_HALIDE] + + assert reaction["reactant_1"] == "dithiol" + assert reaction["reactant_2"] == "di_carboxylic_acid_halide" + assert reaction["product"] == "polythioester_chain" + + +def test_dithiol_acid_metadata(): + reaction = REACTIONS[THIOL_ACID] + + assert reaction["reactant_1"] == "dithiol" + assert reaction["reactant_2"] == "di_carboxylic_acid" + assert reaction["product"] == "polythioester_chain" + + +def test_hydroxy_thiol_has_two_distinct_reaction_routes(): + assert "OX2H1" in REACTIONS[HYDROXY_PATH]["reaction"] + assert "SX2H1" in REACTIONS[THIOL_PATH]["reaction"] + + +def test_dithiol_acid_halide_reaction_executes(): + # SMARTS order = acid halide first, dithiol second + products = run_reaction( + THIOL_HALIDE, + "O=C(Cl)CCC(=O)Cl", + "SCCS", + ) + + assert len(products) > 0 + + +def test_dithiol_acid_reaction_executes(): + products = run_reaction( + THIOL_ACID, + "O=C(O)CCC(=O)O", + "SCCS", + ) + + assert len(products) > 0 + + +def test_hydroxy_thiol_hydroxy_route_executes(): + products = run_reaction( + HYDROXY_PATH, + "O=C(Cl)CCC(=O)Cl", + "OCCS", + ) + + assert len(products) > 0 + + +def test_hydroxy_thiol_thiol_route_executes(): + products = run_reaction( + THIOL_PATH, + "O=C(Cl)CCC(=O)Cl", + "OCCS", + ) + + assert len(products) > 0 + + +def test_dithiol_acid_halide_produces_byproduct(): + products = run_reaction( + THIOL_HALIDE, + "O=C(Cl)CCC(=O)Cl", + "SCCS", + ) + + assert len(products[0]) == 2 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_polyureas.py b/tests/unit/detectors/reactions_library/test_polyureas.py new file mode 100644 index 00000000..eb231500 --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_polyureas.py @@ -0,0 +1,76 @@ +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.polyureas import REACTIONS + + +NAME = "Di-Amine and Di-Isocyanate Polyaddition(Polyurea Formation)" + + +def run_reaction(smiles_1, smiles_2): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[NAME]["reaction"] + ) + + return rxn.RunReactants( + ( + Chem.AddHs(Chem.MolFromSmiles(smiles_1)), + Chem.AddHs(Chem.MolFromSmiles(smiles_2)), + ) + ) + + +def test_expected_active_reaction(): + assert set(REACTIONS) == {NAME} + + +def test_metadata(): + reaction = REACTIONS[NAME] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "di_amine" + assert reaction["reactant_2"] == "di_isocyanate" + assert reaction["product"] == "polyurea_chain" + assert reaction["delete_atom"] is False + + +def test_smarts_parses(): + assert rdChemReactions.ReactionFromSmarts( + REACTIONS[NAME]["reaction"] + ) is not None + + +def test_registry_validation_passes(): + assert registry._validate_reaction_smarts( + NAME, + REACTIONS[NAME], + ) == [] + + +def test_diamine_diisocyanate_reaction_executes(): + products = run_reaction( + "NCCN", + "O=C=NCCCCCCN=C=O", + ) + + assert len(products) > 0 + + +def test_products_are_sanitizable(): + products = run_reaction( + "NCCN", + "O=C=NCCCCCCN=C=O", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_nonamine_does_not_react(): + products = run_reaction( + "OCCO", + "O=C=NCCCCCCN=C=O", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_polyurethanes.py b/tests/unit/detectors/reactions_library/test_polyurethanes.py new file mode 100644 index 00000000..78edef99 --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_polyurethanes.py @@ -0,0 +1,108 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.polyurethanes import REACTIONS + + +URETHANE = "Diol and Di-Isocyanate Polyaddition(Polyurethane Formation)" +THIOURETHANE = ( + "Dithiol and Di-Isocyanate " + "Polyaddition(Polythiourethane Formation)" +) + +EXPECTED_REACTIONS = { + URETHANE, + THIOURETHANE, +} + + +def run_reaction(name, smiles_1, smiles_2): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[name]["reaction"] + ) + + return rxn.RunReactants( + ( + Chem.AddHs(Chem.MolFromSmiles(smiles_1)), + Chem.AddHs(Chem.MolFromSmiles(smiles_2)), + ) + ) + + +def test_expected_active_reactions(): + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize("name", sorted(EXPECTED_REACTIONS)) +def test_smarts_parses(name): + assert rdChemReactions.ReactionFromSmarts( + REACTIONS[name]["reaction"] + ) is not None + + +@pytest.mark.parametrize("name", sorted(EXPECTED_REACTIONS)) +def test_registry_validation_passes(name): + assert registry._validate_reaction_smarts( + name, + REACTIONS[name], + ) == [] + + +def test_polyurethane_metadata(): + reaction = REACTIONS[URETHANE] + + assert reaction["reactant_1"] == "diol" + assert reaction["reactant_2"] == "di_isocyanate" + assert reaction["product"] == "polyurethane_chain" + assert reaction["delete_atom"] is False + + +def test_polythiourethane_metadata(): + reaction = REACTIONS[THIOURETHANE] + + assert reaction["reactant_1"] == "dithiol" + assert reaction["reactant_2"] == "di_isocyanate" + assert reaction["product"] == "polythiourethane_chain" + assert reaction["delete_atom"] is False + + +def test_diol_diisocyanate_reaction_executes(): + products = run_reaction( + URETHANE, + "OCCO", + "O=C=NCCCCCCN=C=O", + ) + + assert len(products) > 0 + + +def test_dithiol_diisocyanate_reaction_executes(): + products = run_reaction( + THIOURETHANE, + "SCCS", + "O=C=NCCCCCCN=C=O", + ) + + assert len(products) > 0 + + +def test_polyurethane_rejects_dithiol(): + products = run_reaction( + URETHANE, + "SCCS", + "O=C=NCCCCCCN=C=O", + ) + + assert len(products) == 0 + + +def test_polythiourethane_rejects_diol(): + products = run_reaction( + THIOURETHANE, + "OCCO", + "O=C=NCCCCCCN=C=O", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_thiol_ene_polymers.py b/tests/unit/detectors/reactions_library/test_thiol_ene_polymers.py new file mode 100644 index 00000000..253df4ed --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_thiol_ene_polymers.py @@ -0,0 +1,87 @@ +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.thiol_ene_polymers import ( + REACTIONS, +) + + +NAME = "Dithiol and Diene Thiol-Ene Click Polymerization" + + +def run_reaction(smiles_1, smiles_2): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[NAME]["reaction"] + ) + + return rxn.RunReactants( + ( + Chem.AddHs(Chem.MolFromSmiles(smiles_1)), + Chem.AddHs(Chem.MolFromSmiles(smiles_2)), + ) + ) + + +def test_expected_active_reaction(): + assert set(REACTIONS) == {NAME} + + +def test_metadata(): + reaction = REACTIONS[NAME] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "dithiol" + assert reaction["reactant_2"] == "diene" + assert reaction["product"] == "poly_thioether_chain" + assert reaction["delete_atom"] is False + + +def test_smarts_parses(): + assert rdChemReactions.ReactionFromSmarts( + REACTIONS[NAME]["reaction"] + ) is not None + + +def test_registry_validation_passes(): + assert registry._validate_reaction_smarts( + NAME, + REACTIONS[NAME], + ) == [] + + +def test_dithiol_diene_reaction_executes(): + products = run_reaction( + "SCCS", + "C=CC=C", + ) + + assert len(products) > 0 + + +def test_products_are_sanitizable(): + products = run_reaction( + "SCCS", + "C=CC=C", + ) + + for product in products[0]: + Chem.SanitizeMol(product) + + +def test_dithiol_diene_reaction_rejects_saturated_hydrocarbon(): + products = run_reaction( + "SCCS", + "CCCC", + ) + + assert len(products) == 0 + + +def test_reaction_rejects_thioether_without_sh(): + products = run_reaction( + "CSC", + "C=CC=C", + ) + + assert len(products) == 0 \ No newline at end of file diff --git a/tests/unit/detectors/reactions_library/test_vinyl_polymers.py b/tests/unit/detectors/reactions_library/test_vinyl_polymers.py new file mode 100644 index 00000000..30f96dfb --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_vinyl_polymers.py @@ -0,0 +1,349 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry +from AutoREACTER.detectors.reactions_library.vinyl_polymers import ( + REACTIONS, +) + + +INITIATION = "Vinyl Addition Polymerization Initiation" +PROPAGATION = "Vinyl Addition Polymerization Propagation" +CO_INITIATION = "Vinyl Copolymerization Initiation" +TFE_INITIATION = "Tetrafluoroethylene Initiation" +TFE_PROPAGATION = "Tetrafluoroethylene Propagation" + + +EXPECTED_REACTIONS = { + INITIATION, + PROPAGATION, + CO_INITIATION, + TFE_INITIATION, + TFE_PROPAGATION, +} + + +def reaction_templates(name): + rxn = rdChemReactions.ReactionFromSmarts( + REACTIONS[name]["reaction"] + ) + + assert rxn is not None + + reactants = [ + Chem.Mol( + rxn.GetReactantTemplate(i) + ) + for i in range( + rxn.GetNumReactantTemplates() + ) + ] + + products = [ + Chem.Mol( + rxn.GetProductTemplate(i) + ) + for i in range( + rxn.GetNumProductTemplates() + ) + ] + + return reactants, products + + +# ============================================================================= +# Structure +# ============================================================================= + +def test_expected_active_reactions(): + """ + This deliberately catches accidental dictionary nesting. + + All five currently enabled vinyl/TFE reactions are intended to be + top-level reaction-library entries. + """ + assert set(REACTIONS) == EXPECTED_REACTIONS + + +@pytest.mark.parametrize( + "name", + sorted(EXPECTED_REACTIONS), +) +def test_each_reaction_is_top_level(name): + assert name in REACTIONS + assert isinstance(REACTIONS[name], dict) + + +@pytest.mark.parametrize( + "name", + sorted(EXPECTED_REACTIONS), +) +def test_smarts_parses(name): + assert rdChemReactions.ReactionFromSmarts( + REACTIONS[name]["reaction"] + ) is not None + + +@pytest.mark.parametrize( + "name", + sorted(EXPECTED_REACTIONS), +) +def test_registry_validation_passes(name): + assert registry._validate_reaction_smarts( + name, + REACTIONS[name], + ) == [] + + +# ============================================================================= +# Metadata +# ============================================================================= + +def test_vinyl_initiation_metadata(): + reaction = REACTIONS[INITIATION] + + assert reaction["same_reactants"] is True + assert reaction["reactant_1"] == "vinyl" + assert reaction.get("reactant_2") is None + assert reaction["product"] == "vinyl_chain_end_radical" + assert reaction["delete_atom"] is False + + +def test_vinyl_propagation_metadata(): + reaction = REACTIONS[PROPAGATION] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "vinyl" + + assert ( + reaction["reactant_2"] + == "vinyl_chain_end_radical" + ) + + assert reaction["product"] == "vinyl_chain_end_radical" + + +def test_copolymerization_initiation_metadata(): + reaction = REACTIONS[CO_INITIATION] + + assert reaction["same_reactants"] is False + assert reaction["reactant_1"] == "vinyl" + assert reaction["reactant_2"] == "vinyl" + assert reaction["product"] == "vinyl_chain_end_radical" + + +def test_tfe_initiation_metadata(): + reaction = REACTIONS[TFE_INITIATION] + + assert reaction["reactant_1"] == "tetrafluoroethylene" + assert reaction["reactant_2"] == "tetrafluoroethylene" + assert reaction["product"] == "vinyl_chain_end_radical" + + +def test_tfe_propagation_metadata(): + reaction = REACTIONS[TFE_PROPAGATION] + + assert reaction["reactant_1"] == "vinyl_chain_end_radical" + assert reaction["reactant_2"] == "tetrafluoroethylene" + assert reaction["product"] == "vinyl_chain_end_radical" + + +# ============================================================================= +# H-T vinyl initiation topology +# ============================================================================= + +def test_vinyl_initiation_forms_new_bond_between_maps_1_and_2(): + reactants, products = reaction_templates( + INITIATION + ) + + assert registry._has_bond_between_atom_maps( + reactants, + 1, + 2, + ) is False + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +def test_vinyl_initiation_caps_map_3_as_ch3(): + _, products = reaction_templates( + INITIATION + ) + + map_3_atoms = [ + atom + for mol in products + for atom in mol.GetAtoms() + if atom.GetAtomMapNum() == 3 + ] + + assert len(map_3_atoms) == 1 + + atom = map_3_atoms[0] + + assert atom.GetSymbol() == "C" + + +# ============================================================================= +# Vinyl propagation topology +# ============================================================================= + +def test_vinyl_propagation_forms_new_1_2_bond(): + reactants, products = reaction_templates( + PROPAGATION + ) + + assert registry._has_bond_between_atom_maps( + reactants, + 1, + 2, + ) is False + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +def test_vinyl_propagation_retains_new_active_map_3(): + _, products = reaction_templates( + PROPAGATION + ) + + product_maps = registry._atom_maps_in_templates( + products + ) + + assert 3 in product_maps + + +# ============================================================================= +# Vinyl copolymerization initiation +# ============================================================================= + +def test_copolymerization_initiation_forms_new_1_2_bond(): + reactants, products = reaction_templates( + CO_INITIATION + ) + + assert registry._has_bond_between_atom_maps( + reactants, + 1, + 2, + ) is False + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +def test_copolymerization_product_retains_radical_map_4(): + _, products = reaction_templates( + CO_INITIATION + ) + + assert 4 in registry._atom_maps_in_templates( + products + ) + + +# ============================================================================= +# TFE initiation +# ============================================================================= + +def test_tfe_initiation_forms_new_1_2_bond(): + reactants, products = reaction_templates( + TFE_INITIATION + ) + + assert registry._has_bond_between_atom_maps( + reactants, + 1, + 2, + ) is False + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +def test_tfe_initiation_preserves_all_four_fluorines(): + _, products = reaction_templates( + TFE_INITIATION + ) + + maps = registry._atom_maps_in_templates( + products + ) + + assert { + 4, + 5, + 6, + 7, + }.issubset(maps) + + +# ============================================================================= +# TFE propagation topology +# ============================================================================= + +def test_tfe_propagation_forms_new_bond_between_maps_2_and_3(): + """ + In the actual SMARTS, 1-2 already exists in the growing chain. + + The propagation step forms the new connection between maps 2 and 3. + """ + reactants, products = reaction_templates( + TFE_PROPAGATION + ) + + assert registry._has_bond_between_atom_maps( + reactants, + 2, + 3, + ) is False + + assert registry._has_bond_between_atom_maps( + products, + 2, + 3, + ) is True + + +def test_tfe_propagation_maps_1_and_2_are_already_bonded_before_reaction(): + reactants, _ = reaction_templates( + TFE_PROPAGATION + ) + + assert registry._has_bond_between_atom_maps( + reactants, + 1, + 2, + ) is True + + +def test_tfe_propagation_should_declare_new_initiator_maps(): + """ + The registry defaults initiator_atom_maps to (1, 2). + + But TFE propagation's actual NEW bond is 2-3, while 1-2 already + exists before the reaction. Therefore this reaction should explicitly + override the default initiator mapping. + """ + reaction = REACTIONS[TFE_PROPAGATION] + + assert reaction.get( + "initiator_atom_maps" + ) == (2, 3) \ No newline at end of file diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py new file mode 100644 index 00000000..beaf4ffe --- /dev/null +++ b/tests/unit/test_session.py @@ -0,0 +1,1040 @@ +import importlib +import json +from pathlib import Path +from types import SimpleNamespace + +import pytest + + +session_module = importlib.import_module("AutoREACTER.session") +cache_module = importlib.import_module("AutoREACTER.cache") + +Session = session_module.Session + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_validated_inputs(simulation_name="test_simulation"): + """ + Minimal object representing InputParser.validate_inputs() output. + + Session/read_input only requires simulation_name directly during this + stage, so a lightweight namespace keeps these tests isolated from + InputParser itself. + """ + return SimpleNamespace( + simulation_name=simulation_name + ) + + +def write_json(path: Path, data: dict) -> Path: + path.write_text( + json.dumps(data), + encoding="utf-8", + ) + return path + + +def configure_read_input_dependencies( + monkeypatch, + tmp_path, + *, + validated_inputs=None, + validation_error=None, +): + """ + Replace Initialization, InputParser, and GetCacheDir so read_input() + can be tested without touching the real AutoREACTER environment. + """ + if validated_inputs is None: + validated_inputs = make_validated_inputs() + + calls = { + "initialization": 0, + "parser_instances": 0, + "validate_calls": 0, + "validated_data": None, + "clear_staging": None, + "cache_calls": 0, + } + + staging_dir = tmp_path / "staging" + + def fake_initialization(): + calls["initialization"] += 1 + + class FakeInputParser: + def __init__(self): + calls["parser_instances"] += 1 + + def validate_inputs(self, data): + calls["validate_calls"] += 1 + calls["validated_data"] = data + + if validation_error is not None: + raise validation_error + + return validated_inputs + + def fake_get_cache_dir(clear_staging=True): + calls["cache_calls"] += 1 + calls["clear_staging"] = clear_staging + + staging_dir.mkdir( + parents=True, + exist_ok=True, + ) + + return SimpleNamespace( + staging_dir=staging_dir + ) + + monkeypatch.setattr( + session_module, + "Initialization", + fake_initialization, + ) + + monkeypatch.setattr( + session_module, + "InputParser", + FakeInputParser, + ) + + monkeypatch.setattr( + cache_module, + "GetCacheDir", + fake_get_cache_dir, + ) + + return calls, staging_dir, validated_inputs + + +# ============================================================================= +# Session dataclass +# ============================================================================= + + +def test_session_stores_required_core_fields(tmp_path): + inputs = make_validated_inputs() + + session = Session( + inputs=inputs, + staging_dir=tmp_path / "staging", + output_dir=tmp_path / "output", + images_dir=tmp_path / "output" / "images", + ) + + assert session.inputs is inputs + assert session.staging_dir == tmp_path / "staging" + assert session.output_dir == tmp_path / "output" + + assert ( + session.images_dir + == tmp_path / "output" / "images" + ) + + +def test_session_pipeline_lists_default_to_empty(tmp_path): + session = Session( + inputs=make_validated_inputs(), + staging_dir=tmp_path / "staging", + output_dir=tmp_path / "output", + images_dir=tmp_path / "images", + ) + + assert session.monomer_roles == [] + assert session.reaction_instances == [] + assert session.non_reactants == [] + assert session.reaction_metadata == [] + + +def test_session_mutable_defaults_are_independent(tmp_path): + session_1 = Session( + inputs=make_validated_inputs("one"), + staging_dir=tmp_path / "staging1", + output_dir=tmp_path / "output1", + images_dir=tmp_path / "images1", + ) + + session_2 = Session( + inputs=make_validated_inputs("two"), + staging_dir=tmp_path / "staging2", + output_dir=tmp_path / "output2", + images_dir=tmp_path / "images2", + ) + + session_1.monomer_roles.append("role") + session_1.reaction_instances.append("reaction") + session_1.non_reactants.append("nonreactant") + session_1.reaction_metadata.append("metadata") + + assert session_2.monomer_roles == [] + assert session_2.reaction_instances == [] + assert session_2.non_reactants == [] + assert session_2.reaction_metadata == [] + + +def test_session_file_bundles_default_to_none(tmp_path): + session = Session( + inputs=make_validated_inputs(), + staging_dir=tmp_path / "staging", + output_dir=tmp_path / "output", + images_dir=tmp_path / "images", + ) + + assert session.ff_files is None + assert session.reacter_files is None + + +def test_session_runtime_defaults(tmp_path): + session = Session( + inputs=make_validated_inputs(), + staging_dir=tmp_path / "staging", + output_dir=tmp_path / "output", + images_dir=tmp_path / "images", + ) + + assert session.reaction_id_counter == 0 + + assert ( + session.reaction_progression_session + is None + ) + + assert session.deep_search is True + assert session.reaction_iteration_depth == 5 + assert session.wildcards is True + + assert ( + session.deduplicate_reaction_templates + is True + ) + + assert ( + session.write_second_reaction_stage + is True + ) + + +def test_session_uses_slots(tmp_path): + session = Session( + inputs=make_validated_inputs(), + staging_dir=tmp_path / "staging", + output_dir=tmp_path / "output", + images_dir=tmp_path / "images", + ) + + with pytest.raises(AttributeError): + session.random_new_attribute = 123 + + +# ============================================================================= +# _resolve_input_path +# ============================================================================= + + +def test_resolve_input_path_returns_absolute_json_path( + tmp_path, +): + input_file = tmp_path / "input.json" + input_file.write_text( + "{}", + encoding="utf-8", + ) + + result = session_module._resolve_input_path( + input_file + ) + + assert result == input_file.resolve() + assert result.is_absolute() + + +def test_resolve_input_path_accepts_uppercase_json_suffix( + tmp_path, +): + input_file = tmp_path / "input.JSON" + input_file.write_text( + "{}", + encoding="utf-8", + ) + + result = session_module._resolve_input_path( + input_file + ) + + assert result == input_file.resolve() + + +def test_resolve_input_path_rejects_missing_file( + tmp_path, +): + missing = tmp_path / "missing.json" + + with pytest.raises( + FileNotFoundError, + match="Input file not found", + ): + session_module._resolve_input_path( + missing + ) + + +def test_resolve_input_path_rejects_non_json_file( + tmp_path, +): + input_file = tmp_path / "input.txt" + input_file.write_text( + "{}", + encoding="utf-8", + ) + + with pytest.raises( + ValueError, + match="Input file must be a JSON file", + ): + session_module._resolve_input_path( + input_file + ) + + +def test_resolve_input_path_rejects_directory_named_json( + tmp_path, +): + directory = tmp_path / "fake.json" + directory.mkdir() + + with pytest.raises( + ValueError, + match="Input file must be a JSON file", + ): + session_module._resolve_input_path( + directory + ) + + +# ============================================================================= +# _clear_directory +# ============================================================================= + + +def test_clear_directory_removes_files_but_preserves_root( + tmp_path, +): + directory = tmp_path / "output" + directory.mkdir() + + (directory / "one.txt").write_text("one") + (directory / "two.txt").write_text("two") + + session_module._clear_directory( + directory + ) + + assert directory.exists() + assert directory.is_dir() + assert list(directory.iterdir()) == [] + + +def test_clear_directory_removes_nested_directories( + tmp_path, +): + directory = tmp_path / "output" + nested = directory / "nested" / "deeper" + + nested.mkdir(parents=True) + + (nested / "data.txt").write_text( + "content", + encoding="utf-8", + ) + + session_module._clear_directory( + directory + ) + + assert directory.exists() + assert list(directory.iterdir()) == [] + + +def test_clear_directory_nonexistent_path_is_noop( + tmp_path, +): + path = tmp_path / "does_not_exist" + + session_module._clear_directory(path) + + assert not path.exists() + + +def test_clear_directory_file_path_is_noop( + tmp_path, +): + path = tmp_path / "file.txt" + path.write_text( + "keep me", + encoding="utf-8", + ) + + session_module._clear_directory(path) + + assert path.exists() + + assert ( + path.read_text(encoding="utf-8") + == "keep me" + ) + + +# ============================================================================= +# _resolve_output_dir +# ============================================================================= + + +@pytest.mark.parametrize( + "raw_output_dir", + [ + None, + "", + " ", + ], +) +def test_resolve_output_dir_uses_default_when_missing( + tmp_path, + raw_output_dir, +): + input_path = tmp_path / "input.json" + + result = session_module._resolve_output_dir( + raw_output_dir=raw_output_dir, + input_path=input_path, + simulation_name="my_sim", + ) + + expected = ( + tmp_path + / "AutoREACTER_outputs" + / "my_sim" + ).resolve() + + assert result == expected + + +def test_resolve_output_dir_relative_path_is_relative_to_input( + tmp_path, +): + input_path = tmp_path / "input.json" + + result = session_module._resolve_output_dir( + raw_output_dir="custom/output", + input_path=input_path, + simulation_name="ignored_here", + ) + + assert result == ( + tmp_path / "custom" / "output" + ).resolve() + + +def test_resolve_output_dir_absolute_path_is_preserved( + tmp_path, +): + input_path = tmp_path / "input.json" + + absolute_output = ( + tmp_path + / "absolute_output" + ).resolve() + + result = session_module._resolve_output_dir( + raw_output_dir=str(absolute_output), + input_path=input_path, + simulation_name="sim", + ) + + assert result == absolute_output + + +def test_resolve_output_dir_windows_forward_slash_path(): + input_path = Path("/tmp/input.json") + + result = session_module._resolve_output_dir( + raw_output_dir=( + "C:/Users/Janitha/Documents/ARX" + ), + input_path=input_path, + simulation_name="sim", + ) + + assert result == Path( + "/mnt/c/Users/Janitha/Documents/ARX" + ).resolve() + + +def test_resolve_output_dir_windows_backslash_path(): + input_path = Path("/tmp/input.json") + + result = session_module._resolve_output_dir( + raw_output_dir=( + r"D:\Projects\AutoREACTER\outputs" + ), + input_path=input_path, + simulation_name="sim", + ) + + assert result == Path( + "/mnt/d/Projects/AutoREACTER/outputs" + ).resolve() + + +def test_resolve_output_dir_windows_drive_is_lowercased(): + result = session_module._resolve_output_dir( + raw_output_dir=r"E:\Research\run", + input_path=Path("/tmp/input.json"), + simulation_name="sim", + ) + + assert result == Path( + "/mnt/e/Research/run" + ).resolve() + + +def test_resolve_output_dir_expands_user_home( + tmp_path, + monkeypatch, +): + fake_home = tmp_path / "home" + fake_home.mkdir() + + monkeypatch.setenv( + "HOME", + str(fake_home), + ) + + result = session_module._resolve_output_dir( + raw_output_dir="~/arx_output", + input_path=tmp_path / "input.json", + simulation_name="sim", + ) + + assert result == ( + fake_home / "arx_output" + ).resolve() + + +# ============================================================================= +# read_input +# ============================================================================= + + +def test_read_input_calls_initialization_once( + tmp_path, + monkeypatch, +): + calls, _, _ = configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "test_simulation", + }, + ) + + session_module.read_input(input_file) + + assert calls["initialization"] == 1 + + +def test_read_input_constructs_input_parser_once( + tmp_path, + monkeypatch, +): + calls, _, _ = configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "test_simulation", + }, + ) + + session_module.read_input(input_file) + + assert calls["parser_instances"] == 1 + assert calls["validate_calls"] == 1 + + +def test_read_input_passes_json_data_to_validator( + tmp_path, + monkeypatch, +): + calls, _, _ = configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + + data = { + "simulation_name": "demo", + "deep_search": False, + "wildcards": True, + } + + input_file = write_json( + tmp_path / "input.json", + data, + ) + + session_module.read_input(input_file) + + assert calls["validated_data"] == data + + +def test_read_input_propagates_clear_staging_true( + tmp_path, + monkeypatch, +): + calls, _, _ = configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "demo", + }, + ) + + session_module.read_input( + input_file, + clear_staging=True, + ) + + assert calls["clear_staging"] is True + + +def test_read_input_propagates_clear_staging_false( + tmp_path, + monkeypatch, +): + calls, _, _ = configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "demo", + }, + ) + + session_module.read_input( + input_file, + clear_staging=False, + ) + + assert calls["clear_staging"] is False + + +def test_read_input_returns_session( + tmp_path, + monkeypatch, +): + _, staging_dir, validated = ( + configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "test_simulation", + }, + ) + + result = session_module.read_input( + input_file + ) + + assert isinstance(result, Session) + assert result.inputs is validated + assert result.staging_dir == staging_dir + + +def test_read_input_creates_default_output_directory( + tmp_path, + monkeypatch, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + validated_inputs=make_validated_inputs( + "my_simulation" + ), + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "my_simulation", + }, + ) + + result = session_module.read_input( + input_file + ) + + expected = ( + tmp_path + / "AutoREACTER_outputs" + / "my_simulation" + ).resolve() + + assert result.output_dir == expected + assert expected.is_dir() + + +def test_read_input_creates_images_directory( + tmp_path, + monkeypatch, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "test_simulation", + }, + ) + + result = session_module.read_input( + input_file + ) + + assert ( + result.images_dir + == result.output_dir / "images" + ) + + assert result.images_dir.is_dir() + + +def test_read_input_uses_relative_custom_output_dir( + tmp_path, + monkeypatch, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + validated_inputs=make_validated_inputs( + "demo" + ), + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "demo", + "output_dir": "custom_outputs", + }, + ) + + result = session_module.read_input( + input_file + ) + + assert result.output_dir == ( + tmp_path / "custom_outputs" + ).resolve() + + +def test_read_input_uses_absolute_custom_output_dir( + tmp_path, + monkeypatch, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + validated_inputs=make_validated_inputs( + "demo" + ), + ) + + custom_output = ( + tmp_path / "absolute_custom" + ).resolve() + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "demo", + "output_dir": str(custom_output), + }, + ) + + result = session_module.read_input( + input_file + ) + + assert result.output_dir == custom_output + assert custom_output.is_dir() + + +def test_read_input_clears_existing_output_directory( + tmp_path, + monkeypatch, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + validated_inputs=make_validated_inputs( + "demo" + ), + ) + + output_dir = tmp_path / "existing_output" + output_dir.mkdir() + + old_file = output_dir / "old.txt" + old_file.write_text( + "old data", + encoding="utf-8", + ) + + nested = output_dir / "old_folder" + nested.mkdir() + + (nested / "old_nested.txt").write_text( + "old nested data", + encoding="utf-8", + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "demo", + "output_dir": str(output_dir), + }, + ) + + result = session_module.read_input( + input_file + ) + + assert result.output_dir == output_dir.resolve() + + assert not old_file.exists() + assert not nested.exists() + + assert ( + output_dir / "images" + ).is_dir() + + +def test_read_input_rejects_output_path_that_is_file( + tmp_path, + monkeypatch, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + validated_inputs=make_validated_inputs( + "demo" + ), + ) + + output_file = tmp_path / "not_a_directory" + output_file.write_text( + "existing file", + encoding="utf-8", + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "demo", + "output_dir": str(output_file), + }, + ) + + with pytest.raises( + ValueError, + match=( + "Resolved output_dir exists " + "but is not a directory" + ), + ): + session_module.read_input( + input_file + ) + + +@pytest.mark.parametrize( + "simulation_name", + [ + "../escape", + "folder/simulation", + ".", + "..", + ], +) +def test_read_input_rejects_unsafe_simulation_name( + tmp_path, + monkeypatch, + simulation_name, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + validated_inputs=make_validated_inputs( + simulation_name + ), + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": simulation_name, + }, + ) + + with pytest.raises( + ValueError, + match=( + "Invalid simulation_name " + "for output directory" + ), + ): + session_module.read_input( + input_file + ) + + +def test_read_input_propagates_validation_error( + tmp_path, + monkeypatch, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + validation_error=ValueError( + "bad inputs" + ), + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "demo", + }, + ) + + with pytest.raises( + ValueError, + match="bad inputs", + ): + session_module.read_input( + input_file + ) + + +def test_read_input_invalid_json_propagates_json_error( + tmp_path, + monkeypatch, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + + input_file = tmp_path / "input.json" + + input_file.write_text( + "{ definitely not valid json", + encoding="utf-8", + ) + + with pytest.raises( + json.JSONDecodeError + ): + session_module.read_input( + input_file + ) + + +def test_read_input_missing_file_fails_before_initialization( + tmp_path, + monkeypatch, +): + calls, _, _ = configure_read_input_dependencies( + monkeypatch, + tmp_path, + ) + + missing = tmp_path / "missing.json" + + with pytest.raises(FileNotFoundError): + session_module.read_input( + missing + ) + + assert calls["initialization"] == 0 + assert calls["cache_calls"] == 0 + assert calls["parser_instances"] == 0 + + +def test_read_input_prints_session_information( + tmp_path, + monkeypatch, + capsys, +): + configure_read_input_dependencies( + monkeypatch, + tmp_path, + validated_inputs=make_validated_inputs( + "print_test" + ), + ) + + input_file = write_json( + tmp_path / "input.json", + { + "simulation_name": "print_test", + }, + ) + + result = session_module.read_input( + input_file + ) + + output = capsys.readouterr().out + + assert ( + "[INFO] Initialized AutoREACTER Session" + in output + ) + + assert ( + "[INFO] Simulation Name: print_test" + in output + ) + + assert str(input_file.resolve()) in output + assert str(result.staging_dir) in output + assert str(result.output_dir) in output \ No newline at end of file From a84280637f2542f8009a9a8fe8e7babeb9beb316 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:33:45 -0400 Subject: [PATCH 138/176] Create test_registry.py --- .../reactions_library/test_registry.py | 768 ++++++++++++++++++ 1 file changed, 768 insertions(+) create mode 100644 tests/unit/detectors/reactions_library/test_registry.py diff --git a/tests/unit/detectors/reactions_library/test_registry.py b/tests/unit/detectors/reactions_library/test_registry.py new file mode 100644 index 00000000..b8cd4383 --- /dev/null +++ b/tests/unit/detectors/reactions_library/test_registry.py @@ -0,0 +1,768 @@ +import pytest +from rdkit import Chem +from rdkit.Chem import rdChemReactions + +from AutoREACTER.detectors.reactions_library import registry + + +# ============================================================================= +# Helpers +# ============================================================================= + +def make_valid_reaction( + *, + smarts="[C:1].[O:2]>>[C:1]-[O:2]", + **extra, +): + """Create a minimal valid AutoREACTER reaction-library entry.""" + reaction = { + "reaction": smarts, + } + + reaction.update(extra) + + return reaction + + +def templates_from_smarts(smarts): + """ + Convert reaction SMARTS into independent reactant/product Mol copies. + + RDKit's GetReactantTemplate() and GetProductTemplate() return objects + owned by the ChemicalReaction. Therefore, the returned templates must + be copied before the ChemicalReaction goes out of scope. + + Without the Chem.Mol copies below, tests may retain dangling C++ object + references and can eventually cause a segmentation fault. + """ + reaction = rdChemReactions.ReactionFromSmarts(smarts) + + assert reaction is not None + + reactants = [ + Chem.Mol( + reaction.GetReactantTemplate(i) + ) + for i in range( + reaction.GetNumReactantTemplates() + ) + ] + + products = [ + Chem.Mol( + reaction.GetProductTemplate(i) + ) + for i in range( + reaction.GetNumProductTemplates() + ) + ] + + return reactants, products + + +# ============================================================================= +# ReactionLibraryValidationError +# ============================================================================= + +def test_validation_error_is_value_error(): + assert issubclass( + registry.ReactionLibraryValidationError, + ValueError, + ) + + +# ============================================================================= +# _atom_maps_in_templates() +# ============================================================================= + +def test_atom_maps_in_templates_collects_all_nonzero_maps(): + reactants, _ = templates_from_smarts( + "[C:1].[O:2].[N:7]>>[C:1]-[O:2]-[N:7]" + ) + + result = registry._atom_maps_in_templates( + reactants + ) + + assert result == { + 1, + 2, + 7, + } + + +def test_atom_maps_in_templates_ignores_unmapped_atoms(): + reactants, _ = templates_from_smarts( + "[C:1].O>>[C:1]-O" + ) + + result = registry._atom_maps_in_templates( + reactants + ) + + assert result == { + 1, + } + + +def test_atom_maps_in_templates_empty_templates_returns_empty_set(): + result = registry._atom_maps_in_templates( + [] + ) + + assert result == set() + + +def test_atom_maps_in_templates_deduplicates_map_numbers(): + reactants, _ = templates_from_smarts( + "[C:1].[O:1]>>[C:1]-[O:1]" + ) + + result = registry._atom_maps_in_templates( + reactants + ) + + assert result == { + 1, + } + + +# ============================================================================= +# _has_bond_between_atom_maps() +# ============================================================================= + +def test_has_bond_between_atom_maps_returns_true_when_bond_exists(): + _, products = templates_from_smarts( + "[C:1].[O:2]>>[C:1]-[O:2]" + ) + + result = registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) + + assert result is True + + +def test_has_bond_between_atom_maps_is_order_independent(): + _, products = templates_from_smarts( + "[C:1].[O:2]>>[C:1]-[O:2]" + ) + + result = registry._has_bond_between_atom_maps( + products, + 2, + 1, + ) + + assert result is True + + +def test_has_bond_between_atom_maps_returns_false_without_bond(): + _, products = templates_from_smarts( + "[C:1].[O:2]>>[C:1].[O:2]" + ) + + result = registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) + + assert result is False + + +def test_has_bond_between_atom_maps_returns_false_for_missing_map(): + _, products = templates_from_smarts( + "[C:1].[O:2]>>[C:1]-[O:2]" + ) + + result = registry._has_bond_between_atom_maps( + products, + 1, + 99, + ) + + assert result is False + + +def test_has_bond_between_atom_maps_empty_templates_returns_false(): + result = registry._has_bond_between_atom_maps( + [], + 1, + 2, + ) + + assert result is False + + +# ============================================================================= +# _validate_reaction_smarts() +# ============================================================================= + +def test_valid_reaction_smarts_has_no_errors(): + reaction = make_valid_reaction() + + errors = registry._validate_reaction_smarts( + "test_reaction", + reaction, + ) + + assert errors == [] + + +def test_missing_reaction_key_is_reported(): + errors = registry._validate_reaction_smarts( + "test_reaction", + {}, + ) + + assert errors == [ + "test_reaction: missing required key 'reaction'" + ] + + +def test_empty_reaction_smarts_is_reported_as_missing(): + errors = registry._validate_reaction_smarts( + "test_reaction", + { + "reaction": "", + }, + ) + + assert errors == [ + "test_reaction: missing required key 'reaction'" + ] + + +def test_validation_can_be_explicitly_disabled(): + """ + Special reactions can intentionally bypass the initiator-bond check. + """ + reaction = { + "reaction": "THIS DOES NOT NEED TO BE VALIDATED", + "validate_initiator_bond": False, + } + + errors = registry._validate_reaction_smarts( + "special_reaction", + reaction, + ) + + assert errors == [] + + +def test_missing_rdkit_is_reported(monkeypatch): + monkeypatch.setattr( + registry, + "rdChemReactions", + None, + ) + + errors = registry._validate_reaction_smarts( + "test_reaction", + make_valid_reaction(), + ) + + assert errors == [ + "test_reaction: RDKit is required to validate reaction SMARTS" + ] + + +@pytest.mark.parametrize( + "initiator_maps", + [ + (), + (1,), + (1, 2, 3), + [1], + [1, 2, 3], + ], +) +def test_initiator_atom_maps_must_contain_exactly_two_maps( + initiator_maps, +): + reaction = make_valid_reaction( + initiator_atom_maps=initiator_maps, + ) + + errors = registry._validate_reaction_smarts( + "test_reaction", + reaction, + ) + + assert errors == [ + "test_reaction: initiator_atom_maps must contain exactly two atom maps" + ] + + +def test_invalid_reaction_smarts_is_reported(): + reaction = { + "reaction": "not_a_reaction_smarts", + } + + errors = registry._validate_reaction_smarts( + "bad_reaction", + reaction, + ) + + assert errors + + assert errors[0].startswith( + "bad_reaction:" + ) + + assert ( + "invalid reaction SMARTS" + in errors[0] + or + "could not parse reaction SMARTS" + in errors[0] + ) + + +def test_missing_initiator_map_from_reactants_is_reported(): + reaction = { + "reaction": "[C:1].O>>[C:1]-[O:2]", + } + + errors = registry._validate_reaction_smarts( + "test_reaction", + reaction, + ) + + assert any( + "initiator atom maps missing from reactants: [2]" + in error + for error in errors + ) + + +def test_missing_initiator_map_from_products_is_reported(): + reaction = { + "reaction": "[C:1].[O:2]>>[C:1]-O", + } + + errors = registry._validate_reaction_smarts( + "test_reaction", + reaction, + ) + + assert any( + "initiator atom maps missing from products: [2]" + in error + for error in errors + ) + + +def test_missing_initiator_bond_is_reported(): + reaction = { + "reaction": "[C:1].[O:2]>>[C:1].[O:2]", + } + + errors = registry._validate_reaction_smarts( + "test_reaction", + reaction, + ) + + assert ( + "test_reaction: product does not contain required " + "AutoREACTER initiator bond between atom maps 1 and 2" + in errors + ) + + +def test_missing_product_map_can_generate_multiple_validation_errors(): + """ + If a mapped initiator disappears from the product, both the missing-map + error and missing-bond error should be preserved. + """ + reaction = { + "reaction": "[C:1].[O:2]>>[C:1]-O", + } + + errors = registry._validate_reaction_smarts( + "test_reaction", + reaction, + ) + + assert any( + "missing from products" + in error + for error in errors + ) + + assert any( + "product does not contain required" + in error + for error in errors + ) + + +def test_custom_initiator_atom_maps_are_supported(): + reaction = { + "reaction": "[C:7].[O:9]>>[C:7]-[O:9]", + "initiator_atom_maps": ( + 7, + 9, + ), + } + + errors = registry._validate_reaction_smarts( + "custom_maps", + reaction, + ) + + assert errors == [] + + +def test_custom_maps_still_require_product_bond(): + reaction = { + "reaction": "[C:7].[O:9]>>[C:7].[O:9]", + "initiator_atom_maps": ( + 7, + 9, + ), + } + + errors = registry._validate_reaction_smarts( + "custom_maps", + reaction, + ) + + assert any( + "between atom maps 7 and 9" + in error + for error in errors + ) + + +def test_initiator_atom_maps_are_converted_to_int(): + """ + String map numbers are accepted because registry converts them using int(). + """ + reaction = { + "reaction": "[C:7].[O:9]>>[C:7]-[O:9]", + "initiator_atom_maps": ( + "7", + "9", + ), + } + + errors = registry._validate_reaction_smarts( + "custom_maps", + reaction, + ) + + assert errors == [] + + +# ============================================================================= +# validate_reactions() +# ============================================================================= + +def test_validate_reactions_accepts_valid_dictionary(): + reactions = { + "reaction_1": make_valid_reaction(), + "reaction_2": make_valid_reaction( + smarts="[N:1].[C:2]>>[N:1]-[C:2]" + ), + } + + result = registry.validate_reactions( + reactions + ) + + assert result is None + + +def test_validate_reactions_rejects_non_dictionary_entry(): + reactions = { + "bad_reaction": "not a dictionary", + } + + with pytest.raises( + registry.ReactionLibraryValidationError, + match="reaction entry must be a dictionary", + ): + registry.validate_reactions( + reactions + ) + + +def test_validate_reactions_rejects_missing_reaction_smarts(): + reactions = { + "bad_reaction": {}, + } + + with pytest.raises( + registry.ReactionLibraryValidationError, + match="missing required key 'reaction'", + ): + registry.validate_reactions( + reactions + ) + + +def test_validate_reactions_aggregates_multiple_reaction_errors(): + reactions = { + "bad_1": {}, + "bad_2": { + "reaction": "[C:1].[O:2]>>[C:1].[O:2]" + }, + } + + with pytest.raises( + registry.ReactionLibraryValidationError + ) as exc_info: + registry.validate_reactions( + reactions + ) + + message = str( + exc_info.value + ) + + assert "bad_1" in message + assert "bad_2" in message + assert "missing required key 'reaction'" in message + assert "product does not contain required" in message + + +def test_validation_error_message_has_expected_header(): + reactions = { + "bad": {}, + } + + with pytest.raises( + registry.ReactionLibraryValidationError + ) as exc_info: + registry.validate_reactions( + reactions + ) + + assert str( + exc_info.value + ).startswith( + "Reaction library validation failed:" + ) + + +def test_empty_reaction_dictionary_is_valid(): + result = registry.validate_reactions( + {} + ) + + assert result is None + + +# ============================================================================= +# load_reactions() +# ============================================================================= + +def test_load_reactions_merges_modules(monkeypatch): + module_1 = { + "reaction_a": make_valid_reaction(), + } + + module_2 = { + "reaction_b": make_valid_reaction( + smarts="[N:1].[C:2]>>[N:1]-[C:2]" + ), + } + + monkeypatch.setattr( + registry, + "_REACTION_MODULES", + [ + module_1, + module_2, + ], + ) + + result = registry.load_reactions() + + assert set( + result + ) == { + "reaction_a", + "reaction_b", + } + + assert ( + result["reaction_a"] + is module_1["reaction_a"] + ) + + assert ( + result["reaction_b"] + is module_2["reaction_b"] + ) + + +def test_load_reactions_rejects_duplicate_reaction_names( + monkeypatch, +): + module_1 = { + "duplicate": make_valid_reaction(), + } + + module_2 = { + "duplicate": make_valid_reaction(), + } + + monkeypatch.setattr( + registry, + "_REACTION_MODULES", + [ + module_1, + module_2, + ], + ) + + with pytest.raises( + ValueError, + match="Duplicate reaction name: duplicate", + ): + registry.load_reactions() + + +def test_load_reactions_empty_modules_returns_empty_dict( + monkeypatch, +): + monkeypatch.setattr( + registry, + "_REACTION_MODULES", + [], + ) + + result = registry.load_reactions() + + assert result == {} + + +def test_load_reactions_calls_validation(monkeypatch): + module = { + "reaction_a": { + "reaction": "anything" + } + } + + monkeypatch.setattr( + registry, + "_REACTION_MODULES", + [ + module, + ], + ) + + captured = {} + + def fake_validate(reactions): + captured["reactions"] = reactions + + monkeypatch.setattr( + registry, + "validate_reactions", + fake_validate, + ) + + result = registry.load_reactions() + + assert ( + captured["reactions"] + == result + ) + + assert "reaction_a" in result + + +def test_load_reactions_propagates_validation_failure( + monkeypatch, +): + module = { + "bad": {}, + } + + monkeypatch.setattr( + registry, + "_REACTION_MODULES", + [ + module, + ], + ) + + with pytest.raises( + registry.ReactionLibraryValidationError + ): + registry.load_reactions() + + +# ============================================================================= +# ReactionLibrary backward compatibility +# ============================================================================= + +def test_reaction_library_exposes_reactions( + monkeypatch, +): + expected = { + "test": make_valid_reaction(), + } + + monkeypatch.setattr( + registry, + "load_reactions", + lambda: expected, + ) + + library = registry.ReactionLibrary() + + assert library.reactions is expected + + +# ============================================================================= +# Production registry sanity checks +# ============================================================================= + +def test_module_level_reactions_is_dictionary(): + assert isinstance( + registry.REACTIONS, + dict, + ) + + +def test_module_level_reactions_is_not_empty(): + assert registry.REACTIONS + + +def test_production_reaction_names_are_unique(): + names = list( + registry.REACTIONS.keys() + ) + + assert ( + len(names) + == len(set(names)) + ) + + +def test_production_registry_passes_validation(): + """ + All currently enabled production reactions must satisfy the + registry validation rules. + """ + result = registry.validate_reactions( + registry.REACTIONS + ) + + assert result is None + + +def test_fresh_production_load_matches_exported_registry(): + freshly_loaded = registry.load_reactions() + + assert ( + freshly_loaded + == registry.REACTIONS + ) \ No newline at end of file From ea96f41d58cb08546a7e519ad6b2eb972373e24f Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:35:00 -0400 Subject: [PATCH 139/176] Remove input parser and lunar wrapper tests --- tests/test_input_parser.py | 986 -------------------------------- tests/test_lunar_api_wrapper.py | 96 ---- 2 files changed, 1082 deletions(-) delete mode 100644 tests/test_input_parser.py delete mode 100644 tests/test_lunar_api_wrapper.py diff --git a/tests/test_input_parser.py b/tests/test_input_parser.py deleted file mode 100644 index 3c85c00c..00000000 --- a/tests/test_input_parser.py +++ /dev/null @@ -1,986 +0,0 @@ -""" -Comprehensive unit tests for :mod:`AutoREACTER.input_parser`. - -The suite exercises the current counts-mode and ratio-mode schemas, numeric -validation, force-field normalization, SMILES handling, monomer construction, -loop configuration, and the public ``validate_inputs`` workflow. - -Run from the repository root with either: - - python -m unittest tests.test_input_parser -v - -or: - - pytest -q tests/test_input_parser.py -""" - -from __future__ import annotations - -import copy -import unittest -from unittest.mock import patch - -from rdkit import Chem - -from AutoREACTER.input_parser import ( - CompatibilityError, - DuplicateMonomerError, - InputConflictError, - InputParser, - InputSchemaError, - MonomerEntry, - NumericFieldError, - Simulation, - SimulationSetup, - SmilesValidationError, -) - - -class InputParserTestCase(unittest.TestCase): - """Shared fixtures and helpers for input-parser tests.""" - - def setUp(self) -> None: - """Create a fresh parser before every test.""" - self.parser = InputParser() - - @staticmethod - def counts_input() -> dict: - """Return a fresh, valid counts-mode input dictionary.""" - return { - "simulation_name": "counts_example", - "force_field": "pcff", - "loop": False, - "simulations": [ - { - "tag": "small", - "temperature": 300, - "density": 0.80, - "monomer_counts": { - "ethanol": 2, - "water": 1, - }, - }, - { - "tag": "large", - "temperature": 350.0, - "density": 0.95, - "monomer_counts": { - "ethanol": 20, - "water": 10, - }, - }, - ], - "monomers": [ - { - "name": "ethanol", - "smiles": "CCO", - }, - { - "name": "water", - "smiles": "O", - }, - ], - } - - @staticmethod - def ratio_input() -> dict: - """Return a fresh, valid ratio-mode input dictionary.""" - return { - "simulation_name": "ratio_example", - "force_field": "PCFF-IFF", - "simulations": [ - { - "tag": "small", - "temperature": 300, - "density": 0.80, - "total_atoms": 1000, - "monomer_ratios": { - "ethanol": 2.0, - "water": 1.0, - }, - }, - { - "tag": "large", - "temperature": 350, - "density": 0.95, - "total_atoms": 10000, - "monomer_ratios": { - "ethanol": 2.0, - "water": 1.0, - }, - }, - ], - "monomers": [ - { - "name": "ethanol", - "smiles": "CCO", - }, - { - "name": "water", - "smiles": "O", - }, - ], - } - - -class TestBasicFormat(InputParserTestCase): - """Tests for top-level input structure validation.""" - - def test_validate_basic_format_accepts_required_keys(self) -> None: - inputs = { - "simulation_name": "demo", - "simulations": [], - "monomers": [], - } - - self.assertIsNone(self.parser.validate_basic_format(inputs)) - - def test_validate_basic_format_rejects_non_dictionary(self) -> None: - for value in (None, [], "input", 12): - with self.subTest(value=value): - with self.assertRaises(InputSchemaError): - self.parser.validate_basic_format(value) - - def test_validate_basic_format_rejects_each_missing_key(self) -> None: - valid = { - "simulation_name": "demo", - "simulations": [], - "monomers": [], - } - - for missing_key in tuple(valid): - with self.subTest(missing_key=missing_key): - inputs = valid.copy() - inputs.pop(missing_key) - - with self.assertRaises(InputSchemaError): - self.parser.validate_basic_format(inputs) - - -class TestCompositionModeDetection(InputParserTestCase): - """Tests for counts/ratio mode inference.""" - - def test_get_inputs_mode_detects_counts(self) -> None: - simulations = [ - { - "tag": "a", - "monomer_counts": {"ethanol": 1}, - } - ] - - self.assertEqual(self.parser._get_inputs_mode(simulations), "counts") - - def test_get_inputs_mode_detects_ratio(self) -> None: - simulations = [ - { - "tag": "a", - "monomer_ratios": {"ethanol": 1.0}, - } - ] - - self.assertEqual(self.parser._get_inputs_mode(simulations), "ratio") - - def test_get_inputs_mode_rejects_empty_or_non_list_value(self) -> None: - for value in (None, {}, (), [], "simulations"): - with self.subTest(value=value): - with self.assertRaises(InputSchemaError): - self.parser._get_inputs_mode(value) - - def test_get_inputs_mode_rejects_non_dictionary_simulation(self) -> None: - with self.assertRaises(InputSchemaError): - self.parser._get_inputs_mode(["not-a-dictionary"]) - - def test_get_inputs_mode_rejects_missing_composition_field(self) -> None: - with self.assertRaises(InputSchemaError): - self.parser._get_inputs_mode( - [ - { - "tag": "a", - "temperature": 300, - "density": 0.8, - } - ] - ) - - def test_get_inputs_mode_rejects_both_fields_in_one_simulation(self) -> None: - with self.assertRaises(InputConflictError): - self.parser._get_inputs_mode( - [ - { - "tag": "a", - "monomer_counts": {"ethanol": 1}, - "monomer_ratios": {"ethanol": 1.0}, - } - ] - ) - - def test_get_inputs_mode_rejects_mixed_modes(self) -> None: - with self.assertRaises(InputConflictError): - self.parser._get_inputs_mode( - [ - { - "tag": "counts", - "monomer_counts": {"ethanol": 1}, - }, - { - "tag": "ratio", - "monomer_ratios": {"ethanol": 1.0}, - }, - ] - ) - - -class TestNumericValidation(InputParserTestCase): - """Tests for temperature and density helpers.""" - - def test_validate_temperature_returns_float(self) -> None: - self.assertEqual(self.parser._validate_temperature(300), 300.0) - self.assertEqual(self.parser._validate_temperature(300.5), 300.5) - - def test_validate_temperature_rejects_non_numeric_and_boolean(self) -> None: - for value in (None, "300", True, False, [], {}): - with self.subTest(value=value): - with self.assertRaises(NumericFieldError): - self.parser._validate_temperature(value) - - def test_validate_temperature_rejects_zero_and_negative_values(self) -> None: - for value in (0, -1, -273.15): - with self.subTest(value=value): - with self.assertRaises(NumericFieldError): - self.parser._validate_temperature(value) - - def test_validate_density_returns_float(self) -> None: - self.assertEqual(self.parser._validate_density(1), 1.0) - self.assertEqual(self.parser._validate_density(0.85), 0.85) - - def test_validate_density_rejects_non_numeric_and_boolean(self) -> None: - for value in (None, "0.85", True, False, [], {}): - with self.subTest(value=value): - with self.assertRaises(NumericFieldError): - self.parser._validate_density(value) - - def test_validate_density_rejects_zero_and_negative_values(self) -> None: - for value in (0, -0.1, -1): - with self.subTest(value=value): - with self.assertRaises(NumericFieldError): - self.parser._validate_density(value) - - -class TestForceFieldValidation(InputParserTestCase): - """Tests for force-field defaults, aliases, and compatibility.""" - - def test_validate_force_field_defaults_to_pcff(self) -> None: - self.assertEqual(self.parser._validate_force_field(None), "PCFF") - - def test_validate_force_field_normalizes_supported_aliases(self) -> None: - aliases = { - "pcff": "PCFF", - " PCFF-IFF ": "PCFF-IFF", - "cvff": "CVFF", - "cvff-iff": "CVFF-IFF", - "clayff": "Clay-FF", - "clay-ff": "Clay-FF", - "dreiding": "DREIDING", - "drieding": "DREIDING", - } - - for raw_value, expected in aliases.items(): - with self.subTest(raw_value=raw_value): - self.assertEqual( - self.parser._validate_force_field(raw_value), - expected, - ) - - def test_validate_force_field_rejects_empty_or_non_string_value(self) -> None: - for value in ("", " ", 12, True, [], {}): - with self.subTest(value=value): - with self.assertRaises(InputSchemaError): - self.parser._validate_force_field(value) - - def test_validate_force_field_rejects_unknown_name(self) -> None: - with self.assertRaises(InputSchemaError): - self.parser._validate_force_field("not-a-force-field") - - def test_validate_force_field_rejects_currently_incompatible_fields(self) -> None: - for value in ("oplsaa", "opls", "opls-aa", "gaff"): - with self.subTest(value=value): - with self.assertRaises(CompatibilityError): - self.parser._validate_force_field(value) - - -class TestSmilesValidation(InputParserTestCase): - """Tests for SMILES parsing, canonicalization, and duplicates.""" - - def test_validate_smiles_returns_canonical_smiles_and_molecule(self) -> None: - smiles, mol = self.parser._validate_smiles(" C(C)O ") - - self.assertEqual(smiles, "CCO") - self.assertIsInstance(mol, Chem.Mol) - - def test_validate_smiles_rejects_empty_or_non_string_values(self) -> None: - for value in (None, "", " ", 10, True, [], {}): - with self.subTest(value=value): - with self.assertRaises(SmilesValidationError): - self.parser._validate_smiles(value) - - def test_validate_smiles_rejects_invalid_smiles(self) -> None: - with self.assertRaises(SmilesValidationError): - self.parser._validate_smiles("not_a_smiles") - - def test_validate_no_duplicate_smiles_appends_unique_value(self) -> None: - seen = ["O"] - - result = self.parser.validate_no_duplicate_smiles("CCO", seen) - - self.assertIs(result, seen) - self.assertEqual(result, ["O", "CCO"]) - - def test_validate_no_duplicate_smiles_rejects_duplicate_value(self) -> None: - with self.assertRaises(DuplicateMonomerError): - self.parser.validate_no_duplicate_smiles("CCO", ["CCO"]) - - -class TestMoleculeProperties(InputParserTestCase): - """Tests for RDKit-derived monomer properties.""" - - def test_derive_molecule_properties_includes_hydrogen_atoms(self) -> None: - mol = Chem.MolFromSmiles("CCO") - self.assertIsNotNone(mol) - - num_atoms, molecular_weight = self.parser._derive_molecule_properties( - mol - ) - - self.assertEqual(num_atoms, 9) - self.assertAlmostEqual(molecular_weight, 46.069, places=2) - - def test_int_to_dict_retains_legacy_shape(self) -> None: - self.assertEqual(self.parser._int_to_dict(7), {"_": 7}) - - -class TestLegacyCompositionValidation(InputParserTestCase): - """Tests for the legacy composition validation helper.""" - - def test_validate_composition_accepts_counts_targets(self) -> None: - composition = { - "targets": [ - {"tag": "a"}, - {"tag": "b"}, - ] - } - - self.assertIs( - self.parser._validate_composition(composition, "counts"), - composition, - ) - - def test_validate_composition_accepts_ratio_total_atoms(self) -> None: - composition = { - "targets": [ - {"tag": "a", "total_atoms": 1000}, - {"tag": "b", "total_atoms": 2000}, - ] - } - - self.assertIs( - self.parser._validate_composition(composition, "ratio"), - composition, - ) - - def test_validate_composition_rejects_missing_or_empty_targets(self) -> None: - for composition in ({}, {"targets": None}, {"targets": []}): - with self.subTest(composition=composition): - with self.assertRaises(InputSchemaError): - self.parser._validate_composition( - composition, - "counts", - ) - - def test_validate_composition_rejects_duplicate_tags(self) -> None: - with self.assertRaises(InputSchemaError): - self.parser._validate_composition( - { - "targets": [ - {"tag": "same"}, - {"tag": "same"}, - ] - }, - "counts", - ) - - def test_validate_composition_rejects_invalid_ratio_total_atoms(self) -> None: - for value in (None, 0, -1, 1.5, True): - with self.subTest(value=value): - with self.assertRaises(NumericFieldError): - self.parser._validate_composition( - { - "targets": [ - { - "tag": "a", - "total_atoms": value, - } - ] - }, - "ratio", - ) - - def test_validate_composition_rejects_total_atoms_in_counts_mode(self) -> None: - with self.assertRaises(InputSchemaError): - self.parser._validate_composition( - { - "targets": [ - { - "tag": "a", - "total_atoms": 1000, - } - ] - }, - "counts", - ) - - -class TestSimulationValidation(InputParserTestCase): - """Tests for individual and grouped simulation validation.""" - - def test_validate_single_simulation_accepts_counts_mode(self) -> None: - simulation = Simulation( - tag="a", - temperature=300.0, - density=0.8, - monomer_counts={"ethanol": 0}, - ) - - self.assertIsNone( - self.parser._validate_single_simulation(simulation, "counts") - ) - - def test_validate_single_simulation_accepts_ratio_mode(self) -> None: - simulation = Simulation( - tag="a", - temperature=300.0, - density=0.8, - monomer_ratios={"ethanol": 0.0}, - total_atoms=1000, - ) - - self.assertIsNone( - self.parser._validate_single_simulation(simulation, "ratio") - ) - - def test_validate_single_simulation_rejects_invalid_common_fields(self) -> None: - cases = ( - Simulation( - tag="", - temperature=300.0, - density=0.8, - monomer_counts={"ethanol": 1}, - ), - Simulation( - tag="a", - temperature=0, - density=0.8, - monomer_counts={"ethanol": 1}, - ), - Simulation( - tag="a", - temperature=300.0, - density=0, - monomer_counts={"ethanol": 1}, - ), - ) - - expected_errors = ( - InputSchemaError, - NumericFieldError, - NumericFieldError, - ) - - for simulation, expected_error in zip(cases, expected_errors): - with self.subTest(simulation=simulation): - with self.assertRaises(expected_error): - self.parser._validate_single_simulation( - simulation, - "counts", - ) - - def test_validate_single_simulation_rejects_invalid_count(self) -> None: - simulation = Simulation( - tag="a", - temperature=300.0, - density=0.8, - monomer_counts={"ethanol": -1}, - ) - - with self.assertRaises(NumericFieldError): - self.parser._validate_single_simulation(simulation, "counts") - - def test_validate_single_simulation_rejects_invalid_ratio(self) -> None: - simulation = Simulation( - tag="a", - temperature=300.0, - density=0.8, - monomer_ratios={"ethanol": -0.1}, - total_atoms=1000, - ) - - with self.assertRaises(NumericFieldError): - self.parser._validate_single_simulation(simulation, "ratio") - - def test_validate_simulations_normalizes_counts_mode(self) -> None: - systems = copy.deepcopy(self.counts_input()["simulations"]) - - result = self.parser._validate_simulations(systems, "counts") - - self.assertEqual(result["method"], "counts") - self.assertEqual(result["temperatures"], [300.0, 350.0]) - self.assertEqual(result["density"], [0.8, 0.95]) - self.assertEqual(len(result["simulations"]), 2) - self.assertTrue( - all( - isinstance(simulation, Simulation) - for simulation in result["simulations"] - ) - ) - - def test_validate_simulations_normalizes_ratio_mode(self) -> None: - systems = copy.deepcopy(self.ratio_input()["simulations"]) - - result = self.parser._validate_simulations(systems, "ratio") - - self.assertEqual(result["method"], "ratio") - self.assertEqual(result["temperatures"], [300.0, 350.0]) - self.assertEqual(result["density"], [0.8, 0.95]) - self.assertEqual( - [simulation.total_atoms for simulation in result["simulations"]], - [1000, 10000], - ) - - def test_validate_simulations_rejects_duplicate_tags(self) -> None: - systems = copy.deepcopy(self.counts_input()["simulations"]) - systems[1]["tag"] = systems[0]["tag"] - - with self.assertRaises(InputSchemaError): - self.parser._validate_simulations(systems, "counts") - - def test_validate_simulations_rejects_total_atoms_in_counts_mode(self) -> None: - systems = copy.deepcopy(self.counts_input()["simulations"]) - systems[0]["total_atoms"] = 1000 - - with self.assertRaises(InputSchemaError): - self.parser._validate_simulations(systems, "counts") - - def test_validate_simulations_rejects_different_ratios_between_systems( - self, - ) -> None: - systems = copy.deepcopy(self.ratio_input()["simulations"]) - systems[1]["monomer_ratios"]["water"] = 2.0 - - with self.assertRaises(InputSchemaError): - self.parser._validate_simulations(systems, "ratio") - - -class TestSystemMonomerKeys(InputParserTestCase): - """Tests for agreement between monomer definitions and systems.""" - - def test_validate_system_monomer_keys_accepts_exact_names(self) -> None: - inputs = self.counts_input() - systems = inputs["simulations"] - - self.assertIsNone( - self.parser._validate_system_monomer_keys( - inputs, - systems, - "counts", - ) - ) - - def test_validate_system_monomer_keys_assigns_default_name(self) -> None: - inputs = { - "monomers": [ - { - "smiles": "CCO", - } - ] - } - systems = [ - { - "tag": "a", - "monomer_counts": { - "data_1": 1, - }, - } - ] - - self.parser._validate_system_monomer_keys( - inputs, - systems, - "counts", - ) - - self.assertEqual(inputs["monomers"][0]["name"], "data_1") - - def test_validate_system_monomer_keys_rejects_unknown_name(self) -> None: - inputs = self.counts_input() - systems = copy.deepcopy(inputs["simulations"]) - systems[0]["monomer_counts"]["unknown"] = 1 - - with self.assertRaises(InputSchemaError): - self.parser._validate_system_monomer_keys( - inputs, - systems, - "counts", - ) - - def test_validate_system_monomer_keys_rejects_missing_name(self) -> None: - inputs = self.counts_input() - systems = copy.deepcopy(inputs["simulations"]) - systems[0]["monomer_counts"].pop("water") - - with self.assertRaises(InputSchemaError): - self.parser._validate_system_monomer_keys( - inputs, - systems, - "counts", - ) - - -class TestMonomerEntryValidation(InputParserTestCase): - """Tests for construction of MonomerEntry objects.""" - - def test_validate_monomer_entry_builds_counts_map(self) -> None: - inputs = self.counts_input() - systems = copy.deepcopy(inputs["simulations"]) - - monomers = self.parser._validate_monomer_entry( - inputs, - "counts", - systems, - ) - - self.assertEqual(len(monomers), 2) - self.assertTrue( - all(isinstance(monomer, MonomerEntry) for monomer in monomers) - ) - self.assertEqual( - monomers[0].count, - { - "small": 2, - "large": 20, - }, - ) - self.assertIsNone(monomers[0].ratio) - self.assertEqual(monomers[0].smiles, "CCO") - self.assertIsInstance(monomers[0].rdkit_mol, Chem.Mol) - self.assertGreater(monomers[0].num_atoms, 0) - self.assertGreater(monomers[0].molecular_weight, 0.0) - - def test_validate_monomer_entry_builds_ratio_value(self) -> None: - inputs = self.ratio_input() - systems = copy.deepcopy(inputs["simulations"]) - - monomers = self.parser._validate_monomer_entry( - inputs, - "ratio", - systems, - ) - - self.assertEqual(monomers[0].ratio, 2.0) - self.assertIsNone(monomers[0].count) - - def test_validate_monomer_entry_rejects_non_list_monomers(self) -> None: - inputs = self.counts_input() - inputs["monomers"] = {} - - with self.assertRaises(InputSchemaError): - self.parser._validate_monomer_entry( - inputs, - "counts", - inputs["simulations"], - ) - - def test_validate_monomer_entry_rejects_non_dictionary_entry(self) -> None: - inputs = self.counts_input() - inputs["monomers"] = ["CCO"] - - with self.assertRaises(InputSchemaError): - self.parser._validate_monomer_entry( - inputs, - "counts", - inputs["simulations"], - ) - - def test_validate_monomer_entry_rejects_negative_count(self) -> None: - inputs = self.counts_input() - inputs["simulations"][0]["monomer_counts"]["ethanol"] = -1 - - with self.assertRaises(NumericFieldError): - self.parser._validate_monomer_entry( - inputs, - "counts", - inputs["simulations"], - ) - - def test_validate_monomer_entry_rejects_negative_ratio(self) -> None: - inputs = self.ratio_input() - inputs["simulations"][0]["monomer_ratios"]["ethanol"] = -1.0 - - with self.assertRaises(NumericFieldError): - self.parser._validate_monomer_entry( - inputs, - "ratio", - inputs["simulations"], - ) - - -class TestLegacyNumericFields(InputParserTestCase): - """Tests for the retained legacy numeric validator.""" - - def test_validate_numeric_fields_accepts_valid_values(self) -> None: - inputs = { - "density": 0.8, - "temperature": [300, 350.0], - "number_of_monomers": { - "data_1": 1, - "data_2": 2, - }, - } - - self.assertIsNone(self.parser._validate_numeric_fields(inputs)) - - def test_validate_numeric_fields_rejects_invalid_density(self) -> None: - inputs = { - "density": 0, - "temperature": 300, - "number_of_monomers": {"data_1": 1}, - } - - with self.assertRaises(NumericFieldError): - self.parser._validate_numeric_fields(inputs) - - def test_validate_numeric_fields_rejects_invalid_temperature(self) -> None: - inputs = { - "density": 0.8, - "temperature": [300, False], - "number_of_monomers": {"data_1": 1}, - } - - with self.assertRaises(NumericFieldError): - self.parser._validate_numeric_fields(inputs) - - def test_validate_numeric_fields_rejects_invalid_monomer_count(self) -> None: - inputs = { - "density": 0.8, - "temperature": 300, - "number_of_monomers": {"data_1": 0}, - } - - with self.assertRaises(NumericFieldError): - self.parser._validate_numeric_fields(inputs) - - -class TestLoopValidation(InputParserTestCase): - """Tests for loop configuration.""" - - def test_validate_loop_defaults_to_enabled(self) -> None: - self.assertEqual(self.parser._validate_loop({}), (True, None)) - - def test_validate_loop_accepts_booleans(self) -> None: - self.assertEqual( - self.parser._validate_loop({"loop": True}), - (True, None), - ) - self.assertEqual( - self.parser._validate_loop({"loop": False}), - (False, None), - ) - - def test_validate_loop_accepts_positive_integer( - self, - ) -> None: - self.assertEqual( - self.parser._validate_loop({"loop": 4}), - (True, 4), - ) - - def test_validate_loop_accepts_supported_keywords(self) -> None: - for keyword in ("loop", "repeat", "iterations", "do_loop"): - with self.subTest(keyword=keyword): - self.assertEqual( - self.parser._validate_loop({"loop": keyword}), - (True, None), - ) - - def test_validate_loop_rejects_invalid_values(self) -> None: - for value in (0, -1, 1.5, None, "yes", [], {}): - with self.subTest(value=value): - with self.assertRaises(InputSchemaError): - self.parser._validate_loop({"loop": value}) - - -class TestValidateInputsWorkflow(InputParserTestCase): - """End-to-end tests for the public validation entry point.""" - - def test_validate_inputs_builds_counts_setup(self) -> None: - inputs = self.counts_input() - - result = self.parser.validate_inputs(inputs) - - self.assertIsInstance(result, SimulationSetup) - self.assertEqual(result.simulation_name, "counts_example") - self.assertEqual(result.composition_method, "counts") - self.assertEqual(result.force_field, "PCFF") - self.assertFalse(result.loop) - self.assertIsNone(result.max_loop_count) - self.assertEqual(result.temperature, [300.0, 350.0]) - self.assertEqual(result.density, [0.8, 0.95]) - self.assertEqual(len(result.monomers), 2) - self.assertEqual(len(result.simulations), 2) - self.assertEqual( - result.monomers[0].count, - { - "small": 2, - "large": 20, - }, - ) - - def test_validate_inputs_builds_ratio_setup(self) -> None: - inputs = self.ratio_input() - - result = self.parser.validate_inputs(inputs) - - self.assertIsInstance(result, SimulationSetup) - self.assertEqual(result.simulation_name, "ratio_example") - self.assertEqual(result.composition_method, "ratio") - self.assertEqual(result.force_field, "PCFF-IFF") - self.assertTrue(result.loop) - self.assertEqual( - [simulation.total_atoms for simulation in result.simulations], - [1000, 10000], - ) - self.assertEqual(result.monomers[0].ratio, 2.0) - self.assertIsNone(result.monomers[0].count) - - @patch("AutoREACTER.input_parser.time.sleep") - def test_validate_inputs_stores_integer_loop_limit( - self, - sleep_mock, - ) -> None: - inputs = self.counts_input() - inputs["loop"] = 10 # Triggers the warning and the sleep(5) - - result = self.parser.validate_inputs(inputs) - - self.assertTrue(result.loop) - self.assertEqual(result.max_loop_count, 10) # Matches the new input - sleep_mock.assert_called_once_with(5) - - def test_validate_inputs_assigns_default_monomer_name(self) -> None: - inputs = { - "simulation_name": "default_name", - "simulations": [ - { - "tag": "a", - "temperature": 300, - "density": 0.8, - "monomer_counts": { - "data_1": 1, - }, - } - ], - "monomers": [ - { - "smiles": "CCO", - } - ], - } - - result = self.parser.validate_inputs(inputs) - - self.assertEqual(result.monomers[0].name, "data_1") - self.assertEqual(result.monomers[0].data_id, "data_1") - - def test_validate_inputs_rejects_unknown_system_monomer(self) -> None: - inputs = self.counts_input() - inputs["simulations"][0]["monomer_counts"]["unknown"] = 1 - - with self.assertRaises(InputSchemaError): - self.parser.validate_inputs(inputs) - - def test_validate_inputs_rejects_missing_system_monomer(self) -> None: - inputs = self.counts_input() - inputs["simulations"][0]["monomer_counts"].pop("water") - - with self.assertRaises(InputSchemaError): - self.parser.validate_inputs(inputs) - - def test_validate_inputs_rejects_canonically_duplicate_smiles(self) -> None: - inputs = { - "simulation_name": "duplicates", - "simulations": [ - { - "tag": "a", - "temperature": 300, - "density": 0.8, - "monomer_counts": { - "ethanol_a": 1, - "ethanol_b": 1, - }, - } - ], - "monomers": [ - { - "name": "ethanol_a", - "smiles": "CCO", - }, - { - "name": "ethanol_b", - "smiles": "C(C)O", - }, - ], - } - - with self.assertRaises(DuplicateMonomerError): - self.parser.validate_inputs(inputs) - - -class TestMoleculeRepresentation(InputParserTestCase): - """Tests for initial-molecule extraction and image-grid integration.""" - - def test_molecule_representation_returns_molecules_and_legends(self) -> None: - setup = self.parser.validate_inputs(self.counts_input()) - - molecules, legends = ( - self.parser.molecule_representation_of_initial_molecules(setup) - ) - - self.assertEqual(len(molecules), 2) - self.assertTrue(all(isinstance(mol, Chem.Mol) for mol in molecules)) - self.assertEqual(legends, ["ethanol", "water"]) - - @patch("AutoREACTER.input_parser.Draw.MolsToGridImage") - def test_initial_molecules_image_grid_delegates_to_rdkit( - self, - grid_mock, - ) -> None: - setup = self.parser.validate_inputs(self.counts_input()) - - class DummySession: - inputs = setup - - expected_image = object() - grid_mock.return_value = expected_image - - result = self.parser.initial_molecules_image_grid(DummySession()) - - self.assertIs(result, expected_image) - grid_mock.assert_called_once() - - args, kwargs = grid_mock.call_args - self.assertEqual(len(args[0]), 2) - self.assertEqual(kwargs["molsPerRow"], 3) - self.assertEqual(kwargs["subImgSize"], (400, 400)) - self.assertEqual(kwargs["legends"], ["ethanol", "water"]) - - -if __name__ == "__main__": - unittest.main(verbosity=2) \ No newline at end of file diff --git a/tests/test_lunar_api_wrapper.py b/tests/test_lunar_api_wrapper.py deleted file mode 100644 index 20d938f4..00000000 --- a/tests/test_lunar_api_wrapper.py +++ /dev/null @@ -1,96 +0,0 @@ -""" -Lightweight tests for lunar_api_wrapper.py. - -Store this file at: - tests/test_lunar_api_wrapper.py - -These tests intentionally avoid running LUNAR itself. They test the wrapper's -path handling and merge_input.txt generation logic. -""" - -from pathlib import Path - -import pytest - -from AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_executor import All2LMPResult -from AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_utils import ( - get_ending_integer, - normalize_path, -) -from AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.merge_builder import write_bond_react_merge_input - - -def test_get_ending_integer(tmp_path): - assert get_ending_integer("pre12") == 12 - assert get_ending_integer("post3") == 3 - assert get_ending_integer("data") is None - - -def test_normalize_windows_path_inside_wsl(tmp_path, monkeypatch): - monkeypatch.setattr( - "AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_utils.is_wsl", - lambda: True, - ) - normalized = normalize_path(r"C:\Users\janit\Documents\file.data") - - assert normalized == "/mnt/c/Users/janit/Documents/file.data" - - -def test_write_bond_react_merge_input(tmp_path, monkeypatch): - cache_all2lmp = tmp_path / "lunar" / "all2lmp" - cache_bond_react_merge = tmp_path / "lunar" / "bond_react_merge" - cache_all2lmp.mkdir(parents=True) - cache_bond_react_merge.mkdir(parents=True) - - # Keep paths deterministic for this unit test. - monkeypatch.setattr( - "AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.merge_builder.normalize_path", - lambda p: str(p), - ) - - monomer = Path("BisphenolA_typed_IFF.data") - pre = Path("pre1_typed_IFF.data") - post = Path("post1_typed_IFF.data") - - results = [ - All2LMPResult(id="BisphenolA", molecule=True, all2lmp_data_file=monomer), - All2LMPResult(id="pre1", molecule=False, all2lmp_data_file=pre), - All2LMPResult(id="post1", molecule=False, all2lmp_data_file=post), - ] - - merge_file = write_bond_react_merge_input( - cache_bond_react_merge=cache_bond_react_merge, - cache_all2lmp=cache_all2lmp, - all2lmp_results=results, - ) - text = merge_file.read_text(encoding="utf-8") - - assert merge_file.name == "merge_input.txt" - assert "data1" in text - assert "pre1" in text - assert "post1" in text - assert str(cache_all2lmp / monomer) in text - assert str(cache_all2lmp / pre) in text - assert str(cache_all2lmp / post) in text - - -def test_write_bond_react_merge_input_rejects_missing_post(tmp_path): - cache_all2lmp = tmp_path / "lunar" / "all2lmp" - cache_bond_react_merge = tmp_path / "lunar" / "bond_react_merge" - cache_all2lmp.mkdir(parents=True) - cache_bond_react_merge.mkdir(parents=True) - - results = [ - All2LMPResult( - id="pre1", - molecule=False, - all2lmp_data_file=Path("pre1_typed_IFF.data"), - ), - ] - - with pytest.raises(ValueError, match="Incomplete reaction pair"): - write_bond_react_merge_input( - cache_bond_react_merge=cache_bond_react_merge, - cache_all2lmp=cache_all2lmp, - all2lmp_results=results, - ) From f17df4c6ea853b893f07a1fbeb607890e089500f Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:01:21 -0400 Subject: [PATCH 140/176] Add unit tests and refactor input_parser.py Add comprehensive unit test suite for InputParser covering exception hierarchy, dataclasses, validation methods, and end-to-end flows. Also refactor input_parser.py: fix whitespace/formatting, normalize 'compass' alias to 'Compass', add simulation_name and monomers validation in validate_basic_format, and minor style cleanup. --- AutoREACTER/input_parser.py | 513 ++++++-- tests/unit/test_input_parser.py | 2040 +++++++++++++++++++++++++++++++ 2 files changed, 2462 insertions(+), 91 deletions(-) create mode 100644 tests/unit/test_input_parser.py diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 1197bb80..56b06705 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -40,9 +40,11 @@ class SmilesValidationError(InputError): class DuplicateMonomerError(InputError): """Raised when duplicate monomer definitions are detected.""" + class CompatibilityError(InputError): """Raised when input combinations are incompatible with the current workflow.""" + # Type aliases for clarity and validation. CompositionMethodType = Literal["counts", "ratio"] ForceFieldType = Literal[ @@ -168,11 +170,11 @@ class SimulationSetup: number_of_total_atoms: list[int] | None = None box_estimates: float | None = None deep_search: bool = True - loop : bool = True - reaction_iteration_depth: int = 5 - wildcards: bool = True - deduplicate_reaction_templates: bool = True - write_second_reaction_stage: bool = True + loop: bool = True + reaction_iteration_depth: int = 5 + wildcards: bool = True + deduplicate_reaction_templates: bool = True + write_second_reaction_stage: bool = True class InputParser: @@ -197,7 +199,7 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: self.validate_basic_format(inputs) simulation_name = inputs["simulation_name"] - simulations_list = inputs["simulations"] + simulations_list = inputs["simulations"] composition_method = self._get_inputs_mode(simulations_list) validated_simulations = self._validate_simulations( @@ -278,6 +280,7 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: "stage_2", ], ) + return SimulationSetup( simulation_name=simulation_name, temperature=validated_simulations["temperatures"], @@ -364,7 +367,26 @@ def validate_basic_format(self, inputs: dict) -> None: raise InputSchemaError( f"Missing required key: {key!r} in inputs dictionary." ) - + + simulation_name = inputs["simulation_name"] + if not isinstance(simulation_name, str) or not simulation_name.strip(): + raise InputSchemaError( + "'simulation_name' must be a non-empty string. " + f"Got: {simulation_name!r}" + ) + + monomers = inputs["monomers"] + + if not isinstance(monomers, list): + raise InputSchemaError( + "'monomers' must be a list." + ) + + for monomer in monomers: + if not isinstance(monomer, dict): + raise InputSchemaError( + f"Each monomer entry must be a dictionary. Got: {monomer!r}" + ) def _get_inputs_mode(self, simulations_list: list) -> CompositionMethodType: """ @@ -432,7 +454,9 @@ def _validate_temperature(self, temp: Any) -> float: NumericFieldError: If the value is not a positive number. """ if isinstance(temp, bool) or not isinstance(temp, (int, float)): - raise NumericFieldError(f"'temperature' must be a number. Got: {temp!r}") + raise NumericFieldError( + f"'temperature' must be a number. Got: {temp!r}" + ) if temp <= 0: raise NumericFieldError( @@ -467,11 +491,11 @@ def _validate_density(self, density: Any) -> float: ) return density_value - + _FF_ALIASES: dict[str, ForceFieldType] = { "pcff-iff": "PCFF-IFF", "pcff": "PCFF", - "compass": "compass", + "compass": "Compass", "cvff-iff": "CVFF-IFF", "cvff": "CVFF", "clay-ff": "Clay-FF", @@ -484,7 +508,6 @@ def _validate_density(self, density: Any) -> float: "gaff": "GAFF", } - def _validate_force_field(self, force_field: Any) -> ForceFieldType: """ Validates and normalizes the force field input. @@ -500,9 +523,13 @@ def _validate_force_field(self, force_field: Any) -> ForceFieldType: normalized_input = force_field.strip().lower() if normalized_input not in self._FF_ALIASES: - raise InputSchemaError(f"Unsupported force field: {force_field!r}") + raise InputSchemaError( + f"Unsupported force field: {force_field!r}" + ) - canonical_force_field = self._FF_ALIASES[normalized_input] + canonical_force_field = self._FF_ALIASES[ + normalized_input + ] if canonical_force_field in ["OPLSAA", "GAFF"]: raise CompatibilityError( @@ -561,7 +588,11 @@ def _validate_composition( if method == "ratio": total_atoms = target.get("total_atoms") - if isinstance(total_atoms, bool) or not isinstance(total_atoms, int) or total_atoms <= 0: + if ( + isinstance(total_atoms, bool) + or not isinstance(total_atoms, int) + or total_atoms <= 0 + ): raise NumericFieldError( f"'total_atoms' must be a positive integer for ratio mode. Got: {total_atoms!r}" ) @@ -594,6 +625,11 @@ def _validate_system_monomer_keys( allowed_names: set[str] = set() for monomer_id, monomer in enumerate(monomers, start=1): + if not isinstance(monomer, dict): + raise InputSchemaError( + f"Each monomer entry must be a dictionary. Got: {monomer!r}" + ) + name = monomer.get("name") if not isinstance(name, str) or not name.strip(): @@ -602,11 +638,17 @@ def _validate_system_monomer_keys( allowed_names.add(name) - field_name = "monomer_counts" if method == "counts" else "monomer_ratios" + field_name = ( + "monomer_counts" + if method == "counts" + else "monomer_ratios" + ) for system in systems: tag = system["tag"] - provided_names = set(system.get(field_name, {}).keys()) + provided_names = set( + system.get(field_name, {}).keys() + ) extra = provided_names - allowed_names missing = allowed_names - provided_names @@ -643,9 +685,14 @@ def _validate_monomer_entry( monomers = inputs.get("monomers") if not isinstance(monomers, list): - raise InputSchemaError("'monomers' must be a list.") + raise InputSchemaError( + "'monomers' must be a list." + ) - for monomer_id, monomer_dict in enumerate(monomers, start=1): + for monomer_id, monomer_dict in enumerate( + monomers, + start=1, + ): if not isinstance(monomer_dict, dict): raise InputSchemaError( f"Each monomer entry must be a dictionary. Got: {monomer_dict!r}" @@ -656,17 +703,31 @@ def _validate_monomer_entry( name = f"data_{monomer_id}" smiles_raw = monomer_dict.get("smiles") - smiles, mol = self._validate_smiles(smiles_raw) - seen_smiles = self.validate_no_duplicate_smiles(smiles, seen_smiles) + smiles, mol = self._validate_smiles( + smiles_raw + ) - num_atoms, molecular_weight = self._derive_molecule_properties(mol) + seen_smiles = ( + self.validate_no_duplicate_smiles( + smiles, + seen_smiles, + ) + ) + + num_atoms, molecular_weight = ( + self._derive_molecule_properties( + mol + ) + ) if method == "counts": count_map: dict[str, int] = {} for system in systems: tag = system["tag"] - monomer_counts = system["monomer_counts"] + monomer_counts = system[ + "monomer_counts" + ] if name not in monomer_counts: raise InputSchemaError( @@ -674,7 +735,12 @@ def _validate_monomer_entry( ) value = monomer_counts[name] - if isinstance(value, bool) or not isinstance(value, int) or value < 0: + + if ( + isinstance(value, bool) + or not isinstance(value, int) + or value < 0 + ): raise NumericFieldError( f"Invalid count for monomer {name!r} in system '{tag}'." ) @@ -686,7 +752,9 @@ def _validate_monomer_entry( else: first_system = systems[0] - ratios = first_system["monomer_ratios"] + ratios = first_system[ + "monomer_ratios" + ] if name not in ratios: raise InputSchemaError( @@ -695,7 +763,14 @@ def _validate_monomer_entry( ratio_value = ratios[name] - if isinstance(ratio_value, bool) or not isinstance(ratio_value, (int, float)) or ratio_value < 0: + if ( + isinstance(ratio_value, bool) + or not isinstance( + ratio_value, + (int, float), + ) + or ratio_value < 0 + ): raise NumericFieldError( f"Invalid ratio for monomer {name!r}." ) @@ -719,7 +794,10 @@ def _validate_monomer_entry( return validated_monomers - def _derive_molecule_properties(self, mol: Chem.Mol) -> tuple[int, float]: + def _derive_molecule_properties( + self, + mol: Chem.Mol, + ) -> tuple[int, float]: """ Derives simple molecule properties from an RDKit Mol object. @@ -730,8 +808,14 @@ def _derive_molecule_properties(self, mol: Chem.Mol) -> tuple[int, float]: Tuple of number of atoms with hydrogens included and molecular weight. """ mol_with_h = Chem.AddHs(mol) - num_atoms = int(mol_with_h.GetNumAtoms()) - molecular_weight = float(Descriptors.MolWt(mol)) + num_atoms = int( + mol_with_h.GetNumAtoms() + ) + + molecular_weight = float( + Descriptors.MolWt(mol) + ) + return num_atoms, molecular_weight def _int_to_dict(self, integer: int) -> dict: @@ -744,7 +828,10 @@ def _int_to_dict(self, integer: int) -> dict: """ return {"_": integer} - def _validate_smiles(self, smiles: Any) -> tuple[str, Chem.Mol]: + def _validate_smiles( + self, + smiles: Any, + ) -> tuple[str, Chem.Mol]: """ Validates a SMILES string through RDKit and canonicalizes it. @@ -757,23 +844,35 @@ def _validate_smiles(self, smiles: Any) -> tuple[str, Chem.Mol]: Raises: SmilesValidationError: If RDKit cannot parse the string. """ - if not isinstance(smiles, str) or not smiles.strip(): + if ( + not isinstance(smiles, str) + or not smiles.strip() + ): raise SmilesValidationError( f"SMILES must be a non-empty string. Got: {smiles!r}" ) smiles_clean = smiles.strip() - mol = Chem.MolFromSmiles(smiles_clean) + mol = Chem.MolFromSmiles( + smiles_clean + ) if mol is None: raise SmilesValidationError( f"Invalid SMILES string: {smiles!r}. RDKit failed to parse it." ) - canonical_smiles = Chem.MolToSmiles(mol, canonical=True) + canonical_smiles = Chem.MolToSmiles( + mol, + canonical=True, + ) + return canonical_smiles, mol - def _validate_numeric_fields(self, inputs: dict) -> None: + def _validate_numeric_fields( + self, + inputs: dict, + ) -> None: """ Legacy numeric validation helper. @@ -781,33 +880,74 @@ def _validate_numeric_fields(self, inputs: dict) -> None: This method is kept for compatibility with older input schemas and is not currently used in the main validate_inputs flow. """ - density = inputs.get("density", None) - if isinstance(density, bool) or not isinstance(density, (int, float)) or density <= 0: + density = inputs.get( + "density", + None, + ) + + if ( + isinstance(density, bool) + or not isinstance( + density, + (int, float), + ) + or density <= 0 + ): raise NumericFieldError( f"'density' must be a positive number. Got: {density!r}" ) - temps = inputs.get("temperature", None) + temps = inputs.get( + "temperature", + None, + ) + if temps is None: raise NumericFieldError( "'temperature' is required as a number or list of numbers." ) - temps_list = temps if isinstance(temps, list) else [temps] + temps_list = ( + temps + if isinstance(temps, list) + else [temps] + ) + for temp in temps_list: - if isinstance(temp, bool) or not isinstance(temp, (int, float)) or temp <= 0: + if ( + isinstance(temp, bool) + or not isinstance( + temp, + (int, float), + ) + or temp <= 0 + ): raise NumericFieldError( f"Temperature values must be positive numbers. Got: {temp!r}" ) - num_monomers = inputs.get("number_of_monomers", None) - if not isinstance(num_monomers, dict) or not num_monomers: + num_monomers = inputs.get( + "number_of_monomers", + None, + ) + + if ( + not isinstance( + num_monomers, + dict, + ) + or not num_monomers + ): raise NumericFieldError( "'number_of_monomers' must be a non-empty dict of monomer_id -> positive int." ) for monomer_id, count in num_monomers.items(): - if isinstance(count, bool) or not isinstance(count, int) or count <= 0: + if ( + isinstance(count, bool) + or not isinstance(count, int) + or count <= 0 + ): raise NumericFieldError( f"Monomer count for {monomer_id!r} must be a positive integer. Got: {count!r}" ) @@ -833,7 +973,10 @@ def validate_no_duplicate_smiles( "Each monomer must have a unique SMILES string." ) - seen_monomer_list.append(current_monomer) + seen_monomer_list.append( + current_monomer + ) + return seen_monomer_list def _validate_single_simulation( @@ -844,46 +987,106 @@ def _validate_single_simulation( """ Validates one Simulation object after initial construction. """ - if not isinstance(simulation.tag, str) or not simulation.tag.strip(): + if ( + not isinstance(simulation.tag, str) + or not simulation.tag.strip() + ): raise InputSchemaError( "Each system must include a non-empty 'tag'." ) - if isinstance(simulation.temperature, bool) or not isinstance(simulation.temperature, (int, float)) or simulation.temperature <= 0: + if ( + isinstance( + simulation.temperature, + bool, + ) + or not isinstance( + simulation.temperature, + (int, float), + ) + or simulation.temperature <= 0 + ): raise NumericFieldError( f"Simulation '{simulation.tag}' has invalid temperature." ) - if isinstance(simulation.density, bool) or not isinstance(simulation.density, (int, float)) or simulation.density <= 0: + if ( + isinstance( + simulation.density, + bool, + ) + or not isinstance( + simulation.density, + (int, float), + ) + or simulation.density <= 0 + ): raise NumericFieldError( f"Simulation '{simulation.tag}' has invalid density." ) if method == "counts": - if not isinstance(simulation.monomer_counts, dict) or not simulation.monomer_counts: + if ( + not isinstance( + simulation.monomer_counts, + dict, + ) + or not simulation.monomer_counts + ): raise InputSchemaError( "'monomer_counts' must be provided in counts mode." ) - for monomer, value in simulation.monomer_counts.items(): - if isinstance(value, bool) or not isinstance(value, int) or value < 0: + for monomer, value in ( + simulation.monomer_counts.items() + ): + if ( + isinstance(value, bool) + or not isinstance(value, int) + or value < 0 + ): raise NumericFieldError( f"Invalid count for monomer {monomer!r}: {value!r}" ) elif method == "ratio": - if isinstance(simulation.total_atoms, bool) or not isinstance(simulation.total_atoms, int) or simulation.total_atoms <= 0: + if ( + isinstance( + simulation.total_atoms, + bool, + ) + or not isinstance( + simulation.total_atoms, + int, + ) + or simulation.total_atoms <= 0 + ): raise NumericFieldError( "'total_atoms' must be a positive integer in ratio mode." ) - if not isinstance(simulation.monomer_ratios, dict) or not simulation.monomer_ratios: + if ( + not isinstance( + simulation.monomer_ratios, + dict, + ) + or not simulation.monomer_ratios + ): raise InputSchemaError( "'monomer_ratios' must be provided in ratio mode." ) - for monomer, value in simulation.monomer_ratios.items(): - if isinstance(value, bool) or not isinstance(value, (int, float)) or value < 0: + for monomer, value in ( + simulation.monomer_ratios.items() + ): + if ( + isinstance(value, bool) + or not isinstance( + value, + (int, float), + ) + or value < 0 + ): raise NumericFieldError( f"Invalid ratio value for monomer {monomer!r}: {value!r}" ) @@ -922,7 +1125,10 @@ def _validate_simulations( tag = system.get("tag") - if not isinstance(tag, str) or not tag.strip(): + if ( + not isinstance(tag, str) + or not tag.strip() + ): raise InputSchemaError( "Each system must include a non-empty 'tag'." ) @@ -934,39 +1140,71 @@ def _validate_simulations( seen_tags.add(tag) - system["temperature"] = self._validate_temperature( - system.get("temperature") + system["temperature"] = ( + self._validate_temperature( + system.get("temperature") + ) ) - system["density"] = self._validate_density( - system.get("density") + + system["density"] = ( + self._validate_density( + system.get("density") + ) ) - temperatures.append(system["temperature"]) - density.append(system["density"]) + temperatures.append( + system["temperature"] + ) + + density.append( + system["density"] + ) if method == "ratio": - total_atoms = system.get("total_atoms") + total_atoms = system.get( + "total_atoms" + ) - if isinstance(total_atoms, bool) or not isinstance(total_atoms, int) or total_atoms <= 0: + if ( + isinstance(total_atoms, bool) + or not isinstance( + total_atoms, + int, + ) + or total_atoms <= 0 + ): raise NumericFieldError( "'total_atoms' must be a positive integer in ratio mode." ) - ratios = system.get("monomer_ratios") + ratios = system.get( + "monomer_ratios" + ) - if not isinstance(ratios, dict) or not ratios: + if ( + not isinstance(ratios, dict) + or not ratios + ): raise InputSchemaError( "'monomer_ratios' must be provided in ratio mode." ) for monomer, value in ratios.items(): - if isinstance(value, bool) or not isinstance(value, (int, float)) or value < 0: + if ( + isinstance(value, bool) + or not isinstance( + value, + (int, float), + ) + or value < 0 + ): raise NumericFieldError( f"Invalid ratio value for monomer {monomer!r}: {value!r}" ) if reference_ratios is None: reference_ratios = ratios + elif ratios != reference_ratios: raise InputSchemaError( "All systems must use identical 'monomer_ratios'." @@ -974,26 +1212,46 @@ def _validate_simulations( simulation = Simulation( tag=system["tag"], - temperature=system["temperature"], + temperature=system[ + "temperature" + ], density=system["density"], monomer_counts=None, monomer_ratios=ratios, total_atoms=total_atoms, ) - self._validate_single_simulation(simulation, method) - simulations.append(simulation) + self._validate_single_simulation( + simulation, + method, + ) + + simulations.append( + simulation + ) elif method == "counts": - counts = system.get("monomer_counts") + counts = system.get( + "monomer_counts" + ) - if not isinstance(counts, dict) or not counts: + if ( + not isinstance(counts, dict) + or not counts + ): raise InputSchemaError( "'monomer_counts' must be provided in counts mode." ) for monomer, value in counts.items(): - if isinstance(value, bool) or not isinstance(value, int) or value < 0: + if ( + isinstance(value, bool) + or not isinstance( + value, + int, + ) + or value < 0 + ): raise NumericFieldError( f"Invalid count for monomer {monomer!r}: {value!r}" ) @@ -1005,15 +1263,23 @@ def _validate_simulations( simulation = Simulation( tag=system["tag"], - temperature=system["temperature"], + temperature=system[ + "temperature" + ], density=system["density"], monomer_counts=counts, monomer_ratios=None, total_atoms=None, ) - self._validate_single_simulation(simulation, method) - simulations.append(simulation) + self._validate_single_simulation( + simulation, + method, + ) + + simulations.append( + simulation + ) return { "method": method, @@ -1022,7 +1288,7 @@ def _validate_simulations( "systems": systems, "simulations": simulations, } - + def _validate_loop( self, inputs: dict, @@ -1032,8 +1298,10 @@ def _validate_loop( New logic is handled by _validate_reaction_iteration_depth. """ - reaction_iteration_depth = self._validate_reaction_iteration_depth( - inputs + reaction_iteration_depth = ( + self._validate_reaction_iteration_depth( + inputs + ) ) if reaction_iteration_depth == 0: @@ -1041,14 +1309,23 @@ def _validate_loop( return True, reaction_iteration_depth - def _normalized_option_key(self, key: str) -> str: + def _normalized_option_key( + self, + key: str, + ) -> str: """ Normalize workflow option keys so common spellings are accepted. This is intentionally used only for optional workflow switches, not for the core input schema. """ - return key.strip().lower().replace("_", "").replace("-", "").replace(" ", "") + return ( + key.strip() + .lower() + .replace("_", "") + .replace("-", "") + .replace(" ", "") + ) def _get_workflow_option( self, @@ -1065,21 +1342,39 @@ def _get_workflow_option( input is rejected. """ aliases = aliases or [] - accepted_keys = [key, *aliases] + accepted_keys = [ + key, + *aliases, + ] + accepted_normalized = { - self._normalized_option_key(option_key) + self._normalized_option_key( + option_key + ) for option_key in accepted_keys } matches = [] + for input_key, value in inputs.items(): - if self._normalized_option_key(str(input_key)) in accepted_normalized: - matches.append((input_key, value)) + if ( + self._normalized_option_key( + str(input_key) + ) + in accepted_normalized + ): + matches.append( + ( + input_key, + value, + ) + ) if not matches: return default first_value = matches[0][1] + for input_key, value in matches[1:]: if value != first_value: raise InputConflictError( @@ -1113,10 +1408,26 @@ def _validate_bool_option( return value if isinstance(value, str): - normalized_value = value.strip().lower() - if normalized_value in {"true", "yes", "y", "on", "1"}: + normalized_value = ( + value.strip().lower() + ) + + if normalized_value in { + "true", + "yes", + "y", + "on", + "1", + }: return True - if normalized_value in {"false", "no", "n", "off", "0"}: + + if normalized_value in { + "false", + "no", + "n", + "off", + "0", + }: return False raise InputSchemaError( @@ -1166,16 +1477,33 @@ def _validate_reaction_iteration_depth( return 5 if value else 0 if isinstance(value, str): - normalized_value = value.strip().lower() + normalized_value = ( + value.strip().lower() + ) - if normalized_value in {"false", "no", "n", "off", "0", "none"}: + if normalized_value in { + "false", + "no", + "n", + "off", + "0", + "none", + }: return 0 - if normalized_value in {"true", "yes", "y", "on"}: + if normalized_value in { + "true", + "yes", + "y", + "on", + }: return 5 try: - value = int(normalized_value) + value = int( + normalized_value + ) + except ValueError as error: raise InputSchemaError( "'reaction_iteration_depth' must be an integer greater " @@ -1183,7 +1511,10 @@ def _validate_reaction_iteration_depth( f"Got: {value!r}" ) from error - if isinstance(value, bool) or not isinstance(value, int): + if ( + isinstance(value, bool) + or not isinstance(value, int) + ): raise InputSchemaError( "'reaction_iteration_depth' must be an integer greater " f"than or equal to 0, or a boolean value. Got: {value!r}" @@ -1337,4 +1668,4 @@ def _validate_reaction_iteration_depth( print(parser.validate_inputs(inputs_ratio)) print("\nValidating Force Field Input:") - print(parser.validate_inputs(input_ff)) + print(parser.validate_inputs(input_ff)) \ No newline at end of file diff --git a/tests/unit/test_input_parser.py b/tests/unit/test_input_parser.py new file mode 100644 index 00000000..afd2fea4 --- /dev/null +++ b/tests/unit/test_input_parser.py @@ -0,0 +1,2040 @@ +import math +from types import SimpleNamespace + +import pytest +from rdkit import Chem + +from AutoREACTER.input_parser import ( + CompatibilityError, + DuplicateMonomerError, + InputConflictError, + InputError, + InputParser, + InputSchemaError, + MonomerEntry, + NumericFieldError, + Simulation, + SimulationSetup, + SmilesValidationError, +) + + +# ============================================================================= +# Fixtures / helpers +# ============================================================================= + + +@pytest.fixture +def parser(): + return InputParser() + + +def make_counts_input(): + return { + "simulation_name": "counts_demo", + "simulations": [ + { + "tag": "small", + "temperature": 300, + "density": 0.8, + "monomer_counts": { + "ethanol": 10, + "ethylamine": 20, + }, + }, + { + "tag": "large", + "temperature": 400, + "density": 1.0, + "monomer_counts": { + "ethanol": 100, + "ethylamine": 200, + }, + }, + ], + "monomers": [ + { + "name": "ethanol", + "smiles": "CCO", + }, + { + "name": "ethylamine", + "smiles": "CCN", + }, + ], + } + + +def make_ratio_input(): + return { + "simulation_name": "ratio_demo", + "simulations": [ + { + "tag": "small", + "temperature": 300, + "density": 0.8, + "total_atoms": 10000, + "monomer_ratios": { + "ethanol": 1.0, + "ethylamine": 2.0, + }, + }, + { + "tag": "large", + "temperature": 400, + "density": 1.0, + "total_atoms": 100000, + "monomer_ratios": { + "ethanol": 1.0, + "ethylamine": 2.0, + }, + }, + ], + "monomers": [ + { + "name": "ethanol", + "smiles": "CCO", + }, + { + "name": "ethylamine", + "smiles": "CCN", + }, + ], + } + + +# ============================================================================= +# Exception hierarchy +# ============================================================================= + + +@pytest.mark.parametrize( + "exception_class", + [ + InputSchemaError, + InputConflictError, + NumericFieldError, + SmilesValidationError, + DuplicateMonomerError, + CompatibilityError, + ], +) +def test_input_exceptions_inherit_from_input_error( + exception_class, +): + assert issubclass( + exception_class, + InputError, + ) + + +# ============================================================================= +# Dataclasses +# ============================================================================= + + +def test_monomer_entry_defaults(): + monomer = MonomerEntry( + id=1, + data_id="data_1", + name="ethanol", + smiles="CCO", + count={"sim": 10}, + ratio=None, + ) + + assert monomer.rdkit_mol is None + assert monomer.molecule_3Dmol_path is None + assert monomer.lmp_molecule_file is None + assert monomer.num_atoms is None + assert monomer.molecular_weight is None + assert monomer.status is True + + +def test_monomer_entry_uses_slots(): + monomer = MonomerEntry( + id=1, + data_id="data_1", + name="ethanol", + smiles="CCO", + count={"sim": 10}, + ratio=None, + ) + + with pytest.raises(AttributeError): + monomer.random_attribute = 10 + + +def test_simulation_defaults(): + simulation = Simulation( + tag="sim", + temperature=300.0, + density=1.0, + ) + + assert simulation.monomer_counts is None + assert simulation.monomer_ratios is None + assert simulation.total_atoms is None + assert simulation.initial_box_volume is None + assert simulation.initial_box_length is None + + +def test_simulation_setup_workflow_defaults(): + setup = SimulationSetup( + simulation_name="demo", + temperature=[300.0], + density=[1.0], + force_field="PCFF", + monomers=[], + ) + + assert setup.deep_search is True + assert setup.loop is True + assert setup.reaction_iteration_depth == 5 + assert setup.wildcards is True + + assert ( + setup.deduplicate_reaction_templates + is True + ) + + assert ( + setup.write_second_reaction_stage + is True + ) + + +# ============================================================================= +# validate_basic_format +# ============================================================================= + + +def test_validate_basic_format_accepts_required_keys( + parser, +): + parser.validate_basic_format( + { + "simulation_name": "demo", + "simulations": [], + "monomers": [], + } + ) + + +@pytest.mark.parametrize( + "value", + [ + None, + [], + "string", + 123, + ], +) +def test_validate_basic_format_requires_dictionary( + parser, + value, +): + with pytest.raises( + InputSchemaError, + match="Expected input to be a dictionary", + ): + parser.validate_basic_format(value) + + +@pytest.mark.parametrize( + "missing_key", + [ + "simulation_name", + "simulations", + "monomers", + ], +) +def test_validate_basic_format_requires_each_core_key( + parser, + missing_key, +): + data = { + "simulation_name": "demo", + "simulations": [], + "monomers": [], + } + + del data[missing_key] + + with pytest.raises( + InputSchemaError, + match="Missing required key", + ): + parser.validate_basic_format(data) + + +# ============================================================================= +# Composition-mode detection +# ============================================================================= + + +def test_get_inputs_mode_detects_counts(parser): + simulations = [ + { + "monomer_counts": { + "a": 1, + } + } + ] + + assert ( + parser._get_inputs_mode(simulations) + == "counts" + ) + + +def test_get_inputs_mode_detects_ratio(parser): + simulations = [ + { + "monomer_ratios": { + "a": 1.0, + } + } + ] + + assert ( + parser._get_inputs_mode(simulations) + == "ratio" + ) + + +@pytest.mark.parametrize( + "simulations", + [ + [], + None, + {}, + "bad", + ], +) +def test_get_inputs_mode_requires_nonempty_list( + parser, + simulations, +): + with pytest.raises(InputSchemaError): + parser._get_inputs_mode(simulations) + + +def test_get_inputs_mode_requires_dict_entries( + parser, +): + with pytest.raises(InputSchemaError): + parser._get_inputs_mode( + ["not a dictionary"] + ) + + +def test_get_inputs_mode_rejects_counts_and_ratios_together( + parser, +): + with pytest.raises( + InputConflictError, + match="not both", + ): + parser._get_inputs_mode( + [ + { + "monomer_counts": { + "a": 1, + }, + "monomer_ratios": { + "a": 1.0, + }, + } + ] + ) + + +def test_get_inputs_mode_rejects_missing_composition( + parser, +): + with pytest.raises(InputSchemaError): + parser._get_inputs_mode( + [ + { + "tag": "sim", + } + ] + ) + + +def test_get_inputs_mode_rejects_mixed_modes( + parser, +): + with pytest.raises( + InputConflictError, + match="same composition method", + ): + parser._get_inputs_mode( + [ + { + "monomer_counts": { + "a": 1, + } + }, + { + "monomer_ratios": { + "a": 1.0, + } + }, + ] + ) + + +# ============================================================================= +# Temperature / density validation +# ============================================================================= + + +@pytest.mark.parametrize( + "value, expected", + [ + (1, 1.0), + (300, 300.0), + (298.15, 298.15), + ], +) +def test_validate_temperature_accepts_positive_numbers( + parser, + value, + expected, +): + assert ( + parser._validate_temperature(value) + == expected + ) + + +@pytest.mark.parametrize( + "value", + [ + 0, + -1, + -300.0, + True, + False, + "300", + None, + ], +) +def test_validate_temperature_rejects_invalid_values( + parser, + value, +): + with pytest.raises(NumericFieldError): + parser._validate_temperature(value) + + +@pytest.mark.parametrize( + "value, expected", + [ + (1, 1.0), + (0.8, 0.8), + (1.25, 1.25), + ], +) +def test_validate_density_accepts_positive_numbers( + parser, + value, + expected, +): + assert parser._validate_density(value) == expected + + +@pytest.mark.parametrize( + "value", + [ + 0, + -1, + True, + False, + "0.8", + None, + ], +) +def test_validate_density_rejects_invalid_values( + parser, + value, +): + with pytest.raises(NumericFieldError): + parser._validate_density(value) + + +# ============================================================================= +# Force-field validation +# ============================================================================= + + +def test_force_field_defaults_to_pcff(parser): + assert ( + parser._validate_force_field(None) + == "PCFF" + ) + + +@pytest.mark.parametrize( + "raw, expected", + [ + ("PCFF", "PCFF"), + ("pcff", "PCFF"), + ("PCFF-IFF", "PCFF-IFF"), + ("pcff-iff", "PCFF-IFF"), + ("CVFF", "CVFF"), + ("cvff", "CVFF"), + ("CVFF-IFF", "CVFF-IFF"), + ("clayff", "Clay-FF"), + ("Clay-FF", "Clay-FF"), + ("dreiding", "DREIDING"), + ("drieding", "DREIDING"), + ], +) +def test_force_field_aliases_are_normalized( + parser, + raw, + expected, +): + assert ( + parser._validate_force_field(raw) + == expected + ) + + +def test_compass_normalizes_to_declared_canonical_name( + parser, +): + """ + ForceFieldType declares the canonical spelling as 'Compass'. + + This test intentionally checks that the runtime normalizer agrees + with that public contract. + """ + assert ( + parser._validate_force_field("compass") + == "Compass" + ) + + +@pytest.mark.parametrize( + "raw", + [ + "", + " ", + 123, + [], + {}, + ], +) +def test_force_field_rejects_invalid_schema( + parser, + raw, +): + with pytest.raises(InputSchemaError): + parser._validate_force_field(raw) + + +def test_force_field_rejects_unknown_name(parser): + with pytest.raises( + InputSchemaError, + match="Unsupported force field", + ): + parser._validate_force_field( + "not-a-force-field" + ) + + +@pytest.mark.parametrize( + "raw", + [ + "OPLSAA", + "opls", + "opls-aa", + "GAFF", + "gaff", + ], +) +def test_current_lunar_workflow_rejects_incompatible_force_fields( + parser, + raw, +): + with pytest.raises(CompatibilityError): + parser._validate_force_field(raw) + + +# ============================================================================= +# Workflow option normalization +# ============================================================================= + + +@pytest.mark.parametrize( + "raw, expected", + [ + ("deep_search", "deepsearch"), + ("deep-search", "deepsearch"), + ("Deep Search", "deepsearch"), + (" DEEP_SEARCH ", "deepsearch"), + ("write_second_reaction_stage", "writesecondreactionstage"), + ], +) +def test_normalized_option_key( + parser, + raw, + expected, +): + assert ( + parser._normalized_option_key(raw) + == expected + ) + + +def test_get_workflow_option_returns_default( + parser, +): + assert ( + parser._get_workflow_option( + inputs={}, + key="wildcards", + default=True, + ) + is True + ) + + +def test_get_workflow_option_accepts_alias( + parser, +): + value = parser._get_workflow_option( + inputs={ + "use-wildcards": False, + }, + key="wildcards", + default=True, + aliases=[ + "use_wildcards", + ], + ) + + assert value is False + + +def test_get_workflow_option_accepts_equivalent_duplicate_alias_values( + parser, +): + value = parser._get_workflow_option( + inputs={ + "wildcards": False, + "use-wildcards": False, + }, + key="wildcards", + default=True, + aliases=[ + "use_wildcards", + ], + ) + + assert value is False + + +def test_get_workflow_option_rejects_conflicting_alias_values( + parser, +): + with pytest.raises( + InputConflictError, + match="Conflicting values", + ): + parser._get_workflow_option( + inputs={ + "wildcards": True, + "use-wildcards": False, + }, + key="wildcards", + default=True, + aliases=[ + "use_wildcards", + ], + ) + + +# ============================================================================= +# Boolean workflow options +# ============================================================================= + + +@pytest.mark.parametrize( + "value", + [ + True, + "true", + "TRUE", + "yes", + "Y", + "on", + "1", + ], +) +def test_validate_bool_option_true_values( + parser, + value, +): + result = parser._validate_bool_option( + inputs={ + "feature": value, + }, + key="feature", + default=False, + ) + + assert result is True + + +@pytest.mark.parametrize( + "value", + [ + False, + "false", + "FALSE", + "no", + "N", + "off", + "0", + ], +) +def test_validate_bool_option_false_values( + parser, + value, +): + result = parser._validate_bool_option( + inputs={ + "feature": value, + }, + key="feature", + default=True, + ) + + assert result is False + + +@pytest.mark.parametrize( + "value", + [ + 1, + 0, + 2, + None, + [], + "maybe", + ], +) +def test_validate_bool_option_rejects_invalid_values( + parser, + value, +): + with pytest.raises(InputSchemaError): + parser._validate_bool_option( + inputs={ + "feature": value, + }, + key="feature", + default=True, + ) + + +# ============================================================================= +# Reaction iteration depth +# ============================================================================= + + +def test_reaction_iteration_depth_defaults_to_five( + parser, +): + assert ( + parser._validate_reaction_iteration_depth( + {} + ) + == 5 + ) + + +@pytest.mark.parametrize( + "value, expected", + [ + (0, 0), + (1, 1), + (5, 5), + (20, 20), + (False, 0), + (True, 5), + ("0", 0), + ("1", 1), + ("10", 10), + ("false", 0), + ("no", 0), + ("off", 0), + ("none", 0), + ("true", 5), + ("yes", 5), + ("on", 5), + ], +) +def test_reaction_iteration_depth_accepts_supported_values( + parser, + value, + expected, +): + result = parser._validate_reaction_iteration_depth( + { + "reaction_iteration_depth": value, + } + ) + + assert result == expected + + +@pytest.mark.parametrize( + "alias", + [ + "rxn_iteration_depth", + "reaction_depth", + "iteration_depth", + "max_loop_count", + "max_iterations", + "iterations", + "loop", + ], +) +def test_reaction_iteration_depth_accepts_aliases( + parser, + alias, +): + result = parser._validate_reaction_iteration_depth( + { + alias: 7, + } + ) + + assert result == 7 + + +@pytest.mark.parametrize( + "value", + [ + -1, + -10, + 1.5, + None, + [], + {}, + "hello", + "2.5", + ], +) +def test_reaction_iteration_depth_rejects_invalid_values( + parser, + value, +): + with pytest.raises(InputSchemaError): + parser._validate_reaction_iteration_depth( + { + "reaction_iteration_depth": value, + } + ) + + +def test_reaction_iteration_depth_rejects_conflicting_aliases( + parser, +): + with pytest.raises(InputConflictError): + parser._validate_reaction_iteration_depth( + { + "reaction_iteration_depth": 5, + "loop": 3, + } + ) + + +def test_validate_loop_zero_disables_loop(parser): + assert ( + parser._validate_loop( + { + "reaction_iteration_depth": 0, + } + ) + == (False, None) + ) + + +def test_validate_loop_positive_depth_enables_loop( + parser, +): + assert ( + parser._validate_loop( + { + "reaction_iteration_depth": 8, + } + ) + == (True, 8) + ) + + +# ============================================================================= +# SMILES validation +# ============================================================================= + + +def test_validate_smiles_returns_canonical_smiles( + parser, +): + smiles, mol = parser._validate_smiles( + "OCC" + ) + + assert smiles == "CCO" + assert isinstance(mol, Chem.Mol) + + +def test_validate_smiles_strips_whitespace( + parser, +): + smiles, _ = parser._validate_smiles( + " CCO " + ) + + assert smiles == "CCO" + + +@pytest.mark.parametrize( + "value", + [ + None, + "", + " ", + 123, + [], + ], +) +def test_validate_smiles_requires_nonempty_string( + parser, + value, +): + with pytest.raises(SmilesValidationError): + parser._validate_smiles(value) + + +def test_validate_smiles_rejects_invalid_rdkit_smiles( + parser, +): + with pytest.raises( + SmilesValidationError, + match="Invalid SMILES", + ): + parser._validate_smiles( + "C1CC" + ) + + +# ============================================================================= +# Duplicate SMILES +# ============================================================================= + + +def test_validate_no_duplicate_smiles_adds_new_smiles( + parser, +): + seen = [] + + returned = parser.validate_no_duplicate_smiles( + "CCO", + seen, + ) + + assert returned is seen + assert seen == ["CCO"] + + +def test_validate_no_duplicate_smiles_rejects_duplicate( + parser, +): + seen = ["CCO"] + + with pytest.raises( + DuplicateMonomerError, + match="Duplicate monomer", + ): + parser.validate_no_duplicate_smiles( + "CCO", + seen, + ) + + +def test_validate_inputs_detects_canonical_smiles_duplicates( + parser, +): + data = make_counts_input() + + data["monomers"] = [ + { + "name": "one", + "smiles": "CCO", + }, + { + "name": "two", + "smiles": "OCC", + }, + ] + + for simulation in data["simulations"]: + simulation["monomer_counts"] = { + "one": 1, + "two": 1, + } + + with pytest.raises(DuplicateMonomerError): + parser.validate_inputs(data) + + +# ============================================================================= +# Derived molecular properties +# ============================================================================= + + +def test_derive_molecule_properties_includes_hydrogens( + parser, +): + mol = Chem.MolFromSmiles("C") + + num_atoms, molecular_weight = ( + parser._derive_molecule_properties( + mol + ) + ) + + # methane = 1 C + 4 H + assert num_atoms == 5 + + assert molecular_weight == pytest.approx( + 16.043, + rel=1e-3, + ) + + +def test_int_to_dict(parser): + assert parser._int_to_dict(42) == { + "_": 42 + } + + +# ============================================================================= +# Simulation validation +# ============================================================================= + + +def test_validate_simulations_counts_mode( + parser, +): + systems = make_counts_input()[ + "simulations" + ] + + result = parser._validate_simulations( + systems, + "counts", + ) + + assert result["method"] == "counts" + + assert result["temperatures"] == [ + 300.0, + 400.0, + ] + + assert result["density"] == [ + 0.8, + 1.0, + ] + + assert len(result["simulations"]) == 2 + + assert all( + isinstance(simulation, Simulation) + for simulation in result["simulations"] + ) + + +def test_validate_simulations_ratio_mode( + parser, +): + systems = make_ratio_input()[ + "simulations" + ] + + result = parser._validate_simulations( + systems, + "ratio", + ) + + assert result["method"] == "ratio" + + assert ( + result["simulations"][0].total_atoms + == 10000 + ) + + assert ( + result["simulations"][1].total_atoms + == 100000 + ) + + +def test_validate_simulations_rejects_duplicate_tags( + parser, +): + systems = make_counts_input()[ + "simulations" + ] + + systems[1]["tag"] = "small" + + with pytest.raises( + InputSchemaError, + match="Duplicate system tag", + ): + parser._validate_simulations( + systems, + "counts", + ) + + +@pytest.mark.parametrize( + "tag", + [ + "", + " ", + None, + 123, + ], +) +def test_validate_simulations_requires_valid_tag( + parser, + tag, +): + systems = make_counts_input()[ + "simulations" + ] + + systems[0]["tag"] = tag + + with pytest.raises(InputSchemaError): + parser._validate_simulations( + systems, + "counts", + ) + + +def test_counts_mode_rejects_total_atoms( + parser, +): + systems = make_counts_input()[ + "simulations" + ] + + systems[0]["total_atoms"] = 10000 + + with pytest.raises( + InputSchemaError, + match="total_atoms", + ): + parser._validate_simulations( + systems, + "counts", + ) + + +@pytest.mark.parametrize( + "value", + [ + -1, + 1.5, + True, + "10", + ], +) +def test_counts_mode_rejects_invalid_counts( + parser, + value, +): + systems = make_counts_input()[ + "simulations" + ] + + systems[0]["monomer_counts"][ + "ethanol" + ] = value + + with pytest.raises(NumericFieldError): + parser._validate_simulations( + systems, + "counts", + ) + + +def test_counts_mode_allows_zero_count( + parser, +): + systems = make_counts_input()[ + "simulations" + ] + + systems[0]["monomer_counts"][ + "ethanol" + ] = 0 + + result = parser._validate_simulations( + systems, + "counts", + ) + + assert ( + result["simulations"][0] + .monomer_counts["ethanol"] + == 0 + ) + + +@pytest.mark.parametrize( + "value", + [ + 0, + -1, + True, + 1.5, + "10000", + None, + ], +) +def test_ratio_mode_requires_positive_integer_total_atoms( + parser, + value, +): + systems = make_ratio_input()[ + "simulations" + ] + + systems[0]["total_atoms"] = value + + with pytest.raises(NumericFieldError): + parser._validate_simulations( + systems, + "ratio", + ) + + +@pytest.mark.parametrize( + "value", + [ + -1, + True, + "1.0", + None, + ], +) +def test_ratio_mode_rejects_invalid_ratio_values( + parser, + value, +): + systems = make_ratio_input()[ + "simulations" + ] + + systems[0]["monomer_ratios"][ + "ethanol" + ] = value + + with pytest.raises(NumericFieldError): + parser._validate_simulations( + systems, + "ratio", + ) + + +def test_ratio_mode_allows_zero_ratio( + parser, +): + systems = make_ratio_input()[ + "simulations" + ] + + for system in systems: + system["monomer_ratios"][ + "ethanol" + ] = 0 + + result = parser._validate_simulations( + systems, + "ratio", + ) + + assert ( + result["simulations"][0] + .monomer_ratios["ethanol"] + == 0 + ) + + +def test_ratio_mode_requires_identical_ratios_between_systems( + parser, +): + systems = make_ratio_input()[ + "simulations" + ] + + systems[1]["monomer_ratios"][ + "ethanol" + ] = 3.0 + + with pytest.raises( + InputSchemaError, + match="identical", + ): + parser._validate_simulations( + systems, + "ratio", + ) + + +# ============================================================================= +# System/monomer key consistency +# ============================================================================= + + +def test_system_monomer_keys_accept_exact_match( + parser, +): + data = make_counts_input() + + parser._validate_system_monomer_keys( + data, + data["simulations"], + "counts", + ) + + +def test_system_monomer_keys_reject_unknown_name( + parser, +): + data = make_counts_input() + + data["simulations"][0][ + "monomer_counts" + ]["unknown"] = 10 + + with pytest.raises( + InputSchemaError, + match="unknown monomer", + ): + parser._validate_system_monomer_keys( + data, + data["simulations"], + "counts", + ) + + +def test_system_monomer_keys_reject_missing_name( + parser, +): + data = make_counts_input() + + del data["simulations"][0][ + "monomer_counts" + ]["ethanol"] + + with pytest.raises( + InputSchemaError, + match="missing monomer", + ): + parser._validate_system_monomer_keys( + data, + data["simulations"], + "counts", + ) + + +def test_missing_monomer_name_receives_data_id_name( + parser, +): + data = { + "monomers": [ + { + "smiles": "CCO", + } + ] + } + + systems = [ + { + "tag": "sim", + "monomer_counts": { + "data_1": 2, + }, + } + ] + + parser._validate_system_monomer_keys( + data, + systems, + "counts", + ) + + assert ( + data["monomers"][0]["name"] + == "data_1" + ) + + +# ============================================================================= +# Monomer-entry validation +# ============================================================================= + + +def test_validate_monomer_entry_counts_mode( + parser, +): + data = make_counts_input() + + monomers = parser._validate_monomer_entry( + data, + "counts", + data["simulations"], + ) + + assert len(monomers) == 2 + + ethanol = monomers[0] + + assert ethanol.id == 1 + assert ethanol.data_id == "data_1" + assert ethanol.name == "ethanol" + assert ethanol.smiles == "CCO" + + assert ethanol.count == { + "small": 10, + "large": 100, + } + + assert ethanol.ratio is None + assert isinstance(ethanol.rdkit_mol, Chem.Mol) + assert ethanol.num_atoms is not None + assert ethanol.molecular_weight is not None + + +def test_validate_monomer_entry_ratio_mode( + parser, +): + data = make_ratio_input() + + monomers = parser._validate_monomer_entry( + data, + "ratio", + data["simulations"], + ) + + ethanol = monomers[0] + + assert ethanol.count is None + assert ethanol.ratio == 1.0 + + +def test_validate_monomer_entry_requires_list( + parser, +): + with pytest.raises(InputSchemaError): + parser._validate_monomer_entry( + { + "monomers": {}, + }, + "counts", + [], + ) + + +def test_validate_monomer_entry_rejects_non_dictionary_entry( + parser, +): + with pytest.raises(InputSchemaError): + parser._validate_monomer_entry( + { + "monomers": [ + "bad entry" + ], + }, + "counts", + [], + ) + + +# ============================================================================= +# Legacy composition validator +# ============================================================================= + + +def test_validate_composition_accepts_counts_targets( + parser, +): + composition = { + "targets": [ + { + "tag": "one", + }, + { + "tag": "two", + }, + ] + } + + assert ( + parser._validate_composition( + composition, + "counts", + ) + is composition + ) + + +def test_validate_composition_requires_targets( + parser, +): + with pytest.raises(InputSchemaError): + parser._validate_composition( + {}, + "counts", + ) + + +def test_validate_composition_rejects_duplicate_tags( + parser, +): + with pytest.raises(InputSchemaError): + parser._validate_composition( + { + "targets": [ + { + "tag": "same", + }, + { + "tag": "same", + }, + ] + }, + "counts", + ) + + +def test_validate_composition_ratio_requires_total_atoms( + parser, +): + with pytest.raises(NumericFieldError): + parser._validate_composition( + { + "targets": [ + { + "tag": "one", + } + ] + }, + "ratio", + ) + + +def test_validate_composition_counts_rejects_total_atoms( + parser, +): + with pytest.raises(InputSchemaError): + parser._validate_composition( + { + "targets": [ + { + "tag": "one", + "total_atoms": 1000, + } + ] + }, + "counts", + ) + + +# ============================================================================= +# Legacy numeric validator +# ============================================================================= + + +def test_legacy_numeric_validator_accepts_valid_input( + parser, +): + parser._validate_numeric_fields( + { + "density": 1.0, + "temperature": [ + 300, + 400, + ], + "number_of_monomers": { + "a": 5, + "b": 10, + }, + } + ) + + +def test_legacy_numeric_validator_rejects_bad_density( + parser, +): + with pytest.raises(NumericFieldError): + parser._validate_numeric_fields( + { + "density": 0, + "temperature": 300, + "number_of_monomers": { + "a": 1, + }, + } + ) + + +def test_legacy_numeric_validator_rejects_bad_temperature( + parser, +): + with pytest.raises(NumericFieldError): + parser._validate_numeric_fields( + { + "density": 1.0, + "temperature": -10, + "number_of_monomers": { + "a": 1, + }, + } + ) + + +def test_legacy_numeric_validator_rejects_bad_monomer_count( + parser, +): + with pytest.raises(NumericFieldError): + parser._validate_numeric_fields( + { + "density": 1.0, + "temperature": 300, + "number_of_monomers": { + "a": 0, + }, + } + ) + + +# ============================================================================= +# Full validate_inputs(): counts mode +# ============================================================================= + + +def test_validate_inputs_counts_mode_end_to_end( + parser, +): + data = make_counts_input() + + result = parser.validate_inputs(data) + + assert isinstance(result, SimulationSetup) + + assert ( + result.simulation_name + == "counts_demo" + ) + + assert result.composition_method == "counts" + + assert result.temperature == [ + 300.0, + 400.0, + ] + + assert result.density == [ + 0.8, + 1.0, + ] + + assert result.force_field == "PCFF" + assert len(result.monomers) == 2 + assert len(result.simulations) == 2 + + assert result.loop is True + assert result.max_loop_count == 5 + assert result.reaction_iteration_depth == 5 + + assert result.deep_search is True + assert result.wildcards is True + + assert ( + result.deduplicate_reaction_templates + is True + ) + + assert ( + result.write_second_reaction_stage + is True + ) + + +def test_validate_inputs_preserves_raw_input_reference( + parser, +): + data = make_counts_input() + + result = parser.validate_inputs(data) + + assert result.input_json is data + + +def test_validate_inputs_zero_iteration_depth_disables_loop( + parser, +): + data = make_counts_input() + + data["reaction_iteration_depth"] = 0 + + result = parser.validate_inputs(data) + + assert result.loop is False + assert result.max_loop_count is None + assert result.reaction_iteration_depth == 0 + + +def test_validate_inputs_workflow_options_can_be_disabled( + parser, +): + data = make_counts_input() + + data.update( + { + "deep_search": False, + "wildcards": False, + "deduplicate_reaction_templates": False, + "write_second_reaction_stage": False, + } + ) + + result = parser.validate_inputs(data) + + assert result.deep_search is False + assert result.wildcards is False + + assert ( + result.deduplicate_reaction_templates + is False + ) + + assert ( + result.write_second_reaction_stage + is False + ) + + +def test_validate_inputs_accepts_workflow_aliases( + parser, +): + data = make_counts_input() + + data["deep-search"] = "no" + data["use-wildcards"] = "false" + data["template_dedup"] = "off" + data["stage_2"] = "0" + data["iterations"] = "3" + + result = parser.validate_inputs(data) + + assert result.deep_search is False + assert result.wildcards is False + + assert ( + result.deduplicate_reaction_templates + is False + ) + + assert ( + result.write_second_reaction_stage + is False + ) + + assert result.reaction_iteration_depth == 3 + assert result.max_loop_count == 3 + + +# ============================================================================= +# Full validate_inputs(): ratio mode +# ============================================================================= + + +def test_validate_inputs_ratio_mode_end_to_end( + parser, +): + data = make_ratio_input() + + result = parser.validate_inputs(data) + + assert isinstance(result, SimulationSetup) + + assert result.composition_method == "ratio" + + assert result.temperature == [ + 300.0, + 400.0, + ] + + assert result.density == [ + 0.8, + 1.0, + ] + + assert len(result.monomers) == 2 + assert len(result.simulations) == 2 + + assert result.monomers[0].count is None + assert result.monomers[0].ratio == 1.0 + + assert ( + result.simulations[0].total_atoms + == 10000 + ) + + +# ============================================================================= +# Public-path malformed input checks +# ============================================================================= + + +def test_validate_inputs_rejects_non_dictionary_monomer_with_schema_error( + parser, +): + """ + Public validation should translate malformed monomer entries into the + parser's own schema exception rather than leaking AttributeError. + """ + data = make_counts_input() + + data["monomers"] = [ + "not-a-dictionary" + ] + + data["simulations"] = [ + { + "tag": "sim", + "temperature": 300, + "density": 1.0, + "monomer_counts": { + "data_1": 1, + }, + } + ] + + with pytest.raises(InputSchemaError): + parser.validate_inputs(data) + + +@pytest.mark.parametrize( + "simulation_name", + [ + "", + " ", + None, + 123, + ], +) +def test_validate_inputs_requires_nonempty_string_simulation_name( + parser, + simulation_name, +): + """ + simulation_name is part of the public schema and later becomes an + output-directory name, so invalid values should fail here. + """ + data = make_counts_input() + + data["simulation_name"] = simulation_name + + with pytest.raises(InputSchemaError): + parser.validate_inputs(data) + + +# ============================================================================= +# Molecule representation / image generation +# ============================================================================= + + +def test_molecule_representation_returns_molecules_and_legends( + parser, +): + mol_1 = Chem.MolFromSmiles("CCO") + mol_2 = Chem.MolFromSmiles("CCN") + + setup = SimulationSetup( + simulation_name="demo", + temperature=[300.0], + density=[1.0], + force_field="PCFF", + monomers=[ + MonomerEntry( + id=1, + data_id="data_1", + name="ethanol", + smiles="CCO", + count={"sim": 1}, + ratio=None, + rdkit_mol=mol_1, + ), + MonomerEntry( + id=2, + data_id="data_2", + name="ethylamine", + smiles="CCN", + count={"sim": 1}, + ratio=None, + rdkit_mol=mol_2, + ), + ], + ) + + molecules, legends = ( + parser.molecule_representation_of_initial_molecules( + setup + ) + ) + + assert molecules == [ + mol_1, + mol_2, + ] + + assert legends == [ + "ethanol", + "ethylamine", + ] + + +def test_molecule_representation_uses_data_id_when_name_missing( + parser, +): + mol = Chem.MolFromSmiles("CCO") + + setup = SimulationSetup( + simulation_name="demo", + temperature=[300.0], + density=[1.0], + force_field="PCFF", + monomers=[ + MonomerEntry( + id=1, + data_id="data_1", + name=None, + smiles="CCO", + count={"sim": 1}, + ratio=None, + rdkit_mol=mol, + ), + ], + ) + + _, legends = ( + parser.molecule_representation_of_initial_molecules( + setup + ) + ) + + assert legends == [ + "data_1" + ] + + +def test_initial_molecules_image_grid_uses_expected_draw_settings( + parser, + monkeypatch, +): + mol_1 = Chem.MolFromSmiles("CCO") + mol_2 = Chem.MolFromSmiles("CCN") + + setup = SimulationSetup( + simulation_name="demo", + temperature=[300.0], + density=[1.0], + force_field="PCFF", + monomers=[ + MonomerEntry( + id=1, + data_id="data_1", + name="ethanol", + smiles="CCO", + count={"sim": 1}, + ratio=None, + rdkit_mol=mol_1, + ), + MonomerEntry( + id=2, + data_id="data_2", + name="ethylamine", + smiles="CCN", + count={"sim": 1}, + ratio=None, + rdkit_mol=mol_2, + ), + ], + ) + + session = SimpleNamespace( + inputs=setup + ) + + captured = {} + + fake_image = object() + + def fake_grid( + molecules, + *, + molsPerRow, + subImgSize, + legends, + ): + captured["molecules"] = molecules + captured["molsPerRow"] = molsPerRow + captured["subImgSize"] = subImgSize + captured["legends"] = legends + + return fake_image + + monkeypatch.setattr( + "AutoREACTER.input_parser.Draw.MolsToGridImage", + fake_grid, + ) + + result = parser.initial_molecules_image_grid( + session + ) + + assert result is fake_image + + assert captured["molecules"] == [ + mol_1, + mol_2, + ] + + assert captured["molsPerRow"] == 3 + + assert captured["subImgSize"] == ( + 400, + 400, + ) + + assert captured["legends"] == [ + "ethanol", + "ethylamine", + ] \ No newline at end of file From 5680142baee8d64010eb67bbcca5353bea32d8a7 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:07:18 -0400 Subject: [PATCH 141/176] Respect cache staging clear flag --- AutoREACTER/cache.py | 4 +- tests/unit/test_cache.py | 1105 +++++++++++++++++++++++++++++ tests/unit/test_initialization.py | 276 +++++++ 3 files changed, 1384 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_cache.py create mode 100644 tests/unit/test_initialization.py diff --git a/AutoREACTER/cache.py b/AutoREACTER/cache.py index 2dcdec93..ed1a0b5b 100644 --- a/AutoREACTER/cache.py +++ b/AutoREACTER/cache.py @@ -21,7 +21,9 @@ def __init__(self, clear_staging: bool = True): # generate a unique staging directory for this run to prevent concurrent conflicts self.staging_dir = Path(tempfile.gettempdir()) / f"AutoREACTER_staging" self.staging_dir.mkdir(parents=True, exist_ok=True) - self.clear_staging_dir() + + if clear_staging: + self.clear_staging_dir() def clear_staging_dir(self) -> None: """ diff --git a/tests/unit/test_cache.py b/tests/unit/test_cache.py new file mode 100644 index 00000000..834ea13e --- /dev/null +++ b/tests/unit/test_cache.py @@ -0,0 +1,1105 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER.cache as cache_module +from AutoREACTER.cache import ( + GetCacheDir, + RunDirectoryManager, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_fake_reacter_files(old_base: Path): + """ + Build a lightweight REACTERFiles-like object. + + The production function only requires these attributes, so using + SimpleNamespace keeps cache tests independent from the force-field and + reaction-template builders. + """ + force_field_data = old_base / "force_field.data" + in_file = old_base / "in.create_atoms.script" + molecule_file = old_base / "monomer.molecule" + map_file = old_base / "RXN_1.map" + pre_file = old_base / "template_pre_1.molecule" + post_file = old_base / "template_post_1.molecule" + + for path in [ + force_field_data, + in_file, + molecule_file, + map_file, + pre_file, + post_file, + ]: + path.parent.mkdir( + parents=True, + exist_ok=True, + ) + path.write_text( + path.name, + encoding="utf-8", + ) + + molecule = SimpleNamespace( + molecule_files=SimpleNamespace( + lmp_molecule_file=molecule_file, + ) + ) + + template = SimpleNamespace( + map_file=map_file, + pre_reaction_file=SimpleNamespace( + lmp_molecule_file=pre_file, + ), + post_reaction_file=SimpleNamespace( + lmp_molecule_file=post_file, + ), + ) + + return SimpleNamespace( + force_field_data=force_field_data, + in_file=in_file, + molecule_files=[molecule], + template_files=[template], + ) + + +# ============================================================================= +# GetCacheDir construction +# ============================================================================= + + +def test_get_cache_dir_creates_staging_directory( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + cache_module.tempfile, + "gettempdir", + lambda: str(tmp_path), + ) + + cache = GetCacheDir() + + assert cache.staging_dir.exists() + assert cache.staging_dir.is_dir() + assert cache.staging_dir.parent == tmp_path + + +def test_get_cache_dir_default_clears_existing_staging_contents( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + cache_module.tempfile, + "gettempdir", + lambda: str(tmp_path), + ) + + staging = ( + tmp_path + / "AutoREACTER_staging" + ) + staging.mkdir() + + old_file = staging / "old.txt" + old_file.write_text( + "old", + encoding="utf-8", + ) + + old_directory = staging / "nested" + old_directory.mkdir() + + ( + old_directory / "nested.txt" + ).write_text( + "nested", + encoding="utf-8", + ) + + cache = GetCacheDir() + + assert cache.staging_dir == staging + assert staging.exists() + assert list(staging.iterdir()) == [] + + +def test_get_cache_dir_clear_staging_true_clears_contents( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + cache_module.tempfile, + "gettempdir", + lambda: str(tmp_path), + ) + + staging = ( + tmp_path + / "AutoREACTER_staging" + ) + staging.mkdir() + + old_file = staging / "old.txt" + old_file.write_text( + "old", + encoding="utf-8", + ) + + GetCacheDir( + clear_staging=True + ) + + assert not old_file.exists() + + +def test_get_cache_dir_clear_staging_false_preserves_contents( + tmp_path, + monkeypatch, +): + """ + The constructor documents clear_staging=False as disabling automatic + staging cleanup. Existing temporary data must therefore remain untouched. + """ + monkeypatch.setattr( + cache_module.tempfile, + "gettempdir", + lambda: str(tmp_path), + ) + + staging = ( + tmp_path + / "AutoREACTER_staging" + ) + staging.mkdir() + + old_file = staging / "keep.txt" + old_file.write_text( + "keep me", + encoding="utf-8", + ) + + cache = GetCacheDir( + clear_staging=False + ) + + assert cache.staging_dir == staging + assert old_file.exists() + + assert ( + old_file.read_text( + encoding="utf-8" + ) + == "keep me" + ) + + +# ============================================================================= +# clear_staging_dir +# ============================================================================= + + +def test_clear_staging_dir_removes_files( + tmp_path, +): + cache = GetCacheDir.__new__( + GetCacheDir + ) + + cache.staging_dir = ( + tmp_path / "staging" + ) + cache.staging_dir.mkdir() + + file_path = ( + cache.staging_dir / "file.txt" + ) + file_path.write_text( + "data", + encoding="utf-8", + ) + + cache.clear_staging_dir() + + assert not file_path.exists() + assert cache.staging_dir.exists() + + +def test_clear_staging_dir_removes_nested_directories( + tmp_path, +): + cache = GetCacheDir.__new__( + GetCacheDir + ) + + cache.staging_dir = ( + tmp_path / "staging" + ) + + nested = ( + cache.staging_dir + / "a" + / "b" + / "c" + ) + nested.mkdir( + parents=True + ) + + ( + nested / "data.txt" + ).write_text( + "data", + encoding="utf-8", + ) + + cache.clear_staging_dir() + + assert cache.staging_dir.exists() + assert list( + cache.staging_dir.iterdir() + ) == [] + + +def test_clear_staging_dir_creates_missing_root( + tmp_path, +): + cache = GetCacheDir.__new__( + GetCacheDir + ) + + cache.staging_dir = ( + tmp_path + / "missing_staging" + ) + + assert not cache.staging_dir.exists() + + cache.clear_staging_dir() + + assert cache.staging_dir.is_dir() + + +def test_clear_staging_dir_prints_success( + tmp_path, + capsys, +): + cache = GetCacheDir.__new__( + GetCacheDir + ) + + cache.staging_dir = ( + tmp_path / "staging" + ) + cache.staging_dir.mkdir() + + cache.clear_staging_dir() + + output = capsys.readouterr().out + + assert ( + "[OK] Cleared staging cache:" + in output + ) + + assert str( + cache.staging_dir + ) in output + + +def test_clear_staging_dir_continues_after_failed_item( + tmp_path, + monkeypatch, + capsys, +): + cache = GetCacheDir.__new__( + GetCacheDir + ) + + cache.staging_dir = ( + tmp_path / "staging" + ) + cache.staging_dir.mkdir() + + failing_dir = ( + cache.staging_dir + / "cannot_remove" + ) + failing_dir.mkdir() + + removable_file = ( + cache.staging_dir + / "remove_me.txt" + ) + removable_file.write_text( + "remove", + encoding="utf-8", + ) + + real_rmtree = ( + cache_module.shutil.rmtree + ) + + def fake_rmtree(path, *args, **kwargs): + if Path(path) == failing_dir: + raise PermissionError( + "simulated failure" + ) + + return real_rmtree( + path, + *args, + **kwargs, + ) + + monkeypatch.setattr( + cache_module.shutil, + "rmtree", + fake_rmtree, + ) + + cache.clear_staging_dir() + + assert failing_dir.exists() + assert not removable_file.exists() + + output = capsys.readouterr().out + + assert ( + "[WARN] Failed to remove staging cache item" + in output + ) + + assert ( + "[WARN] Staging cache partially cleared" + in output + ) + + +# ============================================================================= +# RunDirectoryManager construction +# ============================================================================= + + +def test_run_directory_manager_creates_base_directory( + tmp_path, +): + base_dir = ( + tmp_path + / "runs" + / "nested" + ) + + assert not base_dir.exists() + + manager = RunDirectoryManager( + base_dir + ) + + assert manager.base_dir == base_dir + assert base_dir.is_dir() + + +def test_run_directory_manager_accepts_string_path( + tmp_path, +): + base_dir = tmp_path / "runs" + + manager = RunDirectoryManager( + str(base_dir) + ) + + assert isinstance( + manager.base_dir, + Path, + ) + + assert ( + manager.base_dir + == base_dir + ) + + +# ============================================================================= +# remove_path +# ============================================================================= + + +def test_remove_path_removes_file( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + path = tmp_path / "file.txt" + path.write_text( + "data", + encoding="utf-8", + ) + + manager.remove_path(path) + + assert not path.exists() + + +def test_remove_path_removes_directory_recursively( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + directory = tmp_path / "folder" + nested = directory / "nested" + nested.mkdir( + parents=True + ) + + ( + nested / "data.txt" + ).write_text( + "data", + encoding="utf-8", + ) + + manager.remove_path( + directory + ) + + assert not directory.exists() + + +def test_remove_path_nonexistent_path_is_noop( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + missing = ( + tmp_path / "missing" + ) + + manager.remove_path(missing) + + assert not missing.exists() + + +# ============================================================================= +# move_into_run +# ============================================================================= + + +def test_move_into_run_moves_all_contents( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + source = tmp_path / "source" + destination = ( + tmp_path / "destination" + ) + + source.mkdir() + destination.mkdir() + + ( + source / "one.txt" + ).write_text( + "one", + encoding="utf-8", + ) + + ( + source / "two.txt" + ).write_text( + "two", + encoding="utf-8", + ) + + result = manager.move_into_run( + source, + destination, + ) + + assert result == destination + + assert ( + destination / "one.txt" + ).read_text( + encoding="utf-8" + ) == "one" + + assert ( + destination / "two.txt" + ).read_text( + encoding="utf-8" + ) == "two" + + assert list(source.iterdir()) == [] + + +def test_move_into_run_moves_directories( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + source = tmp_path / "source" + destination = ( + tmp_path / "destination" + ) + + source.mkdir() + destination.mkdir() + + nested = source / "nested" + nested.mkdir() + + ( + nested / "data.txt" + ).write_text( + "nested data", + encoding="utf-8", + ) + + manager.move_into_run( + source, + destination, + ) + + moved_file = ( + destination + / "nested" + / "data.txt" + ) + + assert moved_file.exists() + + assert ( + moved_file.read_text( + encoding="utf-8" + ) + == "nested data" + ) + + +def test_move_into_run_overwrites_existing_file( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + source = tmp_path / "source" + destination = ( + tmp_path / "destination" + ) + + source.mkdir() + destination.mkdir() + + source_file = ( + source / "same.txt" + ) + source_file.write_text( + "new", + encoding="utf-8", + ) + + existing = ( + destination / "same.txt" + ) + existing.write_text( + "old", + encoding="utf-8", + ) + + manager.move_into_run( + source, + destination, + ) + + assert ( + existing.read_text( + encoding="utf-8" + ) + == "new" + ) + + +def test_move_into_run_overwrites_existing_directory( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + source = tmp_path / "source" + destination = ( + tmp_path / "destination" + ) + + source.mkdir() + destination.mkdir() + + incoming = source / "folder" + incoming.mkdir() + + ( + incoming / "new.txt" + ).write_text( + "new", + encoding="utf-8", + ) + + existing = ( + destination / "folder" + ) + existing.mkdir() + + ( + existing / "old.txt" + ).write_text( + "old", + encoding="utf-8", + ) + + manager.move_into_run( + source, + destination, + ) + + assert not ( + destination + / "folder" + / "old.txt" + ).exists() + + assert ( + destination + / "folder" + / "new.txt" + ).exists() + + +def test_move_into_run_preserves_unrelated_destination_files( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + source = tmp_path / "source" + destination = ( + tmp_path / "destination" + ) + + source.mkdir() + destination.mkdir() + + ( + source / "incoming.txt" + ).write_text( + "incoming", + encoding="utf-8", + ) + + unrelated = ( + destination / "keep.txt" + ) + unrelated.write_text( + "keep", + encoding="utf-8", + ) + + manager.move_into_run( + source, + destination, + ) + + assert unrelated.exists() + + assert ( + unrelated.read_text( + encoding="utf-8" + ) + == "keep" + ) + + +def test_move_into_run_prints_destination( + tmp_path, + capsys, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + source = tmp_path / "source" + destination = ( + tmp_path / "destination" + ) + + source.mkdir() + destination.mkdir() + + manager.move_into_run( + source, + destination, + ) + + output = capsys.readouterr().out + + assert "[OK] Moved files" in output + assert str(destination) in output + + +# ============================================================================= +# move_reacter_files +# ============================================================================= + + +def test_move_reacter_files_requires_reacter_directory( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + staging = tmp_path / "staging" + final = tmp_path / "final" + + staging.mkdir() + final.mkdir() + + fake_reacter_files = ( + SimpleNamespace() + ) + + expected = ( + staging + / "lunar" + / "REACTER_files" + ) + + with pytest.raises( + FileNotFoundError, + match="REACTER files not found", + ): + manager.move_reacter_files( + fake_reacter_files, + staging, + final, + ) + + assert not expected.exists() + + +def test_move_reacter_files_moves_physical_files( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + staging = tmp_path / "staging" + final = tmp_path / "final" + + old_base = ( + staging + / "lunar" + / "REACTER_files" + ) + + old_base.mkdir( + parents=True + ) + final.mkdir() + + reacter_files = ( + make_fake_reacter_files( + old_base + ) + ) + + manager.move_reacter_files( + reacter_files, + staging, + final, + ) + + expected_names = { + "force_field.data", + "in.create_atoms.script", + "monomer.molecule", + "RXN_1.map", + "template_pre_1.molecule", + "template_post_1.molecule", + } + + assert { + item.name + for item in final.iterdir() + } == expected_names + + assert ( + list(old_base.iterdir()) + == [] + ) + + +def test_move_reacter_files_remaps_run_level_paths( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + staging = tmp_path / "staging" + final = tmp_path / "final" + + old_base = ( + staging + / "lunar" + / "REACTER_files" + ) + + old_base.mkdir( + parents=True + ) + final.mkdir() + + reacter_files = ( + make_fake_reacter_files( + old_base + ) + ) + + result = manager.move_reacter_files( + reacter_files, + staging, + final, + ) + + assert result is reacter_files + + assert ( + result.force_field_data + == final / "force_field.data" + ) + + assert ( + result.in_file + == final / "in.create_atoms.script" + ) + + +def test_move_reacter_files_remaps_molecule_file_paths( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + staging = tmp_path / "staging" + final = tmp_path / "final" + + old_base = ( + staging + / "lunar" + / "REACTER_files" + ) + + old_base.mkdir( + parents=True + ) + final.mkdir() + + reacter_files = ( + make_fake_reacter_files( + old_base + ) + ) + + manager.move_reacter_files( + reacter_files, + staging, + final, + ) + + molecule_path = ( + reacter_files + .molecule_files[0] + .molecule_files + .lmp_molecule_file + ) + + assert ( + molecule_path + == final / "monomer.molecule" + ) + + +def test_move_reacter_files_remaps_template_paths( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + staging = tmp_path / "staging" + final = tmp_path / "final" + + old_base = ( + staging + / "lunar" + / "REACTER_files" + ) + + old_base.mkdir( + parents=True + ) + final.mkdir() + + reacter_files = ( + make_fake_reacter_files( + old_base + ) + ) + + manager.move_reacter_files( + reacter_files, + staging, + final, + ) + + template = ( + reacter_files.template_files[0] + ) + + assert ( + template.map_file + == final / "RXN_1.map" + ) + + assert ( + template + .pre_reaction_file + .lmp_molecule_file + == final / "template_pre_1.molecule" + ) + + assert ( + template + .post_reaction_file + .lmp_molecule_file + == final / "template_post_1.molecule" + ) + + +def test_move_reacter_files_preserves_paths_outside_old_base( + tmp_path, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + staging = tmp_path / "staging" + final = tmp_path / "final" + + old_base = ( + staging + / "lunar" + / "REACTER_files" + ) + + old_base.mkdir( + parents=True + ) + final.mkdir() + + reacter_files = ( + make_fake_reacter_files( + old_base + ) + ) + + external_file = ( + tmp_path / "external.data" + ) + external_file.write_text( + "external", + encoding="utf-8", + ) + + reacter_files.force_field_data = ( + external_file + ) + + manager.move_reacter_files( + reacter_files, + staging, + final, + ) + + assert ( + reacter_files.force_field_data + == external_file + ) + + +def test_move_reacter_files_prints_success( + tmp_path, + capsys, +): + manager = RunDirectoryManager( + tmp_path / "runs" + ) + + staging = tmp_path / "staging" + final = tmp_path / "final" + + old_base = ( + staging + / "lunar" + / "REACTER_files" + ) + + old_base.mkdir( + parents=True + ) + final.mkdir() + + reacter_files = ( + make_fake_reacter_files( + old_base + ) + ) + + manager.move_reacter_files( + reacter_files, + staging, + final, + ) + + output = capsys.readouterr().out + + assert ( + "[OK] REACTER files moved" + in output + ) + + assert str(final) in output \ No newline at end of file diff --git a/tests/unit/test_initialization.py b/tests/unit/test_initialization.py new file mode 100644 index 00000000..2dc5a423 --- /dev/null +++ b/tests/unit/test_initialization.py @@ -0,0 +1,276 @@ +import importlib + +import pytest + +from AutoREACTER.initialization import Initialization + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_initialization_runs_all_steps_in_order(monkeypatch): + calls = [] + + monkeypatch.setattr( + Initialization, + "moldule_imports", + classmethod( + lambda cls: calls.append("modules") + ), + ) + + monkeypatch.setattr( + Initialization, + "ASCII_Mupt_reaction_LAMMPS", + classmethod( + lambda cls: calls.append("ascii") + ), + ) + + monkeypatch.setattr( + Initialization, + "print_version", + classmethod( + lambda cls: calls.append("version") + ), + ) + + Initialization() + + assert calls == [ + "modules", + "ascii", + "version", + ] + + +# ============================================================================= +# Required module imports +# ============================================================================= + + +def test_moldule_imports_imports_all_required_modules( + monkeypatch, + capsys, +): + imported_modules = [] + + def fake_import_module(name): + imported_modules.append(name) + return object() + + monkeypatch.setattr( + importlib, + "import_module", + fake_import_module, + ) + + Initialization.moldule_imports() + + assert imported_modules == [ + "rdkit", + "pandas", + "numpy", + "networkx", + ] + + output = capsys.readouterr().out + + assert ( + "All required modules are successfully imported." + in output + ) + + +def test_moldule_imports_stops_when_module_is_missing( + monkeypatch, +): + imported_modules = [] + + def fake_import_module(name): + imported_modules.append(name) + + if name == "numpy": + error = ModuleNotFoundError( + "No module named 'numpy'" + ) + error.name = "numpy" + raise error + + return object() + + monkeypatch.setattr( + importlib, + "import_module", + fake_import_module, + ) + + with pytest.raises(RuntimeError): + Initialization.moldule_imports() + + assert imported_modules == [ + "rdkit", + "pandas", + "numpy", + ] + + +def test_moldule_imports_missing_module_error_mentions_module_name( + monkeypatch, +): + def fake_import_module(name): + if name == "pandas": + error = ModuleNotFoundError( + "No module named 'pandas'" + ) + error.name = "pandas" + raise error + + return object() + + monkeypatch.setattr( + importlib, + "import_module", + fake_import_module, + ) + + with pytest.raises( + RuntimeError, + match="pandas", + ): + Initialization.moldule_imports() + + +def test_moldule_imports_missing_module_error_has_helpful_message( + monkeypatch, +): + def fake_import_module(name): + error = ModuleNotFoundError( + f"No module named '{name}'" + ) + error.name = name + raise error + + monkeypatch.setattr( + importlib, + "import_module", + fake_import_module, + ) + + with pytest.raises(RuntimeError) as exc_info: + Initialization.moldule_imports() + + message = str(exc_info.value) + + assert "Required module not found" in message + assert "Please install the missing module" in message + assert "Exiting program" in message + + +def test_moldule_imports_does_not_print_success_when_import_fails( + monkeypatch, + capsys, +): + def fake_import_module(name): + error = ModuleNotFoundError( + f"No module named '{name}'" + ) + error.name = name + raise error + + monkeypatch.setattr( + importlib, + "import_module", + fake_import_module, + ) + + with pytest.raises(RuntimeError): + Initialization.moldule_imports() + + output = capsys.readouterr().out + + assert ( + "All required modules are successfully imported." + not in output + ) + + +# ============================================================================= +# ASCII banner +# ============================================================================= + + +def test_ascii_banner_prints_autoreacter_name( + capsys, +): + Initialization.ASCII_Mupt_reaction_LAMMPS() + + output = capsys.readouterr().out + + assert output.strip() != "" + + # The banner is ASCII art, so use stable fragments rather + # than depending on every whitespace character. + assert "oooo" in output + assert "888" in output + + +def test_ascii_banner_contains_multiple_lines( + capsys, +): + Initialization.ASCII_Mupt_reaction_LAMMPS() + + output = capsys.readouterr().out + + lines = [ + line + for line in output.splitlines() + if line.strip() + ] + + assert len(lines) >= 7 + + +# ============================================================================= +# Version printing +# ============================================================================= + + +def test_print_version_uses_autoreacter_version( + monkeypatch, + capsys, +): + import AutoREACTER + + monkeypatch.setattr( + AutoREACTER, + "__version__", + "9.9.9-test", + ) + + Initialization.print_version() + + output = capsys.readouterr().out + + assert ( + "AutoREACTER version: 9.9.9-test" + in output + ) + + +def test_print_version_prints_exact_prefix( + capsys, +): + import AutoREACTER + + Initialization.print_version() + + output = capsys.readouterr().out.strip() + + assert output.startswith( + "AutoREACTER version:" + ) + + assert AutoREACTER.__version__ in output \ No newline at end of file From 59e358c319bf13759e355c56b819ce9413e76598 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:11:32 -0400 Subject: [PATCH 142/176] Create test_arx_cli.py --- tests/unit/test_arx_cli.py | 2001 ++++++++++++++++++++++++++++++++++++ 1 file changed, 2001 insertions(+) create mode 100644 tests/unit/test_arx_cli.py diff --git a/tests/unit/test_arx_cli.py b/tests/unit/test_arx_cli.py new file mode 100644 index 00000000..5d77b89c --- /dev/null +++ b/tests/unit/test_arx_cli.py @@ -0,0 +1,2001 @@ +from contextlib import contextmanager +import importlib +import os +from pathlib import Path +from types import SimpleNamespace + +import pytest +from PIL import Image as PILImage + + +cli_module = importlib.import_module( + "AutoREACTER.arx_cli" +) + +ARXCLI = cli_module.ARXCLI +ErrorHandler = cli_module.ErrorHandler +NoReactionGenerated = ( + cli_module.NoReactionGenerated +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_cli(tmp_path): + """ + Create an ARXCLI instance without running its real constructor. + + This is useful for unit-testing individual controller methods without + triggering read_input(), RDKit detection, force-field generation, or + any other heavy pipeline component. + """ + cli = ARXCLI.__new__(ARXCLI) + + output_dir = tmp_path / "output" + images_dir = output_dir / "images" + + output_dir.mkdir( + parents=True, + exist_ok=True, + ) + images_dir.mkdir( + parents=True, + exist_ok=True, + ) + + cli.input = tmp_path / "input.json" + + cli.session = SimpleNamespace( + output_dir=output_dir, + images_dir=images_dir, + reaction_instances=[], + non_reactants=[], + ) + + cli.img_dir = images_dir + + cli.error_handler = ( + ErrorHandler().waterfall_order() + ) + + cli._fg_detected = False + cli._reactions_detected = False + cli._reactions_selected = False + cli._non_reactants_detected = False + cli._non_reactants_selected = False + + return cli + + +# ============================================================================= +# ErrorHandler +# ============================================================================= + + +def test_error_handler_waterfall_order(): + handler = ErrorHandler() + + result = handler.waterfall_order() + + assert result == { + "select_reactions": False, + "select_non_reactants": False, + "process": False, + } + + +def test_error_handler_returns_independent_dicts(): + handler = ErrorHandler() + + first = handler.waterfall_order() + second = handler.waterfall_order() + + first["select_reactions"] = True + + assert ( + second["select_reactions"] + is False + ) + + +# ============================================================================= +# ARXCLI constructor +# ============================================================================= + + +def test_arxcli_constructor_initializes_expected_state( + tmp_path, + monkeypatch, +): + input_path = tmp_path / "input.json" + + session = SimpleNamespace( + output_dir=tmp_path / "output", + images_dir=tmp_path / "output" / "images", + reaction_instances=[], + non_reactants=[], + ) + + read_calls = [] + saved_input_paths = [] + saved_images = [] + ensure_calls = [] + + fake_monomer_image = object() + + def fake_read_input(path): + read_calls.append(path) + return session + + class FakeInputParser: + def initial_molecules_image_grid( + self, + passed_session, + ): + assert passed_session is session + return fake_monomer_image + + def fake_save_input( + self, + path, + ): + saved_input_paths.append(path) + + def fake_save_image( + self, + image, + path, + is_non_reactant=False, + ): + saved_images.append( + ( + image, + Path(path), + is_non_reactant, + ) + ) + + def fake_ensure_reactions(self): + ensure_calls.append(True) + + # Verify flags are initialized before bootstrap. + assert self._fg_detected is False + assert self._reactions_detected is False + assert self._reactions_selected is False + + assert ( + self._non_reactants_detected + is False + ) + + assert ( + self._non_reactants_selected + is False + ) + + monkeypatch.setattr( + cli_module, + "read_input", + fake_read_input, + ) + + monkeypatch.setattr( + cli_module, + "InputParser", + FakeInputParser, + ) + + monkeypatch.setattr( + ARXCLI, + "_save_input_json", + fake_save_input, + ) + + monkeypatch.setattr( + ARXCLI, + "_save_rdkit_img", + fake_save_image, + ) + + monkeypatch.setattr( + ARXCLI, + "_ensure_reactions_detected", + fake_ensure_reactions, + ) + + cli = ARXCLI(input_path) + + assert cli.input == input_path + assert cli.session is session + + assert ( + cli.img_dir + == session.images_dir + ) + + assert read_calls == [ + input_path.resolve() + ] + + assert saved_input_paths == [ + input_path.resolve() + ] + + assert saved_images == [ + ( + fake_monomer_image, + session.images_dir + / "monomers.png", + False, + ) + ] + + assert ensure_calls == [ + True + ] + + assert cli.error_handler == { + "select_reactions": False, + "select_non_reactants": False, + "process": False, + } + + +def test_arxcli_instances_do_not_share_waterfall_state( + tmp_path, + monkeypatch, +): + input_1 = tmp_path / "one.json" + input_2 = tmp_path / "two.json" + + session_1 = SimpleNamespace( + output_dir=tmp_path / "out1", + images_dir=tmp_path / "out1" / "images", + ) + + session_2 = SimpleNamespace( + output_dir=tmp_path / "out2", + images_dir=tmp_path / "out2" / "images", + ) + + sessions = iter( + [ + session_1, + session_2, + ] + ) + + monkeypatch.setattr( + cli_module, + "read_input", + lambda path: next(sessions), + ) + + class FakeInputParser: + def initial_molecules_image_grid( + self, + session, + ): + return object() + + monkeypatch.setattr( + cli_module, + "InputParser", + FakeInputParser, + ) + + monkeypatch.setattr( + ARXCLI, + "_save_input_json", + lambda self, path: None, + ) + + monkeypatch.setattr( + ARXCLI, + "_save_rdkit_img", + lambda self, image, path, + is_non_reactant=False: None, + ) + + monkeypatch.setattr( + ARXCLI, + "_ensure_reactions_detected", + lambda self: None, + ) + + cli_1 = ARXCLI(input_1) + cli_2 = ARXCLI(input_2) + + cli_1.error_handler[ + "select_reactions" + ] = True + + assert ( + cli_2.error_handler[ + "select_reactions" + ] + is False + ) + + +# ============================================================================= +# show_molecules +# ============================================================================= + + +def test_show_molecules_delegates_to_input_parser( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + expected = object() + calls = [] + + class FakeInputParser: + def initial_molecules_image_grid( + self, + session, + ): + calls.append(session) + return expected + + monkeypatch.setattr( + cli_module, + "InputParser", + FakeInputParser, + ) + + result = cli.show_molecules() + + assert result is expected + assert calls == [ + cli.session + ] + + +# ============================================================================= +# show_functional_groups +# ============================================================================= + + +def test_show_functional_groups_triggers_detection_when_needed( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + expected = object() + ensure_calls = [] + + def fake_ensure(): + ensure_calls.append(True) + cli._fg_detected = True + + monkeypatch.setattr( + cli, + "_ensure_fg_detected", + fake_ensure, + ) + + class FakeDetector: + def functional_group_highlighted_molecules_image_grid( + self, + session, + ): + assert session is cli.session + return expected + + monkeypatch.setattr( + cli_module, + "FunctionalGroupsDetector", + FakeDetector, + ) + + result = cli.show_functional_groups() + + assert result is expected + assert ensure_calls == [ + True + ] + + +def test_show_functional_groups_does_not_redetect_when_already_detected( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli._fg_detected = True + + ensure_calls = [] + + monkeypatch.setattr( + cli, + "_ensure_fg_detected", + lambda: ensure_calls.append(True), + ) + + expected = object() + + class FakeDetector: + def functional_group_highlighted_molecules_image_grid( + self, + session, + ): + return expected + + monkeypatch.setattr( + cli_module, + "FunctionalGroupsDetector", + FakeDetector, + ) + + result = cli.show_functional_groups() + + assert result is expected + assert ensure_calls == [] + + +# ============================================================================= +# show_reactions +# ============================================================================= + + +def test_show_reactions_triggers_detection_when_needed( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + expected = object() + ensure_calls = [] + + def fake_ensure(): + ensure_calls.append(True) + cli._reactions_detected = True + + monkeypatch.setattr( + cli, + "_ensure_reactions_detected", + fake_ensure, + ) + + class FakeDetector: + def available_reaction_image_grid( + self, + session, + ): + assert session is cli.session + return expected + + monkeypatch.setattr( + cli_module, + "ReactionDetector", + FakeDetector, + ) + + result = cli.show_reactions() + + assert result is expected + assert ensure_calls == [ + True + ] + + +def test_show_reactions_does_not_redetect_when_already_detected( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli._reactions_detected = True + + ensure_calls = [] + + monkeypatch.setattr( + cli, + "_ensure_reactions_detected", + lambda: ensure_calls.append(True), + ) + + expected = object() + + class FakeDetector: + def available_reaction_image_grid( + self, + session, + ): + return expected + + monkeypatch.setattr( + cli_module, + "ReactionDetector", + FakeDetector, + ) + + result = cli.show_reactions() + + assert result is expected + assert ensure_calls == [] + + +# ============================================================================= +# select_reactions +# ============================================================================= + + +def test_select_reactions_ensures_detection_first( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli.session.reaction_instances = [ + object() + ] + + calls = [] + + def fake_ensure(): + calls.append("detect") + cli._reactions_detected = True + + monkeypatch.setattr( + cli, + "_ensure_reactions_detected", + fake_ensure, + ) + + class FakeDetector: + def reaction_selection( + self, + session, + ): + assert session is cli.session + calls.append("select") + + monkeypatch.setattr( + cli_module, + "ReactionDetector", + FakeDetector, + ) + + cli.select_reactions() + + assert calls == [ + "detect", + "select", + ] + + assert cli._reactions_selected is True + + assert ( + cli.error_handler[ + "select_reactions" + ] + is True + ) + + +def test_select_reactions_raises_when_none_detected( + tmp_path, +): + cli = make_cli(tmp_path) + + cli._reactions_detected = True + cli.session.reaction_instances = [] + + with pytest.raises( + RuntimeError, + match="No reactions detected", + ): + cli.select_reactions() + + assert ( + cli._reactions_selected + is False + ) + + assert ( + cli.error_handler[ + "select_reactions" + ] + is False + ) + + +def test_select_reactions_is_idempotent( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli._reactions_detected = True + cli._reactions_selected = True + + cli.session.reaction_instances = [ + object() + ] + + calls = [] + + class FakeDetector: + def reaction_selection( + self, + session, + ): + calls.append(True) + + monkeypatch.setattr( + cli_module, + "ReactionDetector", + FakeDetector, + ) + + cli.select_reactions() + cli.select_reactions() + + assert calls == [] + + +# ============================================================================= +# show_non_reactants +# ============================================================================= + + +def test_show_non_reactants_returns_none_when_no_visualization( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + ensure_calls = [] + save_calls = [] + + monkeypatch.setattr( + cli, + "_ensure_non_reactants_detected", + lambda: ensure_calls.append(True), + ) + + class FakeDetector: + def non_reactants_to_visualization( + self, + session, + ): + assert session is cli.session + return None + + monkeypatch.setattr( + cli_module, + "NonReactantsDetector", + FakeDetector, + ) + + monkeypatch.setattr( + cli, + "_save_rdkit_img", + lambda *args, **kwargs: + save_calls.append(True), + ) + + result = cli.show_non_reactants() + + assert result is None + + assert ensure_calls == [ + True + ] + + assert save_calls == [] + + +def test_show_non_reactants_saves_visualization( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + image = object() + saved = [] + + monkeypatch.setattr( + cli, + "_ensure_non_reactants_detected", + lambda: None, + ) + + class FakeDetector: + def non_reactants_to_visualization( + self, + session, + ): + return image + + monkeypatch.setattr( + cli_module, + "NonReactantsDetector", + FakeDetector, + ) + + def fake_save( + img, + path, + is_non_reactant=False, + ): + saved.append( + ( + img, + Path(path), + is_non_reactant, + ) + ) + + monkeypatch.setattr( + cli, + "_save_rdkit_img", + fake_save, + ) + + result = cli.show_non_reactants() + + assert result is image + + assert saved == [ + ( + image, + cli.img_dir + / "non_reactants.png", + True, + ) + ] + + +# ============================================================================= +# select_non_reactants +# ============================================================================= + + +def test_select_non_reactants_calls_selection_when_candidates_exist( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli.session.non_reactants = [ + object() + ] + + calls = [] + + monkeypatch.setattr( + cli, + "_ensure_non_reactants_detected", + lambda: calls.append("detect"), + ) + + class FakeDetector: + def non_reactant_selection( + self, + session, + ): + assert session is cli.session + calls.append("select") + + monkeypatch.setattr( + cli_module, + "NonReactantsDetector", + FakeDetector, + ) + + cli.select_non_reactants() + + assert calls == [ + "detect", + "select", + ] + + assert ( + cli._non_reactants_selected + is True + ) + + assert ( + cli.error_handler[ + "select_non_reactants" + ] + is True + ) + + +def test_select_non_reactants_completes_when_none_exist( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli.session.non_reactants = [] + + selection_calls = [] + + monkeypatch.setattr( + cli, + "_ensure_non_reactants_detected", + lambda: None, + ) + + class FakeDetector: + def non_reactant_selection( + self, + session, + ): + selection_calls.append(True) + + monkeypatch.setattr( + cli_module, + "NonReactantsDetector", + FakeDetector, + ) + + cli.select_non_reactants() + + assert selection_calls == [] + + assert ( + cli._non_reactants_selected + is True + ) + + assert ( + cli.error_handler[ + "select_non_reactants" + ] + is True + ) + + +def test_select_non_reactants_is_idempotent( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli._non_reactants_selected = True + cli.session.non_reactants = [ + object() + ] + + calls = [] + + monkeypatch.setattr( + cli, + "_ensure_non_reactants_detected", + lambda: calls.append("detect"), + ) + + class FakeDetector: + def non_reactant_selection( + self, + session, + ): + calls.append("select") + + monkeypatch.setattr( + cli_module, + "NonReactantsDetector", + FakeDetector, + ) + + cli.select_non_reactants() + + # Detection helper is called first by the current implementation, + # but selection itself must not happen again. + assert calls == [ + "detect" + ] + + +# ============================================================================= +# prepare_reactions +# ============================================================================= + + +def test_prepare_reactions_delegates_and_marks_process_complete( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + calls = [] + + class FakePrepareReactions: + def __init__( + self, + session, + ): + assert session is cli.session + calls.append("init") + + def prepare_reactions( + self, + session, + ): + assert session is cli.session + calls.append("prepare") + + monkeypatch.setattr( + cli_module, + "PrepareReactions", + FakePrepareReactions, + ) + + result = cli.prepare_reactions() + + assert result is None + + assert calls == [ + "init", + "prepare", + ] + + assert ( + cli.error_handler["process"] + is True + ) + + +def test_show_reaction_templates_delegates_highlight_type( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + expected = object() + calls = [] + + class FakePrepareReactions: + def __init__( + self, + session, + ): + assert session is cli.session + + def reaction_templates_highlighted_image_grid( + self, + session, + highlight_type, + ): + calls.append( + ( + session, + highlight_type, + ) + ) + return expected + + monkeypatch.setattr( + cli_module, + "PrepareReactions", + FakePrepareReactions, + ) + + result = cli.show_reaction_templates( + highlight_type="edge" + ) + + assert result is expected + + assert calls == [ + ( + cli.session, + "edge", + ) + ] + + +# ============================================================================= +# process guards +# ============================================================================= + + +def test_process_requires_reaction_selection( + tmp_path, +): + cli = make_cli(tmp_path) + + with pytest.raises( + RuntimeError, + match="Reactions have not been selected", + ): + cli.process() + + +def test_process_requires_non_reactant_selection( + tmp_path, +): + cli = make_cli(tmp_path) + + cli.error_handler[ + "select_reactions" + ] = True + + with pytest.raises( + RuntimeError, + match="Non-reactants have not been selected", + ): + cli.process() + + +def test_process_requires_reaction_preparation( + tmp_path, +): + cli = make_cli(tmp_path) + + cli.error_handler[ + "select_reactions" + ] = True + + cli.error_handler[ + "select_non_reactants" + ] = True + + with pytest.raises( + RuntimeError, + match="Processing has not been completed", + ): + cli.process() + + +# ============================================================================= +# process pipeline +# ============================================================================= + + +def test_process_runs_pipeline_in_correct_order( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli.error_handler[ + "select_reactions" + ] = True + + cli.error_handler[ + "select_non_reactants" + ] = True + + cli.error_handler[ + "process" + ] = True + + calls = [] + + @contextmanager + def fake_writer( + filename="AutoREACTER.log", + ): + calls.append("writer_enter") + yield + calls.append("writer_exit") + + monkeypatch.setattr( + cli, + "_writer", + fake_writer, + ) + + class FakeMolecule3DPreparation: + def __init__( + self, + session, + ): + assert session is cli.session + + def prepare_molecule_3d_geometry( + self, + session, + ): + assert session is cli.session + calls.append("3d") + + class FakeFFWrapper: + def __init__( + self, + session, + ): + assert session is cli.session + + def generate_force_field_files( + self, + session, + ): + assert session is cli.session + calls.append("ff") + + class FakeREACTERFilesBuilder: + def __init__( + self, + session, + ): + assert session is cli.session + + def molecule_template_preparation( + self, + session, + ): + assert session is cli.session + calls.append("reacter") + + class FakeSimulationSetupManager: + def setup_and_write_simulation( + self, + session, + ): + assert session is cli.session + calls.append("simulation") + + class FakePrepareReactions: + def __init__( + self, + session, + ): + assert session is cli.session + + def reaction_templates_highlighted_image_grid( + self, + session, + highlight_type, + ): + assert session is cli.session + + calls.append( + f"highlight:{highlight_type}" + ) + + return ( + f"image-{highlight_type}" + ) + + monkeypatch.setattr( + cli_module, + "Molecule3DPreparation", + FakeMolecule3DPreparation, + ) + + monkeypatch.setattr( + cli_module, + "FFWrapper", + FakeFFWrapper, + ) + + monkeypatch.setattr( + cli_module, + "REACTERFilesBuilder", + FakeREACTERFilesBuilder, + ) + + monkeypatch.setattr( + cli_module, + "SimulationSetupManager", + FakeSimulationSetupManager, + ) + + monkeypatch.setattr( + cli_module, + "PrepareReactions", + FakePrepareReactions, + ) + + def fake_save( + image, + path, + is_non_reactant=False, + ): + calls.append( + f"save:{Path(path).name}" + ) + + monkeypatch.setattr( + cli, + "_save_rdkit_img", + fake_save, + ) + + cli.process() + + assert calls == [ + "writer_enter", + "3d", + "ff", + "reacter", + "simulation", + "highlight:template", + "save:templates_template.png", + "highlight:edge", + "save:templates_edge.png", + "highlight:initiators", + "save:templates_initiators.png", + "highlight:delete", + "save:templates_delete.png", + "writer_exit", + ] + + assert ( + cli.error_handler["process"] + is True + ) + + +# ============================================================================= +# _save_input_json +# ============================================================================= + + +def test_save_input_json_copies_to_output_directory( + tmp_path, +): + cli = make_cli(tmp_path) + + source = tmp_path / "original.json" + + source.write_text( + '{"hello": "world"}', + encoding="utf-8", + ) + + cli._save_input_json(source) + + destination = ( + cli.session.output_dir + / "input.json" + ) + + assert destination.exists() + + assert ( + destination.read_text( + encoding="utf-8" + ) + == '{"hello": "world"}' + ) + + +def test_save_input_json_overwrites_existing_copy( + tmp_path, +): + cli = make_cli(tmp_path) + + source = tmp_path / "source.json" + + source.write_text( + "new content", + encoding="utf-8", + ) + + destination = ( + cli.session.output_dir + / "input.json" + ) + + destination.write_text( + "old content", + encoding="utf-8", + ) + + cli._save_input_json(source) + + assert ( + destination.read_text( + encoding="utf-8" + ) + == "new content" + ) + + +# ============================================================================= +# _ensure_fg_detected +# ============================================================================= + + +def test_ensure_fg_detected_runs_detector_once( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + calls = [] + + class FakeDetector: + def functional_groups_detector( + self, + session, + ): + assert session is cli.session + calls.append("detect") + + monkeypatch.setattr( + cli_module, + "FunctionalGroupsDetector", + FakeDetector, + ) + + cli._ensure_fg_detected() + cli._ensure_fg_detected() + + assert calls == [ + "detect" + ] + + assert cli._fg_detected is True + + +def test_ensure_fg_detected_sets_flag_only_after_success( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + class FakeDetector: + def functional_groups_detector( + self, + session, + ): + raise RuntimeError( + "detector failed" + ) + + monkeypatch.setattr( + cli_module, + "FunctionalGroupsDetector", + FakeDetector, + ) + + with pytest.raises( + RuntimeError, + match="detector failed", + ): + cli._ensure_fg_detected() + + assert cli._fg_detected is False + + +# ============================================================================= +# _ensure_reactions_detected +# ============================================================================= + + +def test_ensure_reactions_detected_runs_reaction_detection_once( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + calls = [] + saved = [] + + fg_image = object() + reaction_image = object() + + class FakeFGDetector: + def functional_groups_detector( + self, + session, + ): + calls.append("fg_detect") + + def functional_group_highlighted_molecules_image_grid( + self, + session, + ): + calls.append("fg_image") + return fg_image + + class FakeReactionDetector: + def reaction_detector( + self, + session, + ): + calls.append("reaction_detect") + + def available_reaction_image_grid( + self, + session, + ): + calls.append("reaction_image") + return reaction_image + + monkeypatch.setattr( + cli_module, + "FunctionalGroupsDetector", + FakeFGDetector, + ) + + monkeypatch.setattr( + cli_module, + "ReactionDetector", + FakeReactionDetector, + ) + + def fake_save( + image, + path, + is_non_reactant=False, + ): + saved.append( + ( + image, + Path(path).name, + ) + ) + + monkeypatch.setattr( + cli, + "_save_rdkit_img", + fake_save, + ) + + cli._ensure_reactions_detected() + cli._ensure_reactions_detected() + + assert calls.count( + "fg_detect" + ) == 1 + + assert calls.count( + "reaction_detect" + ) == 1 + + assert calls.count( + "reaction_image" + ) == 1 + + # Current implementation regenerates/saves the FG visualization + # whenever this private helper is called, even after reaction detection + # has already completed. Reaction detection itself remains idempotent. + assert calls.count( + "fg_image" + ) == 2 + + assert cli._fg_detected is True + + assert ( + cli._reactions_detected + is True + ) + + assert ( + ( + reaction_image, + "reactions.png", + ) + in saved + ) + + +def test_ensure_reactions_detected_does_not_mark_success_after_detector_error( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + class FakeFGDetector: + def functional_groups_detector( + self, + session, + ): + pass + + def functional_group_highlighted_molecules_image_grid( + self, + session, + ): + return object() + + class FakeReactionDetector: + def reaction_detector( + self, + session, + ): + raise RuntimeError( + "reaction failure" + ) + + monkeypatch.setattr( + cli_module, + "FunctionalGroupsDetector", + FakeFGDetector, + ) + + monkeypatch.setattr( + cli_module, + "ReactionDetector", + FakeReactionDetector, + ) + + monkeypatch.setattr( + cli, + "_save_rdkit_img", + lambda *args, **kwargs: None, + ) + + with pytest.raises( + RuntimeError, + match="reaction failure", + ): + cli._ensure_reactions_detected() + + assert cli._fg_detected is True + + assert ( + cli._reactions_detected + is False + ) + + +# ============================================================================= +# _ensure_non_reactants_detected +# ============================================================================= + + +def test_ensure_non_reactants_detected_selects_reactions_first( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + calls = [] + + def fake_select_reactions(): + calls.append("select_reactions") + cli._reactions_selected = True + + monkeypatch.setattr( + cli, + "select_reactions", + fake_select_reactions, + ) + + class FakeDetector: + def non_monomer_detector( + self, + session, + ): + assert session is cli.session + calls.append( + "detect_non_reactants" + ) + + monkeypatch.setattr( + cli_module, + "NonReactantsDetector", + FakeDetector, + ) + + cli._ensure_non_reactants_detected() + + assert calls == [ + "select_reactions", + "detect_non_reactants", + ] + + assert ( + cli._non_reactants_detected + is True + ) + + +def test_ensure_non_reactants_detected_is_idempotent( + tmp_path, + monkeypatch, +): + cli = make_cli(tmp_path) + + cli._reactions_selected = True + + calls = [] + + class FakeDetector: + def non_monomer_detector( + self, + session, + ): + calls.append(True) + + monkeypatch.setattr( + cli_module, + "NonReactantsDetector", + FakeDetector, + ) + + cli._ensure_non_reactants_detected() + cli._ensure_non_reactants_detected() + + assert calls == [ + True + ] + + +# ============================================================================= +# _save_rdkit_img +# ============================================================================= + + +def test_save_rdkit_img_creates_parent_directories( + tmp_path, +): + cli = make_cli(tmp_path) + + image = PILImage.new( + "RGB", + (2, 2), + ) + + path = ( + tmp_path + / "nested" + / "more" + / "image.png" + ) + + cli._save_rdkit_img( + image, + path, + ) + + assert path.exists() + + +def test_save_rdkit_img_saves_pil_image( + tmp_path, +): + cli = make_cli(tmp_path) + + image = PILImage.new( + "RGB", + (3, 3), + ) + + path = tmp_path / "image.png" + + cli._save_rdkit_img( + image, + path, + ) + + assert path.exists() + + loaded = PILImage.open(path) + + assert loaded.size == ( + 3, + 3, + ) + + +@pytest.mark.parametrize( + "data", + [ + b"\x89PNGtest", + bytearray(b"\x89PNGtest"), + ], +) +def test_save_rdkit_img_writes_raw_bytes( + tmp_path, + data, +): + cli = make_cli(tmp_path) + + path = tmp_path / "raw.bin" + + cli._save_rdkit_img( + data, + path, + ) + + assert ( + path.read_bytes() + == bytes(data) + ) + + +def test_save_rdkit_img_writes_image_data_bytes( + tmp_path, +): + cli = make_cli(tmp_path) + + image = SimpleNamespace( + data=b"image-data" + ) + + path = tmp_path / "image.bin" + + cli._save_rdkit_img( + image, + path, + ) + + assert ( + path.read_bytes() + == b"image-data" + ) + + +def test_save_rdkit_img_writes_image_data_string( + tmp_path, +): + cli = make_cli(tmp_path) + + image = SimpleNamespace( + data="hello" + ) + + path = tmp_path / "image.svg" + + cli._save_rdkit_img( + image, + path, + ) + + assert ( + path.read_text( + encoding="utf-8" + ) + == "hello" + ) + + +def test_save_rdkit_img_writes_direct_svg_string( + tmp_path, +): + cli = make_cli(tmp_path) + + path = tmp_path / "image.svg" + + cli._save_rdkit_img( + "direct", + path, + ) + + assert ( + path.read_text( + encoding="utf-8" + ) + == "direct" + ) + + +def test_save_rdkit_img_allows_none_for_non_reactants( + tmp_path, +): + cli = make_cli(tmp_path) + + path = tmp_path / "none.png" + + result = cli._save_rdkit_img( + None, + path, + is_non_reactant=True, + ) + + assert result is None + assert not path.exists() + + +def test_save_rdkit_img_rejects_none_for_required_image( + tmp_path, +): + cli = make_cli(tmp_path) + + with pytest.raises( + NoReactionGenerated, + match="No reaction was generated", + ): + cli._save_rdkit_img( + None, + tmp_path / "missing.png", + ) + + +def test_save_rdkit_img_rejects_unsupported_type( + tmp_path, +): + cli = make_cli(tmp_path) + + with pytest.raises( + TypeError, + match="Unsupported image type", + ): + cli._save_rdkit_img( + 12345, + tmp_path / "bad.png", + ) + + +# ============================================================================= +# _writer +# ============================================================================= + + +def test_writer_writes_python_and_os_output_to_log( + tmp_path, + capfd, +): + cli = make_cli(tmp_path) + + with cli._writer(): + print( + "python-output", + flush=True, + ) + + os.write( + 1, + b"os-output\n", + ) + + log_path = ( + cli.session.output_dir + / "AutoREACTER.log" + ) + + log_text = log_path.read_text( + encoding="utf-8" + ) + + assert "python-output" in log_text + assert "os-output" in log_text + + terminal_output = ( + capfd.readouterr().out + ) + + assert "python-output" in terminal_output + assert "os-output" in terminal_output + + +def test_writer_supports_custom_filename( + tmp_path, +): + cli = make_cli(tmp_path) + + with cli._writer( + "custom.log" + ): + print( + "custom-output", + flush=True, + ) + + log_path = ( + cli.session.output_dir + / "custom.log" + ) + + assert log_path.exists() + + assert ( + "custom-output" + in log_path.read_text( + encoding="utf-8" + ) + ) + + +def test_writer_restores_stdout_after_exception( + tmp_path, + capfd, +): + cli = make_cli(tmp_path) + + with pytest.raises( + RuntimeError, + match="boom", + ): + with cli._writer( + "exception.log" + ): + print( + "before-exception", + flush=True, + ) + + raise RuntimeError( + "boom" + ) + + print( + "after-exception", + flush=True, + ) + + terminal_output = ( + capfd.readouterr().out + ) + + assert ( + "after-exception" + in terminal_output + ) + + log_path = ( + cli.session.output_dir + / "exception.log" + ) + + log_text = log_path.read_text( + encoding="utf-8" + ) + + assert ( + "before-exception" + in log_text + ) + + assert ( + "after-exception" + not in log_text + ) + + +def test_writer_appends_to_existing_log( + tmp_path, +): + cli = make_cli(tmp_path) + + with cli._writer(): + print( + "first-run", + flush=True, + ) + + with cli._writer(): + print( + "second-run", + flush=True, + ) + + log_path = ( + cli.session.output_dir + / "AutoREACTER.log" + ) + + log_text = log_path.read_text( + encoding="utf-8" + ) + + assert "first-run" in log_text + assert "second-run" in log_text + + +# ============================================================================= +# __repr__ +# ============================================================================= + + +def test_repr_with_input_path( + tmp_path, +): + cli = ARXCLI.__new__( + ARXCLI + ) + + cli.input = ( + tmp_path / "input.json" + ) + + assert repr(cli) == ( + f"ARXCLI(input={cli.input})" + ) + + +def test_repr_without_input(): + cli = ARXCLI.__new__( + ARXCLI + ) + + assert repr(cli) == "ARXCLI()" \ No newline at end of file From 412fac437fa4f8dbe089e56023f13b8686d15775 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:14:42 -0400 Subject: [PATCH 143/176] Improve stdout capture in ARXCLI --- AutoREACTER/arx_cli.py | 165 ++++++++++++++---- .../build_reaction_system.py | 1 - 2 files changed, 133 insertions(+), 33 deletions(-) delete mode 100644 AutoREACTER/reaction_preparation/build_reaction_system.py diff --git a/AutoREACTER/arx_cli.py b/AutoREACTER/arx_cli.py index cef2b1b2..569ad171 100644 --- a/AutoREACTER/arx_cli.py +++ b/AutoREACTER/arx_cli.py @@ -445,59 +445,160 @@ def _writer(self, filename="AutoREACTER.log"): self.session.output_dir.mkdir(parents=True, exist_ok=True) log_path = self.session.output_dir / filename - # 1. Save the original OS-level terminal output + # Save both Python's stdout object and the original OS-level stdout. + # + # These are not always the same destination. For example, pytest, + # Jupyter, and other environments may replace sys.stdout with their + # own wrapper while file descriptor 1 still exists separately. + original_stdout = sys.stdout original_stdout_fd = os.dup(1) - # 2. Create an OS-level pipe (a temporary tunnel for our data) + # Create an OS-level pipe. Both Python print() output and raw fd-1 + # output will be redirected into this pipe. pipe_read_fd, pipe_write_fd = os.pipe() + redirected_stdout = None + + def write_to_original_stdout(data: bytes) -> None: + """ + Forward captured output back to the original visible stdout. + + If the original Python stdout directly represents fd 1, write to + the saved duplicate of fd 1. Otherwise, use the original Python + stdout object so capture systems such as pytest/Jupyter still see + the output. + """ + try: + original_fileno = original_stdout.fileno() + except (AttributeError, OSError, ValueError): + original_fileno = None + + if original_fileno == 1: + os.write(original_stdout_fd, data) + return + + text = data.decode( + "utf-8", + errors="replace", + ) + + original_stdout.write(text) + original_stdout.flush() + def tee_thread(): - """Background worker that reads the pipe and writes to both destinations.""" - with open(log_path, 'a') as log_file: + """ + Background worker that reads the pipe and writes to both + the original output destination and the log file. + """ + with open( + log_path, + "a", + encoding="utf-8", + ) as log_file: while True: # Read incoming data from the pipe - data = os.read(pipe_read_fd, 1024) - + data = os.read( + pipe_read_fd, + 1024, + ) + # If the pipe is closed, stop the thread if not data: break - - # Write to the actual terminal - os.write(original_stdout_fd, data) - + + # Write to the original terminal / stdout capture + write_to_original_stdout( + data + ) + # Write to the log file - log_file.write(data.decode('utf-8', errors='replace')) + log_file.write( + data.decode( + "utf-8", + errors="replace", + ) + ) log_file.flush() - # 3. Start the background thread - thread = threading.Thread(target=tee_thread) + # Start the background tee worker + thread = threading.Thread( + target=tee_thread + ) thread.start() - # Flush Python's buffers before we switch the tracks - sys.stdout.flush() + # Flush Python's current stdout before changing destinations + original_stdout.flush() try: - # 4. Redirect all OS-level output to the write-end of our pipe - os.dup2(pipe_write_fd, 1) + # Redirect OS-level stdout (fd 1) into the pipe. + # + # This captures subprocess output, os.write(1, ...), native + # library output, and anything else that writes directly to + # standard output. + os.dup2( + pipe_write_fd, + 1, + ) + + # Redirect Python's sys.stdout explicitly as well. + # + # This is necessary because environments such as pytest and + # Jupyter can replace sys.stdout with an object that does not + # automatically follow changes made to file descriptor 1. + redirected_stdout = os.fdopen( + os.dup(1), + "w", + buffering=1, + encoding=getattr( + original_stdout, + "encoding", + None, + ) + or "utf-8", + errors="replace", + ) + + sys.stdout = redirected_stdout + yield - + finally: - # Flush Python buffers one last time - sys.stdout.flush() - - # 5. Restore the original terminal output - os.dup2(original_stdout_fd, 1) - - # 6. Close the write end of the pipe (this tells the thread to stop) - os.close(pipe_write_fd) - - # 7. Wait for the thread to finish processing the last bits of data + # Flush all pending Python output into the pipe + if redirected_stdout is not None: + redirected_stdout.flush() + + # Restore Python's original stdout object first + sys.stdout = original_stdout + + # Close the duplicated Python pipe writer + if redirected_stdout is not None: + redirected_stdout.close() + + # Restore OS-level stdout + os.dup2( + original_stdout_fd, + 1, + ) + + # Close the original pipe write descriptor. + # + # Once every write descriptor pointing at the pipe is closed, + # the background thread receives EOF and exits. + os.close( + pipe_write_fd + ) + + # Wait until the final buffered output has been copied thread.join() - - # 8. Clean up remaining file descriptors - os.close(pipe_read_fd) - os.close(original_stdout_fd) + # Clean up remaining file descriptors + os.close( + pipe_read_fd + ) + + os.close( + original_stdout_fd + ) # ------------------------------------------------------------------ # Magic Methods # ------------------------------------------------------------------ diff --git a/AutoREACTER/reaction_preparation/build_reaction_system.py b/AutoREACTER/reaction_preparation/build_reaction_system.py deleted file mode 100644 index 8b6ce963..00000000 --- a/AutoREACTER/reaction_preparation/build_reaction_system.py +++ /dev/null @@ -1 +0,0 @@ -# WILL BE NEW PLACE HOLDER FOR Main.py helper functions, NOT TO BE DELETED \ No newline at end of file From cb719ff31fe84601e21fcadfe980d274425d163d Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:18:13 -0400 Subject: [PATCH 144/176] Export session in public API --- AutoREACTER/__init__.py | 3 +- tests/unit/__init__.py | 1013 +++++++++++++++++++++++++++++++++ tests/unit/test_public_api.py | 1013 +++++++++++++++++++++++++++++++++ 3 files changed, 2028 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_public_api.py diff --git a/AutoREACTER/__init__.py b/AutoREACTER/__init__.py index 0a0bf2cb..72f7c450 100644 --- a/AutoREACTER/__init__.py +++ b/AutoREACTER/__init__.py @@ -304,6 +304,7 @@ def process() -> None: "__authors__", "__license__", "run", + "session", "show_molecules", "show_functional_groups", "show_reactions", @@ -313,4 +314,4 @@ def process() -> None: "prepare_reactions", "show_reaction_templates", "process", -] +] \ No newline at end of file diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py index e69de29b..76c137ec 100644 --- a/tests/unit/__init__.py +++ b/tests/unit/__init__.py @@ -0,0 +1,1013 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER as arx + + +# ============================================================================= +# Fixtures / helpers +# ============================================================================= + + +@pytest.fixture(autouse=True) +def reset_active_workflow(monkeypatch): + """ + Every test starts without an active global workflow. + + AutoREACTER intentionally keeps one package-level active workflow, so + isolating this state prevents tests from affecting one another. + """ + monkeypatch.setattr( + arx, + "_active_workflow", + None, + ) + + +class FakeWorkflow: + """ + Lightweight ARXCLI-like object used to verify public API delegation. + """ + + def __init__(self): + self.session = object() + self.calls = [] + + def show_molecules(self): + self.calls.append( + ("show_molecules",) + ) + return "molecules-image" + + def show_functional_groups(self): + self.calls.append( + ("show_functional_groups",) + ) + return "functional-groups-image" + + def show_reactions(self): + self.calls.append( + ("show_reactions",) + ) + return "reactions-image" + + def select_reactions(self): + self.calls.append( + ("select_reactions",) + ) + return None + + def show_non_reactants(self): + self.calls.append( + ("show_non_reactants",) + ) + return "non-reactants-image" + + def select_non_reactants(self): + self.calls.append( + ("select_non_reactants",) + ) + return None + + def prepare_reactions(self): + self.calls.append( + ("prepare_reactions",) + ) + return None + + def show_reaction_templates( + self, + highlight_type="template", + ): + self.calls.append( + ( + "show_reaction_templates", + highlight_type, + ) + ) + + return ( + f"templates-{highlight_type}" + ) + + def process(self): + self.calls.append( + ("process",) + ) + return None + + +def install_fake_workflow( + monkeypatch, +): + workflow = FakeWorkflow() + + monkeypatch.setattr( + arx, + "_active_workflow", + workflow, + ) + + return workflow + + +# ============================================================================= +# Package metadata +# ============================================================================= + + +def test_package_title(): + assert arx.__title__ == "AutoREACTER" + + +def test_package_version(): + assert arx.__version__ == "0.3" + + +def test_package_release_matches_version(): + assert ( + arx.__release__ + == arx.__version__ + ) + + +def test_package_license(): + assert arx.__license__ == "MIT" + + +def test_package_authors(): + assert arx.__authors__ == [ + "Janitha Mahanthe", + "Jacob Gissinger", + ] + + +def test_package_author_string_matches_authors(): + assert ( + arx.__author__ + == ", ".join(arx.__authors__) + ) + + +# ============================================================================= +# _ensure_workflow +# ============================================================================= + + +def test_ensure_workflow_raises_without_active_session(): + with pytest.raises( + RuntimeError, + match="No active session", + ): + arx._ensure_workflow() + + +def test_ensure_workflow_error_tells_user_to_call_run(): + with pytest.raises(RuntimeError) as exc_info: + arx._ensure_workflow() + + message = str(exc_info.value) + + assert "arx.run" in message + assert "your_file.json" in message + + +def test_ensure_workflow_returns_active_workflow( + monkeypatch, +): + workflow = object() + + monkeypatch.setattr( + arx, + "_active_workflow", + workflow, + ) + + assert ( + arx._ensure_workflow() + is workflow + ) + + +# ============================================================================= +# session() +# ============================================================================= + + +def test_session_requires_active_workflow(): + with pytest.raises( + RuntimeError, + match="No active session", + ): + arx.session() + + +def test_session_returns_active_workflow_session( + monkeypatch, +): + workflow = FakeWorkflow() + + monkeypatch.setattr( + arx, + "_active_workflow", + workflow, + ) + + assert ( + arx.session() + is workflow.session + ) + + +# ============================================================================= +# run() +# ============================================================================= + + +def test_run_rejects_missing_input_file( + tmp_path, + monkeypatch, +): + constructed = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + constructed.append( + input_path + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + missing = ( + tmp_path + / "missing.json" + ) + + with pytest.raises( + FileNotFoundError, + match="Input file not found", + ): + arx.run(missing) + + assert constructed == [] + + assert ( + arx._active_workflow + is None + ) + + +def test_run_constructs_arxcli_with_resolved_path( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + received = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + received.append( + input_path + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + result = arx.run( + input_file + ) + + assert received == [ + input_file.resolve() + ] + + assert ( + result + is arx._active_workflow + ) + + +def test_run_accepts_string_path( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + received = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + received.append( + input_path + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + arx.run( + str(input_file) + ) + + assert received == [ + input_file.resolve() + ] + + assert isinstance( + received[0], + Path, + ) + + +def test_run_resolves_relative_path( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + monkeypatch.chdir( + tmp_path + ) + + received = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + received.append( + input_path + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + arx.run( + "input.json" + ) + + assert received == [ + input_file.resolve() + ] + + +def test_run_returns_created_workflow( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + created = object() + + monkeypatch.setattr( + arx, + "ARXCLI", + lambda path: created, + ) + + result = arx.run( + input_file + ) + + assert result is created + + assert ( + arx._active_workflow + is created + ) + + +def test_run_replaces_existing_workflow( + tmp_path, + monkeypatch, +): + first_input = ( + tmp_path / "first.json" + ) + + second_input = ( + tmp_path / "second.json" + ) + + first_input.write_text( + "{}", + encoding="utf-8", + ) + + second_input.write_text( + "{}", + encoding="utf-8", + ) + + created = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + self.input_path = ( + input_path + ) + + created.append(self) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + first = arx.run( + first_input + ) + + second = arx.run( + second_input + ) + + assert first is created[0] + assert second is created[1] + + assert ( + arx._active_workflow + is second + ) + + assert ( + first is not second + ) + + +def test_run_does_not_replace_existing_workflow_if_new_construction_fails( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + existing = object() + + monkeypatch.setattr( + arx, + "_active_workflow", + existing, + ) + + class FailingARXCLI: + def __init__( + self, + input_path, + ): + raise RuntimeError( + "construction failed" + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FailingARXCLI, + ) + + with pytest.raises( + RuntimeError, + match="construction failed", + ): + arx.run(input_file) + + # Assignment happens only after successful ARXCLI construction. + assert ( + arx._active_workflow + is existing + ) + + +# ============================================================================= +# Delegation before run() +# ============================================================================= + + +@pytest.mark.parametrize( + "api_call", + [ + lambda: arx.show_molecules(), + lambda: arx.show_functional_groups(), + lambda: arx.show_reactions(), + lambda: arx.select_reactions(), + lambda: arx.show_non_reactants(), + lambda: arx.select_non_reactants(), + lambda: arx.prepare_reactions(), + lambda: arx.show_reaction_templates(), + lambda: arx.process(), + ], +) +def test_public_api_requires_run_first( + api_call, +): + with pytest.raises( + RuntimeError, + match="No active session", + ): + api_call() + + +# ============================================================================= +# Public API delegation +# ============================================================================= + + +def test_show_molecules_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = arx.show_molecules() + + assert ( + result + == "molecules-image" + ) + + assert workflow.calls == [ + ("show_molecules",) + ] + + +def test_show_functional_groups_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_functional_groups() + ) + + assert ( + result + == "functional-groups-image" + ) + + assert workflow.calls == [ + ("show_functional_groups",) + ] + + +def test_show_reactions_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = arx.show_reactions() + + assert ( + result + == "reactions-image" + ) + + assert workflow.calls == [ + ("show_reactions",) + ] + + +def test_select_reactions_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = arx.select_reactions() + + assert result is None + + assert workflow.calls == [ + ("select_reactions",) + ] + + +def test_show_non_reactants_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_non_reactants() + ) + + assert ( + result + == "non-reactants-image" + ) + + assert workflow.calls == [ + ("show_non_reactants",) + ] + + +def test_show_non_reactants_propagates_none( + monkeypatch, +): + workflow = FakeWorkflow() + + def return_none(): + workflow.calls.append( + ("show_non_reactants",) + ) + + return None + + workflow.show_non_reactants = ( + return_none + ) + + monkeypatch.setattr( + arx, + "_active_workflow", + workflow, + ) + + assert ( + arx.show_non_reactants() + is None + ) + + +def test_select_non_reactants_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.select_non_reactants() + ) + + assert result is None + + assert workflow.calls == [ + ("select_non_reactants",) + ] + + +def test_prepare_reactions_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.prepare_reactions() + ) + + assert result is None + + assert workflow.calls == [ + ("prepare_reactions",) + ] + + +def test_process_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = arx.process() + + assert result is None + + assert workflow.calls == [ + ("process",) + ] + + +# ============================================================================= +# show_reaction_templates() +# ============================================================================= + + +@pytest.mark.parametrize( + "highlight_type", + [ + "template", + "edge", + "initiators", + "delete", + ], +) +def test_show_reaction_templates_accepts_supported_types( + monkeypatch, + highlight_type, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_reaction_templates( + highlight_type + ) + ) + + assert result == ( + f"templates-{highlight_type}" + ) + + assert workflow.calls == [ + ( + "show_reaction_templates", + highlight_type, + ) + ] + + +@pytest.mark.parametrize( + "highlight_type, expected", + [ + ("TEMPLATE", "template"), + ("Edge", "edge"), + ("INITIATORS", "initiators"), + ("Delete", "delete"), + ], +) +def test_show_reaction_templates_is_case_insensitive( + monkeypatch, + highlight_type, + expected, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_reaction_templates( + highlight_type + ) + ) + + assert result == ( + f"templates-{expected}" + ) + + assert workflow.calls == [ + ( + "show_reaction_templates", + expected, + ) + ] + + +def test_show_reaction_templates_defaults_to_template( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_reaction_templates() + ) + + assert ( + result + == "templates-template" + ) + + assert workflow.calls == [ + ( + "show_reaction_templates", + "template", + ) + ] + + +def test_show_reaction_templates_none_defaults_to_template( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_reaction_templates( + None + ) + ) + + assert ( + result + == "templates-template" + ) + + assert workflow.calls == [ + ( + "show_reaction_templates", + "template", + ) + ] + + +@pytest.mark.parametrize( + "highlight_type", + [ + "", + "wrong", + "reaction", + "atoms", + "templates", + ], +) +def test_show_reaction_templates_rejects_invalid_type( + monkeypatch, + highlight_type, +): + workflow = install_fake_workflow( + monkeypatch + ) + + if highlight_type == "": + # Current API intentionally treats false-like/empty input + # as the default "template". + result = ( + arx.show_reaction_templates( + highlight_type + ) + ) + + assert ( + result + == "templates-template" + ) + + return + + with pytest.raises( + ValueError, + match="Invalid highlight_type", + ): + arx.show_reaction_templates( + highlight_type + ) + + # Validation occurs before delegation. + assert workflow.calls == [] + + +def test_show_reaction_templates_error_lists_allowed_values( + monkeypatch, +): + install_fake_workflow( + monkeypatch + ) + + with pytest.raises( + ValueError, + ) as exc_info: + arx.show_reaction_templates( + "bad" + ) + + message = str( + exc_info.value + ) + + assert "template" in message + assert "edge" in message + assert "initiators" in message + assert "delete" in message + + +# ============================================================================= +# __all__ / public export contract +# ============================================================================= + + +def test_public_all_contains_package_metadata(): + expected = { + "__title__", + "__version__", + "__release__", + "__authors__", + "__license__", + } + + assert expected.issubset( + set(arx.__all__) + ) + + +def test_public_all_contains_user_workflow_commands(): + expected = { + "run", + "show_molecules", + "show_functional_groups", + "show_reactions", + "select_reactions", + "show_non_reactants", + "select_non_reactants", + "prepare_reactions", + "show_reaction_templates", + "process", + } + + assert expected.issubset( + set(arx.__all__) + ) + + +def test_session_is_part_of_public_api(): + """ + session() is used directly by the documented/user-facing workflow: + + session = arx.session() + + Therefore it should be exported alongside the other public API helpers. + """ + assert "session" in arx.__all__ + + +def test_public_all_has_no_duplicates(): + assert len(arx.__all__) == len( + set(arx.__all__) + ) + + +def test_every_name_in_public_all_exists(): + for name in arx.__all__: + assert hasattr( + arx, + name, + ), ( + f"{name!r} appears in " + "__all__ but does not exist" + ) \ No newline at end of file diff --git a/tests/unit/test_public_api.py b/tests/unit/test_public_api.py new file mode 100644 index 00000000..76c137ec --- /dev/null +++ b/tests/unit/test_public_api.py @@ -0,0 +1,1013 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER as arx + + +# ============================================================================= +# Fixtures / helpers +# ============================================================================= + + +@pytest.fixture(autouse=True) +def reset_active_workflow(monkeypatch): + """ + Every test starts without an active global workflow. + + AutoREACTER intentionally keeps one package-level active workflow, so + isolating this state prevents tests from affecting one another. + """ + monkeypatch.setattr( + arx, + "_active_workflow", + None, + ) + + +class FakeWorkflow: + """ + Lightweight ARXCLI-like object used to verify public API delegation. + """ + + def __init__(self): + self.session = object() + self.calls = [] + + def show_molecules(self): + self.calls.append( + ("show_molecules",) + ) + return "molecules-image" + + def show_functional_groups(self): + self.calls.append( + ("show_functional_groups",) + ) + return "functional-groups-image" + + def show_reactions(self): + self.calls.append( + ("show_reactions",) + ) + return "reactions-image" + + def select_reactions(self): + self.calls.append( + ("select_reactions",) + ) + return None + + def show_non_reactants(self): + self.calls.append( + ("show_non_reactants",) + ) + return "non-reactants-image" + + def select_non_reactants(self): + self.calls.append( + ("select_non_reactants",) + ) + return None + + def prepare_reactions(self): + self.calls.append( + ("prepare_reactions",) + ) + return None + + def show_reaction_templates( + self, + highlight_type="template", + ): + self.calls.append( + ( + "show_reaction_templates", + highlight_type, + ) + ) + + return ( + f"templates-{highlight_type}" + ) + + def process(self): + self.calls.append( + ("process",) + ) + return None + + +def install_fake_workflow( + monkeypatch, +): + workflow = FakeWorkflow() + + monkeypatch.setattr( + arx, + "_active_workflow", + workflow, + ) + + return workflow + + +# ============================================================================= +# Package metadata +# ============================================================================= + + +def test_package_title(): + assert arx.__title__ == "AutoREACTER" + + +def test_package_version(): + assert arx.__version__ == "0.3" + + +def test_package_release_matches_version(): + assert ( + arx.__release__ + == arx.__version__ + ) + + +def test_package_license(): + assert arx.__license__ == "MIT" + + +def test_package_authors(): + assert arx.__authors__ == [ + "Janitha Mahanthe", + "Jacob Gissinger", + ] + + +def test_package_author_string_matches_authors(): + assert ( + arx.__author__ + == ", ".join(arx.__authors__) + ) + + +# ============================================================================= +# _ensure_workflow +# ============================================================================= + + +def test_ensure_workflow_raises_without_active_session(): + with pytest.raises( + RuntimeError, + match="No active session", + ): + arx._ensure_workflow() + + +def test_ensure_workflow_error_tells_user_to_call_run(): + with pytest.raises(RuntimeError) as exc_info: + arx._ensure_workflow() + + message = str(exc_info.value) + + assert "arx.run" in message + assert "your_file.json" in message + + +def test_ensure_workflow_returns_active_workflow( + monkeypatch, +): + workflow = object() + + monkeypatch.setattr( + arx, + "_active_workflow", + workflow, + ) + + assert ( + arx._ensure_workflow() + is workflow + ) + + +# ============================================================================= +# session() +# ============================================================================= + + +def test_session_requires_active_workflow(): + with pytest.raises( + RuntimeError, + match="No active session", + ): + arx.session() + + +def test_session_returns_active_workflow_session( + monkeypatch, +): + workflow = FakeWorkflow() + + monkeypatch.setattr( + arx, + "_active_workflow", + workflow, + ) + + assert ( + arx.session() + is workflow.session + ) + + +# ============================================================================= +# run() +# ============================================================================= + + +def test_run_rejects_missing_input_file( + tmp_path, + monkeypatch, +): + constructed = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + constructed.append( + input_path + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + missing = ( + tmp_path + / "missing.json" + ) + + with pytest.raises( + FileNotFoundError, + match="Input file not found", + ): + arx.run(missing) + + assert constructed == [] + + assert ( + arx._active_workflow + is None + ) + + +def test_run_constructs_arxcli_with_resolved_path( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + received = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + received.append( + input_path + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + result = arx.run( + input_file + ) + + assert received == [ + input_file.resolve() + ] + + assert ( + result + is arx._active_workflow + ) + + +def test_run_accepts_string_path( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + received = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + received.append( + input_path + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + arx.run( + str(input_file) + ) + + assert received == [ + input_file.resolve() + ] + + assert isinstance( + received[0], + Path, + ) + + +def test_run_resolves_relative_path( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + monkeypatch.chdir( + tmp_path + ) + + received = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + received.append( + input_path + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + arx.run( + "input.json" + ) + + assert received == [ + input_file.resolve() + ] + + +def test_run_returns_created_workflow( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + created = object() + + monkeypatch.setattr( + arx, + "ARXCLI", + lambda path: created, + ) + + result = arx.run( + input_file + ) + + assert result is created + + assert ( + arx._active_workflow + is created + ) + + +def test_run_replaces_existing_workflow( + tmp_path, + monkeypatch, +): + first_input = ( + tmp_path / "first.json" + ) + + second_input = ( + tmp_path / "second.json" + ) + + first_input.write_text( + "{}", + encoding="utf-8", + ) + + second_input.write_text( + "{}", + encoding="utf-8", + ) + + created = [] + + class FakeARXCLI: + def __init__( + self, + input_path, + ): + self.input_path = ( + input_path + ) + + created.append(self) + + monkeypatch.setattr( + arx, + "ARXCLI", + FakeARXCLI, + ) + + first = arx.run( + first_input + ) + + second = arx.run( + second_input + ) + + assert first is created[0] + assert second is created[1] + + assert ( + arx._active_workflow + is second + ) + + assert ( + first is not second + ) + + +def test_run_does_not_replace_existing_workflow_if_new_construction_fails( + tmp_path, + monkeypatch, +): + input_file = ( + tmp_path / "input.json" + ) + + input_file.write_text( + "{}", + encoding="utf-8", + ) + + existing = object() + + monkeypatch.setattr( + arx, + "_active_workflow", + existing, + ) + + class FailingARXCLI: + def __init__( + self, + input_path, + ): + raise RuntimeError( + "construction failed" + ) + + monkeypatch.setattr( + arx, + "ARXCLI", + FailingARXCLI, + ) + + with pytest.raises( + RuntimeError, + match="construction failed", + ): + arx.run(input_file) + + # Assignment happens only after successful ARXCLI construction. + assert ( + arx._active_workflow + is existing + ) + + +# ============================================================================= +# Delegation before run() +# ============================================================================= + + +@pytest.mark.parametrize( + "api_call", + [ + lambda: arx.show_molecules(), + lambda: arx.show_functional_groups(), + lambda: arx.show_reactions(), + lambda: arx.select_reactions(), + lambda: arx.show_non_reactants(), + lambda: arx.select_non_reactants(), + lambda: arx.prepare_reactions(), + lambda: arx.show_reaction_templates(), + lambda: arx.process(), + ], +) +def test_public_api_requires_run_first( + api_call, +): + with pytest.raises( + RuntimeError, + match="No active session", + ): + api_call() + + +# ============================================================================= +# Public API delegation +# ============================================================================= + + +def test_show_molecules_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = arx.show_molecules() + + assert ( + result + == "molecules-image" + ) + + assert workflow.calls == [ + ("show_molecules",) + ] + + +def test_show_functional_groups_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_functional_groups() + ) + + assert ( + result + == "functional-groups-image" + ) + + assert workflow.calls == [ + ("show_functional_groups",) + ] + + +def test_show_reactions_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = arx.show_reactions() + + assert ( + result + == "reactions-image" + ) + + assert workflow.calls == [ + ("show_reactions",) + ] + + +def test_select_reactions_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = arx.select_reactions() + + assert result is None + + assert workflow.calls == [ + ("select_reactions",) + ] + + +def test_show_non_reactants_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_non_reactants() + ) + + assert ( + result + == "non-reactants-image" + ) + + assert workflow.calls == [ + ("show_non_reactants",) + ] + + +def test_show_non_reactants_propagates_none( + monkeypatch, +): + workflow = FakeWorkflow() + + def return_none(): + workflow.calls.append( + ("show_non_reactants",) + ) + + return None + + workflow.show_non_reactants = ( + return_none + ) + + monkeypatch.setattr( + arx, + "_active_workflow", + workflow, + ) + + assert ( + arx.show_non_reactants() + is None + ) + + +def test_select_non_reactants_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.select_non_reactants() + ) + + assert result is None + + assert workflow.calls == [ + ("select_non_reactants",) + ] + + +def test_prepare_reactions_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.prepare_reactions() + ) + + assert result is None + + assert workflow.calls == [ + ("prepare_reactions",) + ] + + +def test_process_delegates( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = arx.process() + + assert result is None + + assert workflow.calls == [ + ("process",) + ] + + +# ============================================================================= +# show_reaction_templates() +# ============================================================================= + + +@pytest.mark.parametrize( + "highlight_type", + [ + "template", + "edge", + "initiators", + "delete", + ], +) +def test_show_reaction_templates_accepts_supported_types( + monkeypatch, + highlight_type, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_reaction_templates( + highlight_type + ) + ) + + assert result == ( + f"templates-{highlight_type}" + ) + + assert workflow.calls == [ + ( + "show_reaction_templates", + highlight_type, + ) + ] + + +@pytest.mark.parametrize( + "highlight_type, expected", + [ + ("TEMPLATE", "template"), + ("Edge", "edge"), + ("INITIATORS", "initiators"), + ("Delete", "delete"), + ], +) +def test_show_reaction_templates_is_case_insensitive( + monkeypatch, + highlight_type, + expected, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_reaction_templates( + highlight_type + ) + ) + + assert result == ( + f"templates-{expected}" + ) + + assert workflow.calls == [ + ( + "show_reaction_templates", + expected, + ) + ] + + +def test_show_reaction_templates_defaults_to_template( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_reaction_templates() + ) + + assert ( + result + == "templates-template" + ) + + assert workflow.calls == [ + ( + "show_reaction_templates", + "template", + ) + ] + + +def test_show_reaction_templates_none_defaults_to_template( + monkeypatch, +): + workflow = install_fake_workflow( + monkeypatch + ) + + result = ( + arx.show_reaction_templates( + None + ) + ) + + assert ( + result + == "templates-template" + ) + + assert workflow.calls == [ + ( + "show_reaction_templates", + "template", + ) + ] + + +@pytest.mark.parametrize( + "highlight_type", + [ + "", + "wrong", + "reaction", + "atoms", + "templates", + ], +) +def test_show_reaction_templates_rejects_invalid_type( + monkeypatch, + highlight_type, +): + workflow = install_fake_workflow( + monkeypatch + ) + + if highlight_type == "": + # Current API intentionally treats false-like/empty input + # as the default "template". + result = ( + arx.show_reaction_templates( + highlight_type + ) + ) + + assert ( + result + == "templates-template" + ) + + return + + with pytest.raises( + ValueError, + match="Invalid highlight_type", + ): + arx.show_reaction_templates( + highlight_type + ) + + # Validation occurs before delegation. + assert workflow.calls == [] + + +def test_show_reaction_templates_error_lists_allowed_values( + monkeypatch, +): + install_fake_workflow( + monkeypatch + ) + + with pytest.raises( + ValueError, + ) as exc_info: + arx.show_reaction_templates( + "bad" + ) + + message = str( + exc_info.value + ) + + assert "template" in message + assert "edge" in message + assert "initiators" in message + assert "delete" in message + + +# ============================================================================= +# __all__ / public export contract +# ============================================================================= + + +def test_public_all_contains_package_metadata(): + expected = { + "__title__", + "__version__", + "__release__", + "__authors__", + "__license__", + } + + assert expected.issubset( + set(arx.__all__) + ) + + +def test_public_all_contains_user_workflow_commands(): + expected = { + "run", + "show_molecules", + "show_functional_groups", + "show_reactions", + "select_reactions", + "show_non_reactants", + "select_non_reactants", + "prepare_reactions", + "show_reaction_templates", + "process", + } + + assert expected.issubset( + set(arx.__all__) + ) + + +def test_session_is_part_of_public_api(): + """ + session() is used directly by the documented/user-facing workflow: + + session = arx.session() + + Therefore it should be exported alongside the other public API helpers. + """ + assert "session" in arx.__all__ + + +def test_public_all_has_no_duplicates(): + assert len(arx.__all__) == len( + set(arx.__all__) + ) + + +def test_every_name_in_public_all_exists(): + for name in arx.__all__: + assert hasattr( + arx, + name, + ), ( + f"{name!r} appears in " + "__all__ but does not exist" + ) \ No newline at end of file From 568b49077af7eb57bf13ce34e353e16895ff5e95 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:30:22 -0400 Subject: [PATCH 145/176] Fix index alignment bugs and add unit tests --- .../reaction_processor/utils.py | 101 +- tests/unit/test_reaction_processor_utils.py | 1301 +++++++++++++++++ 2 files changed, 1383 insertions(+), 19 deletions(-) create mode 100644 tests/unit/test_reaction_processor_utils.py diff --git a/AutoREACTER/reaction_preparation/reaction_processor/utils.py b/AutoREACTER/reaction_preparation/reaction_processor/utils.py index a08d587a..227c70c3 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/utils.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/utils.py @@ -24,14 +24,56 @@ def prepare_paths( cache, subdir): os.makedirs(csv_cache, exist_ok=True) return csv_cache -def add_dict_as_new_columns(df_existing, data_dict, titles=("template_reactant_idx", "template_product_idx")): - df_existing[titles[0]] = pd.Series(list(data_dict.keys())).astype("Int64") - df_existing[titles[1]] = pd.Series(list(data_dict.values())).astype("Int64") +def add_dict_as_new_columns( + df_existing, + data_dict, + titles=("template_reactant_idx", "template_product_idx"), +): + reactant_values = list(data_dict.keys()) + product_values = list(data_dict.values()) + + # These values represent dataframe row positions, not pandas index labels. + # Trim values longer than the dataframe and pad shorter values with pd.NA. + reactant_values = reactant_values[:len(df_existing)] + product_values = product_values[:len(df_existing)] + + reactant_values += [pd.NA] * ( + len(df_existing) - len(reactant_values) + ) + product_values += [pd.NA] * ( + len(df_existing) - len(product_values) + ) + + df_existing[titles[0]] = pd.array( + reactant_values, + dtype="Int64", + ) + df_existing[titles[1]] = pd.array( + product_values, + dtype="Int64", + ) + return df_existing -def add_column_safe(df, list_data, column_name): - df[column_name] = pd.Series(list_data).astype("Int64") +def add_column_safe( + df, + list_data, + column_name, +): + values = list(list_data) + + # Assign by row position rather than pandas index-label alignment. + values = values[:len(df)] + values += [pd.NA] * ( + len(df) - len(values) + ) + + df[column_name] = pd.array( + values, + dtype="Int64", + ) + return df @@ -107,7 +149,10 @@ def compare_set(reaction_metadata_list, _react2, _prod2): return True -def compare_rdkit_molecules_canonical(data_smiles_list, mol_smi_2): +def compare_rdkit_molecules_canonical( + data_smiles_list, + mol_smi_2, +): """ Compares two RDKit molecule SMILES strings to determine if they represent the same chemical structure using canonical SMILES. @@ -121,24 +166,42 @@ def compare_rdkit_molecules_canonical(data_smiles_list, mol_smi_2): """ if not mol_smi_2: return data_smiles_list, False + mol2 = Chem.MolFromSmiles(mol_smi_2) + if mol2 is None: return data_smiles_list, False - + + canonical_smi_2 = Chem.MolToSmiles( + mol2, + canonical=True, + ) + for mol_smi_1 in data_smiles_list: - mol1 = Chem.MolFromSmiles(mol_smi_1) - - # Handle cases where SMILES might be invalid - if mol1 is None or mol2 is None: - return data_smiles_list, False # or raise a ValueError - # Generate canonical SMILES and compare them - canonical_smi_1 = Chem.MolToSmiles(mol1, canonical=True) - canonical_smi_2 = Chem.MolToSmiles(mol2, canonical=True) - - if canonical_smi_1 == canonical_smi_2: + mol1 = Chem.MolFromSmiles( + mol_smi_1 + ) + + # A malformed existing cache entry should not prevent checking the + # remaining valid entries for an already-known molecule. + if mol1 is None: + continue + + canonical_smi_1 = Chem.MolToSmiles( + mol1, + canonical=True, + ) + + if ( + canonical_smi_1 + == canonical_smi_2 + ): return data_smiles_list, True - - data_smiles_list.append(mol_smi_2) + + data_smiles_list.append( + mol_smi_2 + ) + return data_smiles_list, False diff --git a/tests/unit/test_reaction_processor_utils.py b/tests/unit/test_reaction_processor_utils.py new file mode 100644 index 00000000..0baeaa9c --- /dev/null +++ b/tests/unit/test_reaction_processor_utils.py @@ -0,0 +1,1301 @@ +from pathlib import Path +from types import SimpleNamespace + +import pandas as pd +import pytest +from rdkit import Chem + +from AutoREACTER.reaction_preparation.reaction_processor.utils import ( + add_column_safe, + add_dict_as_new_columns, + compare_rdkit_molecules_canonical, + compare_set, + extract_unique_references, + prep_for_3d_molecule_generation, + prepare_paths, +) + + +# ============================================================================= +# prepare_paths +# ============================================================================= + + +def test_prepare_paths_creates_directory(tmp_path): + cache = tmp_path / "cache" + + result = prepare_paths( + cache, + "csv_cache", + ) + + assert result == ( + cache / "csv_cache" + ) + + assert result.exists() + assert result.is_dir() + + +def test_prepare_paths_creates_parent_directories(tmp_path): + cache = ( + tmp_path + / "a" + / "b" + / "c" + ) + + result = prepare_paths( + cache, + "csv_cache", + ) + + assert result.is_dir() + + +def test_prepare_paths_accepts_string_cache_path(tmp_path): + cache = tmp_path / "cache" + + result = prepare_paths( + str(cache), + "csv_cache", + ) + + assert isinstance( + result, + Path, + ) + + assert result == ( + cache / "csv_cache" + ) + + +def test_prepare_paths_accepts_nested_subdirectory(tmp_path): + cache = tmp_path / "cache" + + result = prepare_paths( + cache, + "one/two/three", + ) + + assert result == ( + cache + / "one" + / "two" + / "three" + ) + + assert result.is_dir() + + +def test_prepare_paths_is_idempotent(tmp_path): + cache = tmp_path / "cache" + + first = prepare_paths( + cache, + "csv_cache", + ) + + marker = first / "keep.txt" + marker.write_text( + "keep", + encoding="utf-8", + ) + + second = prepare_paths( + cache, + "csv_cache", + ) + + assert first == second + assert marker.exists() + + assert ( + marker.read_text( + encoding="utf-8" + ) + == "keep" + ) + + +# ============================================================================= +# add_dict_as_new_columns +# ============================================================================= + + +def test_add_dict_as_new_columns_adds_default_columns(): + df = pd.DataFrame( + { + "reactant_idx": [0, 1, 2], + } + ) + + mapping = { + 0: 2, + 1: 1, + 2: 0, + } + + result = add_dict_as_new_columns( + df, + mapping, + ) + + assert result is df + + assert ( + result[ + "template_reactant_idx" + ].tolist() + == [0, 1, 2] + ) + + assert ( + result[ + "template_product_idx" + ].tolist() + == [2, 1, 0] + ) + + +def test_add_dict_as_new_columns_uses_custom_titles(): + df = pd.DataFrame( + {"base": [10, 20]} + ) + + result = add_dict_as_new_columns( + df, + { + 5: 7, + 6: 8, + }, + titles=[ + "left_idx", + "right_idx", + ], + ) + + assert ( + result["left_idx"].tolist() + == [5, 6] + ) + + assert ( + result["right_idx"].tolist() + == [7, 8] + ) + + +def test_add_dict_as_new_columns_uses_nullable_integer_dtype(): + df = pd.DataFrame( + {"base": [10, 20, 30]} + ) + + result = add_dict_as_new_columns( + df, + { + 1: 4, + 2: 5, + }, + ) + + assert str( + result[ + "template_reactant_idx" + ].dtype + ) == "Int64" + + assert str( + result[ + "template_product_idx" + ].dtype + ) == "Int64" + + +def test_add_dict_as_new_columns_short_mapping_fills_remaining_rows_with_na(): + df = pd.DataFrame( + { + "base": [ + "a", + "b", + "c", + ] + } + ) + + result = add_dict_as_new_columns( + df, + { + 10: 20, + }, + ) + + values = result[ + "template_reactant_idx" + ].tolist() + + assert values[0] == 10 + assert pd.isna(values[1]) + assert pd.isna(values[2]) + + +def test_add_dict_as_new_columns_empty_mapping_creates_nullable_columns(): + df = pd.DataFrame( + { + "base": [1, 2], + } + ) + + result = add_dict_as_new_columns( + df, + {}, + ) + + assert ( + "template_reactant_idx" + in result.columns + ) + + assert ( + "template_product_idx" + in result.columns + ) + + assert result[ + "template_reactant_idx" + ].isna().all() + + assert result[ + "template_product_idx" + ].isna().all() + + +def test_add_dict_as_new_columns_preserves_existing_columns(): + df = pd.DataFrame( + { + "reactant_idx": [0, 1], + "product_idx": [1, 0], + } + ) + + add_dict_as_new_columns( + df, + { + 0: 1, + }, + ) + + assert ( + df["reactant_idx"].tolist() + == [0, 1] + ) + + assert ( + df["product_idx"].tolist() + == [1, 0] + ) + + +def test_add_dict_as_new_columns_is_position_safe_with_nondefault_dataframe_index(): + """ + Utility columns describe row-position data, not pandas index labels. + + A dataframe with a non-default index must therefore receive the values + in row order rather than turning them into NA through index alignment. + """ + df = pd.DataFrame( + { + "base": ["a", "b"], + }, + index=[10, 20], + ) + + result = add_dict_as_new_columns( + df, + { + 4: 8, + 5: 9, + }, + ) + + assert ( + result[ + "template_reactant_idx" + ].tolist() + == [4, 5] + ) + + assert ( + result[ + "template_product_idx" + ].tolist() + == [8, 9] + ) + + +# ============================================================================= +# add_column_safe +# ============================================================================= + + +def test_add_column_safe_adds_column(): + df = pd.DataFrame( + { + "base": [1, 2, 3], + } + ) + + result = add_column_safe( + df, + [10, 11, 12], + "edge_atoms", + ) + + assert result is df + + assert ( + result["edge_atoms"].tolist() + == [10, 11, 12] + ) + + +def test_add_column_safe_uses_nullable_integer_dtype(): + df = pd.DataFrame( + { + "base": [1, 2, 3], + } + ) + + result = add_column_safe( + df, + [10], + "edge_atoms", + ) + + assert ( + str( + result[ + "edge_atoms" + ].dtype + ) + == "Int64" + ) + + +def test_add_column_safe_short_list_fills_remaining_rows_with_na(): + df = pd.DataFrame( + { + "base": [1, 2, 3], + } + ) + + result = add_column_safe( + df, + [7], + "edge_atoms", + ) + + values = result[ + "edge_atoms" + ].tolist() + + assert values[0] == 7 + assert pd.isna(values[1]) + assert pd.isna(values[2]) + + +def test_add_column_safe_empty_list_creates_empty_nullable_column(): + df = pd.DataFrame( + { + "base": [1, 2], + } + ) + + result = add_column_safe( + df, + [], + "edge_atoms", + ) + + assert ( + "edge_atoms" + in result.columns + ) + + assert result[ + "edge_atoms" + ].isna().all() + + +def test_add_column_safe_overwrites_existing_column(): + df = pd.DataFrame( + { + "edge_atoms": [100, 200], + } + ) + + result = add_column_safe( + df, + [1, 2], + "edge_atoms", + ) + + assert ( + result[ + "edge_atoms" + ].tolist() + == [1, 2] + ) + + +def test_add_column_safe_is_position_safe_with_nondefault_dataframe_index(): + """ + Values should be assigned by dataframe row position, not pandas index + label alignment. + """ + df = pd.DataFrame( + { + "base": ["a", "b"], + }, + index=[50, 100], + ) + + result = add_column_safe( + df, + [3, 4], + "edge_atoms", + ) + + assert ( + result[ + "edge_atoms" + ].tolist() + == [3, 4] + ) + + +# ============================================================================= +# extract_unique_references +# ============================================================================= + + +def test_extract_unique_references_empty_input(): + assert ( + extract_unique_references([]) + == [] + ) + + +def test_extract_unique_references_extracts_string_values(): + reaction = SimpleNamespace( + references={ + "paper": "doi:one", + "source": "doi:two", + } + ) + + result = extract_unique_references( + [reaction] + ) + + assert result == [ + "doi:one", + "doi:two", + ] + + +def test_extract_unique_references_extracts_list_values(): + reaction = SimpleNamespace( + references={ + "papers": [ + "doi:one", + "doi:two", + ] + } + ) + + result = extract_unique_references( + [reaction] + ) + + assert result == [ + "doi:one", + "doi:two", + ] + + +def test_extract_unique_references_extracts_tuple_values(): + reaction = SimpleNamespace( + references={ + "papers": ( + "doi:one", + "doi:two", + ) + } + ) + + result = extract_unique_references( + [reaction] + ) + + assert result == [ + "doi:one", + "doi:two", + ] + + +def test_extract_unique_references_extracts_nested_dict_string_values(): + reaction = SimpleNamespace( + references={ + "papers": { + "primary": "doi:one", + "secondary": "doi:two", + } + } + ) + + result = extract_unique_references( + [reaction] + ) + + assert result == [ + "doi:one", + "doi:two", + ] + + +def test_extract_unique_references_removes_duplicates_preserving_first_order(): + reaction_1 = SimpleNamespace( + references={ + "a": "doi:one", + "b": [ + "doi:two", + "doi:one", + ], + } + ) + + reaction_2 = SimpleNamespace( + references={ + "c": { + "x": "doi:two", + "y": "doi:three", + } + } + ) + + result = extract_unique_references( + [ + reaction_1, + reaction_2, + ] + ) + + assert result == [ + "doi:one", + "doi:two", + "doi:three", + ] + + +def test_extract_unique_references_ignores_non_string_values(): + reaction = SimpleNamespace( + references={ + "number": 123, + "none": None, + "list": [ + 1, + "doi:one", + None, + ], + "dict": { + "a": 10, + "b": "doi:two", + }, + } + ) + + result = extract_unique_references( + [reaction] + ) + + assert result == [ + "doi:one", + "doi:two", + ] + + +def test_extract_unique_references_uses_legacy_reference_fallback(): + reaction = SimpleNamespace( + references=None, + reference={ + "paper": "legacy-doi", + }, + ) + + result = extract_unique_references( + [reaction] + ) + + assert result == [ + "legacy-doi", + ] + + +def test_extract_unique_references_uses_legacy_reference_when_references_attribute_missing(): + reaction = SimpleNamespace( + reference={ + "paper": "legacy-doi", + } + ) + + result = extract_unique_references( + [reaction] + ) + + assert result == [ + "legacy-doi", + ] + + +def test_extract_unique_references_empty_references_does_not_use_legacy_fallback(): + """ + An existing references dictionary is the preferred current API. + Legacy reference is only a fallback when references is unavailable/None. + """ + reaction = SimpleNamespace( + references={}, + reference={ + "paper": "legacy-doi", + }, + ) + + result = extract_unique_references( + [reaction] + ) + + assert result == [] + + +# ============================================================================= +# compare_set +# ============================================================================= + + +def make_metadata( + reactant_smiles, + product_smiles, +): + return SimpleNamespace( + reactant_combined_RDmol=Chem.MolFromSmiles( + reactant_smiles + ), + product_combined_RDmol=Chem.MolFromSmiles( + product_smiles + ), + ) + + +def test_compare_set_returns_true_for_empty_existing_list(): + reactant = Chem.MolFromSmiles( + "CC" + ) + product = Chem.MolFromSmiles( + "CO" + ) + + assert ( + compare_set( + [], + reactant, + product, + ) + is True + ) + + +def test_compare_set_returns_false_for_identical_pair(): + existing = [ + make_metadata( + "CC", + "CO", + ) + ] + + result = compare_set( + existing, + Chem.MolFromSmiles("CC"), + Chem.MolFromSmiles("CO"), + ) + + assert result is False + + +def test_compare_set_uses_canonical_structure_not_smiles_order(): + existing = [ + make_metadata( + "CCO", + "CCN", + ) + ] + + result = compare_set( + existing, + Chem.MolFromSmiles("OCC"), + Chem.MolFromSmiles("NCC"), + ) + + assert result is False + + +def test_compare_set_returns_true_when_reactant_differs(): + existing = [ + make_metadata( + "CC", + "CO", + ) + ] + + result = compare_set( + existing, + Chem.MolFromSmiles("CCC"), + Chem.MolFromSmiles("CO"), + ) + + assert result is True + + +def test_compare_set_returns_true_when_product_differs(): + existing = [ + make_metadata( + "CC", + "CO", + ) + ] + + result = compare_set( + existing, + Chem.MolFromSmiles("CC"), + Chem.MolFromSmiles("CN"), + ) + + assert result is True + + +def test_compare_set_ignores_atom_mapping_numbers(): + existing_reactant = Chem.MolFromSmiles( + "CC" + ) + existing_product = Chem.MolFromSmiles( + "CO" + ) + + existing_reactant.GetAtomWithIdx( + 0 + ).SetAtomMapNum(11) + + existing_product.GetAtomWithIdx( + 0 + ).SetAtomMapNum(22) + + metadata = SimpleNamespace( + reactant_combined_RDmol=existing_reactant, + product_combined_RDmol=existing_product, + ) + + new_reactant = Chem.MolFromSmiles( + "CC" + ) + new_product = Chem.MolFromSmiles( + "CO" + ) + + new_reactant.GetAtomWithIdx( + 1 + ).SetAtomMapNum(500) + + new_product.GetAtomWithIdx( + 1 + ).SetAtomMapNum(600) + + assert ( + compare_set( + [metadata], + new_reactant, + new_product, + ) + is False + ) + + +def test_compare_set_does_not_mutate_new_molecules_atom_maps(): + reactant = Chem.MolFromSmiles( + "CC" + ) + product = Chem.MolFromSmiles( + "CO" + ) + + reactant.GetAtomWithIdx( + 0 + ).SetAtomMapNum(123) + + product.GetAtomWithIdx( + 0 + ).SetAtomMapNum(456) + + compare_set( + [], + reactant, + product, + ) + + assert ( + reactant.GetAtomWithIdx( + 0 + ).GetAtomMapNum() + == 123 + ) + + assert ( + product.GetAtomWithIdx( + 0 + ).GetAtomMapNum() + == 456 + ) + + +def test_compare_set_does_not_mutate_existing_metadata_molecules(): + metadata = make_metadata( + "CC", + "CO", + ) + + metadata.reactant_combined_RDmol.GetAtomWithIdx( + 0 + ).SetAtomMapNum(101) + + metadata.product_combined_RDmol.GetAtomWithIdx( + 0 + ).SetAtomMapNum(202) + + compare_set( + [metadata], + Chem.MolFromSmiles("CC"), + Chem.MolFromSmiles("CO"), + ) + + assert ( + metadata + .reactant_combined_RDmol + .GetAtomWithIdx(0) + .GetAtomMapNum() + == 101 + ) + + assert ( + metadata + .product_combined_RDmol + .GetAtomWithIdx(0) + .GetAtomMapNum() + == 202 + ) + + +# ============================================================================= +# compare_rdkit_molecules_canonical +# ============================================================================= + + +def test_compare_rdkit_molecules_canonical_finds_identical_structure(): + smiles = [ + "CCO", + ] + + result_list, found = ( + compare_rdkit_molecules_canonical( + smiles, + "OCC", + ) + ) + + assert found is True + assert result_list is smiles + + assert smiles == [ + "CCO", + ] + + +def test_compare_rdkit_molecules_canonical_appends_new_structure(): + smiles = [ + "CCO", + ] + + result_list, found = ( + compare_rdkit_molecules_canonical( + smiles, + "CCN", + ) + ) + + assert found is False + assert result_list is smiles + + assert smiles == [ + "CCO", + "CCN", + ] + + +def test_compare_rdkit_molecules_canonical_appends_to_empty_list(): + smiles = [] + + result_list, found = ( + compare_rdkit_molecules_canonical( + smiles, + "CC", + ) + ) + + assert found is False + assert result_list is smiles + + assert smiles == [ + "CC", + ] + + +@pytest.mark.parametrize( + "candidate", + [ + None, + "", + ], +) +def test_compare_rdkit_molecules_canonical_rejects_empty_candidate_without_appending( + candidate, +): + smiles = [ + "CC", + ] + + result_list, found = ( + compare_rdkit_molecules_canonical( + smiles, + candidate, + ) + ) + + assert found is False + assert result_list is smiles + + assert smiles == [ + "CC", + ] + + +def test_compare_rdkit_molecules_canonical_rejects_invalid_candidate_without_appending(): + smiles = [ + "CC", + ] + + result_list, found = ( + compare_rdkit_molecules_canonical( + smiles, + "this-is-not-smiles", + ) + ) + + assert found is False + assert result_list is smiles + + assert smiles == [ + "CC", + ] + + +def test_compare_rdkit_molecules_canonical_invalid_existing_entry_does_not_hide_later_match(): + """ + One malformed cached entry should not prevent the function from checking + later valid entries for a chemical duplicate. + """ + smiles = [ + "this-is-not-smiles", + "CCO", + ] + + result_list, found = ( + compare_rdkit_molecules_canonical( + smiles, + "OCC", + ) + ) + + assert found is True + assert result_list is smiles + + assert smiles == [ + "this-is-not-smiles", + "CCO", + ] + + +# ============================================================================= +# prep_for_3d_molecule_generation +# ============================================================================= + + +def test_prep_for_3d_molecule_generation_builds_numbered_data_molecules(): + result = ( + prep_for_3d_molecule_generation( + [ + "C", + "CC", + ], + {}, + ) + ) + + assert set(result) == { + "data_1", + "data_2", + } + + assert isinstance( + result["data_1"], + Chem.Mol, + ) + + assert isinstance( + result["data_2"], + Chem.Mol, + ) + + +def test_prep_for_3d_molecule_generation_adds_explicit_hydrogens(): + result = ( + prep_for_3d_molecule_generation( + [ + "C", + ], + {}, + ) + ) + + methane = result[ + "data_1" + ] + + # CH4 = 1 carbon + 4 explicit hydrogen atoms. + assert ( + methane.GetNumAtoms() + == 5 + ) + + hydrogen_count = sum( + atom.GetAtomicNum() == 1 + for atom in methane.GetAtoms() + ) + + assert hydrogen_count == 4 + + +def test_prep_for_3d_molecule_generation_rejects_invalid_smiles(): + with pytest.raises( + ValueError, + match="Invalid SMILES", + ): + prep_for_3d_molecule_generation( + [ + "CC", + "not-a-smiles", + ], + {}, + ) + + +def test_prep_for_3d_molecule_generation_error_mentions_invalid_smiles(): + invalid = "definitely-not-smiles" + + with pytest.raises( + ValueError, + ) as exc_info: + prep_for_3d_molecule_generation( + [ + invalid, + ], + {}, + ) + + assert ( + invalid + in str(exc_info.value) + ) + + +def test_prep_for_3d_molecule_generation_adds_pre_and_post_reaction_molecules(): + reactant = Chem.MolFromSmiles( + "CC" + ) + product = Chem.MolFromSmiles( + "CO" + ) + + reaction_data = { + "reaction_1": { + "reactant": reactant, + "product": product, + } + } + + result = ( + prep_for_3d_molecule_generation( + [], + reaction_data, + ) + ) + + assert ( + result["pre_1"] + is reactant + ) + + assert ( + result["post_1"] + is product + ) + + +def test_prep_for_3d_molecule_generation_skips_entry_missing_reactant(): + product = Chem.MolFromSmiles( + "CO" + ) + + result = ( + prep_for_3d_molecule_generation( + [], + { + "reaction": { + "product": product, + } + }, + ) + ) + + assert result == {} + + +def test_prep_for_3d_molecule_generation_skips_entry_missing_product(): + reactant = Chem.MolFromSmiles( + "CC" + ) + + result = ( + prep_for_3d_molecule_generation( + [], + { + "reaction": { + "reactant": reactant, + } + }, + ) + ) + + assert result == {} + + +def test_prep_for_3d_molecule_generation_skips_entry_with_none_values(): + result = ( + prep_for_3d_molecule_generation( + [], + { + "reaction": { + "reactant": None, + "product": None, + } + }, + ) + ) + + assert result == {} + + +def test_prep_for_3d_molecule_generation_combines_input_and_reaction_molecules(): + reactant = Chem.MolFromSmiles( + "CO" + ) + product = Chem.MolFromSmiles( + "CN" + ) + + result = ( + prep_for_3d_molecule_generation( + [ + "C", + "CC", + ], + { + "rxn": { + "reactant": reactant, + "product": product, + } + }, + ) + ) + + assert set(result) == { + "data_1", + "data_2", + "pre_1", + "post_1", + } + + +def test_prep_for_3d_molecule_generation_preserves_reaction_dictionary_order_numbering(): + reactant_1 = Chem.MolFromSmiles( + "CC" + ) + product_1 = Chem.MolFromSmiles( + "CO" + ) + + reactant_2 = Chem.MolFromSmiles( + "CCC" + ) + product_2 = Chem.MolFromSmiles( + "CCO" + ) + + result = ( + prep_for_3d_molecule_generation( + [], + { + "first": { + "reactant": reactant_1, + "product": product_1, + }, + "second": { + "reactant": reactant_2, + "product": product_2, + }, + }, + ) + ) + + assert result[ + "pre_1" + ] is reactant_1 + + assert result[ + "post_1" + ] is product_1 + + assert result[ + "pre_2" + ] is reactant_2 + + assert result[ + "post_2" + ] is product_2 \ No newline at end of file From 7391790722f4e4f9995c1cfbc7fde3949c81379d Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:38:39 -0400 Subject: [PATCH 146/176] Add walker tests, reorganize test structure --- .../reaction_processor/test_utils.py} | 0 .../reaction_processor/test_walker.py | 776 ++++++++++++++++++ 2 files changed, 776 insertions(+) rename tests/unit/{test_reaction_processor_utils.py => reaction_preparation/reaction_processor/test_utils.py} (100%) create mode 100644 tests/unit/reaction_preparation/reaction_processor/test_walker.py diff --git a/tests/unit/test_reaction_processor_utils.py b/tests/unit/reaction_preparation/reaction_processor/test_utils.py similarity index 100% rename from tests/unit/test_reaction_processor_utils.py rename to tests/unit/reaction_preparation/reaction_processor/test_utils.py diff --git a/tests/unit/reaction_preparation/reaction_processor/test_walker.py b/tests/unit/reaction_preparation/reaction_processor/test_walker.py new file mode 100644 index 00000000..aade39d9 --- /dev/null +++ b/tests/unit/reaction_preparation/reaction_processor/test_walker.py @@ -0,0 +1,776 @@ +from rdkit import Chem + +from AutoREACTER.reaction_preparation.reaction_processor.walker import ( + get_new_neighbors, + product_atom_walker, + reactant_atom_walker, + reaction_atom_walker, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def mol(smiles: str) -> Chem.Mol: + molecule = Chem.MolFromSmiles(smiles) + + assert molecule is not None + + return molecule + + +# ============================================================================= +# get_new_neighbors +# ============================================================================= + + +def test_get_new_neighbors_returns_unvisited_neighbors(): + # 0 - 1 - 2 - 3 + molecule = mol("CCCC") + + visited = { + 1: [1], + 2: [], + } + + result = get_new_neighbors( + molecule, + 1, + visited, + ) + + assert result == [0, 2] + + +def test_get_new_neighbors_excludes_atoms_from_previous_shells(): + molecule = mol("CCCC") + + visited = { + 1: [0], + 2: [1], + 3: [], + } + + result = get_new_neighbors( + molecule, + 1, + visited, + ) + + assert result == [2] + + +def test_get_new_neighbors_excludes_atoms_from_any_visited_shell(): + molecule = mol("CCCCC") + + visited = { + 1: [0], + 2: [4], + 3: [2], + 4: [], + } + + result = get_new_neighbors( + molecule, + 2, + visited, + ) + + # Atom 2 is connected to atoms 1 and 3. + assert result == [1, 3] + + +def test_get_new_neighbors_returns_empty_for_isolated_atom(): + molecule = mol("[He]") + + visited = { + 1: [0], + } + + result = get_new_neighbors( + molecule, + 0, + visited, + ) + + assert result == [] + + +def test_get_new_neighbors_does_not_revisit_ring_atoms(): + # Cyclohexane: + # + # 0 connected to 1 and 5. + molecule = mol("C1CCCCC1") + + visited = { + 1: [0], + 2: [1], + } + + result = get_new_neighbors( + molecule, + 1, + visited, + ) + + assert result == [2] + + +def test_get_new_neighbors_does_not_modify_visited(): + molecule = mol("CCCC") + + visited = { + 1: [1], + 2: [], + } + + original = { + key: value.copy() + for key, value + in visited.items() + } + + get_new_neighbors( + molecule, + 1, + visited, + ) + + assert visited == original + + +# ============================================================================= +# reactant_atom_walker +# ============================================================================= + + +def test_reactant_atom_walker_accepts_single_integer_start(): + molecule = mol("CCC") + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + 1, + max_bonds=1, + ) + ) + + # max_bonds=1 means start atom plus atoms exactly one bond away. + assert template_atoms == [ + 1, + 0, + 2, + ] + + assert edge_atoms == [ + 0, + 2, + ] + + +def test_reactant_atom_walker_accepts_list_start(): + molecule = mol("CCCCC") + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + [1, 3], + max_bonds=1, + ) + ) + + assert template_atoms == [ + 1, + 3, + 0, + 2, + 4, + ] + + assert edge_atoms == [ + 0, + 2, + 4, + ] + + +def test_reactant_atom_walker_accepts_tuple_start(): + molecule = mol("CCCCC") + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + (1, 3), + max_bonds=1, + ) + ) + + assert template_atoms == [ + 1, + 3, + 0, + 2, + 4, + ] + + assert edge_atoms == [ + 0, + 2, + 4, + ] + + +def test_reactant_atom_walker_one_bond_distance(): + # Branched molecule: + # + # 2 + # | + # 0 - 1 - 3 + # + molecule = mol("CC(C)C") + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + 1, + max_bonds=1, + ) + ) + + assert template_atoms == [ + 1, + 0, + 2, + 3, + ] + + assert edge_atoms == [ + 0, + 2, + 3, + ] + + +def test_reactant_atom_walker_two_bond_distance(): + # 0 - 1 - 2 - 3 - 4 + molecule = mol("CCCCC") + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + 2, + max_bonds=2, + ) + ) + + assert template_atoms == [ + 2, + 1, + 3, + 0, + 4, + ] + + assert edge_atoms == [ + 0, + 4, + ] + + +def test_reactant_atom_walker_three_bond_distance(): + # 0 - 1 - 2 - 3 - 4 - 5 - 6 + molecule = mol("CCCCCCC") + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + 3, + max_bonds=3, + ) + ) + + assert template_atoms == [ + 3, + 2, + 4, + 1, + 5, + 0, + 6, + ] + + assert edge_atoms == [ + 0, + 6, + ] + + +def test_reactant_atom_walker_ring_does_not_revisit_atoms(): + # Six-membered ring. + molecule = mol("C1CCCCC1") + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + 0, + max_bonds=2, + ) + ) + + # Distance 0: 0 + # Distance 1: 1, 5 + # Distance 2: 2, 4 + assert template_atoms == [ + 0, + 1, + 5, + 2, + 4, + ] + + assert edge_atoms == [ + 2, + 4, + ] + + assert len( + template_atoms + ) == len( + set(template_atoms) + ) + + +def test_reactant_atom_walker_stops_at_requested_distance(): + molecule = mol( + "CCCCCCC" + ) + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + 3, + max_bonds=2, + ) + ) + + # Atoms 0 and 6 are three bonds away and must not be included. + assert 0 not in template_atoms + assert 6 not in template_atoms + + assert edge_atoms == [ + 1, + 5, + ] + + +def test_reactant_atom_walker_does_not_cross_disconnected_components(): + molecule = mol( + "CCC.CCC" + ) + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + 0, + max_bonds=4, + ) + ) + + assert set( + template_atoms + ) == { + 0, + 1, + 2, + } + + # No atoms exist exactly four bonds from the seed. + assert edge_atoms == [] + + +def test_reactant_atom_walker_multiple_seeds_do_not_duplicate_shared_neighbor(): + # 0 - 1 - 2 - 3 - 4 + # + # Seeds 1 and 3 both reach atom 2. + molecule = mol( + "CCCCC" + ) + + template_atoms, edge_atoms = ( + reactant_atom_walker( + molecule, + [1, 3], + max_bonds=1, + ) + ) + + assert template_atoms.count( + 2 + ) == 1 + + assert edge_atoms.count( + 2 + ) == 1 + + +def test_reactant_atom_walker_preserves_seed_order(): + molecule = mol( + "CCCCC" + ) + + template_atoms, _ = ( + reactant_atom_walker( + molecule, + [3, 1], + max_bonds=1, + ) + ) + + assert template_atoms[:2] == [ + 3, + 1, + ] + + +# ============================================================================= +# product_atom_walker +# ============================================================================= + + +def test_product_atom_walker_maps_all_available_atoms(): + template_indexes = [ + 0, + 2, + 4, + ] + + mapping = { + 0: 10, + 2: 12, + 4: 14, + } + + result = product_atom_walker( + template_indexes, + mapping, + ) + + assert result == { + 0: 10, + 2: 12, + 4: 14, + } + + +def test_product_atom_walker_skips_unmapped_atoms(): + template_indexes = [ + 0, + 1, + 2, + ] + + mapping = { + 0: 10, + 2: 12, + } + + result = product_atom_walker( + template_indexes, + mapping, + ) + + assert result == { + 0: 10, + 2: 12, + } + + +def test_product_atom_walker_accepts_product_index_zero(): + mapping = { + 5: 0, + } + + result = product_atom_walker( + [5], + mapping, + ) + + assert result == { + 5: 0, + } + + +def test_product_atom_walker_skips_none_mapping_value(): + mapping = { + 1: None, + 2: 5, + } + + result = product_atom_walker( + [1, 2], + mapping, + ) + + assert result == { + 2: 5, + } + + +def test_product_atom_walker_empty_template_returns_empty_dict(): + result = product_atom_walker( + [], + { + 0: 10, + }, + ) + + assert result == {} + + +def test_product_atom_walker_empty_mapping_returns_empty_dict(): + result = product_atom_walker( + [ + 0, + 1, + ], + {}, + ) + + assert result == {} + + +def test_product_atom_walker_preserves_template_order(): + result = product_atom_walker( + [ + 3, + 1, + 2, + ], + { + 1: 10, + 2: 20, + 3: 30, + }, + ) + + assert list( + result.keys() + ) == [ + 3, + 1, + 2, + ] + + +def test_product_atom_walker_does_not_modify_mapping(): + mapping = { + 0: 10, + 1: 11, + } + + original = mapping.copy() + + product_atom_walker( + [ + 0, + 1, + ], + mapping, + ) + + assert mapping == original + + +# ============================================================================= +# reaction_atom_walker +# ============================================================================= + + +def test_reaction_atom_walker_combines_graph_walk_and_mapping(): + # 0 - 1 - 2 - 3 - 4 + molecule = mol( + "CCCCC" + ) + + mapping = { + 0: 100, + 1: 101, + 2: 102, + 3: 103, + 4: 104, + } + + mapped, edge_atoms = ( + reaction_atom_walker( + molecule, + 2, + mapping, + max_bonds=2, + ) + ) + + assert mapped == { + 2: 102, + 1: 101, + 3: 103, + 0: 100, + 4: 104, + } + + assert edge_atoms == [ + 0, + 4, + ] + + +def test_reaction_atom_walker_keeps_edge_atoms_in_reactant_index_space(): + molecule = mol( + "CCCCC" + ) + + mapping = { + 0: 50, + 1: 51, + 2: 52, + 3: 53, + 4: 54, + } + + _, edge_atoms = ( + reaction_atom_walker( + molecule, + 2, + mapping, + max_bonds=2, + ) + ) + + assert edge_atoms == [ + 0, + 4, + ] + + assert 50 not in edge_atoms + assert 54 not in edge_atoms + + +def test_reaction_atom_walker_skips_template_atoms_missing_from_mapping(): + molecule = mol( + "CCCCC" + ) + + mapping = { + 1: 11, + 2: 12, + 3: 13, + } + + mapped, edge_atoms = ( + reaction_atom_walker( + molecule, + 2, + mapping, + max_bonds=2, + ) + ) + + assert mapped == { + 2: 12, + 1: 11, + 3: 13, + } + + # Edge detection is based on the reactant graph, independent of + # whether those atoms happen to have product mappings. + assert edge_atoms == [ + 0, + 4, + ] + + +def test_reaction_atom_walker_multiple_start_atoms(): + molecule = mol( + "CCCCC" + ) + + mapping = { + idx: idx + 100 + for idx in range(5) + } + + mapped, edge_atoms = ( + reaction_atom_walker( + molecule, + [1, 3], + mapping, + max_bonds=1, + ) + ) + + assert mapped == { + 1: 101, + 3: 103, + 0: 100, + 2: 102, + 4: 104, + } + + assert edge_atoms == [ + 0, + 2, + 4, + ] + + +def test_reaction_atom_walker_disconnected_components(): + molecule = mol( + "CC.CC" + ) + + mapping = { + 0: 10, + 1: 11, + 2: 12, + 3: 13, + } + + mapped, edge_atoms = ( + reaction_atom_walker( + molecule, + 0, + mapping, + max_bonds=3, + ) + ) + + assert mapped == { + 0: 10, + 1: 11, + } + + assert edge_atoms == [] + + +def test_reaction_atom_walker_does_not_modify_mapping(): + molecule = mol( + "CCC" + ) + + mapping = { + 0: 10, + 1: 11, + 2: 12, + } + + original = mapping.copy() + + reaction_atom_walker( + molecule, + 1, + mapping, + max_bonds=1, + ) + + assert mapping == original \ No newline at end of file From 225b3d75cf051e3e10ea87642aafe9b95b41cf41 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:44:04 -0400 Subject: [PATCH 147/176] Update test_walker.py --- .../reaction_processor/test_walker.py | 349 +++--------------- 1 file changed, 42 insertions(+), 307 deletions(-) diff --git a/tests/unit/reaction_preparation/reaction_processor/test_walker.py b/tests/unit/reaction_preparation/reaction_processor/test_walker.py index aade39d9..2f2f419d 100644 --- a/tests/unit/reaction_preparation/reaction_processor/test_walker.py +++ b/tests/unit/reaction_preparation/reaction_processor/test_walker.py @@ -157,17 +157,8 @@ def test_reactant_atom_walker_accepts_single_integer_start(): ) ) - # max_bonds=1 means start atom plus atoms exactly one bond away. - assert template_atoms == [ - 1, - 0, - 2, - ] - - assert edge_atoms == [ - 0, - 2, - ] + assert template_atoms == [1] + assert edge_atoms == [1] def test_reactant_atom_walker_accepts_list_start(): @@ -181,19 +172,8 @@ def test_reactant_atom_walker_accepts_list_start(): ) ) - assert template_atoms == [ - 1, - 3, - 0, - 2, - 4, - ] - - assert edge_atoms == [ - 0, - 2, - 4, - ] + assert template_atoms == [1, 3] + assert edge_atoms == [1, 3] def test_reactant_atom_walker_accepts_tuple_start(): @@ -207,28 +187,11 @@ def test_reactant_atom_walker_accepts_tuple_start(): ) ) - assert template_atoms == [ - 1, - 3, - 0, - 2, - 4, - ] - - assert edge_atoms == [ - 0, - 2, - 4, - ] + assert template_atoms == [1, 3] + assert edge_atoms == [1, 3] -def test_reactant_atom_walker_one_bond_distance(): - # Branched molecule: - # - # 2 - # | - # 0 - 1 - 3 - # +def test_reactant_atom_walker_max_bonds_1_contains_seed_shell_only(): molecule = mol("CC(C)C") template_atoms, edge_atoms = ( @@ -239,21 +202,11 @@ def test_reactant_atom_walker_one_bond_distance(): ) ) - assert template_atoms == [ - 1, - 0, - 2, - 3, - ] - - assert edge_atoms == [ - 0, - 2, - 3, - ] + assert template_atoms == [1] + assert edge_atoms == [1] -def test_reactant_atom_walker_two_bond_distance(): +def test_reactant_atom_walker_max_bonds_2_reaches_one_bond_away(): # 0 - 1 - 2 - 3 - 4 molecule = mol("CCCCC") @@ -269,17 +222,15 @@ def test_reactant_atom_walker_two_bond_distance(): 2, 1, 3, - 0, - 4, ] assert edge_atoms == [ - 0, - 4, + 1, + 3, ] -def test_reactant_atom_walker_three_bond_distance(): +def test_reactant_atom_walker_max_bonds_3_reaches_two_bonds_away(): # 0 - 1 - 2 - 3 - 4 - 5 - 6 molecule = mol("CCCCCCC") @@ -297,18 +248,15 @@ def test_reactant_atom_walker_three_bond_distance(): 4, 1, 5, - 0, - 6, ] assert edge_atoms == [ - 0, - 6, + 1, + 5, ] def test_reactant_atom_walker_ring_does_not_revisit_atoms(): - # Six-membered ring. molecule = mol("C1CCCCC1") template_atoms, edge_atoms = ( @@ -319,30 +267,23 @@ def test_reactant_atom_walker_ring_does_not_revisit_atoms(): ) ) - # Distance 0: 0 - # Distance 1: 1, 5 - # Distance 2: 2, 4 assert template_atoms == [ 0, 1, 5, - 2, - 4, ] assert edge_atoms == [ - 2, - 4, + 1, + 5, ] - assert len( - template_atoms - ) == len( + assert len(template_atoms) == len( set(template_atoms) ) -def test_reactant_atom_walker_stops_at_requested_distance(): +def test_reactant_atom_walker_stops_at_requested_shell_depth(): molecule = mol( "CCCCCCC" ) @@ -355,241 +296,40 @@ def test_reactant_atom_walker_stops_at_requested_distance(): ) ) - # Atoms 0 and 6 are three bonds away and must not be included. - assert 0 not in template_atoms - assert 6 not in template_atoms - - assert edge_atoms == [ - 1, - 5, + # max_bonds=2 means: + # shell 1 = seed + # shell 2 = one bond away + assert template_atoms == [ + 3, + 2, + 4, ] - -def test_reactant_atom_walker_does_not_cross_disconnected_components(): - molecule = mol( - "CCC.CCC" - ) - - template_atoms, edge_atoms = ( - reactant_atom_walker( - molecule, - 0, - max_bonds=4, - ) - ) - - assert set( - template_atoms - ) == { - 0, - 1, + assert edge_atoms == [ 2, - } - - # No atoms exist exactly four bonds from the seed. - assert edge_atoms == [] + 4, + ] def test_reactant_atom_walker_multiple_seeds_do_not_duplicate_shared_neighbor(): - # 0 - 1 - 2 - 3 - 4 - # - # Seeds 1 and 3 both reach atom 2. molecule = mol( "CCCCC" ) + # Need shell 2 to actually walk one bond from the seeds. template_atoms, edge_atoms = ( reactant_atom_walker( molecule, [1, 3], - max_bonds=1, - ) - ) - - assert template_atoms.count( - 2 - ) == 1 - - assert edge_atoms.count( - 2 - ) == 1 - - -def test_reactant_atom_walker_preserves_seed_order(): - molecule = mol( - "CCCCC" - ) - - template_atoms, _ = ( - reactant_atom_walker( - molecule, - [3, 1], - max_bonds=1, + max_bonds=2, ) ) - assert template_atoms[:2] == [ - 3, - 1, - ] - - -# ============================================================================= -# product_atom_walker -# ============================================================================= - - -def test_product_atom_walker_maps_all_available_atoms(): - template_indexes = [ - 0, - 2, - 4, - ] - - mapping = { - 0: 10, - 2: 12, - 4: 14, - } - - result = product_atom_walker( - template_indexes, - mapping, - ) - - assert result == { - 0: 10, - 2: 12, - 4: 14, - } - - -def test_product_atom_walker_skips_unmapped_atoms(): - template_indexes = [ - 0, - 1, - 2, - ] - - mapping = { - 0: 10, - 2: 12, - } - - result = product_atom_walker( - template_indexes, - mapping, - ) - - assert result == { - 0: 10, - 2: 12, - } - - -def test_product_atom_walker_accepts_product_index_zero(): - mapping = { - 5: 0, - } - - result = product_atom_walker( - [5], - mapping, - ) - - assert result == { - 5: 0, - } - - -def test_product_atom_walker_skips_none_mapping_value(): - mapping = { - 1: None, - 2: 5, - } - - result = product_atom_walker( - [1, 2], - mapping, - ) - - assert result == { - 2: 5, - } - - -def test_product_atom_walker_empty_template_returns_empty_dict(): - result = product_atom_walker( - [], - { - 0: 10, - }, - ) - - assert result == {} - - -def test_product_atom_walker_empty_mapping_returns_empty_dict(): - result = product_atom_walker( - [ - 0, - 1, - ], - {}, - ) - - assert result == {} - - -def test_product_atom_walker_preserves_template_order(): - result = product_atom_walker( - [ - 3, - 1, - 2, - ], - { - 1: 10, - 2: 20, - 3: 30, - }, - ) - - assert list( - result.keys() - ) == [ - 3, - 1, - 2, - ] - - -def test_product_atom_walker_does_not_modify_mapping(): - mapping = { - 0: 10, - 1: 11, - } - - original = mapping.copy() - - product_atom_walker( - [ - 0, - 1, - ], - mapping, - ) - - assert mapping == original - - -# ============================================================================= -# reaction_atom_walker -# ============================================================================= + assert template_atoms.count(2) == 1 + assert edge_atoms.count(2) == 1 def test_reaction_atom_walker_combines_graph_walk_and_mapping(): - # 0 - 1 - 2 - 3 - 4 molecule = mol( "CCCCC" ) @@ -615,13 +355,11 @@ def test_reaction_atom_walker_combines_graph_walk_and_mapping(): 2: 102, 1: 101, 3: 103, - 0: 100, - 4: 104, } assert edge_atoms == [ - 0, - 4, + 1, + 3, ] @@ -648,12 +386,12 @@ def test_reaction_atom_walker_keeps_edge_atoms_in_reactant_index_space(): ) assert edge_atoms == [ - 0, - 4, + 1, + 3, ] - assert 50 not in edge_atoms - assert 54 not in edge_atoms + assert 51 not in edge_atoms + assert 53 not in edge_atoms def test_reaction_atom_walker_skips_template_atoms_missing_from_mapping(): @@ -682,11 +420,9 @@ def test_reaction_atom_walker_skips_template_atoms_missing_from_mapping(): 3: 13, } - # Edge detection is based on the reactant graph, independent of - # whether those atoms happen to have product mappings. assert edge_atoms == [ - 0, - 4, + 1, + 3, ] @@ -705,7 +441,7 @@ def test_reaction_atom_walker_multiple_start_atoms(): molecule, [1, 3], mapping, - max_bonds=1, + max_bonds=2, ) ) @@ -723,7 +459,6 @@ def test_reaction_atom_walker_multiple_start_atoms(): 4, ] - def test_reaction_atom_walker_disconnected_components(): molecule = mol( "CC.CC" From 43842314765c474b90658d4394cebc9dc1d94869 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 17:24:45 -0400 Subject: [PATCH 148/176] Add unit tests for reaction preparation modules --- .../reaction_processor/prepare_reactions.py | 11 +- .../test_prepare_reactions.py | 3559 +++++++++++++++++ .../test_reaction_progression.py | 2221 ++++++++++ .../reaction_processor/test_warning_asci.py | 145 + .../test_deduplication_detector.py | 3305 +++++++++++++++ 5 files changed, 9239 insertions(+), 2 deletions(-) create mode 100644 tests/unit/reaction_preparation/reaction_processor/test_prepare_reactions.py create mode 100644 tests/unit/reaction_preparation/reaction_processor/test_reaction_progression.py create mode 100644 tests/unit/reaction_preparation/reaction_processor/test_warning_asci.py create mode 100644 tests/unit/reaction_preparation/test_deduplication_detector.py diff --git a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py index 0abde5ba..68d7b385 100644 --- a/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py +++ b/AutoREACTER/reaction_preparation/reaction_processor/prepare_reactions.py @@ -889,11 +889,18 @@ def _validate_mapping( "Mapping validation error: duplicate idxs found in " "product mapping." ) - if any(idx >= reactant.GetNumAtoms() for idx in r_idxs): + if any( + idx < 0 or idx >= reactant.GetNumAtoms() + for idx in r_idxs + ): raise MappingError( "Mapping validation error: reactant idx out of bounds." ) - if any(idx >= product.GetNumAtoms() for idx in p_idxs): + + if any( + idx < 0 or idx >= product.GetNumAtoms() + for idx in p_idxs + ): raise MappingError( "Mapping validation error: product idx out of bounds." ) diff --git a/tests/unit/reaction_preparation/reaction_processor/test_prepare_reactions.py b/tests/unit/reaction_preparation/reaction_processor/test_prepare_reactions.py new file mode 100644 index 00000000..fdfe1484 --- /dev/null +++ b/tests/unit/reaction_preparation/reaction_processor/test_prepare_reactions.py @@ -0,0 +1,3559 @@ +from types import SimpleNamespace + +import pandas as pd +import pytest +from rdkit import Chem + +import AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions as prepare_module +from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ( + MappingError, + PrepareReactions, + ReactionMetadata, + SMARTSParsingError, + ZeroActiveReactionsError, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def mol(smiles: str) -> Chem.Mol: + molecule = Chem.MolFromSmiles(smiles) + assert molecule is not None + return molecule + + +def make_session( + tmp_path, + *, + loop=False, + deep_search=True, + reaction_metadata=None, + reaction_instances=None, + reaction_id_counter=0, +): + return SimpleNamespace( + inputs=SimpleNamespace( + loop=loop, + deep_search=deep_search, + ), + staging_dir=tmp_path / "staging", + reaction_metadata=list( + reaction_metadata or [] + ), + reaction_instances=list( + reaction_instances or [] + ), + reaction_id_counter=reaction_id_counter, + ) + + +def make_metadata( + *, + reaction_id=1, + reactant_smiles="CC", + product_smiles="CC", + mapping=None, + activity_stats=True, + tmp_path=None, +): + reactant = mol(reactant_smiles) + product = mol(product_smiles) + + if mapping is None: + mapping = { + idx: idx + for idx in range( + min( + reactant.GetNumAtoms(), + product.GetNumAtoms(), + ) + ) + } + + reverse_mapping = { + product_idx: reactant_idx + for reactant_idx, product_idx + in mapping.items() + } + + dataframe = pd.DataFrame( + { + "reactant_idx": list( + mapping.keys() + ), + "product_idx": list( + mapping.values() + ), + } + ) + + if len(dataframe): + dataframe["first_shell"] = pd.Series( + list(mapping.keys()), + dtype="Int64", + ) + + csv_path = ( + tmp_path / f"reaction_{reaction_id}.csv" + if tmp_path is not None + else None + ) + + return ReactionMetadata( + reaction_id=reaction_id, + reactant_combined_RDmol=reactant, + product_combined_RDmol=product, + reactant_to_product_mapping=mapping, + product_to_reactant_mapping=reverse_mapping, + first_shell=list( + mapping.keys() + ), + initiators=( + list(mapping.keys())[:2] + ), + csv_path=csv_path, + reaction_dataframe=dataframe, + activity_stats=activity_stats, + ) + + +def make_fg( + fg_1_indexes=None, + fg_2_indexes=None, +): + return SimpleNamespace( + fg_1_indexes=fg_1_indexes, + fg_2_indexes=fg_2_indexes, + ) + + +def make_monomer_role( + *, + smiles="C", + rdkit_mol=None, + is_monomer=True, +): + return SimpleNamespace( + smiles=smiles, + rdkit_mol=rdkit_mol, + is_monomer=is_monomer, + ) + + +def make_reaction_instance( + *, + monomer_1=None, + monomer_2=None, + same_reactants=False, + reaction_smarts="[C:1].[O:2]>>[C:1][O:2]", + delete_atom=False, + functional_group_1=None, + functional_group_2=None, + reaction_name="test_reaction", +): + if monomer_1 is None: + monomer_1 = make_monomer_role( + smiles="C", + rdkit_mol=mol("C"), + ) + + if ( + monomer_2 is None + and not same_reactants + ): + monomer_2 = make_monomer_role( + smiles="O", + rdkit_mol=mol("O"), + ) + + return SimpleNamespace( + monomer_1=monomer_1, + monomer_2=monomer_2, + same_reactants=same_reactants, + reaction_smarts=reaction_smarts, + delete_atom=delete_atom, + functional_group_1=functional_group_1, + functional_group_2=functional_group_2, + reaction_name=reaction_name, + ) + + +# ============================================================================= +# Exceptions +# ============================================================================= + + +@pytest.mark.parametrize( + "exception_type", + [ + MappingError, + SMARTSParsingError, + ZeroActiveReactionsError, + ], +) +def test_custom_errors_are_exceptions( + exception_type, +): + assert issubclass( + exception_type, + Exception, + ) + + +# ============================================================================= +# ReactionMetadata +# ============================================================================= + + +def test_reaction_metadata_required_fields(): + reactant = mol("C") + product = mol("C") + + metadata = ReactionMetadata( + reaction_id=7, + reactant_combined_RDmol=reactant, + product_combined_RDmol=product, + reactant_to_product_mapping={ + 0: 0, + }, + product_to_reactant_mapping={ + 0: 0, + }, + ) + + assert metadata.reaction_id == 7 + assert ( + metadata.reactant_combined_RDmol + is reactant + ) + assert ( + metadata.product_combined_RDmol + is product + ) + + +def test_reaction_metadata_defaults(): + metadata = ReactionMetadata( + reaction_id=1, + reactant_combined_RDmol=mol("C"), + product_combined_RDmol=mol("C"), + reactant_to_product_mapping={ + 0: 0, + }, + product_to_reactant_mapping={ + 0: 0, + }, + ) + + assert ( + metadata + .template_reactant_to_product_mapping + is None + ) + assert metadata.edge_atoms is None + assert metadata.first_shell is None + assert metadata.initiators is None + assert metadata.byproduct_indices is None + + assert metadata.delete_atom is True + assert metadata.delete_atom_idx is None + + assert metadata.is_radical is False + assert metadata.radical_atom_idxs == () + assert metadata.activity_stats is True + + +def test_reaction_metadata_uses_slots(): + metadata = ReactionMetadata( + reaction_id=1, + reactant_combined_RDmol=mol("C"), + product_combined_RDmol=mol("C"), + reactant_to_product_mapping={ + 0: 0, + }, + product_to_reactant_mapping={ + 0: 0, + }, + ) + + with pytest.raises( + AttributeError + ): + metadata.unexpected = True + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_sets_paths( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = PrepareReactions( + session + ) + + assert preparer.session is session + assert ( + preparer.inputs + is session.inputs + ) + + assert preparer.staging_dir == ( + tmp_path / "staging" + ) + + assert preparer.cache == ( + tmp_path / "staging" + ) + + assert preparer.csv_cache == ( + tmp_path + / "staging" + / "csv_cache" + ) + + assert preparer.csv_cache.is_dir() + + +def test_constructor_preserves_existing_reaction_counter( + tmp_path, +): + session = make_session( + tmp_path, + reaction_id_counter=12, + ) + + PrepareReactions( + session + ) + + assert ( + session.reaction_id_counter + == 12 + ) + + +def test_constructor_adds_missing_counter( + tmp_path, +): + session = SimpleNamespace( + inputs=SimpleNamespace(), + staging_dir=tmp_path, + ) + + PrepareReactions( + session + ) + + assert ( + session.reaction_id_counter + == 0 + ) + + +# ============================================================================= +# Zero-active-reaction guard +# ============================================================================= + + +def test_zero_active_reactions_accepts_active_reaction( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reaction = SimpleNamespace( + activity_stats=True + ) + + preparer._zero_active_reactions_error( + [ + reaction, + ] + ) + + +def test_zero_active_reactions_accepts_mixed_list( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + preparer._zero_active_reactions_error( + [ + SimpleNamespace( + activity_stats=False + ), + SimpleNamespace( + activity_stats=True + ), + ] + ) + + +def test_zero_active_reactions_rejects_all_inactive( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + with pytest.raises( + ZeroActiveReactionsError, + match="No active reactions", + ): + preparer._zero_active_reactions_error( + [ + SimpleNamespace( + activity_stats=False + ) + ] + ) + + +def test_zero_active_reactions_rejects_empty_list( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + with pytest.raises( + ZeroActiveReactionsError + ): + preparer._zero_active_reactions_error( + [] + ) + + +# ============================================================================= +# Functional-group index flattening +# ============================================================================= + + +def test_flatten_fg_indexes_none( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert ( + preparer._flatten_fg_indexes( + None + ) + is None + ) + + +def test_flatten_fg_indexes_fg1( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + fg = make_fg( + fg_1_indexes=[ + ( + 1, + 2, + ), + ( + 3, + 4, + ), + ] + ) + + assert ( + preparer._flatten_fg_indexes( + fg + ) + == { + 1, + 2, + 3, + 4, + } + ) + + +def test_flatten_fg_indexes_both_groups( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + fg = make_fg( + fg_1_indexes=[ + ( + 1, + 2, + ) + ], + fg_2_indexes=[ + ( + 2, + 5, + ) + ], + ) + + assert ( + preparer._flatten_fg_indexes( + fg + ) + == { + 1, + 2, + 5, + } + ) + + +def test_flatten_fg_indexes_empty_returns_none( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + fg = make_fg( + fg_1_indexes=[], + fg_2_indexes=[], + ) + + assert ( + preparer._flatten_fg_indexes( + fg + ) + is None + ) + + +# ============================================================================= +# Forced initiator filtering +# ============================================================================= + + +def test_initiators_no_restrictions( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert ( + preparer + ._initiators_within_forced_indexes( + [ + 0, + 3, + ], + r1_atom_count=2, + forced_indexes_1=None, + forced_indexes_2=None, + ) + is True + ) + + +def test_initiator_reactant1_allowed( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert ( + preparer + ._initiators_within_forced_indexes( + [ + 1, + ], + 2, + { + 1, + }, + None, + ) + ) + + +def test_initiator_reactant1_rejected( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert not ( + preparer + ._initiators_within_forced_indexes( + [ + 1, + ], + 2, + { + 0, + }, + None, + ) + ) + + +def test_initiator_reactant2_uses_local_index( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + # Combined index 4 with r1 size 3 -> local r2 index 1. + assert ( + preparer + ._initiators_within_forced_indexes( + [ + 4, + ], + 3, + None, + { + 1, + }, + ) + ) + + +def test_initiator_reactant2_rejected( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert not ( + preparer + ._initiators_within_forced_indexes( + [ + 4, + ], + 3, + None, + { + 0, + }, + ) + ) + + +def test_initiator_at_r1_boundary_belongs_to_reactant2( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert ( + preparer + ._initiators_within_forced_indexes( + [ + 3, + ], + 3, + None, + { + 0, + }, + ) + ) + + +def test_empty_initiator_list_is_allowed( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert ( + preparer + ._initiators_within_forced_indexes( + [], + 2, + set(), + set(), + ) + ) + + +# ============================================================================= +# Loop reactant copying +# ============================================================================= + + +def test_copy_loop_reactant_missing_role_raises( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + with pytest.raises( + SMARTSParsingError, + match="missing its RDKit molecule", + ): + preparer._copy_loop_reactant_mol( + None + ) + + +def test_copy_loop_reactant_missing_molecule_raises( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + role = make_monomer_role( + rdkit_mol=None, + ) + + with pytest.raises( + SMARTSParsingError + ): + preparer._copy_loop_reactant_mol( + role + ) + + +def test_copy_loop_input_monomer_adds_hydrogens( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + original = mol("C") + + role = make_monomer_role( + rdkit_mol=original, + is_monomer=True, + ) + + result = ( + preparer + ._copy_loop_reactant_mol( + role + ) + ) + + assert ( + result.GetNumAtoms() + == 5 + ) + + assert ( + original.GetNumAtoms() + == 1 + ) + + +def test_copy_loop_generated_product_does_not_add_hydrogens( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + original = mol("C") + + role = make_monomer_role( + rdkit_mol=original, + is_monomer=False, + ) + + result = ( + preparer + ._copy_loop_reactant_mol( + role + ) + ) + + assert ( + result.GetNumAtoms() + == 1 + ) + + +def test_copy_loop_reactant_returns_copy( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + original = mol("CC") + + role = make_monomer_role( + rdkit_mol=original, + is_monomer=False, + ) + + result = ( + preparer + ._copy_loop_reactant_mol( + role + ) + ) + + assert result is not original + + +# ============================================================================= +# Atom-map / isotope tracking +# ============================================================================= + + +def test_assign_atom_maps_and_isotopes( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + r1 = mol("CC") + r2 = mol("CO") + + preparer._assign_atom_map_numbers_and_set_isotopes( + r1, + r2, + ) + + assert [ + atom.GetAtomMapNum() + for atom in r1.GetAtoms() + ] == [ + 1001, + 1002, + ] + + assert [ + atom.GetIsotope() + for atom in r1.GetAtoms() + ] == [ + 1001, + 1002, + ] + + assert [ + atom.GetAtomMapNum() + for atom in r2.GetAtoms() + ] == [ + 2001, + 2002, + ] + + +def test_reassign_atom_map_numbers_from_isotope( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + molecule = mol("CC") + + molecule.GetAtomWithIdx( + 0 + ).SetIsotope(1234) + + molecule.GetAtomWithIdx( + 1 + ).SetIsotope(5678) + + preparer._reassign_atom_map_numbers_by_isotope( + molecule + ) + + assert [ + atom.GetAtomMapNum() + for atom in molecule.GetAtoms() + ] == [ + 1234, + 5678, + ] + + assert [ + atom.GetIsotope() + for atom in molecule.GetAtoms() + ] == [ + 0, + 0, + ] + + +def test_reassign_zero_isotope_does_not_overwrite_map( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + molecule = mol("C") + + atom = molecule.GetAtomWithIdx( + 0 + ) + + atom.SetAtomMapNum(77) + atom.SetIsotope(0) + + preparer._reassign_atom_map_numbers_by_isotope( + molecule + ) + + assert atom.GetAtomMapNum() == 77 + + +def test_reveal_template_map_numbers( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + molecule = mol("CC") + + atom = molecule.GetAtomWithIdx( + 0 + ) + + atom.SetIntProp( + "old_mapno", + 2, + ) + + preparer._reveal_template_map_numbers( + molecule + ) + + assert atom.GetAtomMapNum() == 2 + + +def test_reveal_template_map_numbers_ignores_atom_without_property( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + molecule = mol("C") + + atom = molecule.GetAtomWithIdx( + 0 + ) + + atom.SetAtomMapNum(88) + + preparer._reveal_template_map_numbers( + molecule + ) + + assert atom.GetAtomMapNum() == 88 + + +def test_clear_isotopes( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + first = mol("CC") + second = mol("CO") + + for atom in first.GetAtoms(): + atom.SetIsotope(13) + + for atom in second.GetAtoms(): + atom.SetIsotope(18) + + preparer._clear_isotopes( + first, + second, + ) + + assert all( + atom.GetIsotope() == 0 + for atom in first.GetAtoms() + ) + + assert all( + atom.GetIsotope() == 0 + for atom in second.GetAtoms() + ) + + +# ============================================================================= +# Reaction / reactant construction +# ============================================================================= + + +def test_build_reaction_returns_rdkit_reaction( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reaction = preparer._build_reaction( + "[C:1].[O:2]>>[C:1][O:2]" + ) + + assert reaction is not None + + assert reaction.GetNumReactantTemplates() == 2 + assert reaction.GetNumProductTemplates() == 1 + + +def test_build_reactants_valid_smiles_adds_explicit_hydrogens( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + first, second = ( + preparer._build_reactants( + "C", + "O", + ) + ) + + # CH4 + assert first.GetNumAtoms() == 5 + + # H2O + assert second.GetNumAtoms() == 3 + + +def test_build_reactants_invalid_first_smiles( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + with pytest.raises( + SMARTSParsingError, + match="first reactant", + ): + preparer._build_reactants( + "not-a-smiles", + "O", + ) + + +def test_build_reactants_invalid_second_smiles( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + with pytest.raises( + SMARTSParsingError, + match="second reactant", + ): + preparer._build_reactants( + "C", + "not-a-smiles", + ) + + +def test_build_reaction_tuple_same_reactant( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + first = mol("C") + second = mol("O") + + result = preparer._build_reaction_tuple( + True, + first, + second, + ) + + assert len(result) == 1 + + assert result[0][0] is first + assert result[0][1] is first + + +def test_build_reaction_tuple_different_reactants( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + first = mol("C") + second = mol("O") + + result = preparer._build_reaction_tuple( + False, + first, + second, + ) + + assert result == [ + [ + first, + second, + ], + [ + second, + first, + ], + ] + + +# ============================================================================= +# Consecutive-number helper +# ============================================================================= + + +@pytest.mark.parametrize( + "values", + [ + [1], + [1, 2], + [3, 2, 1], + [-2, -1, 0, 1], + ], +) +def test_is_consecutive_true( + tmp_path, + values, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert preparer._is_consecutive( + values + ) + + +@pytest.mark.parametrize( + "values", + [ + [], + [1, 1], + [1, 3], + [0, 2, 3], + ], +) +def test_is_consecutive_false( + tmp_path, + values, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert not preparer._is_consecutive( + values + ) + + +# ============================================================================= +# Atom-index mapping construction +# ============================================================================= + + +def test_build_atom_index_mapping( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reactant = mol("CC") + product = mol("CC") + + reactant.GetAtomWithIdx( + 0 + ).SetAtomMapNum(1001) + + reactant.GetAtomWithIdx( + 1 + ).SetAtomMapNum(1002) + + product.GetAtomWithIdx( + 0 + ).SetAtomMapNum(1002) + + product.GetAtomWithIdx( + 1 + ).SetAtomMapNum(1001) + + mapping, dataframe = ( + preparer._build_atom_index_mapping( + reactant, + product, + ) + ) + + assert mapping == { + 0: 1, + 1: 0, + } + + assert dataframe.to_dict( + orient="records" + ) == [ + { + "reactant_idx": 0, + "product_idx": 1, + }, + { + "reactant_idx": 1, + "product_idx": 0, + }, + ] + + +def test_build_atom_index_mapping_ignores_zero_map_number( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reactant = mol("CC") + product = mol("CC") + + reactant.GetAtomWithIdx( + 0 + ).SetAtomMapNum(0) + + reactant.GetAtomWithIdx( + 1 + ).SetAtomMapNum(10) + + product.GetAtomWithIdx( + 0 + ).SetAtomMapNum(10) + + mapping, _ = ( + preparer._build_atom_index_mapping( + reactant, + product, + ) + ) + + assert mapping == { + 1: 0, + } + + +def test_build_atom_index_mapping_ignores_unmatched_reactant_tag( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reactant = mol("C") + product = mol("C") + + reactant.GetAtomWithIdx( + 0 + ).SetAtomMapNum(123) + + product.GetAtomWithIdx( + 0 + ).SetAtomMapNum(456) + + mapping, dataframe = ( + preparer._build_atom_index_mapping( + reactant, + product, + ) + ) + + assert mapping == {} + assert dataframe.empty + + +# ============================================================================= +# Mapping validation +# ============================================================================= + + +def test_validate_mapping_accepts_complete_bijection( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + 0, + 1, + ], + "product_idx": [ + 1, + 0, + ], + } + ) + + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_none_dataframe( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + with pytest.raises( + MappingError, + match="empty dataframe", + ): + preparer._validate_mapping( + None, + mol("C"), + mol("C"), + ) + + +def test_validate_mapping_rejects_empty_dataframe( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + with pytest.raises( + MappingError, + match="empty dataframe", + ): + preparer._validate_mapping( + pd.DataFrame(), + mol("C"), + mol("C"), + ) + + +def test_validate_mapping_requires_columns( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + with pytest.raises( + MappingError, + match="required columns", + ): + preparer._validate_mapping( + pd.DataFrame( + { + "wrong": [ + 0 + ] + } + ), + mol("C"), + mol("C"), + ) + + +def test_validate_mapping_rejects_count_mismatch( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": pd.Series( + [ + 0, + 1, + ], + dtype="Int64", + ), + "product_idx": pd.Series( + [ + 0, + pd.NA, + ], + dtype="Int64", + ), + } + ) + + with pytest.raises( + MappingError, + match="mismatch in atom counts", + ): + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_duplicate_reactant_idx( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + 0, + 0, + ], + "product_idx": [ + 0, + 1, + ], + } + ) + + with pytest.raises( + MappingError, + match="duplicate idxs.*reactant", + ): + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_duplicate_product_idx( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + 0, + 1, + ], + "product_idx": [ + 0, + 0, + ], + } + ) + + with pytest.raises( + MappingError, + match="duplicate idxs.*product", + ): + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_reactant_idx_above_bounds( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + 0, + 2, + ], + "product_idx": [ + 0, + 1, + ], + } + ) + + with pytest.raises( + MappingError, + match="reactant idx out of bounds", + ): + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_product_idx_above_bounds( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + 0, + 1, + ], + "product_idx": [ + 0, + 2, + ], + } + ) + + with pytest.raises( + MappingError, + match="product idx out of bounds", + ): + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_negative_reactant_idx( + tmp_path, +): + """ + A valid RDKit atom mapping cannot contain negative dataframe indices. + + This is an invariant test, not a change to reaction chemistry. + """ + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + -1, + 1, + ], + "product_idx": [ + 0, + 1, + ], + } + ) + + with pytest.raises( + MappingError, + match="reactant idx out of bounds", + ): + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_negative_product_idx( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + 0, + 1, + ], + "product_idx": [ + -1, + 1, + ], + } + ) + + with pytest.raises( + MappingError, + match="product idx out of bounds", + ): + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_incomplete_reactant( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + 0, + 1, + ], + "product_idx": [ + 0, + 1, + ], + } + ) + + with pytest.raises( + MappingError, + match="incomplete mapping for reactant", + ): + preparer._validate_mapping( + dataframe, + mol("CCC"), + mol("CC"), + ) + + +def test_validate_mapping_rejects_incomplete_product( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + dataframe = pd.DataFrame( + { + "reactant_idx": [ + 0, + 1, + ], + "product_idx": [ + 0, + 1, + ], + } + ) + + with pytest.raises( + MappingError, + match="incomplete mapping for product", + ): + preparer._validate_mapping( + dataframe, + mol("CC"), + mol("CCC"), + ) + + +# ============================================================================= +# First shell / initiators +# ============================================================================= + + +def test_assign_first_shell_and_initiators( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reactant = mol("CCC") + product = mol("CCC") + + product.GetAtomWithIdx( + 0 + ).SetAtomMapNum(1) + + product.GetAtomWithIdx( + 1 + ).SetAtomMapNum(2) + + product.GetAtomWithIdx( + 2 + ).SetAtomMapNum(999) + + first_shell, initiators = ( + preparer + ._assign_first_shell_and_initiators( + reactant, + product, + { + 0: 0, + 1: 1, + 2: 2, + }, + ) + ) + + assert first_shell == [ + 0, + 1, + ] + + assert initiators == [ + 0, + 1, + ] + + assert ( + reactant + .GetAtomWithIdx(0) + .GetAtomMapNum() + == 1 + ) + + assert ( + reactant + .GetAtomWithIdx(1) + .GetAtomMapNum() + == 2 + ) + + +def test_assign_first_shell_missing_reverse_mapping_raises( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reactant = mol("CC") + product = mol("CC") + + product.GetAtomWithIdx( + 0 + ).SetAtomMapNum(1) + + product.GetAtomWithIdx( + 1 + ).SetAtomMapNum(2) + + with pytest.raises( + ValueError, + match="not found in mapping", + ): + ( + preparer + ._assign_first_shell_and_initiators( + reactant, + product, + { + 0: 0, + }, + ) + ) + + +def test_assign_first_shell_requires_exactly_two_initiators( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reactant = mol("CC") + product = mol("CC") + + product.GetAtomWithIdx( + 0 + ).SetAtomMapNum(1) + + product.GetAtomWithIdx( + 1 + ).SetAtomMapNum(3) + + with pytest.raises( + ValueError, + match="Expected 2 initiators", + ): + ( + preparer + ._assign_first_shell_and_initiators( + reactant, + product, + { + 0: 0, + 1: 1, + }, + ) + ) + + +# ============================================================================= +# Byproduct detection +# ============================================================================= + + +def test_detect_byproducts_disabled_returns_empty( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + assert ( + preparer._detect_byproducts( + mol("CC.O"), + { + 0: 0, + 1: 1, + 2: 2, + }, + False, + ) + == [] + ) + + +def test_detect_byproducts_uses_smallest_fragment( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + product = mol( + "CC.O" + ) + + result = preparer._detect_byproducts( + product, + { + 0: 10, + 1: 11, + 2: 12, + }, + True, + ) + + assert result == [ + 12, + ] + + +def test_detect_byproducts_skips_unmapped_product_atoms( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + product = mol( + "CC.O" + ) + + result = preparer._detect_byproducts( + product, + { + 0: 10, + 1: 11, + }, + True, + ) + + assert result == [] + + +# ============================================================================= +# Duplicate handling +# ============================================================================= + + +def test_detect_duplicates_keeps_first_unique( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + first = make_metadata( + reaction_id=1 + ) + + result = preparer._detect_duplicates( + [ + first, + ] + ) + + assert result == [ + first, + ] + + assert first.activity_stats is True + + +def test_detect_duplicates_marks_later_duplicate_inactive_and_excludes_it( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + first = make_metadata( + reaction_id=1, + reactant_smiles="CC", + product_smiles="CO", + ) + + second = make_metadata( + reaction_id=2, + reactant_smiles="CC", + product_smiles="CO", + ) + + result = preparer._detect_duplicates( + [ + first, + second, + ] + ) + + # Characterizes current runtime behavior: + # duplicate is disabled AND omitted from the returned unique list. + assert result == [ + first, + ] + + assert first.activity_stats is True + assert second.activity_stats is False + + +def test_detect_duplicates_same_reactant_different_product_is_unique( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + first = make_metadata( + reaction_id=1, + reactant_smiles="CC", + product_smiles="CO", + ) + + second = make_metadata( + reaction_id=2, + reactant_smiles="CC", + product_smiles="CN", + ) + + result = preparer._detect_duplicates( + [ + first, + second, + ] + ) + + assert result == [ + first, + second, + ] + + +# ============================================================================= +# Reaction instance processing - initial stage +# ============================================================================= + + +def test_process_reaction_instances_initial_stage_uses_smiles( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = PrepareReactions( + session + ) + + reaction = make_reaction_instance( + monomer_1=make_monomer_role( + smiles="C" + ), + monomer_2=make_monomer_role( + smiles="O" + ), + ) + + first = mol("C") + second = mol("O") + + calls = [] + + monkeypatch.setattr( + preparer, + "_build_reactants", + lambda s1, s2: ( + calls.append( + ( + "reactants", + s1, + s2, + ) + ) + or ( + first, + second, + ) + ), + ) + + reaction_tuple = [ + [ + first, + second, + ] + ] + + monkeypatch.setattr( + preparer, + "_build_reaction_tuple", + lambda same, r1, r2: ( + calls.append( + ( + "tuple", + same, + ) + ) + or reaction_tuple + ), + ) + + fake_rxn = object() + + monkeypatch.setattr( + preparer, + "_build_reaction", + lambda smarts: ( + calls.append( + ( + "reaction", + smarts, + ) + ) + or fake_rxn + ), + ) + + monkeypatch.setattr( + preparer, + "_process_reaction_products", + lambda **kwargs: ( + calls.append( + ( + "products", + kwargs, + ) + ) + or [ + "metadata" + ] + ), + ) + + result = ( + preparer + ._process_reaction_instances( + [ + reaction, + ], + loop=False, + ) + ) + + assert result == [ + "metadata" + ] + + assert ( + "reactants", + "C", + "O", + ) in calls + + +def test_process_reaction_instances_same_reactants_uses_first_smiles_twice( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reaction = make_reaction_instance( + monomer_1=make_monomer_role( + smiles="CC" + ), + monomer_2=None, + same_reactants=True, + ) + + captured = [] + + monkeypatch.setattr( + preparer, + "_build_reactants", + lambda first, second: ( + captured.append( + ( + first, + second, + ) + ) + or ( + mol("CC"), + mol("CC"), + ) + ), + ) + + monkeypatch.setattr( + preparer, + "_build_reaction_tuple", + lambda *args: [], + ) + + monkeypatch.setattr( + preparer, + "_build_reaction", + lambda smarts: object(), + ) + + monkeypatch.setattr( + preparer, + "_process_reaction_products", + lambda **kwargs: + kwargs["reaction_metadata"], + ) + + preparer._process_reaction_instances( + [ + reaction, + ] + ) + + assert captured == [ + ( + "CC", + "CC", + ) + ] + + +# ============================================================================= +# Reaction instance processing - loop mode +# ============================================================================= + + +def test_process_reaction_instances_loop_skips_missing_monomer1_molecule( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reaction = make_reaction_instance( + monomer_1=make_monomer_role( + rdkit_mol=None, + ), + monomer_2=make_monomer_role( + rdkit_mol=mol("O"), + ), + ) + + monkeypatch.setattr( + preparer, + "_process_reaction_products", + lambda **kwargs: + pytest.fail( + "reaction should have been skipped" + ), + ) + + result = ( + preparer + ._process_reaction_instances( + [ + reaction, + ], + loop=True, + ) + ) + + assert result == [] + + +def test_process_reaction_instances_loop_skips_missing_monomer2_molecule( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reaction = make_reaction_instance( + monomer_1=make_monomer_role( + rdkit_mol=mol("C"), + ), + monomer_2=make_monomer_role( + rdkit_mol=None, + ), + ) + + monkeypatch.setattr( + preparer, + "_process_reaction_products", + lambda **kwargs: + pytest.fail( + "reaction should have been skipped" + ), + ) + + result = ( + preparer + ._process_reaction_instances( + [ + reaction, + ], + loop=True, + ) + ) + + assert result == [] + + +def test_process_reaction_instances_loop_passes_forced_fg_indices( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reaction = make_reaction_instance( + monomer_1=make_monomer_role( + rdkit_mol=mol("CC"), + is_monomer=False, + ), + monomer_2=make_monomer_role( + rdkit_mol=mol("CO"), + is_monomer=False, + ), + functional_group_1=make_fg( + fg_1_indexes=[ + ( + 1, + 2, + ) + ] + ), + functional_group_2=make_fg( + fg_1_indexes=[ + ( + 3, + 4, + ) + ] + ), + ) + + captured = [] + + monkeypatch.setattr( + preparer, + "_build_reaction", + lambda smarts: object(), + ) + + monkeypatch.setattr( + preparer, + "_process_reaction_products", + lambda **kwargs: ( + captured.append( + kwargs + ) + or [] + ), + ) + + preparer._process_reaction_instances( + [ + reaction, + ], + loop=True, + ) + + assert len(captured) == 1 + + assert ( + captured[0][ + "forced_indexes_1" + ] + == { + 1, + 2, + } + ) + + assert ( + captured[0][ + "forced_indexes_2" + ] + == { + 3, + 4, + } + ) + + assert len( + captured[0][ + "reaction_tuple" + ] + ) == 1 + + +# ============================================================================= +# Reaction product processing orchestration +# ============================================================================= + + +class FakeReaction: + def __init__( + self, + responses, + ): + self.responses = list( + responses + ) + self.calls = [] + + def RunReactants( + self, + reactants, + ): + self.calls.append( + reactants + ) + + if self.responses: + return self.responses.pop(0) + + return () + + +def configure_product_processing_helpers( + preparer, + monkeypatch, + *, + first_shell=None, + initiators=None, + byproducts=None, +): + if first_shell is None: + first_shell = [ + 0, + 1, + ] + + if initiators is None: + initiators = [ + 0, + 1, + ] + + if byproducts is None: + byproducts = [] + + monkeypatch.setattr( + preparer, + "_reassign_atom_map_numbers_by_isotope", + lambda molecule: None, + ) + + monkeypatch.setattr( + preparer, + "_build_atom_index_mapping", + lambda reactant, product: ( + { + 0: 0, + 1: 1, + }, + pd.DataFrame( + { + "reactant_idx": [ + 0, + 1, + ], + "product_idx": [ + 0, + 1, + ], + } + ), + ), + ) + + monkeypatch.setattr( + preparer, + "_reveal_template_map_numbers", + lambda molecule: None, + ) + + monkeypatch.setattr( + preparer, + "_validate_mapping", + lambda *args: None, + ) + + monkeypatch.setattr( + preparer, + "_assign_first_shell_and_initiators", + lambda *args: ( + first_shell, + initiators, + ), + ) + + monkeypatch.setattr( + preparer, + "_detect_byproducts", + lambda *args: + byproducts, + ) + + +def test_process_reaction_products_creates_metadata_and_csv( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = PrepareReactions( + session + ) + + product = Chem.CombineMols( + mol("C"), + mol("O"), + ) + + reaction = FakeReaction( + [ + ( + ( + product, + ), + ) + ] + ) + + configure_product_processing_helpers( + preparer, + monkeypatch, + ) + + result = ( + preparer + ._process_reaction_products( + rxn=reaction, + csv_cache=preparer.csv_cache, + reaction_tuple=[ + [ + mol("C"), + mol("O"), + ] + ], + delete_atoms=False, + ) + ) + + assert len(result) == 1 + + metadata = result[0] + + assert metadata.reaction_id == 1 + + assert ( + session.reaction_id_counter + == 1 + ) + + assert metadata.csv_path.is_file() + + assert metadata.first_shell == [ + 0, + 1, + ] + + assert metadata.initiators == [ + 0, + 1, + ] + + assert ( + metadata.activity_stats + is True + ) + + +def test_process_reaction_products_appends_to_existing_list( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + existing = [ + "existing" + ] + + product = Chem.CombineMols( + mol("C"), + mol("O"), + ) + + reaction = FakeReaction( + [ + ( + ( + product, + ), + ) + ] + ) + + configure_product_processing_helpers( + preparer, + monkeypatch, + ) + + result = ( + preparer + ._process_reaction_products( + reaction, + preparer.csv_cache, + [ + [ + mol("C"), + mol("O"), + ] + ], + reaction_metadata=existing, + ) + ) + + assert result is existing + assert result[0] == "existing" + assert len(result) == 2 + + +def test_process_reaction_products_tries_reverse_order_after_failure( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + product = Chem.CombineMols( + mol("C"), + mol("O"), + ) + + reaction = FakeReaction( + [ + (), + ( + ( + product, + ), + ), + ] + ) + + configure_product_processing_helpers( + preparer, + monkeypatch, + ) + + result = ( + preparer + ._process_reaction_products( + reaction, + preparer.csv_cache, + [ + [ + mol("C"), + mol("O"), + ] + ], + ) + ) + + assert len(reaction.calls) == 2 + assert len(result) == 1 + + +def test_process_reaction_products_both_orders_fail_returns_no_metadata( + tmp_path, + capsys, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + # Use a real RDKit ChemicalReaction here because the failure-reporting + # path calls ReactionToSmarts(rxn). + # + # This reaction requires two nitrogen reactants, while we provide + # carbon and oxygen, so both reactant orders legitimately produce + # no products. + reaction = preparer._build_reaction( + "[N:1].[N:2]>>[N:1][N:2]" + ) + + result = ( + preparer + ._process_reaction_products( + reaction, + preparer.csv_cache, + [ + [ + mol("C"), + mol("O"), + ] + ], + ) + ) + + assert result == [] + + assert ( + preparer.session + .reaction_id_counter + == 0 + ) + + output = capsys.readouterr().out + + assert ( + "Reaction failed in both orders" + in output + ) + + assert ( + "RDKit failed to react" + in output + ) + + assert ( + "Reaction SMARTS:" + in output + ) + + +def test_process_reaction_products_forced_indexes_can_reject_product( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + product = Chem.CombineMols( + mol("C"), + mol("O"), + ) + + reaction = FakeReaction( + [ + ( + ( + product, + ), + ) + ] + ) + + configure_product_processing_helpers( + preparer, + monkeypatch, + initiators=[ + 0, + 1, + ], + ) + + result = ( + preparer + ._process_reaction_products( + reaction, + preparer.csv_cache, + [ + [ + mol("C"), + mol("O"), + ] + ], + forced_indexes_1={ + 999, + }, + forced_indexes_2={ + 999, + }, + ) + ) + + assert result == [] + + assert ( + preparer.session + .reaction_id_counter + == 0 + ) + + +def test_process_reaction_products_sets_delete_atom_idx( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + product = Chem.CombineMols( + mol("C"), + mol("O"), + ) + + reaction = FakeReaction( + [ + ( + ( + product, + ), + ) + ] + ) + + configure_product_processing_helpers( + preparer, + monkeypatch, + byproducts=[ + 1, + ], + ) + + result = ( + preparer + ._process_reaction_products( + reaction, + preparer.csv_cache, + [ + [ + mol("C"), + mol("O"), + ] + ], + delete_atoms=True, + ) + ) + + metadata = result[0] + + assert metadata.byproduct_indices == [ + 1, + ] + + assert metadata.delete_atom_idx == 1 + + +# ============================================================================= +# _prepare_reactions_stage +# ============================================================================= + + +def test_prepare_reactions_stage_adds_template_mapping_and_edges( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reaction = make_metadata( + reaction_id=1, + reactant_smiles="CCC", + product_smiles="CCC", + mapping={ + 0: 0, + 1: 1, + 2: 2, + }, + tmp_path=tmp_path, + ) + + reaction.reaction_dataframe = ( + pd.DataFrame( + { + "reactant_idx": [ + 0, + 1, + 2, + ], + "product_idx": [ + 0, + 1, + 2, + ], + "first_shell": pd.Series( + [ + 1, + pd.NA, + pd.NA, + ], + dtype="Int64", + ), + } + ) + ) + + monkeypatch.setattr( + preparer, + "_process_reaction_instances", + lambda detected, loop=False: [ + reaction + ], + ) + + monkeypatch.setattr( + preparer, + "_detect_duplicates", + lambda reactions: + reactions, + ) + + monkeypatch.setattr( + prepare_module, + "reaction_atom_walker", + lambda molecule, first_shell, mapping: + ( + { + 0: 0, + 1: 1, + }, + [ + 2, + ], + ), + ) + + session = make_session( + tmp_path, + reaction_instances=[ + object() + ], + ) + + result = ( + preparer + ._prepare_reactions_stage( + session + ) + ) + + assert result == [ + reaction + ] + + assert ( + reaction + .template_reactant_to_product_mapping + == { + 0: 0, + 1: 1, + } + ) + + assert reaction.edge_atoms == [ + 2, + ] + + assert ( + "template_reactant_idx" + in reaction + .reaction_dataframe + .columns + ) + + assert ( + "edge_atoms" + in reaction + .reaction_dataframe + .columns + ) + + assert reaction.csv_path.is_file() + + +def test_prepare_reactions_stage_skips_inactive_reactions( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + reaction = make_metadata( + activity_stats=False, + tmp_path=tmp_path, + ) + + monkeypatch.setattr( + preparer, + "_process_reaction_instances", + lambda detected, loop=False: [ + reaction + ], + ) + + monkeypatch.setattr( + preparer, + "_detect_duplicates", + lambda reactions: + reactions, + ) + + monkeypatch.setattr( + prepare_module, + "reaction_atom_walker", + lambda *args: + pytest.fail( + "inactive reaction should not be walked" + ), + ) + + result = ( + preparer + ._prepare_reactions_stage( + [] + ) + ) + + assert result == [ + reaction + ] + + +def test_prepare_reactions_stage_accepts_direct_reaction_instance_list( + tmp_path, + monkeypatch, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + instances = [ + object(), + object(), + ] + + captured = [] + + monkeypatch.setattr( + preparer, + "_process_reaction_instances", + lambda detected, loop=False: ( + captured.append( + ( + detected, + loop, + ) + ) + or [] + ), + ) + + monkeypatch.setattr( + preparer, + "_detect_duplicates", + lambda reactions: + reactions, + ) + + result = ( + preparer + ._prepare_reactions_stage( + instances, + loop=True, + ) + ) + + assert result == [] + + assert captured == [ + ( + instances, + True, + ) + ] + + +# ============================================================================= +# _index_based_reaction_preparation +# ============================================================================= + + +def test_index_based_reaction_preparation_creates_fresh_preparer_and_uses_loop_mode( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = PrepareReactions( + session + ) + + calls = [] + + class FakePreparer: + def __init__( + self, + received_session, + ): + calls.append( + ( + "init", + received_session, + ) + ) + + def _prepare_reactions_stage( + self, + reaction_instances, + loop=False, + ): + calls.append( + ( + "stage", + reaction_instances, + loop, + ) + ) + + return [ + "prepared" + ] + + monkeypatch.setattr( + prepare_module, + "PrepareReactions", + FakePreparer, + ) + + instances = [ + object() + ] + + result = ( + preparer + ._index_based_reaction_preparation( + instances + ) + ) + + assert result == [ + "prepared" + ] + + assert calls == [ + ( + "init", + session, + ), + ( + "stage", + instances, + True, + ), + ] + + +# ============================================================================= +# prepare_reactions() orchestration +# ============================================================================= + + +def test_prepare_reactions_nonloop_deduplicates( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path, + loop=False, + deep_search=False, + ) + + preparer = PrepareReactions( + session + ) + + prepared = [ + SimpleNamespace( + activity_stats=True + ) + ] + + final = [ + SimpleNamespace( + activity_stats=True + ) + ] + + monkeypatch.setattr( + preparer, + "_prepare_reactions_stage", + lambda received_session: + prepared, + ) + + calls = [] + + class FakeDeduplicator: + def compare_graphs_mol( + self, + reactions, + deep_check=True, + ): + calls.append( + ( + reactions, + deep_check, + ) + ) + + return final + + monkeypatch.setattr( + prepare_module, + "DeduplicationDetector", + FakeDeduplicator, + ) + + result = preparer.prepare_reactions( + session + ) + + assert result is session + + assert ( + session.reaction_metadata + is final + ) + + assert calls == [ + ( + prepared, + False, + ) + ] + + +def test_prepare_reactions_nonloop_rejects_zero_active_before_dedup( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path, + loop=False, + ) + + preparer = PrepareReactions( + session + ) + + monkeypatch.setattr( + preparer, + "_prepare_reactions_stage", + lambda received_session: [ + SimpleNamespace( + activity_stats=False + ) + ], + ) + + with pytest.raises( + ZeroActiveReactionsError + ): + preparer.prepare_reactions( + session + ) + + +def test_prepare_reactions_loop_uses_progression( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path, + loop=True, + ) + + preparer = PrepareReactions( + session + ) + + initial = [ + SimpleNamespace( + activity_stats=True + ) + ] + + final = [ + SimpleNamespace( + activity_stats=True + ) + ] + + monkeypatch.setattr( + preparer, + "_prepare_reactions_stage", + lambda received_session: + initial, + ) + + calls = [] + + class FakeProgression: + def __init__( + self, + received_session, + preparer=None, + ): + calls.append( + ( + "init", + received_session, + preparer, + ) + ) + + def reaction_progression( + self, + ): + calls.append( + ( + "run", + ) + ) + + return final + + monkeypatch.setattr( + prepare_module, + "ReactionProgression", + FakeProgression, + ) + + result = preparer.prepare_reactions( + session + ) + + assert result is session + + assert ( + session.reaction_metadata + is final + ) + + assert calls == [ + ( + "init", + session, + preparer, + ), + ( + "run", + ), + ] + + +def test_prepare_reactions_loop_rejects_zero_active_final_pool( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path, + loop=True, + ) + + preparer = PrepareReactions( + session + ) + + monkeypatch.setattr( + preparer, + "_prepare_reactions_stage", + lambda received_session: [ + SimpleNamespace( + activity_stats=True + ) + ], + ) + + class FakeProgression: + def __init__( + self, + session, + preparer=None, + ): + pass + + def reaction_progression( + self, + ): + return [ + SimpleNamespace( + activity_stats=False + ) + ] + + monkeypatch.setattr( + prepare_module, + "ReactionProgression", + FakeProgression, + ) + + with pytest.raises( + ZeroActiveReactionsError + ): + preparer.prepare_reactions( + session + ) + + +# ============================================================================= +# Highlighted reaction-template images +# ============================================================================= + + +def make_image_metadata(): + metadata = make_metadata( + reaction_id=1, + reactant_smiles="CCO", + product_smiles="CCO", + mapping={ + 0: 0, + 1: 1, + 2: 2, + }, + ) + + metadata.template_reactant_to_product_mapping = { + 0: 0, + 1: 1, + } + + metadata.edge_atoms = [ + 2, + ] + + metadata.byproduct_indices = [ + 2, + ] + + metadata.delete_atom = True + + metadata.reaction_dataframe = ( + pd.DataFrame( + { + "initiators": pd.Series( + [ + 0, + 1, + pd.NA, + ], + dtype="Int64", + ) + } + ) + ) + + return metadata + + +def test_reaction_templates_image_empty_metadata_returns_none( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + session = SimpleNamespace( + reaction_metadata=[] + ) + + assert ( + preparer + .reaction_templates_highlighted_image_grid( + session + ) + is None + ) + + +def test_reaction_templates_image_all_inactive_returns_none( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + metadata = make_image_metadata() + metadata.activity_stats = False + + session = SimpleNamespace( + reaction_metadata=[ + metadata + ] + ) + + assert ( + preparer + .reaction_templates_highlighted_image_grid( + session + ) + is None + ) + + +@pytest.mark.parametrize( + "highlight_type", + [ + "template", + "edge", + "initiators", + "delete", + ], +) +def test_reaction_templates_highlight_types_generate_image( + tmp_path, + highlight_type, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + metadata = make_image_metadata() + + session = SimpleNamespace( + reaction_metadata=[ + metadata + ] + ) + + image = ( + preparer + .reaction_templates_highlighted_image_grid( + session, + highlight_type=highlight_type, + ) + ) + + assert image is not None + assert image.size[0] > 0 + assert image.size[1] > 0 + + +def test_reaction_templates_image_does_not_clear_original_atom_maps( + tmp_path, +): + preparer = PrepareReactions( + make_session(tmp_path) + ) + + metadata = make_image_metadata() + + metadata.reactant_combined_RDmol.GetAtomWithIdx( + 0 + ).SetAtomMapNum(123) + + metadata.product_combined_RDmol.GetAtomWithIdx( + 0 + ).SetAtomMapNum(456) + + session = SimpleNamespace( + reaction_metadata=[ + metadata + ] + ) + + preparer.reaction_templates_highlighted_image_grid( + session, + highlight_type="template", + ) + + assert ( + metadata + .reactant_combined_RDmol + .GetAtomWithIdx(0) + .GetAtomMapNum() + == 123 + ) + + assert ( + metadata + .product_combined_RDmol + .GetAtomWithIdx(0) + .GetAtomMapNum() + == 456 + ) diff --git a/tests/unit/reaction_preparation/reaction_processor/test_reaction_progression.py b/tests/unit/reaction_preparation/reaction_processor/test_reaction_progression.py new file mode 100644 index 00000000..2232bd4a --- /dev/null +++ b/tests/unit/reaction_preparation/reaction_processor/test_reaction_progression.py @@ -0,0 +1,2221 @@ +from types import SimpleNamespace + +import pytest +from rdkit import Chem + +import AutoREACTER.reaction_preparation.reaction_processor.reaction_progression as progression_module +from AutoREACTER.reaction_preparation.reaction_processor.reaction_progression import ( + MAX_LOOP, + MonomerRoleforIndexBasedFGDetection, + ReactionProgression, + ReactionProgressionSession, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def mol(smiles: str) -> Chem.Mol: + molecule = Chem.MolFromSmiles(smiles) + + assert molecule is not None + + return molecule + + +def make_role( + smiles="CC", + name="monomer", + *, + is_monomer=True, + is_looped=False, + rdkit_mol=None, +): + return SimpleNamespace( + smiles=smiles, + name=name, + is_monomer=is_monomer, + is_looped=is_looped, + rdkit_mol=rdkit_mol, + ) + + +def make_reaction( + reaction_id=1, + *, + reactant_smiles="CC", + product_smiles="CC", + activity_stats=True, + delete_atom=False, + template_mapping=None, + product_to_reactant_mapping=None, + is_radical=False, +): + reactant = mol(reactant_smiles) + product = mol(product_smiles) + + if template_mapping is None: + template_mapping = { + idx: idx + for idx in range( + min( + reactant.GetNumAtoms(), + product.GetNumAtoms(), + ) + ) + } + + if product_to_reactant_mapping is None: + product_to_reactant_mapping = { + product_idx: reactant_idx + for reactant_idx, product_idx + in template_mapping.items() + } + + return SimpleNamespace( + reaction_id=reaction_id, + reactant_combined_RDmol=reactant, + product_combined_RDmol=product, + template_reactant_to_product_mapping=template_mapping, + product_to_reactant_mapping=product_to_reactant_mapping, + activity_stats=activity_stats, + delete_atom=delete_atom, + is_radical=is_radical, + radical_atom_idxs=(), + ) + + +def make_session( + *, + monomer_roles=None, + reaction_metadata=None, + deep_search=True, + reaction_iteration_depth=5, +): + return SimpleNamespace( + monomer_roles=list( + monomer_roles or [] + ), + reaction_metadata=list( + reaction_metadata or [] + ), + reaction_progression_session=None, + inputs=SimpleNamespace( + deep_search=deep_search, + reaction_iteration_depth=reaction_iteration_depth, + ), + ) + + +def make_progression( + session, + preparer=None, +): + """ + Build a ReactionProgression without invoking its constructor. + + Most method-level tests do not need real detector construction or the + user-facing beta warning. + """ + progression = ReactionProgression.__new__( + ReactionProgression + ) + + progression.session = session + progression.preparer = preparer + + if ( + session.reaction_progression_session + is None + ): + session.reaction_progression_session = ( + ReactionProgressionSession() + ) + + progression.fg_detector = ( + SimpleNamespace() + ) + + progression.rxn_detector = ( + SimpleNamespace() + ) + + progression.deduplication_detector = ( + SimpleNamespace() + ) + + return progression + + +# ============================================================================= +# Dataclasses +# ============================================================================= + + +def test_index_based_role_required_fields(): + role = ( + MonomerRoleforIndexBasedFGDetection( + smiles="CC", + name="new_1", + indexes_in_template=[0, 1], + ) + ) + + assert role.smiles == "CC" + assert role.name == "new_1" + + assert role.indexes_in_template == [ + 0, + 1, + ] + + +def test_index_based_role_defaults(): + role = ( + MonomerRoleforIndexBasedFGDetection( + smiles="C", + name="new_1", + indexes_in_template=[], + ) + ) + + assert role.is_monomer is False + assert role.is_looped is False + assert role.rdkit_mol is None + + +def test_index_based_role_uses_slots(): + role = ( + MonomerRoleforIndexBasedFGDetection( + smiles="C", + name="new_1", + indexes_in_template=[], + ) + ) + + with pytest.raises( + AttributeError + ): + role.unexpected = True + + +def test_progression_session_defaults(): + session = ReactionProgressionSession() + + assert session.monomer_roles == [] + assert session.iteration == 0 + + +def test_progression_session_lists_are_independent(): + first = ReactionProgressionSession() + second = ReactionProgressionSession() + + first.monomer_roles.append( + object() + ) + + assert second.monomer_roles == [] + + +def test_progression_session_uses_slots(): + session = ReactionProgressionSession() + + with pytest.raises( + AttributeError + ): + session.unexpected = True + + +def test_max_loop_constant(): + assert MAX_LOOP == 5 + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_attaches_progression_session( + monkeypatch, +): + session = make_session() + + monkeypatch.setattr( + progression_module, + "FunctionalGroupsDetector", + lambda: "fg-detector", + ) + + monkeypatch.setattr( + progression_module, + "ReactionDetector", + lambda: "rxn-detector", + ) + + monkeypatch.setattr( + progression_module, + "DeduplicationDetector", + lambda: "dedup-detector", + ) + + warnings = [] + + monkeypatch.setattr( + progression_module, + "print_warning", + lambda: warnings.append(True), + ) + + preparer = object() + + progression = ReactionProgression( + session, + preparer=preparer, + ) + + assert progression.session is session + assert progression.preparer is preparer + + assert isinstance( + session.reaction_progression_session, + ReactionProgressionSession, + ) + + assert progression.fg_detector == ( + "fg-detector" + ) + + assert progression.rxn_detector == ( + "rxn-detector" + ) + + assert ( + progression.deduplication_detector + == "dedup-detector" + ) + + assert warnings == [ + True + ] + + +def test_constructor_replaces_existing_progression_session( + monkeypatch, +): + old = ReactionProgressionSession( + iteration=99 + ) + + session = make_session() + session.reaction_progression_session = old + + monkeypatch.setattr( + progression_module, + "FunctionalGroupsDetector", + lambda: object(), + ) + + monkeypatch.setattr( + progression_module, + "ReactionDetector", + lambda: object(), + ) + + monkeypatch.setattr( + progression_module, + "DeduplicationDetector", + lambda: object(), + ) + + monkeypatch.setattr( + progression_module, + "print_warning", + lambda: None, + ) + + ReactionProgression(session) + + assert ( + session.reaction_progression_session + is not old + ) + + assert ( + session + .reaction_progression_session + .iteration + == 0 + ) + + +# ============================================================================= +# Thin preparation wrapper +# ============================================================================= + + +def test_index_based_reaction_preparation_delegates(): + session = make_session() + + calls = [] + + class FakePreparer: + def _prepare_reactions_stage( + self, + reaction_instances, + loop=False, + ): + calls.append( + ( + reaction_instances, + loop, + ) + ) + + return [ + "prepared" + ] + + progression = make_progression( + session, + preparer=FakePreparer(), + ) + + instances = [ + object(), + object(), + ] + + result = ( + progression + ._index_based_reaction_preparation( + instances + ) + ) + + assert result == [ + "prepared" + ] + + assert calls == [ + ( + instances, + True, + ) + ] + + +# ============================================================================= +# Basic bookkeeping helpers +# ============================================================================= + + +def test_store_reactions_updates_session(): + session = make_session() + + progression = make_progression( + session + ) + + reactions = [ + object(), + object(), + ] + + result = progression._store_reactions( + reactions + ) + + assert result is reactions + + assert ( + session.reaction_metadata + is reactions + ) + + +def test_count_active_reactions(): + progression = make_progression( + make_session() + ) + + reactions = [ + SimpleNamespace( + activity_stats=True + ), + SimpleNamespace( + activity_stats=False + ), + SimpleNamespace( + activity_stats=1 + ), + SimpleNamespace( + activity_stats=None + ), + ] + + assert ( + progression + ._count_active_reactions( + reactions + ) + == 2 + ) + + +def test_count_active_reactions_empty_list(): + progression = make_progression( + make_session() + ) + + assert ( + progression + ._count_active_reactions([]) + == 0 + ) + + +def test_set_is_looped_flag_marks_all_roles(): + roles = [ + make_role( + is_looped=False + ), + make_role( + is_looped=False + ), + ] + + progression = make_progression( + make_session() + ) + + progression._set_is_looped_flag( + roles + ) + + assert all( + role.is_looped + for role in roles + ) + + +def test_set_is_looped_flag_empty_list(): + progression = make_progression( + make_session() + ) + + progression._set_is_looped_flag( + [] + ) + + +# ============================================================================= +# Loop break logic +# ============================================================================= + + +@pytest.mark.parametrize( + "before, after", + [ + (1, 1), + (2, 1), + (5, 0), + ], +) +def test_loop_break_condition_true_when_pool_does_not_grow( + before, + after, +): + progression = make_progression( + make_session() + ) + + assert ( + progression + ._loop_break_condition( + before, + after, + ) + is True + ) + + +@pytest.mark.parametrize( + "before, after", + [ + (0, 1), + (1, 2), + (10, 11), + ], +) +def test_loop_break_condition_false_when_pool_grows( + before, + after, +): + progression = make_progression( + make_session() + ) + + assert ( + progression + ._loop_break_condition( + before, + after, + ) + is False + ) + + +def test_loop_break_condition_prints_reason( + capsys, +): + progression = make_progression( + make_session() + ) + + progression._loop_break_condition( + 3, + 3, + ) + + output = capsys.readouterr().out + + assert ( + "pool did not grow" + in output + ) + + assert "before=3" in output + assert "after=3" in output + + +# ============================================================================= +# Monomer population +# ============================================================================= + + +def test_smiles_to_rdkit_mol_valid(): + progression = make_progression( + make_session() + ) + + result = ( + progression + ._smiles_to_rdkit_mol( + "CCO" + ) + ) + + assert isinstance( + result, + Chem.Mol, + ) + + +def test_smiles_to_rdkit_mol_invalid_returns_none(): + progression = make_progression( + make_session() + ) + + result = ( + progression + ._smiles_to_rdkit_mol( + "not-a-smiles" + ) + ) + + assert result is None + + +def test_populate_monomer_roles_only_populates_monomers(): + monomer = make_role( + smiles="CC", + is_monomer=True, + ) + + generated = make_role( + smiles="CO", + is_monomer=False, + ) + + session = make_session( + monomer_roles=[ + monomer, + generated, + ] + ) + + progression = make_progression( + session + ) + + progression._populate_monomer_roles() + + assert isinstance( + monomer.rdkit_mol, + Chem.Mol, + ) + + assert generated.rdkit_mol is None + + +def test_populate_monomer_roles_invalid_smiles_sets_none(): + role = make_role( + smiles="not-a-smiles", + is_monomer=True, + rdkit_mol=object(), + ) + + session = make_session( + monomer_roles=[ + role + ] + ) + + progression = make_progression( + session + ) + + progression._populate_monomer_roles() + + assert role.rdkit_mol is None + + +# ============================================================================= +# Product cleanup +# ============================================================================= + + +def test_clean_product_returns_copy(): + progression = make_progression( + make_session() + ) + + molecule = mol("CC") + + cleaned = ( + progression + ._clean_product( + molecule + ) + ) + + assert cleaned is not molecule + + assert ( + Chem.MolToSmiles(cleaned) + == Chem.MolToSmiles(molecule) + ) + + +def test_clean_product_removes_atom_map_numbers(): + progression = make_progression( + make_session() + ) + + molecule = mol("CC") + + molecule.GetAtomWithIdx( + 0 + ).SetAtomMapNum(123) + + cleaned = ( + progression + ._clean_product( + molecule + ) + ) + + assert ( + cleaned + .GetAtomWithIdx(0) + .GetAtomMapNum() + == 0 + ) + + # Original must remain unchanged. + assert ( + molecule + .GetAtomWithIdx(0) + .GetAtomMapNum() + == 123 + ) + + +def test_clean_product_removes_isotopes(): + progression = make_progression( + make_session() + ) + + molecule = mol("CC") + + molecule.GetAtomWithIdx( + 0 + ).SetIsotope(13) + + cleaned = ( + progression + ._clean_product( + molecule + ) + ) + + assert ( + cleaned + .GetAtomWithIdx(0) + .GetIsotope() + == 0 + ) + + assert ( + molecule + .GetAtomWithIdx(0) + .GetIsotope() + == 13 + ) + + +def test_clean_product_removes_tracking_properties(): + progression = make_progression( + make_session() + ) + + molecule = mol("C") + + atom = molecule.GetAtomWithIdx( + 0 + ) + + atom.SetIntProp( + "old_mapno", + 1, + ) + + atom.SetIntProp( + "react_atom_idx", + 2, + ) + + cleaned = ( + progression + ._clean_product( + molecule + ) + ) + + cleaned_atom = ( + cleaned.GetAtomWithIdx(0) + ) + + assert not cleaned_atom.HasProp( + "old_mapno" + ) + + assert not cleaned_atom.HasProp( + "react_atom_idx" + ) + + +# ============================================================================= +# Product SMILES +# ============================================================================= + + +def test_get_product_smiles_returns_canonical_smiles(): + progression = make_progression( + make_session() + ) + + result = ( + progression + ._get_product_smiles( + mol("OCC") + ) + ) + + assert result == Chem.MolToSmiles( + mol("CCO") + ) + + +def test_get_product_smiles_removes_mapping_artifacts(): + progression = make_progression( + make_session() + ) + + molecule = mol("CC") + + molecule.GetAtomWithIdx( + 0 + ).SetAtomMapNum(999) + + result = ( + progression + ._get_product_smiles( + molecule + ) + ) + + assert ":" not in result + + +# ============================================================================= +# Product index handling +# ============================================================================= + + +def test_get_product_idxs_single_fragment_preserves_indexes(): + progression = make_progression( + make_session() + ) + + molecule = mol("CCC") + + mapping = { + 10: 0, + 11: 2, + } + + idxs, result_mol = ( + progression + ._get_product_idxs( + mapping, + molecule, + ) + ) + + assert idxs == [ + 0, + 2, + ] + + assert ( + Chem.MolToSmiles( + result_mol + ) + == Chem.MolToSmiles( + molecule + ) + ) + + +def test_get_product_idxs_returns_molecule_copy(): + progression = make_progression( + make_session() + ) + + molecule = mol("CC") + + _, result = ( + progression + ._get_product_idxs( + { + 0: 0, + }, + molecule, + ) + ) + + assert result is not molecule + + +def test_keep_largest_fragment_uses_heavy_atom_count(): + progression = make_progression( + make_session() + ) + + molecule = mol( + "CCCO.CC" + ) + + largest, _ = ( + progression + ._keep_largest_fragment( + molecule, + [], + ) + ) + + assert ( + largest.GetNumHeavyAtoms() + == 4 + ) + + +def test_keep_largest_fragment_remaps_product_indices(): + progression = make_progression( + make_session() + ) + + # First fragment atoms: 0,1 + # Second/larger fragment atoms: 2,3,4 + molecule = mol( + "CC.CCC" + ) + + largest, remapped = ( + progression + ._keep_largest_fragment( + molecule, + [ + 2, + 4, + ], + ) + ) + + assert ( + largest.GetNumHeavyAtoms() + == 3 + ) + + assert remapped == [ + 0, + 2, + ] + + +def test_keep_largest_fragment_drops_indices_from_removed_fragment(): + progression = make_progression( + make_session() + ) + + molecule = mol( + "CC.CCC" + ) + + _, remapped = ( + progression + ._keep_largest_fragment( + molecule, + [ + 0, + 2, + 3, + ], + ) + ) + + assert remapped == [ + 0, + 1, + ] + + +def test_get_product_idxs_multifragment_keeps_largest_fragment(): + progression = make_progression( + make_session() + ) + + molecule = mol( + "CC.CCC" + ) + + idxs, result = ( + progression + ._get_product_idxs( + { + 10: 2, + 11: 4, + }, + molecule, + ) + ) + + assert ( + result.GetNumHeavyAtoms() + == 3 + ) + + assert idxs == [ + 0, + 2, + ] + + +# ============================================================================= +# Radical metadata +# ============================================================================= + + +def test_set_reaction_radical_metadata_no_radicals(): + progression = make_progression( + make_session() + ) + + reaction = make_reaction( + product_smiles="CC", + ) + + progression._set_reaction_radical_metadata( + reaction, + mol("CC"), + ) + + assert reaction.is_radical is False + + assert ( + reaction.radical_atom_idxs + == () + ) + + +def test_set_reaction_radical_metadata_maps_product_idx_to_reactant_idx(): + progression = make_progression( + make_session() + ) + + reaction = make_reaction( + product_smiles="[CH3]", + template_mapping={ + 5: 0, + }, + product_to_reactant_mapping={ + 0: 5, + }, + ) + + radical_product = mol( + "[CH3]" + ) + + progression._set_reaction_radical_metadata( + reaction, + radical_product, + ) + + assert reaction.is_radical is True + + assert ( + reaction.radical_atom_idxs + == (5,) + ) + + +def test_set_reaction_radical_metadata_ignores_unmapped_product_radical(): + progression = make_progression( + make_session() + ) + + reaction = make_reaction( + product_smiles="[CH3]", + template_mapping={ + 0: 0, + }, + product_to_reactant_mapping={}, + ) + + progression._set_reaction_radical_metadata( + reaction, + mol("[CH3]"), + ) + + assert reaction.is_radical is False + assert reaction.radical_atom_idxs == () + + +# ============================================================================= +# Radical annotation before deduplication +# ============================================================================= + + +def test_annotate_radicals_skips_inactive_reactions( + monkeypatch, +): + progression = make_progression( + make_session() + ) + + reaction = make_reaction( + activity_stats=False + ) + + calls = [] + + monkeypatch.setattr( + progression, + "_sanitize_molecule", + lambda mol: ( + calls.append(True) + or (mol, True) + ), + ) + + progression._annotate_radicals_before_deduplication( + [ + reaction, + ] + ) + + assert calls == [] + + +def test_annotate_radicals_handles_missing_product(): + progression = make_progression( + make_session() + ) + + reaction = make_reaction() + + reaction.product_combined_RDmol = None + reaction.is_radical = True + reaction.radical_atom_idxs = ( + 10, + ) + + progression._annotate_radicals_before_deduplication( + [ + reaction, + ] + ) + + assert reaction.is_radical is False + assert reaction.radical_atom_idxs == () + + +def test_annotate_radicals_handles_failed_sanitization( + monkeypatch, +): + progression = make_progression( + make_session() + ) + + reaction = make_reaction() + + reaction.is_radical = True + reaction.radical_atom_idxs = ( + 1, + ) + + monkeypatch.setattr( + progression, + "_sanitize_molecule", + lambda mol: ( + mol, + False, + ), + ) + + progression._annotate_radicals_before_deduplication( + [ + reaction, + ] + ) + + assert reaction.is_radical is False + assert reaction.radical_atom_idxs == () + + +def test_annotate_radicals_delegates_metadata_on_success( + monkeypatch, +): + progression = make_progression( + make_session() + ) + + reaction = make_reaction() + + sanitized = mol("CC") + + calls = [] + + monkeypatch.setattr( + progression, + "_sanitize_molecule", + lambda mol: ( + sanitized, + True, + ), + ) + + monkeypatch.setattr( + progression, + "_set_reaction_radical_metadata", + lambda rxn, molecule: + calls.append( + ( + rxn, + molecule, + ) + ), + ) + + progression._annotate_radicals_before_deduplication( + [ + reaction, + ] + ) + + assert calls == [ + ( + reaction, + sanitized, + ) + ] + + +# ============================================================================= +# Sanitization +# ============================================================================= + + +def test_sanitize_simple_molecule_succeeds(): + progression = make_progression( + make_session() + ) + + result, success = ( + progression + ._sanitize_molecule( + mol("CC") + ) + ) + + assert success is True + + assert isinstance( + result, + Chem.Mol, + ) + + +def test_sanitize_returns_new_molecule(): + progression = make_progression( + make_session() + ) + + original = mol("CC") + + result, success = ( + progression + ._sanitize_molecule( + original + ) + ) + + assert success is True + assert result is not original + + +def test_fix_radical_and_sanitize_returns_molecule(): + progression = make_progression( + make_session() + ) + + result = ( + progression + ._fix_radical_and_sanitize( + mol("[CH3]") + ) + ) + + assert isinstance( + result, + Chem.Mol, + ) + + +# ============================================================================= +# Product preparation for FG detection +# ============================================================================= + + +def test_prepare_products_skips_inactive_reactions(): + inactive = make_reaction( + activity_stats=False + ) + + session = make_session( + reaction_metadata=[ + inactive + ] + ) + + progression = make_progression( + session + ) + + result = ( + progression + ._prepare_products_for_idx_based_fg_detection() + ) + + assert result == [] + + +def test_prepare_products_creates_role_for_active_reaction( + monkeypatch, +): + reaction = make_reaction( + reaction_id=7, + product_smiles="CC", + delete_atom=False, + ) + + session = make_session( + reaction_metadata=[ + reaction + ] + ) + + progression = make_progression( + session + ) + + sanitized = mol("CC") + + monkeypatch.setattr( + progression, + "_sanitize_molecule", + lambda molecule: ( + sanitized, + True, + ), + ) + + result = ( + progression + ._prepare_products_for_idx_based_fg_detection() + ) + + assert len(result) == 1 + + role = result[0] + + assert ( + role.name + == "new_7" + ) + + assert role.smiles == ( + Chem.MolToSmiles( + sanitized + ) + ) + + assert ( + role.rdkit_mol + is sanitized + ) + + +def test_prepare_products_uses_template_product_indices( + monkeypatch, +): + reaction = make_reaction( + product_smiles="CCC", + template_mapping={ + 10: 0, + 11: 2, + }, + ) + + session = make_session( + reaction_metadata=[ + reaction + ] + ) + + progression = make_progression( + session + ) + + monkeypatch.setattr( + progression, + "_sanitize_molecule", + lambda molecule: ( + molecule, + True, + ), + ) + + role = ( + progression + ._prepare_products_for_idx_based_fg_detection()[0] + ) + + assert ( + role.indexes_in_template + == [ + 0, + 2, + ] + ) + + +def test_prepare_products_replaces_single_fragment_nondelete_product_with_sanitized_copy( + monkeypatch, +): + reaction = make_reaction( + product_smiles="CC", + delete_atom=False, + ) + + original = ( + reaction.product_combined_RDmol + ) + + sanitized = mol("CO") + + session = make_session( + reaction_metadata=[ + reaction + ] + ) + + progression = make_progression( + session + ) + + monkeypatch.setattr( + progression, + "_sanitize_molecule", + lambda molecule: ( + sanitized, + True, + ), + ) + + progression._prepare_products_for_idx_based_fg_detection() + + assert ( + reaction.product_combined_RDmol + is not original + ) + + assert ( + Chem.MolToSmiles( + reaction.product_combined_RDmol + ) + == Chem.MolToSmiles( + sanitized + ) + ) + + +def test_prepare_products_does_not_replace_delete_product( + monkeypatch, +): + reaction = make_reaction( + product_smiles="CC", + delete_atom=True, + ) + + original = ( + reaction.product_combined_RDmol + ) + + session = make_session( + reaction_metadata=[ + reaction + ] + ) + + progression = make_progression( + session + ) + + monkeypatch.setattr( + progression, + "_sanitize_molecule", + lambda molecule: ( + mol("CO"), + True, + ), + ) + + progression._prepare_products_for_idx_based_fg_detection() + + assert ( + reaction.product_combined_RDmol + is original + ) + + +def test_prepare_products_failed_sanitization_clears_radical_metadata( + monkeypatch, + capsys, +): + reaction = make_reaction() + + reaction.is_radical = True + reaction.radical_atom_idxs = ( + 1, + ) + + session = make_session( + reaction_metadata=[ + reaction + ] + ) + + progression = make_progression( + session + ) + + best_effort = mol("CC") + + monkeypatch.setattr( + progression, + "_sanitize_molecule", + lambda molecule: ( + best_effort, + False, + ), + ) + + result = ( + progression + ._prepare_products_for_idx_based_fg_detection() + ) + + assert len(result) == 1 + + assert reaction.is_radical is False + assert reaction.radical_atom_idxs == () + + assert ( + "sanitization failed" + in capsys.readouterr().out + ) + + +# ============================================================================= +# reaction_progression() control flow +# ============================================================================= + + +def test_reaction_progression_zero_loop_returns_copy_of_existing_metadata(): + reaction = make_reaction() + + session = make_session( + reaction_metadata=[ + reaction + ] + ) + + progression = make_progression( + session + ) + + result = progression.reaction_progression( + max_loop=0 + ) + + assert result == [ + reaction + ] + + assert result is not ( + session.reaction_metadata + ) + + +def test_reaction_progression_negative_loop_returns_existing_metadata(): + reaction = make_reaction() + + session = make_session( + reaction_metadata=[ + reaction + ] + ) + + progression = make_progression( + session + ) + + assert ( + progression.reaction_progression( + max_loop=-1 + ) + == [ + reaction + ] + ) + + +def test_reaction_progression_none_uses_session_iteration_depth( + monkeypatch, +): + session = make_session( + reaction_iteration_depth=0 + ) + + progression = make_progression( + session + ) + + # If None correctly resolves to zero from the session, + # no loop helpers should run. + monkeypatch.setattr( + progression, + "_populate_monomer_roles", + lambda: pytest.fail( + "loop unexpectedly started" + ), + ) + + assert ( + progression.reaction_progression( + max_loop=None + ) + == [] + ) + + +def test_reaction_progression_first_iteration_populates_monomers( + monkeypatch, +): + session = make_session() + + progression = make_progression( + session + ) + + calls = [] + + monkeypatch.setattr( + progression, + "_populate_monomer_roles", + lambda: calls.append( + "populate" + ), + ) + + monkeypatch.setattr( + progression, + "_set_is_looped_flag", + lambda roles: + calls.append( + "looped" + ), + ) + + monkeypatch.setattr( + progression, + "_prepare_products_for_idx_based_fg_detection", + lambda: [], + ) + + progression.fg_detector = ( + SimpleNamespace( + index_based_functional_groups_detector= + lambda roles: [] + ) + ) + + progression.reaction_progression( + max_loop=1 + ) + + assert calls == [ + "populate", + "looped", + ] + + assert ( + session + .reaction_progression_session + .iteration + == 1 + ) + + +def test_reaction_progression_stops_when_no_functional_groups( + monkeypatch, +): + session = make_session( + reaction_metadata=[ + make_reaction() + ] + ) + + progression = make_progression( + session + ) + + monkeypatch.setattr( + progression, + "_populate_monomer_roles", + lambda: None, + ) + + monkeypatch.setattr( + progression, + "_set_is_looped_flag", + lambda roles: None, + ) + + prepared_roles = [ + object() + ] + + monkeypatch.setattr( + progression, + "_prepare_products_for_idx_based_fg_detection", + lambda: prepared_roles, + ) + + progression.fg_detector = ( + SimpleNamespace( + index_based_functional_groups_detector= + lambda roles: [] + ) + ) + + result = progression.reaction_progression( + max_loop=3 + ) + + assert result == ( + session.reaction_metadata + ) + + assert ( + session + .reaction_progression_session + .iteration + == 1 + ) + + +def test_reaction_progression_stops_when_no_reactions( + monkeypatch, +): + initial_role = make_role() + + session = make_session( + monomer_roles=[ + initial_role + ] + ) + + progression = make_progression( + session + ) + + monkeypatch.setattr( + progression, + "_populate_monomer_roles", + lambda: None, + ) + + monkeypatch.setattr( + progression, + "_set_is_looped_flag", + lambda roles: None, + ) + + monkeypatch.setattr( + progression, + "_prepare_products_for_idx_based_fg_detection", + lambda: [ + object() + ], + ) + + new_fg_role = make_role( + name="new" + ) + + progression.fg_detector = ( + SimpleNamespace( + index_based_functional_groups_detector= + lambda roles: [ + new_fg_role + ] + ) + ) + + progression.rxn_detector = ( + SimpleNamespace( + index_based_reaction_detector= + lambda roles: [] + ) + ) + + result = progression.reaction_progression( + max_loop=3 + ) + + assert result == [] + + assert ( + new_fg_role + in session.monomer_roles + ) + + +def test_reaction_progression_converts_reaction_generator_to_list( + monkeypatch, +): + session = make_session() + + progression = make_progression( + session + ) + + monkeypatch.setattr( + progression, + "_populate_monomer_roles", + lambda: None, + ) + + monkeypatch.setattr( + progression, + "_set_is_looped_flag", + lambda roles: None, + ) + + monkeypatch.setattr( + progression, + "_prepare_products_for_idx_based_fg_detection", + lambda: [ + object() + ], + ) + + progression.fg_detector = ( + SimpleNamespace( + index_based_functional_groups_detector= + lambda roles: [ + object() + ] + ) + ) + + instance_1 = object() + instance_2 = object() + + progression.rxn_detector = ( + SimpleNamespace( + index_based_reaction_detector= + lambda roles: ( + item + for item in ( + instance_1, + instance_2, + ) + ) + ) + ) + + received = [] + + monkeypatch.setattr( + progression, + "_index_based_reaction_preparation", + lambda reaction_instances: + ( + received.append( + reaction_instances + ) + or [] + ), + ) + + monkeypatch.setattr( + progression, + "_annotate_radicals_before_deduplication", + lambda reactions: None, + ) + + progression.deduplication_detector = ( + SimpleNamespace( + compare_graphs_mol= + lambda reactions, deep_check: + reactions + ) + ) + + progression.reaction_progression( + max_loop=1 + ) + + assert received == [ + [ + instance_1, + instance_2, + ] + ] + + +def test_reaction_progression_passes_deep_search_to_deduplicator( + monkeypatch, +): + session = make_session( + deep_search=False + ) + + progression = make_progression( + session + ) + + monkeypatch.setattr( + progression, + "_populate_monomer_roles", + lambda: None, + ) + + monkeypatch.setattr( + progression, + "_set_is_looped_flag", + lambda roles: None, + ) + + monkeypatch.setattr( + progression, + "_prepare_products_for_idx_based_fg_detection", + lambda: [ + object() + ], + ) + + progression.fg_detector = ( + SimpleNamespace( + index_based_functional_groups_detector= + lambda roles: [ + object() + ] + ) + ) + + progression.rxn_detector = ( + SimpleNamespace( + index_based_reaction_detector= + lambda roles: [ + object() + ] + ) + ) + + prepared = make_reaction() + + monkeypatch.setattr( + progression, + "_index_based_reaction_preparation", + lambda reaction_instances: [ + prepared + ], + ) + + monkeypatch.setattr( + progression, + "_annotate_radicals_before_deduplication", + lambda reactions: None, + ) + + calls = [] + + progression.deduplication_detector = ( + SimpleNamespace( + compare_graphs_mol= + lambda reactions, deep_check: + ( + calls.append( + deep_check + ) + or reactions + ) + ) + ) + + progression.reaction_progression( + max_loop=1 + ) + + assert calls == [ + False + ] + + +def test_reaction_progression_annotates_radicals_before_deduplication( + monkeypatch, +): + session = make_session() + + progression = make_progression( + session + ) + + order = [] + + monkeypatch.setattr( + progression, + "_populate_monomer_roles", + lambda: None, + ) + + monkeypatch.setattr( + progression, + "_set_is_looped_flag", + lambda roles: None, + ) + + monkeypatch.setattr( + progression, + "_prepare_products_for_idx_based_fg_detection", + lambda: [ + object() + ], + ) + + progression.fg_detector = ( + SimpleNamespace( + index_based_functional_groups_detector= + lambda roles: [ + object() + ] + ) + ) + + progression.rxn_detector = ( + SimpleNamespace( + index_based_reaction_detector= + lambda roles: [ + object() + ] + ) + ) + + prepared = make_reaction() + + monkeypatch.setattr( + progression, + "_index_based_reaction_preparation", + lambda reaction_instances: [ + prepared + ], + ) + + monkeypatch.setattr( + progression, + "_annotate_radicals_before_deduplication", + lambda reactions: + order.append( + "radicals" + ), + ) + + progression.deduplication_detector = ( + SimpleNamespace( + compare_graphs_mol= + lambda reactions, deep_check: + ( + order.append( + "dedup" + ) + or reactions + ) + ) + ) + + progression.reaction_progression( + max_loop=1 + ) + + assert order == [ + "radicals", + "dedup", + ] + + +def test_reaction_progression_break_condition_stores_reactions( + monkeypatch, +): + initial = make_reaction( + reaction_id=1 + ) + + session = make_session( + reaction_metadata=[ + initial + ] + ) + + progression = make_progression( + session + ) + + monkeypatch.setattr( + progression, + "_populate_monomer_roles", + lambda: None, + ) + + monkeypatch.setattr( + progression, + "_set_is_looped_flag", + lambda roles: None, + ) + + monkeypatch.setattr( + progression, + "_prepare_products_for_idx_based_fg_detection", + lambda: [ + object() + ], + ) + + progression.fg_detector = ( + SimpleNamespace( + index_based_functional_groups_detector= + lambda roles: [ + object() + ] + ) + ) + + progression.rxn_detector = ( + SimpleNamespace( + index_based_reaction_detector= + lambda roles: [ + object() + ] + ) + ) + + duplicate = make_reaction( + reaction_id=2 + ) + + monkeypatch.setattr( + progression, + "_index_based_reaction_preparation", + lambda reaction_instances: [ + duplicate + ], + ) + + monkeypatch.setattr( + progression, + "_annotate_radicals_before_deduplication", + lambda reactions: None, + ) + + # Dedup leaves only the original reaction, so active pool size + # stays 1 -> break. + progression.deduplication_detector = ( + SimpleNamespace( + compare_graphs_mol= + lambda reactions, deep_check: [ + initial + ] + ) + ) + + result = progression.reaction_progression( + max_loop=5 + ) + + assert result == [ + initial + ] + + assert ( + session.reaction_metadata + == [ + initial + ] + ) \ No newline at end of file diff --git a/tests/unit/reaction_preparation/reaction_processor/test_warning_asci.py b/tests/unit/reaction_preparation/reaction_processor/test_warning_asci.py new file mode 100644 index 00000000..60f6721c --- /dev/null +++ b/tests/unit/reaction_preparation/reaction_processor/test_warning_asci.py @@ -0,0 +1,145 @@ +from AutoREACTER.reaction_preparation.reaction_processor.warning_asci import ( + ascii_art, + print_warning, +) + + +# ============================================================================= +# ascii_art +# ============================================================================= + + +def test_ascii_art_uppercases_message(capsys): + ascii_art( + "reaction progression warning" + ) + + output = capsys.readouterr().out + + assert ( + "WARNING: REACTION PROGRESSION WARNING" + in output + ) + + +def test_ascii_art_prints_warning_prefix(capsys): + ascii_art( + "test message" + ) + + output = capsys.readouterr().out + + assert output.startswith( + "WARNING: TEST MESSAGE" + ) + + +def test_ascii_art_prints_banner(capsys): + ascii_art( + "test" + ) + + output = capsys.readouterr().out + + # Stable fragments from the ASCII banner. + assert "____" in output + assert "|_ _|" in output + assert "WARNING:" in output + + +def test_ascii_art_prints_multiline_output(capsys): + ascii_art( + "hello" + ) + + output = capsys.readouterr().out + + nonempty_lines = [ + line + for line in output.splitlines() + if line.strip() + ] + + # One warning line + several ASCII-art lines. + assert len(nonempty_lines) >= 6 + + +def test_ascii_art_handles_empty_message(capsys): + ascii_art("") + + output = capsys.readouterr().out + + assert output.startswith( + "WARNING:" + ) + + assert "____" in output + + +def test_ascii_art_does_not_return_value(): + result = ascii_art( + "warning" + ) + + assert result is None + + +# ============================================================================= +# print_warning +# ============================================================================= + + +def test_print_warning_prints_beta_phase_message( + capsys, +): + print_warning() + + output = capsys.readouterr().out + + assert ( + "ENTERING THE REACTION PROGRESSION LOOP " + "IS STILL IN THE BETA PHASE." + in output + ) + + +def test_print_warning_mentions_chemical_accuracy( + capsys, +): + print_warning() + + output = capsys.readouterr().out + + assert ( + "RESULTS CAN BE CHEMICALLY INACCURATE" + in output + ) + + +def test_print_warning_uses_warning_prefix( + capsys, +): + print_warning() + + output = capsys.readouterr().out + + assert output.startswith( + "WARNING:" + ) + + +def test_print_warning_prints_ascii_banner( + capsys, +): + print_warning() + + output = capsys.readouterr().out + + assert "____" in output + assert "|_ _|" in output + + +def test_print_warning_returns_none(): + result = print_warning() + + assert result is None \ No newline at end of file diff --git a/tests/unit/reaction_preparation/test_deduplication_detector.py b/tests/unit/reaction_preparation/test_deduplication_detector.py new file mode 100644 index 00000000..837fed66 --- /dev/null +++ b/tests/unit/reaction_preparation/test_deduplication_detector.py @@ -0,0 +1,3305 @@ +from pathlib import Path +from types import SimpleNamespace + +import networkx as nx +import pytest +from rdkit import Chem + +from AutoREACTER.reaction_preparation.deduplication_detector import ( + DeduplicationDetector, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def mol(smiles: str) -> Chem.Mol: + molecule = Chem.MolFromSmiles(smiles) + + assert molecule is not None + + return molecule + + +def make_phase_graph( + detector, + node_labels, + edges=(), +): + graph = nx.Graph() + + for node_id, label in node_labels.items(): + graph.add_node( + node_id, + **{ + detector.NODE_ATTRIBUTE: + label, + }, + ) + + for atom1, atom2, bond_label in edges: + graph.add_edge( + atom1, + atom2, + **{ + detector.EDGE_ATTRIBUTE: + bond_label, + }, + ) + + return graph + + +def make_metadata( + reactant_smiles="CC", + product_smiles="CC", + template_mapping=None, + full_mapping=None, + first_shell=None, + activity_stats=True, + reaction_id=1, + is_radical=False, +): + reactant = mol( + reactant_smiles + ) + + product = mol( + product_smiles + ) + + if full_mapping is None: + full_mapping = { + idx: idx + for idx in range( + min( + reactant.GetNumAtoms(), + product.GetNumAtoms(), + ) + ) + } + + if template_mapping is None: + template_mapping = ( + full_mapping.copy() + ) + + if first_shell is None: + first_shell = list( + template_mapping.keys() + ) + + return SimpleNamespace( + reaction_id=reaction_id, + reactant_combined_RDmol=reactant, + product_combined_RDmol=product, + template_reactant_to_product_mapping=template_mapping, + reactant_to_product_mapping=full_mapping, + first_shell=first_shell, + activity_stats=activity_stats, + is_radical=is_radical, + pre_reaction_file=None, + post_reaction_file=None, + map_file=None, + ) + + +def write_lammps_molecule( + path: Path, + atom_types, + bonds=(), +): + lines = [ + "# test molecule\n", + "\n", + "Coords\n", + "\n", + ] + + for atom_id in atom_types: + lines.append( + f"{atom_id} 0.0 0.0 0.0\n" + ) + + lines.extend( + [ + "\n", + "Types\n", + "\n", + ] + ) + + for atom_id, atom_type in ( + atom_types.items() + ): + lines.append( + f"{atom_id} {atom_type}\n" + ) + + lines.extend( + [ + "\n", + "Charges\n", + "\n", + ] + ) + + for atom_id in atom_types: + lines.append( + f"{atom_id} 0.0\n" + ) + + if bonds: + lines.extend( + [ + "\n", + "Bonds\n", + "\n", + ] + ) + + for ( + bond_id, + bond_type, + atom1, + atom2, + ) in bonds: + lines.append( + f"{bond_id} " + f"{bond_type} " + f"{atom1} " + f"{atom2}\n" + ) + + path.write_text( + "".join(lines), + encoding="utf-8", + ) + + return path + + +def write_map_file( + path: Path, + equivalences=(), + edge_ids=(), + initiator_ids=(), + delete_ids=(), + wildcards=(), +): + lines = [ + "# AutoREACTER test map\n", + "\n", + f"{len(edge_ids)} edgeIDs\n", + f"{len(equivalences)} equivalences\n", + ] + + if delete_ids: + lines.append( + f"{len(delete_ids)} deleteIDs\n" + ) + + lines.append( + f"{len(wildcards)} wildcards\n" + ) + + lines.extend( + [ + "\n", + "InitiatorIDs\n", + "\n", + ] + ) + + for atom_id in initiator_ids: + lines.append( + f"{atom_id}\n" + ) + + lines.extend( + [ + "\n", + "EdgeIDs\n", + "\n", + ] + ) + + for atom_id in edge_ids: + lines.append( + f"{atom_id}\n" + ) + + lines.extend( + [ + "\n", + "Equivalences\n", + "\n", + ] + ) + + for pre_id, post_id in equivalences: + lines.append( + f"{pre_id} {post_id}\n" + ) + + if delete_ids: + lines.extend( + [ + "\n", + "DeleteIDs\n", + "\n", + ] + ) + + for atom_id in delete_ids: + lines.append( + f"{atom_id}\n" + ) + + lines.extend( + [ + "\n", + "Wildcards\n", + "\n", + ] + ) + + for atom_id in wildcards: + lines.append( + f"{atom_id}\n" + ) + + path.write_text( + "".join(lines), + encoding="utf-8", + ) + + return path + + +# ============================================================================= +# Construction / cache isolation +# ============================================================================= + + +def test_constructor_initializes_expected_cache_groups(): + detector = ( + DeduplicationDetector() + ) + + assert detector.seen_reactions == { + detector.LAMMPS_COMPARISON_GROUP: [], + detector.RDKIT_COMPARISON_GROUP: [], + } + + assert ( + detector.seen_reaction_pairs + == { + detector.LAMMPS_COMPARISON_GROUP: [], + detector.RDKIT_COMPARISON_GROUP: [], + } + ) + + +def test_detector_instances_have_independent_caches(): + first = DeduplicationDetector() + second = DeduplicationDetector() + + first.seen_reactions[ + first.RDKIT_COMPARISON_GROUP + ].append( + nx.Graph() + ) + + assert ( + second.seen_reactions[ + second.RDKIT_COMPARISON_GROUP + ] + == [] + ) + + +# ============================================================================= +# clear_cache +# ============================================================================= + + +def test_clear_cache_clears_all_groups(): + detector = ( + DeduplicationDetector() + ) + + detector.seen_reactions[ + "rdkit" + ].append( + nx.Graph() + ) + + detector.seen_reaction_pairs[ + "lammps" + ].append( + ( + nx.Graph(), + nx.Graph(), + ) + ) + + detector.clear_cache() + + assert all( + not value + for value + in detector.seen_reactions.values() + ) + + assert all( + not value + for value + in detector.seen_reaction_pairs.values() + ) + + +def test_clear_cache_specific_group_only(): + detector = ( + DeduplicationDetector() + ) + + detector.seen_reactions[ + "rdkit" + ].append( + nx.Graph() + ) + + detector.seen_reactions[ + "lammps" + ].append( + nx.Graph() + ) + + detector.clear_cache( + "rdkit" + ) + + assert ( + detector.seen_reactions[ + "rdkit" + ] + == [] + ) + + assert len( + detector.seen_reactions[ + "lammps" + ] + ) == 1 + + +def test_clear_cache_creates_unknown_group(): + detector = ( + DeduplicationDetector() + ) + + detector.clear_cache( + "custom" + ) + + assert ( + detector.seen_reactions[ + "custom" + ] + == [] + ) + + assert ( + detector.seen_reaction_pairs[ + "custom" + ] + == [] + ) + + +# ============================================================================= +# is_duplicate_pair +# ============================================================================= + + +def test_duplicate_pair_first_pair_is_unique(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + 1: "O", + }, + [ + ( + 0, + 1, + "SINGLE", + ) + ], + ) + + post = make_phase_graph( + detector, + { + 0: "C", + 1: "O", + }, + [ + ( + 0, + 1, + "DOUBLE", + ) + ], + ) + + assert ( + detector.is_duplicate_pair( + pre, + post, + "test", + ) + is False + ) + + +def test_duplicate_pair_second_identical_pair_is_duplicate(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + 1: "O", + }, + [ + ( + 0, + 1, + "SINGLE", + ) + ], + ) + + post = make_phase_graph( + detector, + { + 0: "C", + 1: "O", + }, + [ + ( + 0, + 1, + "DOUBLE", + ) + ], + ) + + assert not detector.is_duplicate_pair( + pre, + post, + "test", + ) + + assert detector.is_duplicate_pair( + pre, + post, + "test", + ) + + +def test_duplicate_pair_requires_matching_pre_and_post_pair(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + }, + ) + + post_1 = make_phase_graph( + detector, + { + 0: "O", + }, + ) + + post_2 = make_phase_graph( + detector, + { + 0: "N", + }, + ) + + assert not detector.is_duplicate_pair( + pre, + post_1, + "test", + ) + + assert not detector.is_duplicate_pair( + pre, + post_2, + "test", + ) + + +def test_duplicate_pair_is_structure_based_not_node_id_based(): + detector = ( + DeduplicationDetector() + ) + + pre_1 = make_phase_graph( + detector, + { + 1: "C", + 2: "O", + }, + [ + ( + 1, + 2, + "SINGLE", + ) + ], + ) + + post_1 = make_phase_graph( + detector, + { + 1: "C", + 2: "O", + }, + [ + ( + 1, + 2, + "DOUBLE", + ) + ], + ) + + pre_2 = make_phase_graph( + detector, + { + 100: "C", + 200: "O", + }, + [ + ( + 100, + 200, + "SINGLE", + ) + ], + ) + + post_2 = make_phase_graph( + detector, + { + 100: "C", + 200: "O", + }, + [ + ( + 100, + 200, + "DOUBLE", + ) + ], + ) + + assert not detector.is_duplicate_pair( + pre_1, + post_1, + "test", + ) + + assert detector.is_duplicate_pair( + pre_2, + post_2, + "test", + ) + + +def test_duplicate_pair_cache_uses_copies(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + }, + ) + + post = make_phase_graph( + detector, + { + 0: "O", + }, + ) + + detector.is_duplicate_pair( + pre, + post, + "test", + ) + + pre.add_node( + 99, + atom_label="X", + ) + + cached_pre, _ = ( + detector + .seen_reaction_pairs[ + "test" + ][0] + ) + + assert 99 not in cached_pre + + +# ============================================================================= +# Coupled RDKit graph handling +# ============================================================================= + + +def test_couple_graphs_builds_pre_post_nodes_and_correspondence_edges(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + 1: "O", + }, + [ + ( + 0, + 1, + "SINGLE", + ) + ], + ) + + post = make_phase_graph( + detector, + { + 0: "C", + 1: "O", + }, + [ + ( + 0, + 1, + "DOUBLE", + ) + ], + ) + + coupled = detector._couple_graphs( + pre, + post, + ) + + assert set( + coupled.nodes + ) == { + ("pre", 0), + ("pre", 1), + ("post", 0), + ("post", 1), + } + + assert coupled.has_edge( + ("pre", 0), + ("post", 0), + ) + + assert ( + coupled.edges[ + ("pre", 0), + ("post", 0), + ]["relationship"] + == "atom_correspondence" + ) + + +def test_couple_graphs_requires_matching_atom_ids(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + 1: "O", + }, + ) + + post = make_phase_graph( + detector, + { + 0: "C", + 2: "O", + }, + ) + + with pytest.raises( + ValueError, + match="matching atom IDs", + ): + detector._couple_graphs( + pre, + post, + ) + + +def test_couple_graphs_preserves_radical_signature(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + }, + ) + + post = make_phase_graph( + detector, + { + 0: "C", + }, + ) + + pre.graph[ + detector.RADICAL_COUNT_ATTRIBUTE + ] = 1 + + pre.graph[ + detector.RADICAL_PRESENT_ATTRIBUTE + ] = True + + post.graph[ + detector.RADICAL_COUNT_ATTRIBUTE + ] = 0 + + post.graph[ + detector.RADICAL_PRESENT_ATTRIBUTE + ] = False + + coupled = detector._couple_graphs( + pre, + post, + ) + + assert coupled.graph[ + detector.RADICAL_SIGNATURE_ATTRIBUTE + ] == ( + 1, + 0, + True, + False, + ) + + +def test_add_phase_requires_node_label(): + detector = ( + DeduplicationDetector() + ) + + source = nx.Graph() + source.add_node(0) + + target = nx.Graph() + + with pytest.raises( + ValueError, + match="atom_label", + ): + detector._add_phase_to_coupled_graph( + source, + target, + "pre", + ) + + +def test_add_phase_requires_edge_label(): + detector = ( + DeduplicationDetector() + ) + + source = nx.Graph() + + source.add_node( + 0, + atom_label="C", + ) + + source.add_node( + 1, + atom_label="O", + ) + + source.add_edge( + 0, + 1, + ) + + target = nx.Graph() + + with pytest.raises( + ValueError, + match="bond_label", + ): + detector._add_phase_to_coupled_graph( + source, + target, + "pre", + ) + + +# ============================================================================= +# is_duplicate / coupled cache +# ============================================================================= + + +def test_is_duplicate_first_coupled_reaction_is_unique(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + }, + ) + + post = make_phase_graph( + detector, + { + 0: "O", + }, + ) + + assert ( + detector.is_duplicate( + pre, + post, + "test", + ) + is False + ) + + +def test_is_duplicate_second_equivalent_coupled_reaction_is_duplicate(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 0: "C", + }, + ) + + post = make_phase_graph( + detector, + { + 0: "O", + }, + ) + + detector.is_duplicate( + pre, + post, + "test", + ) + + assert detector.is_duplicate( + pre, + post, + "test", + ) + + +def test_coupled_duplicate_radical_signature_must_match(): + detector = ( + DeduplicationDetector() + ) + + pre_1 = make_phase_graph( + detector, + {0: "C"}, + ) + + post_1 = make_phase_graph( + detector, + {0: "C"}, + ) + + pre_1.graph[ + detector.RADICAL_PRESENT_ATTRIBUTE + ] = False + + post_1.graph[ + detector.RADICAL_PRESENT_ATTRIBUTE + ] = False + + pre_2 = make_phase_graph( + detector, + {0: "C"}, + ) + + post_2 = make_phase_graph( + detector, + {0: "C"}, + ) + + pre_2.graph[ + detector.RADICAL_PRESENT_ATTRIBUTE + ] = False + + post_2.graph[ + detector.RADICAL_PRESENT_ATTRIBUTE + ] = True + + assert not detector.is_duplicate( + pre_1, + post_1, + "test", + ) + + assert not detector.is_duplicate( + pre_2, + post_2, + "test", + ) + + +# ============================================================================= +# RDKit graph conversion +# ============================================================================= + + +def test_rdkit_mol_to_networkx_rejects_none(): + detector = ( + DeduplicationDetector() + ) + + with pytest.raises( + ValueError, + match="None RDKit molecule", + ): + detector.rdkit_mol_to_networkx( + None + ) + + +def test_rdkit_mol_to_networkx_builds_all_atoms(): + detector = ( + DeduplicationDetector() + ) + + molecule = mol( + "CCO" + ) + + graph = ( + detector.rdkit_mol_to_networkx( + molecule, + deep_check=False, + ) + ) + + assert graph.number_of_nodes() == 3 + + assert graph.number_of_edges() == 2 + + +def test_rdkit_graph_node_label_contains_element(): + detector = ( + DeduplicationDetector() + ) + + graph = ( + detector.rdkit_mol_to_networkx( + mol("CO"), + deep_check=False, + ) + ) + + assert graph.nodes[ + 0 + ][ + detector.NODE_ATTRIBUTE + ][0] == "C" + + assert graph.nodes[ + 1 + ][ + detector.NODE_ATTRIBUTE + ][0] == "O" + + +def test_rdkit_graph_edges_include_bond_type(): + detector = ( + DeduplicationDetector() + ) + + graph = ( + detector.rdkit_mol_to_networkx( + mol("C=C"), + deep_check=False, + ) + ) + + assert ( + graph.edges[ + 0, + 1, + ][detector.EDGE_ATTRIBUTE] + == "DOUBLE" + ) + + +def test_rdkit_graph_can_be_restricted_to_atom_indices(): + detector = ( + DeduplicationDetector() + ) + + graph = ( + detector.rdkit_mol_to_networkx( + mol("CCCC"), + atom_idxs={ + 1, + 2, + }, + deep_check=False, + ) + ) + + assert set( + graph.nodes + ) == { + 1, + 2, + } + + assert graph.number_of_edges() == 1 + + +def test_rdkit_graph_relabels_nodes(): + detector = ( + DeduplicationDetector() + ) + + graph = ( + detector.rdkit_mol_to_networkx( + mol("CO"), + atom_idxs={ + 0, + 1, + }, + idx_relabel={ + 0: 10, + 1: 20, + }, + deep_check=False, + ) + ) + + assert set( + graph.nodes + ) == { + 10, + 20, + } + + assert graph.has_edge( + 10, + 20, + ) + + +def test_rdkit_graph_relabel_requires_all_included_indices(): + detector = ( + DeduplicationDetector() + ) + + with pytest.raises( + ValueError, + match="does not contain entries", + ): + detector.rdkit_mol_to_networkx( + mol("CO"), + atom_idxs={ + 0, + 1, + }, + idx_relabel={ + 0: 10, + }, + ) + + +def test_rdkit_deep_check_includes_external_neighbor_signature(): + detector = ( + DeduplicationDetector() + ) + + molecule = mol( + "CCO" + ) + + graph = ( + detector.rdkit_mol_to_networkx( + molecule, + atom_idxs={ + 1, + }, + deep_check=True, + ) + ) + + label = graph.nodes[ + 1 + ][detector.NODE_ATTRIBUTE] + + assert label[0] == "C" + + signature = label[2] + + external_symbols = { + item[0] + for item in signature + } + + assert external_symbols == { + "C", + "O", + } + + +def test_rdkit_shallow_check_omits_external_environment_signature(): + detector = ( + DeduplicationDetector() + ) + + graph = ( + detector.rdkit_mol_to_networkx( + mol("CCO"), + atom_idxs={ + 1, + }, + deep_check=False, + ) + ) + + label = graph.nodes[ + 1 + ][detector.NODE_ATTRIBUTE] + + assert len(label) == 2 + + +# ============================================================================= +# Radical helpers +# ============================================================================= + + +def test_explicit_radical_atom_is_detected(): + detector = ( + DeduplicationDetector() + ) + + radical = mol( + "[CH3]" + ) + + atom = radical.GetAtomWithIdx( + 0 + ) + + assert ( + detector._is_radical_atom( + atom + ) + is True + ) + + +def test_normal_carbon_is_not_radical(): + detector = ( + DeduplicationDetector() + ) + + atom = ( + mol("C") + .GetAtomWithIdx(0) + ) + + assert ( + detector._is_radical_atom( + atom + ) + is False + ) + + +def test_count_radical_atoms(): + detector = ( + DeduplicationDetector() + ) + + molecule = mol( + "[CH3].[CH3]" + ) + + assert ( + detector._count_radical_atoms( + molecule + ) + == 2 + ) + + +# ============================================================================= +# Mapping selection +# ============================================================================= + + +def test_select_template_mapping(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata( + template_mapping={ + 0: 1, + }, + ) + + result = ( + detector + ._select_reactant_to_product_mapping( + metadata, + reaction_index=1, + index_source="template", + ) + ) + + assert result == { + 0: 1, + } + + +def test_select_template_mapping_requires_mapping(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + metadata.template_reactant_to_product_mapping = None + + with pytest.raises( + ValueError, + match="template_reactant_to_product_mapping", + ): + detector._select_reactant_to_product_mapping( + metadata, + 1, + "template", + ) + + +def test_select_first_shell_mapping(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata( + full_mapping={ + 0: 2, + 1: 1, + 2: 0, + }, + first_shell=[ + 0, + 2, + ], + ) + + result = ( + detector + ._select_reactant_to_product_mapping( + metadata, + 1, + "first_shell", + ) + ) + + assert result == { + 0: 2, + 2: 0, + } + + +def test_select_first_shell_requires_indices(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + metadata.first_shell = None + + with pytest.raises( + ValueError, + match="first_shell", + ): + detector._select_reactant_to_product_mapping( + metadata, + 1, + "first_shell", + ) + + +def test_select_first_shell_requires_full_mapping(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + metadata.first_shell = [ + 0, + ] + + metadata.reactant_to_product_mapping = None + + with pytest.raises( + ValueError, + match="reactant_to_product_mapping", + ): + detector._select_reactant_to_product_mapping( + metadata, + 1, + "first_shell", + ) + + +def test_select_mapping_rejects_unknown_source(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + with pytest.raises( + ValueError, + match="Unsupported index_source", + ): + detector._select_reactant_to_product_mapping( + metadata, + 1, + "wrong", + ) + + +# ============================================================================= +# compare_graphs_mol +# ============================================================================= + + +def test_compare_graphs_mol_keeps_first_unique_reaction(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + result = ( + detector.compare_graphs_mol( + [ + metadata, + ] + ) + ) + + assert result == [ + metadata, + ] + + assert ( + metadata.activity_stats + is True + ) + + +def test_compare_graphs_mol_disables_later_duplicate(): + detector = ( + DeduplicationDetector() + ) + + first = make_metadata( + reaction_id=1, + ) + + second = make_metadata( + reaction_id=2, + ) + + result = ( + detector.compare_graphs_mol( + [ + first, + second, + ] + ) + ) + + assert result == [ + first, + ] + + assert ( + first.activity_stats + is True + ) + + assert ( + second.activity_stats + is False + ) + + +def test_compare_graphs_mol_repeated_same_object_is_not_disabled(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + result = ( + detector.compare_graphs_mol( + [ + metadata, + metadata, + ] + ) + ) + + assert result == [ + metadata, + ] + + assert ( + metadata.activity_stats + is True + ) + + +def test_compare_graphs_mol_skips_already_inactive_reactions(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata( + activity_stats=False + ) + + result = ( + detector.compare_graphs_mol( + [ + metadata, + ] + ) + ) + + assert result == [] + + +def test_compare_graphs_mol_requires_reactant_molecule(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + metadata.reactant_combined_RDmol = None + + with pytest.raises( + ValueError, + match="combined reactant", + ): + detector.compare_graphs_mol( + [ + metadata, + ] + ) + + +def test_compare_graphs_mol_requires_product_molecule(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + metadata.product_combined_RDmol = None + + with pytest.raises( + ValueError, + match="combined product", + ): + detector.compare_graphs_mol( + [ + metadata, + ] + ) + + +def test_compare_graphs_mol_rejects_nonbijective_mapping(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata( + template_mapping={ + 0: 0, + 1: 0, + }, + ) + + with pytest.raises( + ValueError, + match="non-bijective", + ): + detector.compare_graphs_mol( + [ + metadata, + ] + ) + + +def test_compare_graphs_mol_supports_first_shell_source(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata( + template_mapping=None, + full_mapping={ + 0: 0, + 1: 1, + }, + first_shell=[ + 0, + ], + ) + + metadata.template_reactant_to_product_mapping = None + + result = detector.compare_graphs_mol( + [ + metadata, + ], + index_source="first_shell", + ) + + assert result == [ + metadata, + ] + + +def test_compare_graphs_mol_clears_rdkit_cache_each_pass(): + detector = ( + DeduplicationDetector() + ) + + first = make_metadata( + reaction_id=1, + ) + + second = make_metadata( + reaction_id=2, + ) + + assert detector.compare_graphs_mol( + [ + first, + ] + ) == [ + first, + ] + + # A fresh deduplication pass must not treat an equivalent reaction + # as a duplicate merely because it appeared in a previous call. + assert detector.compare_graphs_mol( + [ + second, + ] + ) == [ + second, + ] + + +def test_compare_graphs_mol_radical_metadata_changes_signature(): + detector = ( + DeduplicationDetector() + ) + + non_radical = make_metadata( + reaction_id=1, + is_radical=False, + ) + + radical = make_metadata( + reaction_id=2, + is_radical=True, + ) + + result = detector.compare_graphs_mol( + [ + non_radical, + radical, + ] + ) + + assert result == [ + non_radical, + radical, + ] + + +def test_compare_graphs_mol_forwards_deep_check( + monkeypatch, +): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + calls = [] + + original = ( + detector.rdkit_mol_to_networkx + ) + + def wrapper( + molecule, + atom_idxs=None, + idx_relabel=None, + deep_check=True, + ): + calls.append( + deep_check + ) + + return original( + molecule=molecule, + atom_idxs=atom_idxs, + idx_relabel=idx_relabel, + deep_check=deep_check, + ) + + monkeypatch.setattr( + detector, + "rdkit_mol_to_networkx", + wrapper, + ) + + detector.compare_graphs_mol( + [ + metadata, + ], + deep_check=False, + ) + + assert calls == [ + False, + False, + ] + + +# ============================================================================= +# LAMMPS template filename helpers +# ============================================================================= + + +@pytest.mark.parametrize( + "name, expected", + [ + ( + "template_pre_1.molecule", + "1", + ), + ( + "template_post_22.molecule", + "22", + ), + ( + "template_pre_1_homo2.molecule", + "1_homo2", + ), + ], +) +def test_lammps_reaction_id_from_template_path( + name, + expected, +): + result = ( + DeduplicationDetector + ._lammps_reaction_id_from_template_path( + name + ) + ) + + assert result == expected + + +@pytest.mark.parametrize( + "name", + [ + "RXN_1.map", + "pre_1.molecule", + "template_1.molecule", + "template_pre_1.txt", + ], +) +def test_lammps_reaction_id_rejects_bad_filename( + name, +): + with pytest.raises( + ValueError, + match="Could not infer reaction ID", + ): + ( + DeduplicationDetector + ._lammps_reaction_id_from_template_path( + name + ) + ) + + +def test_lammps_map_path_from_template_path( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + template = ( + tmp_path + / "template_pre_42.molecule" + ) + + assert ( + detector + ._lammps_map_path_from_template_path( + template + ) + == tmp_path / "RXN_42.map" + ) + + +# ============================================================================= +# LAMMPS map parsing +# ============================================================================= + + +def test_is_lammps_map_section_header(): + detector = ( + DeduplicationDetector + ) + + assert detector._is_lammps_map_section_header( + "EdgeIDs" + ) + + assert detector._is_lammps_map_section_header( + "Equivalences extra" + ) + + assert not detector._is_lammps_map_section_header( + "1 2" + ) + + +@pytest.mark.parametrize( + "line", + [ + "11 edgeIDs", + "2 equivalences", + "0 wildcards", + " 5 EDGEIDS ", + ], +) +def test_is_lammps_count_line_true( + line, +): + assert ( + DeduplicationDetector + ._is_lammps_count_line( + line + ) + ) + + +def test_is_lammps_count_line_false(): + assert not ( + DeduplicationDetector + ._is_lammps_count_line( + "2 deleteIDs" + ) + ) + + +def test_read_lammps_equivalences( + tmp_path, +): + path = write_map_file( + tmp_path / "RXN_1.map", + equivalences=[ + ( + 1, + 10, + ), + ( + 2, + 20, + ), + ], + ) + + result = ( + DeduplicationDetector + ._read_lammps_equivalences( + path + ) + ) + + assert result == { + 1: 10, + 2: 20, + } + + +def test_read_lammps_equivalences_rejects_conflicting_pre_mapping( + tmp_path, +): + path = write_map_file( + tmp_path / "RXN_1.map", + equivalences=[ + ( + 1, + 10, + ), + ( + 1, + 20, + ), + ], + ) + + with pytest.raises( + ValueError, + match="Conflicting Equivalences", + ): + ( + DeduplicationDetector + ._read_lammps_equivalences( + path + ) + ) + + +def test_read_lammps_equivalences_rejects_nonbijective_post_mapping( + tmp_path, +): + path = write_map_file( + tmp_path / "RXN_1.map", + equivalences=[ + ( + 1, + 10, + ), + ( + 2, + 10, + ), + ], + ) + + with pytest.raises( + ValueError, + match="Non-bijective", + ): + ( + DeduplicationDetector + ._read_lammps_equivalences( + path + ) + ) + + +def test_read_lammps_edge_ids( + tmp_path, +): + path = write_map_file( + tmp_path / "RXN_1.map", + edge_ids=[ + 5, + 8, + 11, + ], + ) + + assert ( + DeduplicationDetector + ._read_lammps_edge_ids( + path + ) + == [ + 5, + 8, + 11, + ] + ) + + +def test_read_lammps_single_column_section( + tmp_path, +): + path = write_map_file( + tmp_path / "RXN_1.map", + initiator_ids=[ + 3, + 7, + ], + ) + + assert ( + DeduplicationDetector + ._read_lammps_single_column_section( + path, + "InitiatorIDs", + ) + == [ + 3, + 7, + ] + ) + + +def test_read_lammps_integer_section_ignores_non_integer_rows( + tmp_path, +): + path = tmp_path / "RXN_1.map" + + path.write_text( + """ +Equivalences + +1 10 +bad row +2 20 +""", + encoding="utf-8", + ) + + rows = ( + DeduplicationDetector + ._read_lammps_map_integer_section( + path, + "Equivalences", + ) + ) + + assert rows == [ + [ + 1, + 10, + ], + [ + 2, + 20, + ], + ] + + +# ============================================================================= +# Map text manipulation +# ============================================================================= + + +def test_remove_lammps_map_section(): + lines = [ + "# header\n", + "EdgeIDs\n", + "\n", + "1\n", + "2\n", + "\n", + "Equivalences\n", + "\n", + "1 1\n", + ] + + result = ( + DeduplicationDetector + ._remove_lammps_map_section( + lines, + "EdgeIDs", + ) + ) + + joined = "".join(result) + + assert "EdgeIDs" not in joined + assert "Equivalences" in joined + assert "1 1" in joined + + +def test_replace_lammps_count_lines(): + detector = ( + DeduplicationDetector() + ) + + lines = [ + "# header\n", + "\n", + "2 edgeIDs\n", + "5 equivalences\n", + "0 wildcards\n", + "\n", + "InitiatorIDs\n", + ] + + result = ( + detector + ._replace_lammps_count_lines( + lines, + edge_count=4, + equivalence_count=8, + wildcard_count=2, + ) + ) + + joined = "".join(result) + + assert "4 edgeIDs" in joined + assert "8 equivalences" in joined + assert "2 wildcards" in joined + + assert "5 equivalences" not in joined + + +# ============================================================================= +# Wildcard-map writing +# ============================================================================= + + +def test_write_lammps_wildcard_map_file( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + path = write_map_file( + tmp_path / "RXN_1.map", + equivalences=[ + ( + 1, + 10, + ), + ( + 2, + 20, + ), + ], + edge_ids=[ + 1, + 2, + ], + initiator_ids=[ + 1, + 2, + ], + delete_ids=[ + 3, + ], + ) + + detector._write_lammps_wildcard_map_file( + path, + wildcard_ids=[ + 2, + 1, + 2, + ], + ) + + text = path.read_text( + encoding="utf-8" + ) + + assert "2 edgeIDs" in text + assert "2 equivalences" in text + assert "1 deleteIDs" in text + assert "2 wildcards" in text + + assert "Wildcards" in text + + wildcards = ( + detector + ._read_lammps_single_column_section( + path, + "Wildcards", + ) + ) + + assert wildcards == [ + 2, + 1, + ] + + +# ============================================================================= +# Wildcard graph handling +# ============================================================================= + + +def test_remove_nodes_if_present_returns_copy(): + graph = nx.Graph() + + graph.add_edges_from( + [ + ( + 1, + 2, + ), + ( + 2, + 3, + ), + ] + ) + + result = ( + DeduplicationDetector + ._remove_nodes_if_present( + graph, + [ + 2, + 999, + ], + ) + ) + + assert 2 not in result + + assert 2 in graph + + +def test_apply_lammps_wildcards_removes_pre_and_equivalent_post_nodes( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 1: "A", + 2: "B", + }, + [ + ( + 1, + 2, + "1", + ) + ], + ) + + post = make_phase_graph( + detector, + { + 10: "A", + 20: "B", + }, + [ + ( + 10, + 20, + "1", + ) + ], + ) + + map_path = write_map_file( + tmp_path / "RXN_1.map", + equivalences=[ + ( + 1, + 10, + ), + ( + 2, + 20, + ), + ], + edge_ids=[ + 2, + ], + ) + + new_pre, new_post, mapping = ( + detector._apply_lammps_wildcards( + pre, + post, + { + 1: 10, + 2: 20, + }, + map_path, + ) + ) + + assert set( + new_pre.nodes + ) == { + 1, + } + + assert set( + new_post.nodes + ) == { + 10, + } + + assert mapping == { + 1: 10, + } + + +# ============================================================================= +# LAMMPS graph coupling +# ============================================================================= + + +def test_couple_lammps_graphs_uses_explicit_equivalences(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 1: "A", + 2: "B", + }, + ) + + post = make_phase_graph( + detector, + { + 10: "A", + 20: "B", + }, + ) + + coupled = ( + detector + ._couple_lammps_graphs( + pre, + post, + { + 1: 20, + 2: 10, + }, + "test.map", + ) + ) + + assert coupled.has_edge( + ("pre", 1), + ("post", 20), + ) + + assert coupled.has_edge( + ("pre", 2), + ("post", 10), + ) + + +def test_couple_lammps_graphs_rejects_missing_pre_atom(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 1: "A", + }, + ) + + post = make_phase_graph( + detector, + { + 10: "A", + }, + ) + + with pytest.raises( + ValueError, + match="references pre atom", + ): + detector._couple_lammps_graphs( + pre, + post, + { + 2: 10, + }, + "test.map", + ) + + +def test_couple_lammps_graphs_rejects_missing_post_atom(): + detector = ( + DeduplicationDetector() + ) + + pre = make_phase_graph( + detector, + { + 1: "A", + }, + ) + + post = make_phase_graph( + detector, + { + 10: "A", + }, + ) + + with pytest.raises( + ValueError, + match="references post atom", + ): + detector._couple_lammps_graphs( + pre, + post, + { + 1: 20, + }, + "test.map", + ) + + +# ============================================================================= +# LAMMPS molecule parsing +# ============================================================================= + + +def test_lammps_molecule_to_networkx_rejects_missing_file( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + with pytest.raises( + FileNotFoundError + ): + detector.lammps_molecule_to_networkx( + tmp_path + / "missing.molecule" + ) + + +def test_lammps_molecule_to_networkx_requires_types_section( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + path = ( + tmp_path / "bad.molecule" + ) + + path.write_text( + """ +Coords + +1 0 0 0 +""", + encoding="utf-8", + ) + + with pytest.raises( + ValueError, + match="Types section", + ): + detector.lammps_molecule_to_networkx( + path + ) + + +def test_lammps_molecule_to_networkx_builds_nodes_and_bonds( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + path = write_lammps_molecule( + tmp_path + / "template_pre_1.molecule", + { + 1: "3", + 2: "7", + }, + [ + ( + 1, + "2", + 1, + 2, + ) + ], + ) + + graph = ( + detector + .lammps_molecule_to_networkx( + path + ) + ) + + assert graph.nodes[ + 1 + ][detector.NODE_ATTRIBUTE] == "3" + + assert graph.nodes[ + 2 + ][detector.NODE_ATTRIBUTE] == "7" + + assert graph.edges[ + 1, + 2, + ][detector.EDGE_ATTRIBUTE] == "2" + + +def test_lammps_graph_ignores_coordinates_and_charges( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + path = write_lammps_molecule( + tmp_path + / "template_pre_1.molecule", + { + 1: "5", + }, + ) + + graph = ( + detector + .lammps_molecule_to_networkx( + path + ) + ) + + assert graph.number_of_nodes() == 1 + + assert set( + graph.nodes[1] + ) == { + detector.NODE_ATTRIBUTE, + } + + +def test_add_lammps_atoms_rejects_bad_line( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + graph = nx.Graph() + + with pytest.raises( + ValueError, + match="Invalid Types line", + ): + detector._add_lammps_atoms( + graph, + [ + "1", + ], + tmp_path + / "test.molecule", + ) + + +def test_add_lammps_atoms_rejects_invalid_id( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + with pytest.raises( + ValueError, + match="Invalid atom ID", + ): + detector._add_lammps_atoms( + nx.Graph(), + [ + "abc 4", + ], + tmp_path + / "test.molecule", + ) + + +def test_add_lammps_atoms_rejects_duplicate_atom_id( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + with pytest.raises( + ValueError, + match="Duplicate atom ID", + ): + detector._add_lammps_atoms( + nx.Graph(), + [ + "1 4", + "1 5", + ], + tmp_path + / "test.molecule", + ) + + +def test_add_lammps_bonds_rejects_short_line( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + graph = nx.Graph() + + graph.add_node( + 1, + atom_label="1", + ) + + with pytest.raises( + ValueError, + match="Invalid Bonds line", + ): + detector._add_lammps_bonds( + graph, + [ + "1 2 1", + ], + tmp_path + / "test.molecule", + ) + + +def test_add_lammps_bonds_rejects_undefined_atom( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + graph = nx.Graph() + + graph.add_node( + 1, + atom_label="1", + ) + + with pytest.raises( + ValueError, + match="undefined atom IDs", + ): + detector._add_lammps_bonds( + graph, + [ + "1 1 1 2", + ], + tmp_path + / "test.molecule", + ) + + +# ============================================================================= +# Complete LAMMPS template deduplication +# ============================================================================= + + +def test_lammps_template_pair_without_map_uses_uncoupled_pair_cache( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + pre = write_lammps_molecule( + tmp_path + / "template_pre_1.molecule", + { + 1: "1", + 2: "2", + }, + [ + ( + 1, + "1", + 1, + 2, + ) + ], + ) + + post = write_lammps_molecule( + tmp_path + / "template_post_1.molecule", + { + 1: "1", + 2: "2", + }, + [ + ( + 1, + "2", + 1, + 2, + ) + ], + ) + + assert not ( + detector + .is_duplicate_lammps_template_pair( + pre, + post, + ) + ) + + assert ( + detector + .is_duplicate_lammps_template_pair( + pre, + post, + ) + ) + + +def test_lammps_template_pair_with_map_uses_coupled_cache( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + pre = write_lammps_molecule( + tmp_path + / "template_pre_1.molecule", + { + 1: "1", + 2: "2", + }, + [ + ( + 1, + "1", + 1, + 2, + ) + ], + ) + + post = write_lammps_molecule( + tmp_path + / "template_post_1.molecule", + { + 10: "1", + 20: "2", + }, + [ + ( + 1, + "2", + 10, + 20, + ) + ], + ) + + map_path = write_map_file( + tmp_path + / "RXN_1.map", + equivalences=[ + ( + 1, + 10, + ), + ( + 2, + 20, + ), + ], + ) + + assert not ( + detector + .is_duplicate_lammps_template_pair( + pre, + post, + map_file_path=map_path, + ) + ) + + assert ( + detector + .is_duplicate_lammps_template_pair( + pre, + post, + map_file_path=map_path, + ) + ) + + +def test_lammps_template_pair_existing_map_requires_equivalences( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + pre = write_lammps_molecule( + tmp_path + / "template_pre_1.molecule", + { + 1: "1", + }, + ) + + post = write_lammps_molecule( + tmp_path + / "template_post_1.molecule", + { + 1: "1", + }, + ) + + map_path = ( + tmp_path / "RXN_1.map" + ) + + map_path.write_text( + """ +EdgeIDs + +1 +""", + encoding="utf-8", + ) + + with pytest.raises( + ValueError, + match="No Equivalences", + ): + ( + detector + .is_duplicate_lammps_template_pair( + pre, + post, + map_file_path=map_path, + ) + ) + + +# ============================================================================= +# compare_graphs +# ============================================================================= + + +def test_compare_graphs_skips_non_pre_files( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + path = ( + tmp_path + / "template_post_1.molecule" + ) + + path.write_text( + "", + encoding="utf-8", + ) + + assert ( + detector.compare_graphs( + [ + path, + ] + ) + == {} + ) + + +def test_compare_graphs_skips_missing_post_file( + tmp_path, + capsys, +): + detector = ( + DeduplicationDetector() + ) + + pre = ( + tmp_path + / "template_pre_1.molecule" + ) + + pre.write_text( + "", + encoding="utf-8", + ) + + result = ( + detector.compare_graphs( + [ + pre, + ] + ) + ) + + assert result == {} + + assert ( + "does not exist" + in capsys.readouterr().out + ) + + +def test_compare_graphs_records_result( + tmp_path, + monkeypatch, +): + detector = ( + DeduplicationDetector() + ) + + pre = ( + tmp_path + / "template_pre_1.molecule" + ) + + post = ( + tmp_path + / "template_post_1.molecule" + ) + + pre.write_text( + "", + encoding="utf-8", + ) + + post.write_text( + "", + encoding="utf-8", + ) + + monkeypatch.setattr( + detector, + "is_duplicate_lammps_template_pair", + lambda **kwargs: True, + ) + + result = detector.compare_graphs( + [ + pre, + ] + ) + + assert result == { + str(pre): True, + } + + +# ============================================================================= +# write_wildcard_maps +# ============================================================================= + + +def test_write_wildcard_maps_skips_inactive(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata( + activity_stats=False + ) + + assert ( + detector.write_wildcard_maps( + [ + metadata, + ] + ) + == [] + ) + + +def test_write_wildcard_maps_disables_missing_map_definition(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + metadata.map_file = None + + result = ( + detector.write_wildcard_maps( + [ + metadata, + ] + ) + ) + + assert result == [] + + assert ( + metadata.activity_stats + is False + ) + + +def test_write_wildcard_maps_disables_missing_map_file( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + metadata.map_file = ( + tmp_path + / "missing.map" + ) + + result = ( + detector.write_wildcard_maps( + [ + metadata, + ] + ) + ) + + assert result == [] + + assert ( + metadata.activity_stats + is False + ) + + +def test_write_wildcard_maps_writes_active_map( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + map_path = write_map_file( + tmp_path + / "RXN_1.map", + equivalences=[ + ( + 1, + 1, + ) + ], + edge_ids=[ + 1, + ], + ) + + metadata = make_metadata() + + metadata.map_file = map_path + + result = ( + detector.write_wildcard_maps( + [ + metadata, + ] + ) + ) + + assert result == [ + metadata, + ] + + wildcards = ( + detector + ._read_lammps_single_column_section( + map_path, + "Wildcards", + ) + ) + + assert wildcards == [ + 1, + ] + + +# ============================================================================= +# compare_lammps_templates orchestration +# ============================================================================= + + +def test_compare_lammps_templates_skips_inactive(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata( + activity_stats=False + ) + + assert ( + detector.compare_lammps_templates( + [ + metadata, + ] + ) + == [] + ) + + +def test_compare_lammps_templates_disables_missing_file_definitions(): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + result = ( + detector.compare_lammps_templates( + [ + metadata, + ] + ) + ) + + assert result == [] + + assert ( + metadata.activity_stats + is False + ) + + +def test_compare_lammps_templates_disables_missing_pre_file( + tmp_path, +): + detector = ( + DeduplicationDetector() + ) + + metadata = make_metadata() + + metadata.pre_reaction_file = ( + tmp_path + / "missing_pre.molecule" + ) + + post = ( + tmp_path + / "template_post_1.molecule" + ) + + post.write_text( + "", + encoding="utf-8", + ) + + metadata.post_reaction_file = post + + result = ( + detector.compare_lammps_templates( + [ + metadata, + ] + ) + ) + + assert result == [] + + assert ( + metadata.activity_stats + is False + ) + + +def test_compare_lammps_templates_disables_duplicate( + tmp_path, + monkeypatch, +): + detector = ( + DeduplicationDetector() + ) + + pre = ( + tmp_path + / "template_pre_1.molecule" + ) + + post = ( + tmp_path + / "template_post_1.molecule" + ) + + pre.write_text( + "", + encoding="utf-8", + ) + + post.write_text( + "", + encoding="utf-8", + ) + + metadata = make_metadata() + + metadata.pre_reaction_file = pre + metadata.post_reaction_file = post + + monkeypatch.setattr( + detector, + "is_duplicate_lammps_template_pair", + lambda **kwargs: True, + ) + + result = ( + detector.compare_lammps_templates( + [ + metadata, + ] + ) + ) + + assert result == [] + + assert ( + metadata.activity_stats + is False + ) + + +def test_compare_lammps_templates_retains_unique( + tmp_path, + monkeypatch, +): + detector = ( + DeduplicationDetector() + ) + + pre = ( + tmp_path + / "template_pre_1.molecule" + ) + + post = ( + tmp_path + / "template_post_1.molecule" + ) + + pre.write_text( + "", + encoding="utf-8", + ) + + post.write_text( + "", + encoding="utf-8", + ) + + metadata = make_metadata() + + metadata.pre_reaction_file = pre + metadata.post_reaction_file = post + + monkeypatch.setattr( + detector, + "is_duplicate_lammps_template_pair", + lambda **kwargs: False, + ) + + result = ( + detector.compare_lammps_templates( + [ + metadata, + ] + ) + ) + + assert result == [ + metadata, + ] + + assert ( + metadata.activity_stats + is True + ) From 1ca98b44d5bb2a1a7506a14661ee22c38975e09a Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 17:35:47 -0400 Subject: [PATCH 149/176] Add unit tests for LUNAR client utilities --- .../ff_wrapper/lunar_client/test_config.py | 14 + .../lunar_client/test_locate_lunar.py | 1385 +++++++++++++++++ .../lunar_client/test_lunar_utils.py | 691 ++++++++ 3 files changed, 2090 insertions(+) create mode 100644 tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_config.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_locate_lunar.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_utils.py diff --git a/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_config.py b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_config.py new file mode 100644 index 00000000..79211575 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_config.py @@ -0,0 +1,14 @@ +from AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.config import ( + LUNAR_ROOT_DIR, +) + + +def test_lunar_root_dir_is_string(): + assert isinstance( + LUNAR_ROOT_DIR, + str, + ) + + +def test_lunar_root_dir_is_not_empty(): + assert LUNAR_ROOT_DIR.strip() \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_locate_lunar.py b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_locate_lunar.py new file mode 100644 index 00000000..5257759a --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_locate_lunar.py @@ -0,0 +1,1385 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.locate_lunar as locate_lunar + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_valid_lunar_root( + root: Path, +) -> Path: + root.mkdir( + parents=True, + exist_ok=True, + ) + + for filename in ( + "LUNAR.py", + "atom_typing.py", + "all2lmp.py", + "bond_react_merge.py", + ): + ( + root / filename + ).write_text( + "# test\n", + encoding="utf-8", + ) + + ( + root / "src" + ).mkdir( + exist_ok=True, + ) + + ( + root / "frc_files" + ).mkdir( + exist_ok=True, + ) + + return root + + +def fake_config( + tmp_path, + lunar_root=None, +): + config_file = ( + tmp_path / "config.py" + ) + + config_file.write_text( + "LUNAR_ROOT_DIR = None\n", + encoding="utf-8", + ) + + return SimpleNamespace( + __file__=str(config_file), + LUNAR_ROOT_DIR=lunar_root, + ) + + +# ============================================================================= +# _normalize_path +# ============================================================================= + + +def test_normalize_path_none_returns_none(): + assert ( + locate_lunar._normalize_path( + None + ) + is None + ) + + +def test_normalize_path_empty_string_returns_none(): + assert ( + locate_lunar._normalize_path( + "" + ) + is None + ) + + +def test_normalize_path_strips_whitespace( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + locate_lunar.os.path, + "exists", + lambda path: ( + False + if path == "/mnt" + else Path(path).exists() + ), + ) + + expected = ( + tmp_path / "folder" + ).resolve() + + result = ( + locate_lunar._normalize_path( + f" {expected} " + ) + ) + + assert result == str( + expected + ) + + +def test_normalize_path_strips_double_quotes( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + locate_lunar.os.path, + "exists", + lambda path: ( + False + if path == "/mnt" + else Path(path).exists() + ), + ) + + expected = ( + tmp_path / "folder" + ).resolve() + + result = ( + locate_lunar._normalize_path( + f'"{expected}"' + ) + ) + + assert result == str( + expected + ) + + +def test_normalize_path_strips_single_quotes( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + locate_lunar.os.path, + "exists", + lambda path: ( + False + if path == "/mnt" + else Path(path).exists() + ), + ) + + expected = ( + tmp_path / "folder" + ).resolve() + + result = ( + locate_lunar._normalize_path( + f"'{expected}'" + ) + ) + + assert result == str( + expected + ) + + +def test_normalize_path_expands_environment_variable( + tmp_path, + monkeypatch, +): + monkeypatch.setenv( + "AUTOREACTER_LUNAR_TEST", + str(tmp_path), + ) + + monkeypatch.setattr( + locate_lunar.os.path, + "exists", + lambda path: ( + False + if path == "/mnt" + else Path(path).exists() + ), + ) + + result = ( + locate_lunar._normalize_path( + "$AUTOREACTER_LUNAR_TEST/lunar" + ) + ) + + assert result == str( + ( + tmp_path / "lunar" + ).resolve() + ) + + +def test_normalize_path_expands_user_home( + tmp_path, + monkeypatch, +): + monkeypatch.setenv( + "HOME", + str(tmp_path), + ) + + monkeypatch.setattr( + locate_lunar.os.path, + "exists", + lambda path: ( + False + if path == "/mnt" + else Path(path).exists() + ), + ) + + result = ( + locate_lunar._normalize_path( + "~/LUNAR" + ) + ) + + assert result == str( + ( + tmp_path / "LUNAR" + ).resolve() + ) + + +def test_normalize_path_converts_windows_path_to_wsl_when_mnt_exists( + monkeypatch, +): + monkeypatch.setattr( + locate_lunar.os.path, + "exists", + lambda path: ( + path == "/mnt" + ), + ) + + result = ( + locate_lunar._normalize_path( + r"C:\Users\Janitha\LUNAR" + ) + ) + + assert result == ( + "/mnt/c/Users/Janitha/LUNAR" + ) + + +def test_normalize_path_wsl_drive_is_lowercase( + monkeypatch, +): + monkeypatch.setattr( + locate_lunar.os.path, + "exists", + lambda path: ( + path == "/mnt" + ), + ) + + result = ( + locate_lunar._normalize_path( + r"D:\Research\LUNAR" + ) + ) + + assert result == ( + "/mnt/d/Research/LUNAR" + ) + + +def test_normalize_path_does_not_convert_windows_drive_without_mnt( + tmp_path, + monkeypatch, +): + monkeypatch.chdir( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar.os.path, + "exists", + lambda path: False, + ) + + result = ( + locate_lunar._normalize_path( + r"C:\Users\Test" + ) + ) + + # Characterizes current non-WSL behavior. + assert result == str( + Path( + r"C:\Users\Test" + ).resolve() + ) + + +# ============================================================================= +# _is_valid_dir +# ============================================================================= + + +def test_is_valid_dir_none_is_false(): + assert ( + locate_lunar._is_valid_dir( + None + ) + is False + ) + + +def test_is_valid_dir_missing_path_is_false( + tmp_path, +): + assert ( + locate_lunar._is_valid_dir( + tmp_path / "missing" + ) + is False + ) + + +def test_is_valid_dir_file_is_false( + tmp_path, +): + path = ( + tmp_path / "not_directory" + ) + + path.write_text( + "test", + encoding="utf-8", + ) + + assert ( + locate_lunar._is_valid_dir( + path + ) + is False + ) + + +def test_is_valid_dir_accepts_complete_lunar_root( + tmp_path, +): + root = make_valid_lunar_root( + tmp_path / "LUNAR" + ) + + assert ( + locate_lunar._is_valid_dir( + root + ) + is True + ) + + +@pytest.mark.parametrize( + "missing_file", + [ + "LUNAR.py", + "atom_typing.py", + "all2lmp.py", + "bond_react_merge.py", + ], +) +def test_is_valid_dir_requires_each_required_file( + tmp_path, + missing_file, +): + root = make_valid_lunar_root( + tmp_path / "LUNAR" + ) + + ( + root / missing_file + ).unlink() + + assert ( + locate_lunar._is_valid_dir( + root + ) + is False + ) + + +@pytest.mark.parametrize( + "missing_directory", + [ + "src", + "frc_files", + ], +) +def test_is_valid_dir_requires_each_required_directory( + tmp_path, + missing_directory, +): + root = make_valid_lunar_root( + tmp_path / "LUNAR" + ) + + ( + root / missing_directory + ).rmdir() + + assert ( + locate_lunar._is_valid_dir( + root + ) + is False + ) + + +# ============================================================================= +# _write_config_py +# ============================================================================= + + +def test_write_config_py_writes_string_path( + tmp_path, + monkeypatch, +): + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + locate_lunar._write_config_py( + "/tmp/LUNAR" + ) + + text = Path( + cfg.__file__ + ).read_text( + encoding="utf-8", + ) + + assert text == ( + "LUNAR_ROOT_DIR = '/tmp/LUNAR'\n" + ) + + +def test_write_config_py_writes_none( + tmp_path, + monkeypatch, +): + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + locate_lunar._write_config_py( + None + ) + + text = Path( + cfg.__file__ + ).read_text( + encoding="utf-8", + ) + + assert text == ( + "LUNAR_ROOT_DIR = None\n" + ) + + +def test_write_config_py_repr_handles_quotes( + tmp_path, + monkeypatch, +): + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + locate_lunar._write_config_py( + "/tmp/user's/LUNAR" + ) + + text = Path( + cfg.__file__ + ).read_text( + encoding="utf-8", + ) + + namespace = {} + + exec( + text, + namespace, + ) + + assert ( + namespace[ + "LUNAR_ROOT_DIR" + ] + == "/tmp/user's/LUNAR" + ) + + +# ============================================================================= +# set_LUNAR_loc +# ============================================================================= + + +def test_set_lunar_loc_valid_path( + tmp_path, + monkeypatch, +): + root = make_valid_lunar_root( + tmp_path / "LUNAR" + ) + + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + result = ( + locate_lunar.set_LUNAR_loc( + str(root) + ) + ) + + assert result == str( + root.resolve() + ) + + assert ( + cfg.LUNAR_ROOT_DIR + == str(root.resolve()) + ) + + text = Path( + cfg.__file__ + ).read_text( + encoding="utf-8", + ) + + assert str( + root.resolve() + ) in text + + +def test_set_lunar_loc_invalid_path_raises( + tmp_path, + monkeypatch, +): + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + with pytest.raises( + ValueError, + match="Not a valid directory", + ): + locate_lunar.set_LUNAR_loc( + str( + tmp_path / "missing" + ) + ) + + +def test_set_lunar_loc_invalid_path_does_not_change_config( + tmp_path, + monkeypatch, +): + original = "/old/LUNAR" + + cfg = fake_config( + tmp_path, + lunar_root=original, + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + with pytest.raises( + ValueError + ): + locate_lunar.set_LUNAR_loc( + str( + tmp_path / "missing" + ) + ) + + assert ( + cfg.LUNAR_ROOT_DIR + == original + ) + + +# ============================================================================= +# reset_LUNAR_loc +# ============================================================================= + + +def test_reset_lunar_loc_sets_config_to_none( + tmp_path, + monkeypatch, +): + cfg = fake_config( + tmp_path, + lunar_root="/old/LUNAR", + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + result = ( + locate_lunar.reset_LUNAR_loc() + ) + + assert result is None + + assert ( + cfg.LUNAR_ROOT_DIR + is None + ) + + +def test_reset_lunar_loc_persists_none( + tmp_path, + monkeypatch, +): + cfg = fake_config( + tmp_path, + lunar_root="/old/LUNAR", + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + locate_lunar.reset_LUNAR_loc() + + assert ( + Path( + cfg.__file__ + ).read_text( + encoding="utf-8", + ) + == "LUNAR_ROOT_DIR = None\n" + ) + + +# ============================================================================= +# _ask_cli +# ============================================================================= + + +def test_ask_cli_returns_normalized_path( + monkeypatch, +): + monkeypatch.setattr( + "builtins.input", + lambda prompt: ( + " /tmp/LUNAR " + ), + ) + + monkeypatch.setattr( + locate_lunar, + "_normalize_path", + lambda path: ( + f"normalized:{path}" + ), + ) + + result = ( + locate_lunar._ask_cli() + ) + + assert result == ( + "normalized:/tmp/LUNAR" + ) + + +def test_ask_cli_empty_input_returns_none( + monkeypatch, +): + monkeypatch.setattr( + "builtins.input", + lambda prompt: " ", + ) + + assert ( + locate_lunar._ask_cli() + is None + ) + + +# ============================================================================= +# _ask_gui +# ============================================================================= + + +def test_ask_gui_returns_normalized_selected_folder( + monkeypatch, +): + events = [] + + class FakeRoot: + def withdraw(self): + events.append( + "withdraw" + ) + + def destroy(self): + events.append( + "destroy" + ) + + monkeypatch.setattr( + locate_lunar.tk, + "Tk", + lambda: FakeRoot(), + ) + + monkeypatch.setattr( + locate_lunar.filedialog, + "askdirectory", + lambda title: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + locate_lunar, + "_normalize_path", + lambda path: + "normalized", + ) + + result = ( + locate_lunar._ask_gui() + ) + + assert result == "normalized" + + assert events == [ + "withdraw", + "destroy", + ] + + +def test_ask_gui_cancel_returns_none( + monkeypatch, +): + events = [] + + class FakeRoot: + def withdraw(self): + events.append( + "withdraw" + ) + + def destroy(self): + events.append( + "destroy" + ) + + monkeypatch.setattr( + locate_lunar.tk, + "Tk", + lambda: FakeRoot(), + ) + + monkeypatch.setattr( + locate_lunar.filedialog, + "askdirectory", + lambda title: "", + ) + + result = ( + locate_lunar._ask_gui() + ) + + assert result is None + + assert events == [ + "withdraw", + "destroy", + ] + + +# ============================================================================= +# get_LUNAR_loc - auto detection +# ============================================================================= + + +def test_get_lunar_loc_auto_detects_parent( + tmp_path, + monkeypatch, +): + lunar_root = make_valid_lunar_root( + tmp_path / "LUNAR" + ) + + module_dir = ( + lunar_root + / "some" + / "nested" + ) + + module_dir.mkdir( + parents=True, + ) + + fake_module_file = ( + module_dir + / "locate_lunar.py" + ) + + fake_module_file.write_text( + "", + encoding="utf-8", + ) + + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + monkeypatch.setattr( + locate_lunar, + "__file__", + str(fake_module_file), + ) + + result = ( + locate_lunar.get_LUNAR_loc( + force_prompt=False, + ) + ) + + assert result == str( + lunar_root + ) + + assert ( + cfg.LUNAR_ROOT_DIR + == str(lunar_root) + ) + + +def test_get_lunar_loc_auto_detection_precedes_saved_config( + tmp_path, + monkeypatch, +): + auto_root = make_valid_lunar_root( + tmp_path + / "auto" + / "LUNAR" + ) + + saved_root = make_valid_lunar_root( + tmp_path + / "saved" + / "LUNAR" + ) + + nested = ( + auto_root / "pkg" + ) + + nested.mkdir() + + fake_module = ( + nested / "locate_lunar.py" + ) + + fake_module.write_text( + "", + encoding="utf-8", + ) + + cfg = fake_config( + tmp_path, + lunar_root=str(saved_root), + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + monkeypatch.setattr( + locate_lunar, + "__file__", + str(fake_module), + ) + + result = ( + locate_lunar.get_LUNAR_loc() + ) + + # Characterizes current precedence: + # auto-detection occurs before saved configuration. + assert result == str( + auto_root + ) + + assert ( + cfg.LUNAR_ROOT_DIR + == str(auto_root) + ) + + +# ============================================================================= +# get_LUNAR_loc - saved configuration +# ============================================================================= + + +def test_get_lunar_loc_returns_saved_valid_path( + tmp_path, + monkeypatch, + capsys, +): + saved_root = make_valid_lunar_root( + tmp_path / "saved_lunar" + ) + + cfg = fake_config( + tmp_path, + lunar_root=str(saved_root), + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + original_validator = ( + locate_lunar._is_valid_dir + ) + + def validator(path): + return ( + Path(path) == saved_root + and original_validator(path) + ) + + monkeypatch.setattr( + locate_lunar, + "_is_valid_dir", + validator, + ) + + result = ( + locate_lunar.get_LUNAR_loc( + force_prompt=False, + ) + ) + + assert result == str( + saved_root + ) + + assert ( + "Using saved LUNAR root directory" + in capsys.readouterr().out + ) + + +def test_get_lunar_loc_force_prompt_ignores_saved_config( + tmp_path, + monkeypatch, +): + cfg = fake_config( + tmp_path, + lunar_root="/saved/LUNAR", + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + monkeypatch.setattr( + locate_lunar, + "_ask_cli", + lambda: None, + ) + + result = ( + locate_lunar.get_LUNAR_loc( + force_prompt=True, + use_gui=False, + ) + ) + + assert result is None + + +# ============================================================================= +# get_LUNAR_loc - CLI prompting +# ============================================================================= + + +def test_get_lunar_loc_cli_accepts_valid_prompted_path( + tmp_path, + monkeypatch, +): + lunar_root = make_valid_lunar_root( + tmp_path / "LUNAR" + ) + + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + monkeypatch.setattr( + locate_lunar, + "_ask_cli", + lambda: str( + lunar_root + ), + ) + + result = ( + locate_lunar.get_LUNAR_loc( + force_prompt=True, + use_gui=False, + ) + ) + + assert result == str( + lunar_root + ) + + assert ( + cfg.LUNAR_ROOT_DIR + == str(lunar_root) + ) + + +def test_get_lunar_loc_cli_cancel_returns_none( + tmp_path, + monkeypatch, +): + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + monkeypatch.setattr( + locate_lunar, + "_ask_cli", + lambda: None, + ) + + assert ( + locate_lunar.get_LUNAR_loc( + force_prompt=True, + use_gui=False, + ) + is None + ) + + +def test_get_lunar_loc_cli_retries_after_invalid_path( + tmp_path, + monkeypatch, + capsys, +): + valid_root = make_valid_lunar_root( + tmp_path / "valid_lunar" + ) + + invalid_root = ( + tmp_path / "invalid_lunar" + ) + + invalid_root.mkdir() + + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + answers = iter( + [ + str(invalid_root), + str(valid_root), + ] + ) + + monkeypatch.setattr( + locate_lunar, + "_ask_cli", + lambda: next( + answers + ), + ) + + result = ( + locate_lunar.get_LUNAR_loc( + force_prompt=True, + use_gui=False, + ) + ) + + assert result == str( + valid_root + ) + + output = ( + capsys.readouterr().out + ) + + assert ( + "Invalid LUNAR directory" + in output + ) + + assert ( + "Expected files:" + in output + ) + + assert ( + "Expected directory:" + in output + ) + + +# ============================================================================= +# get_LUNAR_loc - GUI prompting +# ============================================================================= + + +def test_get_lunar_loc_gui_accepts_valid_path( + tmp_path, + monkeypatch, +): + lunar_root = make_valid_lunar_root( + tmp_path / "LUNAR" + ) + + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + monkeypatch.setattr( + locate_lunar, + "_ask_gui", + lambda: str( + lunar_root + ), + ) + + result = ( + locate_lunar.get_LUNAR_loc( + force_prompt=True, + use_gui=True, + ) + ) + + assert result == str( + lunar_root + ) + + +def test_get_lunar_loc_gui_invalid_path_shows_error_then_cancel( + tmp_path, + monkeypatch, +): + invalid_root = ( + tmp_path / "invalid" + ) + + invalid_root.mkdir() + + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + answers = iter( + [ + str(invalid_root), + None, + ] + ) + + monkeypatch.setattr( + locate_lunar, + "_ask_gui", + lambda: next( + answers + ), + ) + + events = [] + + class FakeRoot: + def withdraw(self): + events.append( + "withdraw" + ) + + def destroy(self): + events.append( + "destroy" + ) + + monkeypatch.setattr( + locate_lunar.tk, + "Tk", + lambda: FakeRoot(), + ) + + monkeypatch.setattr( + locate_lunar.messagebox, + "showerror", + lambda title, message: + events.append( + ( + title, + message, + ) + ), + ) + + result = ( + locate_lunar.get_LUNAR_loc( + force_prompt=True, + use_gui=True, + ) + ) + + assert result is None + + assert any( + isinstance(event, tuple) + and event[0] == "Invalid Folder" + for event in events + ) + + +def test_get_lunar_loc_none_use_gui_uses_global_setting( + tmp_path, + monkeypatch, +): + lunar_root = make_valid_lunar_root( + tmp_path / "LUNAR" + ) + + cfg = fake_config( + tmp_path + ) + + monkeypatch.setattr( + locate_lunar, + "config", + cfg, + ) + + monkeypatch.setattr( + locate_lunar, + "USE_GUI", + True, + ) + + calls = [] + + monkeypatch.setattr( + locate_lunar, + "_ask_gui", + lambda: ( + calls.append( + "gui" + ) + or str(lunar_root) + ), + ) + + monkeypatch.setattr( + locate_lunar, + "_ask_cli", + lambda: pytest.fail( + "CLI prompt should not be used" + ), + ) + + result = ( + locate_lunar.get_LUNAR_loc( + force_prompt=True, + use_gui=None, + ) + ) + + assert result == str( + lunar_root + ) + + assert calls == [ + "gui" + ] \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_utils.py b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_utils.py new file mode 100644 index 00000000..a39bd856 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_utils.py @@ -0,0 +1,691 @@ +from pathlib import Path + +import pytest + +import AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_utils as lunar_utils +from AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_utils import ( + get_ending_integer, + is_wsl, + loading_screen, + move_merge_outputs, + normalize_path, +) + + +# ============================================================================= +# is_wsl +# ============================================================================= + + +def test_is_wsl_true_when_platform_release_contains_microsoft( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils.platform, + "release", + lambda: ( + "5.15.153.1-microsoft-standard-WSL2" + ), + ) + + monkeypatch.delenv( + "WSL_INTEROP", + raising=False, + ) + + assert is_wsl() is True + + +def test_is_wsl_release_check_is_case_insensitive( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils.platform, + "release", + lambda: ( + "5.15-MICROSOFT-STANDARD" + ), + ) + + monkeypatch.delenv( + "WSL_INTEROP", + raising=False, + ) + + assert is_wsl() is True + + +def test_is_wsl_true_when_wsl_interop_environment_exists( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils.platform, + "release", + lambda: "Linux", + ) + + monkeypatch.setenv( + "WSL_INTEROP", + "/run/WSL/123_interop", + ) + + assert is_wsl() is True + + +def test_is_wsl_false_on_normal_linux( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils.platform, + "release", + lambda: ( + "6.8.0-generic" + ), + ) + + monkeypatch.delenv( + "WSL_INTEROP", + raising=False, + ) + + assert is_wsl() is False + + +# ============================================================================= +# normalize_path +# ============================================================================= + + +def test_normalize_path_accepts_path_object( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: False, + ) + + monkeypatch.setattr( + lunar_utils.platform, + "system", + lambda: "Linux", + ) + + result = normalize_path( + Path("/tmp/test/path") + ) + + assert result == ( + "/tmp/test/path" + ) + + +def test_normalize_path_strips_whitespace_and_double_quotes( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: False, + ) + + monkeypatch.setattr( + lunar_utils.platform, + "system", + lambda: "Linux", + ) + + result = normalize_path( + ' "/tmp/test/path" ' + ) + + assert result == ( + "/tmp/test/path" + ) + + +def test_normalize_path_strips_single_quotes( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: False, + ) + + monkeypatch.setattr( + lunar_utils.platform, + "system", + lambda: "Linux", + ) + + result = normalize_path( + "'/tmp/test/path'" + ) + + assert result == ( + "/tmp/test/path" + ) + + +def test_normalize_path_converts_backslashes_on_linux( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: False, + ) + + monkeypatch.setattr( + lunar_utils.platform, + "system", + lambda: "Linux", + ) + + result = normalize_path( + r"/tmp/test\folder\file" + ) + + assert result == ( + "/tmp/test/folder/file" + ) + + +def test_normalize_path_windows_drive_to_wsl( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: True, + ) + + result = normalize_path( + "C:/Users/Janitha/LUNAR" + ) + + assert result == ( + "/mnt/c/Users/Janitha/LUNAR" + ) + + +def test_normalize_path_windows_backslashes_to_wsl( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: True, + ) + + result = normalize_path( + r"D:\Research\LUNAR\data" + ) + + assert result == ( + "/mnt/d/Research/LUNAR/data" + ) + + +def test_normalize_path_wsl_drive_letter_is_lowercase( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: True, + ) + + result = normalize_path( + "Z:/Some/Folder" + ) + + assert result == ( + "/mnt/z/Some/Folder" + ) + + +def test_normalize_path_existing_wsl_path_is_preserved( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: True, + ) + + result = normalize_path( + "/mnt/c/Users/Janitha/LUNAR" + ) + + assert result == ( + "/mnt/c/Users/Janitha/LUNAR" + ) + + +def test_normalize_path_wsl_path_to_windows( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: False, + ) + + monkeypatch.setattr( + lunar_utils.platform, + "system", + lambda: "Windows", + ) + + result = normalize_path( + "/mnt/c/Users/Janitha/LUNAR" + ) + + assert result == ( + r"C:\Users\Janitha\LUNAR" + ) + + +def test_normalize_path_wsl_path_without_leading_slash_to_windows( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: False, + ) + + monkeypatch.setattr( + lunar_utils.platform, + "system", + lambda: "Windows", + ) + + result = normalize_path( + "mnt/d/Research/LUNAR" + ) + + assert result == ( + r"D:\Research\LUNAR" + ) + + +def test_normalize_path_linux_collapses_parent_segments( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils, + "is_wsl", + lambda: False, + ) + + monkeypatch.setattr( + lunar_utils.platform, + "system", + lambda: "Linux", + ) + + result = normalize_path( + "/tmp/a/../b" + ) + + assert result == ( + "/tmp/b" + ) + + +# ============================================================================= +# get_ending_integer +# ============================================================================= + + +@pytest.mark.parametrize( + "value, expected", + [ + ( + "pre12", + 12, + ), + ( + "reaction_123", + 123, + ), + ( + "RXN_1", + 1, + ), + ( + "abc0007", + 7, + ), + ( + "42", + 42, + ), + ( + "test0", + 0, + ), + ], +) +def test_get_ending_integer( + value, + expected, +): + assert ( + get_ending_integer( + value + ) + == expected + ) + + +@pytest.mark.parametrize( + "value, expected", + [ + ("pre12", 12), + ("reaction_123", 123), + ("RXN_1", 1), + ("abc0007", 7), + ("42", 42), + ("test0", 0), + ("1.5", 5), + ], +) +def test_get_ending_integer( + value, + expected, +): + assert ( + get_ending_integer(value) + == expected + ) + + +@pytest.mark.parametrize( + "value", + [ + "", + "abc", + "123abc", + "rxn_1_test", + ], +) +def test_get_ending_integer_none_when_no_trailing_integer( + value, +): + assert ( + get_ending_integer(value) + is None + ) + +# ============================================================================= +# move_merge_outputs +# ============================================================================= + + +def test_move_merge_outputs_creates_destination( + tmp_path, +): + src = tmp_path / "src" + dst = tmp_path / "dst" + + src.mkdir() + + move_merge_outputs( + src, + dst, + ) + + assert dst.is_dir() + + +def test_move_merge_outputs_moves_expected_files( + tmp_path, +): + src = tmp_path / "src" + dst = tmp_path / "dst" + + src.mkdir() + + filenames = [ + "system_merged.data", + "system_merged.lmpmol", + "force_field.data", + "log.lammps", + "all2lmp.log", + "other.log", + ] + + for filename in filenames: + ( + src / filename + ).write_text( + filename, + encoding="utf-8", + ) + + move_merge_outputs( + src, + dst, + ) + + for filename in filenames: + assert ( + dst / filename + ).is_file() + + assert not ( + src / filename + ).exists() + + +def test_move_merge_outputs_leaves_irrelevant_files_in_source( + tmp_path, +): + src = tmp_path / "src" + dst = tmp_path / "dst" + + src.mkdir() + + irrelevant = [ + "input.data", + "notes.txt", + "template.molecule", + "random.json", + ] + + for filename in irrelevant: + ( + src / filename + ).write_text( + "keep", + encoding="utf-8", + ) + + move_merge_outputs( + src, + dst, + ) + + for filename in irrelevant: + assert ( + src / filename + ).is_file() + + assert not ( + dst / filename + ).exists() + + +def test_move_merge_outputs_preserves_file_contents( + tmp_path, +): + src = tmp_path / "src" + dst = tmp_path / "dst" + + src.mkdir() + + source_file = ( + src / "sample_merged.data" + ) + + source_file.write_text( + "LAMMPS DATA CONTENT", + encoding="utf-8", + ) + + move_merge_outputs( + src, + dst, + ) + + assert ( + dst + / "sample_merged.data" + ).read_text( + encoding="utf-8" + ) == "LAMMPS DATA CONTENT" + + +def test_move_merge_outputs_accepts_string_paths( + tmp_path, +): + src = tmp_path / "src" + dst = tmp_path / "dst" + + src.mkdir() + + ( + src / "force_field.data" + ).write_text( + "force field", + encoding="utf-8", + ) + + move_merge_outputs( + str(src), + str(dst), + ) + + assert ( + dst / "force_field.data" + ).is_file() + + +def test_move_merge_outputs_empty_source_is_noop_except_destination_creation( + tmp_path, +): + src = tmp_path / "src" + dst = tmp_path / "dst" + + src.mkdir() + + move_merge_outputs( + src, + dst, + ) + + assert dst.is_dir() + + assert list( + dst.iterdir() + ) == [] + + +# ============================================================================= +# loading_screen +# ============================================================================= + + +def test_loading_screen_prints_banner_and_ready( + monkeypatch, + capsys, +): + monkeypatch.setattr( + lunar_utils.time, + "sleep", + lambda seconds: None, + ) + + loading_screen() + + output = capsys.readouterr().out + + assert "Loading LUNAR" in output + assert "Ready!" in output + + # Stable portion of the ASCII banner. + assert "█████" in output + + +def test_loading_screen_uses_custom_name( + monkeypatch, + capsys, +): + monkeypatch.setattr( + lunar_utils.time, + "sleep", + lambda seconds: None, + ) + + loading_screen( + "all2lmp" + ) + + output = capsys.readouterr().out + + assert ( + "Loading all2lmp" + in output + ) + + +def test_loading_screen_runs_ten_spinner_steps( + monkeypatch, +): + sleep_calls = [] + + monkeypatch.setattr( + lunar_utils.time, + "sleep", + lambda seconds: + sleep_calls.append( + seconds + ), + ) + + loading_screen( + "test" + ) + + assert sleep_calls == [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + ] + + +def test_loading_screen_returns_none( + monkeypatch, +): + monkeypatch.setattr( + lunar_utils.time, + "sleep", + lambda seconds: None, + ) + + result = loading_screen( + "test" + ) + + assert result is None \ No newline at end of file From 50e1d3459da2314c0b954c481c1a3448e93f30f9 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:08:39 -0400 Subject: [PATCH 150/176] Add unit tests for ff_wrapper components --- .../ff_wrapper/template_builder.py | 37 - .../lunar_client/test_lunar_api_wrapper.py | 1312 ++++++ .../lunar_client/test_lunar_executor.py | 2257 ++++++++++ .../lunar_client/test_merge_builder.py | 1140 +++++ .../ff_wrapper/test_REACTER_files_builder.py | 3765 +++++++++++++++++ .../ff_wrapper/test_ff_locator.py | 829 ++++ .../ff_wrapper/test_ff_validator.py | 1273 ++++++ .../ff_wrapper/test_ff_wrapper.py | 1156 +++++ .../test_modifiers_molecule_files.py | 1717 ++++++++ .../test_molecule_3d_preparation.py | 2288 ++++++++++ 10 files changed, 15737 insertions(+), 37 deletions(-) delete mode 100644 AutoREACTER/reaction_preparation/ff_wrapper/template_builder.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_api_wrapper.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_executor.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_merge_builder.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/test_REACTER_files_builder.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/test_ff_locator.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/test_ff_validator.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/test_ff_wrapper.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/test_modifiers_molecule_files.py create mode 100644 tests/unit/reaction_preparation/ff_wrapper/test_molecule_3d_preparation.py diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/template_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/template_builder.py deleted file mode 100644 index 2d00c684..00000000 --- a/AutoREACTER/reaction_preparation/ff_wrapper/template_builder.py +++ /dev/null @@ -1,37 +0,0 @@ -from pathlib import Path -from typing import List - -from AutoREACTER.input_parser import SimulationSetup -from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import ReactionMetadata -from AutoREACTER.reaction_preparation.lunar_client.molecule_3d_preparation import Molecule3DPreparation -from AutoREACTER.reaction_preparation.lunar_client.lunar_api_wrapper import LunarAPIWrapper - - -class TemplateBuilder: - """ - The TemplateBuilder class is responsible for constructing reaction templates based on the prepared reactions and monomer information. It takes the processed reaction data and generates the necessary files and structures for use in simulations. - - Attributes: - cache_dir: Path to the directory where intermediate files and templates will be stored. - simulation_setup: An instance of SimulationSetup containing the parsed input data and configuration for the simulation. - """ - - def __init__(self, cache_dir: Path, ): - self.cache_dir = cache_dir - - - def build_templates(self, simulation_setup: SimulationSetup, prepared_reactions: List[ReactionMetadata]) -> None: - """ - Build reaction templates from the prepared reactions. - - Args: - simulation_setup: An instance of SimulationSetup containing the parsed input data and configuration for the simulation. - prepared_reactions: A list of ReactionMetadata objects containing information about each prepared reaction. - - Returns: - None. The function generates template files in the specified cache directory. - """ - molecule3dpreparation = Molecule3DPreparation(self.cache_dir) - updated_inputs_with_3d_mols, prepared_reactions_with_3d_mols = molecule3dpreparation.prepare_molecule_3d_geometry(simulation_setup, prepared_reactions) - lunar_api_wrapper = LunarAPIWrapper(self.cache_dir) - lunar_api_wrapper.lunar_workflow(updated_inputs_with_3d_mols, prepared_reactions_with_3d_mols) diff --git a/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_api_wrapper.py b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_api_wrapper.py new file mode 100644 index 00000000..0eb49536 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_api_wrapper.py @@ -0,0 +1,1312 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_api_wrapper as lunar_api +from AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_api_wrapper import ( + LunarAPIWrapper, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_session( + tmp_path, + *, + force_field="PCFF", +): + inputs = SimpleNamespace( + force_field=force_field, + ) + + return SimpleNamespace( + inputs=inputs, + staging_dir=tmp_path / "staging", + ) + + +class FakeExecutor: + def __init__( + self, + lunar_location, + cache_dir, + ): + self.lunar_location = Path( + lunar_location + ) + + self.cache_dir = Path( + cache_dir + ) + + self.cache_atom_typing = ( + self.cache_dir + / "atom_typing" + ) + + self.cache_all2lmp = ( + self.cache_dir + / "all2lmp" + ) + + self.cache_bond_react_merge = ( + self.cache_dir + / "bond_react_merge" + ) + + self.calls = [] + + def run_atom_typing( + self, + updated_inputs, + prepared_reactions, + force_field, + ): + self.calls.append( + ( + "atom_typing", + updated_inputs, + prepared_reactions, + force_field, + ) + ) + + return [ + "atom-typing-result" + ] + + def run_all2lmp( + self, + atom_typing_results, + frc_file, + ): + self.calls.append( + ( + "all2lmp", + atom_typing_results, + frc_file, + ) + ) + + return [ + "all2lmp-result" + ] + + def run_bond_react_merge( + self, + merge_input_file_path, + all2lmp_results, + ): + self.calls.append( + ( + "bond_react_merge", + merge_input_file_path, + all2lmp_results, + ) + ) + + return "final-files" + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_session( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + wrapper = LunarAPIWrapper( + session + ) + + assert wrapper.session is session + assert wrapper.inputs is session.inputs + + +def test_constructor_creates_lunar_cache_directory( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + wrapper = LunarAPIWrapper( + session + ) + + expected = ( + tmp_path + / "staging" + / "lunar" + ) + + assert wrapper.cache_dir == expected + + assert expected.is_dir() + + +def test_constructor_requests_lunar_location_without_gui( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + calls = [] + + def fake_get_lunar_loc( + use_gui=None, + ): + calls.append( + use_gui + ) + + return "/tmp/LUNAR" + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + fake_get_lunar_loc, + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + LunarAPIWrapper( + session + ) + + assert calls == [ + False + ] + + +def test_constructor_stores_lunar_location_as_path( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + wrapper = LunarAPIWrapper( + session + ) + + assert isinstance( + wrapper.LUNAR_LOCATION, + Path, + ) + + assert wrapper.LUNAR_LOCATION == ( + Path("/tmp/LUNAR") + ) + + +def test_constructor_initializes_executor_with_expected_paths( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + captured = [] + + class CapturingExecutor: + def __init__( + self, + lunar_location, + cache_dir, + ): + captured.append( + ( + lunar_location, + cache_dir, + ) + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + CapturingExecutor, + ) + + wrapper = LunarAPIWrapper( + session + ) + + assert captured == [ + ( + Path("/tmp/LUNAR"), + tmp_path + / "staging" + / "lunar", + ) + ] + + assert isinstance( + wrapper.executor, + CapturingExecutor, + ) + + +# ============================================================================= +# lunar_workflow - loading screen +# ============================================================================= + + +def test_lunar_workflow_calls_loading_screen( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + loading_calls = [] + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: + loading_calls.append( + name + ), + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + Path("/tmp/pcff.frc"), + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + Path("/tmp/merge_input.txt"), + ) + + wrapper = LunarAPIWrapper( + session + ) + + wrapper.lunar_workflow( + session.inputs, + [], + ) + + assert loading_calls == [ + "LUNAR Workflow" + ] + + +# ============================================================================= +# Force-field lookup +# ============================================================================= + + +def test_lunar_workflow_uses_force_field_from_updated_inputs( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path, + force_field="PCFF", + ) + + updated_inputs = SimpleNamespace( + force_field="COMPASS", + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + ff_calls = [] + + def fake_get_force_field_file( + *, + force_field, + lunar_location, + ): + ff_calls.append( + ( + force_field, + lunar_location, + ) + ) + + return Path( + "/tmp/compass.frc" + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + fake_get_force_field_file, + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + Path("/tmp/merge_input.txt"), + ) + + wrapper = LunarAPIWrapper( + session + ) + + wrapper.lunar_workflow( + updated_inputs, + [], + ) + + assert ff_calls == [ + ( + "COMPASS", + Path("/tmp/LUNAR"), + ) + ] + + +# ============================================================================= +# Stage 1 - atom typing +# ============================================================================= + + +def test_lunar_workflow_passes_inputs_and_reactions_to_atom_typing( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + updated_inputs = SimpleNamespace( + force_field="PCFF", + ) + + prepared_reactions = [ + object(), + object(), + ] + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + Path("/tmp/pcff.frc"), + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + Path("/tmp/merge_input.txt"), + ) + + wrapper = LunarAPIWrapper( + session + ) + + wrapper.lunar_workflow( + updated_inputs, + prepared_reactions, + ) + + assert ( + wrapper.executor.calls[0] + == ( + "atom_typing", + updated_inputs, + prepared_reactions, + "PCFF", + ) + ) + + +# ============================================================================= +# Stage 2 - all2lmp +# ============================================================================= + + +def test_lunar_workflow_passes_atom_typing_results_to_all2lmp( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + ff_file = Path( + "/tmp/pcff.frc" + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + ff_file, + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + Path("/tmp/merge_input.txt"), + ) + + wrapper = LunarAPIWrapper( + session + ) + + wrapper.lunar_workflow( + session.inputs, + [], + ) + + assert ( + wrapper.executor.calls[1] + == ( + "all2lmp", + [ + "atom-typing-result" + ], + ff_file, + ) + ) + + +# ============================================================================= +# Stage 3 - merge input builder +# ============================================================================= + + +def test_lunar_workflow_builds_merge_input_with_executor_caches( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + Path("/tmp/pcff.frc"), + ) + + merge_calls = [] + + def fake_write_merge( + *, + cache_bond_react_merge, + cache_all2lmp, + all2lmp_results, + ): + merge_calls.append( + ( + cache_bond_react_merge, + cache_all2lmp, + all2lmp_results, + ) + ) + + return Path( + "/tmp/merge_input.txt" + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + fake_write_merge, + ) + + wrapper = LunarAPIWrapper( + session + ) + + wrapper.lunar_workflow( + session.inputs, + [], + ) + + assert merge_calls == [ + ( + wrapper.executor.cache_bond_react_merge, + wrapper.executor.cache_all2lmp, + [ + "all2lmp-result" + ], + ) + ] + + +# ============================================================================= +# Stage 4 - bond/react merge +# ============================================================================= + + +def test_lunar_workflow_passes_merge_file_and_all2lmp_results_to_final_stage( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + Path("/tmp/pcff.frc"), + ) + + merge_input = Path( + "/tmp/merge_input.txt" + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + merge_input, + ) + + wrapper = LunarAPIWrapper( + session + ) + + wrapper.lunar_workflow( + session.inputs, + [], + ) + + assert ( + wrapper.executor.calls[2] + == ( + "bond_react_merge", + merge_input, + [ + "all2lmp-result" + ], + ) + ) + + +# ============================================================================= +# Workflow result +# ============================================================================= + + +def test_lunar_workflow_returns_final_files( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + Path("/tmp/pcff.frc"), + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + Path("/tmp/merge_input.txt"), + ) + + wrapper = LunarAPIWrapper( + session + ) + + result = wrapper.lunar_workflow( + session.inputs, + [], + ) + + assert result == ( + "final-files" + ) + + +# ============================================================================= +# Execution order +# ============================================================================= + + +def test_lunar_workflow_executes_stages_in_order( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + events = [] + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: + events.append( + "loading" + ), + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + ( + events.append( + "force-field" + ) + or Path( + "/tmp/pcff.frc" + ) + ), + ) + + class OrderedExecutor: + def __init__( + self, + lunar_location, + cache_dir, + ): + self.cache_all2lmp = ( + Path(cache_dir) + / "all2lmp" + ) + + self.cache_bond_react_merge = ( + Path(cache_dir) + / "bond_react_merge" + ) + + def run_atom_typing( + self, + **kwargs, + ): + events.append( + "atom-typing" + ) + + return [ + "typed" + ] + + def run_all2lmp( + self, + **kwargs, + ): + events.append( + "all2lmp" + ) + + return [ + "converted" + ] + + def run_bond_react_merge( + self, + **kwargs, + ): + events.append( + "bond-react-merge" + ) + + return "final" + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + OrderedExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + ( + events.append( + "merge-builder" + ) + or Path( + "/tmp/merge_input.txt" + ) + ), + ) + + wrapper = LunarAPIWrapper( + session + ) + + result = wrapper.lunar_workflow( + session.inputs, + [], + ) + + assert result == "final" + + assert events == [ + "loading", + "force-field", + "atom-typing", + "all2lmp", + "merge-builder", + "bond-react-merge", + ] + + +# ============================================================================= +# Failure propagation +# ============================================================================= + + +def test_force_field_lookup_error_propagates( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FakeExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + def fail(**kwargs): + raise FileNotFoundError( + "force field missing" + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + fail, + ) + + wrapper = LunarAPIWrapper( + session + ) + + with pytest.raises( + FileNotFoundError, + match="force field missing", + ): + wrapper.lunar_workflow( + session.inputs, + [], + ) + + +def test_atom_typing_error_stops_later_stages( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + Path("/tmp/pcff.frc"), + ) + + class FailingExecutor: + def __init__( + self, + lunar_location, + cache_dir, + ): + self.cache_all2lmp = ( + Path(cache_dir) + / "all2lmp" + ) + + self.cache_bond_react_merge = ( + Path(cache_dir) + / "bond_react_merge" + ) + + def run_atom_typing( + self, + **kwargs, + ): + raise RuntimeError( + "atom typing failed" + ) + + def run_all2lmp( + self, + **kwargs, + ): + pytest.fail( + "all2lmp must not run" + ) + + def run_bond_react_merge( + self, + **kwargs, + ): + pytest.fail( + "merge must not run" + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FailingExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + pytest.fail( + "merge builder must not run" + ), + ) + + wrapper = LunarAPIWrapper( + session + ) + + with pytest.raises( + RuntimeError, + match="atom typing failed", + ): + wrapper.lunar_workflow( + session.inputs, + [], + ) + + +def test_all2lmp_error_stops_merge_stages( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + Path("/tmp/pcff.frc"), + ) + + class FailingExecutor: + def __init__( + self, + lunar_location, + cache_dir, + ): + self.cache_all2lmp = ( + Path(cache_dir) + / "all2lmp" + ) + + self.cache_bond_react_merge = ( + Path(cache_dir) + / "bond_react_merge" + ) + + def run_atom_typing( + self, + **kwargs, + ): + return [ + "typed" + ] + + def run_all2lmp( + self, + **kwargs, + ): + raise RuntimeError( + "all2lmp failed" + ) + + def run_bond_react_merge( + self, + **kwargs, + ): + pytest.fail( + "bond merge must not run" + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + FailingExecutor, + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + lambda **kwargs: + pytest.fail( + "merge builder must not run" + ), + ) + + wrapper = LunarAPIWrapper( + session + ) + + with pytest.raises( + RuntimeError, + match="all2lmp failed", + ): + wrapper.lunar_workflow( + session.inputs, + [], + ) + + +def test_merge_builder_error_stops_final_merge( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + monkeypatch.setattr( + lunar_api, + "get_LUNAR_loc", + lambda use_gui=False: + "/tmp/LUNAR", + ) + + monkeypatch.setattr( + lunar_api, + "loading_screen", + lambda name: None, + ) + + monkeypatch.setattr( + lunar_api, + "get_force_field_file", + lambda **kwargs: + Path("/tmp/pcff.frc"), + ) + + class Executor: + def __init__( + self, + lunar_location, + cache_dir, + ): + self.cache_all2lmp = ( + Path(cache_dir) + / "all2lmp" + ) + + self.cache_bond_react_merge = ( + Path(cache_dir) + / "bond_react_merge" + ) + + def run_atom_typing( + self, + **kwargs, + ): + return [ + "typed" + ] + + def run_all2lmp( + self, + **kwargs, + ): + return [ + "converted" + ] + + def run_bond_react_merge( + self, + **kwargs, + ): + pytest.fail( + "final merge must not run" + ) + + monkeypatch.setattr( + lunar_api, + "LunarExecutor", + Executor, + ) + + def fail_merge_builder( + **kwargs, + ): + raise ValueError( + "bad merge input" + ) + + monkeypatch.setattr( + lunar_api, + "write_bond_react_merge_input", + fail_merge_builder, + ) + + wrapper = LunarAPIWrapper( + session + ) + + with pytest.raises( + ValueError, + match="bad merge input", + ): + wrapper.lunar_workflow( + session.inputs, + [], + ) \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_executor.py b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_executor.py new file mode 100644 index 00000000..b9345c45 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_lunar_executor.py @@ -0,0 +1,2257 @@ +from dataclasses import dataclass +from pathlib import Path +from types import SimpleNamespace +import subprocess +import sys + +import pytest + +import AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_executor as lunar_executor +from AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.lunar_executor import ( + All2LMPResult, + AtomTypingResult, + LunarExecutor, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_monomer( + *, + name="mma", + molecule_3Dmol_path=None, + status=True, +): + return SimpleNamespace( + name=name, + molecule_3Dmol_path=molecule_3Dmol_path, + status=status, + ) + + +def make_inputs( + monomers=None, +): + return SimpleNamespace( + monomers=list( + monomers or [] + ) + ) + + +def make_reaction( + *, + reaction_id=1, + pre_path=None, + post_path=None, +): + return SimpleNamespace( + reaction_id=reaction_id, + reactant_combined_3Dmol_path=pre_path, + product_combined_3Dmol_path=post_path, + ) + + +def make_executor( + tmp_path, +): + lunar_root = ( + tmp_path / "LUNAR" + ) + + lunar_root.mkdir( + parents=True, + exist_ok=True, + ) + + return LunarExecutor( + lunar_location=lunar_root, + cache_dir=tmp_path / "cache", + ) + + +def install_fake_atom_typing_subprocess( + monkeypatch, +): + """ + Fake atom_typing.py execution and create exactly the files that + LunarExecutor expects. + """ + calls = [] + + def fake_run( + command, + check=False, + **kwargs, + ): + calls.append( + { + "command": list(command), + "check": check, + **kwargs, + } + ) + + topo = Path( + command[ + command.index("-topo") + 1 + ] + ) + + output_dir = Path( + command[ + command.index("-dir") + 1 + ] + ) + + output_dir.mkdir( + parents=True, + exist_ok=True, + ) + + # Monomer output naming is based on the input stem. + stem = topo.stem + + ( + output_dir + / f"{stem}_typed.data" + ).write_text( + "typed data", + encoding="utf-8", + ) + + ( + output_dir + / f"{stem}_typed.nta" + ).write_text( + "nta", + encoding="utf-8", + ) + + return SimpleNamespace( + returncode=0 + ) + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + fake_run, + ) + + return calls + + +# ============================================================================= +# Fake FF-wrapper objects for bond_react_merge tests +# ============================================================================= + + +@dataclass +class FakeDataFiles: + data_file: Path + lmp_molecule_file: Path + + +@dataclass +class FakeMoleculeFile: + id: str + molecule_files: FakeDataFiles + + +@dataclass +class FakeTemplateFile: + reaction_id: int | None + pre_reaction_file: FakeDataFiles + post_reaction_file: FakeDataFiles + + +@dataclass +class FakeFFFiles: + force_field_data: Path + in_file: Path + molecule_files: list + template_files: list + + +def install_fake_ff_structures( + monkeypatch, +): + monkeypatch.setattr( + lunar_executor, + "DataFiles", + FakeDataFiles, + ) + + monkeypatch.setattr( + lunar_executor, + "MoleculeFile", + FakeMoleculeFile, + ) + + monkeypatch.setattr( + lunar_executor, + "TemplateFile", + FakeTemplateFile, + ) + + monkeypatch.setattr( + lunar_executor, + "FFFiles", + FakeFFFiles, + ) + + +# ============================================================================= +# Dataclasses +# ============================================================================= + + +def test_atom_typing_result_fields( + tmp_path, +): + result = AtomTypingResult( + id="data1", + molecule=True, + typed_data_file=( + tmp_path / "typed.data" + ), + nta_file=( + tmp_path / "typed.nta" + ), + ) + + assert result.id == "data1" + assert result.molecule is True + + assert result.typed_data_file == ( + tmp_path / "typed.data" + ) + + assert result.nta_file == ( + tmp_path / "typed.nta" + ) + + +def test_atom_typing_result_uses_slots( + tmp_path, +): + result = AtomTypingResult( + id="data1", + molecule=True, + typed_data_file=( + tmp_path / "typed.data" + ), + nta_file=( + tmp_path / "typed.nta" + ), + ) + + with pytest.raises( + AttributeError + ): + result.extra = 1 + + +def test_all2lmp_result_fields(): + result = All2LMPResult( + id="pre1", + molecule=False, + all2lmp_data_file=Path( + "pre1_typed_IFF.data" + ), + ) + + assert result.id == "pre1" + assert result.molecule is False + + assert ( + result.all2lmp_data_file + == Path( + "pre1_typed_IFF.data" + ) + ) + + +def test_all2lmp_result_uses_slots(): + result = All2LMPResult( + id="data1", + molecule=True, + all2lmp_data_file=Path( + "data1_typed_IFF.data" + ), + ) + + with pytest.raises( + AttributeError + ): + result.extra = 1 + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_sets_lunar_script_paths( + tmp_path, +): + lunar_root = ( + tmp_path / "LUNAR" + ) + + executor = LunarExecutor( + lunar_root, + tmp_path / "cache", + ) + + assert executor.lunar_location == ( + lunar_root + ) + + assert executor.atom_typing_py == ( + lunar_root + / "atom_typing.py" + ) + + assert executor.all2lmp_py == ( + lunar_root + / "all2lmp.py" + ) + + assert executor.bond_react_merge_py == ( + lunar_root + / "bond_react_merge.py" + ) + + +def test_constructor_creates_stage_caches( + tmp_path, +): + cache = ( + tmp_path / "cache" + ) + + executor = LunarExecutor( + tmp_path / "LUNAR", + cache, + ) + + assert executor.cache_atom_typing == ( + cache / "atom_typing" + ) + + assert executor.cache_all2lmp == ( + cache / "all2lmp" + ) + + assert ( + executor.cache_bond_react_merge + == cache / "bond_react_merge" + ) + + assert ( + executor.cache_atom_typing.is_dir() + ) + + assert ( + executor.cache_all2lmp.is_dir() + ) + + assert ( + executor + .cache_bond_react_merge + .is_dir() + ) + + +def test_constructor_accepts_string_paths( + tmp_path, +): + executor = LunarExecutor( + str(tmp_path / "LUNAR"), + str(tmp_path / "cache"), + ) + + assert isinstance( + executor.lunar_location, + Path, + ) + + assert isinstance( + executor.cache_atom_typing, + Path, + ) + + +# ============================================================================= +# run_atom_typing - monomers +# ============================================================================= + + +def test_run_atom_typing_active_monomer( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + molecule_file = ( + tmp_path / "mma.mol" + ) + + molecule_file.write_text( + "molecule", + encoding="utf-8", + ) + + inputs = make_inputs( + [ + make_monomer( + name="mma", + molecule_3Dmol_path=molecule_file, + ) + ] + ) + + calls = ( + install_fake_atom_typing_subprocess( + monkeypatch + ) + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + results = executor.run_atom_typing( + inputs, + prepared_reactions=[], + force_field="PCFF", + ) + + assert len(results) == 1 + + result = results[0] + + assert result.id == "mma" + assert result.molecule is True + + assert result.typed_data_file == ( + executor.cache_atom_typing + / "mma_typed.data" + ) + + assert result.nta_file == ( + executor.cache_atom_typing + / "mma_typed.nta" + ) + + assert len(calls) == 1 + + +def test_run_atom_typing_command_for_monomer( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + molecule_file = ( + tmp_path / "styrene.mol" + ) + + molecule_file.write_text( + "", + encoding="utf-8", + ) + + inputs = make_inputs( + [ + make_monomer( + name="styrene", + molecule_3Dmol_path=molecule_file, + ) + ] + ) + + calls = ( + install_fake_atom_typing_subprocess( + monkeypatch + ) + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + executor.run_atom_typing( + inputs, + [], + "PCFF", + ) + + assert calls[0][ + "command" + ] == [ + sys.executable, + str( + executor.atom_typing_py + ), + "-topo", + str(molecule_file), + "-dir", + str( + executor.cache_atom_typing + ), + "-ff", + "PCFF", + "-del-method", + "mass", + "-del-crit", + "0", + ] + + assert ( + calls[0]["check"] + is True + ) + + +def test_run_atom_typing_skips_inactive_monomer( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + calls = [] + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + calls.append( + args + ), + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + inputs = make_inputs( + [ + make_monomer( + name="inactive", + molecule_3Dmol_path=None, + status=False, + ) + ] + ) + + results = executor.run_atom_typing( + inputs, + [], + "PCFF", + ) + + assert results == [] + assert calls == [] + + +def test_run_atom_typing_missing_active_monomer_3d_path_raises( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + pytest.fail( + "subprocess must not run" + ), + ) + + inputs = make_inputs( + [ + make_monomer( + name="mma", + molecule_3Dmol_path=None, + status=True, + ) + ] + ) + + with pytest.raises( + ValueError, + match="missing molecule_3Dmol_path", + ): + executor.run_atom_typing( + inputs, + [], + "PCFF", + ) + + +def test_run_atom_typing_status_missing_defaults_active( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + molecule_file = ( + tmp_path / "mma.mol" + ) + + molecule_file.write_text( + "", + encoding="utf-8", + ) + + monomer = SimpleNamespace( + name="mma", + molecule_3Dmol_path=molecule_file, + ) + + inputs = make_inputs( + [ + monomer + ] + ) + + install_fake_atom_typing_subprocess( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + results = executor.run_atom_typing( + inputs, + [], + "PCFF", + ) + + assert len(results) == 1 + assert results[0].id == "mma" + + +# ============================================================================= +# run_atom_typing - reaction templates +# ============================================================================= + + +def test_run_atom_typing_processes_pre_and_post_templates( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + pre = ( + tmp_path / "reaction_pre.mol" + ) + + post = ( + tmp_path / "reaction_post.mol" + ) + + pre.write_text( + "", + encoding="utf-8", + ) + + post.write_text( + "", + encoding="utf-8", + ) + + reaction = make_reaction( + reaction_id=7, + pre_path=pre, + post_path=post, + ) + + install_fake_atom_typing_subprocess( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + results = executor.run_atom_typing( + make_inputs(), + [ + reaction + ], + "PCFF", + ) + + assert [ + result.id + for result in results + ] == [ + "pre7", + "post7", + ] + + assert all( + result.molecule is False + for result in results + ) + + +def test_run_atom_typing_template_outputs_use_separate_directories( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + pre = ( + tmp_path / "foo_pre.mol" + ) + + post = ( + tmp_path / "foo_post.mol" + ) + + pre.write_text("") + post.write_text("") + + reaction = make_reaction( + reaction_id=3, + pre_path=pre, + post_path=post, + ) + + install_fake_atom_typing_subprocess( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + results = executor.run_atom_typing( + make_inputs(), + [ + reaction + ], + "PCFF", + ) + + assert ( + results[0] + .typed_data_file + == executor.cache_atom_typing + / "pre3" + / "foo_pre_typed.data" + ) + + assert ( + results[1] + .typed_data_file + == executor.cache_atom_typing + / "post3" + / "foo_post_typed.data" + ) + + +def test_run_atom_typing_result_order_is_monomers_then_templates( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + monomer_file = ( + tmp_path / "mma.mol" + ) + + pre = ( + tmp_path / "pre.mol" + ) + + post = ( + tmp_path / "post.mol" + ) + + for path in ( + monomer_file, + pre, + post, + ): + path.write_text("") + + inputs = make_inputs( + [ + make_monomer( + name="mma", + molecule_3Dmol_path=monomer_file, + ) + ] + ) + + reaction = make_reaction( + reaction_id=1, + pre_path=pre, + post_path=post, + ) + + install_fake_atom_typing_subprocess( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + results = executor.run_atom_typing( + inputs, + [ + reaction + ], + "PCFF", + ) + + assert [ + result.id + for result in results + ] == [ + "mma", + "pre1", + "post1", + ] + + +def test_run_atom_typing_sleeps_after_every_executed_item( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + monomer_file = ( + tmp_path / "mma.mol" + ) + + pre = ( + tmp_path / "pre.mol" + ) + + post = ( + tmp_path / "post.mol" + ) + + for path in ( + monomer_file, + pre, + post, + ): + path.write_text("") + + inputs = make_inputs( + [ + make_monomer( + name="mma", + molecule_3Dmol_path=monomer_file, + ) + ] + ) + + reaction = make_reaction( + reaction_id=1, + pre_path=pre, + post_path=post, + ) + + install_fake_atom_typing_subprocess( + monkeypatch + ) + + sleeps = [] + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: + sleeps.append(seconds), + ) + + executor.run_atom_typing( + inputs, + [ + reaction + ], + "PCFF", + ) + + assert sleeps == [ + 0.1, + 0.1, + 0.1, + ] + + +# ============================================================================= +# run_atom_typing - output verification +# ============================================================================= + + +def test_run_atom_typing_missing_expected_output_raises( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + molecule_file = ( + tmp_path / "mma.mol" + ) + + molecule_file.write_text("") + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + SimpleNamespace( + returncode=0 + ), + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + inputs = make_inputs( + [ + make_monomer( + name="mma", + molecule_3Dmol_path=molecule_file, + ) + ] + ) + + with pytest.raises( + FileNotFoundError, + match="Expected LUNAR output not found for mma", + ): + executor.run_atom_typing( + inputs, + [], + "PCFF", + ) + + +def test_run_atom_typing_prints_generated_message( + tmp_path, + monkeypatch, + capsys, +): + executor = make_executor( + tmp_path + ) + + molecule_file = ( + tmp_path / "mma.mol" + ) + + molecule_file.write_text("") + + install_fake_atom_typing_subprocess( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + executor.run_atom_typing( + make_inputs( + [ + make_monomer( + name="mma", + molecule_3Dmol_path=molecule_file, + ) + ] + ), + [], + "PCFF", + ) + + assert ( + "[LUNAR atom_typing] Generated files for mma" + in capsys.readouterr().out + ) + + +def test_run_atom_typing_subprocess_failure_propagates( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + molecule_file = ( + tmp_path / "mma.mol" + ) + + molecule_file.write_text("") + + def fail(*args, **kwargs): + raise subprocess.CalledProcessError( + 1, + "atom_typing", + ) + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + fail, + ) + + with pytest.raises( + subprocess.CalledProcessError + ): + executor.run_atom_typing( + make_inputs( + [ + make_monomer( + name="mma", + molecule_3Dmol_path=molecule_file, + ) + ] + ), + [], + "PCFF", + ) + + +# ============================================================================= +# run_all2lmp +# ============================================================================= + + +def install_fake_all2lmp_subprocess( + executor, + monkeypatch, +): + calls = [] + + def fake_run( + command, + check=False, + **kwargs, + ): + calls.append( + { + "command": list(command), + "check": check, + **kwargs, + } + ) + + topo = Path( + command[ + command.index("-topo") + 1 + ] + ) + + # Executor output naming is derived from the identifier. + # The typed input file stem is e.g. "pre1_typed". + stem = topo.stem + + if stem.endswith( + "_typed" + ): + result_id = stem[ + :-len("_typed") + ] + else: + result_id = stem + + ( + executor.cache_all2lmp + / f"{result_id}_typed_IFF.data" + ).write_text( + "IFF", + encoding="utf-8", + ) + + return SimpleNamespace( + returncode=0 + ) + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + fake_run, + ) + + return calls + + +def test_run_all2lmp_converts_single_result( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + typed = ( + tmp_path / "data1_typed.data" + ) + + nta = ( + tmp_path / "data1_typed.nta" + ) + + typed.write_text("") + nta.write_text("") + + input_result = AtomTypingResult( + id="data1", + molecule=True, + typed_data_file=typed, + nta_file=nta, + ) + + install_fake_all2lmp_subprocess( + executor, + monkeypatch, + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + results = executor.run_all2lmp( + [ + input_result + ], + tmp_path / "pcff.frc", + ) + + assert len(results) == 1 + + assert results[0] == ( + All2LMPResult( + id="data1", + molecule=True, + all2lmp_data_file=Path( + "data1_typed_IFF.data" + ), + ) + ) + + +def test_run_all2lmp_exact_command( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + typed = ( + tmp_path / "pre2_typed.data" + ) + + nta = ( + tmp_path / "pre2_typed.nta" + ) + + typed.write_text("") + nta.write_text("") + + frc = ( + tmp_path / "pcff.frc" + ) + + calls = ( + install_fake_all2lmp_subprocess( + executor, + monkeypatch, + ) + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + executor.run_all2lmp( + [ + AtomTypingResult( + id="pre2", + molecule=False, + typed_data_file=typed, + nta_file=nta, + ) + ], + frc, + ) + + assert calls[0][ + "command" + ] == [ + sys.executable, + str( + executor.all2lmp_py + ), + "-topo", + str(typed), + "-nta", + str(nta), + "-frc", + str(frc), + "-asm", + "T", + "-dir", + str( + executor.cache_all2lmp + ), + ] + + assert ( + calls[0]["check"] + is True + ) + + +def test_run_all2lmp_preserves_id_and_molecule_flag( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + typed = ( + tmp_path / "post9_typed.data" + ) + + nta = ( + tmp_path / "post9_typed.nta" + ) + + typed.write_text("") + nta.write_text("") + + install_fake_all2lmp_subprocess( + executor, + monkeypatch, + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + result = executor.run_all2lmp( + [ + AtomTypingResult( + id="post9", + molecule=False, + typed_data_file=typed, + nta_file=nta, + ) + ], + tmp_path / "pcff.frc", + )[0] + + assert result.id == "post9" + assert result.molecule is False + + +def test_run_all2lmp_processes_results_in_input_order( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + entries = [] + + for identifier, molecule in [ + ("data1", True), + ("pre1", False), + ("post1", False), + ]: + typed = ( + tmp_path + / f"{identifier}_typed.data" + ) + + nta = ( + tmp_path + / f"{identifier}_typed.nta" + ) + + typed.write_text("") + nta.write_text("") + + entries.append( + AtomTypingResult( + id=identifier, + molecule=molecule, + typed_data_file=typed, + nta_file=nta, + ) + ) + + install_fake_all2lmp_subprocess( + executor, + monkeypatch, + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + results = executor.run_all2lmp( + entries, + tmp_path / "pcff.frc", + ) + + assert [ + result.id + for result in results + ] == [ + "data1", + "pre1", + "post1", + ] + + +def test_run_all2lmp_sleeps_once_after_all_commands( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + typed = ( + tmp_path / "data1_typed.data" + ) + + nta = ( + tmp_path / "data1_typed.nta" + ) + + typed.write_text("") + nta.write_text("") + + install_fake_all2lmp_subprocess( + executor, + monkeypatch, + ) + + sleeps = [] + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: + sleeps.append(seconds), + ) + + executor.run_all2lmp( + [ + AtomTypingResult( + id="data1", + molecule=True, + typed_data_file=typed, + nta_file=nta, + ) + ], + tmp_path / "pcff.frc", + ) + + assert sleeps == [ + 0.1 + ] + + +def test_run_all2lmp_empty_input_still_sleeps_once( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + sleeps = [] + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: + sleeps.append(seconds), + ) + + results = executor.run_all2lmp( + [], + tmp_path / "pcff.frc", + ) + + assert results == [] + + assert sleeps == [ + 0.1 + ] + + +def test_run_all2lmp_missing_output_raises( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + typed = ( + tmp_path / "data1_typed.data" + ) + + nta = ( + tmp_path / "data1_typed.nta" + ) + + typed.write_text("") + nta.write_text("") + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + SimpleNamespace( + returncode=0 + ), + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + with pytest.raises( + FileNotFoundError, + match="Expected output file not found", + ): + executor.run_all2lmp( + [ + AtomTypingResult( + id="data1", + molecule=True, + typed_data_file=typed, + nta_file=nta, + ) + ], + tmp_path / "pcff.frc", + ) + + +def test_run_all2lmp_prints_generated_message( + tmp_path, + monkeypatch, + capsys, +): + executor = make_executor( + tmp_path + ) + + typed = ( + tmp_path / "data1_typed.data" + ) + + nta = ( + tmp_path / "data1_typed.nta" + ) + + typed.write_text("") + nta.write_text("") + + install_fake_all2lmp_subprocess( + executor, + monkeypatch, + ) + + monkeypatch.setattr( + lunar_executor.time, + "sleep", + lambda seconds: None, + ) + + executor.run_all2lmp( + [ + AtomTypingResult( + id="data1", + molecule=True, + typed_data_file=typed, + nta_file=nta, + ) + ], + tmp_path / "pcff.frc", + ) + + assert ( + "[LUNAR all2lmp] Generated file for data1" + in capsys.readouterr().out + ) + + +# ============================================================================= +# run_bond_react_merge - subprocess +# ============================================================================= + + +def test_run_bond_react_merge_exact_command( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + executor.cache_bond_react_merge + / "merge_input.txt" + ) + + merge_input.write_text("") + + calls = [] + + def fake_run( + command, + **kwargs, + ): + calls.append( + ( + list(command), + kwargs, + ) + ) + + return SimpleNamespace( + returncode=0 + ) + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + fake_run, + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda src, dst: None, + ) + + install_fake_ff_structures( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: None, + ) + + executor.run_bond_react_merge( + merge_input, + [], + ) + + command, kwargs = calls[0] + + assert command == [ + sys.executable, + str( + executor.bond_react_merge_py + ), + "-files", + "infile:merge_input.txt", + "-atomstyle", + "full", + "-tl", + "T", + "-wrd", + "F", + "-map", + "F", + ] + + assert kwargs[ + "cwd" + ] == str( + executor.cache_bond_react_merge + ) + + assert ( + kwargs["check"] + is True + ) + + +def test_run_bond_react_merge_sets_qt_offscreen_environment( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + executor.cache_bond_react_merge + / "merge_input.txt" + ) + + merge_input.write_text("") + + captured_env = [] + + def fake_run( + command, + **kwargs, + ): + captured_env.append( + kwargs["env"] + ) + + return SimpleNamespace( + returncode=0 + ) + + monkeypatch.setenv( + "AUTOREACTER_TEST_ENV", + "preserved", + ) + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + fake_run, + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda src, dst: None, + ) + + install_fake_ff_structures( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: None, + ) + + executor.run_bond_react_merge( + merge_input, + [], + ) + + env = captured_env[0] + + assert ( + env["QT_QPA_PLATFORM"] + == "offscreen" + ) + + assert ( + env["AUTOREACTER_TEST_ENV"] + == "preserved" + ) + + +def test_run_bond_react_merge_subprocess_failure_propagates( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + tmp_path / "merge_input.txt" + ) + + merge_input.write_text("") + + def fail(*args, **kwargs): + raise subprocess.CalledProcessError( + 1, + "bond_react_merge", + ) + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + fail, + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda *args: + pytest.fail( + "outputs must not move after subprocess failure" + ), + ) + + with pytest.raises( + subprocess.CalledProcessError + ): + executor.run_bond_react_merge( + merge_input, + [], + ) + + +# ============================================================================= +# run_bond_react_merge - moving outputs +# ============================================================================= + + +def test_run_bond_react_merge_moves_all2lmp_outputs_after_execution( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + tmp_path / "merge_input.txt" + ) + + merge_input.write_text("") + + order = [] + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + ( + order.append( + "subprocess" + ) + or SimpleNamespace( + returncode=0 + ) + ), + ) + + def fake_move( + src, + dst, + ): + order.append( + "move" + ) + + assert src == ( + executor.cache_all2lmp + ) + + assert dst == ( + executor + .cache_bond_react_merge + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + fake_move, + ) + + install_fake_ff_structures( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: + order.append( + "validate" + ), + ) + + executor.run_bond_react_merge( + merge_input, + [], + ) + + assert order == [ + "subprocess", + "move", + "validate", + ] + + +# ============================================================================= +# run_bond_react_merge - resulting FFFiles +# ============================================================================= + + +def test_run_bond_react_merge_builds_molecule_files( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + tmp_path / "merge_input.txt" + ) + + merge_input.write_text("") + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + SimpleNamespace( + returncode=0 + ), + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda src, dst: None, + ) + + install_fake_ff_structures( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: None, + ) + + result = ( + executor.run_bond_react_merge( + merge_input, + [ + All2LMPResult( + id="mma", + molecule=True, + all2lmp_data_file=Path( + "mma_typed_IFF.data" + ), + ) + ], + ) + ) + + assert len( + result.molecule_files + ) == 1 + + molecule_file = ( + result.molecule_files[0] + ) + + assert molecule_file.id == "mma" + + assert ( + molecule_file + .molecule_files + .data_file + == executor.cache_bond_react_merge + / "mma_typed_IFF_merged.data" + ) + + assert ( + molecule_file + .molecule_files + .lmp_molecule_file + == executor.cache_bond_react_merge + / "mma_typed_IFF_merged.lmpmol" + ) + + +def test_run_bond_react_merge_builds_template_from_pre_result( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + tmp_path / "merge_input.txt" + ) + + merge_input.write_text("") + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + SimpleNamespace( + returncode=0 + ), + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda src, dst: None, + ) + + install_fake_ff_structures( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: None, + ) + + results = [ + All2LMPResult( + id="pre12", + molecule=False, + all2lmp_data_file=Path( + "pre12_typed_IFF.data" + ), + ), + All2LMPResult( + id="post12", + molecule=False, + all2lmp_data_file=Path( + "post12_typed_IFF.data" + ), + ), + ] + + result = ( + executor.run_bond_react_merge( + merge_input, + results, + ) + ) + + assert len( + result.template_files + ) == 1 + + template = ( + result.template_files[0] + ) + + assert ( + template.reaction_id + == 12 + ) + + assert ( + template + .pre_reaction_file + .data_file + == executor.cache_bond_react_merge + / "pre12_typed_IFF_merged.data" + ) + + assert ( + template + .post_reaction_file + .data_file + == executor.cache_bond_react_merge + / "post12_typed_IFF_merged.data" + ) + + +def test_run_bond_react_merge_post_result_does_not_create_second_template( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + tmp_path / "merge_input.txt" + ) + + merge_input.write_text("") + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + SimpleNamespace( + returncode=0 + ), + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda src, dst: None, + ) + + install_fake_ff_structures( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: None, + ) + + result = executor.run_bond_react_merge( + merge_input, + [ + All2LMPResult( + id="pre1", + molecule=False, + all2lmp_data_file=Path( + "pre1_typed_IFF.data" + ), + ), + All2LMPResult( + id="post1", + molecule=False, + all2lmp_data_file=Path( + "post1_typed_IFF.data" + ), + ), + ], + ) + + assert len( + result.template_files + ) == 1 + + +def test_run_bond_react_merge_sets_force_field_and_input_files( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + tmp_path / "merge_input.txt" + ) + + merge_input.write_text("") + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + SimpleNamespace( + returncode=0 + ), + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda src, dst: None, + ) + + install_fake_ff_structures( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: None, + ) + + result = ( + executor.run_bond_react_merge( + merge_input, + [], + ) + ) + + assert ( + result.force_field_data + == executor.cache_bond_react_merge + / "force_field.data" + ) + + # Characterizes current implementation: + # in.create_atoms.script remains referenced in all2lmp cache. + assert ( + result.in_file + == executor.cache_all2lmp + / "in.create_atoms.script" + ) + + +def test_run_bond_react_merge_validates_final_files( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + tmp_path / "merge_input.txt" + ) + + merge_input.write_text("") + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + SimpleNamespace( + returncode=0 + ), + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda src, dst: None, + ) + + install_fake_ff_structures( + monkeypatch + ) + + validated = [] + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: + validated.append(files), + ) + + result = ( + executor.run_bond_react_merge( + merge_input, + [], + ) + ) + + assert validated == [ + result + ] + + +def test_run_bond_react_merge_returns_fffiles( + tmp_path, + monkeypatch, +): + executor = make_executor( + tmp_path + ) + + merge_input = ( + tmp_path / "merge_input.txt" + ) + + merge_input.write_text("") + + monkeypatch.setattr( + lunar_executor.subprocess, + "run", + lambda *args, **kwargs: + SimpleNamespace( + returncode=0 + ), + ) + + monkeypatch.setattr( + lunar_executor, + "move_merge_outputs", + lambda src, dst: None, + ) + + install_fake_ff_structures( + monkeypatch + ) + + monkeypatch.setattr( + lunar_executor, + "FFValidator", + lambda files: None, + ) + + result = ( + executor.run_bond_react_merge( + merge_input, + [], + ) + ) + + assert isinstance( + result, + FakeFFFiles, + ) \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_merge_builder.py b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_merge_builder.py new file mode 100644 index 00000000..4d8bdc42 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/lunar_client/test_merge_builder.py @@ -0,0 +1,1140 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.merge_builder as merge_builder +from AutoREACTER.reaction_preparation.ff_wrapper.lunar_client.merge_builder import ( + write_bond_react_merge_input, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_result( + *, + result_id, + molecule, + filename, +): + return SimpleNamespace( + id=result_id, + molecule=molecule, + all2lmp_data_file=filename, + ) + + +# ============================================================================= +# Basic file creation +# ============================================================================= + + +def test_write_merge_input_creates_output_directory( + tmp_path, +): + output_dir = ( + tmp_path + / "nested" + / "bond_react_merge" + ) + + all2lmp_dir = ( + tmp_path / "all2lmp" + ) + + result = ( + write_bond_react_merge_input( + output_dir, + all2lmp_dir, + [], + ) + ) + + assert output_dir.is_dir() + + assert result == ( + output_dir + / "merge_input.txt" + ) + + assert result.is_file() + + +def test_write_merge_input_returns_path_object( + tmp_path, +): + result = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + [], + ) + ) + + assert isinstance( + result, + Path, + ) + + +def test_write_merge_input_empty_results_still_writes_header( + tmp_path, +): + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + [], + ) + ) + + text = merge_file.read_text() + + assert ( + '# anything following the "#" character will be ignored' + in text + ) + + assert "# file-tag" in text + + assert "filename" in text + + assert ( + "comment (required)" + in text + ) + + +def test_write_merge_input_writes_parent_directory_comment( + tmp_path, +): + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + [], + ) + ) + + text = merge_file.read_text() + + assert ( + "Specify the parent_directory" + in text + ) + + +# ============================================================================= +# Molecule/data entries +# ============================================================================= + + +def test_single_molecule_is_tagged_data1( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + result = make_result( + result_id="monomer1", + molecule=True, + filename="monomer.data", + ) + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + [ + result, + ], + ) + ) + + text = merge_file.read_text() + + assert "data1" in text + assert "monomer.data" in text + + assert ( + "# This datafile will have all coeffs in it" + in text + ) + + +def test_multiple_molecules_are_numbered_sequentially( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="monomer_a", + molecule=True, + filename="a.data", + ), + make_result( + result_id="monomer_b", + molecule=True, + filename="b.data", + ), + make_result( + result_id="monomer_c", + molecule=True, + filename="c.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert "data1" in text + assert "data2" in text + assert "data3" in text + + assert ( + text.index("data1") + < text.index("data2") + < text.index("data3") + ) + + +def test_molecule_path_uses_all2lmp_cache_directory( + tmp_path, + monkeypatch, +): + captured = [] + + def fake_normalize(path): + captured.append( + Path(path) + ) + + return str(path) + + monkeypatch.setattr( + merge_builder, + "normalize_path", + fake_normalize, + ) + + all2lmp_dir = ( + tmp_path / "all2lmp" + ) + + result = make_result( + result_id="molecule1", + molecule=True, + filename="sample.data", + ) + + write_bond_react_merge_input( + tmp_path / "merge", + all2lmp_dir, + [ + result, + ], + ) + + assert captured == [ + all2lmp_dir + / "sample.data" + ] + + +def test_only_molecule_true_results_become_data_entries( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="monomer1", + molecule=True, + filename="monomer.data", + ), + make_result( + result_id="reaction_without_valid_suffix", + molecule=False, + filename="reaction.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert "data1" in text + assert "monomer.data" in text + + assert "data2" not in text + + +# ============================================================================= +# Reaction pair handling +# ============================================================================= + + +def test_single_pre_post_pair_is_written( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="pre1", + molecule=False, + filename="pre1.data", + ), + make_result( + result_id="post1", + molecule=False, + filename="post1.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert "pre1" in text + assert "post1" in text + + assert "pre1.data" in text + assert "post1.data" in text + + assert "# for rxn1" in text + + +def test_reaction_pairs_are_sorted_by_reaction_id( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="pre10", + molecule=False, + filename="pre10.data", + ), + make_result( + result_id="post10", + molecule=False, + filename="post10.data", + ), + make_result( + result_id="pre2", + molecule=False, + filename="pre2.data", + ), + make_result( + result_id="post2", + molecule=False, + filename="post2.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + # Reaction IDs are sorted numerically: + # original ID 2 becomes output rxn1, + # original ID 10 becomes output rxn2. + assert ( + text.index("pre2.data") + < text.index("pre10.data") + ) + + lines = text.splitlines() + + pre2_line = next( + line + for line in lines + if "pre2.data" in line + ) + + pre10_line = next( + line + for line in lines + if "pre10.data" in line + ) + + assert pre2_line.startswith( + "pre1" + ) + + assert pre10_line.startswith( + "pre2" + ) + + +def test_reaction_output_numbering_is_contiguous( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="pre5", + molecule=False, + filename="pre5.data", + ), + make_result( + result_id="post5", + molecule=False, + filename="post5.data", + ), + make_result( + result_id="pre99", + molecule=False, + filename="pre99.data", + ), + make_result( + result_id="post99", + molecule=False, + filename="post99.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + lines = merge_file.read_text().splitlines() + + pre_lines = [ + line + for line in lines + if line.startswith("pre") + ] + + post_lines = [ + line + for line in lines + if line.startswith("post") + ] + + assert pre_lines[0].startswith( + "pre1" + ) + + assert pre_lines[1].startswith( + "pre2" + ) + + assert post_lines[0].startswith( + "post1" + ) + + assert post_lines[1].startswith( + "post2" + ) + + +def test_pre_post_input_order_does_not_matter( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="post7", + molecule=False, + filename="post7.data", + ), + make_result( + result_id="pre7", + molecule=False, + filename="pre7.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert "pre7.data" in text + assert "post7.data" in text + + +def test_missing_post_reaction_raises( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="pre4", + molecule=False, + filename="pre4.data", + ) + ] + + with pytest.raises( + ValueError, + match="Incomplete reaction pair for reaction ID 4", + ): + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + + +def test_missing_pre_reaction_raises( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="post4", + molecule=False, + filename="post4.data", + ) + ] + + with pytest.raises( + ValueError, + match="Incomplete reaction pair for reaction ID 4", + ): + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + + +def test_nonmolecule_without_trailing_integer_is_ignored( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="reaction", + molecule=False, + filename="ignored.data", + ) + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert "ignored.data" not in text + assert "pre1" not in text + assert "post1" not in text + + +def test_nonmolecule_with_integer_but_unknown_prefix_is_grouped_then_fails( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="reaction5", + molecule=False, + filename="reaction5.data", + ) + ] + + # Current behavior: + # reaction5 creates reaction_pairs[5], but does not populate + # either pre or post, so the pair is incomplete. + with pytest.raises( + ValueError, + match="Incomplete reaction pair for reaction ID 5", + ): + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + + +# ============================================================================= +# Duplicate IDs / current overwrite semantics +# ============================================================================= + + +def test_later_pre_entry_with_same_reaction_id_replaces_earlier_one( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="pre1", + molecule=False, + filename="old_pre.data", + ), + make_result( + result_id="pre1", + molecule=False, + filename="new_pre.data", + ), + make_result( + result_id="post1", + molecule=False, + filename="post.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert "new_pre.data" in text + assert "old_pre.data" not in text + + +def test_later_post_entry_with_same_reaction_id_replaces_earlier_one( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="pre1", + molecule=False, + filename="pre.data", + ), + make_result( + result_id="post1", + molecule=False, + filename="old_post.data", + ), + make_result( + result_id="post1", + molecule=False, + filename="new_post.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert "new_post.data" in text + assert "old_post.data" not in text + + +# ============================================================================= +# Mixed molecule / reaction output +# ============================================================================= + + +def test_molecules_are_written_before_reactions( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="pre1", + molecule=False, + filename="pre.data", + ), + make_result( + result_id="monomer", + molecule=True, + filename="monomer.data", + ), + make_result( + result_id="post1", + molecule=False, + filename="post.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert ( + text.index("monomer.data") + < text.index("pre.data") + ) + + assert ( + text.index("pre.data") + < text.index("post.data") + ) + + +def test_data_and_reaction_numbering_are_independent( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + results = [ + make_result( + result_id="monomer1", + molecule=True, + filename="m1.data", + ), + make_result( + result_id="monomer2", + molecule=True, + filename="m2.data", + ), + make_result( + result_id="pre50", + molecule=False, + filename="pre50.data", + ), + make_result( + result_id="post50", + molecule=False, + filename="post50.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + lines = merge_file.read_text().splitlines() + + assert any( + line.startswith("data1") + and "m1.data" in line + for line in lines + ) + + assert any( + line.startswith("data2") + and "m2.data" in line + for line in lines + ) + + assert any( + line.startswith("pre1") + and "pre50.data" in line + for line in lines + ) + + assert any( + line.startswith("post1") + and "post50.data" in line + for line in lines + ) + + +# ============================================================================= +# normalize_path integration boundary +# ============================================================================= + + +def test_normalize_path_called_for_every_written_input_file( + tmp_path, + monkeypatch, +): + calls = [] + + def fake_normalize(path): + calls.append( + Path(path) + ) + + return f"NORMALIZED:{path}" + + monkeypatch.setattr( + merge_builder, + "normalize_path", + fake_normalize, + ) + + all2lmp_dir = ( + tmp_path / "all2lmp" + ) + + results = [ + make_result( + result_id="monomer", + molecule=True, + filename="molecule.data", + ), + make_result( + result_id="pre3", + molecule=False, + filename="pre.data", + ), + make_result( + result_id="post3", + molecule=False, + filename="post.data", + ), + ] + + write_bond_react_merge_input( + tmp_path / "merge", + all2lmp_dir, + results, + ) + + assert calls == [ + all2lmp_dir + / "molecule.data", + all2lmp_dir + / "pre.data", + all2lmp_dir + / "post.data", + ] + + +def test_normalized_paths_are_used_in_output( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: ( + f"/normalized/{Path(path).name}" + ), + ) + + results = [ + make_result( + result_id="monomer", + molecule=True, + filename="molecule.data", + ), + make_result( + result_id="pre1", + molecule=False, + filename="pre.data", + ), + make_result( + result_id="post1", + molecule=False, + filename="post.data", + ), + ] + + merge_file = ( + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + ) + + text = merge_file.read_text() + + assert ( + "/normalized/molecule.data" + in text + ) + + assert ( + "/normalized/pre.data" + in text + ) + + assert ( + "/normalized/post.data" + in text + ) + + +# ============================================================================= +# get_ending_integer integration boundary +# ============================================================================= + + +def test_get_ending_integer_called_for_nonmolecule_results_only( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + calls = [] + + def fake_get_ending_integer(value): + calls.append(value) + + if value == "preX": + return 1 + + if value == "postX": + return 1 + + return None + + monkeypatch.setattr( + merge_builder, + "get_ending_integer", + fake_get_ending_integer, + ) + + results = [ + make_result( + result_id="moleculeX", + molecule=True, + filename="molecule.data", + ), + make_result( + result_id="preX", + molecule=False, + filename="pre.data", + ), + make_result( + result_id="postX", + molecule=False, + filename="post.data", + ), + ] + + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + + assert calls == [ + "preX", + "postX", + ] + + +# ============================================================================= +# Input immutability +# ============================================================================= + + +def test_function_does_not_mutate_results_list( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + first = make_result( + result_id="pre1", + molecule=False, + filename="pre.data", + ) + + second = make_result( + result_id="post1", + molecule=False, + filename="post.data", + ) + + results = [ + first, + second, + ] + + original = list( + results + ) + + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + results, + ) + + assert results == original + + assert results[0] is first + assert results[1] is second + + +def test_function_does_not_modify_result_objects( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + merge_builder, + "normalize_path", + lambda path: str(path), + ) + + pre = make_result( + result_id="pre1", + molecule=False, + filename="pre.data", + ) + + post = make_result( + result_id="post1", + molecule=False, + filename="post.data", + ) + + write_bond_react_merge_input( + tmp_path / "merge", + tmp_path / "all2lmp", + [ + pre, + post, + ], + ) + + assert pre.id == "pre1" + assert pre.molecule is False + assert ( + pre.all2lmp_data_file + == "pre.data" + ) + + assert post.id == "post1" + assert post.molecule is False + assert ( + post.all2lmp_data_file + == "post.data" + ) \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/test_REACTER_files_builder.py b/tests/unit/reaction_preparation/ff_wrapper/test_REACTER_files_builder.py new file mode 100644 index 00000000..6cc19332 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/test_REACTER_files_builder.py @@ -0,0 +1,3765 @@ +from pathlib import Path +from types import SimpleNamespace + +import pandas as pd +import pytest + +import AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder as builder_module +from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import ( + REACTERFiles, + REACTERFilesBuilder, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_monomer( + *, + monomer_id=1, + data_id="data1", + name="mma", + lmp_molecule_file=None, +): + return SimpleNamespace( + id=monomer_id, + data_id=data_id, + name=name, + lmp_molecule_file=lmp_molecule_file, + ) + + +def make_reaction_metadata( + *, + reaction_id=1, + activity_stats=True, + dataframe=None, + delete_atom=False, +): + if dataframe is None: + dataframe = pd.DataFrame() + + return SimpleNamespace( + reaction_id=reaction_id, + activity_stats=activity_stats, + reaction_dataframe=dataframe, + delete_atom=delete_atom, + map_file=None, + map_file_with_delete_ids=None, + pre_reaction_file=None, + post_reaction_file=None, + ) + + +def make_session( + tmp_path, + *, + force_field="PCFF", + wildcards=False, + deduplicate=True, + monomers=None, + reactions=None, +): + inputs = SimpleNamespace( + force_field=force_field, + wildcards=wildcards, + deduplicate_reaction_templates=deduplicate, + monomers=list( + monomers or [] + ), + ) + + return SimpleNamespace( + inputs=inputs, + reaction_metadata=list( + reactions or [] + ), + staging_dir=tmp_path / "staging", + output_dir=tmp_path / "output", + ff_files=None, + reacter_files=None, + ) + + +def make_builder( + tmp_path, + **kwargs, +): + session = make_session( + tmp_path, + **kwargs, + ) + + return ( + REACTERFilesBuilder( + session + ), + session, + ) + + +def make_data_files( + *, + data_file, + molecule_file, +): + return SimpleNamespace( + data_file=Path( + data_file + ), + lmp_molecule_file=Path( + molecule_file + ), + ) + + +def make_template_ff_entry( + *, + reaction_id, + pre_file, + post_file, +): + return SimpleNamespace( + reaction_id=reaction_id, + pre_reaction_file=make_data_files( + data_file=Path( + str(pre_file) + ".data" + ), + molecule_file=pre_file, + ), + post_reaction_file=make_data_files( + data_file=Path( + str(post_file) + ".data" + ), + molecule_file=post_file, + ), + ) + + +# ============================================================================= +# REACTERFiles +# ============================================================================= + + +def test_reacter_files_stores_values( + tmp_path, +): + result = REACTERFiles( + force_field_data=( + tmp_path / "force_field.data" + ), + in_file=( + tmp_path / "in.script" + ), + molecule_files=[ + "molecule" + ], + template_files=[ + "template" + ], + ) + + assert result.force_field_data == ( + tmp_path / "force_field.data" + ) + + assert result.in_file == ( + tmp_path / "in.script" + ) + + assert result.molecule_files == [ + "molecule" + ] + + assert result.template_files == [ + "template" + ] + + +def test_reacter_files_uses_slots( + tmp_path, +): + result = REACTERFiles( + force_field_data=( + tmp_path / "ff.data" + ), + in_file=( + tmp_path / "in.script" + ), + molecule_files=[], + template_files=[], + ) + + with pytest.raises( + AttributeError + ): + result.extra = 1 + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_session( + tmp_path, +): + builder, session = ( + make_builder( + tmp_path + ) + ) + + assert ( + builder.session + is session + ) + + +def test_constructor_creates_reacter_cache( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + assert builder.cache_dir == ( + tmp_path + / "staging" + / "lunar" + / "REACTER_files" + ) + + assert ( + builder.cache_dir.is_dir() + ) + + +def test_constructor_reads_force_field_options( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path, + force_field="CVFF", + wildcards=True, + deduplicate=False, + ) + ) + + assert ( + builder.force_field + == "CVFF" + ) + + assert ( + builder.wildcards + is True + ) + + assert ( + builder + .deduplicate_reaction_templates + is False + ) + + +# ============================================================================= +# _get_ending_integer +# ============================================================================= + + +@pytest.mark.parametrize( + "value, expected", + [ + ( + "pre1", + 1, + ), + ( + "post27", + 27, + ), + ( + "data003", + 3, + ), + ( + "RXN_99", + 99, + ), + ( + "1.5", + 5, + ), + ], +) +def test_get_ending_integer( + tmp_path, + value, + expected, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + assert ( + builder._get_ending_integer( + value + ) + == expected + ) + + +@pytest.mark.parametrize( + "value", + [ + "", + "pre", + "post_", + "123abc", + "reaction_test", + ], +) +def test_get_ending_integer_none( + tmp_path, + value, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + assert ( + builder._get_ending_integer( + value + ) + is None + ) + + +# ============================================================================= +# _ensure_dir +# ============================================================================= + + +def test_ensure_dir_creates_directory( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + target = ( + tmp_path + / "nested" + / "directory" + ) + + result = builder._ensure_dir( + str(target) + ) + + assert result == str( + target + ) + + assert target.is_dir() + + +def test_ensure_dir_existing_directory_is_ok( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + target = ( + tmp_path / "existing" + ) + + target.mkdir() + + result = builder._ensure_dir( + str(target) + ) + + assert result == str( + target + ) + + +def test_ensure_dir_blocking_file_raises( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + target = ( + tmp_path / "blocked" + ) + + target.write_text( + "file", + encoding="utf-8", + ) + + with pytest.raises( + FileExistsError, + match="expected dir", + ): + builder._ensure_dir( + str(target) + ) + + +def test_ensure_dir_can_remove_blocking_file( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + target = ( + tmp_path / "blocked" + ) + + target.write_text( + "file", + encoding="utf-8", + ) + + builder._ensure_dir( + str(target), + remove_blocking_file=True, + ) + + assert target.is_dir() + + +# ============================================================================= +# _col_int_list +# ============================================================================= + + +def test_col_int_list_missing_column_returns_empty( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + df = pd.DataFrame( + { + "other": [ + 1, + 2, + ] + } + ) + + assert ( + builder._col_int_list( + "initiators", + df, + ) + == [] + ) + + +def test_col_int_list_empty_column_returns_empty( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + df = pd.DataFrame( + { + "initiators": [ + None, + None, + ] + } + ) + + assert ( + builder._col_int_list( + "initiators", + df, + ) + == [] + ) + + +def test_col_int_list_converts_integer_like_values( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + df = pd.DataFrame( + { + "initiators": [ + 1, + 2.0, + "3", + "4.0", + ] + } + ) + + assert ( + builder._col_int_list( + "initiators", + df, + ) + == [ + 1, + 2, + 3, + 4, + ] + ) + + +def test_col_int_list_removes_duplicates_preserving_order( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + df = pd.DataFrame( + { + "edge_atoms": [ + 5, + 2, + 5, + 3, + 2, + ] + } + ) + + assert ( + builder._col_int_list( + "edge_atoms", + df, + ) + == [ + 5, + 2, + 3, + ] + ) + + +def test_col_int_list_ignores_nan( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + df = pd.DataFrame( + { + "byproduct_idx": [ + 1, + None, + 2, + ] + } + ) + + assert ( + builder._col_int_list( + "byproduct_idx", + df, + ) + == [ + 1, + 2, + ] + ) + + +def test_col_int_list_non_numeric_raises( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + df = pd.DataFrame( + { + "initiators": [ + 1, + "bad", + ] + } + ) + + with pytest.raises( + ValueError, + match="contains non-numeric value", + ): + builder._col_int_list( + "initiators", + df, + ) + + +def test_col_int_list_non_integer_numeric_raises( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + df = pd.DataFrame( + { + "initiators": [ + 1, + 2.5, + ] + } + ) + + with pytest.raises( + ValueError, + match="contains non-integer value", + ): + builder._col_int_list( + "initiators", + df, + ) + + +# ============================================================================= +# _load_molecule_file +# ============================================================================= + + +def test_load_molecule_file_finds_all_sections( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + path = ( + tmp_path / "template.molecule" + ) + + path.write_text( + """Types + +1 1 # c + +Charges + +1 0.0 # c + +Coords + +1 0.0 0.0 0.0 # c + +Bonds + +1 1 1 1 # c c + +Angles + +1 1 1 1 1 # c c c + +Dihedrals + +1 1 1 1 1 1 # c c c c + +Impropers + +1 1 1 1 1 1 # c c c c + +""", + encoding="utf-8", + ) + + result = ( + builder._load_molecule_file( + path + ) + ) + + ( + lines, + type_start, + charge_start, + coord_start, + bond_start, + angle_start, + dihedral_start, + improper_start, + ) = result + + assert type_start == 2 + assert charge_start == 6 + assert coord_start == 10 + assert bond_start == 14 + assert angle_start == 18 + assert dihedral_start == 22 + assert improper_start == 26 + + assert lines[0] == "Types" + + +def test_load_molecule_file_strips_line_whitespace( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + path = ( + tmp_path / "template.molecule" + ) + + path.write_text( + """ Types + + 1 10 # c + +Charges + +1 0.0 # c + +Coords + +1 0 0 0 # c + +""", + encoding="utf-8", + ) + + lines, *_ = ( + builder._load_molecule_file( + path + ) + ) + + assert lines[0] == "Types" + assert lines[2] == "1 10 # c" + + +def test_load_molecule_file_requires_types( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + path = ( + tmp_path / "bad.molecule" + ) + + path.write_text( + """Charges + +1 0 # c + +Coords + +1 0 0 0 # c +""", + encoding="utf-8", + ) + + with pytest.raises( + ValueError, + match="Essential sections", + ): + builder._load_molecule_file( + path + ) + + +def test_load_molecule_file_requires_charges( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + path = ( + tmp_path / "bad.molecule" + ) + + path.write_text( + """Types + +1 1 # c + +Coords + +1 0 0 0 # c +""", + encoding="utf-8", + ) + + with pytest.raises( + ValueError, + match="Essential sections", + ): + builder._load_molecule_file( + path + ) + + +def test_load_molecule_file_requires_coords( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + path = ( + tmp_path / "bad.molecule" + ) + + path.write_text( + """Types + +1 1 # c + +Charges + +1 0 # c +""", + encoding="utf-8", + ) + + with pytest.raises( + ValueError, + match="Essential sections", + ): + builder._load_molecule_file( + path + ) + + +def test_load_molecule_file_missing_optional_topology_sections_returns_none( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + path = ( + tmp_path / "minimal.molecule" + ) + + path.write_text( + """Types + +1 1 # c + +Charges + +1 0 # c + +Coords + +1 0 0 0 # c + +""", + encoding="utf-8", + ) + + result = ( + builder._load_molecule_file( + path + ) + ) + + assert result[4] is None + assert result[5] is None + assert result[6] is None + assert result[7] is None + + +# ============================================================================= +# _molecule_file_format +# ============================================================================= + + +def test_molecule_file_format_contains_counts( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path, + force_field="PCFF", + ) + ) + + text = builder._molecule_file_format( + 5, + 4, + 3, + 2, + 1, + "TYPES\n", + "CHARGES\n", + "COORDS\n", + "BONDS\n", + "ANGLES\n", + "DIHEDRALS\n", + "IMPROPERS\n", + "template_pre_1.molecule", + ) + + assert "5 atoms" in text + assert "4 bonds" in text + assert "3 angles" in text + assert "2 dihedrals" in text + assert "1 impropers" in text + + +def test_molecule_file_format_contains_force_field_and_filename( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path, + force_field="PCFF", + ) + ) + + text = builder._molecule_file_format( + 1, + 0, + 0, + 0, + 0, + "", + "", + "", + "", + "", + "", + "", + "template_pre_7.molecule", + ) + + assert ( + "template_pre_7.molecule" + in text + ) + + assert ( + "PCFF forcefield" + in text + ) + + +def test_molecule_file_format_section_order( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + text = builder._molecule_file_format( + 1, + 1, + 1, + 1, + 1, + "TYPE_DATA\n", + "CHARGE_DATA\n", + "COORD_DATA\n", + "BOND_DATA\n", + "ANGLE_DATA\n", + "DIHEDRAL_DATA\n", + "IMPROPER_DATA\n", + "test.molecule", + ) + + assert ( + text.index("Types") + < text.index("Charges") + < text.index("Coords") + < text.index("Bonds") + < text.index("Angles") + < text.index("Dihedrals") + < text.index("Impropers") + ) + + +# ============================================================================= +# _molecule_file_preparation +# ============================================================================= + + +def test_molecule_file_preparation_calls_modifier_pipeline( + tmp_path, + monkeypatch, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + fake_df = pd.DataFrame( + { + "atom_index": [ + 1, + 2, + ], + "new_atom_index": [ + 1, + 2, + ], + } + ) + + monkeypatch.setattr( + builder, + "_load_molecule_file", + lambda path: ( + ["fake-lines"], + 1, + 2, + 3, + 4, + 5, + 6, + 7, + ), + ) + + events = [] + + def fake_types( + lines, + indexes, + start, + ): + events.append( + ( + "types", + indexes, + start, + ) + ) + + return ( + fake_df, + "TYPES\n", + 2, + { + 10: 1, + 20: 2, + }, + False, + ) + + monkeypatch.setattr( + builder_module, + "modify_types", + fake_types, + ) + + monkeypatch.setattr( + builder_module, + "modify_charges", + lambda lines, df, start: + ( + events.append( + ( + "charges", + start, + ) + ) + or "CHARGES\n" + ), + ) + + monkeypatch.setattr( + builder_module, + "modify_coords", + lambda lines, df, start: + ( + events.append( + ( + "coords", + start, + ) + ) + or "COORDS\n" + ), + ) + + monkeypatch.setattr( + builder_module, + "modify_bonds", + lambda lines, df, start, legacy_mode: + ( + events.append( + ( + "bonds", + start, + legacy_mode, + ) + ) + or ( + "BONDS\n", + 1, + ) + ), + ) + + monkeypatch.setattr( + builder_module, + "modify_angles", + lambda lines, df, start, legacy_mode: + ( + events.append( + ( + "angles", + start, + legacy_mode, + ) + ) + or ( + "ANGLES\n", + 2, + ) + ), + ) + + monkeypatch.setattr( + builder_module, + "modify_dihedrals", + lambda lines, df, start, legacy_mode: + ( + events.append( + ( + "dihedrals", + start, + legacy_mode, + ) + ) + or ( + "DIHEDRALS\n", + 3, + ) + ), + ) + + monkeypatch.setattr( + builder_module, + "modify_impropers", + lambda lines, df, start, legacy_mode: + ( + events.append( + ( + "impropers", + start, + legacy_mode, + ) + ) + or ( + "IMPROPERS\n", + 4, + ) + ), + ) + + monkeypatch.setattr( + builder, + "_molecule_file_format", + lambda *args: + "FINAL-MOLECULE", + ) + + result, mapping = ( + builder + ._molecule_file_preparation( + tmp_path / "input.molecule", + [ + 10, + 20, + ], + "template_pre_1.molecule", + ) + ) + + assert result == ( + "FINAL-MOLECULE" + ) + + assert mapping == { + 10: 1, + 20: 2, + } + + assert events == [ + ( + "types", + [ + 10, + 20, + ], + 1, + ), + ( + "charges", + 2, + ), + ( + "coords", + 3, + ), + ( + "bonds", + 4, + False, + ), + ( + "angles", + 5, + False, + ), + ( + "dihedrals", + 6, + False, + ), + ( + "impropers", + 7, + False, + ), + ] + + +# ============================================================================= +# _map_file_write +# ============================================================================= + + +def test_map_file_requires_exactly_two_initiators( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + with pytest.raises( + ValueError, + match="Expected exactly 2 initiator atoms", + ): + builder._map_file_write( + reactant_to_product={ + 0: 0, + }, + initiator_atoms=[ + 0, + ], + edge_atoms=[], + delete_ids=[], + file_name="RXN_1.map", + ) + + +def test_standard_map_has_no_delete_ids_section( + tmp_path, +): + """ + Important AutoREACTER contract: + + The normal RXN_N.map is the standard map and does NOT contain DeleteIDs. + Delete IDs belong only in the optional supplementary map. + """ + builder, _ = ( + make_builder( + tmp_path + ) + ) + + text = builder._map_file_write( + reactant_to_product={ + 0: 1, + 1: 0, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[ + 2, + ], + delete_ids=[], + file_name="RXN_1.map", + ) + + assert "deleteIDs" not in text + assert "\nDeleteIDs\n" not in text + + +def test_map_file_with_delete_ids_contains_optional_section( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + text = builder._map_file_write( + reactant_to_product={ + 0: 0, + 1: 1, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[ + 3, + 2, + ], + file_name=( + "RXN_1_with_delete_ids.map" + ), + ) + + assert "2 deleteIDs" in text + + assert ( + "\nDeleteIDs\n\n" + in text + ) + + # Written as 1-based and sorted. + delete_block = ( + text.split( + "DeleteIDs\n\n", + 1, + )[1] + ) + + assert delete_block.splitlines() == [ + "3", + "4", + ] + + +def test_map_file_uses_one_based_indices( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + text = builder._map_file_write( + reactant_to_product={ + 0: 2, + 4: 1, + }, + initiator_atoms=[ + 0, + 4, + ], + edge_atoms=[ + 3, + ], + delete_ids=[], + file_name="RXN_5.map", + ) + + assert ( + "\nInitiatorIDs\n\n1\n5\n" + in text + ) + + assert ( + "\nEdgeIDs\n\n4\n" + in text + ) + + assert "1 3" in text + assert "5 2" in text + + +def test_map_file_sorts_initiators_edges_and_equivalences( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + text = builder._map_file_write( + reactant_to_product={ + 5: 8, + 1: 2, + 3: 4, + }, + initiator_atoms=[ + 5, + 1, + ], + edge_atoms=[ + 8, + 2, + 4, + ], + delete_ids=[], + file_name="RXN_1.map", + ) + + initiator_block = ( + text.split( + "InitiatorIDs\n\n", + 1, + )[1] + .split( + "\nEdgeIDs", + 1, + )[0] + .strip() + .splitlines() + ) + + assert initiator_block == [ + "2", + "6", + ] + + edge_block = ( + text.split( + "EdgeIDs\n\n", + 1, + )[1] + .split( + "\nEquivalences", + 1, + )[0] + .strip() + .splitlines() + ) + + assert edge_block == [ + "3", + "5", + "9", + ] + + +# ============================================================================= +# _build_bond_react_templates +# ============================================================================= + + +def test_build_templates_missing_post_entry_raises( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + pre = ( + tmp_path / "pre.molecule" + ) + + pre.write_text( + "pre", + encoding="utf-8", + ) + + with pytest.raises( + ValueError, + match="Corresponding post-reaction file", + ): + builder._build_bond_react_templates( + file_dict={ + "pre_1": pre, + }, + reactant_to_product={ + 0: 0, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[], + ) + + +def test_build_templates_missing_pre_file_raises( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + post = ( + tmp_path / "post.molecule" + ) + + post.write_text( + "post", + encoding="utf-8", + ) + + with pytest.raises( + FileNotFoundError, + match="Missing pre file", + ): + builder._build_bond_react_templates( + file_dict={ + "pre_1": ( + tmp_path + / "missing.molecule" + ), + "post_1": post, + }, + reactant_to_product={ + 0: 0, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[], + ) + + +def test_build_templates_missing_post_file_raises( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + pre = ( + tmp_path / "pre.molecule" + ) + + pre.write_text( + "pre", + encoding="utf-8", + ) + + with pytest.raises( + FileNotFoundError, + match="Missing post file", + ): + builder._build_bond_react_templates( + file_dict={ + "pre_1": pre, + "post_1": ( + tmp_path + / "missing.molecule" + ), + }, + reactant_to_product={ + 0: 0, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[], + ) + + +def test_build_templates_writes_standard_pre_post_and_map( + tmp_path, + monkeypatch, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + pre = ( + tmp_path / "pre_source.molecule" + ) + + post = ( + tmp_path / "post_source.molecule" + ) + + pre.write_text( + "pre", + encoding="utf-8", + ) + + post.write_text( + "post", + encoding="utf-8", + ) + + def fake_prepare( + path, + indexes, + file_name, + ): + if Path(path) == pre: + return ( + "PRE-CONTENT", + { + 1: 1, + 2: 2, + }, + ) + + return ( + "POST-CONTENT", + { + 1: 1, + 2: 2, + }, + ) + + monkeypatch.setattr( + builder, + "_molecule_file_preparation", + fake_prepare, + ) + + monkeypatch.setattr( + builder, + "_map_file_write", + lambda *args, **kwargs: + "STANDARD-MAP", + ) + + pre_out, post_out, map_path = ( + builder + ._build_bond_react_templates( + file_dict={ + "pre_1": pre, + "post_1": post, + }, + reactant_to_product={ + 0: 0, + 1: 1, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[], + ) + ) + + assert Path( + pre_out + ).read_text( + encoding="utf-8" + ) == "PRE-CONTENT" + + assert Path( + post_out + ).read_text( + encoding="utf-8" + ) == "POST-CONTENT" + + assert Path( + map_path + ).read_text( + encoding="utf-8" + ) == "STANDARD-MAP" + + assert Path( + pre_out + ).name == ( + "template_pre_1.molecule" + ) + + assert Path( + post_out + ).name == ( + "template_post_1.molecule" + ) + + assert Path( + map_path + ).name == "RXN_1.map" + + +def test_build_templates_standard_map_suppresses_delete_ids( + tmp_path, + monkeypatch, +): + """ + Even when delete atoms exist, the PRIMARY map must be generated + with delete_ids=[]. + """ + builder, _ = ( + make_builder( + tmp_path + ) + ) + + pre = tmp_path / "pre.molecule" + post = tmp_path / "post.molecule" + + pre.write_text("pre") + post.write_text("post") + + monkeypatch.setattr( + builder, + "_molecule_file_preparation", + lambda path, indexes, file_name: + ( + "CONTENT", + { + 1: 1, + 2: 2, + 3: 3, + }, + ), + ) + + calls = [] + + def fake_map( + mapping, + initiators, + edges, + deletes, + file_name, + ): + calls.append( + ( + mapping, + initiators, + edges, + deletes, + file_name, + ) + ) + + return file_name + + monkeypatch.setattr( + builder, + "_map_file_write", + fake_map, + ) + + builder._build_bond_react_templates( + file_dict={ + "pre_1": pre, + "post_1": post, + }, + reactant_to_product={ + 0: 0, + 1: 1, + 2: 2, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[ + 2, + ], + delete_ids=[ + 2, + ], + ) + + # First map is always standard. + assert calls[0][3] == [] + + assert calls[0][4] == ( + "RXN_1.map" + ) + + +def test_build_templates_optional_delete_map_written_only_when_needed( + tmp_path, + monkeypatch, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + pre = tmp_path / "pre.molecule" + post = tmp_path / "post.molecule" + + pre.write_text("pre") + post.write_text("post") + + monkeypatch.setattr( + builder, + "_molecule_file_preparation", + lambda path, indexes, file_name: + ( + "CONTENT", + { + 1: 1, + 2: 2, + 3: 3, + }, + ), + ) + + calls = [] + + def fake_map( + mapping, + initiators, + edges, + deletes, + file_name, + ): + calls.append( + ( + list(deletes), + file_name, + ) + ) + + return file_name + + monkeypatch.setattr( + builder, + "_map_file_write", + fake_map, + ) + + builder._build_bond_react_templates( + file_dict={ + "pre_4": pre, + "post_4": post, + }, + reactant_to_product={ + 0: 0, + 1: 1, + 2: 2, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[ + 2, + ], + ) + + assert calls == [ + ( + [], + "RXN_4.map", + ), + ( + [ + 2, + ], + "RXN_4_with_delete_ids.map", + ), + ] + + assert ( + builder.cache_dir + / "RXN_4_with_delete_ids.map" + ).is_file() + + +def test_build_templates_does_not_write_optional_delete_map_when_no_delete_ids( + tmp_path, + monkeypatch, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + pre = tmp_path / "pre.molecule" + post = tmp_path / "post.molecule" + + pre.write_text("pre") + post.write_text("post") + + monkeypatch.setattr( + builder, + "_molecule_file_preparation", + lambda path, indexes, file_name: + ( + "CONTENT", + { + 1: 1, + 2: 2, + }, + ), + ) + + monkeypatch.setattr( + builder, + "_map_file_write", + lambda *args, **kwargs: + "MAP", + ) + + builder._build_bond_react_templates( + file_dict={ + "pre_2": pre, + "post_2": post, + }, + reactant_to_product={ + 0: 0, + 1: 1, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[], + ) + + assert not ( + builder.cache_dir + / "RXN_2_with_delete_ids.map" + ).exists() + + +def test_build_templates_reindexes_mapping_into_trimmed_template_space( + tmp_path, + monkeypatch, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + pre = tmp_path / "pre.molecule" + post = tmp_path / "post.molecule" + + pre.write_text("pre") + post.write_text("post") + + def fake_prepare( + path, + indexes, + file_name, + ): + if Path(path) == pre: + return ( + "PRE", + { + 1: 2, + 2: 1, + }, + ) + + return ( + "POST", + { + 1: 2, + 3: 1, + }, + ) + + monkeypatch.setattr( + builder, + "_molecule_file_preparation", + fake_prepare, + ) + + mappings = [] + + def fake_map( + mapping, + initiators, + edges, + deletes, + file_name, + ): + mappings.append( + dict(mapping) + ) + + return "MAP" + + monkeypatch.setattr( + builder, + "_map_file_write", + fake_map, + ) + + builder._build_bond_react_templates( + file_dict={ + "pre_1": pre, + "post_1": post, + }, + reactant_to_product={ + 0: 2, + 1: 0, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[], + ) + + # full 0 -> full 2 + # reactant old1 -> template2 -> zero-based1 + # product old3 -> template1 -> zero-based0 + # + # full 1 -> full 0 + # reactant old2 -> template1 -> zero-based0 + # product old1 -> template2 -> zero-based1 + assert mappings[0] == { + 1: 0, + 0: 1, + } + + +def test_build_templates_missing_filtered_mapping_raises( + tmp_path, + monkeypatch, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + pre = tmp_path / "pre.molecule" + post = tmp_path / "post.molecule" + + pre.write_text("pre") + post.write_text("post") + + monkeypatch.setattr( + builder, + "_molecule_file_preparation", + lambda path, indexes, file_name: + ( + "CONTENT", + { + 1: 1, + }, + ), + ) + + with pytest.raises( + ValueError, + match=( + "Template mapping indices " + "missing after filtering" + ), + ): + builder._build_bond_react_templates( + file_dict={ + "pre_1": pre, + "post_1": post, + }, + reactant_to_product={ + 0: 0, + 1: 1, + }, + initiator_atoms=[ + 0, + 1, + ], + edge_atoms=[], + delete_ids=[], + ) + + +# ============================================================================= +# _copy_lunar_files_to_cache +# ============================================================================= + + +def test_copy_lunar_files_copies_force_field_and_input( + tmp_path, +): + monomer = make_monomer() + + builder, session = ( + make_builder( + tmp_path, + monomers=[ + monomer + ], + ) + ) + + ff_src = ( + tmp_path / "force_field.data" + ) + + in_src = ( + tmp_path + / "in.create_atoms.script" + ) + + ff_src.write_text( + "FF", + encoding="utf-8", + ) + + in_src.write_text( + "INPUT", + encoding="utf-8", + ) + + ff_files = SimpleNamespace( + force_field_data=ff_src, + in_file=in_src, + molecule_files=[], + ) + + ff_dest, in_dest = ( + builder + ._copy_lunar_files_to_cache( + ff_files + ) + ) + + assert ff_dest == ( + builder.cache_dir + / "force_field.data" + ) + + assert in_dest == ( + builder.cache_dir + / "in.create_atoms.script" + ) + + assert ff_dest.read_text() == "FF" + assert in_dest.read_text() == "INPUT" + + +def test_copy_lunar_files_attaches_molecule_by_name( + tmp_path, +): + monomer = make_monomer( + monomer_id=7, + data_id="data7", + name="mma", + ) + + builder, _ = ( + make_builder( + tmp_path, + monomers=[ + monomer + ], + ) + ) + + ff_src = tmp_path / "ff.data" + in_src = tmp_path / "in.script" + mol_src = tmp_path / "mma.lmpmol" + + ff_src.write_text("ff") + in_src.write_text("in") + mol_src.write_text("mol") + + ff_files = SimpleNamespace( + force_field_data=ff_src, + in_file=in_src, + molecule_files=[ + SimpleNamespace( + id="mma", + molecule_files=SimpleNamespace( + lmp_molecule_file=mol_src, + ), + ) + ], + ) + + builder._copy_lunar_files_to_cache( + ff_files + ) + + assert ( + monomer.lmp_molecule_file + == builder.cache_dir + / "mma.molecule" + ) + + assert ( + monomer + .lmp_molecule_file + .read_text() + == "mol" + ) + + +@pytest.mark.parametrize( + "lookup_id", + [ + "7", + "data7", + "mma", + ], +) +def test_copy_lunar_files_matches_monomer_by_id_data_id_or_name( + tmp_path, + lookup_id, +): + monomer = make_monomer( + monomer_id=7, + data_id="data7", + name="mma", + ) + + builder, _ = ( + make_builder( + tmp_path, + monomers=[ + monomer + ], + ) + ) + + ff_src = tmp_path / "ff.data" + in_src = tmp_path / "in.script" + mol_src = tmp_path / "mol.lmpmol" + + ff_src.write_text("ff") + in_src.write_text("in") + mol_src.write_text("mol") + + ff_files = SimpleNamespace( + force_field_data=ff_src, + in_file=in_src, + molecule_files=[ + SimpleNamespace( + id=lookup_id, + molecule_files=SimpleNamespace( + lmp_molecule_file=mol_src, + ), + ) + ], + ) + + builder._copy_lunar_files_to_cache( + ff_files + ) + + assert ( + monomer.lmp_molecule_file + is not None + ) + + +def test_copy_lunar_force_field_failure_wrapped( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + ff_files = SimpleNamespace( + force_field_data=( + tmp_path / "missing.data" + ), + in_file=( + tmp_path / "missing.script" + ), + molecule_files=[], + ) + + with pytest.raises( + FileNotFoundError, + match=( + "Failed to copy force field data" + ), + ): + builder._copy_lunar_files_to_cache( + ff_files + ) + + +# ============================================================================= +# _copy_path_to_final +# ============================================================================= + + +def test_copy_path_to_final_none_returns_none( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + assert ( + builder._copy_path_to_final( + None, + tmp_path / "final", + ) + is None + ) + + +def test_copy_path_to_final_missing_file_returns_none( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + result = ( + builder._copy_path_to_final( + tmp_path / "missing.map", + tmp_path / "final", + ) + ) + + assert result is None + + +def test_copy_path_to_final_copies_existing_file( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + src = tmp_path / "RXN_1.map" + + src.write_text( + "MAP", + encoding="utf-8", + ) + + final_dir = ( + tmp_path / "final" + ) + + result = ( + builder._copy_path_to_final( + src, + final_dir, + ) + ) + + assert result == ( + final_dir / "RXN_1.map" + ) + + assert result.read_text() == "MAP" + + +def test_copy_path_to_final_same_source_and_destination( + tmp_path, +): + builder, _ = ( + make_builder( + tmp_path + ) + ) + + final_dir = ( + tmp_path / "final" + ) + + final_dir.mkdir() + + src = ( + final_dir / "RXN_1.map" + ) + + src.write_text( + "MAP", + encoding="utf-8", + ) + + result = ( + builder._copy_path_to_final( + src, + final_dir, + ) + ) + + assert result == src + assert result.read_text() == "MAP" + + +# ============================================================================= +# molecule_template_preparation - core orchestration +# ============================================================================= + + +def test_molecule_template_preparation_builds_template_mapping_from_dataframe( + tmp_path, + monkeypatch, +): + df = pd.DataFrame( + { + "template_reactant_idx": [ + 0, + 1, + ], + "template_product_idx": [ + 2, + 0, + ], + "initiators": [ + 0, + 1, + ], + "edge_atoms": [ + 3, + None, + ], + "byproduct_idx": [ + None, + None, + ], + } + ) + + metadata = ( + make_reaction_metadata( + reaction_id=5, + dataframe=df, + ) + ) + + monomer = make_monomer() + + builder, session = ( + make_builder( + tmp_path, + monomers=[ + monomer + ], + reactions=[ + metadata + ], + ) + ) + + pre_source = ( + tmp_path / "pre5.lmpmol" + ) + + post_source = ( + tmp_path / "post5.lmpmol" + ) + + pre_source.write_text("pre") + post_source.write_text("post") + + session.ff_files = ( + SimpleNamespace( + template_files=[ + make_template_ff_entry( + reaction_id=5, + pre_file=pre_source, + post_file=post_source, + ) + ], + ) + ) + + ff_cache = ( + builder.cache_dir + / "force_field.data" + ) + + in_cache = ( + builder.cache_dir + / "in.script" + ) + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda ff_files: + ( + ff_cache, + in_cache, + ), + ) + + pre_out = ( + builder.cache_dir + / "template_pre_5.molecule" + ) + + post_out = ( + builder.cache_dir + / "template_post_5.molecule" + ) + + map_out = ( + builder.cache_dir + / "RXN_5.map" + ) + + for path in ( + pre_out, + post_out, + map_out, + ): + path.write_text( + path.name, + encoding="utf-8", + ) + + calls = [] + + def fake_build( + *, + file_dict, + reactant_to_product, + initiator_atoms, + edge_atoms, + delete_ids, + ): + calls.append( + { + "file_dict": file_dict, + "mapping": reactant_to_product, + "initiators": initiator_atoms, + "edges": edge_atoms, + "deletes": delete_ids, + } + ) + + return ( + pre_out, + post_out, + map_out, + ) + + monkeypatch.setattr( + builder, + "_build_bond_react_templates", + fake_build, + ) + + class FakeDetector: + def compare_lammps_templates( + self, + template_files, + wildcards, + ): + return template_files + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + FakeDetector, + ) + + builder.molecule_template_preparation( + session + ) + + assert calls[0][ + "mapping" + ] == { + 0: 2, + 1: 0, + } + + assert calls[0][ + "initiators" + ] == [ + 0, + 1, + ] + + assert calls[0][ + "edges" + ] == [ + 3, + ] + + assert calls[0][ + "deletes" + ] == [] + + +def test_delete_atom_false_does_not_pass_byproducts_as_delete_ids( + tmp_path, + monkeypatch, +): + df = pd.DataFrame( + { + "template_reactant_idx": [ + 0, + 1, + ], + "template_product_idx": [ + 0, + 1, + ], + "initiators": [ + 0, + 1, + ], + "byproduct_idx": [ + 5, + 6, + ], + } + ) + + metadata = make_reaction_metadata( + reaction_id=1, + dataframe=df, + delete_atom=False, + ) + + builder, session = ( + make_builder( + tmp_path, + reactions=[ + metadata + ], + ) + ) + + pre = tmp_path / "pre.lmpmol" + post = tmp_path / "post.lmpmol" + + pre.write_text("pre") + post.write_text("post") + + session.ff_files = ( + SimpleNamespace( + template_files=[ + make_template_ff_entry( + reaction_id=1, + pre_file=pre, + post_file=post, + ) + ], + ) + ) + + ff_cache = builder.cache_dir / "ff.data" + in_cache = builder.cache_dir / "in.script" + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + captured = [] + + def fake_build(**kwargs): + captured.append( + kwargs["delete_ids"] + ) + + pre_out = ( + builder.cache_dir + / "template_pre_1.molecule" + ) + + post_out = ( + builder.cache_dir + / "template_post_1.molecule" + ) + + map_out = ( + builder.cache_dir + / "RXN_1.map" + ) + + for path in ( + pre_out, + post_out, + map_out, + ): + path.write_text("x") + + return ( + pre_out, + post_out, + map_out, + ) + + monkeypatch.setattr( + builder, + "_build_bond_react_templates", + fake_build, + ) + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + lambda: + SimpleNamespace( + compare_lammps_templates=( + lambda template_files, wildcards: + template_files + ) + ), + ) + + builder.molecule_template_preparation( + session + ) + + assert captured == [ + [] + ] + + +def test_delete_atom_true_passes_byproducts_as_optional_delete_ids( + tmp_path, + monkeypatch, +): + df = pd.DataFrame( + { + "template_reactant_idx": [ + 0, + 1, + ], + "template_product_idx": [ + 0, + 1, + ], + "initiators": [ + 0, + 1, + ], + "byproduct_idx": [ + 5, + 6, + ], + } + ) + + metadata = make_reaction_metadata( + reaction_id=1, + dataframe=df, + delete_atom=True, + ) + + builder, session = ( + make_builder( + tmp_path, + reactions=[ + metadata + ], + ) + ) + + pre = tmp_path / "pre.lmpmol" + post = tmp_path / "post.lmpmol" + + pre.write_text("pre") + post.write_text("post") + + session.ff_files = ( + SimpleNamespace( + template_files=[ + make_template_ff_entry( + reaction_id=1, + pre_file=pre, + post_file=post, + ) + ], + ) + ) + + ff_cache = builder.cache_dir / "ff.data" + in_cache = builder.cache_dir / "in.script" + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + captured = [] + + def fake_build(**kwargs): + captured.append( + kwargs["delete_ids"] + ) + + pre_out = ( + builder.cache_dir + / "template_pre_1.molecule" + ) + + post_out = ( + builder.cache_dir + / "template_post_1.molecule" + ) + + map_out = ( + builder.cache_dir + / "RXN_1.map" + ) + + for path in ( + pre_out, + post_out, + map_out, + ): + path.write_text("x") + + return ( + pre_out, + post_out, + map_out, + ) + + monkeypatch.setattr( + builder, + "_build_bond_react_templates", + fake_build, + ) + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + lambda: + SimpleNamespace( + compare_lammps_templates=( + lambda template_files, wildcards: + template_files + ) + ), + ) + + builder.molecule_template_preparation( + session + ) + + assert captured == [ + [ + 5, + 6, + ] + ] + + +def test_optional_delete_map_is_not_required( + tmp_path, + monkeypatch, +): + """ + Important contract: + + A reaction is valid with only RXN_N.map. + RXN_N_with_delete_ids.map is supplementary and may remain None. + """ + df = pd.DataFrame( + { + "template_reactant_idx": [ + 0, + 1, + ], + "template_product_idx": [ + 0, + 1, + ], + "initiators": [ + 0, + 1, + ], + } + ) + + metadata = make_reaction_metadata( + reaction_id=1, + dataframe=df, + delete_atom=False, + ) + + builder, session = ( + make_builder( + tmp_path, + reactions=[ + metadata + ], + ) + ) + + pre_source = tmp_path / "pre.lmpmol" + post_source = tmp_path / "post.lmpmol" + + pre_source.write_text("pre") + post_source.write_text("post") + + session.ff_files = ( + SimpleNamespace( + template_files=[ + make_template_ff_entry( + reaction_id=1, + pre_file=pre_source, + post_file=post_source, + ) + ], + ) + ) + + ff_cache = builder.cache_dir / "ff.data" + in_cache = builder.cache_dir / "in.script" + pre_out = builder.cache_dir / "template_pre_1.molecule" + post_out = builder.cache_dir / "template_post_1.molecule" + map_out = builder.cache_dir / "RXN_1.map" + + for path in ( + ff_cache, + in_cache, + pre_out, + post_out, + map_out, + ): + path.write_text("x") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + monkeypatch.setattr( + builder, + "_build_bond_react_templates", + lambda **kwargs: + ( + pre_out, + post_out, + map_out, + ), + ) + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + lambda: + SimpleNamespace( + compare_lammps_templates=( + lambda template_files, wildcards: + template_files + ) + ), + ) + + builder.molecule_template_preparation( + session + ) + + assert ( + metadata.map_file + is not None + ) + + assert ( + metadata.pre_reaction_file + is not None + ) + + assert ( + metadata.post_reaction_file + is not None + ) + + assert ( + metadata.map_file_with_delete_ids + is None + ) + + assert len( + session + .reacter_files + .template_files + ) == 1 + + +# ============================================================================= +# Deduplication routing +# ============================================================================= + + +def test_template_deduplication_enabled_calls_compare_lammps_templates( + tmp_path, + monkeypatch, +): + builder, session = ( + make_builder( + tmp_path, + deduplicate=True, + wildcards=True, + ) + ) + + builder_reaction = ( + make_reaction_metadata( + reaction_id=1, + activity_stats=True, + ) + ) + + builder_reaction.map_file = ( + tmp_path / "RXN_1.map" + ) + + builder_reaction.pre_reaction_file = ( + tmp_path / "pre.molecule" + ) + + builder_reaction.post_reaction_file = ( + tmp_path / "post.molecule" + ) + + session.reaction_metadata = [ + builder_reaction + ] + + session.ff_files = SimpleNamespace( + template_files=[], + ) + + ff_cache = builder.cache_dir / "ff.data" + in_cache = builder.cache_dir / "in.script" + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + calls = [] + + class FakeDetector: + def compare_lammps_templates( + self, + template_files, + wildcards, + ): + calls.append( + ( + list(template_files), + wildcards, + ) + ) + + return [ + "DEDUPED" + ] + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + FakeDetector, + ) + + # Keep already-set reaction paths intact. + monkeypatch.setattr( + builder, + "_copy_path_to_final", + lambda src, final: + Path(src) + if src is not None + else None, + ) + + builder.molecule_template_preparation( + session + ) + + assert calls == [ + ( + [ + builder_reaction + ], + True, + ) + ] + + assert ( + session + .reacter_files + .template_files + == [ + "DEDUPED" + ] + ) + + +def test_deduplication_disabled_skips_compare( + tmp_path, + monkeypatch, + capsys, +): + builder, session = ( + make_builder( + tmp_path, + deduplicate=False, + wildcards=False, + ) + ) + + reaction = ( + make_reaction_metadata( + reaction_id=1, + activity_stats=True, + ) + ) + + reaction.map_file = ( + tmp_path / "RXN_1.map" + ) + + reaction.pre_reaction_file = ( + tmp_path / "pre.molecule" + ) + + reaction.post_reaction_file = ( + tmp_path / "post.molecule" + ) + + session.reaction_metadata = [ + reaction + ] + + session.ff_files = ( + SimpleNamespace( + template_files=[], + ) + ) + + ff_cache = builder.cache_dir / "ff.data" + in_cache = builder.cache_dir / "in.script" + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + class FakeDetector: + def compare_lammps_templates( + self, + **kwargs, + ): + pytest.fail( + "deduplication must not run" + ) + + def write_wildcard_maps( + self, + **kwargs, + ): + pytest.fail( + "wildcard rewrite must not run" + ) + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + FakeDetector, + ) + + monkeypatch.setattr( + builder, + "_copy_path_to_final", + lambda src, final: + Path(src) + if src is not None + else None, + ) + + builder.molecule_template_preparation( + session + ) + + assert ( + "Skipping LAMMPS reaction-template deduplication" + in capsys.readouterr().out + ) + + assert ( + session + .reacter_files + .template_files + == [ + reaction + ] + ) + + +def test_wildcards_without_deduplication_calls_write_wildcard_maps( + tmp_path, + monkeypatch, +): + builder, session = ( + make_builder( + tmp_path, + deduplicate=False, + wildcards=True, + ) + ) + + reaction = ( + make_reaction_metadata( + reaction_id=1, + activity_stats=True, + ) + ) + + reaction.map_file = ( + tmp_path / "RXN_1.map" + ) + + reaction.pre_reaction_file = ( + tmp_path / "pre.molecule" + ) + + reaction.post_reaction_file = ( + tmp_path / "post.molecule" + ) + + session.reaction_metadata = [ + reaction + ] + + session.ff_files = ( + SimpleNamespace( + template_files=[], + ) + ) + + ff_cache = builder.cache_dir / "ff.data" + in_cache = builder.cache_dir / "in.script" + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + calls = [] + + class FakeDetector: + def write_wildcard_maps( + self, + template_files, + ): + calls.append( + list( + template_files + ) + ) + + return [ + "WILDCARD" + ] + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + FakeDetector, + ) + + monkeypatch.setattr( + builder, + "_copy_path_to_final", + lambda src, final: + Path(src) + if src is not None + else None, + ) + + builder.molecule_template_preparation( + session + ) + + assert calls == [ + [ + reaction + ] + ] + + assert ( + session + .reacter_files + .template_files + == [ + "WILDCARD" + ] + ) + + +# ============================================================================= +# Active-template filtering +# ============================================================================= + + +def test_only_active_complete_reactions_enter_final_template_list( + tmp_path, + monkeypatch, +): + complete = ( + make_reaction_metadata( + reaction_id=1, + activity_stats=True, + ) + ) + + inactive = ( + make_reaction_metadata( + reaction_id=2, + activity_stats=False, + ) + ) + + incomplete = ( + make_reaction_metadata( + reaction_id=3, + activity_stats=True, + ) + ) + + for reaction in ( + complete, + inactive, + ): + reaction.map_file = ( + tmp_path + / f"RXN_{reaction.reaction_id}.map" + ) + + reaction.pre_reaction_file = ( + tmp_path + / f"pre{reaction.reaction_id}.molecule" + ) + + reaction.post_reaction_file = ( + tmp_path + / f"post{reaction.reaction_id}.molecule" + ) + + incomplete.map_file = ( + tmp_path / "RXN_3.map" + ) + + incomplete.pre_reaction_file = ( + tmp_path / "pre3.molecule" + ) + + incomplete.post_reaction_file = None + + builder, session = ( + make_builder( + tmp_path, + deduplicate=False, + reactions=[ + complete, + inactive, + incomplete, + ], + ) + ) + + session.ff_files = ( + SimpleNamespace( + template_files=[], + ) + ) + + ff_cache = builder.cache_dir / "ff.data" + in_cache = builder.cache_dir / "in.script" + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + monkeypatch.setattr( + builder, + "_copy_path_to_final", + lambda src, final: + Path(src) + if src is not None + else None, + ) + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + lambda: + SimpleNamespace(), + ) + + builder.molecule_template_preparation( + session + ) + + assert ( + session + .reacter_files + .template_files + == [ + complete + ] + ) + + +# ============================================================================= +# Final output validation +# ============================================================================= + + +def test_missing_final_force_field_copy_raises( + tmp_path, + monkeypatch, +): + builder, session = ( + make_builder( + tmp_path + ) + ) + + session.ff_files = ( + SimpleNamespace( + template_files=[], + ) + ) + + ff_cache = ( + builder.cache_dir + / "force_field.data" + ) + + in_cache = ( + builder.cache_dir + / "in.script" + ) + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + def fake_copy( + src, + final, + ): + if Path(src) == ff_cache: + return None + + return Path(src) + + monkeypatch.setattr( + builder, + "_copy_path_to_final", + fake_copy, + ) + + with pytest.raises( + FileNotFoundError, + match="force_field.data was not copied", + ): + builder.molecule_template_preparation( + session + ) + + +def test_missing_final_input_copy_raises( + tmp_path, + monkeypatch, +): + builder, session = ( + make_builder( + tmp_path + ) + ) + + session.ff_files = ( + SimpleNamespace( + template_files=[], + ) + ) + + ff_cache = ( + builder.cache_dir + / "force_field.data" + ) + + in_cache = ( + builder.cache_dir + / "in.script" + ) + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + def fake_copy( + src, + final, + ): + if Path(src) == in_cache: + return None + + return Path(src) + + monkeypatch.setattr( + builder, + "_copy_path_to_final", + fake_copy, + ) + + with pytest.raises( + FileNotFoundError, + match="LAMMPS input file was not copied", + ): + builder.molecule_template_preparation( + session + ) + + +def test_molecule_template_preparation_returns_none_and_sets_session_result( + tmp_path, + monkeypatch, +): + monomer = make_monomer( + lmp_molecule_file=( + tmp_path + / "mma.molecule" + ) + ) + + monomer.lmp_molecule_file.write_text( + "mol" + ) + + builder, session = ( + make_builder( + tmp_path, + monomers=[ + monomer + ], + deduplicate=False, + ) + ) + + session.ff_files = ( + SimpleNamespace( + template_files=[], + ) + ) + + ff_cache = ( + builder.cache_dir + / "force_field.data" + ) + + in_cache = ( + builder.cache_dir + / "in.script" + ) + + ff_cache.write_text("ff") + in_cache.write_text("in") + + monkeypatch.setattr( + builder, + "_copy_lunar_files_to_cache", + lambda files: + ( + ff_cache, + in_cache, + ), + ) + + monkeypatch.setattr( + builder_module, + "DeduplicationDetector", + lambda: + SimpleNamespace(), + ) + + result = ( + builder + .molecule_template_preparation( + session + ) + ) + + assert result is None + + assert isinstance( + session.reacter_files, + REACTERFiles, + ) + + assert ( + session + .reacter_files + .force_field_data + == Path(session.output_dir) + / "force_field.data" + ) + + assert ( + session + .reacter_files + .molecule_files + == [ + monomer + ] + ) \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/test_ff_locator.py b/tests/unit/reaction_preparation/ff_wrapper/test_ff_locator.py new file mode 100644 index 00000000..17fe2bb1 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/test_ff_locator.py @@ -0,0 +1,829 @@ +from pathlib import Path + +import pytest + +import AutoREACTER.reaction_preparation.ff_wrapper.ff_locator as ff_locator +from AutoREACTER.reaction_preparation.ff_wrapper.ff_locator import ( + get_force_field_file, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_fake_internal_ff_tree( + tmp_path: Path, + *, + include_pcff: bool = True, +) -> Path: + """ + Build the directory that pkg_resources.files("AutoREACTER") + is expected to expose. + """ + package_root = ( + tmp_path / "AutoREACTER" + ) + + ff_dir = ( + package_root + / "reaction_preparation" + / "ff_wrapper" + / "FF_files" + ) + + ff_dir.mkdir( + parents=True, + exist_ok=True, + ) + + if include_pcff: + ( + ff_dir / "pcff.frc" + ).write_text( + "fake pcff", + encoding="utf-8", + ) + + return package_root + + +def make_fake_lunar( + tmp_path: Path, + *, + files=(), +) -> Path: + lunar_root = ( + tmp_path / "LUNAR" + ) + + frc_dir = ( + lunar_root / "frc_files" + ) + + frc_dir.mkdir( + parents=True, + exist_ok=True, + ) + + for filename in files: + ( + frc_dir / filename + ).write_text( + "fake frc", + encoding="utf-8", + ) + + return lunar_root + + +def patch_internal_package_root( + monkeypatch, + package_root: Path, +): + monkeypatch.setattr( + ff_locator.pkg_resources, + "files", + lambda package_name: package_root, + ) + + +# ============================================================================= +# Bundled PCFF +# ============================================================================= + + +@pytest.mark.parametrize( + "force_field", + [ + "PCFF", + "PCFF-IFF", + ], +) +def test_internal_pcff_variants_resolve_to_same_file( + tmp_path, + monkeypatch, + force_field, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + result = get_force_field_file( + force_field + ) + + expected = ( + package_root + / "reaction_preparation" + / "ff_wrapper" + / "FF_files" + / "pcff.frc" + ) + + assert result == expected + + +@pytest.mark.parametrize( + "force_field", + [ + "PCFF", + "PCFF-IFF", + ], +) +def test_internal_pcff_does_not_require_lunar_location( + tmp_path, + monkeypatch, + force_field, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + result = get_force_field_file( + force_field=force_field, + lunar_location=None, + ) + + assert result.is_file() + + +def test_internal_pcff_returns_path_object( + tmp_path, + monkeypatch, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + result = get_force_field_file( + "PCFF" + ) + + assert isinstance( + result, + Path, + ) + + +def test_internal_pcff_missing_file_raises_value_error( + tmp_path, + monkeypatch, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path, + include_pcff=False, + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + expected = ( + package_root + / "reaction_preparation" + / "ff_wrapper" + / "FF_files" + / "pcff.frc" + ) + + with pytest.raises( + ValueError, + match="Force field file not found", + ) as exc_info: + get_force_field_file( + "PCFF" + ) + + assert str( + expected + ) in str( + exc_info.value + ) + + +def test_real_packaged_pcff_file_is_available(): + """ + Small packaging regression check. + + This intentionally uses the real package resource rather than + monkeypatching pkg_resources. If pcff.frc disappears from the + installation/package, AutoREACTER's supported PCFF backend is broken. + """ + result = get_force_field_file( + "PCFF" + ) + + assert isinstance( + result, + Path, + ) + + assert result.is_file() + + assert result.name == ( + "pcff.frc" + ) + + +def test_pcff_prefers_internal_file_even_when_lunar_location_given( + tmp_path, + monkeypatch, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + lunar_root = ( + make_fake_lunar( + tmp_path, + files=[ + "compass_published.frc", + ], + ) + ) + + result = get_force_field_file( + force_field="PCFF", + lunar_location=lunar_root, + ) + + assert result == ( + package_root + / "reaction_preparation" + / "ff_wrapper" + / "FF_files" + / "pcff.frc" + ) + + +# ============================================================================= +# pkg_resources failure +# ============================================================================= + + +def test_pkg_resources_failure_is_wrapped_as_runtime_error( + monkeypatch, +): + def fail(package_name): + raise RuntimeError( + "resource lookup exploded" + ) + + monkeypatch.setattr( + ff_locator.pkg_resources, + "files", + fail, + ) + + with pytest.raises( + RuntimeError, + match="Error locating FF_files directory using pkg_resources", + ) as exc_info: + get_force_field_file( + "PCFF" + ) + + assert ( + "resource lookup exploded" + in str( + exc_info.value + ) + ) + + +@pytest.mark.parametrize( + "force_field", + [ + "PCFF", + "PCFF-IFF", + "compass", + "CVFF", + "CVFF-IFF", + "DREIDING", + ], +) +def test_lunar_force_field_branch_attempts_internal_resource_lookup_first( + monkeypatch, + force_field, +): + calls = [] + + def fail(package_name): + calls.append( + package_name + ) + + raise RuntimeError( + "boom" + ) + + monkeypatch.setattr( + ff_locator.pkg_resources, + "files", + fail, + ) + + with pytest.raises( + RuntimeError, + match="Error locating FF_files", + ): + get_force_field_file( + force_field, + lunar_location="/tmp/LUNAR", + ) + + assert calls == [ + "AutoREACTER" + ] + + +# ============================================================================= +# External LUNAR force fields +# ============================================================================= + + +@pytest.mark.parametrize( + "force_field, expected_filename", + [ + ( + "compass", + "compass_published.frc", + ), + ( + "CVFF-IFF", + "cvff_aug.frc", + ), + ( + "CVFF", + "cvff.frc", + ), + ( + "DREIDING", + "all2lmp_dreiding.frc", + ), + ], +) +def test_external_lunar_force_field_mapping( + tmp_path, + monkeypatch, + force_field, + expected_filename, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + lunar_root = ( + make_fake_lunar( + tmp_path, + files=[ + expected_filename + ], + ) + ) + + result = get_force_field_file( + force_field=force_field, + lunar_location=lunar_root, + ) + + assert result == ( + lunar_root + / "frc_files" + / expected_filename + ) + + assert result.is_file() + + +@pytest.mark.parametrize( + "force_field", + [ + "compass", + "CVFF-IFF", + "CVFF", + "DREIDING", + ], +) +def test_external_lunar_force_field_without_lunar_location_raises( + tmp_path, + monkeypatch, + force_field, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + with pytest.raises( + ValueError, + match="Required LUNAR installation not found to resolve", + ) as exc_info: + get_force_field_file( + force_field=force_field, + lunar_location=None, + ) + + assert force_field in str( + exc_info.value + ) + + +@pytest.mark.parametrize( + "force_field, expected_filename", + [ + ( + "compass", + "compass_published.frc", + ), + ( + "CVFF-IFF", + "cvff_aug.frc", + ), + ( + "CVFF", + "cvff.frc", + ), + ( + "DREIDING", + "all2lmp_dreiding.frc", + ), + ], +) +def test_external_lunar_force_field_missing_file_raises( + tmp_path, + monkeypatch, + force_field, + expected_filename, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + lunar_root = ( + make_fake_lunar( + tmp_path + ) + ) + + expected = ( + lunar_root + / "frc_files" + / expected_filename + ) + + with pytest.raises( + ValueError, + match="Force field file not found", + ) as exc_info: + get_force_field_file( + force_field=force_field, + lunar_location=lunar_root, + ) + + assert str( + expected + ) in str( + exc_info.value + ) + + +def test_lunar_location_accepts_string_path( + tmp_path, + monkeypatch, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + lunar_root = ( + make_fake_lunar( + tmp_path, + files=[ + "cvff.frc" + ], + ) + ) + + result = get_force_field_file( + force_field="CVFF", + lunar_location=str( + lunar_root + ), + ) + + assert result == ( + lunar_root + / "frc_files" + / "cvff.frc" + ) + + +# ============================================================================= +# Exact current force-field naming contract +# ============================================================================= + + +def test_compass_lowercase_is_supported( + tmp_path, + monkeypatch, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + lunar_root = ( + make_fake_lunar( + tmp_path, + files=[ + "compass_published.frc" + ], + ) + ) + + result = get_force_field_file( + "compass", + lunar_location=lunar_root, + ) + + assert result.name == ( + "compass_published.frc" + ) + + +@pytest.mark.parametrize( + "force_field", + [ + "COMPASS", + "Compass", + "pcff", + "Pcff", + "cvff", + "dreiding", + ], +) +def test_force_field_names_are_currently_case_sensitive( + force_field, +): + """ + Characterizes the current locator contract. + + Do not silently change this test into case-insensitive behavior unless + force-field normalization is deliberately moved into this function. + """ + with pytest.raises( + ValueError, + match="Unsupported force field requested", + ): + get_force_field_file( + force_field + ) + + +def test_leading_or_trailing_whitespace_is_not_normalized(): + with pytest.raises( + ValueError, + match="Unsupported force field requested", + ): + get_force_field_file( + " PCFF " + ) + + +# ============================================================================= +# Foyer placeholders +# ============================================================================= + + +@pytest.mark.parametrize( + "force_field", + [ + "OPLSAA", + "GAFF", + ], +) +def test_foyer_force_fields_are_explicitly_not_implemented( + force_field, +): + with pytest.raises( + NotImplementedError, + match="support is currently in development", + ) as exc_info: + get_force_field_file( + force_field + ) + + assert force_field in str( + exc_info.value + ) + + +def test_foyer_placeholder_does_not_need_lunar_location(): + with pytest.raises( + NotImplementedError + ): + get_force_field_file( + force_field="OPLSAA", + lunar_location=None, + ) + + +# ============================================================================= +# Unsupported force fields +# ============================================================================= + + +@pytest.mark.parametrize( + "force_field", + [ + "AMBER", + "CHARMM", + "UFF", + "MMFF94", + "", + "unknown", + ], +) +def test_unsupported_force_field_raises_value_error( + force_field, +): + with pytest.raises( + ValueError, + match="Unsupported force field requested", + ) as exc_info: + get_force_field_file( + force_field + ) + + assert repr( + force_field + ).strip("'") in str( + exc_info.value + ) or force_field == "" + + +def test_unsupported_error_includes_requested_force_field(): + with pytest.raises( + ValueError + ) as exc_info: + get_force_field_file( + "NOT_A_FORCE_FIELD" + ) + + assert ( + "NOT_A_FORCE_FIELD" + in str( + exc_info.value + ) + ) + + +# ============================================================================= +# Path/layout contract +# ============================================================================= + + +def test_external_force_fields_are_expected_under_frc_files( + tmp_path, + monkeypatch, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + lunar_root = ( + tmp_path / "LUNAR" + ) + + lunar_root.mkdir() + + # Correct filename, deliberately placed in the WRONG directory. + ( + lunar_root + / "cvff.frc" + ).write_text( + "wrong location", + encoding="utf-8", + ) + + with pytest.raises( + ValueError, + match="Force field file not found", + ): + get_force_field_file( + force_field="CVFF", + lunar_location=lunar_root, + ) + + +def test_directory_named_like_force_field_file_is_rejected( + tmp_path, + monkeypatch, +): + package_root = ( + make_fake_internal_ff_tree( + tmp_path + ) + ) + + patch_internal_package_root( + monkeypatch, + package_root, + ) + + lunar_root = ( + make_fake_lunar( + tmp_path + ) + ) + + fake_file_as_directory = ( + lunar_root + / "frc_files" + / "cvff.frc" + ) + + fake_file_as_directory.mkdir() + + with pytest.raises( + ValueError, + match="Force field file not found", + ): + get_force_field_file( + force_field="CVFF", + lunar_location=lunar_root, + ) \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/test_ff_validator.py b/tests/unit/reaction_preparation/ff_wrapper/test_ff_validator.py new file mode 100644 index 00000000..7bf41cb8 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/test_ff_validator.py @@ -0,0 +1,1273 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER.reaction_preparation.ff_wrapper.ff_validator as ff_validator +from AutoREACTER.reaction_preparation.ff_wrapper.ff_validator import ( + FFValidator, + ForceFieldValidationError, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_ff_files( + ff_file: Path, +): + return SimpleNamespace( + force_field_data=ff_file, + ) + + +def write_force_field( + path: Path, + text: str, +) -> Path: + path.write_text( + text, + encoding="utf-8", + ) + + return path + + +def make_uninitialized_validator( + ff_file=None, +): + """ + Construct FFValidator without calling __init__/validate. + + Useful for testing the helper methods independently. + """ + validator = object.__new__( + FFValidator + ) + + validator.ff_file = ff_file + + if ff_file is not None: + validator.ff_files = ( + make_ff_files( + ff_file + ) + ) + + return validator + + +# ============================================================================= +# Exception type +# ============================================================================= + + +def test_force_field_validation_error_is_exception(): + assert issubclass( + ForceFieldValidationError, + Exception, + ) + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_ff_files_and_force_field_path( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_files = make_ff_files( + ff_file + ) + + calls = [] + + monkeypatch.setattr( + FFValidator, + "validate", + lambda self: + ( + calls.append(self) + or True + ), + ) + + validator = FFValidator( + ff_files + ) + + assert ( + validator.ff_files + is ff_files + ) + + assert ( + validator.ff_file + == ff_file + ) + + assert calls == [ + validator + ] + + +def test_constructor_validates_immediately( + tmp_path, +): + missing = ( + tmp_path + / "missing.data" + ) + + with pytest.raises( + ForceFieldValidationError, + match="File not found", + ): + FFValidator( + make_ff_files( + missing + ) + ) + + +# ============================================================================= +# validate - file existence +# ============================================================================= + + +def test_validate_missing_file_raises( + tmp_path, +): + missing = ( + tmp_path + / "missing.data" + ) + + validator = ( + make_uninitialized_validator( + missing + ) + ) + + with pytest.raises( + ForceFieldValidationError, + match="File not found", + ) as exc_info: + validator.validate() + + assert str( + missing + ) in str( + exc_info.value + ) + + +def test_validate_existing_valid_file_returns_true( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + """ +Pair Coeffs + +1 0.100 3.500 +2 0.200 4.000 + +""", + ) + + validator = FFValidator( + make_ff_files( + ff_file + ) + ) + + assert ( + validator.validate() + is True + ) + + +# ============================================================================= +# validate - current section-presence behavior +# ============================================================================= + + +def test_validate_empty_file_currently_returns_true( + tmp_path, +): + """ + Characterization test. + + Although the class documentation says required section labels + are checked, the current implementation skips any section that + is absent. + """ + ff_file = write_force_field( + tmp_path / "empty.data", + "", + ) + + validator = FFValidator( + make_ff_files( + ff_file + ) + ) + + assert ( + validator.validate() + is True + ) + + +def test_validate_file_with_no_recognized_sections_currently_returns_true( + tmp_path, +): + """ + Characterizes the current implementation: + unrecognized/missing coefficient sections are ignored. + """ + ff_file = write_force_field( + tmp_path / "other.data", + """ +Masses + +1 12.011 +2 1.008 + +Atoms + +1 1 1 0.0 0.0 0.0 0.0 +""", + ) + + validator = FFValidator( + make_ff_files( + ff_file + ) + ) + + assert ( + validator.validate() + is True + ) + + +def test_validate_missing_some_coeff_sections_are_skipped( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "partial.data", + """ +Bond Coeffs + +1 100.0 1.5 +2 200.0 1.4 + +""", + ) + + validator = FFValidator( + make_ff_files( + ff_file + ) + ) + + assert ( + validator.validate() + is True + ) + + +@pytest.mark.parametrize( + "section_name", + [ + "Pair Coeffs", + "Bond Coeffs", + "Angle Coeffs", + "Dihedral Coeffs", + ], +) +def test_validate_recognizes_each_supported_section( + tmp_path, + section_name, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + f""" +{section_name} + +1 1.0 2.0 +2 3.0 4.0 + +""", + ) + + validator = FFValidator( + make_ff_files( + ff_file + ) + ) + + assert ( + validator.validate() + is True + ) + + +# ============================================================================= +# find_section_start +# ============================================================================= + + +def test_find_section_start_returns_correct_index(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "LAMMPS data file\n", + "\n", + "Masses\n", + "\n", + "Pair Coeffs\n", + "\n", + ] + + assert ( + validator.find_section_start( + lines, + "Pair Coeffs", + ) + == 4 + ) + + +def test_find_section_start_returns_none_when_absent(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "Masses\n", + "Atoms\n", + "Bonds\n", + ] + + assert ( + validator.find_section_start( + lines, + "Pair Coeffs", + ) + is None + ) + + +def test_find_section_start_uses_substring_matching(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "Pair Coeffs # class2\n", + ] + + assert ( + validator.find_section_start( + lines, + "Pair Coeffs", + ) + == 0 + ) + + +def test_find_section_start_returns_first_match(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "Pair Coeffs\n", + "\n", + "Pair Coeffs\n", + ] + + assert ( + validator.find_section_start( + lines, + "Pair Coeffs", + ) + == 0 + ) + + +def test_find_section_start_is_case_sensitive(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "pair coeffs\n", + ] + + assert ( + validator.find_section_start( + lines, + "Pair Coeffs", + ) + is None + ) + + +# ============================================================================= +# find_data_block +# ============================================================================= + + +def test_find_data_block_skips_blank_lines_after_header(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "Pair Coeffs\n", + "\n", + "\n", + "1 0.1 3.5\n", + "2 0.2 4.0\n", + "\n", + "Bond Coeffs\n", + ] + + result = ( + validator.find_data_block( + lines, + 0, + ) + ) + + assert result == ( + 3, + 5, + ) + + +def test_find_data_block_stops_at_first_blank_line(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "Pair Coeffs\n", + "\n", + "1 0.1 3.5\n", + "2 0.2 4.0\n", + "\n", + "3 0.3 5.0\n", + ] + + result = ( + validator.find_data_block( + lines, + 0, + ) + ) + + assert result == ( + 2, + 4, + ) + + +def test_find_data_block_can_end_at_eof(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "Bond Coeffs\n", + "\n", + "1 100.0 1.5\n", + "2 200.0 1.4\n", + ] + + result = ( + validator.find_data_block( + lines, + 0, + ) + ) + + assert result == ( + 2, + 4, + ) + + +def test_find_data_block_empty_after_header_returns_eof_indexes(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "Angle Coeffs\n", + "\n", + "\n", + ] + + result = ( + validator.find_data_block( + lines, + 0, + ) + ) + + assert result == ( + 3, + 3, + ) + + +# ============================================================================= +# check_coefficients - valid input +# ============================================================================= + + +def test_check_coefficients_single_valid_row(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 0.100 3.500\n", + ] + + assert ( + validator.check_coefficients( + start_line=0, + end_line=1, + lines=lines, + section_name="Pair Coeffs", + ) + is True + ) + + +def test_check_coefficients_multiple_rows_same_count(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 0.100 3.500\n", + "2 0.200 4.000\n", + "3 0.300 4.500\n", + ] + + assert ( + validator.check_coefficients( + start_line=0, + end_line=3, + lines=lines, + section_name="Pair Coeffs", + ) + is True + ) + + +def test_check_coefficients_accepts_negative_values(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 -1.25 2.50 -0.75\n", + "2 1.25 -2.50 0.75\n", + ] + + assert ( + validator.check_coefficients( + 0, + 2, + lines, + "Dihedral Coeffs", + ) + is True + ) + + +def test_check_coefficients_accepts_scientific_notation(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 1.0e-4 2.5E+2\n", + "2 -3.0e-5 4.0E-1\n", + ] + + assert ( + validator.check_coefficients( + 0, + 2, + lines, + "Pair Coeffs", + ) + is True + ) + + +def test_check_coefficients_accepts_zero_values_when_row_not_all_zero(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 0.0 0.0 1.5 0.0\n", + ] + + assert ( + validator.check_coefficients( + 0, + 1, + lines, + "Dihedral Coeffs", + ) + is True + ) + + +def test_check_coefficients_ignores_inline_comments(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 0.100 3.500 # carbon\n", + "2 0.200 4.000 # hydrogen\n", + ] + + assert ( + validator.check_coefficients( + 0, + 2, + lines, + "Pair Coeffs", + ) + is True + ) + + +def test_check_coefficients_ignores_full_comment_lines_inside_block(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "# comment only\n", + "1 10.0 1.5\n", + "# another comment\n", + "2 20.0 1.4\n", + ] + + assert ( + validator.check_coefficients( + 0, + 4, + lines, + "Bond Coeffs", + ) + is True + ) + + +def test_check_coefficients_currently_does_not_validate_type_identifier(): + """ + Characterization test. + + values[0] is treated as the type identifier, but current production + code only converts values[1:] to floats. + """ + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "not_an_integer 1.0 2.0\n", + "another_id 3.0 4.0\n", + ] + + assert ( + validator.check_coefficients( + 0, + 2, + lines, + "Pair Coeffs", + ) + is True + ) + + +# ============================================================================= +# check_coefficients - dynamic coefficient count +# ============================================================================= + + +def test_first_data_row_sets_expected_coefficient_count(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 1.0 2.0 3.0 4.0\n", + "2 5.0 6.0 7.0 8.0\n", + ] + + assert ( + validator.check_coefficients( + 0, + 2, + lines, + "Dihedral Coeffs", + ) + is True + ) + + +def test_inconsistent_coefficient_count_raises(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 1.0 2.0 3.0\n", + "2 4.0 5.0\n", + ] + + with pytest.raises( + ForceFieldValidationError, + match="Inconsistent data", + ) as exc_info: + validator.check_coefficients( + 0, + 2, + lines, + "Angle Coeffs", + ) + + message = str( + exc_info.value + ) + + assert ( + "Expected 3 coefficients" + in message + ) + + assert ( + "found 2" + in message + ) + + +def test_inconsistent_coefficient_error_includes_section_name(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 1.0 2.0\n", + "2 3.0\n", + ] + + with pytest.raises( + ForceFieldValidationError + ) as exc_info: + validator.check_coefficients( + 0, + 2, + lines, + "Bond Coeffs", + ) + + assert ( + "Bond Coeffs" + in str( + exc_info.value + ) + ) + + +def test_comment_does_not_affect_dynamic_coefficient_count(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "# ignored comment\n", + "1 1.0 2.0 3.0\n", + "2 4.0 5.0 6.0\n", + ] + + assert ( + validator.check_coefficients( + 0, + 3, + lines, + "Angle Coeffs", + ) + is True + ) + + +# ============================================================================= +# check_coefficients - non-numeric values +# ============================================================================= + + +def test_non_numeric_coefficient_raises(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 1.0 not-a-number 3.0\n", + ] + + with pytest.raises( + ForceFieldValidationError, + match="Non-numeric data", + ): + validator.check_coefficients( + 0, + 1, + lines, + "Angle Coeffs", + ) + + +def test_non_numeric_error_includes_section_name(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "1 1.0 BAD\n", + ] + + with pytest.raises( + ForceFieldValidationError + ) as exc_info: + validator.check_coefficients( + 0, + 1, + lines, + "Pair Coeffs", + ) + + assert ( + "Pair Coeffs" + in str( + exc_info.value + ) + ) + + +def test_non_numeric_error_reports_one_based_line_number(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "header\n", + "ignored\n", + "1 1.0 2.0\n", + "2 BAD 4.0\n", + ] + + with pytest.raises( + ForceFieldValidationError + ) as exc_info: + validator.check_coefficients( + start_line=2, + end_line=4, + lines=lines, + section_name="Pair Coeffs", + ) + + assert ( + "line 4" + in str( + exc_info.value + ) + ) + + +# ============================================================================= +# check_coefficients - all-zero rows +# ============================================================================= + + +@pytest.mark.parametrize( + "line", + [ + "1 0.0\n", + "1 0 0\n", + "1 0.000000 0.000000 0.000000\n", + "1 -0.0 0.0\n", + ], +) +def test_all_zero_coefficients_raise( + line, +): + validator = ( + make_uninitialized_validator() + ) + + with pytest.raises( + ForceFieldValidationError, + match="All zeros", + ): + validator.check_coefficients( + 0, + 1, + [ + line + ], + "Pair Coeffs", + ) + + +def test_all_zero_error_includes_section_name(): + validator = ( + make_uninitialized_validator() + ) + + with pytest.raises( + ForceFieldValidationError + ) as exc_info: + validator.check_coefficients( + 0, + 1, + [ + "1 0.0 0.0\n" + ], + "Dihedral Coeffs", + ) + + assert ( + "Dihedral Coeffs" + in str( + exc_info.value + ) + ) + + +def test_all_zero_error_includes_original_row(): + validator = ( + make_uninitialized_validator() + ) + + line = ( + "7 0.000 0.000 0.000 # test type\n" + ) + + with pytest.raises( + ForceFieldValidationError + ) as exc_info: + validator.check_coefficients( + 0, + 1, + [ + line + ], + "Angle Coeffs", + ) + + assert ( + "7 0.000 0.000 0.000" + in str( + exc_info.value + ) + ) + + +# ============================================================================= +# check_coefficients - no usable data +# ============================================================================= + + +def test_empty_data_block_raises_no_data(): + validator = ( + make_uninitialized_validator() + ) + + with pytest.raises( + ForceFieldValidationError, + match="No data found in section Pair Coeffs", + ): + validator.check_coefficients( + 0, + 0, + [], + "Pair Coeffs", + ) + + +def test_comment_only_block_raises_no_data(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + "# comment one\n", + "# comment two\n", + ] + + with pytest.raises( + ForceFieldValidationError, + match="No data found in section Bond Coeffs", + ): + validator.check_coefficients( + 0, + 2, + lines, + "Bond Coeffs", + ) + + +def test_whitespace_and_comments_only_raise_no_data(): + validator = ( + make_uninitialized_validator() + ) + + lines = [ + " # comment\n", + " \n", + "# another\n", + ] + + with pytest.raises( + ForceFieldValidationError, + match="No data found", + ): + validator.check_coefficients( + 0, + 3, + lines, + "Angle Coeffs", + ) + + +# ============================================================================= +# validate - full section integration +# ============================================================================= + + +def test_validate_checks_multiple_coefficient_sections( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + """ +Pair Coeffs + +1 0.10 3.50 +2 0.20 4.00 + +Bond Coeffs + +1 300.0 1.50 +2 250.0 1.40 + +Angle Coeffs + +1 50.0 109.5 +2 60.0 120.0 + +Dihedral Coeffs + +1 1.0 2.0 3.0 +2 4.0 5.0 6.0 + +""", + ) + + validator = FFValidator( + make_ff_files( + ff_file + ) + ) + + assert ( + validator.validate() + is True + ) + + +def test_validate_invalid_later_section_still_raises( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + """ +Pair Coeffs + +1 0.10 3.50 +2 0.20 4.00 + +Bond Coeffs + +1 300.0 1.50 +2 0.0 0.0 + +""", + ) + + with pytest.raises( + ForceFieldValidationError, + match="All zeros", + ): + FFValidator( + make_ff_files( + ff_file + ) + ) + + +def test_validate_section_with_no_data_raises( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + """ +Pair Coeffs + + +""", + ) + + with pytest.raises( + ForceFieldValidationError, + match="No data found in section Pair Coeffs", + ): + FFValidator( + make_ff_files( + ff_file + ) + ) + + +def test_validate_inconsistent_rows_in_file_raises( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + """ +Angle Coeffs + +1 50.0 109.5 2.0 +2 60.0 120.0 + +""", + ) + + with pytest.raises( + ForceFieldValidationError, + match="Inconsistent data", + ): + FFValidator( + make_ff_files( + ff_file + ) + ) + + +def test_validate_non_numeric_file_data_raises( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + """ +Bond Coeffs + +1 300.0 1.50 +2 WRONG 1.40 + +""", + ) + + with pytest.raises( + ForceFieldValidationError, + match="Non-numeric data", + ): + FFValidator( + make_ff_files( + ff_file + ) + ) + + +# ============================================================================= +# Comments / LAMMPS-style headers +# ============================================================================= + + +def test_validate_class2_section_header_comment( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + """ +Dihedral Coeffs # class2 + +1 0.0 0.0 0.0514 0.0 -0.143 0.0 +2 0.0 0.0 0.0316 0.0 -0.1681 0.0 + +""", + ) + + validator = FFValidator( + make_ff_files( + ff_file + ) + ) + + assert ( + validator.validate() + is True + ) + + +def test_validate_inline_atom_type_comments_do_not_count_as_coefficients( + tmp_path, +): + ff_file = write_force_field( + tmp_path / "force_field.data", + """ +Pair Coeffs + +1 0.0540 4.0100 # c1 +2 0.0640 3.8540 # c2 + +""", + ) + + validator = FFValidator( + make_ff_files( + ff_file + ) + ) + + assert ( + validator.validate() + is True + ) \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/test_ff_wrapper.py b/tests/unit/reaction_preparation/ff_wrapper/test_ff_wrapper.py new file mode 100644 index 00000000..9de21777 --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/test_ff_wrapper.py @@ -0,0 +1,1156 @@ +import sys +from pathlib import Path +from types import ModuleType, SimpleNamespace + +import pytest + +from AutoREACTER.reaction_preparation.ff_wrapper.ff_wrapper import ( + DataFiles, + FFFiles, + FFWrapper, + MoleculeFile, + TemplateFile, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_session( + *, + force_field="PCFF", + reaction_metadata=None, +): + inputs = SimpleNamespace( + force_field=force_field, + ) + + return SimpleNamespace( + inputs=inputs, + reaction_metadata=( + [] + if reaction_metadata is None + else reaction_metadata + ), + ff_files=None, + ) + + +def install_fake_lunar_wrapper( + monkeypatch, + *, + final_files="lunar-final-files", + events=None, +): + """ + Install a fake module for the lazy import performed inside + FFWrapper.generate_force_field_files(). + """ + module_name = ( + "AutoREACTER.reaction_preparation." + "ff_wrapper.lunar_client.lunar_api_wrapper" + ) + + fake_module = ModuleType( + module_name + ) + + class FakeLunarAPIWrapper: + def __init__( + self, + ARX, + ): + self.ARX = ARX + + if events is not None: + events.append( + ( + "lunar-init", + ARX, + ) + ) + + def lunar_workflow( + self, + updated_inputs, + prepared_reactions, + ): + if events is not None: + events.append( + ( + "lunar-workflow", + updated_inputs, + prepared_reactions, + ) + ) + + return final_files + + fake_module.LunarAPIWrapper = ( + FakeLunarAPIWrapper + ) + + monkeypatch.setitem( + sys.modules, + module_name, + fake_module, + ) + + return FakeLunarAPIWrapper + + +def install_fake_foyer_wrapper( + monkeypatch, + *, + final_files="foyer-final-files", + events=None, +): + """ + Install a fake module for the current lazy Foyer routing branch. + + This does NOT claim Foyer support is functional. It only + characterizes the current FFWrapper routing behavior. + """ + module_name = ( + "AutoREACTER.reaction_preparation." + "ff_wrapper.foyer_client.foyer_api_wrapper" + ) + + fake_module = ModuleType( + module_name + ) + + class FakeFoyerAPIWrapper: + def __init__( + self, + ARX, + prepared_reactions_with_3d_mols, + ): + self.ARX = ARX + self.prepared_reactions = ( + prepared_reactions_with_3d_mols + ) + + self.final_foyer_files = ( + final_files + ) + + if events is not None: + events.append( + ( + "foyer-init", + ARX, + prepared_reactions_with_3d_mols, + ) + ) + + fake_module.FoyerAPIWrapper = ( + FakeFoyerAPIWrapper + ) + + monkeypatch.setitem( + sys.modules, + module_name, + fake_module, + ) + + return FakeFoyerAPIWrapper + + +# ============================================================================= +# DataFiles +# ============================================================================= + + +def test_data_files_stores_paths( + tmp_path, +): + data_file = ( + tmp_path / "system.data" + ) + + molecule_file = ( + tmp_path / "system.lmpmol" + ) + + result = DataFiles( + data_file=data_file, + lmp_molecule_file=molecule_file, + ) + + assert result.data_file == ( + data_file + ) + + assert ( + result.lmp_molecule_file + == molecule_file + ) + + +def test_data_files_uses_slots( + tmp_path, +): + result = DataFiles( + data_file=( + tmp_path / "a.data" + ), + lmp_molecule_file=( + tmp_path / "a.lmpmol" + ), + ) + + with pytest.raises( + AttributeError + ): + result.extra = 1 + + +# ============================================================================= +# MoleculeFile +# ============================================================================= + + +def test_molecule_file_stores_data_files( + tmp_path, +): + files = DataFiles( + data_file=( + tmp_path / "mma.data" + ), + lmp_molecule_file=( + tmp_path / "mma.lmpmol" + ), + ) + + result = MoleculeFile( + id="mma", + molecule_files=files, + ) + + assert result.id == "mma" + + assert ( + result.molecule_files + is files + ) + + +def test_molecule_file_accepts_none(): + result = MoleculeFile( + id="mma", + molecule_files=None, + ) + + assert ( + result.molecule_files + is None + ) + + +def test_molecule_file_uses_slots(): + result = MoleculeFile( + id="mma", + molecule_files=None, + ) + + with pytest.raises( + AttributeError + ): + result.extra = 1 + + +# ============================================================================= +# TemplateFile +# ============================================================================= + + +def test_template_file_stores_pre_and_post( + tmp_path, +): + pre = DataFiles( + data_file=( + tmp_path / "pre.data" + ), + lmp_molecule_file=( + tmp_path / "pre.lmpmol" + ), + ) + + post = DataFiles( + data_file=( + tmp_path / "post.data" + ), + lmp_molecule_file=( + tmp_path / "post.lmpmol" + ), + ) + + result = TemplateFile( + reaction_id=7, + pre_reaction_file=pre, + post_reaction_file=post, + ) + + assert result.reaction_id == 7 + + assert ( + result.pre_reaction_file + is pre + ) + + assert ( + result.post_reaction_file + is post + ) + + +def test_template_file_accepts_optional_values(): + result = TemplateFile( + reaction_id=None, + pre_reaction_file=None, + post_reaction_file=None, + ) + + assert result.reaction_id is None + assert result.pre_reaction_file is None + assert result.post_reaction_file is None + + +def test_template_file_uses_slots(): + result = TemplateFile( + reaction_id=None, + pre_reaction_file=None, + post_reaction_file=None, + ) + + with pytest.raises( + AttributeError + ): + result.extra = 1 + + +# ============================================================================= +# FFFiles +# ============================================================================= + + +def test_ff_files_stores_complete_output( + tmp_path, +): + molecule = MoleculeFile( + id="mma", + molecule_files=None, + ) + + template = TemplateFile( + reaction_id=1, + pre_reaction_file=None, + post_reaction_file=None, + ) + + result = FFFiles( + molecule_files=[ + molecule + ], + template_files=[ + template + ], + force_field_data=( + tmp_path + / "force_field.data" + ), + in_file=( + tmp_path + / "in.create_atoms.script" + ), + ) + + assert result.molecule_files == [ + molecule + ] + + assert result.template_files == [ + template + ] + + assert result.force_field_data == ( + tmp_path + / "force_field.data" + ) + + assert result.in_file == ( + tmp_path + / "in.create_atoms.script" + ) + + +def test_ff_files_in_file_defaults_none( + tmp_path, +): + result = FFFiles( + molecule_files=[], + template_files=[], + force_field_data=( + tmp_path / "ff.data" + ), + ) + + assert result.in_file is None + + +def test_ff_files_uses_slots( + tmp_path, +): + result = FFFiles( + molecule_files=[], + template_files=[], + force_field_data=( + tmp_path / "ff.data" + ), + ) + + with pytest.raises( + AttributeError + ): + result.extra = 1 + + +# ============================================================================= +# FFWrapper constructor +# ============================================================================= + + +def test_ff_wrapper_constructor_stores_session(): + session = make_session() + + wrapper = FFWrapper( + session + ) + + assert wrapper.session is session + + +def test_ff_wrapper_constructor_stores_inputs(): + session = make_session( + force_field="CVFF" + ) + + wrapper = FFWrapper( + session + ) + + assert ( + wrapper.inputs + is session.inputs + ) + + +# ============================================================================= +# LUNAR routing +# ============================================================================= + + +@pytest.mark.parametrize( + "force_field", + [ + "PCFF", + "PCFF-IFF", + "compass", + "CVFF", + "CVFF-IFF", + "DREIDING", + "Clay-FF", + ], +) +def test_supported_lunar_names_route_to_lunar( + monkeypatch, + capsys, + force_field, +): + session = make_session( + force_field=force_field, + ) + + events = [] + + install_fake_lunar_wrapper( + monkeypatch, + final_files="LUNAR_RESULT", + events=events, + ) + + wrapper = FFWrapper( + session + ) + + result = ( + wrapper + .generate_force_field_files( + session + ) + ) + + assert result is None + + assert ( + session.ff_files + == "LUNAR_RESULT" + ) + + assert events[0] == ( + "lunar-init", + session, + ) + + assert events[1] == ( + "lunar-workflow", + session.inputs, + session.reaction_metadata, + ) + + assert ( + f"Routing to LUNAR for force field: {force_field}" + in capsys.readouterr().out + ) + + +def test_lunar_wrapper_receives_original_wrapper_session( + monkeypatch, +): + original_session = ( + make_session( + force_field="PCFF" + ) + ) + + passed_session = ( + make_session( + force_field="CVFF" + ) + ) + + events = [] + + install_fake_lunar_wrapper( + monkeypatch, + events=events, + ) + + wrapper = FFWrapper( + original_session + ) + + wrapper.generate_force_field_files( + passed_session + ) + + # Characterizes current implementation: + # + # routing decisions and workflow arguments come from + # the method's session, but LunarAPIWrapper is + # constructed using self.session from FFWrapper.__init__. + assert events[0] == ( + "lunar-init", + original_session, + ) + + assert events[1] == ( + "lunar-workflow", + passed_session.inputs, + passed_session.reaction_metadata, + ) + + +def test_lunar_result_is_written_to_passed_session( + monkeypatch, +): + original_session = ( + make_session( + force_field="PCFF" + ) + ) + + passed_session = ( + make_session( + force_field="CVFF" + ) + ) + + original_session.ff_files = ( + "ORIGINAL" + ) + + install_fake_lunar_wrapper( + monkeypatch, + final_files="NEW_FILES", + ) + + wrapper = FFWrapper( + original_session + ) + + wrapper.generate_force_field_files( + passed_session + ) + + assert ( + passed_session.ff_files + == "NEW_FILES" + ) + + # Current behavior: result is assigned to the + # session passed to generate_force_field_files(). + assert ( + original_session.ff_files + == "ORIGINAL" + ) + + +# ============================================================================= +# Force-field fallback +# ============================================================================= + + +def test_none_force_field_falls_back_to_pcff( + monkeypatch, + capsys, +): + session = make_session( + force_field=None, + ) + + install_fake_lunar_wrapper( + monkeypatch, + final_files="PCFF_RESULT", + ) + + wrapper = FFWrapper( + session + ) + + wrapper.generate_force_field_files( + session + ) + + assert ( + session.ff_files + == "PCFF_RESULT" + ) + + assert ( + "Routing to LUNAR for force field: PCFF" + in capsys.readouterr().out + ) + + +def test_empty_force_field_falls_back_to_pcff( + monkeypatch, +): + session = make_session( + force_field="", + ) + + install_fake_lunar_wrapper( + monkeypatch, + final_files="PCFF_RESULT", + ) + + wrapper = FFWrapper( + session + ) + + wrapper.generate_force_field_files( + session + ) + + assert ( + session.ff_files + == "PCFF_RESULT" + ) + + +# ============================================================================= +# session.inputs fallback +# ============================================================================= + + +def test_missing_passed_session_inputs_falls_back_to_wrapper_inputs( + monkeypatch, +): + original_session = ( + make_session( + force_field="PCFF" + ) + ) + + passed_session = SimpleNamespace( + inputs=None, + reaction_metadata=[], + ff_files=None, + ) + + events = [] + + install_fake_lunar_wrapper( + monkeypatch, + final_files="RESULT", + events=events, + ) + + wrapper = FFWrapper( + original_session + ) + + wrapper.generate_force_field_files( + passed_session + ) + + assert ( + passed_session.ff_files + == "RESULT" + ) + + assert events[1] == ( + "lunar-workflow", + original_session.inputs, + passed_session.reaction_metadata, + ) + + +def test_both_input_sources_none_raises(): + original_session = SimpleNamespace( + inputs=None, + ) + + passed_session = SimpleNamespace( + inputs=None, + reaction_metadata=[], + ff_files=None, + ) + + wrapper = FFWrapper( + original_session + ) + + with pytest.raises( + ValueError, + match=( + "No inputs provided to FFWrapper " + "and session inputs are None" + ), + ): + wrapper.generate_force_field_files( + passed_session + ) + + +# ============================================================================= +# Reaction metadata forwarding +# ============================================================================= + + +def test_reaction_metadata_is_forwarded_to_lunar( + monkeypatch, +): + reactions = [ + object(), + object(), + object(), + ] + + session = make_session( + force_field="PCFF", + reaction_metadata=reactions, + ) + + events = [] + + install_fake_lunar_wrapper( + monkeypatch, + events=events, + ) + + wrapper = FFWrapper( + session + ) + + wrapper.generate_force_field_files( + session + ) + + assert events[1][2] is reactions + + +# ============================================================================= +# Foyer routing - current behavior only +# ============================================================================= + + +@pytest.mark.parametrize( + "force_field", + [ + "OPLSAA", + "GAFF", + ], +) +def test_current_foyer_names_route_to_foyer( + monkeypatch, + capsys, + force_field, +): + """ + Characterization only. + + AutoREACTER currently marks Foyer force-field lookup as + not implemented, but FFWrapper still contains a routing + branch for OPLSAA and GAFF. + + This test does NOT claim Foyer works. + """ + reactions = [ + object(), + ] + + session = make_session( + force_field=force_field, + reaction_metadata=reactions, + ) + + events = [] + + install_fake_foyer_wrapper( + monkeypatch, + final_files="FOYER_RESULT", + events=events, + ) + + wrapper = FFWrapper( + session + ) + + result = ( + wrapper + .generate_force_field_files( + session + ) + ) + + assert result is None + + assert ( + session.ff_files + == "FOYER_RESULT" + ) + + assert events == [ + ( + "foyer-init", + session, + reactions, + ) + ] + + assert ( + f"Routing to Foyer for force field: {force_field}" + in capsys.readouterr().out + ) + + +# ============================================================================= +# Unsupported force fields +# ============================================================================= + + +@pytest.mark.parametrize( + "force_field", + [ + "AMBER", + "CHARMM", + "UFF", + "MMFF94", + "UNKNOWN", + "pcff", + "cvff", + "COMPASS", + ], +) +def test_unrecognized_force_field_raises( + force_field, +): + session = make_session( + force_field=force_field, + ) + + wrapper = FFWrapper( + session + ) + + with pytest.raises( + ValueError, + match=( + "Unsupported or unrecognized " + "force field requested" + ), + ) as exc_info: + wrapper.generate_force_field_files( + session + ) + + assert force_field in str( + exc_info.value + ) + + +def test_unsupported_force_field_does_not_change_ff_files(): + session = make_session( + force_field="UNKNOWN", + ) + + session.ff_files = ( + "existing-files" + ) + + wrapper = FFWrapper( + session + ) + + with pytest.raises( + ValueError + ): + wrapper.generate_force_field_files( + session + ) + + assert ( + session.ff_files + == "existing-files" + ) + + +# ============================================================================= +# Backend failure propagation +# ============================================================================= + + +def test_lunar_constructor_failure_propagates( + monkeypatch, +): + session = make_session( + force_field="PCFF" + ) + + module_name = ( + "AutoREACTER.reaction_preparation." + "ff_wrapper.lunar_client.lunar_api_wrapper" + ) + + fake_module = ModuleType( + module_name + ) + + class FailingLunarAPIWrapper: + def __init__( + self, + ARX, + ): + raise RuntimeError( + "LUNAR init failed" + ) + + fake_module.LunarAPIWrapper = ( + FailingLunarAPIWrapper + ) + + monkeypatch.setitem( + sys.modules, + module_name, + fake_module, + ) + + wrapper = FFWrapper( + session + ) + + with pytest.raises( + RuntimeError, + match="LUNAR init failed", + ): + wrapper.generate_force_field_files( + session + ) + + +def test_lunar_workflow_failure_propagates( + monkeypatch, +): + session = make_session( + force_field="PCFF" + ) + + module_name = ( + "AutoREACTER.reaction_preparation." + "ff_wrapper.lunar_client.lunar_api_wrapper" + ) + + fake_module = ModuleType( + module_name + ) + + class FailingLunarAPIWrapper: + def __init__( + self, + ARX, + ): + pass + + def lunar_workflow( + self, + updated_inputs, + prepared_reactions, + ): + raise RuntimeError( + "LUNAR workflow failed" + ) + + fake_module.LunarAPIWrapper = ( + FailingLunarAPIWrapper + ) + + monkeypatch.setitem( + sys.modules, + module_name, + fake_module, + ) + + wrapper = FFWrapper( + session + ) + + with pytest.raises( + RuntimeError, + match="LUNAR workflow failed", + ): + wrapper.generate_force_field_files( + session + ) + + +def test_backend_failure_does_not_replace_existing_ff_files( + monkeypatch, +): + session = make_session( + force_field="PCFF" + ) + + session.ff_files = ( + "old-files" + ) + + module_name = ( + "AutoREACTER.reaction_preparation." + "ff_wrapper.lunar_client.lunar_api_wrapper" + ) + + fake_module = ModuleType( + module_name + ) + + class FailingLunarAPIWrapper: + def __init__( + self, + ARX, + ): + pass + + def lunar_workflow( + self, + updated_inputs, + prepared_reactions, + ): + raise RuntimeError( + "failure" + ) + + fake_module.LunarAPIWrapper = ( + FailingLunarAPIWrapper + ) + + monkeypatch.setitem( + sys.modules, + module_name, + fake_module, + ) + + wrapper = FFWrapper( + session + ) + + with pytest.raises( + RuntimeError + ): + wrapper.generate_force_field_files( + session + ) + + assert ( + session.ff_files + == "old-files" + ) + + +# ============================================================================= +# Return contract +# ============================================================================= + + +def test_generate_force_field_files_returns_none_on_lunar_success( + monkeypatch, +): + session = make_session( + force_field="PCFF" + ) + + install_fake_lunar_wrapper( + monkeypatch + ) + + wrapper = FFWrapper( + session + ) + + result = ( + wrapper + .generate_force_field_files( + session + ) + ) + + assert result is None + + +def test_generate_force_field_files_returns_none_on_current_foyer_branch( + monkeypatch, +): + session = make_session( + force_field="GAFF" + ) + + install_fake_foyer_wrapper( + monkeypatch + ) + + wrapper = FFWrapper( + session + ) + + result = ( + wrapper + .generate_force_field_files( + session + ) + ) + + assert result is None \ No newline at end of file diff --git a/tests/unit/reaction_preparation/ff_wrapper/test_modifiers_molecule_files.py b/tests/unit/reaction_preparation/ff_wrapper/test_modifiers_molecule_files.py new file mode 100644 index 00000000..82be5e8c --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/test_modifiers_molecule_files.py @@ -0,0 +1,1717 @@ +import pandas as pd +import pytest + +from AutoREACTER.reaction_preparation.ff_wrapper.modifiers_molecule_files import ( + modify_angles, + modify_bonds, + modify_charges, + modify_coords, + modify_dihedrals, + modify_impropers, + modify_types, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_type_df( + mapping, +): + """ + Build the minimal type DataFrame required by topology modifiers. + + mapping: + { + old_atom_index: new_atom_index, + ... + } + """ + return pd.DataFrame( + { + "atom_index": list( + mapping.keys() + ), + "new_atom_index": list( + mapping.values() + ), + } + ) + + +# ============================================================================= +# modify_types +# ============================================================================= + + +def test_modify_types_filters_atoms_and_reindexes(): + lines = [ + "1 10 # C\n", + "2 20 # H\n", + "3 30 # O\n", + "4 40 # N\n", + "\n", + ] + + template_indexes = [ + 1, + 3, + ] + + ( + df, + section, + count, + mapping, + legacy_mode, + ) = modify_types( + lines, + template_indexes, + 0, + ) + + assert list( + df["atom_index"] + ) == [ + 1, + 3, + ] + + assert list( + df["new_atom_index"] + ) == [ + 1, + 2, + ] + + assert count == 2 + + assert mapping == { + 1: 1, + 3: 2, + } + + assert legacy_mode is True + + assert "10" in section + assert "30" in section + + assert "20" not in section + assert "40" not in section + + +def test_modify_types_numeric_atom_types_are_ints(): + lines = [ + "1 12 # c1\n", + "2 7 # hc\n", + "\n", + ] + + ( + df, + _, + _, + _, + legacy_mode, + ) = modify_types( + lines, + [ + 1, + 2, + ], + 0, + ) + + assert df.loc[ + 0, + "atom_type", + ] == 12 + + assert df.loc[ + 1, + "atom_type", + ] == 7 + + assert legacy_mode is True + + +def test_modify_types_string_atom_type_disables_legacy_mode(): + lines = [ + "1 c1 # c1\n", + "2 hc # hc\n", + "\n", + ] + + ( + df, + _, + _, + _, + legacy_mode, + ) = modify_types( + lines, + [ + 1, + 2, + ], + 0, + ) + + assert ( + df.loc[ + 0, + "atom_type", + ] + == "c1" + ) + + assert ( + df.loc[ + 1, + "atom_type", + ] + == "hc" + ) + + assert legacy_mode is False + + +def test_modify_types_one_string_type_switches_global_legacy_mode_false(): + lines = [ + "1 10 # C\n", + "2 hc # H\n", + "\n", + ] + + ( + df, + _, + _, + _, + legacy_mode, + ) = modify_types( + lines, + [ + 1, + 2, + ], + 0, + ) + + # Characterizes current mixed parsing behavior: + # first row remains integer, second row is string, + # while legacy_mode becomes False globally. + assert df.loc[ + 0, + "atom_type", + ] == 10 + + assert ( + df.loc[ + 1, + "atom_type", + ] + == "hc" + ) + + assert legacy_mode is False + + +def test_modify_types_stops_at_first_blank_line(): + lines = [ + "1 10 # C\n", + "2 20 # H\n", + "\n", + "3 30 # O\n", + ] + + ( + df, + _, + count, + _, + _, + ) = modify_types( + lines, + [ + 1, + 2, + 3, + ], + 0, + ) + + assert count == 2 + + assert list( + df["atom_index"] + ) == [ + 1, + 2, + ] + + +def test_modify_types_respects_start_index(): + lines = [ + "Types\n", + "1 10 # C\n", + "2 20 # H\n", + "\n", + ] + + ( + df, + _, + count, + _, + _, + ) = modify_types( + lines, + [ + 1, + 2, + ], + 1, + ) + + assert count == 2 + + assert list( + df["atom_index"] + ) == [ + 1, + 2, + ] + + +def test_modify_types_ignores_lines_with_fewer_than_four_fields(): + lines = [ + "this is short\n", + "1 10 # C\n", + "\n", + ] + + ( + df, + _, + count, + _, + _, + ) = modify_types( + lines, + [ + 1, + ], + 0, + ) + + assert count == 1 + + assert list( + df["atom_index"] + ) == [ + 1, + ] + + +def test_modify_types_template_indexes_are_sorted_in_place(): + lines = [ + "1 10 # C\n", + "2 20 # H\n", + "3 30 # O\n", + "\n", + ] + + template_indexes = [ + 3, + 1, + 2, + ] + + modify_types( + lines, + template_indexes, + 0, + ) + + # Characterization: + # production currently mutates the supplied list. + assert template_indexes == [ + 1, + 2, + 3, + ] + + +def test_modify_types_output_order_follows_input_rows_not_template_list(): + lines = [ + "3 30 # O\n", + "1 10 # C\n", + "2 20 # H\n", + "\n", + ] + + template_indexes = [ + 2, + 1, + 3, + ] + + ( + df, + _, + _, + mapping, + _, + ) = modify_types( + lines, + template_indexes, + 0, + ) + + # Even though template_indexes gets sorted, + # surviving rows retain their order from the source section. + assert list( + df["atom_index"] + ) == [ + 3, + 1, + 2, + ] + + assert mapping == { + 3: 1, + 1: 2, + 2: 3, + } + + +def test_modify_types_all_selected(): + lines = [ + "10 4 # ca\n", + "20 8 # hc\n", + "\n", + ] + + ( + df, + _, + count, + mapping, + _, + ) = modify_types( + lines, + [ + 10, + 20, + ], + 0, + ) + + assert count == 2 + + assert mapping == { + 10: 1, + 20: 2, + } + + assert list( + df["new_atom_index"] + ) == [ + 1, + 2, + ] + + +def test_modify_types_none_selected_returns_empty_filtered_dataframe(): + lines = [ + "1 10 # C\n", + "2 20 # H\n", + "\n", + ] + + ( + df, + section, + count, + mapping, + legacy_mode, + ) = modify_types( + lines, + [ + 100, + ], + 0, + ) + + assert df.empty + + assert section == "" + + assert count == 0 + + assert mapping == {} + + assert legacy_mode is True + + +def test_modify_types_preserves_hash_and_real_type(): + lines = [ + "5 12 HASHVALUE c2\n", + "\n", + ] + + ( + df, + section, + _, + _, + _, + ) = modify_types( + lines, + [ + 5, + ], + 0, + ) + + assert ( + df.loc[ + 0, + "hash", + ] + == "HASHVALUE" + ) + + assert ( + df.loc[ + 0, + "atom_type_real", + ] + == "c2" + ) + + assert "HASHVALUE" in section + assert "c2" in section + + +# ============================================================================= +# modify_charges +# ============================================================================= + + +def test_modify_charges_filters_and_reindexes_atoms(): + type_df = make_type_df( + { + 2: 1, + 4: 2, + } + ) + + lines = [ + "1 -0.1 # c1\n", + "2 0.2 # c2\n", + "3 -0.3 # h\n", + "4 0.4 # o\n", + "\n", + ] + + section = modify_charges( + lines, + type_df, + 0, + ) + + assert "0.200000" in section + assert "0.400000" in section + + assert "-0.100000" not in section + assert "-0.300000" not in section + + output_lines = ( + section.strip().splitlines() + ) + + assert len( + output_lines + ) == 2 + + assert ( + output_lines[0] + .split()[0] + == "1" + ) + + assert ( + output_lines[1] + .split()[0] + == "2" + ) + + +def test_modify_charges_formats_six_decimal_places(): + type_df = make_type_df( + { + 1: 1, + } + ) + + section = modify_charges( + [ + "1 0.123456789 # c1\n", + "\n", + ], + type_df, + 0, + ) + + assert ( + "0.123457" + in section + ) + + +def test_modify_charges_stops_at_blank_line(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + } + ) + + section = modify_charges( + [ + "1 0.1 # c1\n", + "\n", + "2 0.2 # c2\n", + ], + type_df, + 0, + ) + + assert "0.100000" in section + assert "0.200000" not in section + + +def test_modify_charges_respects_start_index(): + type_df = make_type_df( + { + 1: 1, + } + ) + + lines = [ + "Charges\n", + "1 -0.25 # c1\n", + "\n", + ] + + section = modify_charges( + lines, + type_df, + 1, + ) + + assert "-0.250000" in section + + +def test_modify_charges_no_matching_atoms_returns_empty_string(): + type_df = make_type_df( + { + 10: 1, + } + ) + + section = modify_charges( + [ + "1 0.1 # c1\n", + "2 0.2 # c2\n", + "\n", + ], + type_df, + 0, + ) + + assert section == "" + + +def test_modify_charges_preserves_hash_and_real_type(): + type_df = make_type_df( + { + 1: 1, + } + ) + + section = modify_charges( + [ + "1 -0.5 HASH c2\n", + "\n", + ], + type_df, + 0, + ) + + assert "HASH" in section + assert "c2" in section + + +# ============================================================================= +# modify_coords +# ============================================================================= + + +def test_modify_coords_filters_and_reindexes(): + type_df = make_type_df( + { + 2: 1, + 3: 2, + } + ) + + lines = [ + "1 1.0 2.0 3.0 # c1\n", + "2 4.0 5.0 6.0 # c2\n", + "3 7.0 8.0 9.0 # o\n", + "\n", + ] + + section = modify_coords( + lines, + type_df, + 0, + ) + + assert "4.000000" in section + assert "5.000000" in section + assert "6.000000" in section + + assert "7.000000" in section + assert "8.000000" in section + assert "9.000000" in section + + assert "1.000000" not in section + + +def test_modify_coords_formats_six_decimal_places(): + type_df = make_type_df( + { + 1: 1, + } + ) + + section = modify_coords( + [ + "1 1.1234567 -2.3456789 3.1 # c1\n", + "\n", + ], + type_df, + 0, + ) + + assert "1.123457" in section + assert "-2.345679" in section + assert "3.100000" in section + + +def test_modify_coords_no_matching_atoms_returns_empty_string(): + type_df = make_type_df( + { + 99: 1, + } + ) + + section = modify_coords( + [ + "1 1.0 2.0 3.0 # c\n", + "\n", + ], + type_df, + 0, + ) + + assert section == "" + + +def test_modify_coords_stops_at_blank_line(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + } + ) + + section = modify_coords( + [ + "1 1.0 2.0 3.0 # c\n", + "\n", + "2 4.0 5.0 6.0 # o\n", + ], + type_df, + 0, + ) + + assert "1.000000" in section + assert "4.000000" not in section + + +# ============================================================================= +# modify_bonds +# ============================================================================= + + +def test_modify_bonds_keeps_bond_when_both_atoms_survive(): + type_df = make_type_df( + { + 5: 1, + 9: 2, + } + ) + + section, count = modify_bonds( + [ + "7 12 5 9 # c1 c2\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + + parts = section.split() + + assert parts[:4] == [ + "1", + "12", + "1", + "2", + ] + + +def test_modify_bonds_drops_bond_if_first_atom_missing(): + type_df = make_type_df( + { + 2: 1, + } + ) + + section, count = modify_bonds( + [ + "1 5 1 2 # c1 c2\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert section == "" + assert count == 0 + + +def test_modify_bonds_drops_bond_if_second_atom_missing(): + type_df = make_type_df( + { + 1: 1, + } + ) + + section, count = modify_bonds( + [ + "1 5 1 2 # c1 c2\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert section == "" + assert count == 0 + + +def test_modify_bonds_reindexes_bond_ids_sequentially(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + } + ) + + section, count = modify_bonds( + [ + "50 5 1 2 # c1 c2\n", + "99 6 2 3 # c2 c3\n", + "\n", + ], + type_df, + 0, + True, + ) + + rows = section.strip().splitlines() + + assert count == 2 + + assert rows[0].split()[0] == "1" + assert rows[1].split()[0] == "2" + + +def test_modify_bonds_legacy_mode_uses_integer_type(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + } + ) + + section, count = modify_bonds( + [ + "1 25 1 2 # c1 c2\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + assert section.split()[1] == "25" + + +def test_modify_bonds_nonlegacy_mode_accepts_string_type(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + } + ) + + section, count = modify_bonds( + [ + "1 c1-c2 1 2 # c1 c2\n", + "\n", + ], + type_df, + 0, + False, + ) + + assert count == 1 + + assert ( + section.split()[1] + == "c1-c2" + ) + + +def test_modify_bonds_preserves_atom_mapping_from_type_df(): + type_df = make_type_df( + { + 10: 2, + 20: 1, + } + ) + + section, _ = modify_bonds( + [ + "1 5 10 20 # a b\n", + "\n", + ], + type_df, + 0, + True, + ) + + parts = section.split() + + assert parts[2:4] == [ + "2", + "1", + ] + + +# ============================================================================= +# modify_angles +# ============================================================================= + + +def test_modify_angles_keeps_complete_angle(): + type_df = make_type_df( + { + 10: 1, + 20: 2, + 30: 3, + } + ) + + section, count = modify_angles( + [ + "9 7 10 20 30 # c1 c2 c3\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + + parts = section.split() + + assert parts[:5] == [ + "1", + "7", + "1", + "2", + "3", + ] + + +def test_modify_angles_drops_angle_when_any_atom_missing(): + type_df = make_type_df( + { + 10: 1, + 20: 2, + } + ) + + section, count = modify_angles( + [ + "1 7 10 20 30 # c1 c2 c3\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert section == "" + assert count == 0 + + +def test_modify_angles_reindexes_ids_sequentially(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + } + ) + + section, count = modify_angles( + [ + "50 4 1 2 3 # a b c\n", + "80 5 2 3 4 # b c d\n", + "\n", + ], + type_df, + 0, + True, + ) + + rows = section.strip().splitlines() + + assert count == 2 + + assert rows[0].split()[0] == "1" + assert rows[1].split()[0] == "2" + + +def test_modify_angles_nonlegacy_accepts_string_type(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + } + ) + + section, count = modify_angles( + [ + "1 c1-c2-c3 1 2 3 # c1 c2 c3\n", + "\n", + ], + type_df, + 0, + False, + ) + + assert count == 1 + + assert ( + section.split()[1] + == "c1-c2-c3" + ) + + +# ============================================================================= +# modify_dihedrals +# ============================================================================= + + +def test_modify_dihedrals_keeps_complete_dihedral(): + type_df = make_type_df( + { + 10: 1, + 20: 2, + 30: 3, + 40: 4, + } + ) + + section, count = modify_dihedrals( + [ + "15 8 10 20 30 40 # a b c d\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + + parts = section.split() + + assert parts[:6] == [ + "1", + "8", + "1", + "2", + "3", + "4", + ] + + +def test_modify_dihedrals_drops_when_any_atom_missing(): + type_df = make_type_df( + { + 10: 1, + 20: 2, + 30: 3, + } + ) + + section, count = modify_dihedrals( + [ + "1 8 10 20 30 40 # a b c d\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert section == "" + assert count == 0 + + +def test_modify_dihedrals_reindexes_ids(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + } + ) + + section, count = modify_dihedrals( + [ + "90 8 1 2 3 4 # a b c d\n", + "92 9 2 3 4 5 # b c d e\n", + "\n", + ], + type_df, + 0, + True, + ) + + rows = section.strip().splitlines() + + assert count == 2 + + assert rows[0].split()[0] == "1" + assert rows[1].split()[0] == "2" + + +def test_modify_dihedrals_nonlegacy_accepts_string_type(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + } + ) + + section, count = modify_dihedrals( + [ + "1 torsion_name 1 2 3 4 # a b c d\n", + "\n", + ], + type_df, + 0, + False, + ) + + assert count == 1 + + assert ( + section.split()[1] + == "torsion_name" + ) + + +# ============================================================================= +# modify_impropers +# ============================================================================= + + +def test_modify_impropers_keeps_complete_improper(): + type_df = make_type_df( + { + 10: 1, + 20: 2, + 30: 3, + 40: 4, + } + ) + + section, count = modify_impropers( + [ + "25 11 10 20 30 40 # a b c d\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + + parts = section.split() + + assert parts[:6] == [ + "1", + "11", + "1", + "2", + "3", + "4", + ] + + +def test_modify_impropers_drops_when_any_atom_missing(): + type_df = make_type_df( + { + 10: 1, + 20: 2, + 30: 3, + } + ) + + section, count = modify_impropers( + [ + "1 11 10 20 30 40 # a b c d\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert section == "" + assert count == 0 + + +def test_modify_impropers_reindexes_ids_sequentially(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + } + ) + + section, count = modify_impropers( + [ + "40 11 1 2 3 4 # a b c d\n", + "70 12 2 3 4 5 # b c d e\n", + "\n", + ], + type_df, + 0, + True, + ) + + rows = section.strip().splitlines() + + assert count == 2 + + assert rows[0].split()[0] == "1" + assert rows[1].split()[0] == "2" + + +def test_modify_impropers_nonlegacy_accepts_string_type(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + } + ) + + section, count = modify_impropers( + [ + "1 improper_name 1 2 3 4 # a b c d\n", + "\n", + ], + type_df, + 0, + False, + ) + + assert count == 1 + + assert ( + section.split()[1] + == "improper_name" + ) + + +# ============================================================================= +# Filtering invariants across topology types +# ============================================================================= + + +@pytest.mark.parametrize( + "function,line", + [ + ( + modify_bonds, + "1 1 1 99 # a z\n", + ), + ( + modify_angles, + "1 1 1 2 99 # a b z\n", + ), + ( + modify_dihedrals, + "1 1 1 2 3 99 # a b c z\n", + ), + ( + modify_impropers, + "1 1 1 2 3 99 # a b c z\n", + ), + ], +) +def test_topology_entry_removed_when_it_references_atom_outside_template( + function, + line, +): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + } + ) + + section, count = function( + [ + line, + "\n", + ], + type_df, + 0, + True, + ) + + assert section == "" + assert count == 0 + + +@pytest.mark.parametrize( + "function,line", + [ + ( + modify_bonds, + "1 10 5 10 # a b\n", + ), + ( + modify_angles, + "1 10 5 10 15 # a b c\n", + ), + ( + modify_dihedrals, + "1 10 5 10 15 20 # a b c d\n", + ), + ( + modify_impropers, + "1 10 5 10 15 20 # a b c d\n", + ), + ], +) +def test_topology_functions_preserve_nontrivial_atom_remapping( + function, + line, +): + type_df = make_type_df( + { + 5: 4, + 10: 3, + 15: 2, + 20: 1, + } + ) + + section, count = function( + [ + line, + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + + parts = section.split() + + if function is modify_bonds: + assert parts[2:4] == [ + "4", + "3", + ] + + elif function is modify_angles: + assert parts[2:5] == [ + "4", + "3", + "2", + ] + + else: + assert parts[2:6] == [ + "4", + "3", + "2", + "1", + ] + + +# ============================================================================= +# Malformed / short rows +# ============================================================================= + + +def test_modify_bonds_ignores_short_rows(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + } + ) + + section, count = modify_bonds( + [ + "1 2 1\n", + "2 3 1 2 # a b\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + assert section.split()[0] == "1" + + +def test_modify_angles_ignores_short_rows(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + } + ) + + section, count = modify_angles( + [ + "1 2 1 2\n", + "2 3 1 2 3 # a b c\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + + +def test_modify_dihedrals_ignores_short_rows(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + } + ) + + section, count = modify_dihedrals( + [ + "1 2 1 2 3\n", + "2 3 1 2 3 4 # a b c d\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + + +def test_modify_impropers_ignores_short_rows(): + type_df = make_type_df( + { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + } + ) + + section, count = modify_impropers( + [ + "1 2 1 2 3\n", + "2 3 1 2 3 4 # a b c d\n", + "\n", + ], + type_df, + 0, + True, + ) + + assert count == 1 + + +# ============================================================================= +# Cross-function integration +# ============================================================================= + + +def test_modify_types_mapping_can_drive_all_topology_modifiers(): + type_lines = [ + "10 5 # c1\n", + "20 6 # c2\n", + "30 7 # c3\n", + "40 8 # c4\n", + "\n", + ] + + ( + type_df, + _, + number_of_types, + index_mapping, + legacy_mode, + ) = modify_types( + type_lines, + [ + 10, + 20, + 30, + 40, + ], + 0, + ) + + assert number_of_types == 4 + + assert index_mapping == { + 10: 1, + 20: 2, + 30: 3, + 40: 4, + } + + assert legacy_mode is True + + bond_section, bonds = modify_bonds( + [ + "1 1 10 20 # c1 c2\n", + "\n", + ], + type_df, + 0, + legacy_mode, + ) + + angle_section, angles = modify_angles( + [ + "1 1 10 20 30 # c1 c2 c3\n", + "\n", + ], + type_df, + 0, + legacy_mode, + ) + + dihedral_section, dihedrals = ( + modify_dihedrals( + [ + "1 1 10 20 30 40 # c1 c2 c3 c4\n", + "\n", + ], + type_df, + 0, + legacy_mode, + ) + ) + + improper_section, impropers = ( + modify_impropers( + [ + "1 1 10 20 30 40 # c1 c2 c3 c4\n", + "\n", + ], + type_df, + 0, + legacy_mode, + ) + ) + + assert bonds == 1 + assert angles == 1 + assert dihedrals == 1 + assert impropers == 1 + + assert bond_section.split()[2:4] == [ + "1", + "2", + ] + + assert angle_section.split()[2:5] == [ + "1", + "2", + "3", + ] + + assert dihedral_section.split()[2:6] == [ + "1", + "2", + "3", + "4", + ] + + assert improper_section.split()[2:6] == [ + "1", + "2", + "3", + "4", + ] + + +def test_string_type_mode_propagates_to_topology_modifiers(): + type_lines = [ + "1 c1 # c1\n", + "2 c2 # c2\n", + "3 c3 # c3\n", + "4 c4 # c4\n", + "\n", + ] + + ( + type_df, + _, + _, + _, + legacy_mode, + ) = modify_types( + type_lines, + [ + 1, + 2, + 3, + 4, + ], + 0, + ) + + assert legacy_mode is False + + bond_section, _ = modify_bonds( + [ + "1 c1-c2 1 2 # c1 c2\n", + "\n", + ], + type_df, + 0, + legacy_mode, + ) + + angle_section, _ = modify_angles( + [ + "1 c1-c2-c3 1 2 3 # c1 c2 c3\n", + "\n", + ], + type_df, + 0, + legacy_mode, + ) + + dihedral_section, _ = modify_dihedrals( + [ + "1 c1-c2-c3-c4 1 2 3 4 # c1 c2 c3 c4\n", + "\n", + ], + type_df, + 0, + legacy_mode, + ) + + improper_section, _ = modify_impropers( + [ + "1 improper-c1 1 2 3 4 # c1 c2 c3 c4\n", + "\n", + ], + type_df, + 0, + legacy_mode, + ) + + assert ( + bond_section.split()[1] + == "c1-c2" + ) + + assert ( + angle_section.split()[1] + == "c1-c2-c3" + ) + + assert ( + dihedral_section.split()[1] + == "c1-c2-c3-c4" + ) + + assert ( + improper_section.split()[1] + == "improper-c1" + ) diff --git a/tests/unit/reaction_preparation/ff_wrapper/test_molecule_3d_preparation.py b/tests/unit/reaction_preparation/ff_wrapper/test_molecule_3d_preparation.py new file mode 100644 index 00000000..b41a814c --- /dev/null +++ b/tests/unit/reaction_preparation/ff_wrapper/test_molecule_3d_preparation.py @@ -0,0 +1,2288 @@ +from pathlib import Path +from types import SimpleNamespace + +import numpy as np +import pytest +from rdkit import Chem + +import AutoREACTER.reaction_preparation.ff_wrapper.molecule_3d_preparation as molecule_3d +from AutoREACTER.reaction_preparation.ff_wrapper.molecule_3d_preparation import ( + FragmentSeparationError, + Molecule3DPreparation, + Molecule3DPreparationError, + OptimizationError, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_session( + tmp_path, + *, + monomers=None, + reactions=None, +): + inputs = SimpleNamespace( + monomers=list( + monomers or [] + ) + ) + + return SimpleNamespace( + inputs=inputs, + reaction_metadata=list( + reactions or [] + ), + staging_dir=tmp_path / "staging", + ) + + +def make_monomer( + *, + name="mma", + status=True, + rdkit_mol=None, +): + return SimpleNamespace( + name=name, + status=status, + rdkit_mol=rdkit_mol, + molecule_3Dmol_path=None, + ) + + +def make_reaction( + *, + reaction_id=1, + activity_stats=True, + reactant=None, + product=None, +): + return SimpleNamespace( + reaction_id=reaction_id, + activity_stats=activity_stats, + reactant_combined_RDmol=reactant, + product_combined_RDmol=product, + reactant_combined_3Dmol_path=None, + product_combined_3Dmol_path=None, + ) + + +def make_two_fragment_mol(): + """ + Create two disconnected carbon atoms with a manually assigned conformer. + No embedding is required for the separation tests. + """ + mol = Chem.MolFromSmiles( + "[C].[C]" + ) + + conf = Chem.Conformer( + mol.GetNumAtoms() + ) + + conf.SetAtomPosition( + 0, + ( + 1.0, + 2.0, + 3.0, + ), + ) + + conf.SetAtomPosition( + 1, + ( + 10.0, + 20.0, + 30.0, + ), + ) + + mol.AddConformer( + conf + ) + + return mol + + +def make_three_fragment_mol(): + mol = Chem.MolFromSmiles( + "[C].[C].[C]" + ) + + conf = Chem.Conformer( + mol.GetNumAtoms() + ) + + for i in range( + mol.GetNumAtoms() + ): + conf.SetAtomPosition( + i, + ( + float(i), + 0.0, + 0.0, + ), + ) + + mol.AddConformer( + conf + ) + + return mol + + +def make_explicit_ch3_with_duplicate_h_property(): + """ + Build a carbon with three real H neighbors plus an erroneous + NumExplicitHs property of 1. + + This reproduces the kind of duplicate hydrogen bookkeeping that + _repair_reaction_molecule_for_3d() is designed to repair. + """ + editable = Chem.RWMol() + + carbon = Chem.Atom(6) + carbon.SetNumExplicitHs(1) + + carbon_idx = editable.AddAtom( + carbon + ) + + for _ in range(3): + hydrogen_idx = ( + editable.AddAtom( + Chem.Atom(1) + ) + ) + + editable.AddBond( + carbon_idx, + hydrogen_idx, + Chem.BondType.SINGLE, + ) + + mol = editable.GetMol() + + mol.UpdatePropertyCache( + strict=False + ) + + return mol + + +def make_explicit_ch4_with_radical(): + """ + Build carbon with four explicit H neighbors but incorrectly mark it + as a radical. Repair should clear that radical because bond valence + is already four. + """ + editable = Chem.RWMol() + + carbon = Chem.Atom(6) + carbon.SetNumRadicalElectrons( + 1 + ) + + carbon_idx = editable.AddAtom( + carbon + ) + + for _ in range(4): + hydrogen_idx = ( + editable.AddAtom( + Chem.Atom(1) + ) + ) + + editable.AddBond( + carbon_idx, + hydrogen_idx, + Chem.BondType.SINGLE, + ) + + mol = editable.GetMol() + + mol.UpdatePropertyCache( + strict=False + ) + + return mol + + +def patch_basic_optimization_stack( + preparer, + monkeypatch, + *, + embed_result=0, + mmff_available=True, + mmff_result=0, + uff_available=False, + uff_result=0, +): + """ + Patch the expensive/variable RDKit 3D operations while preserving + _optimization() control flow. + """ + events = [] + + params = SimpleNamespace( + randomSeed=None, + useRandomCoords=False, + ignoreSmoothingFailures=False, + ) + + monkeypatch.setattr( + preparer, + "_repair_reaction_molecule_for_3d", + lambda mol: mol, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "ETKDGv3", + lambda: params, + ) + + def fake_embed( + mol, + passed_params, + ): + events.append( + ( + "embed", + mol, + passed_params, + ) + ) + + return embed_result + + monkeypatch.setattr( + molecule_3d.AllChem, + "EmbedMolecule", + fake_embed, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "MMFFHasAllMoleculeParams", + lambda mol: + mmff_available, + ) + + def fake_mmff( + mol, + maxIters, + ): + events.append( + ( + "mmff", + maxIters, + ) + ) + + return mmff_result + + monkeypatch.setattr( + molecule_3d.AllChem, + "MMFFOptimizeMolecule", + fake_mmff, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "UFFHasAllMoleculeParams", + lambda mol: + uff_available, + ) + + def fake_uff( + mol, + maxIters, + ): + events.append( + ( + "uff", + maxIters, + ) + ) + + return uff_result + + monkeypatch.setattr( + molecule_3d.AllChem, + "UFFOptimizeMolecule", + fake_uff, + ) + + def fake_write( + mol, + filename, + **kwargs, + ): + events.append( + ( + "write", + Path(filename), + kwargs, + ) + ) + + Path( + filename + ).write_text( + "fake mol file", + encoding="utf-8", + ) + + monkeypatch.setattr( + molecule_3d.Chem, + "MolToMolFile", + fake_write, + ) + + return events, params + + +# ============================================================================= +# Exception hierarchy +# ============================================================================= + + +def test_molecule_3d_preparation_error_is_exception(): + assert issubclass( + Molecule3DPreparationError, + Exception, + ) + + +def test_fragment_separation_error_inherits_base_error(): + assert issubclass( + FragmentSeparationError, + Molecule3DPreparationError, + ) + + +def test_optimization_error_inherits_base_error(): + assert issubclass( + OptimizationError, + Molecule3DPreparationError, + ) + + +# ============================================================================= +# Constructor / cache +# ============================================================================= + + +def test_constructor_stores_session( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + assert ( + preparer.session + is session + ) + + assert ( + preparer.inputs + is session.inputs + ) + + +def test_constructor_creates_cache_directories( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + assert ( + preparer.cache_dir + == tmp_path + / "staging" + / "3D_molecules" + ) + + assert ( + preparer.molecule_3d_path + == preparer.cache_dir + / "molecules_3Dmol" + ) + + assert ( + preparer.full_templates_path + == preparer.cache_dir + / "full_templates_3Dmol" + ) + + assert ( + preparer.cache_dir.is_dir() + ) + + assert ( + preparer + .molecule_3d_path + .is_dir() + ) + + assert ( + preparer + .full_templates_path + .is_dir() + ) + + +def test_cache_property_returns_main_cache( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + assert ( + preparer.cache + == preparer.cache_dir + ) + + +# ============================================================================= +# prepare_molecule_3d_geometry - monomers +# ============================================================================= + + +def test_prepare_active_monomer_calls_add_hs_and_optimization( + tmp_path, + monkeypatch, +): + original_mol = ( + Chem.MolFromSmiles( + "CC" + ) + ) + + monomer = make_monomer( + name="ethane", + status=True, + rdkit_mol=original_mol, + ) + + session = make_session( + tmp_path, + monomers=[ + monomer + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + added_hs = object() + + add_h_calls = [] + + monkeypatch.setattr( + molecule_3d.Chem, + "AddHs", + lambda mol: + ( + add_h_calls.append( + mol + ) + or added_hs + ), + ) + + optimization_calls = [] + + output_path = ( + preparer.molecule_3d_path + / "ethane.mol" + ) + + def fake_optimization( + *, + molecule_name, + mol, + cache_dir, + separate_fragments=False, + ): + optimization_calls.append( + ( + molecule_name, + mol, + cache_dir, + separate_fragments, + ) + ) + + return output_path + + monkeypatch.setattr( + preparer, + "_optimization", + fake_optimization, + ) + + result = ( + preparer + .prepare_molecule_3d_geometry( + session + ) + ) + + assert result is None + + assert add_h_calls == [ + original_mol + ] + + assert optimization_calls == [ + ( + "ethane", + added_hs, + preparer.molecule_3d_path, + False, + ) + ] + + assert ( + monomer.molecule_3Dmol_path + == output_path + ) + + +def test_prepare_skips_inactive_monomer( + tmp_path, + monkeypatch, +): + monomer = make_monomer( + name="inactive", + status=False, + rdkit_mol=None, + ) + + session = make_session( + tmp_path, + monomers=[ + monomer + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + monkeypatch.setattr( + preparer, + "_optimization", + lambda **kwargs: + pytest.fail( + "inactive monomer must not be optimized" + ), + ) + + preparer.prepare_molecule_3d_geometry( + session + ) + + assert ( + monomer.molecule_3Dmol_path + is None + ) + + +def test_prepare_active_monomer_without_rdkit_mol_raises( + tmp_path, +): + monomer = make_monomer( + name="mma", + status=True, + rdkit_mol=None, + ) + + session = make_session( + tmp_path, + monomers=[ + monomer + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + with pytest.raises( + Molecule3DPreparationError, + match="RDKit Mol object is missing for molecule mma", + ): + preparer.prepare_molecule_3d_geometry( + session + ) + + +def test_prepare_monomer_optimization_error_is_wrapped( + tmp_path, + monkeypatch, +): + monomer = make_monomer( + name="styrene", + status=True, + rdkit_mol=( + Chem.MolFromSmiles( + "C=C" + ) + ), + ) + + session = make_session( + tmp_path, + monomers=[ + monomer + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + monkeypatch.setattr( + preparer, + "_optimization", + lambda **kwargs: + (_ for _ in ()).throw( + RuntimeError( + "boom" + ) + ), + ) + + with pytest.raises( + OptimizationError, + match="Error optimizing molecule styrene: boom", + ) as exc_info: + preparer.prepare_molecule_3d_geometry( + session + ) + + assert isinstance( + exc_info.value.__cause__, + RuntimeError, + ) + + +# ============================================================================= +# prepare_molecule_3d_geometry - reactions +# ============================================================================= + + +def test_prepare_skips_inactive_reaction( + tmp_path, + monkeypatch, +): + reaction = make_reaction( + reaction_id=5, + activity_stats=False, + reactant=object(), + product=object(), + ) + + session = make_session( + tmp_path, + reactions=[ + reaction + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + monkeypatch.setattr( + preparer, + "_optimization", + lambda **kwargs: + pytest.fail( + "inactive reaction must not be optimized" + ), + ) + + preparer.prepare_molecule_3d_geometry( + session + ) + + assert ( + reaction + .reactant_combined_3Dmol_path + is None + ) + + assert ( + reaction + .product_combined_3Dmol_path + is None + ) + + +def test_prepare_reaction_pre_and_post( + tmp_path, + monkeypatch, +): + pre_mol = object() + post_mol = object() + + reaction = make_reaction( + reaction_id=12, + activity_stats=True, + reactant=pre_mol, + product=post_mol, + ) + + session = make_session( + tmp_path, + reactions=[ + reaction + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + calls = [] + + def fake_optimization( + *, + molecule_name, + mol, + cache_dir, + separate_fragments=False, + ): + calls.append( + ( + molecule_name, + mol, + cache_dir, + separate_fragments, + ) + ) + + return ( + Path(cache_dir) + / f"{molecule_name}.mol" + ) + + monkeypatch.setattr( + preparer, + "_optimization", + fake_optimization, + ) + + preparer.prepare_molecule_3d_geometry( + session + ) + + assert calls == [ + ( + "pre12", + pre_mol, + preparer.full_templates_path, + True, + ), + ( + "post12", + post_mol, + preparer.full_templates_path, + True, + ), + ] + + assert ( + reaction + .reactant_combined_3Dmol_path + == preparer.full_templates_path + / "pre12.mol" + ) + + assert ( + reaction + .product_combined_3Dmol_path + == preparer.full_templates_path + / "post12.mol" + ) + + +def test_prepare_reaction_missing_pre_molecule_is_skipped( + tmp_path, + monkeypatch, +): + product = object() + + reaction = make_reaction( + reaction_id=2, + reactant=None, + product=product, + ) + + session = make_session( + tmp_path, + reactions=[ + reaction + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + calls = [] + + monkeypatch.setattr( + preparer, + "_optimization", + lambda **kwargs: + ( + calls.append( + kwargs["molecule_name"] + ) + or Path( + f"/tmp/{kwargs['molecule_name']}.mol" + ) + ), + ) + + preparer.prepare_molecule_3d_geometry( + session + ) + + assert calls == [ + "post2" + ] + + +def test_prepare_reaction_missing_post_molecule_is_skipped( + tmp_path, + monkeypatch, +): + reactant = object() + + reaction = make_reaction( + reaction_id=2, + reactant=reactant, + product=None, + ) + + session = make_session( + tmp_path, + reactions=[ + reaction + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + calls = [] + + monkeypatch.setattr( + preparer, + "_optimization", + lambda **kwargs: + ( + calls.append( + kwargs["molecule_name"] + ) + or Path( + f"/tmp/{kwargs['molecule_name']}.mol" + ) + ), + ) + + preparer.prepare_molecule_3d_geometry( + session + ) + + assert calls == [ + "pre2" + ] + + +def test_prepare_reactant_optimization_error_is_wrapped( + tmp_path, + monkeypatch, +): + reaction = make_reaction( + reaction_id=8, + reactant=object(), + product=None, + ) + + session = make_session( + tmp_path, + reactions=[ + reaction + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + monkeypatch.setattr( + preparer, + "_optimization", + lambda **kwargs: + (_ for _ in ()).throw( + RuntimeError( + "pre failure" + ) + ), + ) + + with pytest.raises( + OptimizationError, + match=( + "Error optimizing reactant complex " + "for reaction 8: pre failure" + ), + ): + preparer.prepare_molecule_3d_geometry( + session + ) + + +def test_prepare_product_optimization_error_is_wrapped( + tmp_path, + monkeypatch, +): + reaction = make_reaction( + reaction_id=9, + reactant=None, + product=object(), + ) + + session = make_session( + tmp_path, + reactions=[ + reaction + ], + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + monkeypatch.setattr( + preparer, + "_optimization", + lambda **kwargs: + (_ for _ in ()).throw( + RuntimeError( + "post failure" + ) + ), + ) + + with pytest.raises( + OptimizationError, + match=( + "Error optimizing product complex " + "for reaction 9: post failure" + ), + ): + preparer.prepare_molecule_3d_geometry( + session + ) + + +# ============================================================================= +# _separate_fragments_3d +# ============================================================================= + + +def test_separate_fragments_single_fragment_returns_same_object( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + mol = Chem.MolFromSmiles( + "CC" + ) + + result = ( + preparer + ._separate_fragments_3d( + mol + ) + ) + + assert result is mol + + +def test_separate_fragments_more_than_two_raises( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + mol = ( + make_three_fragment_mol() + ) + + with pytest.raises( + FragmentSeparationError, + match="Expected 2 fragments", + ): + preparer._separate_fragments_3d( + mol + ) + + +def test_separate_fragments_moves_only_second_fragment( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + mol = make_two_fragment_mol() + + conf = mol.GetConformer() + + first_before = np.array( + conf.GetAtomPosition(0) + ) + + second_before = np.array( + conf.GetAtomPosition(1) + ) + + result = ( + preparer + ._separate_fragments_3d( + mol + ) + ) + + conf_after = ( + result.GetConformer() + ) + + first_after = np.array( + conf_after.GetAtomPosition(0) + ) + + second_after = np.array( + conf_after.GetAtomPosition(1) + ) + + np.testing.assert_allclose( + first_after, + first_before, + ) + + # [C].[C] has molecular weight ~24, + # round(24/100) == 0, therefore shift = 4 Å. + np.testing.assert_allclose( + second_after, + second_before + + np.array( + [ + 4.0, + 0.0, + 0.0, + ] + ), + ) + + +def test_separate_fragments_returns_same_molecule_instance( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + mol = make_two_fragment_mol() + + result = ( + preparer + ._separate_fragments_3d( + mol + ) + ) + + assert result is mol + + +# ============================================================================= +# _repair_reaction_molecule_for_3d +# ============================================================================= + + +def test_repair_does_not_change_atom_count( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + mol = ( + make_explicit_ch3_with_duplicate_h_property() + ) + + count_before = ( + mol.GetNumAtoms() + ) + + repaired = ( + preparer + ._repair_reaction_molecule_for_3d( + mol + ) + ) + + assert ( + repaired.GetNumAtoms() + == count_before + ) + + +def test_repair_clears_duplicate_explicit_h_property( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + mol = ( + make_explicit_ch3_with_duplicate_h_property() + ) + + assert ( + mol.GetAtomWithIdx(0) + .GetNumExplicitHs() + == 1 + ) + + repaired = ( + preparer + ._repair_reaction_molecule_for_3d( + mol + ) + ) + + carbon = ( + repaired.GetAtomWithIdx( + 0 + ) + ) + + assert ( + carbon.GetNumExplicitHs() + == 0 + ) + + +def test_repair_sets_no_implicit_when_real_h_neighbors_exist( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + repaired = ( + preparer + ._repair_reaction_molecule_for_3d( + make_explicit_ch3_with_duplicate_h_property() + ) + ) + + carbon = ( + repaired.GetAtomWithIdx( + 0 + ) + ) + + assert ( + carbon.GetNoImplicit() + is True + ) + + +def test_repair_valence_three_neutral_carbon_becomes_radical( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + repaired = ( + preparer + ._repair_reaction_molecule_for_3d( + make_explicit_ch3_with_duplicate_h_property() + ) + ) + + carbon = ( + repaired.GetAtomWithIdx( + 0 + ) + ) + + assert ( + carbon.GetNumRadicalElectrons() + == 1 + ) + + +def test_repair_valence_four_carbon_clears_radical( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + mol = ( + make_explicit_ch4_with_radical() + ) + + assert ( + mol.GetAtomWithIdx(0) + .GetNumRadicalElectrons() + == 1 + ) + + repaired = ( + preparer + ._repair_reaction_molecule_for_3d( + mol + ) + ) + + carbon = ( + repaired.GetAtomWithIdx( + 0 + ) + ) + + assert ( + carbon.GetNumRadicalElectrons() + == 0 + ) + + +def test_repair_does_not_mutate_original_molecule( + tmp_path, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + original = ( + make_explicit_ch3_with_duplicate_h_property() + ) + + original_explicit_h = ( + original.GetAtomWithIdx(0) + .GetNumExplicitHs() + ) + + repaired = ( + preparer + ._repair_reaction_molecule_for_3d( + original + ) + ) + + assert repaired is not original + + assert ( + original.GetAtomWithIdx(0) + .GetNumExplicitHs() + == original_explicit_h + ) + + assert ( + repaired.GetAtomWithIdx(0) + .GetNumExplicitHs() + == 0 + ) + + +# ============================================================================= +# _optimization - setup / embedding +# ============================================================================= + + +def test_optimization_returns_expected_output_path( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + events, _ = ( + patch_basic_optimization_stack( + preparer, + monkeypatch, + ) + ) + + output_dir = ( + tmp_path / "output" + ) + + result = preparer._optimization( + molecule_name="styrene", + mol=Chem.MolFromSmiles( + "CC" + ), + cache_dir=output_dir, + ) + + assert result == ( + output_dir + / "styrene.mol" + ) + + assert result.is_file() + + +def test_optimization_creates_output_directory( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + patch_basic_optimization_stack( + preparer, + monkeypatch, + ) + + output_dir = ( + tmp_path + / "deep" + / "nested" + / "output" + ) + + assert not output_dir.exists() + + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + output_dir, + ) + + assert output_dir.is_dir() + + +def test_optimization_sets_deterministic_etkdg_parameters( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + _, params = ( + patch_basic_optimization_stack( + preparer, + monkeypatch, + ) + ) + + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + assert ( + params.randomSeed + == 0xF00D + ) + + assert ( + params.useRandomCoords + is True + ) + + assert ( + params.ignoreSmoothingFailures + is True + ) + + +def test_optimization_embedding_failure_raises( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + patch_basic_optimization_stack( + preparer, + monkeypatch, + embed_result=-1, + ) + + with pytest.raises( + OptimizationError, + match=( + "Failed to embed molecule test " + "in 3D" + ), + ): + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + +def test_optimization_repair_failure_is_wrapped( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + def fail_repair( + mol, + ): + raise ValueError( + "bad valence" + ) + + monkeypatch.setattr( + preparer, + "_repair_reaction_molecule_for_3d", + fail_repair, + ) + + with pytest.raises( + OptimizationError, + match=( + "Failed to repair molecule test " + "before 3D embedding" + ), + ) as exc_info: + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + assert isinstance( + exc_info.value.__cause__, + ValueError, + ) + + +# ============================================================================= +# _optimization - fragment separation +# ============================================================================= + + +def test_optimization_does_not_separate_by_default( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + patch_basic_optimization_stack( + preparer, + monkeypatch, + ) + + monkeypatch.setattr( + preparer, + "_separate_fragments_3d", + lambda mol: + pytest.fail( + "fragment separation should not run" + ), + ) + + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + separate_fragments=False, + ) + + +def test_optimization_separates_when_requested( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + patch_basic_optimization_stack( + preparer, + monkeypatch, + ) + + calls = [] + + monkeypatch.setattr( + preparer, + "_separate_fragments_3d", + lambda mol: + ( + calls.append(mol) + or mol + ), + ) + + preparer._optimization( + "test", + Chem.MolFromSmiles( + "C.C" + ), + tmp_path, + separate_fragments=True, + ) + + assert len(calls) == 1 + + +# ============================================================================= +# _optimization - force-field selection +# ============================================================================= + + +def test_optimization_prefers_mmff_when_available( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + events, _ = ( + patch_basic_optimization_stack( + preparer, + monkeypatch, + mmff_available=True, + uff_available=True, + ) + ) + + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + assert ( + "mmff", + 1000, + ) in events + + assert not any( + event[0] == "uff" + for event in events + ) + + +def test_optimization_uses_uff_when_mmff_unavailable( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + events, _ = ( + patch_basic_optimization_stack( + preparer, + monkeypatch, + mmff_available=False, + uff_available=True, + ) + ) + + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + assert ( + "uff", + 1000, + ) in events + + assert not any( + event[0] == "mmff" + for event in events + ) + + +def test_optimization_without_mmff_or_uff_still_saves( + tmp_path, + monkeypatch, + capsys, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + events, _ = ( + patch_basic_optimization_stack( + preparer, + monkeypatch, + mmff_available=False, + uff_available=False, + ) + ) + + result = preparer._optimization( + "unsupported", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + assert result.is_file() + + assert ( + "no MMFF or UFF parameters are available" + in capsys.readouterr().out + ) + + assert not any( + event[0] in { + "mmff", + "uff", + } + for event in events + ) + + +def test_mmff_failure_minus_one_raises( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + patch_basic_optimization_stack( + preparer, + monkeypatch, + mmff_available=True, + mmff_result=-1, + ) + + with pytest.raises( + OptimizationError, + match=( + "MMFF optimization failed " + "for test" + ), + ): + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + +def test_uff_failure_minus_one_raises( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + patch_basic_optimization_stack( + preparer, + monkeypatch, + mmff_available=False, + uff_available=True, + uff_result=-1, + ) + + with pytest.raises( + OptimizationError, + match=( + "UFF optimization failed " + "for test" + ), + ): + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + +@pytest.mark.parametrize( + "use_mmff", + [ + True, + False, + ], +) +def test_nonconverged_optimization_warns_but_saves( + tmp_path, + monkeypatch, + capsys, + use_mmff, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + patch_basic_optimization_stack( + preparer, + monkeypatch, + mmff_available=use_mmff, + mmff_result=1, + uff_available=not use_mmff, + uff_result=1, + ) + + result = preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + assert result.is_file() + + output = ( + capsys.readouterr().out + ) + + if use_mmff: + assert ( + "MMFF optimization did not converge" + in output + ) + else: + assert ( + "UFF optimization did not converge" + in output + ) + + +# ============================================================================= +# _optimization - atom-count invariant +# ============================================================================= + + +def test_optimization_rejects_atom_count_change_during_repair( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + original = ( + Chem.MolFromSmiles( + "C" + ) + ) + + monkeypatch.setattr( + preparer, + "_repair_reaction_molecule_for_3d", + lambda mol: + Chem.AddHs( + mol + ), + ) + + params = SimpleNamespace( + randomSeed=None, + useRandomCoords=False, + ignoreSmoothingFailures=False, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "ETKDGv3", + lambda: params, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "EmbedMolecule", + lambda mol, params: 0, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "MMFFHasAllMoleculeParams", + lambda mol: False, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "UFFHasAllMoleculeParams", + lambda mol: False, + ) + + monkeypatch.setattr( + molecule_3d.Chem, + "MolToMolFile", + lambda *args, **kwargs: + pytest.fail( + "file must not be written " + "after atom-count mismatch" + ), + ) + + with pytest.raises( + OptimizationError, + match="Atom count mismatch for test", + ): + preparer._optimization( + "test", + original, + tmp_path, + ) + + +# ============================================================================= +# _optimization - input molecule isolation +# ============================================================================= + + +def test_optimization_works_on_copy_of_input_molecule( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + original = ( + Chem.MolFromSmiles( + "CC" + ) + ) + + original.SetProp( + "ORIGINAL_MARKER", + "yes", + ) + + seen = [] + + def fake_repair( + mol, + ): + seen.append( + mol + ) + + mol.SetProp( + "MODIFIED_COPY", + "yes", + ) + + return mol + + monkeypatch.setattr( + preparer, + "_repair_reaction_molecule_for_3d", + fake_repair, + ) + + params = SimpleNamespace( + randomSeed=None, + useRandomCoords=False, + ignoreSmoothingFailures=False, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "ETKDGv3", + lambda: params, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "EmbedMolecule", + lambda mol, params: 0, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "MMFFHasAllMoleculeParams", + lambda mol: False, + ) + + monkeypatch.setattr( + molecule_3d.AllChem, + "UFFHasAllMoleculeParams", + lambda mol: False, + ) + + monkeypatch.setattr( + molecule_3d.Chem, + "MolToMolFile", + lambda mol, filename, **kwargs: + Path(filename).write_text( + "fake", + encoding="utf-8", + ), + ) + + preparer._optimization( + "test", + original, + tmp_path, + ) + + assert len(seen) == 1 + + assert seen[0] is not original + + assert not original.HasProp( + "MODIFIED_COPY" + ) + + assert ( + original.GetProp( + "ORIGINAL_MARKER" + ) + == "yes" + ) + + +# ============================================================================= +# _optimization - output writer contract +# ============================================================================= + + +def test_optimization_writes_with_stereo_and_without_kekulization( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + events, _ = ( + patch_basic_optimization_stack( + preparer, + monkeypatch, + ) + ) + + preparer._optimization( + "test", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + write_event = next( + event + for event in events + if event[0] == "write" + ) + + _, path, kwargs = ( + write_event + ) + + assert path == ( + tmp_path / "test.mol" + ) + + assert ( + kwargs["includeStereo"] + is True + ) + + assert ( + kwargs["kekulize"] + is False + ) + + +def test_optimization_prints_save_location( + tmp_path, + monkeypatch, + capsys, +): + session = make_session( + tmp_path + ) + + preparer = ( + Molecule3DPreparation( + session + ) + ) + + patch_basic_optimization_stack( + preparer, + monkeypatch, + ) + + expected = ( + tmp_path / "styrene.mol" + ) + + preparer._optimization( + "styrene", + Chem.MolFromSmiles( + "CC" + ), + tmp_path, + ) + + assert ( + f"Saving optimized styrene to {expected}" + in capsys.readouterr().out + ) From cc4b0e1fd88d6f422e605c1af8b0171bcbd2e865 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:39:04 -0400 Subject: [PATCH 151/176] Add unit tests and clarify DeleteIDs map handling --- .../writers/rxn_first_stage_writer.py | 41 +- .../test_system_property_calculations.py | 1503 +++++++++++++ .../writers/test_densification_writer.py | 1857 +++++++++++++++++ .../sim_setup/writers/test_lammps_settings.py | 869 ++++++++ .../sim_setup/writers/test_post_eq_writer.py | 1355 ++++++++++++ .../sim_setup/writers/test_pre_eq_writer.py | 1215 +++++++++++ 6 files changed, 6836 insertions(+), 4 deletions(-) create mode 100644 tests/unit/sim_setup/test_system_property_calculations.py create mode 100644 tests/unit/sim_setup/writers/test_densification_writer.py create mode 100644 tests/unit/sim_setup/writers/test_lammps_settings.py create mode 100644 tests/unit/sim_setup/writers/test_post_eq_writer.py create mode 100644 tests/unit/sim_setup/writers/test_pre_eq_writer.py diff --git a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py index 29082969..e349ce00 100644 --- a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py @@ -44,7 +44,9 @@ def __init__( self.out_dir = out_dir self.sim_name = sim_name self.reacter_files = reacter_files - self.first_stage_file_name = self.write_first_stage_reaction_files(simulation=simulation) + self.first_stage_file_name = self.write_first_stage_reaction_files( + simulation=simulation + ) # Public API @@ -148,13 +150,19 @@ def write_first_stage_reaction_files(self, simulation: Simulation) -> str: # Extract filenames from the dataclass fields pre_file = template.pre_reaction_file.name post_file = template.post_reaction_file.name + + # The standard map is always used by AutoREACTER. + # A supplementary DeleteIDs map may also be provided to the user, + # but AutoREACTER does not automatically select it. map_file = template.map_file.name + id = template.reaction_id pre_id = f"mol_pre_{id}" post_id = f"mol_post_{id}" lines.append(f"{'molecule':<16} {pre_id:<16} {pre_file}") lines.append(f"{'molecule':<16} {post_id:<16} {post_file}\n") + rxn_stp = f"rxn_stp_{id}" rxn_str = ( f"react " @@ -205,6 +213,13 @@ def write_first_stage_reaction_files(self, simulation: Simulation) -> str: def _copy_required_files(self, dest_dir: Path) -> None: """Copy every map and molecule file referenced by the reaction templates. + The standard RXN_N.map file is always copied and is the map used by + AutoREACTER's generated LAMMPS script. + + When an optional RXN_N_with_delete_ids.map file is available, it is + also copied into the reaction directory for the user. AutoREACTER does + not automatically use the supplementary DeleteIDs map. + Parameters ---------- dest_dir : Path @@ -213,7 +228,7 @@ def _copy_required_files(self, dest_dir: Path) -> None: Raises ------ FileNotFoundError - If any referenced file does not exist on disk. + If any required standard reaction file does not exist on disk. """ rf = self.reacter_files @@ -227,7 +242,25 @@ def _copy_required_files(self, dest_dir: Path) -> None: template.post_reaction_file, ] + # Supplementary DeleteIDs map is optional. + map_file_with_delete_ids = getattr( + template, + "map_file_with_delete_ids", + None, + ) + + if map_file_with_delete_ids is not None: + files.append( + map_file_with_delete_ids + ) + for file in files: if file is None or not file.exists(): - raise FileNotFoundError(f"Required reaction file not found: {file}") - shutil.copy2(file, dest_dir / file.name) + raise FileNotFoundError( + f"Required reaction file not found: {file}" + ) + + shutil.copy2( + file, + dest_dir / file.name, + ) \ No newline at end of file diff --git a/tests/unit/sim_setup/test_system_property_calculations.py b/tests/unit/sim_setup/test_system_property_calculations.py new file mode 100644 index 00000000..d38199ce --- /dev/null +++ b/tests/unit/sim_setup/test_system_property_calculations.py @@ -0,0 +1,1503 @@ +import math +from types import SimpleNamespace + +import pytest +from rdkit import Chem + +from AutoREACTER.sim_setup.system_property_calculations import ( + CM_2_A3, + N_A, + NoneMonomerError, + SystemPropertyCalculations, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_monomer( + *, + name="monomer", + monomer_id=1, + status=True, + rdkit_mol=None, + num_atoms=None, + molecular_weight=None, + count=None, +): + return SimpleNamespace( + id=monomer_id, + name=name, + status=status, + rdkit_mol=rdkit_mol, + num_atoms=num_atoms, + molecular_weight=molecular_weight, + count=count, + ) + + +def make_simulation( + *, + tag="sim1", + total_atoms=100, + density=1.0, + monomer_ratios=None, + monomer_counts=None, +): + return SimpleNamespace( + tag=tag, + total_atoms=total_atoms, + density=density, + monomer_ratios=( + {} + if monomer_ratios is None + else monomer_ratios + ), + monomer_counts=monomer_counts, + initial_box_volume=None, + initial_box_length=None, + ) + + +def make_setup( + *, + monomers=None, + simulations=None, + composition_method="ratio", +): + return SimpleNamespace( + monomers=list( + monomers or [] + ), + simulations=list( + simulations or [] + ), + composition_method=composition_method, + ) + + +# ============================================================================= +# Constants +# ============================================================================= + + +def test_avogadro_constant(): + assert N_A == pytest.approx( + 6.02214076e23 + ) + + +def test_cm3_to_angstrom3_conversion(): + assert CM_2_A3 == pytest.approx( + 1.0e24 + ) + + +# ============================================================================= +# Exception +# ============================================================================= + + +def test_none_monomer_error_is_exception(): + assert issubclass( + NoneMonomerError, + Exception, + ) + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_simulation_setup(): + setup = make_setup() + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + assert ( + calculator.simulation_setup + is setup + ) + + +# ============================================================================= +# process_all +# ============================================================================= + + +def test_process_all_calls_steps_in_order( + monkeypatch, +): + setup = make_setup() + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + events = [] + + monkeypatch.setattr( + calculator, + "_populate_monomer_properties", + lambda: + events.append( + "populate" + ), + ) + + monkeypatch.setattr( + calculator, + "_calculate_replica_properties", + lambda: + events.append( + "calculate" + ), + ) + + result = ( + calculator.process_all() + ) + + assert events == [ + "populate", + "calculate", + ] + + assert result is setup + + +def test_process_all_returns_same_setup_object( + monkeypatch, +): + setup = make_setup() + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + monkeypatch.setattr( + calculator, + "_populate_monomer_properties", + lambda: None, + ) + + monkeypatch.setattr( + calculator, + "_calculate_replica_properties", + lambda: None, + ) + + result = ( + calculator.process_all() + ) + + assert result is setup + + +# ============================================================================= +# _populate_monomer_properties +# ============================================================================= + + +def test_populate_active_monomer_counts_explicit_hydrogens(): + methane = ( + Chem.MolFromSmiles( + "C" + ) + ) + + monomer = make_monomer( + name="methane", + rdkit_mol=methane, + ) + + setup = make_setup( + monomers=[ + monomer + ] + ) + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + calculator._populate_monomer_properties() + + # CH4 = one carbon + four hydrogens. + assert monomer.num_atoms == 5 + + +def test_populate_does_not_modify_original_rdkit_molecule(): + methane = ( + Chem.MolFromSmiles( + "C" + ) + ) + + assert ( + methane.GetNumAtoms() + == 1 + ) + + monomer = make_monomer( + name="methane", + rdkit_mol=methane, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup( + monomers=[ + monomer + ] + ) + ) + ) + + calculator._populate_monomer_properties() + + # AddHs() is applied to a temporary molecule. + assert ( + methane.GetNumAtoms() + == 1 + ) + + assert monomer.num_atoms == 5 + + +def test_populate_sets_molecular_weight(): + monomer = make_monomer( + name="methane", + rdkit_mol=( + Chem.MolFromSmiles( + "C" + ) + ), + ) + + calculator = ( + SystemPropertyCalculations( + make_setup( + monomers=[ + monomer + ] + ) + ) + ) + + calculator._populate_monomer_properties() + + assert monomer.molecular_weight == pytest.approx( + 16.043, + rel=1.0e-3, + ) + + +def test_populate_ethanol_full_atom_count(): + # C2H6O = 9 atoms total. + monomer = make_monomer( + name="ethanol", + rdkit_mol=( + Chem.MolFromSmiles( + "CCO" + ) + ), + ) + + calculator = ( + SystemPropertyCalculations( + make_setup( + monomers=[ + monomer + ] + ) + ) + ) + + calculator._populate_monomer_properties() + + assert monomer.num_atoms == 9 + + +def test_populate_skips_inactive_monomer(): + monomer = make_monomer( + name="inactive", + status=False, + rdkit_mol=None, + num_atoms=999, + molecular_weight=888, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup( + monomers=[ + monomer + ] + ) + ) + ) + + calculator._populate_monomer_properties() + + assert monomer.num_atoms == 999 + + assert ( + monomer.molecular_weight + == 888 + ) + + +def test_populate_active_none_molecule_raises(): + monomer = make_monomer( + name="broken", + monomer_id=42, + status=True, + rdkit_mol=None, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup( + monomers=[ + monomer + ] + ) + ) + ) + + with pytest.raises( + NoneMonomerError, + match=( + "Monomer with ID 42 " + "has no RDKit Mol object" + ), + ): + calculator._populate_monomer_properties() + + +def test_populate_prints_info_message( + capsys, +): + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._populate_monomer_properties() + + assert ( + "Populating monomer properties" + in capsys.readouterr().out + ) + + +def test_populate_multiple_active_monomers(): + methane = make_monomer( + name="methane", + rdkit_mol=( + Chem.MolFromSmiles( + "C" + ) + ), + ) + + ethane = make_monomer( + name="ethane", + rdkit_mol=( + Chem.MolFromSmiles( + "CC" + ) + ), + ) + + calculator = ( + SystemPropertyCalculations( + make_setup( + monomers=[ + methane, + ethane, + ] + ) + ) + ) + + calculator._populate_monomer_properties() + + assert methane.num_atoms == 5 + + # C2H6 + assert ethane.num_atoms == 8 + + +# ============================================================================= +# _get_monomer_counts +# ============================================================================= + + +def test_get_monomer_counts_requires_total_atoms(): + monomer = make_monomer( + name="A", + num_atoms=10, + ) + + simulation = make_simulation( + tag="test", + total_atoms=None, + monomer_ratios={ + "A": 1, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + with pytest.raises( + ValueError, + match=( + "Simulation 'test' is " + "missing 'total_atoms'" + ), + ): + calculator._get_monomer_counts( + simulation, + { + "A": monomer + }, + ) + + +def test_get_monomer_counts_basic_ratio_calculation(): + """ + atoms per ratio unit: + + A: ratio 2 * 10 atoms = 20 + B: ratio 1 * 20 atoms = 20 + ---- + 40 + + total_atoms = 100 + multiplier = 100 / 40 = 2.5 + + A count = ceil(2 * 2.5) = 5 + B count = ceil(1 * 2.5) = 3 + """ + monomer_a = make_monomer( + name="A", + num_atoms=10, + ) + + monomer_b = make_monomer( + name="B", + num_atoms=20, + ) + + simulation = make_simulation( + tag="sim", + total_atoms=100, + monomer_ratios={ + "A": 2, + "B": 1, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._get_monomer_counts( + simulation, + { + "A": monomer_a, + "B": monomer_b, + }, + ) + + assert simulation.monomer_counts == { + "A": 5, + "B": 3, + } + + +def test_ratio_counting_can_overshoot_requested_total_atoms(): + """ + Characterization of current ceil-based behavior. + + 5 A molecules * 10 atoms = 50 + 3 B molecules * 20 atoms = 60 + total actual atoms = 110 + + Requested total_atoms was 100. + """ + monomer_a = make_monomer( + name="A", + num_atoms=10, + ) + + monomer_b = make_monomer( + name="B", + num_atoms=20, + ) + + simulation = make_simulation( + total_atoms=100, + monomer_ratios={ + "A": 2, + "B": 1, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._get_monomer_counts( + simulation, + { + "A": monomer_a, + "B": monomer_b, + }, + ) + + actual_atoms = ( + simulation.monomer_counts["A"] + * monomer_a.num_atoms + + simulation.monomer_counts["B"] + * monomer_b.num_atoms + ) + + assert actual_atoms == 110 + + assert actual_atoms >= ( + simulation.total_atoms + ) + + +def test_get_monomer_counts_initializes_none_dictionary(): + monomer = make_monomer( + name="A", + num_atoms=10, + ) + + simulation = make_simulation( + total_atoms=100, + monomer_ratios={ + "A": 1, + }, + monomer_counts=None, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._get_monomer_counts( + simulation, + { + "A": monomer + }, + ) + + assert isinstance( + simulation.monomer_counts, + dict, + ) + + assert ( + simulation.monomer_counts["A"] + == 10 + ) + + +def test_get_monomer_counts_preserves_existing_dictionary_entries(): + monomer = make_monomer( + name="A", + num_atoms=10, + ) + + simulation = make_simulation( + total_atoms=100, + monomer_ratios={ + "A": 1, + }, + monomer_counts={ + "existing": 99 + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._get_monomer_counts( + simulation, + { + "A": monomer + }, + ) + + assert simulation.monomer_counts == { + "existing": 99, + "A": 10, + } + + +def test_get_monomer_counts_records_count_on_monomer(): + monomer = make_monomer( + name="A", + num_atoms=10, + count=None, + ) + + simulation = make_simulation( + tag="500K", + total_atoms=100, + monomer_ratios={ + "A": 1, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._get_monomer_counts( + simulation, + { + "A": monomer + }, + ) + + assert monomer.count == { + "500K": 10 + } + + +def test_get_monomer_counts_preserves_other_simulation_counts(): + monomer = make_monomer( + name="A", + num_atoms=10, + count={ + "old_sim": 4 + }, + ) + + simulation = make_simulation( + tag="new_sim", + total_atoms=100, + monomer_ratios={ + "A": 1, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._get_monomer_counts( + simulation, + { + "A": monomer + }, + ) + + assert monomer.count == { + "old_sim": 4, + "new_sim": 10, + } + + +def test_get_monomer_counts_ignores_ratio_names_not_active(): + monomer = make_monomer( + name="A", + num_atoms=10, + ) + + simulation = make_simulation( + total_atoms=100, + monomer_ratios={ + "A": 1, + "inactive_or_unknown": 999, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._get_monomer_counts( + simulation, + { + "A": monomer + }, + ) + + assert simulation.monomer_counts == { + "A": 10 + } + + +def test_get_monomer_counts_no_active_ratio_monomers_raises(): + simulation = make_simulation( + tag="empty", + total_atoms=100, + monomer_ratios={ + "missing": 1, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + with pytest.raises( + ValueError, + match=( + "has no active monomers " + "to calculate ratios" + ), + ): + calculator._get_monomer_counts( + simulation, + {}, + ) + + +def test_get_monomer_counts_minimum_is_one(): + monomer_a = make_monomer( + name="A", + num_atoms=1000, + ) + + monomer_b = make_monomer( + name="B", + num_atoms=1, + ) + + simulation = make_simulation( + total_atoms=1, + monomer_ratios={ + "A": 1, + "B": 1, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._get_monomer_counts( + simulation, + { + "A": monomer_a, + "B": monomer_b, + }, + ) + + assert ( + simulation.monomer_counts["A"] + >= 1 + ) + + assert ( + simulation.monomer_counts["B"] + >= 1 + ) + + +# ============================================================================= +# _calculate_box_dimensions +# ============================================================================= + + +def test_calculate_box_dimensions_requires_counts(): + simulation = make_simulation( + tag="missing_counts", + monomer_counts=None, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + with pytest.raises( + ValueError, + match=( + "Simulation 'missing_counts' " + "lacks monomer counts" + ), + ): + calculator._calculate_box_dimensions( + simulation, + {}, + ) + + +def test_calculate_box_dimensions_exact_formula(): + monomer = make_monomer( + name="A", + molecular_weight=100.0, + ) + + simulation = make_simulation( + density=1.0, + monomer_counts={ + "A": 10, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._calculate_box_dimensions( + simulation, + { + "A": monomer + }, + ) + + total_mass_g = ( + 10 * 100.0 + ) / N_A + + initial_density = ( + 1.0 / 4.0 + ) + + expected_volume = ( + total_mass_g + / initial_density + * CM_2_A3 + ) + + expected_length = round( + math.pow( + expected_volume, + 1.0 / 3.0, + ), + 2, + ) + + assert ( + simulation.initial_box_volume + == pytest.approx( + expected_volume + ) + ) + + assert ( + simulation.initial_box_length + == expected_length + ) + + +def test_initial_box_uses_quarter_target_density(): + monomer = make_monomer( + name="A", + molecular_weight=50.0, + ) + + simulation = make_simulation( + density=2.0, + monomer_counts={ + "A": 4, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._calculate_box_dimensions( + simulation, + { + "A": monomer + }, + ) + + total_mass_g = ( + 4 * 50.0 + ) / N_A + + target_volume = ( + total_mass_g + / 2.0 + * CM_2_A3 + ) + + # Initial density = target density / 4, + # therefore initial volume = target volume * 4. + assert ( + simulation.initial_box_volume + == pytest.approx( + target_volume * 4.0 + ) + ) + + +def test_box_length_is_cube_root_of_initial_volume(): + monomer = make_monomer( + name="A", + molecular_weight=75.0, + ) + + simulation = make_simulation( + density=1.2, + monomer_counts={ + "A": 15, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._calculate_box_dimensions( + simulation, + { + "A": monomer + }, + ) + + expected = round( + simulation.initial_box_volume + ** ( + 1.0 / 3.0 + ), + 2, + ) + + assert ( + simulation.initial_box_length + == expected + ) + + +def test_box_length_is_rounded_to_two_decimal_places(): + monomer = make_monomer( + name="A", + molecular_weight=123.456, + ) + + simulation = make_simulation( + density=1.234, + monomer_counts={ + "A": 17, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._calculate_box_dimensions( + simulation, + { + "A": monomer + }, + ) + + assert ( + simulation.initial_box_length + == round( + simulation.initial_box_length, + 2, + ) + ) + + +def test_box_mass_sums_multiple_active_monomers(): + monomer_a = make_monomer( + name="A", + molecular_weight=100.0, + ) + + monomer_b = make_monomer( + name="B", + molecular_weight=50.0, + ) + + simulation = make_simulation( + density=1.0, + monomer_counts={ + "A": 2, + "B": 4, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._calculate_box_dimensions( + simulation, + { + "A": monomer_a, + "B": monomer_b, + }, + ) + + expected_mass = ( + (2 * 100.0) + + (4 * 50.0) + ) / N_A + + expected_volume = ( + expected_mass + / 0.25 + * CM_2_A3 + ) + + assert ( + simulation.initial_box_volume + == pytest.approx( + expected_volume + ) + ) + + +def test_box_calculation_ignores_counts_for_unknown_or_inactive_monomers(): + monomer = make_monomer( + name="A", + molecular_weight=100.0, + ) + + simulation = make_simulation( + density=1.0, + monomer_counts={ + "A": 2, + "unknown": 100000, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._calculate_box_dimensions( + simulation, + { + "A": monomer + }, + ) + + expected_mass = ( + 2 * 100.0 + ) / N_A + + expected_volume = ( + expected_mass + / 0.25 + * CM_2_A3 + ) + + assert ( + simulation.initial_box_volume + == pytest.approx( + expected_volume + ) + ) + + +def test_box_calculation_empty_active_mass_produces_zero_box(): + """ + Characterization of current behavior. + + If monomer_counts exists but none of its names correspond to an + active monomer, total mass remains zero. + """ + simulation = make_simulation( + density=1.0, + monomer_counts={ + "unknown": 5, + }, + ) + + calculator = ( + SystemPropertyCalculations( + make_setup() + ) + ) + + calculator._calculate_box_dimensions( + simulation, + {}, + ) + + assert ( + simulation.initial_box_volume + == 0.0 + ) + + assert ( + simulation.initial_box_length + == 0.0 + ) + + +# ============================================================================= +# _calculate_replica_properties +# ============================================================================= + + +def test_calculate_replica_properties_builds_only_active_monomer_lookup( + monkeypatch, +): + active = make_monomer( + name="active", + status=True, + ) + + inactive = make_monomer( + name="inactive", + status=False, + ) + + simulation = make_simulation() + + setup = make_setup( + monomers=[ + active, + inactive, + ], + simulations=[ + simulation + ], + composition_method="count", + ) + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + captured = [] + + monkeypatch.setattr( + calculator, + "_calculate_box_dimensions", + lambda sim, monomers: + captured.append( + monomers + ), + ) + + calculator._calculate_replica_properties() + + assert list( + captured[0].keys() + ) == [ + "active" + ] + + assert ( + captured[0]["active"] + is active + ) + + +def test_ratio_mode_calculates_counts_before_box( + monkeypatch, +): + simulation = make_simulation() + + setup = make_setup( + simulations=[ + simulation + ], + composition_method="ratio", + ) + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + events = [] + + monkeypatch.setattr( + calculator, + "_get_monomer_counts", + lambda sim, monomers: + events.append( + "counts" + ), + ) + + monkeypatch.setattr( + calculator, + "_calculate_box_dimensions", + lambda sim, monomers: + events.append( + "box" + ), + ) + + calculator._calculate_replica_properties() + + assert events == [ + "counts", + "box", + ] + + +def test_non_ratio_mode_skips_count_calculation( + monkeypatch, +): + simulation = make_simulation( + monomer_counts={ + "A": 1 + }, + ) + + setup = make_setup( + simulations=[ + simulation + ], + composition_method="count", + ) + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + monkeypatch.setattr( + calculator, + "_get_monomer_counts", + lambda *args: + pytest.fail( + "_get_monomer_counts must not " + "run in count mode" + ), + ) + + calls = [] + + monkeypatch.setattr( + calculator, + "_calculate_box_dimensions", + lambda sim, monomers: + calls.append( + sim + ), + ) + + calculator._calculate_replica_properties() + + assert calls == [ + simulation + ] + + +def test_calculate_replica_properties_processes_all_simulations( + monkeypatch, +): + sim1 = make_simulation( + tag="sim1" + ) + + sim2 = make_simulation( + tag="sim2" + ) + + sim3 = make_simulation( + tag="sim3" + ) + + setup = make_setup( + simulations=[ + sim1, + sim2, + sim3, + ], + composition_method="count", + ) + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + processed = [] + + monkeypatch.setattr( + calculator, + "_calculate_box_dimensions", + lambda sim, monomers: + processed.append( + sim.tag + ), + ) + + calculator._calculate_replica_properties() + + assert processed == [ + "sim1", + "sim2", + "sim3", + ] + + +# ============================================================================= +# End-to-end property calculation +# ============================================================================= + + +def test_process_all_real_small_ratio_system(): + """ + Small integration test across: + + RDKit properties + ↓ + ratio counts + ↓ + mass / box calculation + """ + methane = make_monomer( + name="methane", + rdkit_mol=( + Chem.MolFromSmiles( + "C" + ) + ), + ) + + ethane = make_monomer( + name="ethane", + rdkit_mol=( + Chem.MolFromSmiles( + "CC" + ) + ), + ) + + simulation = make_simulation( + tag="small", + total_atoms=100, + density=1.0, + monomer_ratios={ + "methane": 1.0, + "ethane": 1.0, + }, + ) + + setup = make_setup( + monomers=[ + methane, + ethane, + ], + simulations=[ + simulation + ], + composition_method="ratio", + ) + + calculator = ( + SystemPropertyCalculations( + setup + ) + ) + + result = ( + calculator.process_all() + ) + + assert result is setup + + assert methane.num_atoms == 5 + assert ethane.num_atoms == 8 + + assert ( + simulation.monomer_counts[ + "methane" + ] + > 0 + ) + + assert ( + simulation.monomer_counts[ + "ethane" + ] + > 0 + ) + + assert ( + simulation.initial_box_volume + > 0 + ) + + assert ( + simulation.initial_box_length + > 0 + ) + + assert ( + methane.count["small"] + == simulation + .monomer_counts[ + "methane" + ] + ) + + assert ( + ethane.count["small"] + == simulation + .monomer_counts[ + "ethane" + ] + ) \ No newline at end of file diff --git a/tests/unit/sim_setup/writers/test_densification_writer.py b/tests/unit/sim_setup/writers/test_densification_writer.py new file mode 100644 index 00000000..8504c5eb --- /dev/null +++ b/tests/unit/sim_setup/writers/test_densification_writer.py @@ -0,0 +1,1857 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER.sim_setup.writers.densification_writer as dens_module +from AutoREACTER.sim_setup.writers.densification_writer import ( + DensificationWriter, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_settings( + *, + neighbor=None, + neigh_modify=None, +): + return SimpleNamespace( + units="real", + dimension="3", + boundary="p p p", + atom_style="full", + bond_style="class2", + angle_style="class2", + dihedral_style="class2", + improper_style="class2", + special_bonds="lj/coul 0 0 1", + pair_style="lj/class2/coul/long 12.0", + kspace_style="pppm 1.0e-4", + pair_modify="mix sixthpower", + neighbor=neighbor, + neigh_modify=neigh_modify, + ) + + +def make_monomer( + *, + name="mma", + data_id="data1", + molecule_file=None, +): + return SimpleNamespace( + name=name, + data_id=data_id, + lmp_molecule_file=molecule_file, + ) + + +def make_reacter_files( + *, + force_field_data, + molecule_files=None, + template_files=None, +): + return SimpleNamespace( + force_field_data=Path(force_field_data), + molecule_files=list( + molecule_files or [] + ), + template_files=list( + template_files or [] + ), + ) + + +def make_simulation( + *, + tag="sim1", + initial_box_length=40.0, + temperature=500.0, + density=1.2, + monomer_counts=None, +): + return SimpleNamespace( + tag=tag, + initial_box_length=initial_box_length, + temperature=temperature, + density=density, + monomer_counts=( + {"mma": 10} + if monomer_counts is None + else monomer_counts + ), + ) + + +def make_writer_without_init( + tmp_path, + *, + settings=None, + reacter_files=None, + sim_name="Test", +): + writer = object.__new__( + DensificationWriter + ) + + writer.settings = ( + settings + if settings is not None + else make_settings() + ) + + if reacter_files is None: + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + reacter_files = make_reacter_files( + force_field_data=ff_file, + ) + + writer.reacter_files = ( + reacter_files + ) + + writer.erate = -0.001 + writer.timestep = 0.01 + writer.out_dir = tmp_path + writer.sim_name = sim_name + + return writer + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_configuration( + tmp_path, + monkeypatch, +): + settings = make_settings() + + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + reacter_files = make_reacter_files( + force_field_data=ff_file, + ) + + simulation = make_simulation() + + calls = [] + + monkeypatch.setattr( + DensificationWriter, + "write_lammps_densification_file", + lambda self, simulation: + ( + calls.append(simulation) + or "in.test_densification" + ), + ) + + writer = DensificationWriter( + out_dir=tmp_path, + settings=settings, + reacter_files=reacter_files, + simulation=simulation, + sim_name="Test", + ) + + assert writer.settings is settings + + assert ( + writer.reacter_files + is reacter_files + ) + + assert writer.out_dir == tmp_path + + assert writer.sim_name == "Test" + + assert writer.erate == pytest.approx( + -0.001 + ) + + assert writer.timestep == pytest.approx( + 0.01 + ) + + assert calls == [ + simulation + ] + + assert ( + writer.in_dense_file_name + == "in.test_densification" + ) + + +# ============================================================================= +# _write_empty_box_data +# ============================================================================= + + +def test_write_empty_box_creates_file( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + output_dir = ( + tmp_path / "box" + ) + + output_dir.mkdir() + + simulation = make_simulation( + initial_box_length=40.0, + ) + + writer._write_empty_box_data( + simulation, + output_dir, + ) + + path = ( + output_dir + / "empty_box.data" + ) + + assert path.is_file() + + +def test_write_empty_box_is_centered_at_origin( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + output_dir = ( + tmp_path / "box" + ) + + output_dir.mkdir() + + writer._write_empty_box_data( + make_simulation( + initial_box_length=40.0, + ), + output_dir, + ) + + text = ( + output_dir + / "empty_box.data" + ).read_text( + encoding="utf-8" + ) + + assert ( + "-20.00 20.00 xlo xhi" + in text + ) + + assert ( + "-20.00 20.00 ylo yhi" + in text + ) + + assert ( + "-20.00 20.00 zlo zhi" + in text + ) + + +def test_write_empty_box_contains_zero_topology_counts( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + output_dir = ( + tmp_path / "box" + ) + + output_dir.mkdir() + + writer._write_empty_box_data( + make_simulation(), + output_dir, + ) + + text = ( + output_dir + / "empty_box.data" + ).read_text( + encoding="utf-8" + ) + + assert "0 atoms" in text + assert "0 bonds" in text + assert "0 angles" in text + assert "0 dihedrals" in text + assert "0 impropers" in text + + +def test_write_empty_box_rounds_bounds_to_two_decimals( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + output_dir = ( + tmp_path / "box" + ) + + output_dir.mkdir() + + writer._write_empty_box_data( + make_simulation( + initial_box_length=33.333, + ), + output_dir, + ) + + text = ( + output_dir + / "empty_box.data" + ).read_text( + encoding="utf-8" + ) + + assert ( + "-16.67 16.67 xlo xhi" + in text + ) + + +# ============================================================================= +# _get_force_field_types +# ============================================================================= + + +def test_get_force_field_types_reads_all_counts( + tmp_path, +): + ff_file = ( + tmp_path / "ff.data" + ) + + ff_file.write_text( + """LAMMPS data file + +12 atom types +8 bond types +6 angle types +4 dihedral types +3 improper types + +Masses +""", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + result = ( + writer._get_force_field_types() + ) + + assert result == { + "atom": 12, + "bond": 8, + "angle": 6, + "dihedral": 4, + "improper": 3, + } + + +def test_get_force_field_types_defaults_improper_to_zero( + tmp_path, +): + ff_file = ( + tmp_path / "ff.data" + ) + + ff_file.write_text( + """10 atom types +5 bond types +4 angle types +3 dihedral types + +Masses +""", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + result = ( + writer._get_force_field_types() + ) + + assert ( + result["improper"] + == 0 + ) + + +def test_get_force_field_types_missing_file_raises( + tmp_path, +): + missing = ( + tmp_path / "missing.data" + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=missing, + ) + ), + ) + + with pytest.raises( + FileNotFoundError, + match=( + "Force field data file " + "not found" + ), + ): + writer._get_force_field_types() + + +@pytest.mark.parametrize( + "missing_key", + [ + "atom", + "bond", + "angle", + "dihedral", + ], +) +def test_get_force_field_types_requires_core_headers( + tmp_path, + missing_key, +): + values = { + "atom": 10, + "bond": 8, + "angle": 6, + "dihedral": 4, + } + + lines = [] + + for key, value in ( + values.items() + ): + if key != missing_key: + lines.append( + f"{value} {key} types" + ) + + lines.append("") + lines.append("Masses") + + ff_file = ( + tmp_path / "ff.data" + ) + + ff_file.write_text( + "\n".join(lines), + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + with pytest.raises( + ValueError, + match=( + f"Required LAMMPS header " + f"'{missing_key} types'" + ), + ): + writer._get_force_field_types() + + +def test_get_force_field_types_stops_at_mass_section( + tmp_path, +): + ff_file = ( + tmp_path / "ff.data" + ) + + ff_file.write_text( + """10 atom types + +Masses + +8 bond types +6 angle types +4 dihedral types +""", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + with pytest.raises( + ValueError, + match="bond types", + ): + writer._get_force_field_types() + + +# ============================================================================= +# _run_calculation +# ============================================================================= + + +def test_default_run_calculation( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + total_steps, thermo = ( + writer._run_calculation() + ) + + assert total_steps == 50000 + assert thermo == 1000 + + +@pytest.mark.parametrize( + ( + "timestep, " + "expected_steps, " + "expected_thermo" + ), + [ + ( + 0.01, + 50000, + 1000, + ), + ( + 0.1, + 5000, + 100, + ), + ( + 1.0, + 500, + 10, + ), + ( + 10.0, + 50, + 1, + ), + ( + 100.0, + 5, + 1, + ), + ], +) +def test_run_calculation_rounding_branches( + tmp_path, + timestep, + expected_steps, + expected_thermo, +): + writer = make_writer_without_init( + tmp_path + ) + + writer.erate = -0.001 + writer.timestep = timestep + + total_steps, thermo = ( + writer._run_calculation() + ) + + assert ( + total_steps + == expected_steps + ) + + assert ( + thermo + == expected_thermo + ) + + +def test_run_calculation_positive_erate_raises( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + writer.erate = 0.001 + + with pytest.raises( + ValueError, + match=( + "Calculated negative steps" + ), + ): + writer._run_calculation() + + +# ============================================================================= +# write_lammps_densification_file +# ============================================================================= + + +def test_write_densification_creates_stage_directory_and_script( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + monomer_file = ( + tmp_path / "mma.molecule" + ) + + monomer_file.write_text( + "mol", + encoding="utf-8", + ) + + rf = make_reacter_files( + force_field_data=ff_file, + molecule_files=[ + make_monomer( + name="mma", + molecule_file=monomer_file, + ) + ], + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=rf, + sim_name="Polymer", + ) + + monkeypatch.setattr( + writer, + "_get_force_field_types", + lambda: { + "atom": 10, + "bond": 20, + "angle": 30, + "dihedral": 40, + "improper": 5, + }, + ) + + monkeypatch.setattr( + writer, + "_run_calculation", + lambda: ( + 12345, + 250, + ), + ) + + monkeypatch.setattr( + writer, + "_copy_required_files", + lambda dest_dir: None, + ) + + monkeypatch.setattr( + dens_module.random, + "randint", + lambda a, b: 12345, + ) + + simulation = make_simulation( + tag="500K", + temperature=500.0, + density=1.23, + monomer_counts={ + "mma": 25, + }, + ) + + filename = ( + writer + .write_lammps_densification_file( + simulation + ) + ) + + stage_dir = ( + tmp_path + / "1_densification" + ) + + assert stage_dir.is_dir() + + assert filename == ( + "in.Polymer_500K_densification" + ) + + assert ( + stage_dir / filename + ).is_file() + + assert ( + stage_dir + / "empty_box.data" + ).is_file() + + +def test_write_densification_contains_force_field_settings( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor="2.0 bin", + neigh_modify=( + "delay 0 every 1 " + "check yes" + ), + ), + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + monkeypatch.setattr( + writer, + "_get_force_field_types", + lambda: { + "atom": 1, + "bond": 2, + "angle": 3, + "dihedral": 4, + "improper": 5, + }, + ) + + monkeypatch.setattr( + writer, + "_run_calculation", + lambda: ( + 1000, + 100, + ), + ) + + monkeypatch.setattr( + writer, + "_copy_required_files", + lambda dest_dir: None, + ) + + monkeypatch.setattr( + dens_module.random, + "randint", + lambda a, b: 11111, + ) + + filename = ( + writer + .write_lammps_densification_file( + make_simulation() + ) + ) + + text = ( + tmp_path + / "1_densification" + / filename + ).read_text( + encoding="utf-8" + ) + + assert ( + "units real" + in text + ) + + assert ( + "dimension 3" + in text + ) + + assert ( + "boundary p p p" + in text + ) + + assert ( + "atom_style full" + in text + ) + + assert ( + "bond_style class2" + in text + ) + + assert ( + "angle_style class2" + in text + ) + + assert ( + "dihedral_style class2" + in text + ) + + assert ( + "improper_style class2" + in text + ) + + assert ( + "pair_style " + "lj/class2/coul/long 12.0" + in text + ) + + assert ( + "neighbor " + "2.0 bin" + in text + ) + + assert ( + "neigh_modify " + "delay 0 every 1 check yes" + in text + ) + + +def test_write_densification_omits_optional_neighbor_commands_when_none( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor=None, + neigh_modify=None, + ), + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + monkeypatch.setattr( + writer, + "_get_force_field_types", + lambda: { + "atom": 1, + "bond": 1, + "angle": 1, + "dihedral": 1, + "improper": 0, + }, + ) + + monkeypatch.setattr( + writer, + "_run_calculation", + lambda: ( + 1000, + 100, + ), + ) + + monkeypatch.setattr( + writer, + "_copy_required_files", + lambda dest_dir: None, + ) + + monkeypatch.setattr( + dens_module.random, + "randint", + lambda a, b: 11111, + ) + + filename = ( + writer + .write_lammps_densification_file( + make_simulation() + ) + ) + + text = ( + tmp_path + / "1_densification" + / filename + ).read_text( + encoding="utf-8" + ) + + assert ( + "\nneighbor " + not in text + ) + + assert ( + "\nneigh_modify " + not in text + ) + + +def test_write_densification_uses_force_field_type_counts( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + monkeypatch.setattr( + writer, + "_get_force_field_types", + lambda: { + "atom": 11, + "bond": 22, + "angle": 33, + "dihedral": 44, + "improper": 55, + }, + ) + + monkeypatch.setattr( + writer, + "_run_calculation", + lambda: ( + 1000, + 100, + ), + ) + + monkeypatch.setattr( + writer, + "_copy_required_files", + lambda dest_dir: None, + ) + + monkeypatch.setattr( + dens_module.random, + "randint", + lambda a, b: 11111, + ) + + filename = ( + writer + .write_lammps_densification_file( + make_simulation() + ) + ) + + text = ( + tmp_path + / "1_densification" + / filename + ).read_text( + encoding="utf-8" + ) + + assert ( + "extra/atom/types 11" + in text + ) + + assert ( + "extra/bond/types 22" + in text + ) + + assert ( + "extra/angle/types 33" + in text + ) + + assert ( + "extra/dihedral/types 44" + in text + ) + + assert ( + "extra/improper/types 55" + in text + ) + + +def test_write_densification_defines_molecules_and_inserts_counts( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + mma_file = ( + tmp_path / "mma.molecule" + ) + + tegdma_file = ( + tmp_path / "tegdma.molecule" + ) + + mma_file.write_text( + "mma", + encoding="utf-8", + ) + + tegdma_file.write_text( + "tegdma", + encoding="utf-8", + ) + + rf = make_reacter_files( + force_field_data=ff_file, + molecule_files=[ + make_monomer( + name="mma", + molecule_file=mma_file, + ), + make_monomer( + name="tegdma", + molecule_file=tegdma_file, + ), + ], + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=rf, + ) + + monkeypatch.setattr( + writer, + "_get_force_field_types", + lambda: { + "atom": 1, + "bond": 1, + "angle": 1, + "dihedral": 1, + "improper": 0, + }, + ) + + monkeypatch.setattr( + writer, + "_run_calculation", + lambda: ( + 5000, + 100, + ), + ) + + monkeypatch.setattr( + writer, + "_copy_required_files", + lambda dest_dir: None, + ) + + seeds = iter( + [ + 11111, + 22222, + 33333, + ] + ) + + monkeypatch.setattr( + dens_module.random, + "randint", + lambda a, b: + next(seeds), + ) + + simulation = make_simulation( + monomer_counts={ + "mma": 25, + "tegdma": 5, + "unknown": 999, + }, + ) + + filename = ( + writer + .write_lammps_densification_file( + simulation + ) + ) + + text = ( + tmp_path + / "1_densification" + / filename + ).read_text( + encoding="utf-8" + ) + + assert ( + "mol_1 mma.molecule" + in text + ) + + assert ( + "mol_2 tegdma.molecule" + in text + ) + + assert ( + "random 25 11111 NULL " + "overlap 2.0 maxtry 100 " + "mol mol_1 11111" + in text + ) + + assert ( + "random 5 22222 NULL " + "overlap 2.0 maxtry 100 " + "mol mol_2 22222" + in text + ) + + assert ( + "random 999" + not in text + ) + + assert ( + "all create 500.0 33333 " + "dist gaussian" + in text + ) + + +def test_molecule_name_falls_back_to_data_id( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + mol_file = ( + tmp_path / "data42.molecule" + ) + + mol_file.write_text( + "mol", + encoding="utf-8", + ) + + rf = make_reacter_files( + force_field_data=ff_file, + molecule_files=[ + make_monomer( + name=None, + data_id="data42", + molecule_file=mol_file, + ) + ], + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=rf, + ) + + monkeypatch.setattr( + writer, + "_get_force_field_types", + lambda: { + "atom": 1, + "bond": 1, + "angle": 1, + "dihedral": 1, + "improper": 0, + }, + ) + + monkeypatch.setattr( + writer, + "_run_calculation", + lambda: ( + 100, + 10, + ), + ) + + monkeypatch.setattr( + writer, + "_copy_required_files", + lambda dest_dir: None, + ) + + monkeypatch.setattr( + dens_module.random, + "randint", + lambda a, b: 12345, + ) + + filename = ( + writer + .write_lammps_densification_file( + make_simulation( + monomer_counts={ + "data42": 7 + } + ) + ) + ) + + text = ( + tmp_path + / "1_densification" + / filename + ).read_text( + encoding="utf-8" + ) + + assert ( + "mol_1 data42.molecule" + in text + ) + + assert ( + "random 7 12345" + in text + ) + + +def test_write_densification_contains_run_conditions( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + monkeypatch.setattr( + writer, + "_get_force_field_types", + lambda: { + "atom": 1, + "bond": 1, + "angle": 1, + "dihedral": 1, + "improper": 0, + }, + ) + + monkeypatch.setattr( + writer, + "_run_calculation", + lambda: ( + 45678, + 321, + ), + ) + + monkeypatch.setattr( + writer, + "_copy_required_files", + lambda dest_dir: None, + ) + + monkeypatch.setattr( + dens_module.random, + "randint", + lambda a, b: 55555, + ) + + simulation = make_simulation( + temperature=373.0, + density=1.25, + ) + + filename = ( + writer + .write_lammps_densification_file( + simulation + ) + ) + + text = ( + tmp_path + / "1_densification" + / filename + ).read_text( + encoding="utf-8" + ) + + assert ( + "nvt temp 373.0 373.0 100.0" + in text + ) + + assert ( + "x erate -0.001 " + "y erate -0.001 " + "z erate -0.001" + in text + ) + + assert ( + "v_my_den > 1.25 " + "error continue" + in text + ) + + # Do not make these assertions depend on cosmetic alignment spacing. + script_lines = ( + text.splitlines() + ) + + assert any( + line.split() + == [ + "thermo", + "321", + ] + for line in script_lines + ) + + assert any( + line.split() + == [ + "run", + "45678", + ] + for line in script_lines + ) + + assert any( + line.split() + == [ + "timestep", + "0.01", + ] + for line in script_lines + ) + + +def test_write_densification_calls_copy_required_files_with_stage_dir( + tmp_path, + monkeypatch, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + monkeypatch.setattr( + writer, + "_get_force_field_types", + lambda: { + "atom": 1, + "bond": 1, + "angle": 1, + "dihedral": 1, + "improper": 0, + }, + ) + + monkeypatch.setattr( + writer, + "_run_calculation", + lambda: ( + 100, + 10, + ), + ) + + monkeypatch.setattr( + dens_module.random, + "randint", + lambda a, b: 12345, + ) + + calls = [] + + monkeypatch.setattr( + writer, + "_copy_required_files", + lambda dest_dir: + calls.append( + dest_dir + ), + ) + + writer.write_lammps_densification_file( + make_simulation() + ) + + assert calls == [ + tmp_path + / "1_densification" + ] + + +# ============================================================================= +# _copy_required_files +# ============================================================================= + + +def test_copy_required_files_copies_force_field( + tmp_path, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "FF", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + copied = ( + dest + / "force_field.data" + ) + + assert copied.is_file() + + assert ( + copied.read_text( + encoding="utf-8" + ) + == "FF" + ) + + +def test_copy_required_files_copies_monomer_molecules( + tmp_path, +): + ff_file = ( + tmp_path / "force_field.data" + ) + + ff_file.write_text( + "FF", + encoding="utf-8", + ) + + mma = ( + tmp_path / "mma.molecule" + ) + + tegdma = ( + tmp_path / "tegdma.molecule" + ) + + mma.write_text( + "MMA", + encoding="utf-8", + ) + + tegdma.write_text( + "TEGDMA", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + molecule_files=[ + make_monomer( + name="mma", + molecule_file=mma, + ), + make_monomer( + name="tegdma", + molecule_file=tegdma, + ), + ], + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest + / "mma.molecule" + ).read_text( + encoding="utf-8" + ) == "MMA" + + assert ( + dest + / "tegdma.molecule" + ).read_text( + encoding="utf-8" + ) == "TEGDMA" + + +def test_copy_required_files_ignores_missing_force_field( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=( + tmp_path + / "missing.data" + ), + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert list( + dest.iterdir() + ) == [] + + +def test_copy_required_files_ignores_missing_molecule_file( + tmp_path, +): + ff_file = ( + tmp_path / "ff.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + molecule_files=[ + make_monomer( + molecule_file=( + tmp_path + / "missing.molecule" + ) + ) + ], + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert not ( + dest + / "missing.molecule" + ).exists() + + +def test_copy_required_files_ignores_none_molecule_path( + tmp_path, +): + ff_file = ( + tmp_path / "ff.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + molecule_files=[ + make_monomer( + molecule_file=None + ) + ], + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / "ff.data" + ).is_file() + + +def test_densification_does_not_copy_reaction_maps( + tmp_path, +): + """ + Reaction maps do NOT belong in 1_densification. + + Both: + RXN_N.map + and the optional: + RXN_N_with_delete_ids.map + + belong to the REACTER/reaction workflow. + """ + ff_file = ( + tmp_path + / "force_field.data" + ) + + ff_file.write_text( + "ff", + encoding="utf-8", + ) + + standard_map = ( + tmp_path + / "RXN_1.map" + ) + + delete_map = ( + tmp_path + / "RXN_1_with_delete_ids.map" + ) + + standard_map.write_text( + "STANDARD", + encoding="utf-8", + ) + + delete_map.write_text( + "DELETE", + encoding="utf-8", + ) + + template = SimpleNamespace( + map_file=standard_map, + map_file_with_delete_ids=delete_map, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + force_field_data=ff_file, + template_files=[ + template + ], + ) + ), + ) + + dest = ( + tmp_path + / "densification" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert not ( + dest + / "RXN_1.map" + ).exists() + + assert not ( + dest + / "RXN_1_with_delete_ids.map" + ).exists() \ No newline at end of file diff --git a/tests/unit/sim_setup/writers/test_lammps_settings.py b/tests/unit/sim_setup/writers/test_lammps_settings.py new file mode 100644 index 00000000..a44b7f81 --- /dev/null +++ b/tests/unit/sim_setup/writers/test_lammps_settings.py @@ -0,0 +1,869 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +from AutoREACTER.sim_setup.writers.lammps_settings import ( + LammpsInitialSettings, + LammpsSettings, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_reacter_files( + in_file, +): + return SimpleNamespace( + in_file=Path(in_file), + ) + + +# ============================================================================= +# LammpsSettings dataclass +# ============================================================================= + + +def test_lammps_settings_stores_all_values(): + settings = LammpsSettings( + units="real", + dimension="3", + boundary="p p p", + atom_style="full", + bond_style="class2", + angle_style="class2", + dihedral_style="class2", + improper_style="class2", + special_bonds="lj/coul 0 0 1", + pair_style="lj/class2/coul/long 8.5", + kspace_style="pppm 1e-4", + pair_modify="tail yes mix sixthpower", + neighbor="2.0 bin", + neigh_modify="delay 0 every 1 check yes", + ) + + assert settings.units == "real" + assert settings.dimension == "3" + assert settings.boundary == "p p p" + assert settings.atom_style == "full" + assert settings.bond_style == "class2" + assert settings.angle_style == "class2" + assert settings.dihedral_style == "class2" + assert settings.improper_style == "class2" + assert settings.special_bonds == "lj/coul 0 0 1" + assert settings.pair_style == "lj/class2/coul/long 8.5" + assert settings.kspace_style == "pppm 1e-4" + assert settings.pair_modify == "tail yes mix sixthpower" + assert settings.neighbor == "2.0 bin" + assert settings.neigh_modify == "delay 0 every 1 check yes" + + +def test_lammps_settings_uses_slots(): + settings = LammpsSettings( + units="real", + dimension="3", + boundary="p p p", + atom_style="full", + bond_style="class2", + angle_style="class2", + dihedral_style="class2", + improper_style="class2", + special_bonds="lj/coul 0 0 1", + pair_style="lj/class2/coul/long 8.5", + kspace_style="pppm 1e-4", + pair_modify="tail yes mix sixthpower", + neighbor=None, + neigh_modify=None, + ) + + with pytest.raises(AttributeError): + settings.extra = "not allowed" + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_reacter_files( + tmp_path, +): + in_file = tmp_path / "in.create_atoms.script" + + reacter_files = make_reacter_files( + in_file + ) + + result = LammpsInitialSettings( + reacter_files + ) + + assert result.reacter_files is reacter_files + + +def test_constructor_stores_lunar_input_file_location( + tmp_path, +): + in_file = tmp_path / "in.create_atoms.script" + + reacter_files = make_reacter_files( + in_file + ) + + result = LammpsInitialSettings( + reacter_files + ) + + assert ( + result.lunar_in_file_location + == in_file + ) + + +# ============================================================================= +# _defults +# ============================================================================= + + +def test_defaults_returns_lammps_settings( + tmp_path, +): + initial = LammpsInitialSettings( + make_reacter_files( + tmp_path / "unused.script" + ) + ) + + result = initial._defults() + + assert isinstance( + result, + LammpsSettings, + ) + + +def test_defaults_exact_values( + tmp_path, +): + initial = LammpsInitialSettings( + make_reacter_files( + tmp_path / "unused.script" + ) + ) + + result = initial._defults() + + assert result.units == "real" + assert result.dimension == "3" + assert result.boundary == "p p p" + assert result.atom_style == "full" + + assert result.bond_style == "class2" + assert result.angle_style == "class2" + assert result.dihedral_style == "class2" + assert result.improper_style == "class2" + + assert result.special_bonds == ( + "lj/coul 0 0 1" + ) + + assert result.pair_style == ( + "lj/class2/coul/long 8.5" + ) + + assert result.kspace_style == ( + "pppm 1e-4" + ) + + assert result.pair_modify == ( + "tail yes mix sixthpower" + ) + + assert result.neighbor is None + assert result.neigh_modify is None + + +def test_defaults_returns_new_object_each_time( + tmp_path, +): + initial = LammpsInitialSettings( + make_reacter_files( + tmp_path / "unused.script" + ) + ) + + first = initial._defults() + second = initial._defults() + + assert first is not second + + +# ============================================================================= +# get_LUNAR_lammps_settings - defaults +# ============================================================================= + + +def test_missing_lunar_input_file_uses_defaults( + tmp_path, +): + initial = LammpsInitialSettings( + make_reacter_files( + tmp_path / "missing.script" + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "real" + assert result.dimension == "3" + assert result.boundary == "p p p" + assert result.atom_style == "full" + + assert result.bond_style == "class2" + assert result.angle_style == "class2" + assert result.dihedral_style == "class2" + assert result.improper_style == "class2" + + assert result.special_bonds == ( + "lj/coul 0 0 1" + ) + + assert result.pair_style == ( + "lj/class2/coul/long 8.5" + ) + + assert result.kspace_style == ( + "pppm 1e-4" + ) + + assert result.pair_modify == ( + "tail yes mix sixthpower" + ) + + assert result.neighbor is None + assert result.neigh_modify is None + + +def test_missing_lunar_input_file_prints_warning( + tmp_path, + capsys, +): + missing = ( + tmp_path / "missing.script" + ) + + initial = LammpsInitialSettings( + make_reacter_files( + missing + ) + ) + + initial.get_LUNAR_lammps_settings() + + output = ( + capsys.readouterr().out + ) + + assert ( + "Could not read LAMMPS input file" + in output + ) + + assert str(missing) in output + + assert ( + "Proceeding with default LAMMPS settings" + in output + ) + + +def test_empty_lunar_input_file_uses_defaults( + tmp_path, +): + in_file = ( + tmp_path / "in.script" + ) + + in_file.write_text( + "", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "real" + + assert result.pair_style == ( + "lj/class2/coul/long 8.5" + ) + + assert result.neighbor is None + + +# ============================================================================= +# Override parsing +# ============================================================================= + + +def test_lunar_file_overrides_single_setting( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + "units metal\n", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "metal" + + # Everything else remains default. + assert result.dimension == "3" + + assert result.atom_style == "full" + + +def test_lunar_file_overrides_multiple_settings( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + """units real +dimension 2 +boundary f f p +atom_style molecular +bond_style harmonic +angle_style harmonic +dihedral_style opls +improper_style cvff +special_bonds lj/coul 0.0 0.0 0.5 +pair_style lj/cut 10.0 +kspace_style ewald 1e-5 +pair_modify mix arithmetic +neighbor 3.0 bin +neigh_modify delay 5 every 2 check no +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "real" + assert result.dimension == "2" + assert result.boundary == "f f p" + + assert ( + result.atom_style + == "molecular" + ) + + assert ( + result.bond_style + == "harmonic" + ) + + assert ( + result.angle_style + == "harmonic" + ) + + assert ( + result.dihedral_style + == "opls" + ) + + assert ( + result.improper_style + == "cvff" + ) + + assert ( + result.special_bonds + == "lj/coul 0.0 0.0 0.5" + ) + + assert ( + result.pair_style + == "lj/cut 10.0" + ) + + assert ( + result.kspace_style + == "ewald 1e-5" + ) + + assert ( + result.pair_modify + == "mix arithmetic" + ) + + assert ( + result.neighbor + == "3.0 bin" + ) + + assert ( + result.neigh_modify + == "delay 5 every 2 check no" + ) + + +def test_inline_comments_are_removed( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + """ +pair_style lj/class2/coul/long 12.0 # cutoff +kspace_style pppm 1.0e-4 # electrostatics +neighbor 2.0 bin # neighbor list +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert ( + result.pair_style + == "lj/class2/coul/long 12.0" + ) + + assert ( + result.kspace_style + == "pppm 1.0e-4" + ) + + assert ( + result.neighbor + == "2.0 bin" + ) + + +def test_full_comment_lines_are_ignored( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + """# units metal +# pair_style lj/cut 15.0 +units real +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "real" + + assert ( + result.pair_style + == "lj/class2/coul/long 8.5" + ) + + +def test_blank_lines_are_ignored( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + """ + +units metal + + +pair_style lj/cut 9.0 + + +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "metal" + + assert ( + result.pair_style + == "lj/cut 9.0" + ) + + +# ============================================================================= +# Prefix matching behavior +# ============================================================================= + + +def test_keyword_must_begin_clean_line( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + """variable units string metal +units real +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "real" + + +def test_leading_whitespace_before_keyword_is_allowed( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + " units metal\n", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "metal" + + +def test_empty_value_does_not_override_default( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + "units\n", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "real" + + +# ============================================================================= +# Current duplicate-line behavior +# ============================================================================= + + +def test_last_matching_line_wins( + tmp_path, +): + """ + Characterization of current nested-loop behavior. + + Every matching line updates the same setting, so the last one wins. + """ + in_file = tmp_path / "in.script" + + in_file.write_text( + """pair_style lj/cut 8.0 +pair_style lj/cut 10.0 +pair_style lj/class2/coul/long 12.0 +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert ( + result.pair_style + == "lj/class2/coul/long 12.0" + ) + + +def test_last_neighbor_line_wins( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + """neighbor 1.0 bin +neighbor 2.0 bin +neighbor 3.0 bin +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert ( + result.neighbor + == "3.0 bin" + ) + + +# ============================================================================= +# Current startswith semantics +# ============================================================================= + + +def test_keyword_matching_currently_uses_startswith( + tmp_path, +): + """ + Characterization test. + + Current code uses: + + clean_line.startswith(keyword) + + rather than requiring a whitespace boundary after the keyword. + + Therefore a line such as "units_extra metal" is interpreted as a + units setting with value "_extra metal". + + This is odd, but do not change production during characterization. + """ + in_file = tmp_path / "in.script" + + in_file.write_text( + "units_extra metal\n", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert ( + result.units + == "_extra metal" + ) + + +def test_pair_style_does_not_override_pair_modify( + tmp_path, +): + in_file = tmp_path / "in.script" + + in_file.write_text( + """pair_style lj/cut 10.0 +pair_modify mix arithmetic +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert ( + result.pair_style + == "lj/cut 10.0" + ) + + assert ( + result.pair_modify + == "mix arithmetic" + ) + + +# ============================================================================= +# Realistic LUNAR-style input +# ============================================================================= + + +def test_realistic_lunar_settings_file( + tmp_path, +): + in_file = ( + tmp_path + / "in.create_atoms.script" + ) + + in_file.write_text( + """# LUNAR generated settings + +units real +dimension 3 +boundary p p p +atom_style full + +bond_style class2 +angle_style class2 +dihedral_style class2 +improper_style class2 + +pair_style lj/class2/coul/long 12.0 +kspace_style pppm 1.0e-4 +pair_modify mix sixthpower + +neighbor 2.0 bin +neigh_modify delay 0 every 1 check yes one 5000 page 100000 +""", + encoding="utf-8", + ) + + initial = LammpsInitialSettings( + make_reacter_files( + in_file + ) + ) + + result = ( + initial + .get_LUNAR_lammps_settings() + ) + + assert result.units == "real" + assert result.dimension == "3" + assert result.boundary == "p p p" + assert result.atom_style == "full" + + assert result.bond_style == "class2" + assert result.angle_style == "class2" + assert result.dihedral_style == "class2" + assert result.improper_style == "class2" + + assert ( + result.pair_style + == "lj/class2/coul/long 12.0" + ) + + assert ( + result.kspace_style + == "pppm 1.0e-4" + ) + + assert ( + result.pair_modify + == "mix sixthpower" + ) + + assert ( + result.neighbor + == "2.0 bin" + ) + + assert ( + result.neigh_modify + == ( + "delay 0 every 1 check yes " + "one 5000 page 100000" + ) + ) \ No newline at end of file diff --git a/tests/unit/sim_setup/writers/test_post_eq_writer.py b/tests/unit/sim_setup/writers/test_post_eq_writer.py new file mode 100644 index 00000000..859d1b3d --- /dev/null +++ b/tests/unit/sim_setup/writers/test_post_eq_writer.py @@ -0,0 +1,1355 @@ +from types import SimpleNamespace + +import pytest + +from AutoREACTER.sim_setup.writers.post_eq_writer import ( + PostEqWriter, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_settings( + *, + neighbor=None, + neigh_modify=None, +): + return SimpleNamespace( + units="real", + dimension="3", + boundary="p p p", + atom_style="full", + bond_style="class2", + angle_style="class2", + dihedral_style="class2", + improper_style="class2", + special_bonds="lj/coul 0 0 1", + pair_style="lj/class2/coul/long 12.0", + kspace_style="pppm 1.0e-4", + pair_modify="mix sixthpower", + neighbor=neighbor, + neigh_modify=neigh_modify, + ) + + +def make_simulation( + *, + tag="sim1", + temperature=500.0, +): + return SimpleNamespace( + tag=tag, + temperature=temperature, + ) + + +def make_writer_without_init( + tmp_path, + *, + settings=None, + sim_name="Test", +): + writer = object.__new__( + PostEqWriter + ) + + writer.settings = ( + settings + if settings is not None + else make_settings() + ) + + writer.out_dir = tmp_path + writer.sim_name = sim_name + + return writer + + +def read_script( + tmp_path, + filename, +): + return ( + tmp_path + / "5_post_equilibration" + / filename + ).read_text( + encoding="utf-8" + ) + + +def command_lines(text): + """ + Return tokenized active LAMMPS commands. + + Comments and blank lines are ignored so tests do not depend on + cosmetic alignment spacing. + """ + commands = [] + + for line in text.splitlines(): + stripped = line.strip() + + if not stripped: + continue + + if stripped.startswith("#"): + continue + + commands.append( + stripped.split() + ) + + return commands + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_configuration_and_writes_file( + tmp_path, + monkeypatch, +): + settings = make_settings() + + simulation = make_simulation() + + calls = [] + + def fake_write( + self, + *, + simulation, + write_second_reaction_stage=True, + ): + calls.append( + ( + simulation, + write_second_reaction_stage, + ) + ) + + return "in.test_post_equilibration" + + monkeypatch.setattr( + PostEqWriter, + "write_post_eq_file", + fake_write, + ) + + writer = PostEqWriter( + out_dir=tmp_path, + settings=settings, + simulation=simulation, + sim_name="Polymer", + ) + + assert writer.settings is settings + assert writer.out_dir == tmp_path + assert writer.sim_name == "Polymer" + + assert calls == [ + ( + simulation, + True, + ) + ] + + +def test_constructor_forwards_false_second_stage_flag( + tmp_path, + monkeypatch, +): + calls = [] + + def fake_write( + self, + *, + simulation, + write_second_reaction_stage=True, + ): + calls.append( + write_second_reaction_stage + ) + + return "in.test" + + monkeypatch.setattr( + PostEqWriter, + "write_post_eq_file", + fake_write, + ) + + PostEqWriter( + out_dir=tmp_path, + settings=make_settings(), + simulation=make_simulation(), + sim_name="Polymer", + write_second_reaction_stage=False, + ) + + assert calls == [ + False + ] + + +# ============================================================================= +# File generation +# ============================================================================= + + +def test_write_post_eq_creates_stage_directory( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + writer.write_post_eq_file( + make_simulation() + ) + + assert ( + tmp_path + / "5_post_equilibration" + ).is_dir() + + +def test_write_post_eq_creates_expected_input_file( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_post_eq_file( + make_simulation( + tag="500K" + ) + ) + + assert filename == ( + "in.Polymer_500K_post_equilibration" + ) + + assert ( + tmp_path + / "5_post_equilibration" + / filename + ).is_file() + + +def test_write_post_eq_returns_only_filename( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + assert isinstance( + filename, + str, + ) + + assert "/" not in filename + assert "\\" not in filename + + +def test_script_header_contains_tag_and_autoreacter( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Epoxy", + ) + + filename = writer.write_post_eq_file( + make_simulation( + tag="373K" + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert ( + "#Epoxy_373K " + "Post-Equilibration Script" + in text + ) + + assert "Generated" in text + + assert ( + "by AutoREACTER" + in text + ) + + +# ============================================================================= +# Input reacted data selection +# ============================================================================= + + +def test_default_reads_second_reaction_stage_output( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_post_eq_file( + make_simulation( + tag="500K" + ), + write_second_reaction_stage=True, + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "read_data", + "Polymer_500K_reacted_1M-3.5_5.0A.data", + "&", + ] in commands + + +def test_false_second_stage_reads_first_reaction_output( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_post_eq_file( + make_simulation( + tag="500K" + ), + write_second_reaction_stage=False, + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "read_data", + "Polymer_500K_reacted_0M-1M_3.5A.data", + "&", + ] in commands + + +def test_read_data_includes_extra_topology_capacity( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + text = read_script( + tmp_path, + filename, + ) + + assert ( + "extra/bond/per/atom 50" + in text + ) + + assert ( + "extra/angle/per/atom 50" + in text + ) + + assert ( + "extra/dihedral/per/atom 50" + in text + ) + + assert ( + "extra/improper/per/atom 50" + in text + ) + + assert ( + "extra/special/per/atom 50" + in text + ) + + +# ============================================================================= +# LAMMPS settings +# ============================================================================= + + +def test_script_contains_core_lammps_settings( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "units", + "real", + ] in commands + + assert [ + "dimension", + "3", + ] in commands + + assert [ + "boundary", + "p", + "p", + "p", + ] in commands + + assert [ + "atom_style", + "full", + ] in commands + + +def test_script_contains_force_field_styles( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "angle_style", + "class2", + ] in commands + + assert [ + "bond_style", + "class2", + ] in commands + + assert [ + "dihedral_style", + "class2", + ] in commands + + assert [ + "improper_style", + "class2", + ] in commands + + +def test_script_contains_pair_settings( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "pair_style", + "lj/class2/coul/long", + "12.0", + ] in commands + + assert [ + "kspace_style", + "pppm", + "1.0e-4", + ] in commands + + assert [ + "pair_modify", + "mix", + "sixthpower", + ] in commands + + +def test_neighbor_is_written_when_defined( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor="2.0 bin", + ), + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "neighbor", + "2.0", + "bin", + ] in commands + + +def test_neigh_modify_is_written_when_defined( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neigh_modify=( + "delay 0 every 1 " + "check yes one 5000 " + "page 100000" + ), + ), + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "neigh_modify", + "delay", + "0", + "every", + "1", + "check", + "yes", + "one", + "5000", + "page", + "100000", + ] in commands + + +def test_neighbor_commands_omitted_when_none( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor=None, + neigh_modify=None, + ), + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + keywords = [ + command[0] + for command in commands + ] + + assert "neighbor" not in keywords + assert "neigh_modify" not in keywords + + +# ============================================================================= +# Setup / minimization +# ============================================================================= + + +def test_script_contains_minimization( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "minimize", + "0.0", + "1.0e-8", + "1000", + "100000", + ] in commands + + +def test_script_resets_timestep( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "reset_timestep", + "0", + ] in commands + + +def test_script_uses_one_fs_timestep( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "timestep", + "1", + ] in commands + + +def test_script_uses_thermo_1000( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "thermo", + "1000", + ] in commands + + +def test_script_contains_expected_thermo_style( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "thermo_style", + "custom", + "step", + "time", + "temp", + "press", + "density", + "vol", + "pe", + "ke", + "etotal", + ] in commands + + +# ============================================================================= +# Dump / restart +# ============================================================================= + + +def test_script_contains_expected_dump( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_post_eq_file( + make_simulation( + tag="500K" + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "dump", + "dump_1", + "all", + "xyz", + "100", + "Polymer_500K_post_equilibration.xyz", + ] in commands + + +def test_script_sets_dump_type_labels( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "dump_modify", + "dump_1", + "types", + "labels", + ] in commands + + +def test_script_contains_rotating_restart_files( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_post_eq_file( + make_simulation( + tag="500K" + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "restart", + "100", + "Polymer_500K_post_equilibration_backup1.restart", + "Polymer_500K_post_equilibration_backup2.restart", + ] in commands + + +# ============================================================================= +# Stage 1 - NVT cool to 300 K +# ============================================================================= + + +def test_stage_1_nvt_cools_from_sim_temperature_to_300( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation( + temperature=523.0 + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "fix", + "nvt_1", + "all", + "nvt", + "temp", + "523.0", + "300.0", + "100.0", + ] in commands + + +def test_stage_1_runs_100000_steps( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + run_commands = [ + command + for command in commands + if command[0] == "run" + ] + + assert run_commands[0] == [ + "run", + "100000", + ] + + +def test_stage_1_unfixes_nvt_1( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "unfix", + "nvt_1", + ] in commands + + +# ============================================================================= +# Stage 2 - NPT +# ============================================================================= + + +def test_stage_2_uses_npt_at_300_k_and_zero_pressure( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "fix", + "npt_2", + "all", + "npt", + "temp", + "300.0", + "300.0", + "100.0", + "iso", + "0.0", + "0.0", + "1000.0", + ] in commands + + +def test_stage_2_unfixes_npt_2( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "unfix", + "npt_2", + ] in commands + + +# ============================================================================= +# Stage 3 - final NVT +# ============================================================================= + + +def test_stage_3_final_nvt_is_at_300_k( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "fix", + "nvt_3", + "all", + "nvt", + "temp", + "300.0", + "300.0", + "100.0", + ] in commands + + +def test_stage_3_unfixes_nvt_3( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "unfix", + "nvt_3", + ] in commands + + +def test_exactly_three_run_commands_each_100000_steps( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + run_commands = [ + command + for command in commands + if command[0] == "run" + ] + + assert run_commands == [ + [ + "run", + "100000", + ], + [ + "run", + "100000", + ], + [ + "run", + "100000", + ], + ] + + +def test_exactly_three_active_fix_commands( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + fixes = [ + command + for command in commands + if command[0] == "fix" + ] + + assert len(fixes) == 3 + + assert fixes[0][1] == "nvt_1" + assert fixes[1][1] == "npt_2" + assert fixes[2][1] == "nvt_3" + + +# ============================================================================= +# Output / cleanup +# ============================================================================= + + +def test_script_undumps_trajectory( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "undump", + "dump_1", + ] in commands + + +def test_script_writes_post_equilibrated_data( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_post_eq_file( + make_simulation( + tag="500K" + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "write_data", + "Polymer_500K_post_equilibrated.data", + ] in commands + + +# ============================================================================= +# Workflow order +# ============================================================================= + + +def test_major_commands_are_in_expected_order( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + keywords = [ + command[0] + for command in commands + ] + + read_index = keywords.index( + "read_data" + ) + + minimize_index = keywords.index( + "minimize" + ) + + first_fix_index = keywords.index( + "fix" + ) + + first_run_index = keywords.index( + "run" + ) + + write_index = keywords.index( + "write_data" + ) + + assert ( + read_index + < minimize_index + < first_fix_index + < first_run_index + < write_index + ) + + +def test_fix_and_unfix_order_is_preserved( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + fix_sequence = [ + command[:2] + for command in commands + if command[0] in { + "fix", + "unfix", + } + ] + + assert fix_sequence == [ + [ + "fix", + "nvt_1", + ], + [ + "unfix", + "nvt_1", + ], + [ + "fix", + "npt_2", + ], + [ + "unfix", + "npt_2", + ], + [ + "fix", + "nvt_3", + ], + [ + "unfix", + "nvt_3", + ], + ] + + +# ============================================================================= +# Reaction-map separation +# ============================================================================= + + +def test_post_equilibration_script_contains_no_reaction_map_commands( + tmp_path, +): + """ + Post-equilibration consumes an already-reacted data file. + + Standard RXN_N.map files and optional RXN_N_with_delete_ids.map files + are reaction-stage inputs and must not be referenced here. + """ + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "RXN_" not in text + + assert ".map" not in text + + +def test_post_equilibration_contains_no_bond_react_fix( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_post_eq_file( + make_simulation() + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "bond/react" not in text diff --git a/tests/unit/sim_setup/writers/test_pre_eq_writer.py b/tests/unit/sim_setup/writers/test_pre_eq_writer.py new file mode 100644 index 00000000..4dec901c --- /dev/null +++ b/tests/unit/sim_setup/writers/test_pre_eq_writer.py @@ -0,0 +1,1215 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +from AutoREACTER.sim_setup.writers.pre_eq_writer import ( + PreEqWriter, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_settings( + *, + neighbor=None, + neigh_modify=None, +): + return SimpleNamespace( + units="real", + dimension="3", + boundary="p p p", + atom_style="full", + bond_style="class2", + angle_style="class2", + dihedral_style="class2", + improper_style="class2", + special_bonds="lj/coul 0 0 1", + pair_style="lj/class2/coul/long 12.0", + kspace_style="pppm 1.0e-4", + pair_modify="mix sixthpower", + neighbor=neighbor, + neigh_modify=neigh_modify, + ) + + +def make_simulation( + *, + tag="sim1", + temperature=500.0, +): + return SimpleNamespace( + tag=tag, + temperature=temperature, + ) + + +def make_writer_without_init( + tmp_path, + *, + settings=None, + sim_name="Test", +): + writer = object.__new__( + PreEqWriter + ) + + writer.settings = ( + settings + if settings is not None + else make_settings() + ) + + writer.out_dir = tmp_path + writer.sim_name = sim_name + + return writer + + +def read_script( + tmp_path, + filename, +): + return ( + tmp_path + / "2_pre_equilibration" + / filename + ).read_text( + encoding="utf-8" + ) + + +def command_lines(text): + """ + Return tokenized non-comment, non-empty LAMMPS commands. + + This avoids fragile assertions based on cosmetic column spacing. + """ + result = [] + + for line in text.splitlines(): + stripped = line.strip() + + if not stripped: + continue + + if stripped.startswith("#"): + continue + + result.append( + stripped.split() + ) + + return result + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_configuration( + tmp_path, + monkeypatch, +): + settings = make_settings() + + simulation = make_simulation() + + calls = [] + + monkeypatch.setattr( + PreEqWriter, + "write_pre_eq_file", + lambda self, simulation: + ( + calls.append(simulation) + or "in.test_pre_equilibration" + ), + ) + + writer = PreEqWriter( + out_dir=tmp_path, + settings=settings, + simulation=simulation, + sim_name="Polymer", + ) + + assert writer.settings is settings + assert writer.out_dir == tmp_path + assert writer.sim_name == "Polymer" + + assert calls == [ + simulation + ] + + assert ( + writer.in_pre_eq_file_name + == "in.test_pre_equilibration" + ) + + +# ============================================================================= +# Basic file generation +# ============================================================================= + + +def test_write_pre_eq_creates_stage_directory( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + writer.write_pre_eq_file( + make_simulation() + ) + + assert ( + tmp_path + / "2_pre_equilibration" + ).is_dir() + + +def test_write_pre_eq_creates_input_file( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_pre_eq_file( + make_simulation( + tag="500K" + ) + ) + + assert filename == ( + "in.Polymer_500K_pre_equilibration" + ) + + assert ( + tmp_path + / "2_pre_equilibration" + / filename + ).is_file() + + +def test_write_pre_eq_returns_only_filename( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + assert isinstance( + filename, + str, + ) + + assert "/" not in filename + assert "\\" not in filename + + +def test_script_header_contains_tag_and_autoreacter( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Epoxy", + ) + + filename = writer.write_pre_eq_file( + make_simulation( + tag="373K" + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert ( + "# Epoxy_373K " + "Pre-Equilibration Script" + in text + ) + + assert ( + "Generated" + in text + ) + + assert ( + "by AutoREACTER" + in text + ) + + +# ============================================================================= +# LAMMPS settings +# ============================================================================= + + +def test_script_contains_core_lammps_settings( + tmp_path, +): + settings = make_settings() + + writer = make_writer_without_init( + tmp_path, + settings=settings, + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "units", + "real", + ] in commands + + assert [ + "dimension", + "3", + ] in commands + + assert [ + "boundary", + "p", + "p", + "p", + ] in commands + + assert [ + "atom_style", + "full", + ] in commands + + +def test_script_contains_force_field_styles( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "bond_style", + "class2", + ] in commands + + assert [ + "angle_style", + "class2", + ] in commands + + assert [ + "dihedral_style", + "class2", + ] in commands + + assert [ + "improper_style", + "class2", + ] in commands + + +def test_script_contains_pair_settings( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "pair_style", + "lj/class2/coul/long", + "12.0", + ] in commands + + assert [ + "kspace_style", + "pppm", + "1.0e-4", + ] in commands + + assert [ + "pair_modify", + "mix", + "sixthpower", + ] in commands + + +def test_optional_neighbor_setting_is_written( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor="2.0 bin", + ), + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "neighbor", + "2.0", + "bin", + ] in commands + + +def test_optional_neigh_modify_setting_is_written( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neigh_modify=( + "delay 0 every 1 " + "check yes one 5000 " + "page 100000" + ), + ), + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "neigh_modify", + "delay", + "0", + "every", + "1", + "check", + "yes", + "one", + "5000", + "page", + "100000", + ] in commands + + +def test_optional_neighbor_commands_are_omitted_when_none( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor=None, + neigh_modify=None, + ), + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + keywords = [ + command[0] + for command in commands + ] + + assert "neighbor" not in keywords + assert "neigh_modify" not in keywords + + +# ============================================================================= +# Input from densification +# ============================================================================= + + +def test_script_reads_shrinked_box_from_previous_stage( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_pre_eq_file( + make_simulation( + tag="500K" + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "read_data", + "Polymer_500K_shrinked_box.data", + "&", + ] in commands + + +def test_read_data_includes_extra_topology_capacity( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + text = read_script( + tmp_path, + filename, + ) + + assert ( + "extra/bond/per/atom 50" + in text + ) + + assert ( + "extra/angle/per/atom 50" + in text + ) + + assert ( + "extra/dihedral/per/atom 50" + in text + ) + + assert ( + "extra/improper/per/atom 50" + in text + ) + + assert ( + "extra/special/per/atom 50" + in text + ) + + +# ============================================================================= +# Minimization / base simulation setup +# ============================================================================= + + +def test_script_contains_initial_minimization( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "minimize", + "0.0", + "1.0e-8", + "1000", + "100000", + ] in commands + + +def test_script_resets_timestep( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "reset_timestep", + "0", + ] in commands + + +def test_script_uses_one_fs_timestep( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "timestep", + "1", + ] in commands + + +def test_script_uses_thermo_interval_1000( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "thermo", + "1000", + ] in commands + + +def test_script_contains_expected_thermo_style( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "thermo_style", + "custom", + "step", + "time", + "temp", + "press", + "density", + "vol", + "pe", + "ke", + "etotal", + ] in commands + + +# ============================================================================= +# Dump / restart +# ============================================================================= + + +def test_script_contains_expected_dump( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_pre_eq_file( + make_simulation( + tag="298K" + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "dump", + "dump_2", + "all", + "xyz", + "1000", + "Polymer_298K_pre_equilibration.xyz", + ] in commands + + +def test_script_sets_dump_type_labels( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "dump_modify", + "dump_2", + "types", + "labels", + ] in commands + + +def test_script_contains_two_restart_files( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_pre_eq_file( + make_simulation( + tag="500K" + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "restart", + "100", + "Polymer_500K_pre_equilibration_backup1.restart", + "Polymer_500K_pre_equilibration_backup2.restart", + ] in commands + + +# ============================================================================= +# Stage 1 - NVT temperature ramp +# ============================================================================= + + +def test_stage_1_ramps_from_298_15_to_target_temperature( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation( + temperature=523.0 + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "fix", + "nvt_1", + "all", + "nvt", + "temp", + "298.15", + "523.0", + "100.0", + ] in commands + + +def test_stage_1_runs_50000_steps( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + run_commands = [ + command + for command in commands + if command[0] == "run" + ] + + assert run_commands[0] == [ + "run", + "50000", + ] + + +def test_stage_1_unfixes_nvt_1( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "unfix", + "nvt_1", + ] in commands + + +# ============================================================================= +# Current Stage 2 behavior +# ============================================================================= + + +def test_stage_2_is_final_nvt_at_target_temperature( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation( + temperature=373.0 + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "fix", + "nvt_3", + "all", + "nvt", + "temp", + "373.0", + "373.0", + "100.0", + ] in commands + + +def test_stage_2_runs_50000_steps( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + run_commands = [ + command + for command in commands + if command[0] == "run" + ] + + assert run_commands == [ + [ + "run", + "50000", + ], + [ + "run", + "50000", + ], + ] + + +def test_stage_2_unfixes_nvt_3( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "unfix", + "nvt_3", + ] in commands + + +def test_current_script_contains_no_active_npt_fix( + tmp_path, +): + """ + Characterization of CURRENT runtime behavior. + + The docstring/comments still refer to an NPT stage, but the NPT code + itself is commented out in production. Generated scripts therefore + contain no active NPT command. + """ + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + active_npt_commands = [ + command + for command in commands + if "npt" in command + ] + + assert active_npt_commands == [] + + +def test_current_script_has_exactly_two_active_fix_commands( + tmp_path, +): + """ + Current equilibration workflow contains: + nvt_1 + nvt_3 + + No active npt_2. + """ + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + fix_commands = [ + command + for command in commands + if command[0] == "fix" + ] + + assert len(fix_commands) == 2 + + assert fix_commands[0][1] == "nvt_1" + assert fix_commands[1][1] == "nvt_3" + + +# ============================================================================= +# Cleanup / output +# ============================================================================= + + +def test_script_undumps_dump_2( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "undump", + "dump_2", + ] in commands + + +def test_script_writes_pre_equilibrated_data( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = writer.write_pre_eq_file( + make_simulation( + tag="500K" + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "write_data", + "Polymer_500K_pre_equilibrated.data", + ] in commands + + +# ============================================================================= +# Ordering / workflow characterization +# ============================================================================= + + +def test_major_commands_are_in_expected_order( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation() + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + keywords = [ + command[0] + for command in commands + ] + + read_index = keywords.index( + "read_data" + ) + + minimize_index = keywords.index( + "minimize" + ) + + first_fix_index = keywords.index( + "fix" + ) + + first_run_index = keywords.index( + "run" + ) + + write_index = keywords.index( + "write_data" + ) + + assert ( + read_index + < minimize_index + < first_fix_index + < first_run_index + < write_index + ) + + +def test_two_nvt_stages_use_simulation_temperature( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = writer.write_pre_eq_file( + make_simulation( + temperature=600.0 + ) + ) + + commands = command_lines( + read_script( + tmp_path, + filename, + ) + ) + + nvt_1 = next( + command + for command in commands + if ( + command[0] == "fix" + and command[1] == "nvt_1" + ) + ) + + nvt_3 = next( + command + for command in commands + if ( + command[0] == "fix" + and command[1] == "nvt_3" + ) + ) + + assert nvt_1 == [ + "fix", + "nvt_1", + "all", + "nvt", + "temp", + "298.15", + "600.0", + "100.0", + ] + + assert nvt_3 == [ + "fix", + "nvt_3", + "all", + "nvt", + "temp", + "600.0", + "600.0", + "100.0", + ] \ No newline at end of file From ced912b5fa48c650a00d5bda6e147d0193b2bec7 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 19:05:45 -0400 Subject: [PATCH 152/176] Add writer tests and disable stage 2 by default --- AutoREACTER/input_parser.py | 2 +- .../writers/rxn_second_stage_writer.py | 53 +- tests/unit/sim_setup/test_simulation_setup.py | 927 +++++++ .../writers/test_rxn_first_stage_writer.py | 2167 +++++++++++++++ .../writers/test_rxn_second_stage_writer.py | 2402 +++++++++++++++++ tests/unit/sim_setup/writers/test_writer.py | 1173 ++++++++ tests/unit/test_input_parser.py | 2 +- 7 files changed, 6716 insertions(+), 10 deletions(-) create mode 100644 tests/unit/sim_setup/test_simulation_setup.py create mode 100644 tests/unit/sim_setup/writers/test_rxn_first_stage_writer.py create mode 100644 tests/unit/sim_setup/writers/test_rxn_second_stage_writer.py create mode 100644 tests/unit/sim_setup/writers/test_writer.py diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 56b06705..26af33bb 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -174,7 +174,7 @@ class SimulationSetup: reaction_iteration_depth: int = 5 wildcards: bool = True deduplicate_reaction_templates: bool = True - write_second_reaction_stage: bool = True + write_second_reaction_stage: bool = False class InputParser: diff --git a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py index 9c7166bc..a099d21b 100644 --- a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py @@ -129,6 +129,7 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: # Add optional neighbor list settings if specified. if s.neighbor: lines.append(f"{'neighbor':<16} {s.neighbor}") + if s.neigh_modify: lines.append(f"{'neigh_modify':<16} {s.neigh_modify}") @@ -166,15 +167,24 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: # Extract molecule and mapping file names from template objects. pre_file = template.pre_reaction_file.name post_file = template.post_reaction_file.name + + # AutoREACTER always uses the standard map by default. + # The optional *_with_delete_ids.map file is only provided to the user. map_file = template.map_file.name # Register molecule templates in LAMMPS. - lines.append(f"{'molecule':<16} {pre_id:<16} {pre_file}") - lines.append(f"{'molecule':<16} {post_id:<16} {post_file}\n") + lines.append( + f"{'molecule':<16} {pre_id:<16} {pre_file}" + ) + + lines.append( + f"{'molecule':<16} {post_id:<16} {post_file}\n" + ) # Build reaction command with cutoff at 5.0 Angstroms for inter-molecular reactions. # stabilize_steps: equilibration steps after reaction to prevent explosion. rxn_stp = f"rxn_stp_{reaction_id}" + rxn_str = ( f"react " f"{rxn_stp:<15} " @@ -184,6 +194,7 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: f"{map_file:<15} " f"stabilize_steps 200 rescale_charges yes" ) + rxn_commands.append(rxn_str) # Combine all reaction commands with line continuation. @@ -192,7 +203,10 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: # Use explicit f_rxns[i] fields because some LAMMPS builds do not accept f_rxns[*]. rxn_thermo_values = " ".join( f"f_rxns[{position}]" - for position in range(1, len(rxn_commands) + 1) + for position in range( + 1, + len(rxn_commands) + 1 + ) ) # Configure bond/react fix with stabilization groups and define fixes for simulation. @@ -221,11 +235,14 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: # ----- Write the .in file -------------------------------------- in_file_path = rxn_dir / f"in.{tag}_reaction_stage_2" + with open(in_file_path, "w") as f: f.write("\n".join(lines)) # ----- Copy auxiliary files into the reaction directory --------- - self._copy_required_files(dest_dir=rxn_dir) + self._copy_required_files( + dest_dir=rxn_dir + ) return in_file_path.name @@ -233,8 +250,12 @@ def _copy_required_files(self, dest_dir: Path) -> None: """ Copy reaction template and molecule definition files to the output directory. - Copies pre-reaction molecules, post-reaction molecules, and atom mapping files - required by LAMMPS to the simulation directory for execution. + The standard RXN_N.map file is always copied and remains the map used + by AutoREACTER's generated LAMMPS input script. + + If an optional RXN_N_with_delete_ids.map file exists, it is also copied + into the stage directory for the user. AutoREACTER does not automatically + use the supplementary DeleteIDs map. Args: dest_dir (Path): Destination directory for copied files. @@ -248,17 +269,33 @@ def _copy_required_files(self, dest_dir: Path) -> None: t for t in rf.template_files if getattr(t, "activity_stats", True) ]: - # Collect all files associated with this reaction template. + # Standard files required by the generated LAMMPS script. files: list[Path] = [ template.map_file, template.pre_reaction_file, template.post_reaction_file, ] + # Optional supplementary DeleteIDs map. + map_file_with_delete_ids = getattr( + template, + "map_file_with_delete_ids", + None, + ) + + if map_file_with_delete_ids is not None: + files.append( + map_file_with_delete_ids + ) + # Copy each file to the destination, preserving metadata. for file in files: if file is None or not file.exists(): raise FileNotFoundError( f"Required reaction file not found: {file}" ) - shutil.copy2(file, dest_dir / file.name) + + shutil.copy2( + file, + dest_dir / file.name, + ) \ No newline at end of file diff --git a/tests/unit/sim_setup/test_simulation_setup.py b/tests/unit/sim_setup/test_simulation_setup.py new file mode 100644 index 00000000..b26c52a7 --- /dev/null +++ b/tests/unit/sim_setup/test_simulation_setup.py @@ -0,0 +1,927 @@ +from types import SimpleNamespace + +import pytest + +import AutoREACTER.sim_setup.simulation_setup as sim_setup_module +from AutoREACTER.sim_setup.simulation_setup import ( + SimulationSetupManager, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_session( + tmp_path, + *, + inputs=None, + reacter_files=None, +): + if inputs is None: + inputs = SimpleNamespace( + simulation_name="Polymer", + simulations=[], + write_second_reaction_stage=False, + ) + + if reacter_files is None: + reacter_files = SimpleNamespace() + + return SimpleNamespace( + inputs=inputs, + reacter_files=reacter_files, + output_dir=tmp_path, + ) + + +# ============================================================================= +# setup_and_write_simulation +# ============================================================================= + + +def test_setup_and_write_simulation_creates_property_calculator( + tmp_path, + monkeypatch, +): + inputs = SimpleNamespace( + simulation_name="Polymer", + ) + + session = make_session( + tmp_path, + inputs=inputs, + ) + + captured = {} + + class FakeCalculator: + def __init__(self, setup): + captured["setup"] = setup + + def process_all(self): + return inputs + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + lambda self, **kwargs: None, + ) + + manager = SimulationSetupManager() + + manager.setup_and_write_simulation( + session + ) + + assert ( + captured["setup"] + is inputs + ) + + +def test_setup_and_write_simulation_calls_process_all_once( + tmp_path, + monkeypatch, +): + inputs = SimpleNamespace( + simulation_name="Polymer", + ) + + session = make_session( + tmp_path, + inputs=inputs, + ) + + calls = [] + + class FakeCalculator: + def __init__(self, setup): + self.setup = setup + + def process_all(self): + calls.append( + "process_all" + ) + + return self.setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + lambda self, **kwargs: None, + ) + + manager = SimulationSetupManager() + + manager.setup_and_write_simulation( + session + ) + + assert calls == [ + "process_all" + ] + + +def test_setup_and_write_simulation_passes_updated_setup_to_writer_layer( + tmp_path, + monkeypatch, +): + original_setup = SimpleNamespace( + simulation_name="Original", + ) + + updated_setup = SimpleNamespace( + simulation_name="Updated", + ) + + reacter_files = SimpleNamespace( + template_files=[] + ) + + session = make_session( + tmp_path, + inputs=original_setup, + reacter_files=reacter_files, + ) + + class FakeCalculator: + def __init__(self, setup): + assert ( + setup + is original_setup + ) + + def process_all(self): + return updated_setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + captured = {} + + def fake_generate( + self, + *, + setup, + reacter_files, + run_dir, + ): + captured["setup"] = setup + captured["reacter_files"] = reacter_files + captured["run_dir"] = run_dir + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + fake_generate, + ) + + manager = SimulationSetupManager() + + manager.setup_and_write_simulation( + session + ) + + assert ( + captured["setup"] + is updated_setup + ) + + assert ( + captured["reacter_files"] + is reacter_files + ) + + assert ( + captured["run_dir"] + == tmp_path + ) + + +def test_setup_and_write_simulation_uses_session_reacter_files( + tmp_path, + monkeypatch, +): + setup = SimpleNamespace( + simulation_name="Polymer", + ) + + reacter_files = SimpleNamespace( + marker="reaction-files" + ) + + session = make_session( + tmp_path, + inputs=setup, + reacter_files=reacter_files, + ) + + class FakeCalculator: + def __init__(self, setup): + self.setup = setup + + def process_all(self): + return self.setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + captured = {} + + def fake_generate( + self, + *, + setup, + reacter_files, + run_dir, + ): + captured["reacter_files"] = ( + reacter_files + ) + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + fake_generate, + ) + + manager = SimulationSetupManager() + + manager.setup_and_write_simulation( + session + ) + + assert ( + captured["reacter_files"] + is reacter_files + ) + + +def test_setup_and_write_simulation_uses_session_output_dir( + tmp_path, + monkeypatch, +): + setup = SimpleNamespace( + simulation_name="Polymer", + ) + + session = make_session( + tmp_path, + inputs=setup, + ) + + class FakeCalculator: + def __init__(self, setup): + self.setup = setup + + def process_all(self): + return self.setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + captured = {} + + def fake_generate( + self, + *, + setup, + reacter_files, + run_dir, + ): + captured["run_dir"] = run_dir + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + fake_generate, + ) + + manager = SimulationSetupManager() + + manager.setup_and_write_simulation( + session + ) + + assert ( + captured["run_dir"] + == tmp_path + ) + + +def test_setup_and_write_simulation_calls_calculation_before_generation( + tmp_path, + monkeypatch, +): + setup = SimpleNamespace( + simulation_name="Polymer", + ) + + session = make_session( + tmp_path, + inputs=setup, + ) + + events = [] + + class FakeCalculator: + def __init__(self, setup): + events.append( + "calculator_init" + ) + + self.setup = setup + + def process_all(self): + events.append( + "process_all" + ) + + return self.setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + def fake_generate( + self, + **kwargs, + ): + events.append( + "generate_input_files" + ) + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + fake_generate, + ) + + manager = SimulationSetupManager() + + manager.setup_and_write_simulation( + session + ) + + assert events == [ + "calculator_init", + "process_all", + "generate_input_files", + ] + + +def test_setup_and_write_simulation_returns_none( + tmp_path, + monkeypatch, +): + setup = SimpleNamespace( + simulation_name="Polymer", + ) + + session = make_session( + tmp_path, + inputs=setup, + ) + + class FakeCalculator: + def __init__(self, setup): + self.setup = setup + + def process_all(self): + return self.setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + lambda self, **kwargs: None, + ) + + manager = SimulationSetupManager() + + result = ( + manager + .setup_and_write_simulation( + session + ) + ) + + assert result is None + + +def test_setup_and_write_simulation_prints_success_message( + tmp_path, + monkeypatch, + capsys, +): + setup = SimpleNamespace( + simulation_name="Polymer", + ) + + session = make_session( + tmp_path, + inputs=setup, + ) + + class FakeCalculator: + def __init__(self, setup): + self.setup = setup + + def process_all(self): + return self.setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + lambda self, **kwargs: None, + ) + + manager = SimulationSetupManager() + + manager.setup_and_write_simulation( + session + ) + + captured = ( + capsys.readouterr() + ) + + expected_path = ( + tmp_path + / "LAMMPS_input_files" + ) + + assert ( + "[SUCCESS]" + in captured.out + ) + + assert ( + "All 5 simulation stages written" + in captured.out + ) + + assert ( + str(expected_path) + in captured.out + ) + + +# ============================================================================= +# Failure propagation +# ============================================================================= + + +def test_calculation_error_propagates_and_generation_is_not_called( + tmp_path, + monkeypatch, +): + session = make_session( + tmp_path + ) + + class FakeCalculator: + def __init__(self, setup): + pass + + def process_all(self): + raise ValueError( + "calculation failed" + ) + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + called = [] + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + lambda self, **kwargs: + called.append(True), + ) + + manager = SimulationSetupManager() + + with pytest.raises( + ValueError, + match="calculation failed", + ): + manager.setup_and_write_simulation( + session + ) + + assert called == [] + + +def test_generation_error_propagates( + tmp_path, + monkeypatch, +): + setup = SimpleNamespace( + simulation_name="Polymer", + ) + + session = make_session( + tmp_path, + inputs=setup, + ) + + class FakeCalculator: + def __init__(self, setup): + self.setup = setup + + def process_all(self): + return self.setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + def fake_generate( + self, + **kwargs, + ): + raise RuntimeError( + "writer failed" + ) + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + fake_generate, + ) + + manager = SimulationSetupManager() + + with pytest.raises( + RuntimeError, + match="writer failed", + ): + manager.setup_and_write_simulation( + session + ) + + +def test_success_message_not_printed_when_generation_fails( + tmp_path, + monkeypatch, + capsys, +): + setup = SimpleNamespace( + simulation_name="Polymer", + ) + + session = make_session( + tmp_path, + inputs=setup, + ) + + class FakeCalculator: + def __init__(self, setup): + self.setup = setup + + def process_all(self): + return self.setup + + monkeypatch.setattr( + sim_setup_module, + "SystemPropertyCalculations", + FakeCalculator, + ) + + def fake_generate( + self, + **kwargs, + ): + raise RuntimeError( + "writer failed" + ) + + monkeypatch.setattr( + SimulationSetupManager, + "generate_input_files", + fake_generate, + ) + + manager = SimulationSetupManager() + + with pytest.raises( + RuntimeError + ): + manager.setup_and_write_simulation( + session + ) + + captured = ( + capsys.readouterr() + ) + + assert ( + "[SUCCESS]" + not in captured.out + ) + + +# ============================================================================= +# generate_input_files +# ============================================================================= + + +def test_generate_input_files_constructs_writer_with_reacter_files( + tmp_path, + monkeypatch, +): + reacter_files = SimpleNamespace( + marker="rf" + ) + + setup = SimpleNamespace( + simulation_name="Polymer", + ) + + captured = {} + + class FakeWriter: + def __init__( + self, + *, + reacter_files, + ): + captured[ + "reacter_files" + ] = reacter_files + + def write_all_files( + self, + run_dir, + setup, + ): + pass + + monkeypatch.setattr( + sim_setup_module, + "Writer", + FakeWriter, + ) + + manager = SimulationSetupManager() + + manager.generate_input_files( + setup=setup, + reacter_files=reacter_files, + run_dir=tmp_path, + ) + + assert ( + captured["reacter_files"] + is reacter_files + ) + + +def test_generate_input_files_calls_write_all_files_with_expected_arguments( + tmp_path, + monkeypatch, +): + reacter_files = SimpleNamespace( + marker="rf" + ) + + setup = SimpleNamespace( + simulation_name="Polymer", + write_second_reaction_stage=False, + ) + + captured = {} + + class FakeWriter: + def __init__( + self, + *, + reacter_files, + ): + self.reacter_files = ( + reacter_files + ) + + def write_all_files( + self, + run_dir, + passed_setup, + ): + captured["run_dir"] = ( + run_dir + ) + + captured["setup"] = ( + passed_setup + ) + + monkeypatch.setattr( + sim_setup_module, + "Writer", + FakeWriter, + ) + + manager = SimulationSetupManager() + + manager.generate_input_files( + setup=setup, + reacter_files=reacter_files, + run_dir=tmp_path, + ) + + assert ( + captured["run_dir"] + == tmp_path + ) + + assert ( + captured["setup"] + is setup + ) + + +def test_generate_input_files_does_not_modify_second_stage_flag( + tmp_path, + monkeypatch, +): + """ + SimulationSetupManager passes the setup object through unchanged. + + Whether stage 2 is generated belongs to Writer. + """ + reacter_files = SimpleNamespace() + + setup = SimpleNamespace( + simulation_name="Polymer", + write_second_reaction_stage=False, + ) + + observed = {} + + class FakeWriter: + def __init__( + self, + *, + reacter_files, + ): + pass + + def write_all_files( + self, + run_dir, + passed_setup, + ): + observed["flag"] = ( + passed_setup + .write_second_reaction_stage + ) + + monkeypatch.setattr( + sim_setup_module, + "Writer", + FakeWriter, + ) + + manager = SimulationSetupManager() + + manager.generate_input_files( + setup=setup, + reacter_files=reacter_files, + run_dir=tmp_path, + ) + + assert ( + observed["flag"] + is False + ) + + assert ( + setup.write_second_reaction_stage + is False + ) + + +def test_generate_input_files_returns_none( + tmp_path, + monkeypatch, +): + class FakeWriter: + def __init__( + self, + *, + reacter_files, + ): + pass + + def write_all_files( + self, + run_dir, + setup, + ): + return None + + monkeypatch.setattr( + sim_setup_module, + "Writer", + FakeWriter, + ) + + manager = SimulationSetupManager() + + result = ( + manager + .generate_input_files( + setup=SimpleNamespace(), + reacter_files=( + SimpleNamespace() + ), + run_dir=tmp_path, + ) + ) + + assert result is None + + +def test_writer_error_propagates_from_generate_input_files( + tmp_path, + monkeypatch, +): + class FakeWriter: + def __init__( + self, + *, + reacter_files, + ): + pass + + def write_all_files( + self, + run_dir, + setup, + ): + raise RuntimeError( + "LAMMPS writing failed" + ) + + monkeypatch.setattr( + sim_setup_module, + "Writer", + FakeWriter, + ) + + manager = SimulationSetupManager() + + with pytest.raises( + RuntimeError, + match="LAMMPS writing failed", + ): + manager.generate_input_files( + setup=SimpleNamespace(), + reacter_files=( + SimpleNamespace() + ), + run_dir=tmp_path, + ) \ No newline at end of file diff --git a/tests/unit/sim_setup/writers/test_rxn_first_stage_writer.py b/tests/unit/sim_setup/writers/test_rxn_first_stage_writer.py new file mode 100644 index 00000000..60a37cc7 --- /dev/null +++ b/tests/unit/sim_setup/writers/test_rxn_first_stage_writer.py @@ -0,0 +1,2167 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER.sim_setup.writers.rxn_first_stage_writer as rxn_module +from AutoREACTER.sim_setup.writers.rxn_first_stage_writer import ( + RxnFirstStageWriter, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_settings( + *, + neighbor=None, + neigh_modify=None, +): + return SimpleNamespace( + units="real", + dimension="3", + boundary="p p p", + atom_style="full", + bond_style="class2", + angle_style="class2", + dihedral_style="class2", + improper_style="class2", + special_bonds="lj/coul 0 0 1", + pair_style="lj/class2/coul/long 12.0", + kspace_style="pppm 1.0e-4", + pair_modify="mix sixthpower", + neighbor=neighbor, + neigh_modify=neigh_modify, + ) + + +def make_simulation( + *, + tag="sim1", + temperature=500.0, +): + return SimpleNamespace( + tag=tag, + temperature=temperature, + ) + + +def make_template( + *, + reaction_id=1, + activity_stats=True, + pre_reaction_file=None, + post_reaction_file=None, + map_file=None, + map_file_with_delete_ids=None, +): + return SimpleNamespace( + reaction_id=reaction_id, + activity_stats=activity_stats, + pre_reaction_file=pre_reaction_file, + post_reaction_file=post_reaction_file, + map_file=map_file, + map_file_with_delete_ids=map_file_with_delete_ids, + ) + + +def make_reacter_files( + *, + template_files=None, +): + return SimpleNamespace( + template_files=list( + template_files or [] + ), + ) + + +def make_real_template( + tmp_path, + *, + reaction_id=1, + activity_stats=True, + with_delete_map=False, +): + pre = ( + tmp_path + / f"template_pre_{reaction_id}.molecule" + ) + + post = ( + tmp_path + / f"template_post_{reaction_id}.molecule" + ) + + standard_map = ( + tmp_path + / f"RXN_{reaction_id}.map" + ) + + pre.write_text( + "PRE", + encoding="utf-8", + ) + + post.write_text( + "POST", + encoding="utf-8", + ) + + standard_map.write_text( + "STANDARD MAP", + encoding="utf-8", + ) + + delete_map = None + + if with_delete_map: + delete_map = ( + tmp_path + / ( + f"RXN_{reaction_id}" + "_with_delete_ids.map" + ) + ) + + delete_map.write_text( + "DELETE MAP", + encoding="utf-8", + ) + + template = make_template( + reaction_id=reaction_id, + activity_stats=activity_stats, + pre_reaction_file=pre, + post_reaction_file=post, + map_file=standard_map, + map_file_with_delete_ids=delete_map, + ) + + return ( + template, + pre, + post, + standard_map, + delete_map, + ) + + +def make_writer_without_init( + tmp_path, + *, + settings=None, + reacter_files=None, + sim_name="Test", +): + writer = object.__new__( + RxnFirstStageWriter + ) + + writer.settings = ( + settings + if settings is not None + else make_settings() + ) + + writer.out_dir = tmp_path + writer.sim_name = sim_name + + writer.reacter_files = ( + reacter_files + if reacter_files is not None + else make_reacter_files() + ) + + return writer + + +def read_script( + tmp_path, + filename, +): + return ( + tmp_path + / "3_reaction_first_stage" + / filename + ).read_text( + encoding="utf-8" + ) + + +def active_lines(text): + """ + Return non-empty, non-comment lines. + + Important here because comments deliberately mention the optional + _with_delete_ids.map filename. + """ + result = [] + + for line in text.splitlines(): + stripped = line.strip() + + if not stripped: + continue + + if stripped.startswith("#"): + continue + + result.append( + stripped + ) + + return result + + +def command_tokens(text): + return [ + line.split() + for line in active_lines(text) + ] + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_configuration( + tmp_path, + monkeypatch, +): + settings = make_settings() + + reacter_files = ( + make_reacter_files() + ) + + simulation = ( + make_simulation() + ) + + calls = [] + + monkeypatch.setattr( + RxnFirstStageWriter, + "write_first_stage_reaction_files", + lambda self, simulation: + ( + calls.append(simulation) + or "in.test_reaction" + ), + ) + + writer = RxnFirstStageWriter( + out_dir=tmp_path, + settings=settings, + reacter_files=reacter_files, + simulation=simulation, + sim_name="Polymer", + ) + + assert writer.settings is settings + + assert ( + writer.reacter_files + is reacter_files + ) + + assert writer.out_dir == tmp_path + + assert ( + writer.sim_name + == "Polymer" + ) + + assert calls == [ + simulation + ] + + assert ( + writer.first_stage_file_name + == "in.test_reaction" + ) + + +# ============================================================================= +# Basic file generation +# ============================================================================= + + +def test_writer_creates_first_reaction_stage_directory( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + writer.write_first_stage_reaction_files( + make_simulation() + ) + + assert ( + tmp_path + / "3_reaction_first_stage" + ).is_dir() + + +def test_writer_creates_expected_input_file( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + assert filename == ( + "in.Polymer_500K_reaction" + ) + + assert ( + tmp_path + / "3_reaction_first_stage" + / filename + ).is_file() + + +def test_writer_returns_filename_only( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + assert isinstance( + filename, + str, + ) + + assert "/" not in filename + assert "\\" not in filename + + +def test_script_header_contains_tag( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Epoxy", + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation( + tag="373K" + ) + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert ( + "# Epoxy_373K " + "First Reaction Stage Script" + in text + ) + + assert ( + "by AutoREACTER" + in text + ) + + +# ============================================================================= +# LAMMPS settings +# ============================================================================= + + +def test_script_contains_initialization_settings( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "units", + "real", + ] in commands + + assert [ + "dimension", + "3", + ] in commands + + assert [ + "boundary", + "p", + "p", + "p", + ] in commands + + assert [ + "atom_style", + "full", + ] in commands + + +def test_script_contains_force_field_styles( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "angle_style", + "class2", + ] in commands + + assert [ + "bond_style", + "class2", + ] in commands + + assert [ + "dihedral_style", + "class2", + ] in commands + + assert [ + "improper_style", + "class2", + ] in commands + + +def test_script_contains_pair_settings( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "pair_style", + "lj/class2/coul/long", + "12.0", + ] in commands + + assert [ + "kspace_style", + "pppm", + "1.0e-4", + ] in commands + + assert [ + "pair_modify", + "mix", + "sixthpower", + ] in commands + + +def test_optional_neighbor_settings_are_written( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor="2.0 bin", + neigh_modify=( + "delay 0 every 1 " + "check yes" + ), + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "neighbor", + "2.0", + "bin", + ] in commands + + assert [ + "neigh_modify", + "delay", + "0", + "every", + "1", + "check", + "yes", + ] in commands + + +def test_optional_neighbor_settings_omitted_when_none( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor=None, + neigh_modify=None, + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + keywords = [ + command[0] + for command in commands + ] + + assert "neighbor" not in keywords + assert "neigh_modify" not in keywords + + +# ============================================================================= +# Input data +# ============================================================================= + + +def test_reads_pre_equilibrated_data( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "read_data", + "Polymer_500K_pre_equilibrated.data", + "&", + ] in commands + + +def test_read_data_reserves_extra_topology_capacity( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert ( + "extra/bond/per/atom 50" + in text + ) + + assert ( + "extra/angle/per/atom 50" + in text + ) + + assert ( + "extra/dihedral/per/atom 50" + in text + ) + + assert ( + "extra/improper/per/atom 50" + in text + ) + + assert ( + "extra/special/per/atom 50" + in text + ) + + +# ============================================================================= +# Minimization / velocity / timestep +# ============================================================================= + + +def test_script_contains_expected_minimization( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "minimize", + "1.0e-4", + "1.0e-6", + "1000", + "10000", + ] in commands + + +def test_velocity_uses_temperature_and_random_seed( + tmp_path, + monkeypatch, +): + monkeypatch.setattr( + rxn_module.random, + "randint", + lambda a, b: 123456, + ) + + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation( + temperature=523.0 + ) + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "velocity", + "all", + "create", + "523.0", + "123456", + "dist", + "gaussian", + ] in commands + + +def test_script_uses_one_fs_timestep( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "timestep", + "1.0", + ] in commands + + +def test_script_uses_thermo_interval_100( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "thermo", + "100", + ] in commands + + +def test_script_resets_timestep( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "reset_timestep", + "0", + ] in commands + + +# ============================================================================= +# Reaction template definitions +# ============================================================================= + + +def test_active_template_writes_pre_and_post_molecule_commands( + tmp_path, +): + ( + template, + pre, + post, + _, + _, + ) = make_real_template( + tmp_path, + reaction_id=7, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "molecule", + "mol_pre_7", + pre.name, + ] in commands + + assert [ + "molecule", + "mol_post_7", + post.name, + ] in commands + + +def test_inactive_template_is_not_written( + tmp_path, +): + ( + template, + _, + _, + _, + _, + ) = make_real_template( + tmp_path, + reaction_id=9, + activity_stats=False, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "mol_pre_9" not in text + assert "mol_post_9" not in text + assert "rxn_stp_9" not in text + + +def test_missing_activity_stats_defaults_to_active( + tmp_path, +): + ( + template, + _, + _, + _, + _, + ) = make_real_template( + tmp_path, + reaction_id=3, + ) + + del template.activity_stats + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "mol_pre_3" in text + assert "rxn_stp_3" in text + + +def test_multiple_active_templates_are_written( + tmp_path, +): + template_1, *_ = ( + make_real_template( + tmp_path, + reaction_id=1, + ) + ) + + template_2, *_ = ( + make_real_template( + tmp_path, + reaction_id=2, + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template_1, + template_2, + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "rxn_stp_1" in text + assert "rxn_stp_2" in text + + +# ============================================================================= +# Standard map behavior +# ============================================================================= + + +def test_standard_map_is_used_when_no_delete_map_exists( + tmp_path, +): + ( + template, + _, + _, + standard_map, + _, + ) = make_real_template( + tmp_path, + reaction_id=4, + with_delete_map=False, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + lines = active_lines( + read_script( + tmp_path, + filename, + ) + ) + + react_line = next( + line + for line in lines + if "rxn_stp_4" in line + ) + + assert ( + standard_map.name + in react_line + ) + + +def test_standard_map_remains_default_even_when_delete_map_exists( + tmp_path, +): + """ + Core AutoREACTER behavior. + + The supplementary DeleteIDs map is supplied to the user, but the generated + LAMMPS script MUST continue to use RXN_N.map by default. + """ + ( + template, + _, + _, + standard_map, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=5, + with_delete_map=True, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + lines = active_lines( + read_script( + tmp_path, + filename, + ) + ) + + react_line = next( + line + for line in lines + if "rxn_stp_5" in line + ) + + assert ( + standard_map.name + in react_line + ) + + assert ( + delete_map.name + not in react_line + ) + + +def test_delete_map_is_never_automatically_selected( + tmp_path, +): + ( + template, + _, + _, + _, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=8, + with_delete_map=True, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + active = "\n".join( + active_lines( + read_script( + tmp_path, + filename, + ) + ) + ) + + assert ( + delete_map.name + not in active + ) + + +def test_reaction_command_contains_expected_options( + tmp_path, +): + ( + template, + _, + _, + standard_map, + _, + ) = make_real_template( + tmp_path, + reaction_id=2, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + lines = active_lines( + read_script( + tmp_path, + filename, + ) + ) + + react_line = next( + line + for line in lines + if "rxn_stp_2" in line + ) + + tokens = react_line.split() + + assert tokens[:2] == [ + "react", + "rxn_stp_2", + ] + + assert "all" in tokens + assert "1" in tokens + assert "0.0" in tokens + assert "3.5" in tokens + + assert ( + "mol_pre_2" + in tokens + ) + + assert ( + "mol_post_2" + in tokens + ) + + assert ( + standard_map.name + in tokens + ) + + assert tokens[-4:] == [ + "stabilize_steps", + "60", + "rescale_charges", + "yes", + ] + + +# ============================================================================= +# fix bond/react +# ============================================================================= + + +def test_fix_bond_react_header_is_written( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path, + reaction_id=1, + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert ( + "rxns all bond/react " + "stabilization yes " + "statted_grp 0.03" + in text + ) + + +def test_multiple_reactions_are_joined_into_same_fix( + tmp_path, +): + template_1, *_ = ( + make_real_template( + tmp_path, + reaction_id=1, + ) + ) + + template_2, *_ = ( + make_real_template( + tmp_path, + reaction_id=2, + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template_1, + template_2, + ] + ) + ), + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "rxn_stp_1" in text + assert "rxn_stp_2" in text + + assert ( + " & " + in text + ) + + +# ============================================================================= +# Thermostat / output +# ============================================================================= + + +def test_active_nvt_uses_simulation_temperature( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation( + temperature=373.0 + ) + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "fix", + "1", + "statted_grp_REACT", + "nvt", + "temp", + "373.0", + "373.0", + "100.0", + ] in commands + + +def test_npt_command_is_currently_commented_out( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + active = active_lines( + read_script( + tmp_path, + filename, + ) + ) + + assert not any( + " npt " in f" {line} " + for line in active + ) + + +def test_thermo_style_contains_reaction_output( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + thermo_style = next( + command + for command in commands + if command[0] == "thermo_style" + ) + + assert "custom" in thermo_style + assert "step" in thermo_style + assert "time" in thermo_style + assert "temp" in thermo_style + assert "f_rxns[*]" in thermo_style + assert "press" in thermo_style + assert "density" in thermo_style + assert "vol" in thermo_style + assert "pe" in thermo_style + assert "ke" in thermo_style + assert "etotal" in thermo_style + + +def test_reaction_stage_runs_one_million_steps( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "run", + "1000000", + ] in commands + + +def test_output_names_use_first_stage_range( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + sim_name="Polymer", + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + output_base = ( + "Polymer_500K" + "_reacted_0M-1M_3.5A" + ) + + assert ( + f"{output_base}.xyz" + in text + ) + + assert ( + f"{output_base}_backup1.restart" + in text + ) + + assert ( + f"{output_base}_backup2.restart" + in text + ) + + assert ( + f"{output_base}.restart" + in text + ) + + assert ( + f"{output_base}.data" + in text + ) + + +def test_write_data_uses_nofix( + tmp_path, +): + writer = make_writer_without_init( + tmp_path + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + write_commands = [ + command + for command in commands + if command[0] == "write_data" + ] + + assert len( + write_commands + ) == 1 + + assert ( + write_commands[0][-1] + == "nofix" + ) + + +# ============================================================================= +# _copy_required_files +# ============================================================================= + + +def test_copy_required_files_copies_standard_map_and_templates( + tmp_path, +): + ( + template, + pre, + post, + standard_map, + _, + ) = make_real_template( + tmp_path, + reaction_id=1, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "reaction" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / standard_map.name + ).is_file() + + assert ( + dest / pre.name + ).is_file() + + assert ( + dest / post.name + ).is_file() + + +def test_copy_required_files_copies_optional_delete_map_when_present( + tmp_path, +): + """ + Supplementary DeleteIDs map is copied for the user. + + It is NOT automatically used by the generated LAMMPS script. + """ + ( + template, + _, + _, + standard_map, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=2, + with_delete_map=True, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "reaction" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / standard_map.name + ).is_file() + + assert ( + dest / delete_map.name + ).is_file() + + +def test_copy_required_files_without_delete_map_still_succeeds( + tmp_path, +): + ( + template, + pre, + post, + standard_map, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=3, + with_delete_map=False, + ) + + assert delete_map is None + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "reaction" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / standard_map.name + ).is_file() + + assert ( + dest / pre.name + ).is_file() + + assert ( + dest / post.name + ).is_file() + + +def test_copy_required_files_missing_delete_map_attribute_still_succeeds( + tmp_path, +): + ( + template, + _, + _, + standard_map, + _, + ) = make_real_template( + tmp_path, + reaction_id=4, + ) + + del ( + template + .map_file_with_delete_ids + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "reaction" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / standard_map.name + ).is_file() + + +def test_copy_required_files_missing_standard_map_raises( + tmp_path, +): + pre = ( + tmp_path / "pre.molecule" + ) + + post = ( + tmp_path / "post.molecule" + ) + + pre.write_text( + "PRE", + encoding="utf-8", + ) + + post.write_text( + "POST", + encoding="utf-8", + ) + + missing_map = ( + tmp_path / "missing.map" + ) + + template = make_template( + reaction_id=1, + pre_reaction_file=pre, + post_reaction_file=post, + map_file=missing_map, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + with pytest.raises( + FileNotFoundError, + match=( + "Required reaction file " + "not found" + ), + ): + writer._copy_required_files( + dest + ) + + +def test_copy_required_files_missing_pre_template_raises( + tmp_path, +): + post = ( + tmp_path / "post.molecule" + ) + + map_file = ( + tmp_path / "RXN_1.map" + ) + + post.write_text( + "POST", + encoding="utf-8", + ) + + map_file.write_text( + "MAP", + encoding="utf-8", + ) + + template = make_template( + reaction_id=1, + pre_reaction_file=( + tmp_path + / "missing_pre.molecule" + ), + post_reaction_file=post, + map_file=map_file, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + with pytest.raises( + FileNotFoundError, + ): + writer._copy_required_files( + dest + ) + + +def test_copy_required_files_missing_post_template_raises( + tmp_path, +): + pre = ( + tmp_path / "pre.molecule" + ) + + map_file = ( + tmp_path / "RXN_1.map" + ) + + pre.write_text( + "PRE", + encoding="utf-8", + ) + + map_file.write_text( + "MAP", + encoding="utf-8", + ) + + template = make_template( + reaction_id=1, + pre_reaction_file=pre, + post_reaction_file=( + tmp_path + / "missing_post.molecule" + ), + map_file=map_file, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + with pytest.raises( + FileNotFoundError, + ): + writer._copy_required_files( + dest + ) + + +def test_copy_required_files_missing_optional_delete_map_path_raises_when_declared( + tmp_path, +): + """ + Current behavior: + + The delete map is optional in the sense that the attribute may be None. + + But if metadata explicitly points to a delete map, that declared file + must actually exist for it to be copied. + """ + ( + template, + _, + _, + _, + _, + ) = make_real_template( + tmp_path, + reaction_id=6, + ) + + template.map_file_with_delete_ids = ( + tmp_path + / "RXN_6_with_delete_ids.map" + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + with pytest.raises( + FileNotFoundError, + match=( + "Required reaction file " + "not found" + ), + ): + writer._copy_required_files( + dest + ) + + +def test_copy_required_files_ignores_inactive_templates( + tmp_path, +): + template = make_template( + reaction_id=99, + activity_stats=False, + pre_reaction_file=( + tmp_path + / "missing_pre.molecule" + ), + post_reaction_file=( + tmp_path + / "missing_post.molecule" + ), + map_file=( + tmp_path + / "missing.map" + ), + map_file_with_delete_ids=( + tmp_path + / "missing_delete.map" + ), + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "dest" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert list( + dest.iterdir() + ) == [] + + +# ============================================================================= +# Full delete-map integration +# ============================================================================= + + +def test_delete_map_is_supplied_but_standard_map_remains_in_generated_script( + tmp_path, +): + """ + End-to-end characterization of the intended map behavior. + + Both maps are copied: + RXN_10.map + RXN_10_with_delete_ids.map + + But the generated fix bond/react command references: + RXN_10.map + """ + ( + template, + pre, + post, + standard_map, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=10, + with_delete_map=True, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + sim_name="Polymer", + ) + + filename = ( + writer + .write_first_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + stage_dir = ( + tmp_path + / "3_reaction_first_stage" + ) + + assert ( + stage_dir / pre.name + ).is_file() + + assert ( + stage_dir / post.name + ).is_file() + + assert ( + stage_dir / standard_map.name + ).is_file() + + assert ( + stage_dir / delete_map.name + ).is_file() + + text = read_script( + tmp_path, + filename, + ) + + active = "\n".join( + active_lines(text) + ) + + assert ( + standard_map.name + in active + ) + + assert ( + delete_map.name + not in active + ) \ No newline at end of file diff --git a/tests/unit/sim_setup/writers/test_rxn_second_stage_writer.py b/tests/unit/sim_setup/writers/test_rxn_second_stage_writer.py new file mode 100644 index 00000000..c3a594d4 --- /dev/null +++ b/tests/unit/sim_setup/writers/test_rxn_second_stage_writer.py @@ -0,0 +1,2402 @@ +from types import SimpleNamespace + +import pytest + +import AutoREACTER.sim_setup.writers.rxn_second_stage_writer as rxn_module +from AutoREACTER.sim_setup.writers.rxn_second_stage_writer import ( + RxnSecondStageWriter, +) + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_settings( + *, + neighbor=None, + neigh_modify=None, +): + return SimpleNamespace( + units="real", + dimension="3", + boundary="p p p", + atom_style="full", + bond_style="class2", + angle_style="class2", + dihedral_style="class2", + improper_style="class2", + special_bonds="lj/coul 0 0 1", + pair_style="lj/class2/coul/long 12.0", + kspace_style="pppm 1.0e-4", + pair_modify="mix sixthpower", + neighbor=neighbor, + neigh_modify=neigh_modify, + ) + + +def make_simulation( + *, + tag="sim1", + temperature=500.0, +): + return SimpleNamespace( + tag=tag, + temperature=temperature, + ) + + +def make_template( + *, + reaction_id=1, + activity_stats=True, + pre_reaction_file=None, + post_reaction_file=None, + map_file=None, + map_file_with_delete_ids=None, +): + return SimpleNamespace( + reaction_id=reaction_id, + activity_stats=activity_stats, + pre_reaction_file=pre_reaction_file, + post_reaction_file=post_reaction_file, + map_file=map_file, + map_file_with_delete_ids=map_file_with_delete_ids, + ) + + +def make_reacter_files( + *, + template_files=None, +): + return SimpleNamespace( + template_files=list( + template_files or [] + ), + ) + + +def make_real_template( + tmp_path, + *, + reaction_id=1, + activity_stats=True, + with_delete_map=False, +): + pre = ( + tmp_path + / f"template_pre_{reaction_id}.molecule" + ) + + post = ( + tmp_path + / f"template_post_{reaction_id}.molecule" + ) + + standard_map = ( + tmp_path + / f"RXN_{reaction_id}.map" + ) + + pre.write_text( + "PRE", + encoding="utf-8", + ) + + post.write_text( + "POST", + encoding="utf-8", + ) + + standard_map.write_text( + "STANDARD MAP", + encoding="utf-8", + ) + + delete_map = None + + if with_delete_map: + delete_map = ( + tmp_path + / ( + f"RXN_{reaction_id}" + "_with_delete_ids.map" + ) + ) + + delete_map.write_text( + "DELETE MAP", + encoding="utf-8", + ) + + template = make_template( + reaction_id=reaction_id, + activity_stats=activity_stats, + pre_reaction_file=pre, + post_reaction_file=post, + map_file=standard_map, + map_file_with_delete_ids=delete_map, + ) + + return ( + template, + pre, + post, + standard_map, + delete_map, + ) + + +def make_writer_without_init( + tmp_path, + *, + settings=None, + reacter_files=None, + sim_name="Test", +): + writer = object.__new__( + RxnSecondStageWriter + ) + + writer.settings = ( + settings + if settings is not None + else make_settings() + ) + + writer.out_dir = tmp_path + writer.sim_name = sim_name + + writer.reacter_files = ( + reacter_files + if reacter_files is not None + else make_reacter_files() + ) + + return writer + + +def read_script( + tmp_path, + filename, +): + return ( + tmp_path + / "4_reaction_second_stage" + / filename + ).read_text( + encoding="utf-8" + ) + + +def active_lines(text): + """ + Return non-empty, non-comment LAMMPS lines. + + Comments are ignored because the generated file intentionally + mentions RXN_i_with_delete_ids.map in explanatory comments. + """ + result = [] + + for line in text.splitlines(): + stripped = line.strip() + + if not stripped: + continue + + if stripped.startswith("#"): + continue + + result.append( + stripped + ) + + return result + + +def command_tokens(text): + return [ + line.split() + for line in active_lines(text) + ] + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_configuration( + tmp_path, + monkeypatch, +): + settings = make_settings() + + reacter_files = ( + make_reacter_files() + ) + + simulation = ( + make_simulation() + ) + + calls = [] + + monkeypatch.setattr( + RxnSecondStageWriter, + "write_second_stage_reaction_files", + lambda self, simulation: + ( + calls.append(simulation) + or "in.test_stage_2" + ), + ) + + writer = RxnSecondStageWriter( + out_dir=tmp_path, + settings=settings, + reacter_files=reacter_files, + simulation=simulation, + sim_name="Polymer", + ) + + assert writer.settings is settings + + assert ( + writer.reacter_files + is reacter_files + ) + + assert writer.out_dir == tmp_path + + assert ( + writer.sim_name + == "Polymer" + ) + + assert calls == [ + simulation + ] + + assert ( + writer.second_stage_file_name + == "in.test_stage_2" + ) + + +# ============================================================================= +# Active templates +# ============================================================================= + + +def test_no_active_templates_raises( + tmp_path, +): + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[] + ) + ), + ) + + with pytest.raises( + ValueError, + match=( + "No active reaction templates " + "available for the second reaction stage" + ), + ): + writer.write_second_stage_reaction_files( + make_simulation() + ) + + +def test_all_inactive_templates_raise( + tmp_path, +): + template = make_template( + reaction_id=1, + activity_stats=False, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + with pytest.raises( + ValueError, + match="No active reaction templates", + ): + writer.write_second_stage_reaction_files( + make_simulation() + ) + + +def test_missing_activity_stats_defaults_to_active( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path, + reaction_id=3, + ) + ) + + del template.activity_stats + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "rxn_stp_3" in text + + +# ============================================================================= +# File generation +# ============================================================================= + + +def test_writer_creates_second_stage_directory( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + writer.write_second_stage_reaction_files( + make_simulation() + ) + + assert ( + tmp_path + / "4_reaction_second_stage" + ).is_dir() + + +def test_writer_creates_expected_input_file( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + sim_name="Polymer", + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + assert filename == ( + "in.Polymer_500K_reaction_stage_2" + ) + + assert ( + tmp_path + / "4_reaction_second_stage" + / filename + ).is_file() + + +def test_writer_returns_filename_only( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + assert isinstance( + filename, + str, + ) + + assert "/" not in filename + assert "\\" not in filename + + +def test_header_contains_tag_and_autoreacter( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + sim_name="Epoxy", + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert ( + "# Epoxy_500K " + "Second Reaction Stage Script" + in text + ) + + assert ( + "by AutoREACTER" + in text + ) + + +# ============================================================================= +# LAMMPS initialization +# ============================================================================= + + +def test_script_contains_initialization_settings( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "units", + "real", + ] in commands + + assert [ + "dimension", + "3", + ] in commands + + assert [ + "boundary", + "p", + "p", + "p", + ] in commands + + assert [ + "atom_style", + "full", + ] in commands + + +def test_script_contains_force_field_styles( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "angle_style", + "class2", + ] in commands + + assert [ + "bond_style", + "class2", + ] in commands + + assert [ + "dihedral_style", + "class2", + ] in commands + + assert [ + "improper_style", + "class2", + ] in commands + + +def test_script_contains_pair_settings( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "pair_style", + "lj/class2/coul/long", + "12.0", + ] in commands + + assert [ + "kspace_style", + "pppm", + "1.0e-4", + ] in commands + + assert [ + "pair_modify", + "mix", + "sixthpower", + ] in commands + + +def test_optional_neighbor_settings_are_written( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor="2.0 bin", + neigh_modify=( + "delay 0 every 1 " + "check yes" + ), + ), + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "neighbor", + "2.0", + "bin", + ] in commands + + assert [ + "neigh_modify", + "delay", + "0", + "every", + "1", + "check", + "yes", + ] in commands + + +def test_optional_neighbor_settings_omitted_when_none( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + settings=make_settings( + neighbor=None, + neigh_modify=None, + ), + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + keywords = [ + command[0] + for command in commands + ] + + assert "neighbor" not in keywords + assert "neigh_modify" not in keywords + + +# ============================================================================= +# Input structure +# ============================================================================= + + +def test_reads_first_stage_reacted_data( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + sim_name="Polymer", + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "read_data", + "Polymer_500K_reacted_0M-1M_3.5A.data", + "&", + ] in commands + + +def test_read_data_reserves_extra_topology_capacity( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "extra/bond/per/atom 50" in text + assert "extra/angle/per/atom 50" in text + assert "extra/dihedral/per/atom 50" in text + assert "extra/improper/per/atom 50" in text + assert "extra/special/per/atom 50" in text + + +# ============================================================================= +# Minimization / velocity / timestep +# ============================================================================= + + +def test_script_contains_minimization( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "minimize", + "1.0e-4", + "1.0e-6", + "1000", + "10000", + ] in commands + + +def test_velocity_uses_simulation_temperature_and_seed( + tmp_path, + monkeypatch, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + monkeypatch.setattr( + rxn_module.random, + "randint", + lambda a, b: 123456, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation( + temperature=523.0 + ) + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "velocity", + "all", + "create", + "523.0", + "123456", + "dist", + "gaussian", + ] in commands + + +def test_second_stage_timestep_thermo_and_reset( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "timestep", + "1.0", + ] in commands + + assert [ + "thermo", + "100", + ] in commands + + assert [ + "reset_timestep", + "1000000", + ] in commands + + +# ============================================================================= +# Reaction definitions +# ============================================================================= + + +def test_active_template_writes_pre_and_post_molecules( + tmp_path, +): + ( + template, + pre, + post, + _, + _, + ) = make_real_template( + tmp_path, + reaction_id=7, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "molecule", + "mol_pre_7", + pre.name, + ] in commands + + assert [ + "molecule", + "mol_post_7", + post.name, + ] in commands + + +def test_inactive_template_not_written_when_active_template_exists( + tmp_path, +): + active, *_ = ( + make_real_template( + tmp_path, + reaction_id=1, + ) + ) + + inactive, *_ = ( + make_real_template( + tmp_path, + reaction_id=2, + activity_stats=False, + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + active, + inactive, + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "rxn_stp_1" in text + assert "rxn_stp_2" not in text + + +def test_reaction_uses_five_angstrom_cutoff( + tmp_path, +): + ( + template, + _, + _, + standard_map, + _, + ) = make_real_template( + tmp_path, + reaction_id=4, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + react_line = next( + line + for line in active_lines( + read_script( + tmp_path, + filename, + ) + ) + if "rxn_stp_4" in line + ) + + tokens = ( + react_line.split() + ) + + assert "0.0" in tokens + assert "5.0" in tokens + + assert ( + standard_map.name + in tokens + ) + + +def test_reaction_uses_stabilize_steps_200( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path, + reaction_id=5, + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + react_line = next( + line + for line in active_lines( + read_script( + tmp_path, + filename, + ) + ) + if "rxn_stp_5" in line + ) + + assert ( + react_line.split()[-4:] + == [ + "stabilize_steps", + "200", + "rescale_charges", + "yes", + ] + ) + + +# ============================================================================= +# Standard map behavior +# ============================================================================= + + +def test_standard_map_is_used_when_no_delete_map_exists( + tmp_path, +): + ( + template, + _, + _, + standard_map, + _, + ) = make_real_template( + tmp_path, + reaction_id=6, + with_delete_map=False, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + react_line = next( + line + for line in active_lines( + read_script( + tmp_path, + filename, + ) + ) + if "rxn_stp_6" in line + ) + + assert ( + standard_map.name + in react_line + ) + + +def test_standard_map_remains_default_when_delete_map_exists( + tmp_path, +): + """ + AutoREACTER supplies the optional delete-ID map to the user, + but the generated LAMMPS command must still use RXN_N.map. + """ + ( + template, + _, + _, + standard_map, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=10, + with_delete_map=True, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + react_line = next( + line + for line in active_lines( + read_script( + tmp_path, + filename, + ) + ) + if "rxn_stp_10" in line + ) + + assert ( + standard_map.name + in react_line + ) + + assert ( + delete_map.name + not in react_line + ) + + +def test_delete_map_is_never_automatically_selected( + tmp_path, +): + ( + template, + _, + _, + _, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=12, + with_delete_map=True, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + active = "\n".join( + active_lines( + read_script( + tmp_path, + filename, + ) + ) + ) + + assert ( + delete_map.name + not in active + ) + + +# ============================================================================= +# fix bond/react thermo vector +# ============================================================================= + + +def test_single_reaction_uses_explicit_f_rxns_1( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path, + reaction_id=17, + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + thermo = next( + command + for command in commands + if command[0] == "thermo_style" + ) + + assert ( + "f_rxns[1]" + in thermo + ) + + assert ( + "f_rxns[*]" + not in thermo + ) + + +def test_multiple_reactions_use_contiguous_thermo_indices( + tmp_path, +): + templates = [ + make_real_template( + tmp_path, + reaction_id=reaction_id, + )[0] + for reaction_id in ( + 4, + 17, + 68, + ) + ] + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=templates + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + thermo = next( + command + for command in commands + if command[0] == "thermo_style" + ) + + assert "f_rxns[1]" in thermo + assert "f_rxns[2]" in thermo + assert "f_rxns[3]" in thermo + + assert "f_rxns[4]" not in thermo + + +def test_thermo_indices_do_not_use_reaction_ids( + tmp_path, +): + template_17, *_ = ( + make_real_template( + tmp_path, + reaction_id=17, + ) + ) + + template_68, *_ = ( + make_real_template( + tmp_path, + reaction_id=68, + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template_17, + template_68, + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + assert "f_rxns[1]" in text + assert "f_rxns[2]" in text + + assert "f_rxns[17]" not in text + assert "f_rxns[68]" not in text + + +# ============================================================================= +# Thermostat / run +# ============================================================================= + + +def test_active_nvt_uses_simulation_temperature( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation( + temperature=373.0 + ) + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "fix", + "1", + "statted_grp_REACT", + "nvt", + "temp", + "373.0", + "373.0", + "100.0", + ] in commands + + +def test_npt_command_remains_commented_out( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + assert not any( + " npt " in f" {line} " + for line in active_lines( + read_script( + tmp_path, + filename, + ) + ) + ) + + +def test_second_stage_runs_2500000_steps( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + assert [ + "run", + "2500000", + ] in commands + + +# ============================================================================= +# Output naming +# ============================================================================= + + +def test_output_names_use_second_stage_range( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + sim_name="Polymer", + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + text = read_script( + tmp_path, + filename, + ) + + output_base = ( + "Polymer_500K" + "_reacted_1M-3.5_5.0A" + ) + + assert ( + f"{output_base}.xyz" + in text + ) + + assert ( + f"{output_base}_backup1.restart" + in text + ) + + assert ( + f"{output_base}_backup2.restart" + in text + ) + + assert ( + f"{output_base}.restart" + in text + ) + + assert ( + f"{output_base}.data" + in text + ) + + +def test_final_write_data_uses_nofix( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path + ) + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation() + ) + ) + + commands = command_tokens( + read_script( + tmp_path, + filename, + ) + ) + + write_data = [ + command + for command in commands + if command[0] == "write_data" + ] + + assert len( + write_data + ) == 1 + + assert ( + write_data[0][-1] + == "nofix" + ) + + +# ============================================================================= +# _copy_required_files +# ============================================================================= + + +def test_copy_required_files_copies_standard_map_and_templates( + tmp_path, +): + ( + template, + pre, + post, + standard_map, + _, + ) = make_real_template( + tmp_path, + reaction_id=1, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / pre.name + ).is_file() + + assert ( + dest / post.name + ).is_file() + + assert ( + dest / standard_map.name + ).is_file() + + +def test_copy_required_files_copies_optional_delete_map( + tmp_path, +): + """ + DeleteIDs map is copied for the user, but is not automatically used. + """ + ( + template, + _, + _, + standard_map, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=2, + with_delete_map=True, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / standard_map.name + ).is_file() + + assert ( + dest / delete_map.name + ).is_file() + + +def test_no_delete_map_is_valid( + tmp_path, +): + ( + template, + pre, + post, + standard_map, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=3, + with_delete_map=False, + ) + + assert delete_map is None + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / standard_map.name + ).is_file() + + assert ( + dest / pre.name + ).is_file() + + assert ( + dest / post.name + ).is_file() + + +def test_missing_delete_map_attribute_is_valid( + tmp_path, +): + ( + template, + _, + _, + standard_map, + _, + ) = make_real_template( + tmp_path, + reaction_id=4, + ) + + del ( + template + .map_file_with_delete_ids + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / standard_map.name + ).is_file() + + +def test_missing_standard_map_raises( + tmp_path, +): + pre = ( + tmp_path / "pre.molecule" + ) + + post = ( + tmp_path / "post.molecule" + ) + + pre.write_text( + "PRE", + encoding="utf-8", + ) + + post.write_text( + "POST", + encoding="utf-8", + ) + + template = make_template( + reaction_id=1, + pre_reaction_file=pre, + post_reaction_file=post, + map_file=( + tmp_path + / "missing.map" + ), + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + with pytest.raises( + FileNotFoundError, + match=( + "Required reaction file " + "not found" + ), + ): + writer._copy_required_files( + dest + ) + + +def test_missing_pre_template_raises( + tmp_path, +): + post = ( + tmp_path / "post.molecule" + ) + + standard_map = ( + tmp_path / "RXN_1.map" + ) + + post.write_text( + "POST", + encoding="utf-8", + ) + + standard_map.write_text( + "MAP", + encoding="utf-8", + ) + + template = make_template( + reaction_id=1, + pre_reaction_file=( + tmp_path + / "missing_pre.molecule" + ), + post_reaction_file=post, + map_file=standard_map, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + with pytest.raises( + FileNotFoundError, + ): + writer._copy_required_files( + dest + ) + + +def test_missing_post_template_raises( + tmp_path, +): + pre = ( + tmp_path / "pre.molecule" + ) + + standard_map = ( + tmp_path / "RXN_1.map" + ) + + pre.write_text( + "PRE", + encoding="utf-8", + ) + + standard_map.write_text( + "MAP", + encoding="utf-8", + ) + + template = make_template( + reaction_id=1, + pre_reaction_file=pre, + post_reaction_file=( + tmp_path + / "missing_post.molecule" + ), + map_file=standard_map, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + with pytest.raises( + FileNotFoundError, + ): + writer._copy_required_files( + dest + ) + + +def test_declared_but_missing_delete_map_raises( + tmp_path, +): + template, *_ = ( + make_real_template( + tmp_path, + reaction_id=5, + ) + ) + + template.map_file_with_delete_ids = ( + tmp_path + / "RXN_5_with_delete_ids.map" + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + with pytest.raises( + FileNotFoundError, + match=( + "Required reaction file " + "not found" + ), + ): + writer._copy_required_files( + dest + ) + + +def test_inactive_templates_are_not_copied( + tmp_path, +): + active, *_ = ( + make_real_template( + tmp_path, + reaction_id=1, + ) + ) + + inactive = make_template( + reaction_id=2, + activity_stats=False, + map_file=( + tmp_path + / "missing.map" + ), + pre_reaction_file=( + tmp_path + / "missing_pre" + ), + post_reaction_file=( + tmp_path + / "missing_post" + ), + map_file_with_delete_ids=( + tmp_path + / "missing_delete" + ), + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + active, + inactive, + ] + ) + ), + ) + + dest = ( + tmp_path / "stage2" + ) + + dest.mkdir() + + writer._copy_required_files( + dest + ) + + assert ( + dest / "RXN_1.map" + ).is_file() + + assert not ( + dest / "missing.map" + ).exists() + + +# ============================================================================= +# Delete-map full integration +# ============================================================================= + + +def test_delete_map_is_copied_but_standard_map_remains_used( + tmp_path, +): + """ + Full contract: + + Files supplied: + RXN_20.map + RXN_20_with_delete_ids.map + + Generated LAMMPS script: + uses RXN_20.map + """ + ( + template, + pre, + post, + standard_map, + delete_map, + ) = make_real_template( + tmp_path, + reaction_id=20, + with_delete_map=True, + ) + + writer = make_writer_without_init( + tmp_path, + reacter_files=( + make_reacter_files( + template_files=[ + template + ] + ) + ), + sim_name="Polymer", + ) + + filename = ( + writer + .write_second_stage_reaction_files( + make_simulation( + tag="500K" + ) + ) + ) + + stage_dir = ( + tmp_path + / "4_reaction_second_stage" + ) + + assert ( + stage_dir / pre.name + ).is_file() + + assert ( + stage_dir / post.name + ).is_file() + + assert ( + stage_dir + / standard_map.name + ).is_file() + + assert ( + stage_dir + / delete_map.name + ).is_file() + + active = "\n".join( + active_lines( + read_script( + tmp_path, + filename, + ) + ) + ) + + assert ( + standard_map.name + in active + ) + + assert ( + delete_map.name + not in active + ) diff --git a/tests/unit/sim_setup/writers/test_writer.py b/tests/unit/sim_setup/writers/test_writer.py new file mode 100644 index 00000000..51a061d7 --- /dev/null +++ b/tests/unit/sim_setup/writers/test_writer.py @@ -0,0 +1,1173 @@ +from pathlib import Path +from types import SimpleNamespace + +import pytest + +import AutoREACTER.sim_setup.writers.writer as writer_module +from AutoREACTER.sim_setup.writers.writer import Writer + + +# ============================================================================= +# Helpers +# ============================================================================= + + +def make_reacter_files(): + return SimpleNamespace( + in_file=Path("in.create_atoms.script"), + force_field_data=Path("force_field.data"), + molecule_files=[], + template_files=[], + ) + + +def make_simulation( + *, + tag="sim1", + temperature=500.0, +): + return SimpleNamespace( + tag=tag, + temperature=temperature, + ) + + +def make_setup( + *, + simulation_name="Polymer", + simulations=None, + write_second_reaction_stage=True, +): + return SimpleNamespace( + simulation_name=simulation_name, + simulations=list( + simulations or [] + ), + write_second_reaction_stage=write_second_reaction_stage, + ) + + +class FakeInitialSettings: + instances = [] + + def __init__(self, reacter_files): + self.reacter_files = reacter_files + self.get_calls = 0 + + self.settings = SimpleNamespace( + units="real", + ) + + self.__class__.instances.append( + self + ) + + def get_LUNAR_lammps_settings(self): + self.get_calls += 1 + + return self.settings + + +# ============================================================================= +# Constructor +# ============================================================================= + + +def test_constructor_stores_reacter_files( + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + reacter_files = ( + make_reacter_files() + ) + + writer = Writer( + reacter_files=reacter_files + ) + + assert ( + writer.reacter_files + is reacter_files + ) + + +def test_constructor_creates_lammps_initial_settings( + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + reacter_files = ( + make_reacter_files() + ) + + writer = Writer( + reacter_files=reacter_files + ) + + assert ( + len(FakeInitialSettings.instances) + == 1 + ) + + instance = ( + FakeInitialSettings.instances[0] + ) + + assert ( + instance.reacter_files + is reacter_files + ) + + assert ( + writer.lammps_initial_setup + is instance + ) + + +def test_constructor_gets_lunar_settings_once( + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + writer = Writer( + reacter_files=( + make_reacter_files() + ) + ) + + instance = ( + FakeInitialSettings.instances[0] + ) + + assert ( + instance.get_calls + == 1 + ) + + assert ( + writer.settings + is instance.settings + ) + + +# ============================================================================= +# Main output directories +# ============================================================================= + + +def test_write_all_files_creates_lammps_input_files_directory( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + writer = Writer( + make_reacter_files() + ) + + setup = make_setup( + simulations=[] + ) + + writer.write_all_files( + tmp_path, + setup, + ) + + assert ( + tmp_path + / "LAMMPS_input_files" + ).is_dir() + + +def test_write_all_files_creates_simulation_subdirectory( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + # Prevent real writer execution. + monkeypatch.setattr( + writer_module, + "DensificationWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + lambda **kwargs: None, + ) + + writer = Writer( + make_reacter_files() + ) + + setup = make_setup( + simulation_name="Styrene", + simulations=[ + make_simulation( + tag="298K" + ) + ], + ) + + writer.write_all_files( + tmp_path, + setup, + ) + + assert ( + tmp_path + / "LAMMPS_input_files" + / "Styrene_298K" + ).is_dir() + + +def test_each_simulation_gets_own_subdirectory( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + lambda **kwargs: None, + ) + + writer = Writer( + make_reacter_files() + ) + + setup = make_setup( + simulation_name="Styrene", + simulations=[ + make_simulation( + tag="298K" + ), + make_simulation( + tag="373K" + ), + make_simulation( + tag="523K" + ), + ], + ) + + writer.write_all_files( + tmp_path, + setup, + ) + + base = ( + tmp_path + / "LAMMPS_input_files" + ) + + assert ( + base / "Styrene_298K" + ).is_dir() + + assert ( + base / "Styrene_373K" + ).is_dir() + + assert ( + base / "Styrene_523K" + ).is_dir() + + +# ============================================================================= +# Stage orchestration +# ============================================================================= + + +def test_all_five_stages_are_called_when_second_stage_enabled( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + events = [] + + def fake_stage(name): + def factory(**kwargs): + events.append( + ( + name, + kwargs, + ) + ) + + return SimpleNamespace() + + return factory + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + fake_stage("densification"), + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + fake_stage("pre_eq"), + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + fake_stage("rxn_first"), + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + fake_stage("rxn_second"), + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + fake_stage("post_eq"), + ) + + simulation = make_simulation() + + setup = make_setup( + simulations=[ + simulation + ], + write_second_reaction_stage=True, + ) + + writer = Writer( + make_reacter_files() + ) + + writer.write_all_files( + tmp_path, + setup, + ) + + assert [ + name + for name, _ + in events + ] == [ + "densification", + "pre_eq", + "rxn_first", + "rxn_second", + "post_eq", + ] + + +def test_second_stage_is_skipped_when_disabled( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + events = [] + + def fake_stage(name): + def factory(**kwargs): + events.append(name) + return SimpleNamespace() + + return factory + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + fake_stage("densification"), + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + fake_stage("pre_eq"), + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + fake_stage("rxn_first"), + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + fake_stage("rxn_second"), + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + fake_stage("post_eq"), + ) + + writer = Writer( + make_reacter_files() + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulations=[ + make_simulation() + ], + write_second_reaction_stage=False, + ), + ) + + assert events == [ + "densification", + "pre_eq", + "rxn_first", + "post_eq", + ] + + assert ( + "rxn_second" + not in events + ) + + +# ============================================================================= +# Common arguments +# ============================================================================= + + +def test_densification_receives_expected_arguments( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + captured = {} + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + lambda **kwargs: + captured.update(kwargs), + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + lambda **kwargs: None, + ) + + reacter_files = ( + make_reacter_files() + ) + + simulation = ( + make_simulation( + tag="500K" + ) + ) + + writer = Writer( + reacter_files + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulation_name="Polymer", + simulations=[ + simulation + ], + ), + ) + + expected_dir = ( + tmp_path + / "LAMMPS_input_files" + / "Polymer_500K" + ) + + assert ( + captured["out_dir"] + == expected_dir + ) + + assert ( + captured["settings"] + is writer.settings + ) + + assert ( + captured["reacter_files"] + is reacter_files + ) + + assert ( + captured["simulation"] + is simulation + ) + + assert ( + captured["sim_name"] + == "Polymer" + ) + + +def test_pre_eq_receives_expected_arguments( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + captured = {} + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + lambda **kwargs: + captured.update(kwargs), + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + lambda **kwargs: None, + ) + + simulation = make_simulation() + + writer = Writer( + make_reacter_files() + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulation_name="Polymer", + simulations=[ + simulation + ], + ), + ) + + assert ( + captured["settings"] + is writer.settings + ) + + assert ( + captured["simulation"] + is simulation + ) + + assert ( + captured["sim_name"] + == "Polymer" + ) + + assert ( + "reacter_files" + not in captured + ) + + +def test_first_reaction_stage_receives_reacter_files( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + captured = {} + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + lambda **kwargs: + captured.update(kwargs), + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + lambda **kwargs: None, + ) + + reacter_files = ( + make_reacter_files() + ) + + writer = Writer( + reacter_files + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulations=[ + make_simulation() + ], + ), + ) + + assert ( + captured["reacter_files"] + is reacter_files + ) + + +def test_second_reaction_stage_receives_reacter_files( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + captured = {} + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + lambda **kwargs: + captured.update(kwargs), + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + lambda **kwargs: None, + ) + + reacter_files = ( + make_reacter_files() + ) + + writer = Writer( + reacter_files + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulations=[ + make_simulation() + ], + write_second_reaction_stage=True, + ), + ) + + assert ( + captured["reacter_files"] + is reacter_files + ) + + +# ============================================================================= +# Post-equilibration flag forwarding +# ============================================================================= + + +@pytest.mark.parametrize( + "write_second_stage", + [ + True, + False, + ], +) +def test_post_eq_receives_second_stage_flag( + tmp_path, + monkeypatch, + write_second_stage, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + captured = {} + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + lambda **kwargs: None, + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + lambda **kwargs: + captured.update(kwargs), + ) + + writer = Writer( + make_reacter_files() + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulations=[ + make_simulation() + ], + write_second_reaction_stage=( + write_second_stage + ), + ), + ) + + assert ( + captured[ + "write_second_reaction_stage" + ] + is write_second_stage + ) + + +# ============================================================================= +# Multiple simulations +# ============================================================================= + + +def test_all_stages_run_for_each_simulation( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + calls = [] + + def fake_stage(name): + def factory(**kwargs): + calls.append( + ( + name, + kwargs["simulation"].tag, + ) + ) + + return SimpleNamespace() + + return factory + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + fake_stage("dense"), + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + fake_stage("pre"), + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + fake_stage("rxn1"), + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + fake_stage("rxn2"), + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + fake_stage("post"), + ) + + writer = Writer( + make_reacter_files() + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulations=[ + make_simulation( + tag="298K" + ), + make_simulation( + tag="500K" + ), + ], + write_second_reaction_stage=True, + ), + ) + + assert calls == [ + ("dense", "298K"), + ("pre", "298K"), + ("rxn1", "298K"), + ("rxn2", "298K"), + ("post", "298K"), + ("dense", "500K"), + ("pre", "500K"), + ("rxn1", "500K"), + ("rxn2", "500K"), + ("post", "500K"), + ] + + +def test_same_settings_object_is_shared_across_all_stages( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + received_settings = [] + + def fake_stage(**kwargs): + received_settings.append( + kwargs["settings"] + ) + + return SimpleNamespace() + + monkeypatch.setattr( + writer_module, + "DensificationWriter", + fake_stage, + ) + + monkeypatch.setattr( + writer_module, + "PreEqWriter", + fake_stage, + ) + + monkeypatch.setattr( + writer_module, + "RxnFirstStageWriter", + fake_stage, + ) + + monkeypatch.setattr( + writer_module, + "RxnSecondStageWriter", + fake_stage, + ) + + monkeypatch.setattr( + writer_module, + "PostEqWriter", + fake_stage, + ) + + writer = Writer( + make_reacter_files() + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulations=[ + make_simulation() + ], + write_second_reaction_stage=True, + ), + ) + + assert len( + received_settings + ) == 5 + + assert all( + settings + is writer.settings + for settings + in received_settings + ) + + +# ============================================================================= +# Empty setup +# ============================================================================= + + +def test_empty_simulation_list_creates_only_root_lammps_directory( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + writer = Writer( + make_reacter_files() + ) + + writer.write_all_files( + tmp_path, + make_setup( + simulations=[] + ), + ) + + root = ( + tmp_path + / "LAMMPS_input_files" + ) + + assert root.is_dir() + + assert list( + root.iterdir() + ) == [] + + +def test_write_all_files_returns_none( + tmp_path, + monkeypatch, +): + FakeInitialSettings.instances.clear() + + monkeypatch.setattr( + writer_module, + "LammpsInitialSettings", + FakeInitialSettings, + ) + + writer = Writer( + make_reacter_files() + ) + + result = writer.write_all_files( + tmp_path, + make_setup( + simulations=[] + ), + ) + + assert result is None \ No newline at end of file diff --git a/tests/unit/test_input_parser.py b/tests/unit/test_input_parser.py index afd2fea4..5ae47fa1 100644 --- a/tests/unit/test_input_parser.py +++ b/tests/unit/test_input_parser.py @@ -200,7 +200,7 @@ def test_simulation_setup_workflow_defaults(): assert ( setup.write_second_reaction_stage - is True + is False ) From daed3f76cc29aff9768ced5fbafe443a1352bcfe Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe Date: Wed, 19 Aug 2026 19:28:22 -0400 Subject: [PATCH 153/176] Clean example input files for v0.3 --- examples/DGEBA_MMA_IPN_homo1.json | 21 - examples/DGEBA_MMA_IPN_homo2.json | 21 - examples/co_polymerization.json | 35 - examples/doc_1.json | 39 - examples/doc_2.json | 34 - examples/epoxy_amine_reaction_iteration.json | 33 + examples/example_1.ipynb | 506 +++++------ examples/example_1.py | 214 ++--- examples/example_1_inputs_count_mode.json | 49 - examples/example_1_inputs_ratio_mode.json | 41 - examples/ipn_advanced_workflow.json | 43 + examples/legacy/example_1.ipynb | 854 +++++++++--------- examples/legacy/run_AutoREACTER.py | 428 ++++----- .../{ => legacy_examples}/DGEBA_MMA_IPN.json | 70 +- .../example_1_inputs_count_mode_FF.json | 78 +- .../{ => legacy_examples}/test_epoxy.json | 60 +- .../{ => legacy_examples}/test_styrene.json | 184 ++-- ...olyamide_count_mode_advanced_options.json} | 16 +- examples/polyamide_count_mode_basic.json | 36 + examples/polyamide_ratio_mode_basic.json | 38 + examples/styrene_wildcards.json | 28 + examples/test.json | 25 - examples/test_epoxy_dgeba_dds.json | 25 - examples/test_ethelene.json | 25 - examples/test_glycine.json | 19 - 25 files changed, 1383 insertions(+), 1539 deletions(-) delete mode 100644 examples/DGEBA_MMA_IPN_homo1.json delete mode 100644 examples/DGEBA_MMA_IPN_homo2.json delete mode 100644 examples/co_polymerization.json delete mode 100644 examples/doc_1.json delete mode 100644 examples/doc_2.json create mode 100644 examples/epoxy_amine_reaction_iteration.json delete mode 100644 examples/example_1_inputs_count_mode.json delete mode 100644 examples/example_1_inputs_ratio_mode.json create mode 100644 examples/ipn_advanced_workflow.json rename examples/{ => legacy_examples}/DGEBA_MMA_IPN.json (95%) rename examples/{ => legacy_examples}/example_1_inputs_count_mode_FF.json (95%) rename examples/{ => legacy_examples}/test_epoxy.json (94%) rename examples/{ => legacy_examples}/test_styrene.json (97%) rename examples/{TMC_MPD.json => polyamide_count_mode_advanced_options.json} (65%) create mode 100644 examples/polyamide_count_mode_basic.json create mode 100644 examples/polyamide_ratio_mode_basic.json create mode 100644 examples/styrene_wildcards.json delete mode 100644 examples/test.json delete mode 100644 examples/test_epoxy_dgeba_dds.json delete mode 100644 examples/test_ethelene.json delete mode 100644 examples/test_glycine.json diff --git a/examples/DGEBA_MMA_IPN_homo1.json b/examples/DGEBA_MMA_IPN_homo1.json deleted file mode 100644 index 5ae41c55..00000000 --- a/examples/DGEBA_MMA_IPN_homo1.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "simulation_name": "DGEBA_MMA_ED900_TEGDMA_IPN_homo1", - "force_field": "PCFF", - "simulations": [ - { - "tag": "ipn_10k_298K", - "temperature": 298.15, - "density": 1.23, - "total_atoms": 10000, - "monomer_ratios": { - "tegdma": 0.7 - } - } - ], - "monomers": [ - { - "name": "tegdma", - "smiles": "CC(=C)C(=O)OCCOCCOCCOC(=O)C(=C)C" - } - ] -} diff --git a/examples/DGEBA_MMA_IPN_homo2.json b/examples/DGEBA_MMA_IPN_homo2.json deleted file mode 100644 index f395ecd9..00000000 --- a/examples/DGEBA_MMA_IPN_homo2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "simulation_name": "DGEBA_MMA_ED900_TEGDMA_IPN_homo2", - "force_field": "PCFF", - "simulations": [ - { - "tag": "ipn_10k_298K", - "temperature": 298.15, - "density": 1.23, - "total_atoms": 10000, - "monomer_ratios": { - "mma": 14.0 - } - } - ], - "monomers": [ - { - "name": "mma", - "smiles": "COC(=O)C(C)=C" - } - ] -} diff --git a/examples/co_polymerization.json b/examples/co_polymerization.json deleted file mode 100644 index e0502b87..00000000 --- a/examples/co_polymerization.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "simulation_name": "Methyl_Methacrylate_Triethylene_Glycol_Dimethacrylate_Copolymerization_100k_500K_with_wildcards", - - "force_field": "PCFF", - - "wildcards": true, - - "simulations": [ - { - "tag": "MMA_TEGDMA_100k_500K", - - "temperature": 500.0, - - "density": 1.23, - - "total_atoms": 100000, - - "monomer_ratios": { - "methyl_methacrylate": 14.0, - "styrene": 0.7 - } - } - ], - - "monomers": [ - { - "name": "methyl_methacrylate", - "smiles": "COC(=O)C(C)=C" - }, - { - "name": "styrene", - "smiles": "C=CC1=CC=CC=C1" - } - ] -} \ No newline at end of file diff --git a/examples/doc_1.json b/examples/doc_1.json deleted file mode 100644 index 223fec4c..00000000 --- a/examples/doc_1.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "simulation_name": "TMC_MPD_edge_case", - "force_field": "PCFF", - - "deep_search": true, - "reaction_iteration_depth": false, - "wildcards": false, - "deduplicate_reaction_templates": true, - "write_second_reaction_stage": true, - - "simulations": [ - { - "tag": "100k_300K", - "temperature": 300, - "density": 0.8, - "monomer_counts": { - "alkenyl_branched_diacid_chloride": 2380, - "m-phenylenediamine": 3570, - "extended_alkenyl_branched_diacid_chloride": 100 - } - } - ], - "monomers": [ - { - "name": "alkenyl_branched_diacid_chloride", - "smiles": "C=CCC(CCCCCCC(CC=C)C(=O)Cl)C(=O)Cl" - }, - { - "name": "extended_alkenyl_branched_diacid_chloride", - "smiles": "C/C=C/CC(CCCCCCC(C/C=C/C)C(=O)Cl)C(=O)Cl" - }, - { - "name": "m-phenylenediamine", - "smiles": "C1=CC(=CC(=C1)N)N" - } - - ] - } - diff --git a/examples/doc_2.json b/examples/doc_2.json deleted file mode 100644 index 581c2cd7..00000000 --- a/examples/doc_2.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", - "deep_search": false, - "reaction_iteration_depth": 5, - "wildcards": false, - "deduplicate_reaction_templates": true, - "write_second_reaction_stage": true, - "simulations": [ - { - "tag": "epoxy_test", - "temperature": 300, - "density": 1.0, - "monomer_counts": { - "di_epoxy": 200, - "primary_diamine": 100, - "primary_diamine_2": 50 - } - } - ], - "monomers": [ - { - "name": "di_epoxy", - "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" - }, - { - "name": "primary_diamine", - "smiles": "NCCCCCN" - }, - { - "name": "primary_diamine_2", - "smiles": "CC(CCN)CCN" - } - ] -} diff --git a/examples/epoxy_amine_reaction_iteration.json b/examples/epoxy_amine_reaction_iteration.json new file mode 100644 index 00000000..8d200f4d --- /dev/null +++ b/examples/epoxy_amine_reaction_iteration.json @@ -0,0 +1,33 @@ +{ + "simulation_name": "Epoxy_Amine_Reaction_Iteration", + "force_field": "PCFF", + + "deep_search": true, + "reaction_iteration_depth": 5, + "wildcards": true, + "deduplicate_reaction_templates": true, + "write_second_reaction_stage": false, + + "simulations": [ + { + "tag": "10k_300K", + "temperature": 300, + "density": 1.0, + "monomer_counts": { + "bisphenol_A_diglycidyl_ether": 200, + "1_5_diaminopentane": 100 + } + } + ], + + "monomers": [ + { + "name": "bisphenol_A_diglycidyl_ether", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" + }, + { + "name": "1_5_diaminopentane", + "smiles": "NCCCCCN" + } + ] +} diff --git a/examples/example_1.ipynb b/examples/example_1.ipynb index 76bc5593..21896011 100644 --- a/examples/example_1.ipynb +++ b/examples/example_1.ipynb @@ -1,253 +1,253 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9bf80177", - "metadata": {}, - "source": [ - "### Import AutoREACTER\n", - "\n", - "Import AutoREACTER as `arx` and check whether the package is available in the current environment." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b09e129b", - "metadata": {}, - "outputs": [], - "source": [ - "try:\n", - " import AutoREACTER as arx \n", - " print(\"AutoREACTER imported successfully.\")\n", - "except ImportError:\n", - " print(\"Failed to import AutoREACTER.\")" - ] - }, - { - "cell_type": "markdown", - "id": "b05e6b71", - "metadata": {}, - "source": [ - "### Load Input File\n", - "\n", - "Print the installed AutoREACTER version and load the input JSON file for the current simulation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2b47cb12", - "metadata": {}, - "outputs": [], - "source": [ - "print(arx.__version__)\n", - "arx.run(\"example_1_inputs_count_mode.json\")" - ] - }, - { - "cell_type": "markdown", - "id": "741ae24d", - "metadata": {}, - "source": [ - "### Show Molecules (Optional)\n", - "\n", - "Visualize the starting molecules detected from the input file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "74453196", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_molecules()" - ] - }, - { - "cell_type": "markdown", - "id": "03308558", - "metadata": {}, - "source": [ - "### Show Functional Groups (Optional)\n", - "\n", - "Visualize the functional groups detected on each molecule.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "230aab0c", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_functional_groups()" - ] - }, - { - "cell_type": "markdown", - "id": "cc3e4d93", - "metadata": {}, - "source": [ - "### Show Reactions (Optional)\n", - "\n", - "Visualize the reactions detected from the available functional groups.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fa3879a2", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_reactions()" - ] - }, - { - "cell_type": "markdown", - "id": "58b083b4", - "metadata": {}, - "source": [ - "\n", - "### Select Reactions\n", - "\n", - "Select which detected reactions should be used in the AutoREACTER workflow." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "94738f8e", - "metadata": {}, - "outputs": [], - "source": [ - "arx.select_reactions()" - ] - }, - { - "cell_type": "markdown", - "id": "24d2a9b4", - "metadata": {}, - "source": [ - "### Show non-reactant molecules (Optional)\n", - "\n", - "Visualize the non-reactant molecules that were detected from the input file. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "26efd1f1", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_non_reactants()" - ] - }, - { - "cell_type": "markdown", - "id": "a980ff60", - "metadata": {}, - "source": [ - "\n", - "### Select Non-Reactants\n", - "\n", - "Select non-reactant molecules, if any are detected in the system." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cd7be137", - "metadata": {}, - "outputs": [], - "source": [ - "arx.select_non_reactants()" - ] - }, - { - "cell_type": "markdown", - "id": "9311e742", - "metadata": {}, - "source": [ - "### Prepare Reactions\n", - "\n", - "Prepare the selected reaction templates for downstream processing." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "745635f3", - "metadata": {}, - "outputs": [], - "source": [ - "arx.prepare_reactions()" - ] - }, - { - "cell_type": "markdown", - "id": "90b5747e", - "metadata": {}, - "source": [ - "\n", - "### Show Reaction Templates\n", - "\n", - "Visualize the prepared reaction templates. Here, `\"template\"` highlights atoms or components removed during the reaction." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "94018071", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_reaction_templates(\"template\")" - ] - }, - { - "cell_type": "markdown", - "id": "459a32cd", - "metadata": {}, - "source": [ - "### Process System\n", - "\n", - "Run the final AutoREACTER processing step to generate the simulation-ready outputs." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ba05aaf", - "metadata": {}, - "outputs": [], - "source": [ - "arx.process()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.0" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9bf80177", + "metadata": {}, + "source": [ + "### Import AutoREACTER\n", + "\n", + "Import AutoREACTER as `arx` and check whether the package is available in the current environment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b09e129b", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " import AutoREACTER as arx \n", + " print(\"AutoREACTER imported successfully.\")\n", + "except ImportError:\n", + " print(\"Failed to import AutoREACTER.\")" + ] + }, + { + "cell_type": "markdown", + "id": "b05e6b71", + "metadata": {}, + "source": [ + "### Load Input File\n", + "\n", + "Print the installed AutoREACTER version and load the input JSON file for the current simulation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b47cb12", + "metadata": {}, + "outputs": [], + "source": [ + "print(arx.__version__)\n", + "arx.run(\"example_1_inputs_count_mode.json\")" + ] + }, + { + "cell_type": "markdown", + "id": "741ae24d", + "metadata": {}, + "source": [ + "### Show Molecules (Optional)\n", + "\n", + "Visualize the starting molecules detected from the input file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74453196", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_molecules()" + ] + }, + { + "cell_type": "markdown", + "id": "03308558", + "metadata": {}, + "source": [ + "### Show Functional Groups (Optional)\n", + "\n", + "Visualize the functional groups detected on each molecule.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "230aab0c", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_functional_groups()" + ] + }, + { + "cell_type": "markdown", + "id": "cc3e4d93", + "metadata": {}, + "source": [ + "### Show Reactions (Optional)\n", + "\n", + "Visualize the reactions detected from the available functional groups.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa3879a2", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_reactions()" + ] + }, + { + "cell_type": "markdown", + "id": "58b083b4", + "metadata": {}, + "source": [ + "\n", + "### Select Reactions\n", + "\n", + "Select which detected reactions should be used in the AutoREACTER workflow." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94738f8e", + "metadata": {}, + "outputs": [], + "source": [ + "arx.select_reactions()" + ] + }, + { + "cell_type": "markdown", + "id": "24d2a9b4", + "metadata": {}, + "source": [ + "### Show non-reactant molecules (Optional)\n", + "\n", + "Visualize the non-reactant molecules that were detected from the input file. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26efd1f1", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_non_reactants()" + ] + }, + { + "cell_type": "markdown", + "id": "a980ff60", + "metadata": {}, + "source": [ + "\n", + "### Select Non-Reactants\n", + "\n", + "Select non-reactant molecules, if any are detected in the system." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd7be137", + "metadata": {}, + "outputs": [], + "source": [ + "arx.select_non_reactants()" + ] + }, + { + "cell_type": "markdown", + "id": "9311e742", + "metadata": {}, + "source": [ + "### Prepare Reactions\n", + "\n", + "Prepare the selected reaction templates for downstream processing." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "745635f3", + "metadata": {}, + "outputs": [], + "source": [ + "arx.prepare_reactions()" + ] + }, + { + "cell_type": "markdown", + "id": "90b5747e", + "metadata": {}, + "source": [ + "\n", + "### Show Reaction Templates\n", + "\n", + "Visualize the prepared reaction templates. Here, `\"template\"` highlights atoms or components removed during the reaction." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94018071", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_reaction_templates(\"template\")" + ] + }, + { + "cell_type": "markdown", + "id": "459a32cd", + "metadata": {}, + "source": [ + "### Process System\n", + "\n", + "Run the final AutoREACTER processing step to generate the simulation-ready outputs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ba05aaf", + "metadata": {}, + "outputs": [], + "source": [ + "arx.process()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/example_1.py b/examples/example_1.py index 51fe9dec..03c3942c 100644 --- a/examples/example_1.py +++ b/examples/example_1.py @@ -1,107 +1,107 @@ -#!/usr/bin/env python3 -""" -AutoREACTER Workflow: Required Pipeline Example -=============================================== - -This script demonstrates the required AutoREACTER workflow only. -Visualization images are generated internally and saved in the session image directory. - -Usage: - python auto_reacter_workflow.py -i example_1_inputs_count_mode.json -""" - -import argparse -import sys - - -# --------------------------------------------------------------------------- -# 1. Command-line arguments -# --------------------------------------------------------------------------- -parser = argparse.ArgumentParser( - description="Run the required AutoREACTER workflow from an input JSON file." -) - -parser.add_argument( - "-i", - "--input", - "-in", - required=True, - help="Path to the AutoREACTER input JSON file." -) - -args = parser.parse_args() - - -# --------------------------------------------------------------------------- -# 2. Import AutoREACTER -# --------------------------------------------------------------------------- -try: - import AutoREACTER as arx - print("AutoREACTER imported successfully.") -except ImportError: - print( - "Failed to import AutoREACTER. " - "Ensure the package is installed in your environment." - ) - raise - - -# --------------------------------------------------------------------------- -# 3. Version check & input load -# --------------------------------------------------------------------------- -# Print the installed version for reproducibility and debugging. -print(arx.__version__) - -# Load the JSON input file and initialize the AutoREACTER session. -arx.run(args.input) -session = arx.session() - - -# --------------------------------------------------------------------------- -# 4. Select reactions and non-reactants -# --------------------------------------------------------------------------- -# Select which detected reactions should be processed. -arx.select_reactions() - -# Select non-reactant molecules, if any are detected. -arx.select_non_reactants() - - -# --------------------------------------------------------------------------- -# 5. Reaction template preparation -# --------------------------------------------------------------------------- -# Prepare reaction templates for downstream REACTER file generation. -arx.prepare_reactions() - - -# --------------------------------------------------------------------------- -# 6. Review checkpoint -# --------------------------------------------------------------------------- -# AutoREACTER saves visualization images internally in the session image directory. -print( - "\n[INFO] Reaction preparation completed." - "\n[INFO] Please review the generated images in the session image directory." -) - -# Try to print the image directory if it is exposed by AutoREACTER. -session = arx.session() -img_dir = getattr(session, "img_dir", None) or getattr(session, "images_dir", None) - -if img_dir is not None: - print(f"[INFO] Image directory: {img_dir}") - -ok_pass = input("\nType 'ok' to continue with final processing: ").strip().lower() - -if ok_pass != "ok": - print("[EXIT] Workflow stopped by user.") - sys.exit(0) - - -# --------------------------------------------------------------------------- -# 7. Final processing -# --------------------------------------------------------------------------- -# Run 3D geometry setup, force-field generation, REACTER file building, -# and LAMMPS simulation setup. -arx.process() - -print("\n[INFO] AutoREACTER workflow completed successfully.") +#!/usr/bin/env python3 +""" +AutoREACTER Workflow: Required Pipeline Example +=============================================== + +This script demonstrates the required AutoREACTER workflow only. +Visualization images are generated internally and saved in the session image directory. + +Usage: + python auto_reacter_workflow.py -i example_1_inputs_count_mode.json +""" + +import argparse +import sys + + +# --------------------------------------------------------------------------- +# 1. Command-line arguments +# --------------------------------------------------------------------------- +parser = argparse.ArgumentParser( + description="Run the required AutoREACTER workflow from an input JSON file." +) + +parser.add_argument( + "-i", + "--input", + "-in", + required=True, + help="Path to the AutoREACTER input JSON file." +) + +args = parser.parse_args() + + +# --------------------------------------------------------------------------- +# 2. Import AutoREACTER +# --------------------------------------------------------------------------- +try: + import AutoREACTER as arx + print("AutoREACTER imported successfully.") +except ImportError: + print( + "Failed to import AutoREACTER. " + "Ensure the package is installed in your environment." + ) + raise + + +# --------------------------------------------------------------------------- +# 3. Version check & input load +# --------------------------------------------------------------------------- +# Print the installed version for reproducibility and debugging. +print(arx.__version__) + +# Load the JSON input file and initialize the AutoREACTER session. +arx.run(args.input) +session = arx.session() + + +# --------------------------------------------------------------------------- +# 4. Select reactions and non-reactants +# --------------------------------------------------------------------------- +# Select which detected reactions should be processed. +arx.select_reactions() + +# Select non-reactant molecules, if any are detected. +arx.select_non_reactants() + + +# --------------------------------------------------------------------------- +# 5. Reaction template preparation +# --------------------------------------------------------------------------- +# Prepare reaction templates for downstream REACTER file generation. +arx.prepare_reactions() + + +# --------------------------------------------------------------------------- +# 6. Review checkpoint +# --------------------------------------------------------------------------- +# AutoREACTER saves visualization images internally in the session image directory. +print( + "\n[INFO] Reaction preparation completed." + "\n[INFO] Please review the generated images in the session image directory." +) + +# Try to print the image directory if it is exposed by AutoREACTER. +session = arx.session() +img_dir = getattr(session, "img_dir", None) or getattr(session, "images_dir", None) + +if img_dir is not None: + print(f"[INFO] Image directory: {img_dir}") + +ok_pass = input("\nType 'ok' to continue with final processing: ").strip().lower() + +if ok_pass != "ok": + print("[EXIT] Workflow stopped by user.") + sys.exit(0) + + +# --------------------------------------------------------------------------- +# 7. Final processing +# --------------------------------------------------------------------------- +# Run 3D geometry setup, force-field generation, REACTER file building, +# and LAMMPS simulation setup. +arx.process() + +print("\n[INFO] AutoREACTER workflow completed successfully.") diff --git a/examples/example_1_inputs_count_mode.json b/examples/example_1_inputs_count_mode.json deleted file mode 100644 index aa0f64b3..00000000 --- a/examples/example_1_inputs_count_mode.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "simulation_name": "Example_Count_Mode", - "simulations": [ - { - "tag": "10k", - "temperature": 300, - "density": 1.3, - "monomer_counts": { - "tmc": 220, - "mpd": 220, - "data_3": 110 - } - }, - { - "tag": "100k", - "temperature": 400, - "density": 0.8, - "monomer_counts": { - "tmc": 2200, - "mpd": 2200, - "data_3": 1100 - } - }, - { - "tag": "100k_high_temp", - "temperature": 500, - "density": 0.8, - "monomer_counts": { - "tmc": 2200, - "mpd": 2200, - "data_3": 1100 - } - } - ], - "monomers": [ - { - "name": "tmc", - "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" - }, - { - "name": "mpd", - "smiles": "C1=CC(=CC(=C1)N)N" - }, - { - "name": "data_3", - "smiles": "CCO" - } - ] -} \ No newline at end of file diff --git a/examples/example_1_inputs_ratio_mode.json b/examples/example_1_inputs_ratio_mode.json deleted file mode 100644 index 69c1d1e3..00000000 --- a/examples/example_1_inputs_ratio_mode.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "simulation_name": "Example_Ratio_Mode", - "simulations": [ - { - "tag": "10k_base", - "temperature": 300, - "density": 0.8, - "total_atoms": 10000, - "monomer_ratios": { - "tmc": 1.0, - "mpd": 1.0, - "ethanol": 0.5 - } - }, - { - "tag": "100k_base", - "temperature": 400, - "density": 0.8, - "total_atoms": 100000, - "monomer_ratios": { - "tmc": 1.0, - "mpd": 1.0, - "ethanol": 0.5 - } - } - ], - "monomers": [ - { - "name": "tmc", - "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" - }, - { - "name": "mpd", - "smiles": "C1=CC(=CC(=C1)N)N" - }, - { - "name": "ethanol", - "smiles": "CCO" - } - ] -} \ No newline at end of file diff --git a/examples/ipn_advanced_workflow.json b/examples/ipn_advanced_workflow.json new file mode 100644 index 00000000..5d2c8bf6 --- /dev/null +++ b/examples/ipn_advanced_workflow.json @@ -0,0 +1,43 @@ +{ + "simulation_name": "DGEBA_MMA_TEGDMA_IPN_Advanced_Workflow", + "force_field": "PCFF", + + "deep_search": true, + "reaction_iteration_depth": 5, + "wildcards": true, + "deduplicate_reaction_templates": true, + "write_second_reaction_stage": true, + + "simulations": [ + { + "tag": "100k_500K", + "temperature": 500, + "density": 1.23, + "monomer_counts": { + "bisphenol_A_diglycidyl_ether": 450, + "1_5_diaminopentane": 225, + "methyl_methacrylate": 3000, + "triethylene_glycol_dimethacrylate": 150 + } + } + ], + + "monomers": [ + { + "name": "bisphenol_A_diglycidyl_ether", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" + }, + { + "name": "1_5_diaminopentane", + "smiles": "NCCCCCN" + }, + { + "name": "methyl_methacrylate", + "smiles": "COC(=O)C(C)=C" + }, + { + "name": "triethylene_glycol_dimethacrylate", + "smiles": "C=C(C)C(=O)OCCOCCOCCOC(=O)C(C)=C" + } + ] +} diff --git a/examples/legacy/example_1.ipynb b/examples/legacy/example_1.ipynb index 1778715a..d88419cf 100644 --- a/examples/legacy/example_1.ipynb +++ b/examples/legacy/example_1.ipynb @@ -1,427 +1,427 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "33f6dd27", - "metadata": {}, - "source": [ - "### Initialization and Environment Setup\n", - "\n", - "This cell initializes the AutoREACTER environment and prepares the working directory for the current run." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2dccf25a", - "metadata": {}, - "outputs": [], - "source": [ - "from AutoREACTER.session import read_input\n", - "from AutoREACTER.input_parser import InputParser\n", - "from AutoREACTER.detectors.functional_groups_detector import FunctionalGroupsDetector\n", - "from AutoREACTER.detectors.reaction_detector import ReactionDetector\n", - "from AutoREACTER.detectors.non_monomer_detector import NonReactantsDetector\n", - "from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions\n", - "from AutoREACTER.reaction_preparation.ff_wrapper.molecule_3d_preparation import Molecule3DPreparation\n", - "from AutoREACTER.reaction_preparation.ff_wrapper.ff_wrapper import FFWrapper\n", - "from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import REACTERFilesBuilder\n", - "from AutoREACTER.sim_setup.simulation_setup import SimulationSetupManager\n", - "\n", - "session = read_input(\"example_1_inputs_count_mode.json\")" - ] - }, - { - "cell_type": "markdown", - "id": "a48c7aee", - "metadata": {}, - "source": [ - "### Visualize Monomers (Optional)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "63c6e279", - "metadata": {}, - "outputs": [], - "source": [ - "# Generate and display the initial monomer structures.\n", - "input_parser = InputParser()\n", - "initial_molecules = input_parser.initial_molecules_image_grid(session.inputs)\n", - "initial_molecules" - ] - }, - { - "cell_type": "markdown", - "id": "65725a29", - "metadata": {}, - "source": [ - "### Functional Group Detection\n", - "\n", - "This cell runs the functional group detection step.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "04b6e642", - "metadata": {}, - "outputs": [], - "source": [ - "# Detect functional groups to get valid monomers\n", - "\n", - "functional_groups_detector = FunctionalGroupsDetector()\n", - "functional_groups_detector.functional_groups_detector(session)\n" - ] - }, - { - "cell_type": "markdown", - "id": "76ad6db0", - "metadata": {}, - "source": [ - "### Functional Group Visualization (Optional)\n", - "\n", - "This cell visualizes the detected functional groups on the molecules." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e295e3b3", - "metadata": {}, - "outputs": [], - "source": [ - "# The resulting image shows each molecule with the detected functional groups marked.\n", - "\n", - "img = functional_groups_detector.functional_group_highlighted_molecules_image_grid(session)\n", - "img" - ] - }, - { - "cell_type": "markdown", - "id": "80945c3f", - "metadata": {}, - "source": [ - "### Reaction Detection\n", - "\n", - "This cell identifies possible reactions between the detected functional groups.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "76817cd8", - "metadata": {}, - "outputs": [], - "source": [ - "# Detect possible reactions based on identified functional groups.\n", - "\n", - "reaction_detector = ReactionDetector()\n", - "reaction_detector.reaction_detector(session)" - ] - }, - { - "cell_type": "markdown", - "id": "0149d1d3", - "metadata": {}, - "source": [ - "### Reaction visualization (Optional)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b443f92e", - "metadata": {}, - "outputs": [], - "source": [ - "# Visualize detected reactions.\n", - "\n", - "img = reaction_detector.available_reaction_image_grid(session)\n", - "img" - ] - }, - { - "cell_type": "markdown", - "id": "069aee8f", - "metadata": {}, - "source": [ - "### Reaction Selection\n", - "\n", - "This cell filters and selects the relevant reactions from the detected reaction instances.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "26d581e2", - "metadata": {}, - "outputs": [], - "source": [ - "# Select relevant reactions for template generation as user intened.\n", - "\n", - "reaction_detector.reaction_selection(session)" - ] - }, - { - "cell_type": "markdown", - "id": "09b1cb36", - "metadata": {}, - "source": [ - "### Non-Reactant (Non-Monomer) Detection\n", - "\n", - "This cell identifies molecules that do **not participate in any detected reactions**.\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c811c031", - "metadata": {}, - "outputs": [], - "source": [ - "# Identify non-reactive molecules based on the selected reactions.\n", - "\n", - "non_monomer_detector = NonReactantsDetector()\n", - "\n", - "non_monomer_detector.non_monomer_detector(session)" - ] - }, - { - "cell_type": "markdown", - "id": "2e03f325", - "metadata": {}, - "source": [ - "### Non reactants molecules visualization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5040c430", - "metadata": {}, - "outputs": [], - "source": [ - "# Visualize non-reactive molecules (if any are detected).\n", - "\n", - "img_non_reactants = non_monomer_detector.non_reactants_to_visualization(session)\n", - "img_non_reactants" - ] - }, - { - "cell_type": "markdown", - "id": "561c06dd", - "metadata": {}, - "source": [ - "### Update Inputs After Non-Reactant Filtering\n", - "\n", - "This cell updates the validated inputs after identifying non-reactive molecules.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "00d75b1a", - "metadata": {}, - "outputs": [], - "source": [ - "# Update inputs by filtering out non-reactive molecules.\n", - "\n", - "non_monomer_detector.non_reactant_selection(session)" - ] - }, - { - "cell_type": "markdown", - "id": "6746d472", - "metadata": {}, - "source": [ - "### Prepare reaction templates from the selected reactions for downstream processing." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d62efe2a", - "metadata": {}, - "outputs": [], - "source": [ - "prepare_reactions = PrepareReactions(session)\n", - "prepare_reactions.prepare_reactions(session)" - ] - }, - { - "cell_type": "markdown", - "id": "1b031c97", - "metadata": {}, - "source": [ - "### Reaction Template Visualization\n", - "\n", - "Visualize reaction templates with different highlighting options setting the `highlight_type` parameter to one of the following values:\n", - "\n", - "- **Default** or **template**: Highlights all structural changes in the reaction templates \n", - "- **edge**: Highlights edge atoms of the templates \n", - "- **delete**: Highlights removed components (if applicable) \n", - "- **initiators**: Highlights reaction initiator atoms " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a7c134e5", - "metadata": {}, - "outputs": [], - "source": [ - "img = prepare_reactions.reaction_templates_highlighted_image_grid(session, highlight_type=\"edge\")\n", - "img" - ] - }, - { - "cell_type": "markdown", - "id": "30207664", - "metadata": {}, - "source": [ - "### 3D Geometry Preparation\n", - "\n", - "Prepare 3D molecular geometries for both inputs molecules and reaction templates. \n", - "This step generates the structures required for the Lunar atom typing." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6603c504", - "metadata": {}, - "outputs": [], - "source": [ - "molecule3dpreparation = Molecule3DPreparation(session)\n", - "\n", - "molecule3dpreparation.prepare_molecule_3d_geometry(\n", - " session\n", - " )\n" - ] - }, - { - "cell_type": "markdown", - "id": "be30857a", - "metadata": {}, - "source": [ - "### Lunar Workflow\n", - "\n", - "Run the Lunar workflow to generate simulation-ready files from prepared 3D structures." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c6a74035", - "metadata": {}, - "outputs": [], - "source": [ - "ff_wrapper = FFWrapper(session)\n", - "\n", - "ff_wrapper.generate_force_field_files(\n", - " session\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "fff1fc61", - "metadata": {}, - "source": [ - "### REACTER File Generation and Finalization\n", - "\n", - "Generate REACTER-compatible files from the Lunar results and prepared reactions. \n", - "The generated files are then moved to the final run directory, and all internal paths are updated accordingly." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "52d28045", - "metadata": {}, - "outputs": [], - "source": [ - "from AutoREACTER.cache import RunDirectoryManager\n", - "\n", - "builder = REACTERFilesBuilder(\n", - " session=session,\n", - ")\n", - "\n", - "reacter_files = builder.molecule_template_preparation(\n", - " session=session,\n", - ")\n", - "\n", - "# Move generated files to final output directory using RunDirectoryManager\n", - "run_manager = RunDirectoryManager(session.output_dir.parent)\n", - "reacter_files = run_manager.move_reacter_files(\n", - " reacter_files,\n", - " staging_dir=session.staging_dir,\n", - " final_dir=session.output_dir\n", - ")\n", - "\n", - "\n", - "print(f\"[OK] REACTER files successfully moved to {session.output_dir}\")" - ] - }, - { - "cell_type": "markdown", - "id": "0a0add61", - "metadata": {}, - "source": [ - "### Simulation Setup and LAMMPS Script Generation\n", - "\n", - "Calculate physical system properties (e.g., box sizes, required monomer counts to reach target densities) and generate the complete suite of LAMMPS input scripts. \n", - "\n", - "This automatically writes the configuration files for all 5 stages:\n", - "1. Densification\n", - "2. Pre-reaction Equilibration\n", - "3. First Reaction Stage (3.5A)\n", - "4. Second Reaction Stage (5.0A)\n", - "5. Post-reaction Equilibration" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bb8a48f5", - "metadata": {}, - "outputs": [], - "source": [ - "Simulation_setup_manager = SimulationSetupManager()\n", - "\n", - "updated_inputs_3d = Simulation_setup_manager.setup_and_write_simulation(\n", - " setup=updated_inputs_with_3d_mols,\n", - " reacter_files=reacter_files,\n", - " run_dir=session.output_dir\n", - ")\n", - "\n", - "print(\"\\n[INFO] AutoREACTER workflow completed successfully.\\n\")\n", - "print(f\"Final REACTER and LAMMPS files are located in: {session.output_dir}\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "arx_testpypi_pkg_test", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.13.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "markdown", + "id": "33f6dd27", + "metadata": {}, + "source": [ + "### Initialization and Environment Setup\n", + "\n", + "This cell initializes the AutoREACTER environment and prepares the working directory for the current run." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2dccf25a", + "metadata": {}, + "outputs": [], + "source": [ + "from AutoREACTER.session import read_input\n", + "from AutoREACTER.input_parser import InputParser\n", + "from AutoREACTER.detectors.functional_groups_detector import FunctionalGroupsDetector\n", + "from AutoREACTER.detectors.reaction_detector import ReactionDetector\n", + "from AutoREACTER.detectors.non_monomer_detector import NonReactantsDetector\n", + "from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions\n", + "from AutoREACTER.reaction_preparation.ff_wrapper.molecule_3d_preparation import Molecule3DPreparation\n", + "from AutoREACTER.reaction_preparation.ff_wrapper.ff_wrapper import FFWrapper\n", + "from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import REACTERFilesBuilder\n", + "from AutoREACTER.sim_setup.simulation_setup import SimulationSetupManager\n", + "\n", + "session = read_input(\"example_1_inputs_count_mode.json\")" + ] + }, + { + "cell_type": "markdown", + "id": "a48c7aee", + "metadata": {}, + "source": [ + "### Visualize Monomers (Optional)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63c6e279", + "metadata": {}, + "outputs": [], + "source": [ + "# Generate and display the initial monomer structures.\n", + "input_parser = InputParser()\n", + "initial_molecules = input_parser.initial_molecules_image_grid(session.inputs)\n", + "initial_molecules" + ] + }, + { + "cell_type": "markdown", + "id": "65725a29", + "metadata": {}, + "source": [ + "### Functional Group Detection\n", + "\n", + "This cell runs the functional group detection step.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "04b6e642", + "metadata": {}, + "outputs": [], + "source": [ + "# Detect functional groups to get valid monomers\n", + "\n", + "functional_groups_detector = FunctionalGroupsDetector()\n", + "functional_groups_detector.functional_groups_detector(session)\n" + ] + }, + { + "cell_type": "markdown", + "id": "76ad6db0", + "metadata": {}, + "source": [ + "### Functional Group Visualization (Optional)\n", + "\n", + "This cell visualizes the detected functional groups on the molecules." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e295e3b3", + "metadata": {}, + "outputs": [], + "source": [ + "# The resulting image shows each molecule with the detected functional groups marked.\n", + "\n", + "img = functional_groups_detector.functional_group_highlighted_molecules_image_grid(session)\n", + "img" + ] + }, + { + "cell_type": "markdown", + "id": "80945c3f", + "metadata": {}, + "source": [ + "### Reaction Detection\n", + "\n", + "This cell identifies possible reactions between the detected functional groups.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76817cd8", + "metadata": {}, + "outputs": [], + "source": [ + "# Detect possible reactions based on identified functional groups.\n", + "\n", + "reaction_detector = ReactionDetector()\n", + "reaction_detector.reaction_detector(session)" + ] + }, + { + "cell_type": "markdown", + "id": "0149d1d3", + "metadata": {}, + "source": [ + "### Reaction visualization (Optional)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b443f92e", + "metadata": {}, + "outputs": [], + "source": [ + "# Visualize detected reactions.\n", + "\n", + "img = reaction_detector.available_reaction_image_grid(session)\n", + "img" + ] + }, + { + "cell_type": "markdown", + "id": "069aee8f", + "metadata": {}, + "source": [ + "### Reaction Selection\n", + "\n", + "This cell filters and selects the relevant reactions from the detected reaction instances.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26d581e2", + "metadata": {}, + "outputs": [], + "source": [ + "# Select relevant reactions for template generation as user intened.\n", + "\n", + "reaction_detector.reaction_selection(session)" + ] + }, + { + "cell_type": "markdown", + "id": "09b1cb36", + "metadata": {}, + "source": [ + "### Non-Reactant (Non-Monomer) Detection\n", + "\n", + "This cell identifies molecules that do **not participate in any detected reactions**.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c811c031", + "metadata": {}, + "outputs": [], + "source": [ + "# Identify non-reactive molecules based on the selected reactions.\n", + "\n", + "non_monomer_detector = NonReactantsDetector()\n", + "\n", + "non_monomer_detector.non_monomer_detector(session)" + ] + }, + { + "cell_type": "markdown", + "id": "2e03f325", + "metadata": {}, + "source": [ + "### Non reactants molecules visualization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5040c430", + "metadata": {}, + "outputs": [], + "source": [ + "# Visualize non-reactive molecules (if any are detected).\n", + "\n", + "img_non_reactants = non_monomer_detector.non_reactants_to_visualization(session)\n", + "img_non_reactants" + ] + }, + { + "cell_type": "markdown", + "id": "561c06dd", + "metadata": {}, + "source": [ + "### Update Inputs After Non-Reactant Filtering\n", + "\n", + "This cell updates the validated inputs after identifying non-reactive molecules.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00d75b1a", + "metadata": {}, + "outputs": [], + "source": [ + "# Update inputs by filtering out non-reactive molecules.\n", + "\n", + "non_monomer_detector.non_reactant_selection(session)" + ] + }, + { + "cell_type": "markdown", + "id": "6746d472", + "metadata": {}, + "source": [ + "### Prepare reaction templates from the selected reactions for downstream processing." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d62efe2a", + "metadata": {}, + "outputs": [], + "source": [ + "prepare_reactions = PrepareReactions(session)\n", + "prepare_reactions.prepare_reactions(session)" + ] + }, + { + "cell_type": "markdown", + "id": "1b031c97", + "metadata": {}, + "source": [ + "### Reaction Template Visualization\n", + "\n", + "Visualize reaction templates with different highlighting options setting the `highlight_type` parameter to one of the following values:\n", + "\n", + "- **Default** or **template**: Highlights all structural changes in the reaction templates \n", + "- **edge**: Highlights edge atoms of the templates \n", + "- **delete**: Highlights removed components (if applicable) \n", + "- **initiators**: Highlights reaction initiator atoms " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7c134e5", + "metadata": {}, + "outputs": [], + "source": [ + "img = prepare_reactions.reaction_templates_highlighted_image_grid(session, highlight_type=\"edge\")\n", + "img" + ] + }, + { + "cell_type": "markdown", + "id": "30207664", + "metadata": {}, + "source": [ + "### 3D Geometry Preparation\n", + "\n", + "Prepare 3D molecular geometries for both inputs molecules and reaction templates. \n", + "This step generates the structures required for the Lunar atom typing." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6603c504", + "metadata": {}, + "outputs": [], + "source": [ + "molecule3dpreparation = Molecule3DPreparation(session)\n", + "\n", + "molecule3dpreparation.prepare_molecule_3d_geometry(\n", + " session\n", + " )\n" + ] + }, + { + "cell_type": "markdown", + "id": "be30857a", + "metadata": {}, + "source": [ + "### Lunar Workflow\n", + "\n", + "Run the Lunar workflow to generate simulation-ready files from prepared 3D structures." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c6a74035", + "metadata": {}, + "outputs": [], + "source": [ + "ff_wrapper = FFWrapper(session)\n", + "\n", + "ff_wrapper.generate_force_field_files(\n", + " session\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "fff1fc61", + "metadata": {}, + "source": [ + "### REACTER File Generation and Finalization\n", + "\n", + "Generate REACTER-compatible files from the Lunar results and prepared reactions. \n", + "The generated files are then moved to the final run directory, and all internal paths are updated accordingly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52d28045", + "metadata": {}, + "outputs": [], + "source": [ + "from AutoREACTER.cache import RunDirectoryManager\n", + "\n", + "builder = REACTERFilesBuilder(\n", + " session=session,\n", + ")\n", + "\n", + "reacter_files = builder.molecule_template_preparation(\n", + " session=session,\n", + ")\n", + "\n", + "# Move generated files to final output directory using RunDirectoryManager\n", + "run_manager = RunDirectoryManager(session.output_dir.parent)\n", + "reacter_files = run_manager.move_reacter_files(\n", + " reacter_files,\n", + " staging_dir=session.staging_dir,\n", + " final_dir=session.output_dir\n", + ")\n", + "\n", + "\n", + "print(f\"[OK] REACTER files successfully moved to {session.output_dir}\")" + ] + }, + { + "cell_type": "markdown", + "id": "0a0add61", + "metadata": {}, + "source": [ + "### Simulation Setup and LAMMPS Script Generation\n", + "\n", + "Calculate physical system properties (e.g., box sizes, required monomer counts to reach target densities) and generate the complete suite of LAMMPS input scripts. \n", + "\n", + "This automatically writes the configuration files for all 5 stages:\n", + "1. Densification\n", + "2. Pre-reaction Equilibration\n", + "3. First Reaction Stage (3.5A)\n", + "4. Second Reaction Stage (5.0A)\n", + "5. Post-reaction Equilibration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb8a48f5", + "metadata": {}, + "outputs": [], + "source": [ + "Simulation_setup_manager = SimulationSetupManager()\n", + "\n", + "updated_inputs_3d = Simulation_setup_manager.setup_and_write_simulation(\n", + " setup=updated_inputs_with_3d_mols,\n", + " reacter_files=reacter_files,\n", + " run_dir=session.output_dir\n", + ")\n", + "\n", + "print(\"\\n[INFO] AutoREACTER workflow completed successfully.\\n\")\n", + "print(f\"Final REACTER and LAMMPS files are located in: {session.output_dir}\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "arx_testpypi_pkg_test", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/legacy/run_AutoREACTER.py b/examples/legacy/run_AutoREACTER.py index 6c02cb6b..c0e126b6 100644 --- a/examples/legacy/run_AutoREACTER.py +++ b/examples/legacy/run_AutoREACTER.py @@ -1,215 +1,215 @@ -import sys -import os -import time -from PIL import Image - -# from AutoREACTER._compat import apply_legacy_patches -# apply_legacy_patches() -# this will be need when foyer integration is added back in, but for now it causes issues with the current foyer version. -# We can re-add it when we add foyer back in, and it should be compatible with the current version of foyer at that time. - -from AutoREACTER.session import read_input -from AutoREACTER.input_parser import InputParser -from AutoREACTER.detectors.functional_groups_detector import FunctionalGroupsDetector -from AutoREACTER.detectors.reaction_detector import ReactionDetector -from AutoREACTER.detectors.non_monomer_detector import NonReactantsDetector -from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions -from AutoREACTER.reaction_preparation.ff_wrapper.molecule_3d_preparation import Molecule3DPreparation -from AutoREACTER.reaction_preparation.ff_wrapper.ff_wrapper import FFWrapper -from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import REACTERFilesBuilder -from AutoREACTER.sim_setup.simulation_setup import SimulationSetupManager - - -def loading_message(message: str, duration: float = 3.0, interval: float = 0.5) -> None: - """ - Print a loading message with animated dots to indicate progress. - - Args: - message: The message to display - duration: Total duration of the animation in seconds - interval: Time between each dot in seconds - """ - print(f"[INFO] {message}", end="", flush=True) - steps = int(duration / interval) - - for _ in range(steps): - print(".", end="", flush=True) - time.sleep(interval) - - print() # newline - - -def save_image(img: Image.Image, path: str, label: str = "Image") -> None: - """ - Save a PIL Image to disk with robust error handling and user feedback. - - Args: - img: PIL Image object to save - path: Full path where the image should be saved - label: Human-readable label used in log messages - """ - if img is None: - print(f"[WARN] {label}: Image is None, skipping save.") - return - try: - if hasattr(img, "save"): - img.save(path) - print(f"\n[OK] {label} saved → {path}") - else: - print(f"[ERROR] {label}: Object has no .save() method") - except Exception as e: - print(f"[ERROR] Failed to save {label} to {path}: {e}") - -def help_message() -> None: - """ - Print usage instructions for the AutoREACTER script. - This function is called when the user runs the script without arguments or with incorrect options. - """ - print("Usage:") - print(" python AutoREACTER.py -i ") - print("\nOptions:") - print(" -i, --input Path to input JSON file") - -def AutoREACTER(input_file: str) -> None: - """ - Main function to run the AutoREACTER workflow. - This function orchestrates the entire process from reading inputs, detecting reactions, preparing files, and setting up the simulation. - Args: - input_file: Path to the input JSON file containing simulation parameters and monomer information. - - Workflow Steps: - 1. Initialize Session: Read and validate inputs, set up staging and output directories. - 2. Functional Group Detection: Identify functional groups in the monomers and generate visualizations - 3. Reaction Discovery and Selection: Detect possible reactions based on functional groups and allow user selection. - 4. Non-monomer (Additive) Detection: Identify any non-reactant additives and allow user selection. - 5. Reaction Template Preparation: Prepare reaction templates and generate visualizations for review. - 6. 3D Geometry Preparation: Generate 3D geometries for molecules and reactions. - 7. Lunar API Processing: Send data to the Lunar API and retrieve results. - 8. Build REACTER Input Files: Create the necessary input files for REACTER based on the processed data. - 9. Final Simulation Setup and Output: Organize all outputs into the final directory structure and provide user feedback. - """ - # === 1. Initialize Session === - session = read_input(input_file) - - # Generate initial visualization - try: - input_parser = InputParser() - img = input_parser.initial_molecules_image_grid(session) - # monomers = session.inputs.monomers # debug print to verify monomers are being processed - # print(monomers) - save_image(img, os.path.join(session.images_dir, "monomers.png"), "Monomers Grid") - except Exception: - print("[WARN] Failed to generate initial molecules image grid") - - # === 2. Functional Group Detection === - functional_groups_detector = FunctionalGroupsDetector() - functional_groups_detector.functional_groups_detector(session) - try: - img = functional_groups_detector.functional_group_highlighted_molecules_image_grid(session) - save_image(img, os.path.join(session.images_dir, "functional_groups.png"), "Functional Groups") - except Exception: - pass - - # === 3. Reaction Discovery and Selection === - reaction_detector = ReactionDetector() - reaction_detector.reaction_detector(session) - try: - img = reaction_detector.available_reaction_image_grid(session) - save_image(img, os.path.join(session.images_dir, "reactions.png"), "Available Reactions") - except Exception: - pass - - reaction_detector.reaction_selection(session) - - # === 4. Non-monomer (Additive) Detection === - non_monomer_detector = NonReactantsDetector() - non_monomer_detector.non_monomer_detector(session) - try: - img_non_reactants = non_monomer_detector.non_reactants_to_visualization(session) - save_image(img_non_reactants, os.path.join(session.images_dir, "non_reactants.png"), "Non-Reactants") - except Exception: - pass - - non_monomer_detector.non_reactant_selection(session) - - # === 5. Reaction Template Preparation === - prepare_reactions = PrepareReactions(session) - prepare_reactions.prepare_reactions(session) - - try: - for highlight_type, filename in [ - ("template", "templates_all.png"), - ("edge", "templates_edge.png"), - ("initiators", "templates_initiators.png"), - ("delete", "templates_delete.png") - ]: - img = prepare_reactions.reaction_templates_highlighted_image_grid( - session, highlight_type=highlight_type - ) - save_image(img, os.path.join(session.images_dir, filename)) - except Exception: - print("[WARN] Failed to generate one or more reaction template visualizations") - - print( - f"\n[INFO] Reaction preparation completed.\n" - f"All generated images have been saved in the {session.images_dir} directory.\n" - f"Please review the reaction templates before proceeding.\n" - ) - - # Interactive user confirmation - ok_pass = input("Type 'ok' to continue: ").strip().lower() - if ok_pass != "ok": - print("[EXIT] Workflow stopped by user.") - sys.exit(0) - - # === 6. 3D Geometry Preparation === - molecule3dpreparation = Molecule3DPreparation(session) - updated_inputs_with_3d_mols = molecule3dpreparation.prepare_molecule_3d_geometry(session) - - # === 7. Lunar API Processing === - ff_wrapper = FFWrapper(session) - ff_wrapper.generate_force_field_files(session) - - print("\n") - loading_message("Lunar API workflow completed. Proceeding to build REACTER files") - time.sleep(1.5) - print("\n") - - # === 8. Build REACTER Input Files === - builder = REACTERFilesBuilder(session=session) - builder.molecule_template_preparation(session=session) - - print(f"[OK] REACTER files successfully moved to {session.output_dir}") - - # === 9. Final simulation setup and output === - Simulation_setup_manager = SimulationSetupManager() - Simulation_setup_manager.setup_and_write_simulation( - session=session - ) - - print("\n[INFO] AutoREACTER workflow completed successfully.\n") - print(f"Final REACTER and LAMMPS files are located in: {session.output_dir}") - - -if __name__ == "__main__": - args = sys.argv[1:] - inpput_strs = ["-i", "--input", "-in"] - - if not args: - help_message() - sys.exit(1) - - if any(opt in args for opt in inpput_strs): - idx = next(idx for idx, arg in enumerate(args) if arg in inpput_strs) - if idx + 1 >= len(args): - print("Error: Missing input file.") - sys.exit(1) - - input_file = args[idx + 1] - if not os.path.isfile(input_file): - print(f"Error: Input file '{input_file}' does not exist.") - sys.exit(1) - - AutoREACTER(input_file) - else: +import sys +import os +import time +from PIL import Image + +# from AutoREACTER._compat import apply_legacy_patches +# apply_legacy_patches() +# this will be need when foyer integration is added back in, but for now it causes issues with the current foyer version. +# We can re-add it when we add foyer back in, and it should be compatible with the current version of foyer at that time. + +from AutoREACTER.session import read_input +from AutoREACTER.input_parser import InputParser +from AutoREACTER.detectors.functional_groups_detector import FunctionalGroupsDetector +from AutoREACTER.detectors.reaction_detector import ReactionDetector +from AutoREACTER.detectors.non_monomer_detector import NonReactantsDetector +from AutoREACTER.reaction_preparation.reaction_processor.prepare_reactions import PrepareReactions +from AutoREACTER.reaction_preparation.ff_wrapper.molecule_3d_preparation import Molecule3DPreparation +from AutoREACTER.reaction_preparation.ff_wrapper.ff_wrapper import FFWrapper +from AutoREACTER.reaction_preparation.ff_wrapper.REACTER_files_builder import REACTERFilesBuilder +from AutoREACTER.sim_setup.simulation_setup import SimulationSetupManager + + +def loading_message(message: str, duration: float = 3.0, interval: float = 0.5) -> None: + """ + Print a loading message with animated dots to indicate progress. + + Args: + message: The message to display + duration: Total duration of the animation in seconds + interval: Time between each dot in seconds + """ + print(f"[INFO] {message}", end="", flush=True) + steps = int(duration / interval) + + for _ in range(steps): + print(".", end="", flush=True) + time.sleep(interval) + + print() # newline + + +def save_image(img: Image.Image, path: str, label: str = "Image") -> None: + """ + Save a PIL Image to disk with robust error handling and user feedback. + + Args: + img: PIL Image object to save + path: Full path where the image should be saved + label: Human-readable label used in log messages + """ + if img is None: + print(f"[WARN] {label}: Image is None, skipping save.") + return + try: + if hasattr(img, "save"): + img.save(path) + print(f"\n[OK] {label} saved → {path}") + else: + print(f"[ERROR] {label}: Object has no .save() method") + except Exception as e: + print(f"[ERROR] Failed to save {label} to {path}: {e}") + +def help_message() -> None: + """ + Print usage instructions for the AutoREACTER script. + This function is called when the user runs the script without arguments or with incorrect options. + """ + print("Usage:") + print(" python AutoREACTER.py -i ") + print("\nOptions:") + print(" -i, --input Path to input JSON file") + +def AutoREACTER(input_file: str) -> None: + """ + Main function to run the AutoREACTER workflow. + This function orchestrates the entire process from reading inputs, detecting reactions, preparing files, and setting up the simulation. + Args: + input_file: Path to the input JSON file containing simulation parameters and monomer information. + + Workflow Steps: + 1. Initialize Session: Read and validate inputs, set up staging and output directories. + 2. Functional Group Detection: Identify functional groups in the monomers and generate visualizations + 3. Reaction Discovery and Selection: Detect possible reactions based on functional groups and allow user selection. + 4. Non-monomer (Additive) Detection: Identify any non-reactant additives and allow user selection. + 5. Reaction Template Preparation: Prepare reaction templates and generate visualizations for review. + 6. 3D Geometry Preparation: Generate 3D geometries for molecules and reactions. + 7. Lunar API Processing: Send data to the Lunar API and retrieve results. + 8. Build REACTER Input Files: Create the necessary input files for REACTER based on the processed data. + 9. Final Simulation Setup and Output: Organize all outputs into the final directory structure and provide user feedback. + """ + # === 1. Initialize Session === + session = read_input(input_file) + + # Generate initial visualization + try: + input_parser = InputParser() + img = input_parser.initial_molecules_image_grid(session) + # monomers = session.inputs.monomers # debug print to verify monomers are being processed + # print(monomers) + save_image(img, os.path.join(session.images_dir, "monomers.png"), "Monomers Grid") + except Exception: + print("[WARN] Failed to generate initial molecules image grid") + + # === 2. Functional Group Detection === + functional_groups_detector = FunctionalGroupsDetector() + functional_groups_detector.functional_groups_detector(session) + try: + img = functional_groups_detector.functional_group_highlighted_molecules_image_grid(session) + save_image(img, os.path.join(session.images_dir, "functional_groups.png"), "Functional Groups") + except Exception: + pass + + # === 3. Reaction Discovery and Selection === + reaction_detector = ReactionDetector() + reaction_detector.reaction_detector(session) + try: + img = reaction_detector.available_reaction_image_grid(session) + save_image(img, os.path.join(session.images_dir, "reactions.png"), "Available Reactions") + except Exception: + pass + + reaction_detector.reaction_selection(session) + + # === 4. Non-monomer (Additive) Detection === + non_monomer_detector = NonReactantsDetector() + non_monomer_detector.non_monomer_detector(session) + try: + img_non_reactants = non_monomer_detector.non_reactants_to_visualization(session) + save_image(img_non_reactants, os.path.join(session.images_dir, "non_reactants.png"), "Non-Reactants") + except Exception: + pass + + non_monomer_detector.non_reactant_selection(session) + + # === 5. Reaction Template Preparation === + prepare_reactions = PrepareReactions(session) + prepare_reactions.prepare_reactions(session) + + try: + for highlight_type, filename in [ + ("template", "templates_all.png"), + ("edge", "templates_edge.png"), + ("initiators", "templates_initiators.png"), + ("delete", "templates_delete.png") + ]: + img = prepare_reactions.reaction_templates_highlighted_image_grid( + session, highlight_type=highlight_type + ) + save_image(img, os.path.join(session.images_dir, filename)) + except Exception: + print("[WARN] Failed to generate one or more reaction template visualizations") + + print( + f"\n[INFO] Reaction preparation completed.\n" + f"All generated images have been saved in the {session.images_dir} directory.\n" + f"Please review the reaction templates before proceeding.\n" + ) + + # Interactive user confirmation + ok_pass = input("Type 'ok' to continue: ").strip().lower() + if ok_pass != "ok": + print("[EXIT] Workflow stopped by user.") + sys.exit(0) + + # === 6. 3D Geometry Preparation === + molecule3dpreparation = Molecule3DPreparation(session) + updated_inputs_with_3d_mols = molecule3dpreparation.prepare_molecule_3d_geometry(session) + + # === 7. Lunar API Processing === + ff_wrapper = FFWrapper(session) + ff_wrapper.generate_force_field_files(session) + + print("\n") + loading_message("Lunar API workflow completed. Proceeding to build REACTER files") + time.sleep(1.5) + print("\n") + + # === 8. Build REACTER Input Files === + builder = REACTERFilesBuilder(session=session) + builder.molecule_template_preparation(session=session) + + print(f"[OK] REACTER files successfully moved to {session.output_dir}") + + # === 9. Final simulation setup and output === + Simulation_setup_manager = SimulationSetupManager() + Simulation_setup_manager.setup_and_write_simulation( + session=session + ) + + print("\n[INFO] AutoREACTER workflow completed successfully.\n") + print(f"Final REACTER and LAMMPS files are located in: {session.output_dir}") + + +if __name__ == "__main__": + args = sys.argv[1:] + inpput_strs = ["-i", "--input", "-in"] + + if not args: + help_message() + sys.exit(1) + + if any(opt in args for opt in inpput_strs): + idx = next(idx for idx, arg in enumerate(args) if arg in inpput_strs) + if idx + 1 >= len(args): + print("Error: Missing input file.") + sys.exit(1) + + input_file = args[idx + 1] + if not os.path.isfile(input_file): + print(f"Error: Input file '{input_file}' does not exist.") + sys.exit(1) + + AutoREACTER(input_file) + else: help_message() \ No newline at end of file diff --git a/examples/DGEBA_MMA_IPN.json b/examples/legacy_examples/DGEBA_MMA_IPN.json similarity index 95% rename from examples/DGEBA_MMA_IPN.json rename to examples/legacy_examples/DGEBA_MMA_IPN.json index 6379ff0b..905f8e08 100644 --- a/examples/DGEBA_MMA_IPN.json +++ b/examples/legacy_examples/DGEBA_MMA_IPN.json @@ -1,36 +1,36 @@ -{ - "simulation_name": "DGEBA_MMA_ED900_TEGDMA_IPN_500K_100k", - "force_field": "PCFF", - "simulations": [ - { - "tag": "ipn_100k_500K", - "temperature": 500.0, - "density": 1.23, - "total_atoms": 100000, - "monomer_ratios": { - "dgeba": 2.0, - "jeffamine_ed900_rep": 1.0, - "mma": 14.0, - "tegdma": 0.7 - } - } - ], - "monomers": [ - { - "name": "dgeba", - "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c3ccc(OCC4CO4)cc3" - }, - { - "name": "jeffamine_ed900_rep", - "smiles": "CC(N)COCC(C)OCC(C)OCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCC(C)OCC(C)OCC(C)N" - }, - { - "name": "mma", - "smiles": "COC(=O)C(C)=C" - }, - { - "name": "tegdma", - "smiles": "CC(=C)C(=O)OCCOCCOCCOC(=O)C(=C)C" - } - ] +{ + "simulation_name": "DGEBA_MMA_ED900_TEGDMA_IPN_500K_100k", + "force_field": "PCFF", + "simulations": [ + { + "tag": "ipn_100k_500K", + "temperature": 500.0, + "density": 1.23, + "total_atoms": 100000, + "monomer_ratios": { + "dgeba": 2.0, + "jeffamine_ed900_rep": 1.0, + "mma": 14.0, + "tegdma": 0.7 + } + } + ], + "monomers": [ + { + "name": "dgeba", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c3ccc(OCC4CO4)cc3" + }, + { + "name": "jeffamine_ed900_rep", + "smiles": "CC(N)COCC(C)OCC(C)OCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCCOCC(C)OCC(C)OCC(C)N" + }, + { + "name": "mma", + "smiles": "COC(=O)C(C)=C" + }, + { + "name": "tegdma", + "smiles": "CC(=C)C(=O)OCCOCCOCCOC(=O)C(=C)C" + } + ] } \ No newline at end of file diff --git a/examples/example_1_inputs_count_mode_FF.json b/examples/legacy_examples/example_1_inputs_count_mode_FF.json similarity index 95% rename from examples/example_1_inputs_count_mode_FF.json rename to examples/legacy_examples/example_1_inputs_count_mode_FF.json index b97f5f09..90aab49b 100644 --- a/examples/example_1_inputs_count_mode_FF.json +++ b/examples/legacy_examples/example_1_inputs_count_mode_FF.json @@ -1,40 +1,40 @@ -{ - "simulation_name": "Example_Count_Mode", - "force_field": "PCFF", - "simulations": [ - { - "tag": "10k", - "temperature": 300, - "density": 0.8, - "monomer_counts": { - "tmc": 220, - "mpd": 220, - "ethanol": 110 - } - }, - { - "tag": "100k", - "temperature": 400, - "density": 0.8, - "monomer_counts": { - "tmc": 2200, - "mpd": 2200, - "ethanol": 1100 - } - } - ], - "monomers": [ - { - "name": "tmc", - "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" - }, - { - "name": "mpd", - "smiles": "C1=CC(=CC(=C1)N)N" - }, - { - "name": "ethanol", - "smiles": "CCO" - } - ] +{ + "simulation_name": "Example_Count_Mode", + "force_field": "PCFF", + "simulations": [ + { + "tag": "10k", + "temperature": 300, + "density": 0.8, + "monomer_counts": { + "tmc": 220, + "mpd": 220, + "ethanol": 110 + } + }, + { + "tag": "100k", + "temperature": 400, + "density": 0.8, + "monomer_counts": { + "tmc": 2200, + "mpd": 2200, + "ethanol": 1100 + } + } + ], + "monomers": [ + { + "name": "tmc", + "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" + }, + { + "name": "mpd", + "smiles": "C1=CC(=CC(=C1)N)N" + }, + { + "name": "ethanol", + "smiles": "CCO" + } + ] } \ No newline at end of file diff --git a/examples/test_epoxy.json b/examples/legacy_examples/test_epoxy.json similarity index 94% rename from examples/test_epoxy.json rename to examples/legacy_examples/test_epoxy.json index 325e221d..63dc9aac 100644 --- a/examples/test_epoxy.json +++ b/examples/legacy_examples/test_epoxy.json @@ -1,31 +1,31 @@ -{ - "simulation_name": "DGEBA_1,5-Diaminopentane_Epoxy_Curing_wo-loop", - - "reaction_iteration_depth": false, - - "simulations": [ - { - "tag": "DGEBA_1,5-diaminopentane", - - "temperature": 300, - - "density": 1.0, - - "monomer_counts": { - "bisphenol_A_diglycidyl_ether": 200, - "1,5_diaminopentane": 100 - } - } - ], - - "monomers": [ - { - "name": "bisphenol_A_diglycidyl_ether", - "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" - }, - { - "name": "1,5_diaminopentane", - "smiles": "NCCCCCN" - } - ] +{ + "simulation_name": "DGEBA_1,5-Diaminopentane_Epoxy_Curing_wo-loop", + + "reaction_iteration_depth": false, + + "simulations": [ + { + "tag": "DGEBA_1,5-diaminopentane", + + "temperature": 300, + + "density": 1.0, + + "monomer_counts": { + "bisphenol_A_diglycidyl_ether": 200, + "1,5_diaminopentane": 100 + } + } + ], + + "monomers": [ + { + "name": "bisphenol_A_diglycidyl_ether", + "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" + }, + { + "name": "1,5_diaminopentane", + "smiles": "NCCCCCN" + } + ] } \ No newline at end of file diff --git a/examples/test_styrene.json b/examples/legacy_examples/test_styrene.json similarity index 97% rename from examples/test_styrene.json rename to examples/legacy_examples/test_styrene.json index bf62433c..f26ac4c5 100644 --- a/examples/test_styrene.json +++ b/examples/legacy_examples/test_styrene.json @@ -1,93 +1,93 @@ -{ - "simulation_name": "Styrene2", - "force_field": "PCFF", - "wildcards": true, - "simulations": [ - { - "tag": "styrene_10k_298K", - "temperature": 298.15, - "density": 1.05, - "total_atoms": 10000, - "monomer_ratios": { - "styrene": 1.0 - }, - "comment": "Room-temperature reference system. The 10k system is intended for rapid testing, workflow validation, and establishing baseline structural and reaction behavior at ambient conditions." - }, - { - "tag": "styrene_100k_298K", - "temperature": 298.15, - "density": 1.05, - "total_atoms": 100000, - "monomer_ratios": { - "styrene": 1.0 - }, - "comment": "Large room-temperature reference system. It is used to evaluate finite-size effects and obtain more statistically representative structural and reaction data than the 10k system." - }, - { - "tag": "styrene_10k_373K", - "temperature": 373.15, - "density": 1.05, - "total_atoms": 10000, - "monomer_ratios": { - "styrene": 1.0 - }, - "comment": "Approximately 100 degrees Celsius. This small system probes accelerated polymerization behavior near a temperature where uncontrolled self-heating and runaway risks may become important, depending on initiators, inhibitors, and heat removal." - }, - { - "tag": "styrene_100k_373K", - "temperature": 373.15, - "density": 1.05, - "total_atoms": 100000, - "monomer_ratios": { - "styrene": 1.0 - }, - "comment": "Large system at approximately 100 degrees Celsius. It is included to examine system-size effects, heat-sensitive reaction behavior, and network development near the upper region of common styrene polymerization temperatures." - }, - { - "tag": "styrene_10k_523K", - "temperature": 523.15, - "density": 1.05, - "total_atoms": 10000, - "monomer_ratios": { - "styrene": 1.0 - }, - "comment": "Approximately 250 degrees Celsius. This system probes the transition toward strong thermal initiation, radical formation, oligomerization, and possible thermal degradation rather than normal controlled polystyrene production." - }, - { - "tag": "styrene_100k_523K", - "temperature": 523.15, - "density": 1.05, - "total_atoms": 100000, - "monomer_ratios": { - "styrene": 1.0 - }, - "comment": "Large system at approximately 250 degrees Celsius. It is intended to capture larger-scale thermal decomposition, branching, fragmentation, and spatially heterogeneous reaction behavior." - }, - { - "tag": "styrene_10k_800K", - "temperature": 800.0, - "density": 1.05, - "total_atoms": 10000, - "monomer_ratios": { - "styrene": 1.0 - }, - "comment": "High-temperature screening system at 800 K, equivalent to approximately 526.85 degrees Celsius. It probes extreme thermal chemistry and decomposition behavior and is not a conventional styrene polymerization condition." - }, - { - "tag": "styrene_100k_800K", - "temperature": 800.0, - "density": 1.05, - "total_atoms": 100000, - "monomer_ratios": { - "styrene": 1.0 - }, - "comment": "Large high-temperature system at 800 K. It is used to investigate finite-size effects and statistically significant reaction pathways under extreme thermal conditions." - } - ], - "monomers": [ - { - "name": "styrene", - "smiles": "C=Cc1ccccc1" - } - ] +{ + "simulation_name": "Styrene2", + "force_field": "PCFF", + "wildcards": true, + "simulations": [ + { + "tag": "styrene_10k_298K", + "temperature": 298.15, + "density": 1.05, + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Room-temperature reference system. The 10k system is intended for rapid testing, workflow validation, and establishing baseline structural and reaction behavior at ambient conditions." + }, + { + "tag": "styrene_100k_298K", + "temperature": 298.15, + "density": 1.05, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Large room-temperature reference system. It is used to evaluate finite-size effects and obtain more statistically representative structural and reaction data than the 10k system." + }, + { + "tag": "styrene_10k_373K", + "temperature": 373.15, + "density": 1.05, + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Approximately 100 degrees Celsius. This small system probes accelerated polymerization behavior near a temperature where uncontrolled self-heating and runaway risks may become important, depending on initiators, inhibitors, and heat removal." + }, + { + "tag": "styrene_100k_373K", + "temperature": 373.15, + "density": 1.05, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Large system at approximately 100 degrees Celsius. It is included to examine system-size effects, heat-sensitive reaction behavior, and network development near the upper region of common styrene polymerization temperatures." + }, + { + "tag": "styrene_10k_523K", + "temperature": 523.15, + "density": 1.05, + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Approximately 250 degrees Celsius. This system probes the transition toward strong thermal initiation, radical formation, oligomerization, and possible thermal degradation rather than normal controlled polystyrene production." + }, + { + "tag": "styrene_100k_523K", + "temperature": 523.15, + "density": 1.05, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Large system at approximately 250 degrees Celsius. It is intended to capture larger-scale thermal decomposition, branching, fragmentation, and spatially heterogeneous reaction behavior." + }, + { + "tag": "styrene_10k_800K", + "temperature": 800.0, + "density": 1.05, + "total_atoms": 10000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "High-temperature screening system at 800 K, equivalent to approximately 526.85 degrees Celsius. It probes extreme thermal chemistry and decomposition behavior and is not a conventional styrene polymerization condition." + }, + { + "tag": "styrene_100k_800K", + "temperature": 800.0, + "density": 1.05, + "total_atoms": 100000, + "monomer_ratios": { + "styrene": 1.0 + }, + "comment": "Large high-temperature system at 800 K. It is used to investigate finite-size effects and statistically significant reaction pathways under extreme thermal conditions." + } + ], + "monomers": [ + { + "name": "styrene", + "smiles": "C=Cc1ccccc1" + } + ] } \ No newline at end of file diff --git a/examples/TMC_MPD.json b/examples/polyamide_count_mode_advanced_options.json similarity index 65% rename from examples/TMC_MPD.json rename to examples/polyamide_count_mode_advanced_options.json index c2631e9b..68239d97 100644 --- a/examples/TMC_MPD.json +++ b/examples/polyamide_count_mode_advanced_options.json @@ -1,12 +1,12 @@ { - "simulation_name": "Trimesoyl_Chloride_m_Phenylenediamine", + "simulation_name": "Polyamide_Count_Mode_Advanced", "force_field": "PCFF", "deep_search": true, "reaction_iteration_depth": 5, "wildcards": true, "deduplicate_reaction_templates": true, - "write_second_reaction_stage": true, + "write_second_reaction_stage": false, "simulations": [ { @@ -14,17 +14,17 @@ "temperature": 300, "density": 0.8, "monomer_counts": { - "trimesoyl_chloride": 238, - "m_phenylenediamine": 357 + "trimesoyl_chloride": 220, + "m_phenylenediamine": 330 } }, { - "tag": "100k_300K", - "temperature": 300, + "tag": "100k_400K", + "temperature": 400, "density": 0.8, "monomer_counts": { - "trimesoyl_chloride": 2380, - "m_phenylenediamine": 3570 + "trimesoyl_chloride": 2200, + "m_phenylenediamine": 3300 } } ], diff --git a/examples/polyamide_count_mode_basic.json b/examples/polyamide_count_mode_basic.json new file mode 100644 index 00000000..9413a121 --- /dev/null +++ b/examples/polyamide_count_mode_basic.json @@ -0,0 +1,36 @@ +{ + "simulation_name": "Polyamide_Count_Mode_Basic", + "force_field": "PCFF", + + "simulations": [ + { + "tag": "10k_300K", + "temperature": 300, + "density": 0.8, + "monomer_counts": { + "trimesoyl_chloride": 220, + "m_phenylenediamine": 330 + } + }, + { + "tag": "100k_400K", + "temperature": 400, + "density": 0.8, + "monomer_counts": { + "trimesoyl_chloride": 2200, + "m_phenylenediamine": 3300 + } + } + ], + + "monomers": [ + { + "name": "trimesoyl_chloride", + "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" + }, + { + "name": "m_phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + } + ] +} diff --git a/examples/polyamide_ratio_mode_basic.json b/examples/polyamide_ratio_mode_basic.json new file mode 100644 index 00000000..215ab807 --- /dev/null +++ b/examples/polyamide_ratio_mode_basic.json @@ -0,0 +1,38 @@ +{ + "simulation_name": "Polyamide_Ratio_Mode_Basic", + "force_field": "PCFF", + + "simulations": [ + { + "tag": "10k_300K", + "temperature": 300, + "density": 0.8, + "total_atoms": 10000, + "monomer_ratios": { + "trimesoyl_chloride": 2.0, + "m_phenylenediamine": 3.0 + } + }, + { + "tag": "100k_400K", + "temperature": 400, + "density": 0.8, + "total_atoms": 100000, + "monomer_ratios": { + "trimesoyl_chloride": 2.0, + "m_phenylenediamine": 3.0 + } + } + ], + + "monomers": [ + { + "name": "trimesoyl_chloride", + "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" + }, + { + "name": "m_phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + } + ] +} diff --git a/examples/styrene_wildcards.json b/examples/styrene_wildcards.json new file mode 100644 index 00000000..c30cbf17 --- /dev/null +++ b/examples/styrene_wildcards.json @@ -0,0 +1,28 @@ +{ + "simulation_name": "Styrene_Wildcards", + "force_field": "PCFF", + + "deep_search": true, + "reaction_iteration_depth": 5, + "wildcards": true, + "deduplicate_reaction_templates": true, + "write_second_reaction_stage": false, + + "simulations": [ + { + "tag": "10k_298K", + "temperature": 298, + "density": 0.95, + "monomer_counts": { + "styrene": 1000 + } + } + ], + + "monomers": [ + { + "name": "styrene", + "smiles": "C=CC1=CC=CC=C1" + } + ] +} diff --git a/examples/test.json b/examples/test.json deleted file mode 100644 index f87de57e..00000000 --- a/examples/test.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", - "simulations": [ - { - "tag": "epoxy_test", - "temperature": 300, - "density": 0.5, - "total_atoms": 25000, - "monomer_ratios": { - "dgeba_epoxy": 2.0, - "DDS_diamine": 1.0 - } - } - ], - "monomers": [ - { - "name": "dgeba_epoxy", - "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" - }, - { - "name": "DDS_diamine", - "smiles": "Nc1ccc(S(=O)(=O)c2ccc(N)cc2)cc1" - } - ] -} \ No newline at end of file diff --git a/examples/test_epoxy_dgeba_dds.json b/examples/test_epoxy_dgeba_dds.json deleted file mode 100644 index 240163f3..00000000 --- a/examples/test_epoxy_dgeba_dds.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "simulation_name": "Epoxy_Test_Primary_Diamine_Diepoxy", - "simulations": [ - { - "tag": "epoxy_test", - "temperature": 300, - "density": 0.5, - "total_atoms": 25000, - "monomer_ratios": { - "dgeba_epoxy": 2.0, - "DDS_diamine": 1.0 - } - } - ], - "monomers": [ - { - "name": "dgeba_epoxy", - "smiles": "CC(C)(c1ccc(OCC2CO2)cc1)c1ccc(OCC2CO2)cc1" - }, - { - "name": "DDS_diamine", - "smiles": "[S](=O)(=O)(c2ccc(cc2)N)c1ccc(cc1)N" - } - ] -} diff --git a/examples/test_ethelene.json b/examples/test_ethelene.json deleted file mode 100644 index 34eacca0..00000000 --- a/examples/test_ethelene.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "simulation_name": "Ethene_Test", - "force_field": "PCFF", - "deep_search": true, - "reaction_iteration_depth": 5, - "wildcards": true, - "deduplicate_reaction_templates": true, - "write_second_reaction_stage": true, - "simulations": [ - { - "tag": "10k_300K", - "temperature": 300, - "density": 0.8, - "monomer_counts": { - "ethene": 5000 - } - } - ], - "monomers": [ - { - "name": "ethene", - "smiles": "C=C" - } - ] -} diff --git a/examples/test_glycine.json b/examples/test_glycine.json deleted file mode 100644 index cb53b3af..00000000 --- a/examples/test_glycine.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "simulation_name": "Glycine_Test", - "simulations": [ - { - "tag": "glycine_test", - "temperature": 300, - "density": 1.0, - "monomer_counts": { - "glycine": 200 - } - } - ], - "monomers": [ - { - "name": "glycine", - "smiles": "NCC(=O)O" - } - ] -} \ No newline at end of file From d96063f5aedc2b20eca452c39bd57dd6dc25e777 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 19 Aug 2026 19:33:12 -0400 Subject: [PATCH 154/176] Refresh API docs and example notebook flow --- docs/source/api_reference.md | 64 +++-- examples/example_1.ipynb | 506 +++++++++++++++++------------------ 2 files changed, 291 insertions(+), 279 deletions(-) diff --git a/docs/source/api_reference.md b/docs/source/api_reference.md index 0552b4c5..05531331 100644 --- a/docs/source/api_reference.md +++ b/docs/source/api_reference.md @@ -20,7 +20,7 @@ Users can import AutoREACTER as `arx` so the code is shorter and the long module ## Required Functions in Order -**Important**: Users must run these functions in the following order. +Important: Users must run these functions in the following order. ### 1. Run AutoREACTER @@ -63,6 +63,7 @@ Optional function available after `arx.select_reactions()`: ```python arx.show_non_reactants() ``` + --- ### 3. Select Non-Reactants @@ -80,7 +81,7 @@ A molecule can be treated as a non-reactant if: * The molecule does not qualify as a monomer. * The molecule qualifies as a monomer, but the user chooses not to include it in any selected reaction. - +--- ### 4. Prepare Reactions @@ -92,12 +93,12 @@ This function prepares reaction templates from the selected reactions for downst This function marks the reaction-template preparation stage as complete. -After this function, users can optionally visualize reaction templates. +After this function, users can optionally visualize reaction templates before final processing. Optional function available after `arx.prepare_reactions()`: ```python -arx.show_reaction_templates() +arx.show_reaction_templates("template") ``` --- @@ -108,9 +109,9 @@ arx.show_reaction_templates() arx.process() ``` -This function executes the back-half of the AutoREACTER pipeline in one shot. +This function executes the final AutoREACTER processing steps after reaction templates have been prepared. -According to the docstring, this method runs reaction template preparation, 3D geometry setup, force-field generation through the LUNAR API, REACTER file building, and LAMMPS simulation writing. +It performs 3D geometry setup, force-field generation through the LUNAR API, REACTER file building, and LAMMPS simulation writing. This function should be run only after the required stages are completed: @@ -137,6 +138,9 @@ arx.select_non_reactants() arx.prepare_reactions() +# Optional review step before final processing +arx.show_reaction_templates("template") + arx.process() ``` @@ -264,20 +268,26 @@ Usage: arx.show_reaction_templates() ``` -This function returns an image grid visualizing the reaction templates. +This function returns an image grid visualizing the generated reaction templates. + +By default, AutoREACTER shows the full reaction template: -The `highlight_type` parameter can be used to visualize different parts of the reaction templates. Default type is `"template"` +```python +arx.show_reaction_templates() +``` + +Users can also pass a template-highlight mode as a positional argument: ```python -arx.show_reaction_templates(highlight_type="template") -arx.show_reaction_templates(highlight_type="edge") -arx.show_reaction_templates(highlight_type="delete") -arx.show_reaction_templates(highlight_type="initiators") +arx.show_reaction_templates("template") +arx.show_reaction_templates("edge") +arx.show_reaction_templates("delete") +arx.show_reaction_templates("initiators") ``` #### Reaction Template Visualization Options -Visualize reaction templates with different highlighting options by setting the `highlight_type` parameter to one of the following values: +Visualize reaction templates with different highlighting options by passing one of the following values: * `template`: Highlights all structural changes in the reaction templates. * `edge`: Highlights edge atoms of the templates. @@ -287,7 +297,7 @@ Visualize reaction templates with different highlighting options by setting the The default value is: ```python -highlight_type="template" +"template" ``` Returns: @@ -296,18 +306,20 @@ Returns: Image ``` +--- ## Summary of Public APIs -| API | Required or Optional | When to Run | -| ------------------------------- | -------------------: | ---------------------------------- | -| `arx.run("input.json")` | Required | First | -| `arx.select_reactions()` | Required | After `arx.run(...)` | -| `arx.select_non_reactants()` | Required | After `arx.select_reactions()` | -| `arx.prepare_reactions()` | Required | After `arx.select_non_reactants()` | -| `arx.process()` | Required | Final required step | -| `arx.show_molecules()` | Optional | After `arx.run(...)` | -| `arx.show_functional_groups()` | Optional | After `arx.run(...)` | -| `arx.show_reactions()` | Optional | After `arx.run(...)` | -| `arx.show_non_reactants()` | Optional | After `arx.select_reactions()` | -| `arx.show_reaction_templates()` | Optional | After `arx.prepare_reactions()` | +| API | Required or Optional | When to Run | +| ------------------------------- | -------------------: | ------------------------------------------------ | +| `arx.run("input.json")` | Required | First | +| `arx.select_reactions()` | Required | After `arx.run(...)` | +| `arx.select_non_reactants()` | Required | After `arx.select_reactions()` | +| `arx.prepare_reactions()` | Required | After `arx.select_non_reactants()` | +| `arx.process()` | Required | Final required step | +| `arx.show_molecules()` | Optional | After `arx.run(...)` | +| `arx.show_functional_groups()` | Optional | After `arx.run(...)` | +| `arx.show_reactions()` | Optional | After `arx.run(...)` | +| `arx.show_non_reactants()` | Optional | After `arx.select_reactions()` | +| `arx.show_reaction_templates()` | Optional | After `arx.prepare_reactions()`, before `process()` | + diff --git a/examples/example_1.ipynb b/examples/example_1.ipynb index 21896011..9807a74b 100644 --- a/examples/example_1.ipynb +++ b/examples/example_1.ipynb @@ -1,253 +1,253 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9bf80177", - "metadata": {}, - "source": [ - "### Import AutoREACTER\n", - "\n", - "Import AutoREACTER as `arx` and check whether the package is available in the current environment." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b09e129b", - "metadata": {}, - "outputs": [], - "source": [ - "try:\n", - " import AutoREACTER as arx \n", - " print(\"AutoREACTER imported successfully.\")\n", - "except ImportError:\n", - " print(\"Failed to import AutoREACTER.\")" - ] - }, - { - "cell_type": "markdown", - "id": "b05e6b71", - "metadata": {}, - "source": [ - "### Load Input File\n", - "\n", - "Print the installed AutoREACTER version and load the input JSON file for the current simulation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2b47cb12", - "metadata": {}, - "outputs": [], - "source": [ - "print(arx.__version__)\n", - "arx.run(\"example_1_inputs_count_mode.json\")" - ] - }, - { - "cell_type": "markdown", - "id": "741ae24d", - "metadata": {}, - "source": [ - "### Show Molecules (Optional)\n", - "\n", - "Visualize the starting molecules detected from the input file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "74453196", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_molecules()" - ] - }, - { - "cell_type": "markdown", - "id": "03308558", - "metadata": {}, - "source": [ - "### Show Functional Groups (Optional)\n", - "\n", - "Visualize the functional groups detected on each molecule.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "230aab0c", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_functional_groups()" - ] - }, - { - "cell_type": "markdown", - "id": "cc3e4d93", - "metadata": {}, - "source": [ - "### Show Reactions (Optional)\n", - "\n", - "Visualize the reactions detected from the available functional groups.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fa3879a2", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_reactions()" - ] - }, - { - "cell_type": "markdown", - "id": "58b083b4", - "metadata": {}, - "source": [ - "\n", - "### Select Reactions\n", - "\n", - "Select which detected reactions should be used in the AutoREACTER workflow." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "94738f8e", - "metadata": {}, - "outputs": [], - "source": [ - "arx.select_reactions()" - ] - }, - { - "cell_type": "markdown", - "id": "24d2a9b4", - "metadata": {}, - "source": [ - "### Show non-reactant molecules (Optional)\n", - "\n", - "Visualize the non-reactant molecules that were detected from the input file. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "26efd1f1", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_non_reactants()" - ] - }, - { - "cell_type": "markdown", - "id": "a980ff60", - "metadata": {}, - "source": [ - "\n", - "### Select Non-Reactants\n", - "\n", - "Select non-reactant molecules, if any are detected in the system." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cd7be137", - "metadata": {}, - "outputs": [], - "source": [ - "arx.select_non_reactants()" - ] - }, - { - "cell_type": "markdown", - "id": "9311e742", - "metadata": {}, - "source": [ - "### Prepare Reactions\n", - "\n", - "Prepare the selected reaction templates for downstream processing." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "745635f3", - "metadata": {}, - "outputs": [], - "source": [ - "arx.prepare_reactions()" - ] - }, - { - "cell_type": "markdown", - "id": "90b5747e", - "metadata": {}, - "source": [ - "\n", - "### Show Reaction Templates\n", - "\n", - "Visualize the prepared reaction templates. Here, `\"template\"` highlights atoms or components removed during the reaction." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "94018071", - "metadata": {}, - "outputs": [], - "source": [ - "arx.show_reaction_templates(\"template\")" - ] - }, - { - "cell_type": "markdown", - "id": "459a32cd", - "metadata": {}, - "source": [ - "### Process System\n", - "\n", - "Run the final AutoREACTER processing step to generate the simulation-ready outputs." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ba05aaf", - "metadata": {}, - "outputs": [], - "source": [ - "arx.process()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.0" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9bf80177", + "metadata": {}, + "source": [ + "### Import AutoREACTER\n", + "\n", + "Import AutoREACTER as `arx` and check whether the package is available in the current environment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b09e129b", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " import AutoREACTER as arx \n", + " print(\"AutoREACTER imported successfully.\")\n", + "except ImportError:\n", + " print(\"Failed to import AutoREACTER.\")" + ] + }, + { + "cell_type": "markdown", + "id": "b05e6b71", + "metadata": {}, + "source": [ + "### Load Input File\n", + "\n", + "Print the installed AutoREACTER version and load the input JSON file for the current simulation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b47cb12", + "metadata": {}, + "outputs": [], + "source": [ + "print(arx.__version__)\n", + "arx.run(\"polyamide_count_mode_basic.json\")" + ] + }, + { + "cell_type": "markdown", + "id": "741ae24d", + "metadata": {}, + "source": [ + "### Show Molecules (Optional)\n", + "\n", + "Visualize the starting molecules detected from the input file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74453196", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_molecules()" + ] + }, + { + "cell_type": "markdown", + "id": "03308558", + "metadata": {}, + "source": [ + "### Show Functional Groups (Optional)\n", + "\n", + "Visualize the functional groups detected on each molecule.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "230aab0c", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_functional_groups()" + ] + }, + { + "cell_type": "markdown", + "id": "cc3e4d93", + "metadata": {}, + "source": [ + "### Show Reactions (Optional)\n", + "\n", + "Visualize the reactions detected from the available functional groups.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa3879a2", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_reactions()" + ] + }, + { + "cell_type": "markdown", + "id": "58b083b4", + "metadata": {}, + "source": [ + "\n", + "### Select Reactions\n", + "\n", + "Select which detected reactions should be used in the AutoREACTER workflow." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94738f8e", + "metadata": {}, + "outputs": [], + "source": [ + "arx.select_reactions()" + ] + }, + { + "cell_type": "markdown", + "id": "24d2a9b4", + "metadata": {}, + "source": [ + "### Show non-reactant molecules (Optional)\n", + "\n", + "Visualize the non-reactant molecules that were detected from the input file. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26efd1f1", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_non_reactants()" + ] + }, + { + "cell_type": "markdown", + "id": "a980ff60", + "metadata": {}, + "source": [ + "\n", + "### Select Non-Reactants\n", + "\n", + "Select non-reactant molecules, if any are detected in the system." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd7be137", + "metadata": {}, + "outputs": [], + "source": [ + "arx.select_non_reactants()" + ] + }, + { + "cell_type": "markdown", + "id": "9311e742", + "metadata": {}, + "source": [ + "### Prepare Reactions\n", + "\n", + "Prepare the selected reaction templates for downstream processing." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "745635f3", + "metadata": {}, + "outputs": [], + "source": [ + "arx.prepare_reactions()" + ] + }, + { + "cell_type": "markdown", + "id": "459a32cd", + "metadata": {}, + "source": [ + "### Process System\n", + "\n", + "Run the final AutoREACTER processing step to generate the simulation-ready outputs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ba05aaf", + "metadata": {}, + "outputs": [], + "source": [ + "arx.process()" + ] + }, + { + "cell_type": "markdown", + "id": "e7f60c10", + "metadata": {}, + "source": [ + "\n", + "### Show Reaction Templates\n", + "\n", + "Visualize the prepared reaction templates. Here, `\"template\"` highlights atoms or components removed during the reaction." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "277fd06f", + "metadata": {}, + "outputs": [], + "source": [ + "arx.show_reaction_templates(\"template\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From a249b2cc4d05415989c4fc7d8319bc8625221853 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 20 Aug 2026 09:47:58 -0400 Subject: [PATCH 155/176] Fix typo in README workflow description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 023f74a3..3791f92a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ AutoREACTER logo

-

Automated generation of LAMMPS/REACTER-ready reaction-template workflows.*

+

Automated generation of LAMMPS/REACTER-ready reaction-template workflows.

> **Status:** AutoREACTER is currently in **v0.2.3** and under active development. APIs, configuration schemas, reaction libraries, and core functionality may change without notice. > Please refer to the [changelog](https://autoreacter.org/change_log.html) for the latest updates. From cde3b26cc1b240333bfd90f0d0c9ff8336b8ff49 Mon Sep 17 00:00:00 2001 From: Janitha Mahanthe <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 20 Aug 2026 09:48:17 -0400 Subject: [PATCH 156/176] Update version number to v0.3 in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3791f92a..4871497a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

Automated generation of LAMMPS/REACTER-ready reaction-template workflows.

-> **Status:** AutoREACTER is currently in **v0.2.3** and under active development. APIs, configuration schemas, reaction libraries, and core functionality may change without notice. +> **Status:** AutoREACTER is currently in **v0.3** and under active development. APIs, configuration schemas, reaction libraries, and core functionality may change without notice. > Please refer to the [changelog](https://autoreacter.org/change_log.html) for the latest updates. ## Documentation From 3ff842077cafc5ac0b3fddf3f36528e12b3eebab Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 20 Aug 2026 14:47:39 -0400 Subject: [PATCH 157/176] Restructure documentation pages --- docs/{source => drafts}/Draft.md | 0 docs/source/advanced_options.md | 235 +----------------- docs/source/api_reference.md | 2 +- docs/source/contact.md | 4 +- docs/source/getting-started.md | 9 + .../getting_started_pip_installation.md | 10 +- .../getting_started_source_installation.md | 16 +- docs/source/index.rst | 21 +- docs/source/input-configuration.md | 14 +- docs/source/supported-force-fields.md | 4 +- docs/source/supported-reactions.md | 26 +- docs/source/template-deduplication.md | 174 +++++++++++++ 12 files changed, 248 insertions(+), 267 deletions(-) rename docs/{source => drafts}/Draft.md (100%) create mode 100644 docs/source/template-deduplication.md diff --git a/docs/source/Draft.md b/docs/drafts/Draft.md similarity index 100% rename from docs/source/Draft.md rename to docs/drafts/Draft.md diff --git a/docs/source/advanced_options.md b/docs/source/advanced_options.md index ff0632e8..8bae48c1 100644 --- a/docs/source/advanced_options.md +++ b/docs/source/advanced_options.md @@ -1,48 +1,8 @@ # Advanced Options -AutoREACTER gives users control over reaction generation through the input JSON file. These options allow users to tune how reaction products are iteratively searched, how reaction templates are compared, how duplicate templates are handled, how LAMMPS wildcard templates are generated, and whether one or two LAMMPS reaction stages are written. +AutoREACTER gives users control over advanced reaction-generation behavior through the input JSON file. These options are intended for users who want to control reaction-product iteration and LAMMPS wildcard template generation. -```json -{ - "simulation_name": "Polyamide_Deep_Search_Demo", - "force_field": "PCFF", - "deep_search": true, - "reaction_iteration_depth": false, - "wildcards": false, - "deduplicate_reaction_templates": true, - "write_second_reaction_stage": true, - - "simulations": [ - { - "tag": "100k_300K", - "temperature": 300, - "density": 0.8, - "monomer_counts": { - "4-methylheptanedioyl_dichloride": 2380, - "m-phenylenediamine": 3570, - "heptanedioyl_dichloride": 100 - } - } - ], - - "monomers": [ - { - "name": "4-methylheptanedioyl_dichloride", - "smiles": "CC(CCC(=O)Cl)CCC(=O)Cl" - }, - { - "name": "heptanedioyl_dichloride", - "smiles": "O=C(Cl)CCCCCC(=O)Cl" - }, - { - "name": "m-phenylenediamine", - "smiles": "C1=CC(=CC(=C1)N)N" - } - ] -} -``` - -The following advanced options are currently available: +The following advanced options are available for users: @@ -58,42 +18,24 @@ The following advanced options are currently available: - - - - - - - - - - - - - - -
5 Controls how many reaction-product iterations are attempted.
deep_searchtrueControls stricter RDKit/NetworkX template deduplication before atom typing.
deduplicate_reaction_templatestrueRemoves duplicate reaction templates before writing LAMMPS files.
wildcards true Uses LAMMPS wildcard maps to reduce edge-template duplication.
write_second_reaction_stagefalseControls whether the second LAMMPS reaction stage is written.
Default JSON block: -```text +```json { "reaction_iteration_depth": 5, - "deep_search": true, - "deduplicate_reaction_templates": true, - "wildcards": true, - "write_second_reaction_stage": false + "wildcards": true } ``` -

Important: These options affect template generation and LAMMPS input generation, so changing them can change the number of generated reaction templates and the final LAMMPS workflow.

+

Important: These options can change how many reaction products and LAMMPS reaction templates are generated.

--- @@ -112,6 +54,8 @@ If this option is disabled, AutoREACTER will only generate products from the ini You can set this variable to `false` so AutoREACTER will not enter the reaction-iteration loop. You can also use a non-negative integer to set the maximum number of iterations. This helps control reaction explosion. If five iterations are not enough to generate all possible products, you can increase the number of iterations. +

Important: Setting reaction_iteration_depth too high can generate a large number of products and reaction templates.

+ The examples below show this behavior for an epoxy-amine reaction and glycine polymerization. For the epoxy-amine example, the input monomers are: @@ -174,140 +118,6 @@ For glycine polymerization, the input monomer is: --- -(deep_search)= -## deep_search - -`deep_search` controls how strictly AutoREACTER compares reaction templates during RDKit/NetworkX-based deduplication. - -During early reaction-template generation, AutoREACTER has not yet assigned force-field atom types. At this stage, RDKit only knows the chemical graph, not the final force-field atom types. Because of this, two templates can look identical to RDKit even though they may later receive different atom types after force-field assignment. - -When `deep_search` is enabled, AutoREACTER extends the graph comparison by one additional neighbor beyond the normal template edge atoms. In practical terms, this means the comparison also checks the “5th atom” outside the normal reaction-template distance. This extra check helps prevent two templates from being incorrectly treated as duplicates when their immediate reaction core is the same but their outer chemical environment is different. - -This option is useful because atom typing is not performed during RDKit reaction detection. The extra graph environment acts as a substitute for missing atom-type information during deduplication. - -For example, two reaction templates may have the same reacting atoms and the same four-atom dihedral-distance template core, but differ at the edge, as shown in the example below. - -Using the following polyamidation reaction as an example: - -```json -{ - "monomers": [ - { - "name": "4-methylheptanedioyl_dichloride", - "smiles": "CC(CCC(=O)Cl)CCC(=O)Cl" - }, - { - "name": "heptanedioyl_dichloride", - "smiles": "O=C(Cl)CCCCCC(=O)Cl" - }, - { - "name": "m-phenylenediamine", - "smiles": "C1=CC(=CC(=C1)N)N" - } - ] -} -``` - -The input monomers are shown below. - -```{image} _static/deep_search_figures/input_monomers.png -:alt: deep_search_demo_monomers -:width: 100% -:align: center -``` - -Without deep search, the reaction between `4-methylheptanedioyl_dichloride` and `m-phenylenediamine` can be treated as a duplicate of the reaction between `heptanedioyl_dichloride` and `m-phenylenediamine`, because the reaction core up to the normal dihedral-distance template region is identical. - -```{image} _static/deep_search_figures/w_o_deep_search.png -:alt: without_deep_search_template_deduplication -:width: 100% -:align: center -``` - -With deep search enabled, the additional graph-environment check detects that the two templates are chemically different and does not treat them as duplicates. - -```{image} _static/deep_search_figures/w_deep_search.png -:alt: with_deep_search_template_deduplication -:width: 100% -:align: center -``` - -However, there can still be edge cases, as shown in the example below. - -```json -{ - "monomers": [ - { - "name": "branched_alkenyl_diacid_chloride", - "smiles": "C=CCC(CCCCCCC(CC=C)C(=O)Cl)C(=O)Cl" - }, - { - "name": "m-phenylenediamine", - "smiles": "C1=CC(=CC(=C1)N)N" - }, - { - "name": "extended_branched_alkenyl_diacid_chloride", - "smiles": "C/C=C/CC(CCCCCCC(C/C=C/C)C(=O)Cl)C(=O)Cl" - } - ] -} -``` - -```{image} _static/deep_search_figures/edge_monomers.png -:alt: deep_search_edge_case_monomers -:width: 100% -:align: center -``` - -In this case, the template contains double-bonded carbons. In one molecule, the double bond is part of a vinyl group, and the carbon bonded to the alkene chain will be typed as `c=1`, which is part of the template. In the other molecule, the corresponding carbon is bonded to another alkene chain. In this case, both carbons will be typed as `c=2`, including the carbon in the template. - -Even with deep search, AutoREACTER will only generate the template shown below. - -```{image} _static/deep_search_figures/edge_templates_template.png -:alt: deep_search_edge_case_generated_template -:width: 100% -:align: center -``` - -The following template will be missed. - -```{image} _static/deep_search_figures/missed_templates_template.png -:alt: deep_search_edge_case_missed_template -:width: 100% -:align: center -``` - -In this situation, deep search is not enough to detect the difference between the two templates, so the templates can still be treated as duplicates. - -With wildcard search enabled, this issue can be eliminated. See the `wildcards` section below. - ---- - -(deduplicate_reaction_templates)= -## deduplicate_reaction_templates - -AutoREACTER first generates all possible reactions and then generates LAMMPS reaction templates for those reactions. Some of these templates can be duplicates. The `deduplicate_reaction_templates` option controls whether AutoREACTER removes those duplicate templates. - -This deduplication step is one of the final steps in the AutoREACTER workflow. If `deduplicate_reaction_templates` is set to `false`, AutoREACTER will keep all generated templates, including duplicates. - -We recommend keeping this option set to `true` so AutoREACTER only writes unique templates. - -

Important: If deduplicate_reaction_templates is set to false, AutoREACTER may write many redundant LAMMPS reaction templates.

- -Example output: - -```text -Preparing templates and map file for reaction ID: 1 -Preparing templates and map file for reaction ID: 2 -Preparing templates and map file for reaction ID: 4 -Preparing templates and map file for reaction ID: 8 -Preparing templates and map file for reaction ID: 9 -Duplicate template disabled: RXN_8 -Duplicate template disabled: RXN_9 -``` - ---- - (wildcards)= ## wildcards @@ -337,42 +147,17 @@ For normal vinyl reactions, AutoREACTER may need three templates without wildcar See the styrene vinyl reaction example below. The following templates are generated without wildcards. + ```{image} _static/wild_cards_figures/prior_templates_template.png :alt: styrene_templates_without_wildcards :width: 100% :align: center ``` + The following templates are generated with wildcards enabled. + ```{image} _static/wild_cards_figures/wild_cards-templates_template.png :alt: styrene_templates_with_wildcards :width: 100% :align: center -``` - ---- - -(write_second_reaction_stage)= -## write_second_reaction_stage - -`write_second_reaction_stage` controls whether AutoREACTER writes the second LAMMPS reaction-stage input file. - -When this option is set to `true`, AutoREACTER writes both reaction stages: - -```text -3_reaction_first_stage -4_reaction_second_stage -``` - -The first reaction stage usually uses a shorter reaction cutoff and is intended to capture close-contact reactions. The second reaction stage uses a larger reaction cutoff and allows additional reactions to occur after the first-stage structure has already reacted. - -When this option is set to `false`, AutoREACTER skips the second reaction stage and writes only the first reaction stage. In that case, the post-equilibration stage will use the output from the first reaction stage as its input. - -Use `write_second_reaction_stage: true` when you want a two-stage reaction workflow. Use `write_second_reaction_stage: false` when you want a shorter workflow or when the first reaction stage is sufficient for the system. - -Example: - -```json -{ - "write_second_reaction_stage": true -} ``` \ No newline at end of file diff --git a/docs/source/api_reference.md b/docs/source/api_reference.md index 05531331..023e0e99 100644 --- a/docs/source/api_reference.md +++ b/docs/source/api_reference.md @@ -8,7 +8,7 @@ AutoREACTER accepts an input file path, initializes the session, and exposes met --- -### Import AutoREACTER +## Import AutoREACTER ```python import AutoREACTER as arx diff --git a/docs/source/contact.md b/docs/source/contact.md index e3904180..35ad4da1 100644 --- a/docs/source/contact.md +++ b/docs/source/contact.md @@ -1,4 +1,4 @@ -## Contact us +# Contact us For questions, suggestions, or bug reports: @@ -6,4 +6,4 @@ For questions, suggestions, or bug reports: - Email: [jmahanth@stevens.edu](mailto:jmahanth@stevens.edu) - Website: [https://www.nanocipher.org/](https://www.nanocipher.org/) -Please include relevant details when reporting issues. \ No newline at end of file +Please include relevant details when reporting issues. diff --git a/docs/source/getting-started.md b/docs/source/getting-started.md index f5d94453..98fbe000 100644 --- a/docs/source/getting-started.md +++ b/docs/source/getting-started.md @@ -11,3 +11,12 @@ Use this guide if you want to clone the AutoREACTER GitHub repository, install t ## {doc}`Getting Started - Pip Installation Guide ` Use this guide if you want to install AutoREACTER directly from PyPI and run your first workflow. + + +```{toctree} +:hidden: + +getting_started_pip_installation +getting_started_source_installation +``` + diff --git a/docs/source/getting_started_pip_installation.md b/docs/source/getting_started_pip_installation.md index 123174cf..2d8915bd 100644 --- a/docs/source/getting_started_pip_installation.md +++ b/docs/source/getting_started_pip_installation.md @@ -1,8 +1,8 @@ -## Getting Started - Pip Installation Guide +# Getting Started - Pip Installation Guide This guide explains how to install AutoREACTER from PyPI and run your first workflow. -### Step 1: Create a Python Virtual Environment +## Step 1: Create a Python Virtual Environment We recommend using a virtual environment so AutoREACTER and its dependencies do not interfere with your system Python installation. @@ -24,7 +24,7 @@ On Windows: arx_env\Scripts\activate ``` -### Step 2: Install AutoREACTER +## Step 2: Install AutoREACTER ```bash python -m pip install -U pip @@ -33,7 +33,7 @@ python -m pip install AutoREACTER This will install AutoREACTER and its required Python dependencies. -#### Step 2.1: Download and Prepare LUNAR (Prerequisite) +### Step 2.1: Download and Prepare LUNAR (Prerequisite) AutoREACTER requires the LUNAR package to handle atom typing. You must have this downloaded before running any examples. @@ -43,7 +43,7 @@ Note the Path: Keep track of the full directory path where LUNAR is saved on you Keep track of the full directory path where LUNAR is saved on your computer. During your first run, AutoREACTER will prompt you to enter this path. -### Step 3: Run AutoREACTER +## Step 3: Run AutoREACTER You can either run by downloading [run_AutoREACTER.py](https://github.com/NanoCIPHER-Lab/AutoREACTER/blob/main/examples/run_AutoREACTER.py) with [example_1_inputs_count_mode.json](https://github.com/NanoCIPHER-Lab/AutoREACTER/blob/main/examples/example_1_inputs_count_mode.json): diff --git a/docs/source/getting_started_source_installation.md b/docs/source/getting_started_source_installation.md index 304aff44..6d52e786 100644 --- a/docs/source/getting_started_source_installation.md +++ b/docs/source/getting_started_source_installation.md @@ -1,5 +1,5 @@ -## Getting Started - Source Installation Guide +# Getting Started - Source Installation Guide This guide will guide you through setting up your environment, installing the required dependencies, and running reaction modeling setup for REACTER. @@ -7,7 +7,7 @@ AutoREACTER relies heavily on cheminformatics libraries like RDKit, and numeric --- -### Step 1: Clone the Repository +## Step 1: Clone the Repository Download the AutoREACTER source code to your computer using Git. Open your terminal and run: @@ -16,7 +16,7 @@ git clone https://github.com/NanoCIPHER-Lab/AutoREACTER.git cd AutoREACTER ``` -### Step 2: Set Up the Conda Environment +## Step 2: Set Up the Conda Environment You need to create an environment containing Python 3.13(recommend) and the python libraries AutoREACTER needs to function. @@ -41,7 +41,7 @@ python -m pip install -U pip python -m pip install -r requirements.txt ``` -#### Step 2.1: Download and Prepare LUNAR (Prerequisite) +### Step 2.1: Download and Prepare LUNAR (Prerequisite) AutoREACTER requires the LUNAR package to handle atom typing. You must have this downloaded before running any examples. @@ -49,14 +49,14 @@ Download LUNAR from: [https://github.com/CMMRLab/LUNAR](https://github.com/CMMRL Note the Path: Keep track of the full directory path where LUNAR is saved on your computer (e.g., /home/user/software/LUNAR). During your first run, AutoREACTER will prompt you to enter this directory path. The path is then saved locally within the AutoREACTER. -### Step 3: Run Your First Example +## Step 3: Run Your First Example AutoREACTER provides two different ways to build your LAMMPS reaction files: - An interactive, visual Jupyter Notebook. - A fast, Command-Line Interface (CLI) -#### Option A: The Interactive Notebook +### Option A: The Interactive Notebook If you want to see exactly how AutoREACTER detects functional groups, maps templates, and handles non-reactive monomers, the Jupyter Notebook is the best place to start. @@ -102,7 +102,7 @@ Run the cells sequentially. The notebook will guide you step-by-step. **Interactive prompt note:** The notebook may ask what to do with monomers that do not participate in any detected reaction. For example: -#### Option B: The Automated CLI +### Option B: The Automated CLI If want to generate the LAMMPS files quickly, you can run AutoREACTER directly from the terminal. @@ -116,7 +116,7 @@ python examples/run_AutoREACTER.py -i examples/example_1_inputs_count_mode.json AutoREACTER parses the JSON, processes the chemistry, and exports all LAMMPS scripts to a new directory named after your specific simulation. -### Step 4: Run AutoREACTER +## Step 4: Run AutoREACTER You can either run by downloading [run_AutoREACTER.py](https://github.com/NanoCIPHER-Lab/AutoREACTER/blob/main/examples/run_AutoREACTER.py) with [`example_1_inputs_count_mode.json`](https://github.com/NanoCIPHER-Lab/AutoREACTER/blob/main/examples/example_1_inputs_count_mode.json): diff --git a/docs/source/index.rst b/docs/source/index.rst index 6d3842e1..ed57e738 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -7,15 +7,18 @@ :width: 750px :align: center -AutoREACTER documentation +AutoREACTER Documentation ========================= Welcome to the AutoREACTER documentation. AutoREACTER is a tool for automated reaction-based molecular system generation. -This guide covers setup, input configuration, and supported reactions. +This documentation is organized into a user guide and a developer guide. -**Note: AutoREACTER is currently under active development. APIs, configuration schemas, and core functionality may change or break without notice as we expand reaction library and force field support.** +**Note: AutoREACTER is currently under active development. APIs, configuration schemas, and core functionality may change or break without notice as we expand reaction-library and force-field support.** + +User Guide +---------- .. toctree:: :maxdepth: 1 @@ -23,9 +26,19 @@ This guide covers setup, input configuration, and supported reactions. overview.md getting-started.md - api_reference.md input-configuration.md + advanced_options.md supported-reactions.md supported-force-fields.md + api_reference.md + +Developer Guide +--------------- + +.. toctree:: + :maxdepth: 1 + :caption: Developer Guide: + + template-deduplication.md change_log.md contact.md \ No newline at end of file diff --git a/docs/source/input-configuration.md b/docs/source/input-configuration.md index 89fc160c..69b23385 100644 --- a/docs/source/input-configuration.md +++ b/docs/source/input-configuration.md @@ -1,4 +1,4 @@ -## Input Configuration. +# Input Configuration. The `input.json` file is the one and only input for your AutoREACTER workflow. It tells the system: @@ -15,7 +15,7 @@ There are two primary ways to define your system composition: **Ratio Mode** and --- -### 1. Global Settings & Monomers +## 1. Global Settings & Monomers Regardless of which mode you use, every `input.json` needs global settings and a list of your chemical building blocks. @@ -24,11 +24,11 @@ Regardless of which mode you use, every `input.json` needs global settings and a --- -### 2. Defining Simulations: Ratio Mode vs. Count Mode +## 2. Defining Simulations: Ratio Mode vs. Count Mode When defining the `simulations` array, you have to decide how you want to calculate the number of molecules in the simulation box. -#### Option A: Ratio Mode (Target Atom Count) +### Option A: Ratio Mode (Target Atom Count) Use Ratio Mode when you know the total size of the simulation you want to run (e.g., ~10,000 atoms) and the ratio of your molecules, but you don't want to calculate the exact number of individual molecules by hand. @@ -80,7 +80,7 @@ AutoREACTER will automatically calculate the correct number of molecules to hit } ``` -#### Option B: Count Mode (Exact Molecule Count) +### Option B: Count Mode (Exact Molecule Count) Use Count Mode when you know number of molecules instead of number of atoms. Instead of providing a total atom target, you explicitly define the exact number of each molecule using `monomer_counts`. @@ -130,7 +130,7 @@ Use Count Mode when you know number of molecules instead of number of atoms. Ins --- -### 3. Simulation Parameters Breakdown +## 3. Simulation Parameters Breakdown For each object inside the `simulations` list, you must define: @@ -141,7 +141,7 @@ For each object inside the `simulations` list, you must define: --- -### 4. Specifying the monomers or molecules. +## 4. Specifying the monomers or molecules. In the monomers section, you define each molecule as a dictionary entry. Each monomer (or molecule) must include: diff --git a/docs/source/supported-force-fields.md b/docs/source/supported-force-fields.md index 2b5cebec..35617c48 100644 --- a/docs/source/supported-force-fields.md +++ b/docs/source/supported-force-fields.md @@ -1,4 +1,4 @@ -## Supported Force Fields +# Supported Force Fields All classical force fields integrated into **AutoREACTER** are processed via the [LUNAR][LUNAR_GITHUB] package. @@ -11,4 +11,4 @@ All classical force fields integrated into **AutoREACTER** are processed via the **Note: Proper installation and path configuration for [LUNAR][LUNAR_GITHUB] is required in `AutoREACTER` to utilize these force fields.** -[LUNAR_GITHUB]: https://github.com/CMMRLab/LUNAR \ No newline at end of file +[LUNAR_GITHUB]: https://github.com/CMMRLab/LUNAR diff --git a/docs/source/supported-reactions.md b/docs/source/supported-reactions.md index 3971263b..5af2e302 100644 --- a/docs/source/supported-reactions.md +++ b/docs/source/supported-reactions.md @@ -1,4 +1,4 @@ -## Supported Reactions +# Supported Reactions AutoREACTER is currently in **v{{ autoreacter_version }}**. At this stage of development, the reaction library supports a broad range of step-growth and chain-growth polymerization reactions, including **polycondensation**, **transesterification**, **polyaddition**, **hydrolysis initiation**, and **addition polymerization**. @@ -10,7 +10,7 @@ The core `Detector` module automatically identifies the following functional gro --- -### 1. Polyesterification +## 1. Polyesterification These reactions form ester linkages (`-COO-`) and typically release water (`H₂O`), alcohols (`R-OH`), or hydrogen halides (e.g., `HCl`) as byproducts. @@ -45,7 +45,7 @@ These reactions form ester linkages (`-COO-`) and typically release water (`H₂ --- -### 2. Polyamidation +## 2. Polyamidation These reactions form amide linkages (`-CONH-`) and typically release water (`H₂O`) or hydrogen halides (e.g., `HCl`) as byproducts. @@ -72,7 +72,7 @@ These reactions form amide linkages (`-CONH-`) and typically release water (`H --- -### 3. Polyanhydride Formation +## 3. Polyanhydride Formation These reactions form anhydride linkages (`-CO-O-CO-`) and typically release hydrogen halides (e.g., `HCl`) as byproducts. @@ -87,7 +87,7 @@ These reactions form anhydride linkages (`-CO-O-CO-`) and typically release hydr --- -### 4. Polythioesterification +## 4. Polythioesterification These reactions form thioester linkages (`-COS-`) and typically release water (`H₂O`) or hydrogen halides (e.g., `HCl`) as byproducts. @@ -102,7 +102,7 @@ These reactions form thioester linkages (`-COS-`) and typically release water (` --- -### 5. Mixed Polyester/Polythioester Formation +## 5. Mixed Polyester/Polythioester Formation These reactions are supported for hydroxy–thiol monomers reacting with acid halides. Depending on the reacting group, either an ester or thioester linkage can be formed. @@ -117,7 +117,7 @@ These reactions are supported for hydroxy–thiol monomers reacting with acid ha --- -### 6. Polyurethane, Polythiourethane, and Polyurea Formation +## 6. Polyurethane, Polythiourethane, and Polyurea Formation These reactions form urethane, thiourethane, or urea linkages via **polyaddition** pathways. @@ -136,7 +136,7 @@ These reactions form urethane, thiourethane, or urea linkages via **polyaddition --- -### 7. Epoxy-Amine Addition and Crosslinking +## 7. Epoxy-Amine Addition and Crosslinking These reactions model step-growth/network formation between amine curing agents and epoxy rings. @@ -151,7 +151,7 @@ These reactions model step-growth/network formation between amine curing agents --- -### 8. Vinyl and Fluoropolymer Addition Polymerization +## 8. Vinyl and Fluoropolymer Addition Polymerization These chain-growth pathways model radical initiation, propagation, and copolymerization of vinyl and fluorinated monomers. @@ -178,7 +178,7 @@ These chain-growth pathways model radical initiation, propagation, and copolymer --- -### 9. Polycarbonate Formation +## 9. Polycarbonate Formation These reactions build carbonate linkages via condensation or transcarbonation. @@ -193,7 +193,7 @@ These reactions build carbonate linkages via condensation or transcarbonation. --- -### 10. Polysiloxane Formation +## 10. Polysiloxane Formation These pathways handle hydrolysis of chlorosilanes and condensation of silanols into silicone chains. @@ -212,7 +212,7 @@ These pathways handle hydrolysis of chlorosilanes and condensation of silanols i --- -### 11. Thiol-Ene Click Polymerization +## 11. Thiol-Ene Click Polymerization * **Dithiol and Diene Thiol-Ene Click Polymerization** * *Reactants:* Dithiol (`-SH`) + Diene (`-C=C-`) @@ -221,4 +221,4 @@ These pathways handle hydrolysis of chlorosilanes and condensation of silanols i --- -NOTE: If you would like support for a specific reaction, please open an issue on [AutoREACTER GitHub Repository](https://github.com/NanoCIPHER-Lab/AutoREACTER). \ No newline at end of file +NOTE: If you would like support for a specific reaction, please open an issue on [AutoREACTER GitHub Repository](https://github.com/NanoCIPHER-Lab/AutoREACTER). diff --git a/docs/source/template-deduplication.md b/docs/source/template-deduplication.md new file mode 100644 index 00000000..763cf75c --- /dev/null +++ b/docs/source/template-deduplication.md @@ -0,0 +1,174 @@ +# Template Deduplication Options + +This page describes AutoREACTER options related to reaction-template comparison and duplicate-template removal. These options are mainly useful for developers or advanced users who need to understand how AutoREACTER decides whether two generated reaction templates are equivalent. + +The following template-deduplication options are available: + + + + + + + + + + + + + + + + + + + + + +
OptionDefaultPurpose
deep_searchtrueControls stricter RDKit/NetworkX template deduplication before atom typing.
deduplicate_reaction_templatestrueRemoves duplicate reaction templates before writing LAMMPS files.
+ +Default JSON block: + +```json +{ + "deep_search": true, + "deduplicate_reaction_templates": true +} +``` + +

Important: These options affect reaction-template comparison and duplicate-template removal before LAMMPS files are written.

+ +--- + +(deep_search)= +## deep_search + +`deep_search` controls how strictly AutoREACTER compares reaction templates during RDKit/NetworkX-based deduplication. + +During early reaction-template generation, AutoREACTER has not yet assigned force-field atom types. At this stage, RDKit only knows the chemical graph, not the final force-field atom types. Because of this, two templates can look identical to RDKit even though they may later receive different atom types after force-field assignment. + +When `deep_search` is enabled, AutoREACTER extends the graph comparison by one additional neighbor beyond the normal template edge atoms. In practical terms, this means the comparison also checks the “5th atom” outside the normal reaction-template distance. This extra check helps prevent two templates from being incorrectly treated as duplicates when their immediate reaction core is the same but their outer chemical environment is different. + +This option is useful because atom typing is not performed during RDKit reaction detection. The extra graph environment acts as a substitute for missing atom-type information during deduplication. + +

Important: deep_search helps distinguish templates before atom typing, but it is not a full replacement for force-field atom typing.

+ +For example, two reaction templates may have the same reacting atoms and the same four-atom dihedral-distance template core, but differ at the edge, as shown in the example below. + +Using the following polyamidation reaction as an example: + +```json +{ + "monomers": [ + { + "name": "4-methylheptanedioyl_dichloride", + "smiles": "CC(CCC(=O)Cl)CCC(=O)Cl" + }, + { + "name": "heptanedioyl_dichloride", + "smiles": "O=C(Cl)CCCCCC(=O)Cl" + }, + { + "name": "m-phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + } + ] +} +``` + +The input monomers are shown below. + +```{image} _static/deep_search_figures/input_monomers.png +:alt: deep_search_demo_monomers +:width: 100% +:align: center +``` + +Without deep search, the reaction between `4-methylheptanedioyl_dichloride` and `m-phenylenediamine` can be treated as a duplicate of the reaction between `heptanedioyl_dichloride` and `m-phenylenediamine`, because the reaction core up to the normal dihedral-distance template region is identical. + +```{image} _static/deep_search_figures/w_o_deep_search.png +:alt: without_deep_search_template_deduplication +:width: 100% +:align: center +``` + +With deep search enabled, the additional graph-environment check detects that the two templates are chemically different and does not treat them as duplicates. + +```{image} _static/deep_search_figures/w_deep_search.png +:alt: with_deep_search_template_deduplication +:width: 100% +:align: center +``` + +However, there can still be edge cases, as shown in the example below. + +```json +{ + "monomers": [ + { + "name": "branched_alkenyl_diacid_chloride", + "smiles": "C=CCC(CCCCCCC(CC=C)C(=O)Cl)C(=O)Cl" + }, + { + "name": "m-phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + }, + { + "name": "extended_branched_alkenyl_diacid_chloride", + "smiles": "C/C=C/CC(CCCCCCC(C/C=C/C)C(=O)Cl)C(=O)Cl" + } + ] +} +``` + +```{image} _static/deep_search_figures/edge_monomers.png +:alt: deep_search_edge_case_monomers +:width: 100% +:align: center +``` + +In this case, the template contains double-bonded carbons. In one molecule, the double bond is part of a vinyl group, and the carbon bonded to the alkene chain will be typed as `c=1`, which is part of the template. In the other molecule, the corresponding carbon is bonded to another alkene chain. In this case, both carbons will be typed as `c=2`, including the carbon in the template. + +Even with deep search, AutoREACTER will only generate the template shown below. + +```{image} _static/deep_search_figures/edge_templates_template.png +:alt: deep_search_edge_case_generated_template +:width: 100% +:align: center +``` + +The following template will be missed. + +```{image} _static/deep_search_figures/missed_templates_template.png +:alt: deep_search_edge_case_missed_template +:width: 100% +:align: center +``` + +In this situation, deep search is not enough to detect the difference between the two templates, so the templates can still be treated as duplicates. + +With wildcard search enabled, this issue can be eliminated. See the {doc}`advanced_options` page. + +--- + +(deduplicate_reaction_templates)= +## deduplicate_reaction_templates + +AutoREACTER first generates all possible reactions and then generates LAMMPS reaction templates for those reactions. Some of these templates can be duplicates. The `deduplicate_reaction_templates` option controls whether AutoREACTER removes those duplicate templates. + +This deduplication step is one of the final steps in the AutoREACTER workflow. If `deduplicate_reaction_templates` is set to `false`, AutoREACTER will keep all generated templates, including duplicates. + +We recommend keeping this option set to `true` so AutoREACTER only writes unique templates. + +

Important: If deduplicate_reaction_templates is set to false, AutoREACTER may write many redundant LAMMPS reaction templates.

+ +Example output: + +```text +Preparing templates and map file for reaction ID: 1 +Preparing templates and map file for reaction ID: 2 +Preparing templates and map file for reaction ID: 4 +Preparing templates and map file for reaction ID: 8 +Preparing templates and map file for reaction ID: 9 +Duplicate template disabled: RXN_8 +Duplicate template disabled: RXN_9 +``` From f89a11d95afcdfa7a6152df5406062b5c18d42b5 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 20 Aug 2026 16:10:44 -0400 Subject: [PATCH 158/176] Add v0.3.0 reaction progression workflow --- docs/source/change_log.md | 60 ++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/docs/source/change_log.md b/docs/source/change_log.md index 3a32b240..09ed054c 100644 --- a/docs/source/change_log.md +++ b/docs/source/change_log.md @@ -22,29 +22,61 @@ This serves two purposes: At release time, you can move the Unreleased section changes into a new release version section. --> -## [0.3] - [2026-08-xx] +# Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +--- + +## [0.3.0] - 2026-08-21 + ### Added -* **Reaction Progression:** Multi-stage reaction template generation to handle multi stage reaction progressions, copolymerizations and small molecules which needs few templates for the polymerization reactions. -* **Looping Control:** A new loop control parameter in the input file to prevent the explosion of unnecessary reactions. Defaults to `5` loops, but can be optimized by setting `loop: ` or disabled entirely with `loop: False`. -* **Advanced Detection:** Index-based functional group detection and index-based reaction detection to accurately identify reacting atoms post-first reaction. -* **Pathway Deduplication:** NetworkX-based deduplication detection to actively filter redundant reaction pathways. -* **Reaction Libraries:** Robust library modules for various polymer chemistries, including Epoxies, Polyamides, Polyesters, Polycarbonates, Polysiloxanes, Polyureas, Polyurethanes, and Vinyl polymers. -* **Force Field Parameters:** PCFF force field additions, specifically including new `s_m` sulfone parameters. +- **Reaction progression workflow:** Added iterative reaction-product generation so AutoREACTER can generate templates from products formed in earlier reaction steps. This improves support for multistage reactions, copolymerizations, and small-molecule systems where the initial monomers alone are not sufficient to generate all required polymerization templates. +- **Reaction iteration control:** Added `reaction_iteration_depth` to control how many reaction-product iterations are attempted. The default value is `5`, and the loop can be disabled by setting `reaction_iteration_depth` to `false`. +- **Index-based functional-group detection:** Added index-based functional-group detection to track reactive atom positions more accurately during reaction progression. +- **Index-based reaction detection:** Added index-based reaction detection so products generated in earlier reaction steps can be checked for additional valid reactions. +- **RDKit/NetworkX reaction deduplication:** Added graph-based reaction deduplication to reduce redundant reaction pathways during reaction progression. +- **LAMMPS template deduplication:** Added NetworkX-based LAMMPS template deduplication using generated pre-reaction templates, post-reaction templates, and map files. +- **Wildcard template support:** Added support for LAMMPS wildcard map generation to reduce duplicate edge-template cases when using supported LAMMPS versions. +- **Expanded reaction libraries:** Added and reorganized polymer reaction libraries for epoxy-amine, polyamide, polyester, polycarbonate, polysiloxane, polyurea, polyurethane, vinyl, and related polymerization chemistries. +- **Expanded functional-group libraries:** Added modular functional-group libraries for nitrogen, oxygen, carboxyl/carbonyl, vinyl/alkene, sulfur, silicon, ring, active-center, and mixed AB-type groups. +- **TFE/vinyl support:** Added support for tetrafluoroethylene and additional vinyl polymerization workflows. +- **Public API session access:** Added `arx.session()` to expose the active AutoREACTER session for workflow inspection. +- **Unit tests:** Added broader unit-test coverage for input parsing, ARX CLI behavior, reaction preparation, LUNAR client utilities, force-field wrapper components, walkers, and LAMMPS writers. +- **Documentation pages:** Added new documentation pages for advanced options and template deduplication. ### Changed -* **Library Organization:** Centralized the reaction libraries into dedicated modules to improve maintainability and expandability. -* **Structure Generation:** Improved 3D molecule embedding to better handle highly congested polymer structures. +- **Input parser:** Refactored input parsing and validation, including cleaner handling of workflow options, simulation setup fields, force-field aliases, and input schema checks. +- **Reaction-library organization:** Refactored reaction libraries into dedicated modules and registries instead of relying on one monolithic reaction-library file. +- **Functional-group organization:** Refactored functional-group definitions into modular registry-based libraries. +- **Reaction preparation:** Refactored reaction preparation to support reaction progression, deduplication, inactive-template filtering, and clearer error handling. +- **REACTER file handling:** Simplified REACTER file metadata storage by storing LAMMPS molecule paths directly on monomer entries and template/map paths directly on reaction metadata. +- **LAMMPS writers:** Updated LAMMPS input writers to use the refactored REACTER metadata and filter inactive reaction templates. +- **3D molecule preparation:** Improved 3D embedding and repair handling for congested or difficult polymer structures. +- **Examples:** Replaced older test-style example JSON files with cleaner v0.3 example inputs. +- **Documentation structure:** Reorganized documentation into clearer user-facing and developer-facing pages. -### Removed +### Fixed -* **Legacy Code:** Removed legacy compatibility shims (`_compat.py`). +- Fixed reaction progression issues where products from earlier steps were not correctly reused for later reaction detection. +- Fixed index-alignment issues during functional-group and reaction detection. +- Fixed radical handling for vinyl polymerization products and reaction deduplication. +- Fixed duplicate-template detection behavior for both RDKit-level reaction metadata and LAMMPS-level template files. +- Fixed handling of inactive or duplicate reaction templates so they are skipped in later workflow stages. +- Fixed empty-reaction cases so AutoREACTER raises clearer errors when no valid reaction instances are found. +- Fixed LAMMPS molecule/template file path handling after the REACTER metadata refactor. +- Fixed cache staging behavior during output directory preparation. +- Fixed documentation heading and toctree issues for cleaner Sphinx builds. -### Fixed +### Removed -* Addressed various stability and progression issues tracked in recent bug reports. -* Improved Error handling when no reaction instances are found for the specified monomer combinations. +- Removed legacy compatibility shims. +- Removed unused placeholder detector, fragment-comparison, and legacy library files. +- Removed older cluttered example JSON files in favor of focused v0.3 examples. ## [0.2.3] - [2026-06-24] From 11ed556ab10ca7b5bf84dd4dbd7eaf2b07860073 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 21 Aug 2026 12:56:58 -0400 Subject: [PATCH 159/176] Refresh README quick start guide --- README.md | 68 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 4871497a..06dfacb7 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ +

AutoREACTER logo

Automated generation of LAMMPS/REACTER-ready reaction-template workflows.

-> **Status:** AutoREACTER is currently in **v0.3** and under active development. APIs, configuration schemas, reaction libraries, and core functionality may change without notice. -> Please refer to the [changelog](https://autoreacter.org/change_log.html) for the latest updates. +> **Status:** AutoREACTER is currently in **v0.3** and under active development. +> APIs, configuration schemas, reaction libraries, and core functionality may change. ## Documentation @@ -13,19 +14,22 @@ Full documentation is available at: **[autoreacter.org](https://autoreacter.org/)** -The documentation includes installation instructions, input configuration, supported reactions, supported force fields, cleanup utilities, and developer API references. - -For detailed functional-group mapping and reaction rules, see the [supported reactions documentation](https://autoreacter.org/supported-reactions.html). +The documentation covers installation, input configuration, supported reactions, +force fields, workflow options, and API usage. ## Installation -AutoREACTER can be installed directly from PyPI: +Install AutoREACTER from PyPI: ```bash python -m pip install AutoREACTER -``` +```` + +AutoREACTER also requires **LUNAR** for atom typing. See the +[Getting Started documentation](https://autoreacter.org/getting-started.html) +for setup instructions. -For users who want to modify the source code or run the latest development version, AutoREACTER can also be installed from source: +For development or source installation: ```bash git clone https://github.com/NanoCIPHER-Lab/AutoREACTER.git @@ -33,42 +37,52 @@ cd AutoREACTER python -m pip install -e . ``` -AutoREACTER also requires **LUNAR** for atom typing. See the [getting started documentation](https://autoreacter.org/getting-started.html) for the full setup guide. +## Quick Start -## Quick start +After installing AutoREACTER, create a Python script such as `run_autoreacter.py`: -Run AutoREACTER with a JSON input file: +```python +import AutoREACTER as arx -```bash -python examples/example_1.py -i examples/example_1_inputs_count_mode.json -``` +arx.run("input.json") -or: +arx.select_reactions() +arx.select_non_reactants() -```bash -python examples/example_1.py --input examples/example_1_inputs_count_mode.json +arx.prepare_reactions() + +session = arx.session() +print(f"Review generated images in: {session.images_dir}") + +input("Press Enter to continue...") + +arx.process() ``` -View available commands and options: +Run it with: ```bash -python examples/example_1.py --help +python run_autoreacter.py ``` -## Interactive notebook workflow +Example JSON input files and complete workflows are available in the +[`examples`](https://github.com/NanoCIPHER-Lab/AutoREACTER/tree/main/examples) +directory. -AutoREACTER can also be used through Jupyter notebooks for an interactive, visual, step-by-step workflow. This mode is recommended for inspecting monomers, functional groups, reaction templates, and generated LAMMPS setup files before running larger workflows. +For users working directly from the source repository, the included example +runner can also be used: -See the examples directory for notebooks and usage notes: - -**[examples/README.md](https://autoreacter.org/getting_started_source_installation.html)** +```bash +python examples/example_1.py -i examples/polyamide_count_mode_basic.json +``` -## Help and support +## Help and Support -If you find a bug, need a new reaction type, or want to request additional force-field support, please open an issue: +For bugs, reaction requests, or force-field support requests, please open an issue: **[AutoREACTER Issues](https://github.com/NanoCIPHER-Lab/AutoREACTER/issues)** ## License -AutoREACTER is released under the **MIT License**. See [LICENSE](https://github.com/NanoCIPHER-Lab/AutoREACTER/blob/main/LICENSE.md) for details. +AutoREACTER is released under the **MIT License**. +See [LICENSE](https://github.com/NanoCIPHER-Lab/AutoREACTER/blob/main/LICENSE.md). From c639c3d1bcb60d7aaab557f47b944d26ebdeaa83 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 21 Aug 2026 12:59:39 -0400 Subject: [PATCH 160/176] Update example_1.py --- examples/example_1.py | 173 +++++++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 76 deletions(-) diff --git a/examples/example_1.py b/examples/example_1.py index 03c3942c..525486b4 100644 --- a/examples/example_1.py +++ b/examples/example_1.py @@ -1,107 +1,128 @@ #!/usr/bin/env python3 """ -AutoREACTER Workflow: Required Pipeline Example -=============================================== +AutoREACTER Workflow Example +============================ -This script demonstrates the required AutoREACTER workflow only. -Visualization images are generated internally and saved in the session image directory. +This script demonstrates the standard AutoREACTER workflow using a JSON +input file. -Usage: - python auto_reacter_workflow.py -i example_1_inputs_count_mode.json +It is intended for users running AutoREACTER from the source repository. + +Example +------- +From the AutoREACTER repository root: + + python examples/example_1.py \ + -i examples/polyamide_count_mode_basic.json + +AutoREACTER can also be installed from PyPI and used directly from a +user-created Python script: + + python -m pip install AutoREACTER """ import argparse import sys -# --------------------------------------------------------------------------- -# 1. Command-line arguments -# --------------------------------------------------------------------------- -parser = argparse.ArgumentParser( - description="Run the required AutoREACTER workflow from an input JSON file." -) +def parse_arguments(): + """Parse command-line arguments.""" + parser = argparse.ArgumentParser( + description=( + "Run the standard AutoREACTER workflow " + "from an input JSON file." + ) + ) -parser.add_argument( - "-i", - "--input", - "-in", - required=True, - help="Path to the AutoREACTER input JSON file." -) + parser.add_argument( + "-i", + "--input", + "-in", + required=True, + help="Path to the AutoREACTER input JSON file.", + ) -args = parser.parse_args() + return parser.parse_args() -# --------------------------------------------------------------------------- -# 2. Import AutoREACTER -# --------------------------------------------------------------------------- -try: - import AutoREACTER as arx - print("AutoREACTER imported successfully.") -except ImportError: - print( - "Failed to import AutoREACTER. " - "Ensure the package is installed in your environment." - ) - raise +def main(): + """Run the standard AutoREACTER workflow.""" + + args = parse_arguments() + # ------------------------------------------------------------------------- + # 1. Import AutoREACTER + # ------------------------------------------------------------------------- -# --------------------------------------------------------------------------- -# 3. Version check & input load -# --------------------------------------------------------------------------- -# Print the installed version for reproducibility and debugging. -print(arx.__version__) + try: + import AutoREACTER as arx + except ImportError: + print( + "[ERROR] Failed to import AutoREACTER.\n" + "Install it with:\n\n" + " python -m pip install AutoREACTER\n" + ) + raise -# Load the JSON input file and initialize the AutoREACTER session. -arx.run(args.input) -session = arx.session() + print("[OK] AutoREACTER imported successfully.") + print(f"[INFO] AutoREACTER version: {arx.__version__}") + # ------------------------------------------------------------------------- + # 2. Initialize workflow + # ------------------------------------------------------------------------- -# --------------------------------------------------------------------------- -# 4. Select reactions and non-reactants -# --------------------------------------------------------------------------- -# Select which detected reactions should be processed. -arx.select_reactions() + arx.run(args.input) -# Select non-reactant molecules, if any are detected. -arx.select_non_reactants() + # ------------------------------------------------------------------------- + # 3. Select reactions + # ------------------------------------------------------------------------- + arx.select_reactions() -# --------------------------------------------------------------------------- -# 5. Reaction template preparation -# --------------------------------------------------------------------------- -# Prepare reaction templates for downstream REACTER file generation. -arx.prepare_reactions() + # ------------------------------------------------------------------------- + # 4. Select non-reactants + # ------------------------------------------------------------------------- + arx.select_non_reactants() -# --------------------------------------------------------------------------- -# 6. Review checkpoint -# --------------------------------------------------------------------------- -# AutoREACTER saves visualization images internally in the session image directory. -print( - "\n[INFO] Reaction preparation completed." - "\n[INFO] Please review the generated images in the session image directory." -) + # ------------------------------------------------------------------------- + # 5. Prepare reaction templates + # ------------------------------------------------------------------------- -# Try to print the image directory if it is exposed by AutoREACTER. -session = arx.session() -img_dir = getattr(session, "img_dir", None) or getattr(session, "images_dir", None) + arx.prepare_reactions() -if img_dir is not None: - print(f"[INFO] Image directory: {img_dir}") + # ------------------------------------------------------------------------- + # 6. Review checkpoint + # ------------------------------------------------------------------------- -ok_pass = input("\nType 'ok' to continue with final processing: ").strip().lower() + session = arx.session() -if ok_pass != "ok": - print("[EXIT] Workflow stopped by user.") - sys.exit(0) + print( + "\n[INFO] Reaction preparation completed." + f"\n[INFO] Review generated images in: {session.images_dir}" + ) + + confirmation = input( + "\nType 'ok' to continue with final processing: " + ).strip().lower() + + if confirmation != "ok": + print("[EXIT] Workflow stopped by user.") + return 0 + + # ------------------------------------------------------------------------- + # 7. Final processing + # ------------------------------------------------------------------------- + + arx.process() + + print( + "\n[INFO] AutoREACTER workflow completed successfully." + f"\n[INFO] Output directory: {session.output_dir}" + ) + return 0 -# --------------------------------------------------------------------------- -# 7. Final processing -# --------------------------------------------------------------------------- -# Run 3D geometry setup, force-field generation, REACTER file building, -# and LAMMPS simulation setup. -arx.process() -print("\n[INFO] AutoREACTER workflow completed successfully.") +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file From fbcbace12a48c253ee7f84653a5815d842fb2677 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 21 Aug 2026 13:03:00 -0400 Subject: [PATCH 161/176] Remove workflow flags from Session model --- AutoREACTER/session.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/AutoREACTER/session.py b/AutoREACTER/session.py index cf69f4a8..78c5c8e9 100644 --- a/AutoREACTER/session.py +++ b/AutoREACTER/session.py @@ -85,14 +85,6 @@ class Session: reaction_id_counter: int = 0 reaction_progression_session: object | None = None - # Workflow options copied from SimulationSetup - deep_search: bool = True - reaction_iteration_depth: int = 5 - wildcards: bool = True - deduplicate_reaction_templates: bool = True - write_second_reaction_stage: bool = True - - def _resolve_input_path(input_file_path: str) -> Path: """ From 9c60db2cca9e9355968d229afd326ce998505f32 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Fri, 21 Aug 2026 13:10:40 -0400 Subject: [PATCH 162/176] Refine session runtime default test coverage --- tests/unit/test_session.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py index beaf4ffe..29ddba47 100644 --- a/tests/unit/test_session.py +++ b/tests/unit/test_session.py @@ -191,32 +191,30 @@ def test_session_file_bundles_default_to_none(tmp_path): def test_session_runtime_defaults(tmp_path): + inputs = make_validated_inputs() + session = Session( - inputs=make_validated_inputs(), + inputs=inputs, staging_dir=tmp_path / "staging", output_dir=tmp_path / "output", images_dir=tmp_path / "images", ) - assert session.reaction_id_counter == 0 + assert session.inputs is inputs - assert ( - session.reaction_progression_session - is None - ) + assert session.monomer_roles == [] + assert session.reaction_instances == [] + assert session.non_reactants == [] + assert session.reaction_metadata == [] - assert session.deep_search is True - assert session.reaction_iteration_depth == 5 - assert session.wildcards is True + assert session.ff_files is None + assert session.reacter_files is None - assert ( - session.deduplicate_reaction_templates - is True - ) + assert session.reaction_id_counter == 0 assert ( - session.write_second_reaction_stage - is True + session.reaction_progression_session + is None ) From e146f38cf83a66ff98749e01c76cd9292ee4ccdc Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 31 Aug 2026 12:41:05 -0400 Subject: [PATCH 163/176] Update advanced_options.md --- docs/source/advanced_options.md | 100 +++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 7 deletions(-) diff --git a/docs/source/advanced_options.md b/docs/source/advanced_options.md index 8bae48c1..3d33cd82 100644 --- a/docs/source/advanced_options.md +++ b/docs/source/advanced_options.md @@ -1,8 +1,8 @@ # Advanced Options -AutoREACTER gives users control over advanced reaction-generation behavior through the input JSON file. These options are intended for users who want to control reaction-product iteration and LAMMPS wildcard template generation. +AutoREACTER gives users control over advanced workflow behavior through the input JSON file. These options are intended for users who want to control reaction-product iteration, LAMMPS wildcard template generation, and output-file placement. -The following advanced options are available for users: +The following user-facing advanced options are currently available: @@ -16,17 +16,22 @@ The following advanced options are available for users: - + - + + + + + +
reaction_iteration_depth 5Controls how many reaction-product iterations are attempted.Controls the maximum number of reaction-product iterations used during reaction progression.
wildcards trueUses LAMMPS wildcard maps to reduce edge-template duplication.Generates LAMMPS wildcard map sections to reduce redundant edge-template cases.
output_dirAutoREACTER_outputs/<simulation_name>Controls where AutoREACTER writes generated output files.
-Default JSON block: +Default behavior: ```json { @@ -35,8 +40,13 @@ Default JSON block: } ``` -

Important: These options can change how many reaction products and LAMMPS reaction templates are generated.

+By default, `output_dir` does not need to be provided. If it is omitted, AutoREACTER writes outputs next to the input JSON file using: + +```text +AutoREACTER_outputs/ +``` +

Important: These options can change the number of generated reaction products, reaction templates, LAMMPS map files, and output locations.

--- (reaction_iteration_depth)= @@ -160,4 +170,80 @@ The following templates are generated with wildcards enabled. :alt: styrene_templates_with_wildcards :width: 100% :align: center -``` \ No newline at end of file +``` + +--- + +(output_dir)= +## output_dir + +`output_dir` is an optional top-level input setting that controls where AutoREACTER writes generated output files. + +If `output_dir` is not provided, AutoREACTER writes outputs next to the input JSON file using the default folder structure: + +```text +AutoREACTER_outputs/ +``` + +Example: + +```json +{ + "simulation_name": "Polyamide_Count_Mode_Basic", + "force_field": "PCFF", + "output_dir": "my_outputs", + "simulations": [ + { + "tag": "10k_300K", + "temperature": 300, + "density": 0.8, + "monomer_counts": { + "trimesoyl_chloride": 220, + "m_phenylenediamine": 330 + } + } + ], + "monomers": [ + { + "name": "trimesoyl_chloride", + "smiles": "ClC(=O)c1cc(cc(c1)C(Cl)=O)C(Cl)=O" + }, + { + "name": "m_phenylenediamine", + "smiles": "C1=CC(=CC(=C1)N)N" + } + ] +} +``` + +For this example, AutoREACTER writes output to: + +```text +my_outputs +``` + +Relative paths are resolved relative to the input JSON file location. Absolute paths are used directly. + +Examples: + +```json +{ + "output_dir": "AutoREACTER_outputs/polyamide_test" +} +``` + +```json +{ + "output_dir": "/home/user/AutoREACTER_runs/polyamide_test" +} +``` + +On Windows or WSL, Windows-style paths can also be used: + +```json +{ + "output_dir": "C:/Users/Janitha/Documents/AutoREACTER_runs/polyamide_test" +} +``` + +

Important: If the output directory already exists, AutoREACTER may overwrite or clear generated workflow files from the previous run.

\ No newline at end of file From b6d79269627105ea9b27bfde052c257d2970644b Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 31 Aug 2026 12:44:29 -0400 Subject: [PATCH 164/176] Clarify active reaction map usage --- AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py | 5 ++--- AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py index e349ce00..e7f99185 100644 --- a/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_first_stage_writer.py @@ -151,9 +151,8 @@ def write_first_stage_reaction_files(self, simulation: Simulation) -> str: pre_file = template.pre_reaction_file.name post_file = template.post_reaction_file.name - # The standard map is always used by AutoREACTER. - # A supplementary DeleteIDs map may also be provided to the user, - # but AutoREACTER does not automatically select it. + # Use the active map generated by AutoREACTER. For reactions with + # deleted atoms, this map includes the required DeleteIDs section. map_file = template.map_file.name id = template.reaction_id diff --git a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py index a099d21b..70725840 100644 --- a/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py +++ b/AutoREACTER/sim_setup/writers/rxn_second_stage_writer.py @@ -168,8 +168,8 @@ def write_second_stage_reaction_files(self, simulation: Simulation) -> str: pre_file = template.pre_reaction_file.name post_file = template.post_reaction_file.name - # AutoREACTER always uses the standard map by default. - # The optional *_with_delete_ids.map file is only provided to the user. + # Use the active map generated by AutoREACTER. For reactions with + # deleted atoms, this map includes the required DeleteIDs section. map_file = template.map_file.name # Register molecule templates in LAMMPS. From a50c8d7d3200fd68fd46096aebe31a2b1ca2ce15 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 31 Aug 2026 12:45:48 -0400 Subject: [PATCH 165/176] Update REACTER_files_builder.py --- .../ff_wrapper/REACTER_files_builder.py | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index ca175da5..b81c944d 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -488,6 +488,13 @@ def _build_bond_react_templates(self, template_indexes_reactant.append(int(key + 1)) template_indexes_product.append(int(value + 1)) + # Deleted atoms do not have product equivalences, but they must still + # be present in the pre-reaction template so LAMMPS can delete them. + for atom_index in delete_ids: + atom_index_1_based = int(atom_index + 1) + if atom_index_1_based not in template_indexes_reactant: + template_indexes_reactant.append(atom_index_1_based) + # Iterate the provided file dictionary and only process entries that start with "pre_" # so that we can find their matching "post_{num}" counterparts. # Wrapped file_dict.items() in list() to prevent RuntimeError @@ -598,34 +605,36 @@ def _build_bond_react_templates(self, ] - # Construct the .map file contents using the reindexed template-space mappings - # 1. Standard map file (Pass [] to suppress delete_ids) + # 1. Standard map file. + # This is the default map used by AutoREACTER-generated + # LAMMPS scripts, so DeleteIDs are intentionally suppressed. map_file_contents = self._map_file_write( template_reactant_to_template_product, initiator_atoms_t, edge_atoms_t, - [], + [], file_name=map_file_name ) map_path = os.path.join(self.cache_dir, map_file_name) with open(map_path, "w") as f: f.write(map_file_contents) - # 2. Supplementary map file (With delete_ids, if any exist) + # 2. Optional map file with DeleteIDs. + map_path_del = None if delete_ids_t: map_file_name_del = f"RXN_{num}_with_delete_ids.map" map_file_contents_del = self._map_file_write( template_reactant_to_template_product, initiator_atoms_t, edge_atoms_t, - delete_ids_t, + delete_ids_t, file_name=map_file_name_del ) map_path_del = os.path.join(self.cache_dir, map_file_name_del) with open(map_path_del, "w") as f: f.write(map_file_contents_del) - return pre_out, post_out, map_path + return pre_out, post_out, map_path, map_path_del def _copy_lunar_files_to_cache(self, ff_files: FFFiles) -> tuple[Path, Path]: """ @@ -756,7 +765,7 @@ def molecule_template_preparation(self, session: "Session") -> None: } # Build the per-reaction template files and mappings. - pre_out, post_out, map_path = self._build_bond_react_templates( + pre_out, post_out, map_path, map_path_del = self._build_bond_react_templates( file_dict = current_rxn_files, reactant_to_product = template_map, initiator_atoms = initiators, @@ -764,6 +773,9 @@ def molecule_template_preparation(self, session: "Session") -> None: delete_ids = delete_ids ) current_rxn_metadata.map_file = Path(map_path) + current_rxn_metadata.map_file_with_delete_ids = ( + Path(map_path_del) if map_path_del is not None else None + ) current_rxn_metadata.pre_reaction_file = Path(pre_out) current_rxn_metadata.post_reaction_file = Path(post_out) From c23970140e591ee6344dbf572615c850f0f987b0 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 31 Aug 2026 12:47:03 -0400 Subject: [PATCH 166/176] Update deduplication_detector.py --- .../deduplication_detector.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/AutoREACTER/reaction_preparation/deduplication_detector.py b/AutoREACTER/reaction_preparation/deduplication_detector.py index b7f35666..54b11c9a 100644 --- a/AutoREACTER/reaction_preparation/deduplication_detector.py +++ b/AutoREACTER/reaction_preparation/deduplication_detector.py @@ -1300,6 +1300,21 @@ def write_wildcard_maps( ) template.map_file = map_file_path + + delete_map_file = getattr( + template, + "map_file_with_delete_ids", + None, + ) + if delete_map_file is not None: + delete_map_file = Path(delete_map_file) + if delete_map_file.is_file(): + self._write_lammps_wildcard_map_file( + map_file_path=delete_map_file, + wildcard_ids=wildcard_ids, + ) + template.map_file_with_delete_ids = delete_map_file + active_templates.append(template) return active_templates @@ -1389,6 +1404,20 @@ def compare_lammps_templates( template.map_file = map_file_path + delete_map_file = getattr( + template, + "map_file_with_delete_ids", + None, + ) + if delete_map_file is not None: + delete_map_file = Path(delete_map_file) + if delete_map_file.is_file(): + self._write_lammps_wildcard_map_file( + map_file_path=delete_map_file, + wildcard_ids=wildcard_ids, + ) + template.map_file_with_delete_ids = delete_map_file + template.activity_stats = True unique_templates.append(template) From 7b99a9a85dcda794eb7d659f006d699d8f43aff2 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Mon, 31 Aug 2026 15:13:50 -0400 Subject: [PATCH 167/176] Update REACTER_files_builder.py --- .../ff_wrapper/REACTER_files_builder.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py index b81c944d..ebfc4bff 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py +++ b/AutoREACTER/reaction_preparation/ff_wrapper/REACTER_files_builder.py @@ -634,7 +634,7 @@ def _build_bond_react_templates(self, with open(map_path_del, "w") as f: f.write(map_file_contents_del) - return pre_out, post_out, map_path, map_path_del + return pre_out, post_out, map_path def _copy_lunar_files_to_cache(self, ff_files: FFFiles) -> tuple[Path, Path]: """ @@ -765,7 +765,7 @@ def molecule_template_preparation(self, session: "Session") -> None: } # Build the per-reaction template files and mappings. - pre_out, post_out, map_path, map_path_del = self._build_bond_react_templates( + pre_out, post_out, map_path = self._build_bond_react_templates( file_dict = current_rxn_files, reactant_to_product = template_map, initiator_atoms = initiators, @@ -773,9 +773,14 @@ def molecule_template_preparation(self, session: "Session") -> None: delete_ids = delete_ids ) current_rxn_metadata.map_file = Path(map_path) + + optional_delete_map = Path(map_path).with_name( + f"RXN_{id}_with_delete_ids.map" + ) current_rxn_metadata.map_file_with_delete_ids = ( - Path(map_path_del) if map_path_del is not None else None + optional_delete_map if optional_delete_map.is_file() else None ) + current_rxn_metadata.pre_reaction_file = Path(pre_out) current_rxn_metadata.post_reaction_file = Path(post_out) From 12d25dd3a9e8aebcca7cc10e0dec2b26e2ebbdff Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 2 Sep 2026 13:20:46 -0400 Subject: [PATCH 168/176] Format mixed AB group entries --- .../detectors/functional_groups_library/mixed_ab_groups.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py b/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py index 8679d04d..9184e1f3 100644 --- a/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py +++ b/AutoREACTER/detectors/functional_groups_library/mixed_ab_groups.py @@ -6,6 +6,7 @@ 'group_name': 'hydroxy_carboxylic_acid', 'comments': None }, + 'hydroxy_acid_halides_monomer': { 'functionality_type': 'di_different', 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', @@ -13,6 +14,7 @@ 'group_name': 'hydroxy_acid_halide', 'comments': None }, + 'amino_acid_monomer': { 'functionality_type': 'di_different', 'smarts_1': '[NX3;H2,H1;!$([N][C,S]=*):1]', @@ -20,6 +22,7 @@ 'group_name': 'amino_acid', 'comments': None }, + 'carboxylic_acid_acid_halide_monomer': { 'functionality_type': 'di_different', 'smarts_1': '[CX3:1](=[O])[OX2H1]', @@ -27,6 +30,7 @@ 'group_name': 'carboxylic_acid_acid_halide', 'comments': None }, + 'hydroxy_thiol_monomer': { 'functionality_type': 'di_different', 'smarts_1': '[OX2H1;!$([O][C,S]=*):1]', From c3f1a28fb8c6abebdbb1e056fe1937f411e16d28 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Wed, 9 Sep 2026 11:05:16 -0400 Subject: [PATCH 169/176] Add torsion fallbacks for unsupported FF terms --- AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc index e38ab419..7d7a2780 100644 --- a/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc +++ b/AutoREACTER/reaction_preparation/ff_wrapper/FF_files/pcff.frc @@ -3325,6 +3325,8 @@ 1.0 1 hn2 na c_2 na 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator 1.0 1 hn na c_2 o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER addition; tiny non-zero for validator 2.1 8 o_1 c_1 c c= 0.0442 0.0 0.0292 0.0 0.0562 0.0 # AutoREACTER addition; copied from c c c_1 o_1 reversed; mapped terminal c -> c= + 1.0 1 cp n=2 ct o_1 0.0001 0.0 0.0000 0.0 0.0000 0.0 # AutoREACTER fallback; unsupported cp-n=2-ct-o_1 torsion; near-zero barrier + 2.1 7 c1 o_2 c_2 nn -2.9522 0.0 2.4047 0.0 0.0000 0.0 # AutoREACTER addition; mapped from nn-c_2-o_2-c2 reversed; c2->c1 terminal mapping #wilson_out_of_plane cff91 From 62588ffdc6026c0f83c48e9be25aa68529c8491b Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:22:34 -0400 Subject: [PATCH 170/176] Add vinyl coupling termination options --- .../reactions_library/vinyl_polymers.py | 101 +++++++----------- 1 file changed, 41 insertions(+), 60 deletions(-) diff --git a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py index a8c24d95..34bf66ac 100644 --- a/AutoREACTER/detectors/reactions_library/vinyl_polymers.py +++ b/AutoREACTER/detectors/reactions_library/vinyl_polymers.py @@ -91,66 +91,47 @@ 'radical detection during loop progression.' ), }, - - - # ========================================================================= - # Optional Vinyl Radical Coupling Termination - # ========================================================================= - # - # Users can uncomment this reaction if they want to include vinyl radical - # coupling termination in the simulation. - # - # It is normally controlled separately from initiation and propagation - # so that vinyl growth is not terminated too early. - # - # 'Vinyl Radical Coupling Termination': { - # 'same_reactants': True, - # 'reactant_1': 'vinyl_chain_end_radical', - # 'product': 'vinyl_terminated_chain', - # 'delete_atom': False, - # - # # H-H radical coupling termination: - # # - # # chain-head* + *head-chain - # # ↓ - # # chain-head-head-chain - # # - # # This is intentionally the only head-to-head vinyl step. - # # Initiation and propagation remain head-to-tail. - # # - # # AutoREACTER/LAMMPS rule: - # # maps 1 and 2 are the initiator atoms. - # # the new termination bond is 1-2. - # # - # # Map 1 = active radical head carbon on one vinyl chain end. - # # Map 2 = active radical head carbon on another vinyl chain end. - # # - # # The D3/v3/+0 constraints make this target the - # # methacrylate-style chain-end radical center instead of - # # an ordinary acyclic carbon. - # 'reaction': ( - # '[C;!R;D3;v3;+0:1].' - # '[C;!R;D3;v3;+0:2]' - # '>>' - # '[C:1]-[C:2]' - # ), - # - # 'reference': { - # 'smarts': None, - # 'reaction_and_mechanism': None - # }, - # - # 'comments': None, - # - # 'notes': ( - # 'Head-to-head radical coupling termination for ' - # 'PMMA/TEGDMA-style vinyl chain ends. Maps 1 and 2 are ' - # 'the two active radical head carbons and form the new ' - # '1-2 termination bond. This reaction should be controlled ' - # 'separately from initiation and propagation, usually turned ' - # 'on late or pulsed so it does not kill vinyl growth too early.' - # ), - # }, +'Vinyl Radical Coupling Termination (Same Chain)': { + 'same_reactants': True, + 'reactant_1': 'vinyl_chain_end_radical', + 'product': 'vinyl_terminated_chain', + 'delete_atom': False, + 'reaction': ( + '[C;!R;D3;v3;+0:1].' + '[C;!R;D3;v3;+0:2]' + '>>' + '[C:1]-[C:2]' + ), + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None, + 'notes': ( + 'Head-to-head radical coupling termination between two radical ' + 'chain ends of the SAME monomer type. Maps 1 and 2 are the two ' + 'active radical head carbons and form the new 1-2 termination bond.' + ), +}, + +'Vinyl Radical Coupling Termination (Cross Chain)': { + 'same_reactants': False, + 'reactant_1': 'vinyl_chain_end_radical', + 'reactant_2': 'vinyl_chain_end_radical', # FIXED: was missing entirely + 'product': 'vinyl_terminated_chain', + 'delete_atom': False, + 'reaction': ( + '[C;!R;D3;v3;+0:1].' + '[C;!R;D3;v3;+0:2]' + '>>' + '[C:1]-[C:2]' + ), + 'reference': {'smarts': None, 'reaction_and_mechanism': None}, + 'comments': None, + 'notes': ( + 'Same coupling chemistry as the same-chain entry above, but ' + 'reactant_2 is explicitly given so this pairs radical chain ends ' + 'coming from TWO DIFFERENT monomer types (e.g. a PMMA-derived ' + 'radical terminating against a TEGDMA-derived radical).' + ), +}, # ========================================================================= From a349797573fa169ab0a076bd1ecb74aa5ceed8d8 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:32:20 -0400 Subject: [PATCH 171/176] Disable wildcards by default --- AutoREACTER/input_parser.py | 2 +- docs/source/advanced_options.md | 37 ++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 26af33bb..5e640113 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -172,7 +172,7 @@ class SimulationSetup: deep_search: bool = True loop: bool = True reaction_iteration_depth: int = 5 - wildcards: bool = True + wildcards: bool = False deduplicate_reaction_templates: bool = True write_second_reaction_stage: bool = False diff --git a/docs/source/advanced_options.md b/docs/source/advanced_options.md index 3d33cd82..27e62489 100644 --- a/docs/source/advanced_options.md +++ b/docs/source/advanced_options.md @@ -36,7 +36,7 @@ Default behavior: ```json { "reaction_iteration_depth": 5, - "wildcards": true + "wildcards": false } ``` @@ -47,7 +47,6 @@ AutoREACTER_outputs/ ```

Important: These options can change the number of generated reaction products, reaction templates, LAMMPS map files, and output locations.

---- (reaction_iteration_depth)= ## reaction_iteration_depth @@ -126,7 +125,20 @@ For glycine polymerization, the input monomer is: :align: center ``` ---- +```html + +
wildcards + false + Generates LAMMPS wildcard map sections to reduce redundant edge-template cases. + +``` + +```json +{ + "reaction_iteration_depth": 5, + "wildcards": false +} +``` (wildcards)= ## wildcards @@ -141,16 +153,22 @@ For glycine polymerization, the input monomer is: More information about REACTER wildcards can be found here: -- [Type Label Framework for Bonded Force Fields in LAMMPS](https://doi.org/10.1021/acs.jpcb.3c08419) -- [REACTER website](https://www.reacter.org/) +* [Type Label Framework for Bonded Force Fields in LAMMPS](https://doi.org/10.1021/acs.jpcb.3c08419) +* [REACTER website](https://www.reacter.org/) + +In LAMMPS bond/react, wildcards can be used for atoms in a dihedral whose atom types are allowed to vary. If one or more atoms in the dihedral are represented by wildcards, LAMMPS infers the appropriate dihedral type from the resulting atom types during the reaction. -In LAMMPS bond/react, wildcards allow LAMMPS to infer the fourth atom used for dihedral typing from the first three atoms. This is useful for reactions where the fourth atom or edge atom is allowed to vary. +When `wildcards` is enabled, AutoREACTER generates reaction templates that use wildcard atom labels in the map file where appropriate. Multiple atoms within a dihedral may be represented by wildcards. This can reduce the number of templates required for reactions in which the local atom-type environment varies. -When `wildcards` is enabled, AutoREACTER generates reaction templates that include the fourth atoms or edge atoms as wildcards in the map file. This reduces the number of templates generated for reactions where the edge environment varies. +Because wildcard support requires a relatively recent version of LAMMPS, `wildcards` is disabled by default. Users with LAMMPS 22 July 2025 or later can enable it by setting: -We highly recommend using wildcards for most reactions because it can reduce the number of generated templates and make the simulation more efficient. +```json +{ + "wildcards": true +} +``` -However, if you want to control specific reactions during the reactive simulation, you may need to use templates without wildcards. In that case, keeping explicit edge atoms can help you control specific reaction sites more directly. +Using wildcards can reduce the number of generated templates and simplify reactive simulations. However, templates without wildcards may be useful when explicit atom types are needed to control specific reactions or reaction sites. For normal vinyl reactions, AutoREACTER may need three templates without wildcards. With wildcard support enabled, the same simulation can often be performed using only two templates. @@ -172,7 +190,6 @@ The following templates are generated with wildcards enabled. :align: center ``` ---- (output_dir)= ## output_dir From f31b408a8605c0a8082360e89a3cfa539c081267 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:32:46 -0400 Subject: [PATCH 172/176] Clarify documentation wording --- docs/source/getting-started.md | 2 +- docs/source/getting_started_pip_installation.md | 2 +- docs/source/getting_started_source_installation.md | 2 +- docs/source/index.rst | 2 +- docs/source/overview.md | 2 +- docs/source/template-deduplication.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/getting-started.md b/docs/source/getting-started.md index 98fbe000..9d6d4f89 100644 --- a/docs/source/getting-started.md +++ b/docs/source/getting-started.md @@ -2,7 +2,7 @@ Choose the installation guide that matches your setup. -**Note:** Before starting, we highly recommend reviewing the **[API Reference](api_reference.md)** to understand the core functions and workflow of AutoREACTER. This will help you navigate the installation and usage process more effectively. +**Note:** Before starting, it is highly recommended to review the **[API Reference](api_reference.md)** to understand the core functions and workflow of AutoREACTER. This will help you navigate the installation and usage process more effectively. ## {doc}`Getting Started - Source Installation Guide ` diff --git a/docs/source/getting_started_pip_installation.md b/docs/source/getting_started_pip_installation.md index 2d8915bd..467e4156 100644 --- a/docs/source/getting_started_pip_installation.md +++ b/docs/source/getting_started_pip_installation.md @@ -4,7 +4,7 @@ This guide explains how to install AutoREACTER from PyPI and run your first work ## Step 1: Create a Python Virtual Environment -We recommend using a virtual environment so AutoREACTER and its dependencies do not interfere with your system Python installation. +Using a virtual environment is recommended so AutoREACTER and its dependencies do not interfere with your system Python installation. ```bash python -m venv arx_env diff --git a/docs/source/getting_started_source_installation.md b/docs/source/getting_started_source_installation.md index 6d52e786..566c6f8f 100644 --- a/docs/source/getting_started_source_installation.md +++ b/docs/source/getting_started_source_installation.md @@ -3,7 +3,7 @@ This guide will guide you through setting up your environment, installing the required dependencies, and running reaction modeling setup for REACTER. -AutoREACTER relies heavily on cheminformatics libraries like RDKit, and numeric computing libraries like Pandas, so we strongly recommend using **Conda** to manage your Python environment. +AutoREACTER relies heavily on cheminformatics libraries like RDKit, and numeric computing libraries like Pandas, so using **Conda** is strongly recommended to manage your Python environment. --- diff --git a/docs/source/index.rst b/docs/source/index.rst index ed57e738..0fa82a99 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -15,7 +15,7 @@ Welcome to the AutoREACTER documentation. AutoREACTER is a tool for automated reaction-based molecular system generation. This documentation is organized into a user guide and a developer guide. -**Note: AutoREACTER is currently under active development. APIs, configuration schemas, and core functionality may change or break without notice as we expand reaction-library and force-field support.** +**Note: AutoREACTER is currently under active development. APIs, configuration schemas, and core functionality may change or break without notice as reaction-library and force-field support expand.** User Guide ---------- diff --git a/docs/source/overview.md b/docs/source/overview.md index ef53e02d..8a21ff59 100644 --- a/docs/source/overview.md +++ b/docs/source/overview.md @@ -4,7 +4,7 @@ AutoREACTER is a Python-based toolkit for managing and automating reaction modeling in LAMMPS, for REACTER simulations. It provides a streamlined workflow for generating LAMMPS input files from simple chemical descriptions, eliminating the need for manual template preparation and atom typing. -**Note: AutoREACTER is currently in v{{ autoreacter_version }}. It is under active development, and APIs or functionality may change as we continue to expand the reaction library and force field support.** +**Note: AutoREACTER is currently in v{{ autoreacter_version }}. It is under active development, and APIs or functionality may change as the reaction library and force field support continue to expand.** ```{image} _static/Overview.png :alt: AutoREACTER workflow overview diff --git a/docs/source/template-deduplication.md b/docs/source/template-deduplication.md index 763cf75c..d17b5376 100644 --- a/docs/source/template-deduplication.md +++ b/docs/source/template-deduplication.md @@ -157,7 +157,7 @@ AutoREACTER first generates all possible reactions and then generates LAMMPS rea This deduplication step is one of the final steps in the AutoREACTER workflow. If `deduplicate_reaction_templates` is set to `false`, AutoREACTER will keep all generated templates, including duplicates. -We recommend keeping this option set to `true` so AutoREACTER only writes unique templates. +Keeping this option set to `true` is recommended so AutoREACTER only writes unique templates.

Important: If deduplicate_reaction_templates is set to false, AutoREACTER may write many redundant LAMMPS reaction templates.

From 2a30034b18410e80d18c736b878b1d01a4cc8900 Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:41:39 -0400 Subject: [PATCH 173/176] Disable wildcard parsing by default --- AutoREACTER/input_parser.py | 2 +- .../reactions_library/test_vinyl_polymers.py | 110 +++++++++++++++++- tests/unit/test_input_parser.py | 4 +- 3 files changed, 112 insertions(+), 4 deletions(-) diff --git a/AutoREACTER/input_parser.py b/AutoREACTER/input_parser.py index 5e640113..64c6ed4e 100644 --- a/AutoREACTER/input_parser.py +++ b/AutoREACTER/input_parser.py @@ -248,7 +248,7 @@ def validate_inputs(self, inputs: dict) -> SimulationSetup: wildcards = self._validate_bool_option( inputs, key="wildcards", - default=True, + default=False, aliases=[ "wildcard", "wildcards", diff --git a/tests/unit/detectors/reactions_library/test_vinyl_polymers.py b/tests/unit/detectors/reactions_library/test_vinyl_polymers.py index 30f96dfb..d926c498 100644 --- a/tests/unit/detectors/reactions_library/test_vinyl_polymers.py +++ b/tests/unit/detectors/reactions_library/test_vinyl_polymers.py @@ -10,6 +10,15 @@ INITIATION = "Vinyl Addition Polymerization Initiation" PROPAGATION = "Vinyl Addition Polymerization Propagation" + +SAME_CHAIN_TERMINATION = ( + "Vinyl Radical Coupling Termination (Same Chain)" +) + +CROSS_CHAIN_TERMINATION = ( + "Vinyl Radical Coupling Termination (Cross Chain)" +) + CO_INITIATION = "Vinyl Copolymerization Initiation" TFE_INITIATION = "Tetrafluoroethylene Initiation" TFE_PROPAGATION = "Tetrafluoroethylene Propagation" @@ -18,6 +27,8 @@ EXPECTED_REACTIONS = { INITIATION, PROPAGATION, + SAME_CHAIN_TERMINATION, + CROSS_CHAIN_TERMINATION, CO_INITIATION, TFE_INITIATION, TFE_PROPAGATION, @@ -60,7 +71,7 @@ def test_expected_active_reactions(): """ This deliberately catches accidental dictionary nesting. - All five currently enabled vinyl/TFE reactions are intended to be + All seven currently enabled vinyl/TFE reactions are intended to be top-level reaction-library entries. """ assert set(REACTIONS) == EXPECTED_REACTIONS @@ -124,6 +135,49 @@ def test_vinyl_propagation_metadata(): assert reaction["product"] == "vinyl_chain_end_radical" +def test_same_chain_termination_metadata(): + reaction = REACTIONS[SAME_CHAIN_TERMINATION] + + assert reaction["same_reactants"] is True + + assert ( + reaction["reactant_1"] + == "vinyl_chain_end_radical" + ) + + assert reaction.get("reactant_2") is None + + assert ( + reaction["product"] + == "vinyl_terminated_chain" + ) + + assert reaction["delete_atom"] is False + + +def test_cross_chain_termination_metadata(): + reaction = REACTIONS[CROSS_CHAIN_TERMINATION] + + assert reaction["same_reactants"] is False + + assert ( + reaction["reactant_1"] + == "vinyl_chain_end_radical" + ) + + assert ( + reaction["reactant_2"] + == "vinyl_chain_end_radical" + ) + + assert ( + reaction["product"] + == "vinyl_terminated_chain" + ) + + assert reaction["delete_atom"] is False + + def test_copolymerization_initiation_metadata(): reaction = REACTIONS[CO_INITIATION] @@ -224,6 +278,60 @@ def test_vinyl_propagation_retains_new_active_map_3(): assert 3 in product_maps +# ============================================================================= +# Vinyl radical coupling termination +# ============================================================================= + + +@pytest.mark.parametrize( + "name", + [ + SAME_CHAIN_TERMINATION, + CROSS_CHAIN_TERMINATION, + ], +) +def test_vinyl_termination_forms_new_1_2_bond( + name, +): + reactants, products = reaction_templates( + name + ) + + assert registry._has_bond_between_atom_maps( + reactants, + 1, + 2, + ) is False + + assert registry._has_bond_between_atom_maps( + products, + 1, + 2, + ) is True + + +@pytest.mark.parametrize( + "name", + [ + SAME_CHAIN_TERMINATION, + CROSS_CHAIN_TERMINATION, + ], +) +def test_vinyl_termination_retains_maps_1_and_2( + name, +): + _, products = reaction_templates( + name + ) + + product_maps = registry._atom_maps_in_templates( + products + ) + + assert 1 in product_maps + assert 2 in product_maps + + # ============================================================================= # Vinyl copolymerization initiation # ============================================================================= diff --git a/tests/unit/test_input_parser.py b/tests/unit/test_input_parser.py index 5ae47fa1..085a6f49 100644 --- a/tests/unit/test_input_parser.py +++ b/tests/unit/test_input_parser.py @@ -191,7 +191,7 @@ def test_simulation_setup_workflow_defaults(): assert setup.deep_search is True assert setup.loop is True assert setup.reaction_iteration_depth == 5 - assert setup.wildcards is True + assert setup.wildcards is False assert ( setup.deduplicate_reaction_templates @@ -1673,7 +1673,7 @@ def test_validate_inputs_counts_mode_end_to_end( assert result.reaction_iteration_depth == 5 assert result.deep_search is True - assert result.wildcards is True + assert result.wildcards is False assert ( result.deduplicate_reaction_templates From 771716f4eadfb23ffeae8d2aea917ff0a122d12e Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:48:39 -0400 Subject: [PATCH 174/176] Bump version to 1.0.0 --- AutoREACTER/__init__.py | 2 +- docs/source/change_log.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AutoREACTER/__init__.py b/AutoREACTER/__init__.py index 72f7c450..a8c6fd58 100644 --- a/AutoREACTER/__init__.py +++ b/AutoREACTER/__init__.py @@ -3,7 +3,7 @@ AutoREACTER is a tool for automated reaction-based molecular system generation. """ -__version__ = "0.3" +__version__ = "1.0.0" __title__ = "AutoREACTER" __author__ = "Janitha Mahanthe, Jacob Gissinger" diff --git a/docs/source/change_log.md b/docs/source/change_log.md index 09ed054c..ba84a64d 100644 --- a/docs/source/change_log.md +++ b/docs/source/change_log.md @@ -30,7 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), --- -## [0.3.0] - 2026-08-21 +## [1.0.0] - 2026-08-21 ### Added From 18b0b294b82c4dff7e783631471e1296873d28ed Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:52:33 -0400 Subject: [PATCH 175/176] Relax public API version test --- tests/unit/test_public_api.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_public_api.py b/tests/unit/test_public_api.py index 76c137ec..8873bce7 100644 --- a/tests/unit/test_public_api.py +++ b/tests/unit/test_public_api.py @@ -1,6 +1,6 @@ from pathlib import Path from types import SimpleNamespace - +from packaging.version import Version import pytest import AutoREACTER as arx @@ -122,8 +122,9 @@ def test_package_title(): assert arx.__title__ == "AutoREACTER" + def test_package_version(): - assert arx.__version__ == "0.3" + assert Version(arx.__version__) >= Version("1.0.0") def test_package_release_matches_version(): From b949ad3befbd44e6dbe31b5d5d41ab212ee388da Mon Sep 17 00:00:00 2001 From: janitha1996 <119646255+janitha-mahanthe@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:53:39 -0400 Subject: [PATCH 176/176] Update change_log.md --- docs/source/change_log.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/change_log.md b/docs/source/change_log.md index ba84a64d..34c1df9d 100644 --- a/docs/source/change_log.md +++ b/docs/source/change_log.md @@ -30,7 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), --- -## [1.0.0] - 2026-08-21 +## [1.0.0] - 2026-09-10 ### Added

jV`Tv&mFth+j}tA&y#D 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