moirepy.layers.Layer
Base class representing a 2D crystal lattice layer.
Wraps a Rust-backed lattice object that handles the heavy numerical work.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lv1
|
ndarray
|
First primitive lattice vector. Must lie along the x-axis,
i.e. |
required |
lv2
|
ndarray
|
Second primitive lattice vector. Must have a positive y-component
( |
required |
basis_points
|
list of tuple
|
Atom positions within the unit cell. Each element is a 3-tuple
|
required |
neighbours
|
dict
|
Nearest-neighbour displacement vectors for each atom type.
Keys are the type labels from |
required |
pbc
|
bool
|
Whether to apply periodic boundary conditions when computing
neighbours. Default is |
False
|
study_proximity
|
int
|
Number of supercell shells to include in the neighbour search.
Larger values find neighbours across more unit-cell images.
Default is |
1
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
LatticeAlreadyFinalisedError
|
If any of the lattice parameters are attempted to be reassigned after construction. |
See Also
SquareLayer, TriangularLayer, HexagonalLayer, KagomeLayer, Rhombus60Layer : Pre-built layer types for common 2D lattices.
Notes
The orientation convention (lv1 along x, lv2 with positive y)
is required by the rotation machinery. See
https://jabed-umar.github.io/MoirePy/find_theta/ for details.
Examples:
Build a custom honeycomb-like layer from scratch:
>>> import numpy as np
>>> from moirepy import Layer
>>> lv1 = np.array([1.0, 0.0])
>>> lv2 = np.array([0.5, np.sqrt(3) / 2])
>>> basis = [(0, 0, "A"), (1, 1/np.sqrt(3), "B")]
>>> nb = {
... "A": [[0, 1/np.sqrt(3)], [-0.5, -1/(2*np.sqrt(3))], [0.5, -1/(2*np.sqrt(3))]],
... "B": [[0.5, 1/(2*np.sqrt(3))], [-0.5, 1/(2*np.sqrt(3))], [0, -1/np.sqrt(3)]],
... }
>>> layer = Layer(lv1, lv2, basis, nb)
basis_points
property
writable
basis_points
list of tuple: Atom positions (x, y, type_label) within the unit cell.
basis_types
property
writable
basis_types
list of str: Ordered atom-type labels extracted from basis_points.
bigger_points
property
writable
bigger_points
np.ndarray or None: Lattice points that extend beyond the primary supercell.
Used internally to resolve periodic images during neighbour search.
None until :meth:generate_points has been called.
lv1
property
writable
lv1
np.ndarray: First primitive lattice vector [x, 0].
lv2
property
writable
lv2
np.ndarray: Second primitive lattice vector with positive y-component.
mln1
property
writable
mln1
int: Supercell repetition count along mlv1.
mln2
property
writable
mln2
int: Supercell repetition count along mlv2.
mlv1
property
writable
mlv1
np.ndarray or None: First moiré supercell vector, set by :meth:generate_points.
mlv2
property
writable
mlv2
np.ndarray or None: Second moiré supercell vector, set by :meth:generate_points.
neighbours
property
writable
neighbours
dict: Nearest-neighbour displacements keyed by atom-type label.
Returns a plain Python dict mapping each type label (str) to its
list of [dx, dy] displacement vectors. Reconstructed from the
Rust backend on every access.
pbc
property
writable
pbc
bool: Whether periodic boundary conditions are active.
point_types
property
writable
point_types
list of str: Atom-type label for each point in :attr:points.
Has the same length as :attr:points. None until
:meth:generate_points has been called.
points
property
writable
points
np.ndarray or None: Generated lattice-point coordinates, shape (N, 2).
None until :meth:generate_points has been called.
rot_m
property
writable
rot_m
np.ndarray: 2x2 rotation matrix applied to this layer.
study_proximity
property
writable
study_proximity
int: Number of supercell shells included in the neighbour search.
translation
property
writable
translation
tuple of float: Translation (tx, ty) applied after rotation.
first_nearest_neighbours
first_nearest_neighbours(points=None, types=None)
Find the first nearest neighbours for each lattice point.
For every point, returns the indices of its first-shell neighbours
as defined by the neighbours displacement dictionary supplied
at construction. The Rust backend handles type-to-ID mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
array-like of shape (N, 2)
|
Query point coordinates. Defaults to :attr: |
None
|
types
|
array-like of length N
|
Atom-type label for each query point. Defaults to
:attr: |
None
|
Returns:
| Type | Description |
|---|---|
list of list of int
|
A jagged list of length N. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
generate_points
generate_points(mlv1, mlv2, mln1=1, mln2=1)
Populate the layer with lattice points inside a moiré supercell.
The supercell is tiled mln1 x mln2 times along mlv1 and
mlv2 respectively. All basis atoms in each unit cell within that
region are added to :attr:points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mlv1
|
ndarray
|
First moiré supercell lattice vector, shape |
required |
mlv2
|
ndarray
|
Second moiré supercell lattice vector, shape |
required |
mln1
|
int
|
Number of supercell repetitions along |
1
|
mln2
|
int
|
Number of supercell repetitions along |
1
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If |
get_neighbors_within_radius
get_neighbors_within_radius(query_points, radius)
Find all lattice points within a given radius of each query point.
Searches the full generated lattice for any atom within radius
of each entry in query_points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query_points
|
array-like of shape (N, 2)
|
Coordinates of the N probe positions. |
required |
radius
|
float
|
Search radius (in the same units as the lattice vectors). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bigger_list |
list of list of int
|
|
smaller_list |
list of list of int
|
|
dist_list |
list of list of float
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Notes
The bigger/smaller split mirrors the convention used in the
Rust backend to avoid double-counting hopping terms when building
tight-binding Hamiltonians.
perform_rotation_translation
perform_rotation_translation(rot, translation=None)
Apply a rotation and optional translation to the layer.
Must be called before :meth:generate_points. The rotation is
stored internally and applied when lattice points are generated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rot
|
float
|
Rotation angle in degrees. |
required |
translation
|
array-like of length 2
|
Translation vector |
None
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If points have already been generated via :meth: |
ValueError
|
If |
plot_lattice
plot_lattice(plot_connections=True, colours=['r', 'g', 'b', 'c', 'm', 'y', 'k'])
Plot the generated lattice points, optionally with neighbour bonds.
Atom types are distinguished by colour, cycling through the
colours list in the same order as :attr:basis_points. Bond
lines are drawn with 10 % opacity so they do not obscure the sites.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plot_connections
|
bool
|
Whether to draw lines between each atom and its nearest
neighbours. Default is |
True
|
colours
|
list of str
|
Matplotlib colour strings assigned to each atom type in order.
If the list has exactly one entry, all types share that colour.
Default is |
['r', 'g', 'b', 'c', 'm', 'y', 'k']
|
Notes
This method adds artists to the current active Matplotlib axes.
Call plt.show() (or save the figure) after this method.
The axes aspect ratio is set to "equal" automatically.
Examples:
>>> import matplotlib.pyplot as plt
>>> layer = HexagonalLayer()
>>> layer.generate_points(mlv1, mlv2)
>>> layer.plot_lattice()
>>> plt.show()