nanoCAT.recipes.surface_dissociation

A recipe for dissociation specific sets of surface atoms.

Index

dissociate_surface(mol, idx[, symbol, ...])

A workflow for dissociating \((XY_{n})_{\le m}\) compounds from the surface of mol.

dissociate_bulk(mol, symbol_x[, symbol_y, ...])

A workflow for removing \(XY\)-based compounds from the bulk of mol.

row_accumulator(iterable)

Return a generator which accumulates elements along the nested elements of iterable.

API

nanoCAT.recipes.dissociate_surface(mol, idx, symbol='Cl', lig_count=1, k=4, displacement_factor=0.5, **kwargs)[source]

A workflow for dissociating \((XY_{n})_{\le m}\) compounds from the surface of mol.

The workflow consists of four distinct steps:

  1. Identify which atoms \(Y\), as specified by symbol, are located on the surface of mol.

  2. Identify which surface atoms are neighbors of \(X\), the latter being defined by idx.

  3. Identify which pairs of \(n*m\) neighboring surface atoms are furthest removed from each other. \(n\) is defined by lig_count and \(m\), if applicable, by the index along axis 1 of idx.

  4. Yield \((XY_{n})_{\le m}\) molecules constructed from mol.

Note

The indices supplied in idx will, when applicable, be sorted along its last axis.

Examples

>>> from pathlib import Path

>>> import numpy as np

>>> from scm.plams import Molecule
>>> from CAT.recipes import dissociate_surface, row_accumulator

>>> base_path = Path(...)
>>> mol = Molecule(base_path / 'mol.xyz')

# The indices of, e.g., Cs-pairs
>>> idx = np.array([
...     [1, 3],
...     [4, 5],
...     [6, 10],
...     [15, 12],
...     [99, 105],
...     [20, 4]
... ])

# Convert 1- to 0-based indices by substracting 1 from idx
>>> mol_generator = dissociate_surface(mol, idx-1, symbol='Cl', lig_count=1)

# Note: The indices in idx are (always) be sorted along axis 1
>>> iterator = zip(row_accumulator(np.sort(idx, axis=1)), mol_generator)
>>> for i, mol in iterator:
...     mol.write(base_path / f'output{i}.xyz')
Parameters:
  • mol (Molecule) – The input molecule.

  • idx (array-like, dimensions: \(\le 2\)) – An array of indices denoting to-be dissociated atoms (i.e. \(X\)); its elements will, if applicable, be sorted along the last axis. If a 2D array is provided then all elements along axis 1 will be dissociated in a cumulative manner. \(m\) is herein defined as the index along axis 1.

  • symbol (str or int) – An atomic symbol or number defining the super-set of the atoms to-be dissociated in combination with idx (i.e. \(Y\)).

  • lig_count (int) – The number of atoms specified in symbol to-be dissociated in combination with a single atom from idx (i.e. \(n\)).

  • k (int) – The number of atoms specified in symbol which are surrounding a single atom in idx. Must obey the following condition: \(k \ge 1\).

  • displacement_factor (float) –

    The smoothing factor \(n\) for constructing a convex hull; should obey \(0 <= n <= 1\). Represents the degree of displacement of all atoms with respect to a spherical surface; \(n = 1\) is a complete projection while \(n = 0\) means no displacement at all.

    A non-zero value is generally recomended here, as the herein utilized ConvexHull class requires an adequate degree of surface-convexness, lest it fails to properly identify all valid surface points.

  • **kwargs (Any) – Further keyword arguments for brute_uniform_idx().

Yields:

Molecule – Yields new \((XY_{n})_{m}\)-dissociated molecules.

See also

brute_uniform_idx()

Brute force approach to creating uniform or clustered distributions.

identify_surface()

Take a molecule and identify which atoms are located on the surface, rather than in the bulk.

identify_surface_ch()

Identify the surface of a molecule using a convex hull-based approach.

dissociate_ligand()

Remove \(XY_{n}\) from mol with the help of the MolDissociater class.

nanoCAT.recipes.dissociate_bulk(mol, symbol_x, symbol_y=None, count_x=1, count_y=1, n_pairs=1, k=4, r_max=None, mode='uniform', **kwargs)[source]

A workflow for removing \(XY\)-based compounds from the bulk of mol.

Examples

>>> from scm.plams import Molecule
>>> from CAT.recipes import dissociate_bulk

>>> mol: Molecule = ...

# Remove two PbBr2 pairs in a system where
# each lead atom is surrounded by 6 bromides
>>> mol_out1 = dissociate_bulk(
...     mol, symbol_x="Pb", symbol_y="Br", count_y=2, n_pairs=2, k=6
... )

# The same as before, expect all potential bromides are
# identified based on a radius, rather than a fixed number
>>> mol_out2 = dissociate_bulk(
...     mol, symbol_x="Pb", symbol_y="Br", count_y=2, n_pairs=2, r_max=5.0
... )

# Convert a fraction to a number of pairs
>>> f = 0.5
>>> count_x = 2
>>> symbol_x = "Pb"
>>> n_pairs = int(f * sum(at.symbol == symbol_x for at in mol) / count_x)

>>> mol_out3 = dissociate_bulk(
...     mol, symbol_x="Pb", symbol_y="Br", count_y=2, n_pairs=n_pairs, k=6
... )
Parameters:
  • mol (Molecule) – The input molecule.

  • symbol_x (str or int) – The atomic symbol or number of the central (to-be dissociated) atom(s) \(X\).

  • symbol_y (str or int, optional) – The atomic symbol or number of the surrounding (to-be dissociated) atom(s) \(Y\). If None, do not dissociate any atoms \(Y\).

  • count_x (int) – The number of central atoms \(X\) per individual to-be dissociated cluster.

  • count_y (int) – The number of surrounding atoms \(Y\) per individual to-be dissociated cluster.

  • n_pairs (int) – The number of to-be removed \(XY\) fragments.

  • k (int, optional) – The total number of \(Y\) candidates surrounding each atom \(X\). This value should be smaller than or equal to count_y. See the r_max parameter for a radius-based approach; note that both parameters are not mutually exclusive.

  • r_max (int, optional) – The radius used for searching for \(Y\) candidates surrounding each atom \(X\). See k parameter to use a fixed number of nearest neighbors; note that both parameters are not mutually exclusive.

  • mode (str) –

    How the subset of to-be removed atoms \(X\) should be generated. Accepts one of the following values:

    • "random": A random distribution.

    • "uniform": A uniform distribution; the distance between each successive atom and all previous points is maximized.

    • "cluster": A clustered distribution; the distance between each successive atom and all previous points is minmized.

Keyword Arguments:

**kwargs (Any) – Further keyword arguments for CAT.distribution.distribute_idx().

Returns:

The molecule with \(n_{\text{pair}} * XY\) fragments removed.

Return type:

Molecule

nanoCAT.recipes.row_accumulator(iterable)[source]

Return a generator which accumulates elements along the nested elements of iterable.

Examples

>>> iterable = [[1, 3],
...             [4, 5],
...             [6, 10]]

>>> for i in row_accumulator(iterable):
...     print(repr(i))
'_1'
'_1_3'
'_4'
'_4_5'
'_6'
'_6_10'
Parameters:

iterable (Iterable [Iterable [Any]]) – A nested iterable.

Yields:

str – The accumulated nested elements of iterable as strings.