Passed
Push — master ( a4dae9...10a6a8 )
by Daniel
07:04
created

amd.periodicset.PeriodicSet.__getattr__()   A

Complexity

Conditions 3

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 3
nop 2
1
"""Implements the :class:`PeriodicSet` class representing a periodic set,
2
defined by a motif and unit cell. This models a crystal with a point at the
3
center of each atom.
4
5
This is the object type yielded by the readers :class:`.io.CifReader` and
6
:class:`.io.CSDReader`. The :class:`PeriodicSet` can be passed as the first argument
7
to :func:`.calculate.AMD` or :func:`.calculate.PDD` to calculate its invariants.
8
"""
9
10
from typing import Optional
11
import numpy as np
12
13
14
class PeriodicSet:
15
    """A periodic set is the mathematical representation of a crystal by putting a
16
    single point in the center of every atom. It is defined by a basis (unit cell) 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
17
    and collection of points (motif) which repeats according to the basis.
18
19
    :class:`PeriodicSet` s are returned by the readers in the :mod:`.io` module.
20
    Instances of this object can be passed to :func:`.calculate.AMD` or
21
    :func:`.calculate.PDD` to calculate the invariant.
22
23
    Parameters
24
    ----------
25
    motif : numpy.ndarray
26
        Cartesian (orthogonal) coordinates of the motif, shape (no points, dims).
27
    cell : numpy.ndarray
28
        Cartesian (orthogonal) square array representing the unit cell, shape (dims, dims).
29
        Use :func:`.utils.cellpar_to_cell` to convert 6 cell parameters to an orthogonal square matrix.
30
    name : str, optional
31
        Name of the periodic set.
32
    asymmetric_unit : numpy.ndarray, optional
33
        Indices for the asymmetric unit, pointing to the motif.
34
    wyckoff_multiplicities : numpy.ndarray, optional
35
        Wyckoff multiplicities of each atom in the asymmetric unit
36
        (number of unique sites generated under all symmetries).
37
    types : numpy.ndarray, optional
38
        Array of atomic numbers of motif points.
39
    """
40
41
    def __init__(
0 ignored issues
show
best-practice introduced by
Too many arguments (7/5)
Loading history...
42
            self,
43
            motif: np.ndarray,
44
            cell: np.ndarray,
45
            name: Optional[str] = None,
46
            asymmetric_unit: Optional[np.ndarray] = None,
47
            wyckoff_multiplicities: Optional[np.ndarray] = None,
48
            types : Optional[np.ndarray] = None
0 ignored issues
show
Coding Style introduced by
No space allowed before :
Loading history...
49
    ):
50
51
        self.motif = motif
52
        self.cell = cell
53
        self.name = name
54
        self.asymmetric_unit = asymmetric_unit
55
        self.wyckoff_multiplicities = wyckoff_multiplicities
56
        self.types = types
57
58
    def __str__(self):
59
60
        m, dims = self.motif.shape
61
        return f"PeriodicSet({self.name}: {m} motif points in {dims} dimensions)"
62
63
    def __repr__(self):
64
        return f"PeriodicSet(name: {self.name}, cell: {self.cell}, motif shape {self.motif.shape})"
65
 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
66
    # used for debugging, checks if the motif/cell agree point for point
67
    # (disregarding order), NOT up to isometry.
68
    def __eq__(self, other):
69
70
        if self.cell.shape != other.cell.shape or self.motif.shape != other.motif.shape:
71
            return False
72
73
        if not np.allclose(self.cell, other.cell):
74
            return False
75
76
        # this is the part that'd be confused by overlapping sites
77
        # just checks every motif point in either have a neighbour in the other
78
        diffs = np.amax(np.abs(other.motif[:, None] - self.motif), axis=-1)
79
        if not np.all((np.amin(diffs, axis=0) <= 1e-6) & (np.amin(diffs, axis=-1) <= 1e-6)):
80
            return False
81
82
        return True
83
84
    def __ne__(self, other):
85
        return not self.__eq__(other)
86