Source code for stko._internal.molecular.decompose.decompose_moc

import logging

import numpy as np
import stk

from stko._internal.molecular.networkx.network import Network

logger = logging.getLogger(__name__)


[docs] class DecomposeMOC: """Decompose a metal-organic cage to obtain its organic building blocks. .. warning:: This code is only present in the latest versions of stko that require Python 3.11! """ def _get_connected_graphs( self, molecule: stk.Molecule, metal_atom_nos: tuple[int], ) -> list: graph = Network.init_from_molecule(molecule) graph = graph.with_deleted_elements(metal_atom_nos) return graph.get_connected_components()
[docs] def decompose( self, molecule: stk.Molecule, metal_atom_nos: tuple[int], ) -> tuple[stk.Molecule, ...]: """Decompose a MOC into ligands by deleting specific metal atoms. Parameters: molecule: The molecule to decompose. metal_atom_nos: The atomic numbers to delete. Can be a tuple of one or any element on periodic table. Returns: The ligands as distinct, connected molecules. """ connected_graphs = self._get_connected_graphs( molecule=molecule, metal_atom_nos=metal_atom_nos, ) ligands = [] for cg in connected_graphs: # Get atoms from nodes. atoms = list(cg) atom_ids = tuple(i.get_id() for i in atoms) # Sort both by atom id. atom_ids, atoms = zip( # type: ignore[assignment] *sorted(zip(atom_ids, atoms, strict=True)), strict=True ) atom_ids_map = {atom_ids[i]: i for i in range(len(atom_ids))} new_mol = stk.BuildingBlock.init( atoms=( stk.Atom( id=atom_ids_map[i.get_id()], atomic_number=i.get_atomic_number(), charge=i.get_charge(), ) for i in atoms ), bonds=( i.with_ids(id_map=atom_ids_map) for i in molecule.get_bonds() if i.get_atom1().get_id() in atom_ids and i.get_atom2().get_id() in atom_ids ), position_matrix=np.array( tuple( i for i in molecule.get_atomic_positions( atom_ids=atom_ids ) ) ), ) ligands.append(new_mol) return tuple(ligands)