qrunch.chemistry.embedded_atoms.embedded_atoms_selector
Active site selection based on coordination environment changes and partial charge changes during a reaction.
Classes
Extends the embedded atoms to include the complete aromatic ring whenever any ring atom is active. |
|
Selects atoms involved in the bonds whose length changes most across reaction images. |
|
Selects atoms whose coordination environment changes across reaction images. |
|
Extends the embedded atoms to include atoms within a distance threshold from any active atom. |
|
Selects atoms whose local electronic structure changes significantly across reaction images. |
|
Chemically "repairs" the active selection by connecting fragments into complete pieces. |
|
Composes primary embedded atoms selectors and extenders to identify active atoms in a reaction. |
|
Options controlling |
|
Extends the embedded atoms to include all atoms in connected fragments containing active atoms. |
|
Selects atoms in hydrogen bonds whose geometry changes most across reaction images. |
|
Extends the embedded atoms to include atoms directly bonded to any active atom in any image. |
- class AromaticRingExtender
Bases:
EmbeddedAtomsExtenderExtends the embedded atoms to include the complete aromatic ring whenever any ring atom is active.
If the current selection includes part of an aromatic ring (e.g. a benzene ring), this extender adds the remaining atoms of that ring, so that the whole conjugated ring system is embedded together. Only the ring atoms themselves are added - hydrogens and side chains attached to the ring are not included.
Aromatic rings are detected geometrically: a ring is treated as aromatic when it is planar and composed of aromatic-eligible elements (see
_detect_aromatic_rings()). This handles benzene as well as heteroaromatic rings (e.g. pyridine, furan) without needing to perceive bond orders. A ring is included if any of its atoms is active in any reaction image.- __init__(ring_sizes: tuple[int, ...] = (5, 6), planarity_tolerance: float = 0.1) None
- Parameters:
ring_sizes (tuple[int, ...])
planarity_tolerance (float)
- Return type:
None
- extend(active_indices: set[int], reaction: Reaction) set[int]
Return the atom indices completing any aromatic ring that overlaps the active set.
- Parameters:
active_indices (set[int]) – The current set of active atom indices.
reaction (Reaction) – The reaction being analyzed.
- Return type:
set[int]
- planarity_tolerance: float = 0.1
Maximum out-of-plane deviation (in Angstrom) for a ring to be considered planar/aromatic.
- class BondLengthChangeSelector
Bases:
PrimaryEmbeddedAtomsSelectorSelects atoms involved in the bonds whose length changes most across reaction images.
For each bond (taken as the union of the connectivity graphs of all images) the change in length is the spread
max - minof its length across the images. Each atom is scored by the largest change among its incident bonds, and atoms are separated into active and inactive groups either by an unsupervised clustering algorithm (Jenks natural breaks) or a user-provided threshold.This is a purely geometric selector: it is invariant to rigid-body motion and, unlike the per-atom electronic descriptor used by
ElectronicStructureChangeSelector, it detects symmetric homonuclear bond stretches (e.g. H2 dissociation). The two selectors are intended to be combined for a robust selection.- __init__(threshold: float | None = None) None
- Parameters:
threshold (float | None)
- Return type:
None
- scores(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) ndarray[tuple[Any, ...], dtype[float64]]
Score atoms by their largest incident bond-length change.
- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Not used by this selector.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Not used by this selector.
- Return type:
ndarray[tuple[Any, …], dtype[float64]]
- select(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) set[int]
Select atoms involved in the bonds whose length changes most across reaction images.
- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Not used by this selector.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Not used by this selector.
- Return type:
set[int]
- threshold: float | None = None
Optional explicit threshold (in Angstrom) for active atom selection.
When
None(default), the threshold is determined automatically using Jenks natural breaks clustering. When set, atoms whose largest incident bond-length change is at or above this value are considered active.
- class CoordinationChangeSelector
Bases:
PrimaryEmbeddedAtomsSelectorSelects atoms whose coordination environment changes across reaction images.
Builds a connectivity graph for each image using RDKit’s hybridization-aware bond determination and detects atoms whose coordination environment changes between any pair of images. The coordination environment is the sorted tuple of atomic numbers of an atom’s neighbors, so it distinguishes both changes in coordination number and changes in the types of bonded atoms (e.g., a hydrogen switching from being bonded to another hydrogen to being bonded to a carbon).
- __init__() None
- Return type:
None
- scores(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) ndarray[tuple[Any, ...], dtype[float64]]
Score atoms by whether their coordination environment changed.
- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Not used by this selector.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Not used by this selector.
- Return type:
ndarray[tuple[Any, …], dtype[float64]]
- select(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) set[int]
Select atoms whose coordination environment changed across the reaction images.
- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Not used by this selector.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Not used by this selector.
- Return type:
set[int]
- class DistanceExtender
Bases:
EmbeddedAtomsExtenderExtends the embedded atoms to include atoms within a distance threshold from any active atom.
- __init__(distance_threshold: float) None
- Parameters:
distance_threshold (float)
- Return type:
None
- distance_threshold: float
Maximum distance (in Angstrom) for inclusion.
- class ElectronicStructureChangeSelector
Bases:
PrimaryEmbeddedAtomsSelectorSelects atoms whose local electronic structure changes significantly across reaction images.
For each image the total electronic density is symmetrically (Lowdin) orthogonalized, \(D' = S^{1/2} D S^{1/2}\), and partitioned into atom-local diagonal blocks in the full AO basis. Each atom is described by the sorted eigenvalues of its block, i.e. its local Lowdin orbital occupations. Atoms are ranked by the maximum change of this descriptor across all pairs of images.
The descriptor is invariant under rigid-body translation and rotation of any fragment (an atom’s block transforms as an orthogonal similarity \(B \\to O B O^T\), leaving its eigenvalues unchanged), so spectator fragments that merely move between images score near zero. Genuine electronic rearrangements - charge transfer, changes in hybridization, polarization, or bond order that redistribute local occupation - do change the eigenvalues and are detected. This directly targets local electronic-structure change without relying on connectivity, which is handled separately by
CoordinationChangeSelector.Either an unsupervised clustering algorithm (Jenks natural breaks) or a user-provided threshold separates atoms into active and inactive groups.
Supports both restricted and unrestricted prepared data. For unrestricted calculations, the total (alpha + beta) density matrix is used.
Notes that this selector cannot detect homonuclear bond stretches (e.g. H2 dissociation) because the local occupation spectra of the two atoms remain identical.
Requires
prepared_dataandmolecular_configurationsto be provided toselect(), or they will be automatically generated using a minimal basis (STO-3G) unrestricted Hartree-Fock calculation followed by Pipek-Mezey localization.- __init__(threshold: float | None = None) None
- Parameters:
threshold (float | None)
- Return type:
None
- scores(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) ndarray[tuple[Any, ...], dtype[float64]]
Score atoms by their local electronic-structure change.
- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Sequence of prepared data (one per reaction image) from the mean-field and localization stages. Both restricted and unrestricted data are supported.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Sequence of molecular configurations (one per reaction image), providing PySCF mol and overlap matrix for the Lowdin orthogonalization.
- Return type:
ndarray[tuple[Any, …], dtype[float64]]
- select(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) set[int]
Select atoms whose local electronic structure changes significantly across reaction images.
- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Sequence of prepared data (one per reaction image) from the mean-field and localization stages. Both restricted and unrestricted data are supported.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Sequence of molecular configurations (one per reaction image), providing PySCF mol and overlap matrix for the Lowdin orthogonalization.
- Return type:
set[int]
- threshold: float | None = None
Optional explicit threshold for active atom selection.
When
None(default), the threshold is determined automatically using Jenks natural breaks clustering. When set, atoms with a change score at or above this value are considered active.
- class EmbeddedAtomsConnectionExtender
Bases:
EmbeddedAtomsExtenderChemically “repairs” the active selection by connecting fragments into complete pieces.
Electronic-structure changes are often localized on a few atoms, but wavefunction methods generally perform better on chemically complete fragments. This extender therefore adds a minimum number of backbone atoms (typically carbons) needed to link the disconnected pieces of the active selection into a single connected fragment - or into as few fragments as possible.
Atoms are connected component by component: within each connected molecule of the system, the active atoms are linked using a minimum-weight Steiner tree of the connectivity graph, which adds the fewest intermediate atoms. Active atoms sitting in genuinely different molecules (for example a solute and a hydrogen-bonded water) cannot be connected and are left in separate fragments - the extender only links what is physically bonded.
After connecting the fragments, an
AromaticRingExtenderis applied so that whenever the connecting path enters an aromatic (or conjugated planar) ring, the whole ring is included rather than cutting through it.- __init__(aromatic_ring_extender: AromaticRingExtender = AromaticRingExtender(ring_sizes=(5, 6), planarity_tolerance=0.1)) None
- Parameters:
aromatic_ring_extender (AromaticRingExtender)
- Return type:
None
- aromatic_ring_extender: AromaticRingExtender = AromaticRingExtender(ring_sizes=(5, 6), planarity_tolerance=0.1)
Applied after connecting fragments to complete any aromatic ring that is partially included.
- extend(active_indices: set[int], reaction: Reaction) set[int]
Return the backbone atoms needed to connect the active fragments (plus completed rings).
- Parameters:
active_indices (set[int]) – The current set of active atom indices.
reaction (Reaction) – The reaction being analyzed.
- Return type:
set[int]
- class EmbeddedAtomsSelector
Bases:
objectComposes primary embedded atoms selectors and extenders to identify active atoms in a reaction.
Primary selectors identify the core active atoms (e.g., atoms with changed coordination or significant charge redistribution). Extenders then expand the selection (e.g., by including nearest neighbors, atoms within a distance threshold, or entire connected fragments).
Extenders are not chained: each extender is applied to the primary selection only, never to the atoms proposed by a preceding extender. The final selection is the union of the primary selection with every extender’s proposals. As a result the ordering of
extendersdoes not affect the outcome, and an extender cannot cascade off atoms added by another extender (for example, a nearest-neighbor extender followed by a second nearest-neighbor extender does not grow the region by two bonds). To grow the embedded region past the immediate neighborhood of the primary atoms, use an extender that reaches the desired distance directly (e.g.DistanceExtender) rather than composing several short-range extenders.- __init__(primary_selectors: list[PrimaryEmbeddedAtomsSelector], extenders: list[EmbeddedAtomsExtender] | None = None, options: EmbeddedAtomsSelectorOptions | None = None) None
Initialize the EmbeddedAtomsSelector.
- Parameters:
primary_selectors (list[PrimaryEmbeddedAtomsSelector]) – One or more selectors that identify core active atoms.
extenders (list[EmbeddedAtomsExtender] | None) – Optional list of extenders applied in order to expand the selection.
options (EmbeddedAtomsSelectorOptions | None) – Optional
EmbeddedAtomsSelectorOptionscontrolling the selection, e.g. the maximum number of embedded atoms. WhenNone, default options are used.
- Return type:
None
- select_embedded_atoms(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) list[int]
Identify embedded atoms atoms by running all selectors and extenders.
The active atoms are formed by unioning each selector’s
select()indices, then applying the extenders. Only if the result exceedsmax_number_of_embedded_atomsare the selectors’scores()consulted to rank the atoms and keep the highest-scoring ones.- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Optional sequence of prepared data (one per reaction image) from the mean-field and localization stages. Required by selectors that depend on electronic structure information.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Optional sequence of molecular configurations (one per reaction image). Required by selectors that need basis set information.
- Return type:
list[int]
- static write_embedded_atoms_reaction_xyz(reaction: Reaction, embedded_atoms_indices: list[int], file_path: Path, *, comment: str = '') None
Write a reaction XYZ file containing only the specified embedded_atoms atoms.
The output file contains multiple XYZ frames (one per reaction image), which can be viewed as an animation in molecular visualization tools.
- Parameters:
reaction (Reaction) – The reaction to write.
embedded_atoms_indices (list[int]) – The atom indices to include in the output.
file_path (Path) – Path to the output XYZ file.
comment (str) – Optional comment to include in each frame’s comment line.
- Return type:
None
- class EmbeddedAtomsSelectorOptions
Bases:
DataclassPublicAPIOptions controlling
EmbeddedAtomsSelector.All fields are immutable (
frozen=True) so an instance can be safely reused.- Parameters:
max_number_of_embedded_atoms – Optional hard cap on the number of embedded atoms. When set and the selection (after extenders) exceeds it, only the highest-scoring atoms are kept. Primary atoms always outrank extender-added context atoms. Must be a positive integer when provided. (default=None)
- __init__(*, max_number_of_embedded_atoms: int | None = None) None
- Parameters:
max_number_of_embedded_atoms (int | None)
- Return type:
None
- max_number_of_embedded_atoms: int | None = None
- class FullMoleculeExtender
Bases:
EmbeddedAtomsExtenderExtends the embedded atoms to include all atoms in connected fragments containing active atoms.
This is useful for ensuring that entire molecules are included when any part of them is active, which can be important for preserving chemical context in reactions involving many small molecules, like a reaction solvated in water where only a few water molecules are directly involved but the entire solvent environment is relevant.
- __init__() None
- Return type:
None
- extend(active_indices: set[int], reaction: Reaction) set[int]
Return atom indices belonging to the same molecule as active atoms.
This assumes the reaction consist of several disconnected molecules (e.g., reactants, products, solvent molecules) and that we want to include entire molecules if any part of them is active.
- Parameters:
active_indices (set[int]) – The current set of active atom indices.
reaction (Reaction) – The reaction being analyzed.
- Return type:
set[int]
- class HydrogenBondChangeSelector
Bases:
PrimaryEmbeddedAtomsSelectorSelects atoms in hydrogen bonds whose geometry changes most across reaction images.
A hydrogen bond
D-H...Ais characterized by three atoms: a hydrogen atom, its covalently bonded heavy donorDand a nearby electronegative acceptorA(e.g. a C-H…O bond). A pair is treated as a hydrogen bond when the hydrogen-acceptor distance is at mosthydrogen_acceptor_max_distanceand the donor-hydrogen-acceptor angle is at leastminimum_angle.Each hydrogen bond is described by three geometric features - the donor-hydrogen distance, the hydrogen-acceptor distance and the donor-hydrogen-acceptor angle. The change of each feature (spread
max - minacross images) is made dimensionless viadistance_change_scaleandangle_change_scaleand combined by their Euclidean norm. Each of the three participating atoms is scored by the largest change among its incident hydrogen bonds, and atoms are separated into active and inactive groups either by an unsupervised clustering algorithm (Jenks natural breaks) or a user-provided threshold.This is a purely geometric selector detecting reactions driven by hydrogen-bond formation, breaking or rearrangement without a change in covalent connectivity.
- __init__(acceptor_atomic_numbers: tuple[int, ...] = (7, 8, 9, 15, 16, 17), hydrogen_acceptor_max_distance: float = 2.5, minimum_angle: float = 120.0, distance_change_scale: float = 0.3, angle_change_scale: float = 30.0, threshold: float | None = None) None
- Parameters:
acceptor_atomic_numbers (tuple[int, ...])
hydrogen_acceptor_max_distance (float)
minimum_angle (float)
distance_change_scale (float)
angle_change_scale (float)
threshold (float | None)
- Return type:
None
- acceptor_atomic_numbers: tuple[int, ...] = (7, 8, 9, 15, 16, 17)
N, O, F, P, S, Cl).
- Type:
Atomic numbers eligible to act as hydrogen-bond acceptors (default
- angle_change_scale: float = 30.0
Angle change (in degrees) that maps to a unit contribution in the combined score.
- distance_change_scale: float = 0.3
Distance change (in Angstrom) that maps to a unit contribution in the combined score.
- hydrogen_acceptor_max_distance: float = 2.5
Maximum hydrogen-acceptor distance (in Angstrom) for a pair to be a hydrogen bond.
- minimum_angle: float = 120.0
Minimum donor-hydrogen-acceptor angle (in degrees) for a pair to be a hydrogen bond.
- scores(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) ndarray[tuple[Any, ...], dtype[float64]]
Score atoms by their largest incident hydrogen-bond change.
- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Not used by this selector.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Not used by this selector.
- Return type:
ndarray[tuple[Any, …], dtype[float64]]
- select(reaction: Reaction, prepared_data: Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None = None, molecular_configurations: Sequence[MolecularConfiguration] | None = None) set[int]
Select atoms in the hydrogen bonds whose geometry changes most across reaction images.
- Parameters:
reaction (Reaction) – The reaction to analyze.
prepared_data (Sequence[PreparedRestrictedData] | Sequence[PreparedUnrestrictedData] | None) – Not used by this selector.
molecular_configurations (Sequence[MolecularConfiguration] | None) – Not used by this selector.
- Return type:
set[int]
- threshold: float | None = None
Optional explicit threshold for active atom selection.
When
None(default), the threshold is determined automatically using Jenks natural breaks clustering. When set, atoms whose largest incident hydrogen-bond change is at or above this value are considered active.
- class NearestNeighborExtender
Bases:
EmbeddedAtomsExtenderExtends the embedded atoms to include atoms directly bonded to any active atom in any image.
- __init__() None
- Return type:
None