Source code for stko._internal.molecular.subgroup_analysis.subgroup_analyser

import logging
from collections import abc

import numpy as np
import stk

from stko._internal.calculators.planarity_calculators import (
    PlanarityCalculator,
)
from stko._internal.utilities.utilities import vector_angle

logger = logging.getLogger(__name__)


[docs] class Subgroup: """Defines subgroup to search for and its measure of interest. .. warning:: This code is only present in the latest versions of stko that require Python 3.11! """ def _find_subgroup( self, molecule: stk.Molecule, ) -> abc.Iterable[stk.FunctionalGroup]: raise NotImplementedError def _calculate_measure( self, molecule: stk.Molecule, atom_group: stk.FunctionalGroup, ) -> float: raise NotImplementedError
[docs] def measure(self, molecule: stk.Molecule) -> list[float]: """Measure the geometrical property of interest for the subgroup. Defined in `_calculate_measure` and `_find_subgroup` private methods. Parameters: molecule: The molecule to analyse. Returns: List of measures. """ atom_groups = self._find_subgroup(molecule) return [self._calculate_measure(molecule, ag) for ag in atom_groups]
[docs] class C6Planarity(Subgroup): """Sub group measure of C6 ring planarity. .. warning:: This code is only present in the latest versions of stko that require Python 3.11! """ def _find_subgroup( self, molecule: stk.Molecule, ) -> abc.Iterable[stk.FunctionalGroup]: smarts = "[#6X3]1@[#6X3]@[#6X3]@[#6X3]@[#6X3]@[#6X3]1" with_fgs = stk.BuildingBlock.init_from_molecule( molecule=molecule, functional_groups=( stk.SmartsFunctionalGroupFactory( smarts=smarts, bonders=(), deleters=(), ), ), ) yield from with_fgs.get_functional_groups() def _calculate_measure( self, molecule: stk.Molecule, atom_group: stk.FunctionalGroup, ) -> float: atom_ids = [i.get_id() for i in atom_group.get_atoms()] # Create the calculator. pc = PlanarityCalculator() # Extract the measures. pc_results = pc.get_results( molecule, plane_atom_ids=atom_ids, deviation_atom_ids=atom_ids, ) return pc_results.get_plane_deviation()
[docs] class C5N1Planarity(C6Planarity): """Sub group measure of C5N1 ring planarity. .. warning:: This code is only present in the latest versions of stko that require Python 3.11! """ def _find_subgroup( self, molecule: stk.Molecule, ) -> abc.Iterable[stk.FunctionalGroup]: smarts = "[#6X3]1@[#7X2]@[#6X3]@[#6X3]@[#6X3]@[#6X3]1" with_fgs = stk.BuildingBlock.init_from_molecule( molecule=molecule, functional_groups=( stk.SmartsFunctionalGroupFactory( smarts=smarts, bonders=(), deleters=(), ), ), ) yield from with_fgs.get_functional_groups()
[docs] class X5Planarity(C6Planarity): """Sub group measure of five-membered ring planarity. .. warning:: This code is only present in the latest versions of stko that require Python 3.11! """ def _find_subgroup( self, molecule: stk.Molecule, ) -> abc.Iterable[stk.FunctionalGroup]: smarts = "[*]1@[*]@[*]@[*]@[*]1" with_fgs = stk.BuildingBlock.init_from_molecule( molecule=molecule, functional_groups=( stk.SmartsFunctionalGroupFactory( smarts=smarts, bonders=(), deleters=(), ), ), ) yield from with_fgs.get_functional_groups()
[docs] class AlkyneAngle(Subgroup): """Sub group measure of avg. CCC angle in C-C#C-C group. .. warning:: This code is only present in the latest versions of stko that require Python 3.11! """ def _find_subgroup( self, molecule: stk.Molecule, ) -> abc.Iterable[stk.FunctionalGroup]: smarts = "[#6][#6]#[#6][#6]" with_fgs = stk.BuildingBlock.init_from_molecule( molecule=molecule, functional_groups=( stk.SmartsFunctionalGroupFactory( smarts=smarts, bonders=(), deleters=(), ), ), ) yield from with_fgs.get_functional_groups() def _calculate_measure( self, molecule: stk.Molecule, atom_group: stk.FunctionalGroup, ) -> float: atom_ids = [i.get_id() for i in atom_group.get_atoms()] atom_positions = [ next(molecule.get_atomic_positions(atom_ids=i)) for i in atom_ids ] vector_sets = [ ( atom_positions[0] - atom_positions[1], atom_positions[2] - atom_positions[1], ), ( atom_positions[1] - atom_positions[2], atom_positions[3] - atom_positions[2], ), ] return np.average( [ np.degrees(vector_angle(vects[0], vects[1])) for vects in vector_sets ] )
[docs] class SubgroupAnalyser: """Defines the analyser of subgroup instances. .. warning:: This code is only present in the latest versions of stko that require Python 3.11! """
[docs] def calculate(self, molecule: stk.Molecule) -> dict[str, list[float]]: """Calculate the all possible fg values in molecule.""" fg_definitions: dict[str, Subgroup] = { "c6_planarity": C6Planarity(), "c5n1_planarity": C5N1Planarity(), "x5_planarity": X5Planarity(), "c#c_angle": AlkyneAngle(), } fg_results = {} for pot_fg, fg_cls in fg_definitions.items(): fg_results[pot_fg] = fg_cls.measure(molecule) return fg_results