ccu.structure package¶
Structure analysis functions and utilities.
This subpackage enables determination of orientation axes
(ccu.structure.axisfinder), comparison of structure graphs
(ccu.structure.comparator, ccu.structure.fingerprint),
calculation of closest distance between fragments
(:mod:ccu.structure.geometry`), structure permutation
(ccu.structure.defects ), and cell resizing
(ccu.structure.resizecell).
Submodules¶
ccu.structure.axisfinder module¶
Utilities for determining a molecule’s orientation axes.
Example
The function get_axes() returns all three orientation axes for a
given molecule.
>>> import ase
>>> from ccu.structure.axisfinder import get_axes
>>> coh = ase.Atoms("COH", positions=[[0, 0, 0], [-2, 0, 0], [-1, 0.5, 0]])
>>> get_axes(coh)
(array([1., 0., 0.]), array([0., 1., 0.]), array([0., 0., 1.]))
Example
The function find_farthest_atoms() returns the two atoms within a
molecule whose separation is the greatest. For example,
>>> import ase
>>> from ccu.structure.axisfinder import find_farthest_atoms
>>> coh = ase.Atoms("COH", positions=[[0, 0, 0], [-2, 0, 0], [-1, 0.5, 0]])
>>> find_farthest_atoms(coh)
(Atom('C', [0.0, 0.0, 0.0], index=0), Atom('O', [-2.0, 0.0, 0.0], index=1))
Example
The function find_primary_axis() returns the primary orientation axis
for a given molecule. For example,
>>> import ase
>>> from ccu.structure.axisfinder import find_primary_axis
>>> coh = ase.Atoms("COH", positions=[[0, 0, 0], [-2, 0, 0], [-1, 0.5, 0]])
>>> find_primary_axis(coh)
array([1., 0., 0.])
Example
The function find_secondary_axis() returns the primary orientation
axis for a given molecule. For example,
>>> import ase
>>> from ccu.structure.axisfinder import find_secondary_axis
>>> coh = ase.Atoms("COH", positions=[[0, 0, 0], [-2, 0, 0], [-1, 0.5, 0]])
>>> find_secondary_axis(coh)
array([0., 1., 0.])
Example
The function find_tertiary_axis() returns the primary orientation
axis for a given molecule. For example,
>>> import ase
>>> from ccu.structure.axisfinder import find_tertiary_axis
>>> coh = ase.Atoms("COH", positions=[[0, 0, 0], [-2, 0, 0], [-1, 0.5, 0]])
>>> find_tertiary_axis(coh)
array([0., 0., 1.])
- ccu.structure.axisfinder.find_farthest_atoms(molecule: Atoms, tol: float = 1e-05) tuple[Atoms][source]¶
Find the two atoms in the molecule separated by the greatest distance.
In molecules for which there are several pairs of atoms with equidistant separations, this function will return the pair of atoms with lowest indices whose separation is within a given tolerance of the largest atomic separation in the molecule. Each pair is sorted according to the index of the lowest index atom and then the index of the second atom. For example,
If atoms 0 and 1 have the same separation as atoms 2 and 3, atoms 0 and 1 will be returned since 0 < 2.
If atoms 0 and 1 have the same separation as atoms 0 and 3, atoms 0 and 1 will be returned since 1 < 3.
If atoms 1 and 2 have the same separation as atoms 0 and 4, atoms 0 and 4 will be returned since 0 < 1.
If atoms 1 and 2 have the same separation as atoms 0 and 2, atoms 0 and 2 will be returned since 0 < 1.
- Parameters:
molecule – The molecule for whom the two farthest atoms are to be determined.
tol – A float indicating the resolution (in Angstroms) between atomic distances.
- Returns:
A tuple containing the two atoms in the molecule separated by the greatest distance. The atoms are ordered by lowest index within the structure.
- ccu.structure.axisfinder.find_primary_axis(molecule: Atoms) array[source]¶
Determine the primary orientation axis of a molecule.
The primary axis is defined as the unit vector which is parallel to the direction vector between the two most distant atoms in the molecule and points from the higher index atom to the lower index atom.
- Parameters:
molecule – An
atoms.Atomsinstance representing the molecule for whom the primary axis is to be determined.- Returns:
A
numpy.arrayrepresenting a unit vector in the direction of the primary orientation axis. Note that for zero-dimensional molecules, this function will return the zero vector.
- ccu.structure.axisfinder.find_secondary_axis(molecule: Atoms, min_distance: float = 0.1) array[source]¶
Determine the secondary orientation axis of a molecule.
Let \(L\) be the line between the two farthest atoms in the molecule, let \(v\) be the vector which defines the primary axis, and let \(P\) be the position of the atom farthest from \(L\). Further, let \(w\) be the vector from \(L\) to \(P\), and let \(z\) be the component of \(w\) which is orthogonal to \(v\). The secondary axis is defined as the unit vector in the direction of \(z\).
- Parameters:
molecule – An
atoms.Atomsinstance representing the molecule for whom the secondary axis is to be determined.min_distance – A float specifying the minimum distance from the primary axis (in Angstroms) to be considered for defining the secondary axis. Defaults to 0.1.
- Returns:
A
numpy.arrayrepresenting a unit vector in the direction of the secondary orientation axis. Note that for zero- and one-dimensional molecules, this function will return the zero vector.
- ccu.structure.axisfinder.find_tertiary_axis(molecule: Atoms) array[source]¶
Determine the tertiary orientation axis of a molecule.
The tertiary orientation axis is simply the cross product of the primary and secondary orientation axes. See
find_primary_axis()andfind_secondary_axis()for information on how these axes are defined.- Parameters:
molecule – An
atoms.Atomsinstance representing the molecule for whom the tertiary axis is to be determined.- Returns:
A
numpy.arrayrepresenting a unit vector in the direction of the tertiary orientation axis. Note that if the molecule is zero- or one-dimensional, this function will return the zero vector.
- ccu.structure.axisfinder.get_axes(molecule: Atoms) tuple[array][source]¶
Determine a molecule’s three orientation axes.
The primary axis is defined as the vector between the two most distant atoms. The secondary axis is defined as the orthogonal component (to the primary axis) of the vector from the primary axis to the atom farthest from the line between the two most distant atoms. The tertiary axis is the cross product of the primary and secondary axes. The axes so defined are orthogonal. Note that if the molecule is unimolecular, all three vectors will be the zero vector, and that if the molecule is linear only the primary axis will be nonzero.
- Parameters:
molecule – An ase.Atoms instance whose axes are to be determined.
- Returns:
A tuple containing unit vectors reprsenting the three orientation axes. The first, second, and third entries are the primary, secondary, and tertiary axes, respectively. For nonlinear molecules, the axes form an orthonormal set.
ccu.structure.cli module¶
This module contains the ccu.structure package CLI logic.
ccu.structure.comparator module¶
This module defines the Comparator class.
The Comparator class can be used to determine teh similarity of two structures as follows:
>>> import ase
>>> from ccu.structure.comparator import Comparator
>>> co1 = ase.Atoms("CO", positions=[[0, 0, 0], [1, 0, 0]])
>>> co2 = ase.Atoms("CO", positions=[[0, 1, 1], [1, 1, 1]])
>>> oc = ase.Atoms("OC", positions=[[0, 0, 0], [1, 0, 0]])
>>> Comparator.check_similarity(co1, co2)
True
>>> Comparator.check_similarity(co1, oc)
False
- class ccu.structure.comparator.Comparator[source]¶
Bases:
objectAn object which compares the similarity of two structures.
- static calculate_cumulative_displacement(fingerprint1: Fingerprint, fingerprint2: Fingerprint) float[source]¶
Calculates the cumulative displacement for
fingerprint2.The cumulative displacement is calculated for
fingerprint2relative to the corresponding atomic positions infingerprint1.The cumulative displacement is defined as follows:
Note that each row in each
np.ndarrayassociated with each histogram key corresponds to a displacement vector between two atoms. With each such displacement vector in the histogram offingerprint1, we can identify a corresponding displacement vector in the histogram offingerprint2as the displacement vector associated with the same histogram key and index. We then define a difference vector as the difference between a displacement vector infingerprint1and its counterpart infingerprint2. The set of all difference vectors is defined on the basis offingerprint1. That is, if \(X\) is the set of all displacement vectors infingerprint1and \(Y\) is the set of all corresponding vectors infingerprint2, the set of all difference vectors is the set of all vectors \(x - y\) where \(x\) is a displacement vector in fingerprint1 and y is the corresponding displacement vector in \(Y\). (Note that this requires that the histogram offingerprint2must include all the keys that that of the histogram offingerprint1includes. Additionally, this requires that for each key in the histogram offingerprint1, the value infingerprint2includes at least as many displacement vectors as the value infingerprint1.) The cumulative displacement is then defined as the sum of the norms of all the difference vectors corresponding tofingerprint1andfingerprint2.- Parameters:
fingerprint1 – The
fingerprint.Fingerprintinstance used as a reference to calculate the cumulative displacement.fingerprint2 – The second
fingerprint.Fingerprintinstance used to calculate the cumulative displacement.
- Returns:
A float representing the cumulative displacement for
fingerprint2relative tofingerprint1.
- static check_similarity(structure1: Atoms, structure2: Atoms, tol: float = 0.05) bool[source]¶
Determines similarity of two structures within a given tolerance.
- Parameters:
structure1 – An
atoms.Atomsinstance representing the first structure to compare.structure2 – An
atoms.Atomsinstance representing the second structure to compare.tol – A float specifying the tolerance for the cumulative displacement for fingerprint in Angstroms. Defaults to 5e-2.
- Returns:
A bool indicating whether or not the two structures are similar within the specified tolerance.
Note
The notion of similarity here can be summarized as:
Two structures are similar if they can be superimposed via a translation operation.
- static cosort_fingerprints(fingerprints1: Iterable[Fingerprint], fingerprints2: Iterable[Fingerprint]) tuple[Fingerprint][source]¶
Determines the second fingerprints’s minimally displaced ordering.
The minimally displaced ordering of the second
Fingerprintlist relative to the first is the ordering of the second supplied iterable ofFingerprintswhich minimizes the cumulative displacement across the two iterables ofFingerprints.- Parameters:
fingerprints1 – An iterable containing
fingerprint.Fingerprintinstances.fingerprints2 – An iterable containing
fingerprintFingerprintinstances.Note that the two iterables must be of the same length and that the
:meth:`.fingerprint.Fingerprint.values` methods of all
:class:`.fingerprint.Fingerprint` instances across the two
iterables must be of the same length.
- Returns:
A tuple containing the ordering of
fingerprints2which minimizes the cumulative displacement across the two iterables ofFingerprints.
- static cosort_histograms(fingerprint1: Fingerprint, fingerprint2: Fingerprint) dict[str, ndarray][source]¶
Minimizes the cumulative displacement of atoms in each structure.
Given the first fingerprint, this method determines the ordering of the second fingerprint’s histogram which minizes the cumulative displacement of atoms in each structure.
The two supplied
Fingerprintsneed not have the same keys or the same number of entries under each key. Such cases are handled as follows:Let \(k\) be a key in both the histograms of
fingerprint1andfingerprint2. Let \(p\) be the iterable corresponding to the key \(k\) in the histogram offingerprint1, and let \(q\) be the iterable corresponding to the key \(k\) in the histogram offingerprint2.If \(len(p) > len(q)\), then \(q\) is ordered according to its match with the first \(len(q)\) elements of \(p\).
If \(len(p) <= len(q)\), then \(q\) is ordered according to the best match with \(p\) and the first \(len(p)\) elements of \(q\).
- Parameters:
fingerprint1 – The
fingerprint.Fingerprintobject to be used as a reference for each displacement in the otherFingerprintobject’s histogram.fingerprint2 – The
fingerprint.Fingerprintobject for which the optimally ordered histogram is to be determined.
- Returns:
A dict constructed from
fingerprint2._histogrammapping chemical symbols to a :class:numpy.ndarray` containing the displacement vectors to atoms with the corresponding chemical symbol. The order of the displacement vectors is such that the cumulative displacement of the displacement vectors is minimized relative to ``fingerprint1._histogram.
ccu.structure.defects module¶
Functions for creating defects within structures.
- ccu.structure.defects.permute(*, structure: Atoms, sites: Iterable[int | str] | None = None, occupancies: Iterable[tuple[str, int]] | None = None) list[Atoms][source]¶
Create permutations of a structure considering a number of sites.
- Parameters:
structure – an ase.atoms.Atoms object to permutate.
sites – an optional list of integers and strings representing the sites to permute. Integers are interpreted as structure indices. Strings are interpreted as all sites of a given element. Defaults to all the indices of the structure.
occupancies – an optional list of tuples whose first elements are strings representing chemical symbols and whose second elements are integers indicating the number of sites to fill with the given element. Empty strings can be passed to denote vacancy defects. Defaults to the occupancies of the sites defined in
sites.
Example
Permute all atoms in a structure
>>> from ase import Atoms >>> from ase.build import bulk
>>> from ccu.structure.defects import permute
>>> permuted_nios = permute(structure=bulk("NiO", "rocksalt", a=0.352) * 2)
Example
Permute all atoms in a set of sites of a structure
>>> from ase import Atoms >>> from ase.build import bulk
>>> from ccu.structure.defects import permute
>>> permuted_nios = permute( ... structure=bulk("NiO", "rocksalt", a=0.352) * 2, ... sites=[0, 1, 2], ... )
Example
Create Ni-M bimetallics
>>> from ase import Atoms >>> from ase.build import bulk
>>> from ccu.structure.defects import permute
>>> ni = bulk("Ni", "fcc", a=0.352) * 2 >>> metals = ["Co", "Cr", "Cu", "Fe", "Ti"] >>> bimetallics = [ni] >>> for metal in metal: ... for atom in ni: ... bimetallics.extend( ... permute(structure=ni, occupancies=(metal, atom.index + 1)) ... )
ccu.structure.fingerprint module¶
This module defines the Fingerprint class.
- class ccu.structure.fingerprint.Fingerprint(structure: ase.Atoms, reference: int, indices: Iterable[int] | None = None)[source]¶
Bases:
MutableMappingA set of displacement vectors relative to a particular atom.
The displacement vectors for atoms of a given chemical symbol can be accessed through the
MutableMappinginterface. For example:structure = ase.Atoms("CO", positions=[[0, 0, 0], [1, 0, 0]]) fp = Fingerprint(structure, 0, [0, 1]) fp["C"]
- Variables:
structure – The ase.Atoms instance to which the
Fingerprintinstance is related.reference – An int indicating the index of the reference atom used to construct the
Fingerprintinstance.indices – A tuple indicating the indices of the atoms within the structure used to construct the
Fingerprintinstance.
Generate a fingerprint from a structure.
- Parameters:
structure – The structure for which the
Fingerprintwill be generated.reference – The index of the reference atom within
structuretoFingerprint.indices – The indices of the atoms corresponding to the points for which the displacements will be calculated to generate the fingerprint. Defaults to None.
- classmethod from_structure(structure: ase.Atoms) list[Fingerprint][source]¶
Creates a list of Fingerprint objects from an ase.Atoms object.
- Parameters:
structure – An ase.Atoms instance representing the structure from which to create the list of
Fingerprints.- Returns:
A list of the
Fingerprintsfor each atom.
ccu.structure.geometry module¶
Geometry-related functions for atomic structures.
- ccu.structure.geometry.calculate_separation(structure1: Atoms, structure2: Atoms) float[source]¶
Calculates the separation between two Atoms instances.
The distance is defined as the smallest distance between an atom in one structure and an atom in the second structure.
- Parameters:
structure1 – An
atoms.Atomsinstance.structure2 – An
atoms.Atomsinstance.
- Returns:
A float representing the separation between the two structures.
ccu.structure.resizecell module¶
Cell resizing tools.
This script resizes the c vector of all the .traj files in the current
working directory to the specified positive number.
ccu.structure.symmetry module¶
Symmetry-related functions and classes.
This class defines the Symmetry and SymmetryOperation subclasses.
Example
>>> import ase
>>> from ccu.structure.symmetry import Rotation, RotationSymmetry
>>> rotation1 = Rotation(90, [0, 0, 1])
>>> symmetry1 = RotationSymmetry(rotation1)
>>> co = ase.Atoms("CO", positions=[[0, 0, 0], [1, 0, 0]])
>>> rotated = rotation1.transform(co)
>>> rotated.positions
array([[0.000000e+00, 0.000000e+00, 0.000000e+00],
[6.123234e-17, 1.000000e+00, 0.000000e+00]])
>>> symmetry1.check_symmetry(co)
False
>>> h2 = ase.Atoms("HH", positions=[[0, 0, 0], [1, 0, 0]])
>>> rotation2 = Rotation(180, [0, 0, 1])
>>> symmetry2 = RotationSymmetry(rotation2)
>>> symmetry2.check_symmetry(h2)
True
- class ccu.structure.symmetry.Inversion[source]¶
Bases:
SymmetryOperationAn inversion operation.
- class ccu.structure.symmetry.Rotation(angle: float, axis: Iterable[float])[source]¶
Bases:
SymmetryOperationA rotation operation.
- Variables:
angle – A float specifying a rotation angle in degrees.
axis – A numpy.array representing the axis of rotation.
Create a rotation symmetry operation.
- Parameters:
angle – The angle of rotation.
axis – The axis of rotation.
- transform(structure: Atoms) Atoms[source]¶
Rotate a structure.
This retthe given structure by the angle and about the axis specified as attributes of the Rotation object.
- Parameters:
structure – An
atoms.Atomsinstance representing structure to be rotated.- Returns:
A copy of the original
atoms.Atomsinstance rotated byRotation.angleabout the axisRotation.axis.
- class ccu.structure.symmetry.RotationSymmetry(operation: Rotation)[source]¶
Bases:
SymmetryA rotational symmetry.
Create a rotation symmetry.
- Parameters:
operation – A rotation operation.
- check_symmetry(structure: Atoms, tol: float = 0.05) bool[source]¶
Check if the symmetry belongs to the structure’s symmetry group.
- Parameters:
structure – An
atoms.Atomsinstance representing the structure whose symmetry is to be determined.tol – A float specifying the absolute tolerance for positions. Defaults to 5e-2.
- Returns:
- A bool indicating whether or not the given structure possesses
the symmetry of the
RotationSymmetryobject subject to the specified tolerance.
- class ccu.structure.symmetry.Symmetry[source]¶
Bases:
ABCAn abstract base class for molecule symmetries.
- abstract check_symmetry(structure: Atoms, tol: float) bool[source]¶
Subclasses should override this method.
- abstract property operation: SymmetryOperation¶
Subclasses should override this method.