Source code for stko._internal.molecular.topology_extractor.topology_extractor

import logging
from collections import abc

import stk

from stko._internal.molecular.networkx.network import Network
from stko._internal.molecular.topology_extractor.topology_info import (
    TopologyInfo,
)

logger = logging.getLogger(__name__)


[docs] class TopologyExtractor: """Extractor of topology definitions from a molecule. Examples: Using a SMARTS string and the :class:`stk.SmartsFunctionalGroupFactory`, you can split a molecule at any point to define a topology. .. testcode:: topology-extract import stk import stko import pathlib smarts = '[#6]~[#7]' mol = stk.BuildingBlock( smiles='C1=CC=C(C=C1)CN', # Find the functional groups uses to split the molecule. functional_groups=(stk.SmartsFunctionalGroupFactory( smarts=smarts, bonders=(), deleters=(), ), ) ) # For each functional group, we add disconnecting atom ids to two # objects for passing to extractor. broken_bonds_by_id = [] disconnectors = [] for fg in mol.get_functional_groups(): atom_ids = list(fg.get_atom_ids()) bond_c = atom_ids[0] bond_n = atom_ids[1] broken_bonds_by_id.append(sorted((bond_c, bond_n))) disconnectors.extend((bond_c, bond_n)) new_topology_graph = stko.TopologyExtractor() tg_info = new_topology_graph.extract_topology( molecule=mol, broken_bonds_by_id=broken_bonds_by_id, disconnectors=set(disconnectors), ) # Use these variables to write new topology graph like seen in # stk source code. vertex_positions = tg_info.get_vertex_positions() connectivities = tg_info.get_connectivities() edge_pairs = tg_info.get_edge_pairs() # Write molecules to file to visualise new topology graph. output_directory = pathlib.Path("output_directory") output_directory.mkdir(exist_ok=True) # Original molecule. mol.write(output_directory / "tg_cage.mol") # Underlying topology graph. tg_info.write(output_directory / "tg_info.pdb") .. testcleanup:: topology-extract import shutil shutil.rmtree('output_directory') """
[docs] def extract_topology( self, molecule: stk.Molecule, broken_bonds_by_id: abc.Iterable[tuple[int, int]], disconnectors: set[int], ) -> TopologyInfo: """Extract a toplogy defining a molecule with disconnections. Parameters: molecule: Molecule to get underlying topology of. broken_bonds_by_id: Tuples of bonds to break by atom id. disconnectors: Atom ids of disconnection points. Returns: Information of the underlying topology. """ connected_graphs = self.get_connected_graphs( molecule=molecule, atom_ids_to_disconnect=broken_bonds_by_id, ) centroids = {} connectivities = {} edge_pairs = [] for i, cg in enumerate(connected_graphs): centroids[i] = molecule.get_centroid( atom_ids=[i.get_id() for i in cg] ) disconnections = 0 for atom in cg: if atom.get_id() in disconnectors: disconnections += 1 connectivities[i] = disconnections for pair in broken_bonds_by_id: a1_g, a2_g = ( i for i, cg in enumerate(connected_graphs) if pair[0] in {atom.get_id() for atom in cg} or pair[1] in {atom.get_id() for atom in cg} ) edge_pairs.append((a1_g, a2_g)) return TopologyInfo(centroids, connectivities, edge_pairs)
[docs] def get_connected_graphs( self, molecule: stk.Molecule, atom_ids_to_disconnect: abc.Iterable[tuple[int, int]], ) -> list: graph = Network.init_from_molecule(molecule) graph = graph.with_deleted_bonds(atom_ids_to_disconnect) return graph.get_connected_components()