From c746dc306d4be0f52b5caad724442b8f1864d88f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 17:02:32 +0000 Subject: [PATCH 01/44] Bump pymatgen from 2024.6.10 to 2024.7.18 Bumps [pymatgen](https://github.com/materialsproject/pymatgen) from 2024.6.10 to 2024.7.18. - [Release notes](https://github.com/materialsproject/pymatgen/releases) - [Changelog](https://github.com/materialsproject/pymatgen/blob/master/docs/CHANGES.md) - [Commits](https://github.com/materialsproject/pymatgen/compare/v2024.6.10...v2024.7.18) --- updated-dependencies: - dependency-name: pymatgen dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 59c3a29a3..c2ece202d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ Repository = "https://github.com/pyiron/structuretoolkit" dscribe = ["dscribe==2.1.1"] grainboundary = [ "aimsgb==1.1.1", - "pymatgen==2024.6.10", + "pymatgen==2024.7.18", ] pyscal = ["pyscal3==3.2.6"] nglview = ["nglview==3.1.2"] @@ -49,7 +49,7 @@ clusters = ["scikit-learn==1.5.1"] symmetry = ["spglib==2.5.0"] surface = [ "spglib==2.5.0", - "pymatgen==2024.6.10", + "pymatgen==2024.7.18", ] phonopy = [ "phonopy==2.26.6", From d3fc5347e4144148e1154fdb06d6815dec18ba73 Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Thu, 18 Jul 2024 17:02:46 +0000 Subject: [PATCH 02/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 3e168719e..7c0dda85a 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -12,7 +12,7 @@ dependencies: - numpy =1.26.4 - phonopy =2.26.6 - plotly =5.22.0 -- pymatgen =2024.6.10 +- pymatgen =2024.7.18 - pyscal3 =3.2.6 - pyxtal =0.6.7 - scikit-learn =1.5.1 From 2a1275e0ef82c60c7583306e82c4dbf602a9e53a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 20:51:42 +0000 Subject: [PATCH 03/44] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.2 → v0.5.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.2...v0.5.4) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5452daa38..d27b7e3eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.2 + rev: v0.5.4 hooks: - id: ruff name: ruff lint From 60de26c106b8b959b06afccd890aa4c793675274 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 16:11:39 +0000 Subject: [PATCH 04/44] Bump plotly from 5.22.0 to 5.23.0 Bumps [plotly](https://github.com/plotly/plotly.py) from 5.22.0 to 5.23.0. - [Release notes](https://github.com/plotly/plotly.py/releases) - [Changelog](https://github.com/plotly/plotly.py/blob/master/CHANGELOG.md) - [Commits](https://github.com/plotly/plotly.py/compare/v5.22.0...v5.23.0) --- updated-dependencies: - dependency-name: plotly dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 59c3a29a3..e886b07ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ grainboundary = [ pyscal = ["pyscal3==3.2.6"] nglview = ["nglview==3.1.2"] matplotlib = ["matplotlib==3.9.1"] -plotly = ["plotly==5.22.0"] +plotly = ["plotly==5.23.0"] clusters = ["scikit-learn==1.5.1"] symmetry = ["spglib==2.5.0"] surface = [ From 5a9cd52732ce67bdc95657ebaf6e3a1e8f5591c0 Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Tue, 23 Jul 2024 16:11:55 +0000 Subject: [PATCH 05/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 3e168719e..e69662160 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -11,7 +11,7 @@ dependencies: - notebook - numpy =1.26.4 - phonopy =2.26.6 -- plotly =5.22.0 +- plotly =5.23.0 - pymatgen =2024.6.10 - pyscal3 =3.2.6 - pyxtal =0.6.7 From fe3a37ce50f5132eed9f07c850a9f3309e853200 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 26 Jul 2024 07:10:18 +0200 Subject: [PATCH 06/44] Update environment-lammps.yml --- .ci_support/environment-lammps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index b68d377dd..dc1384b3b 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -1,4 +1,4 @@ channels: - conda-forge dependencies: -- lammps =2024.02.07 \ No newline at end of file +- lammps =2024.06.27 From 0282ad7cf37efeb1e80c4fa6c9e92b851b51e43c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:49:26 +0000 Subject: [PATCH 07/44] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.4 → v0.5.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.4...v0.5.5) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d27b7e3eb..82cd15f5a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.4 + rev: v0.5.5 hooks: - id: ruff name: ruff lint From d2c3d91dee188caad00a1ff8e1c300c0d6b19d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Sun, 4 Aug 2024 07:09:10 +0200 Subject: [PATCH 08/44] Add docstrings and type hints using Github Co-pilot --- structuretoolkit/analyse/distance.py | 21 +- structuretoolkit/analyse/dscribe.py | 25 ++ structuretoolkit/analyse/neighbors.py | 414 ++++++++++++++++++++------ structuretoolkit/analyse/phonopy.py | 25 +- structuretoolkit/analyse/pyscal.py | 59 ++-- structuretoolkit/analyse/snap.py | 11 +- structuretoolkit/analyse/spatial.py | 91 +++++- structuretoolkit/analyse/strain.py | 116 +++++++- structuretoolkit/analyse/symmetry.py | 101 ++++++- structuretoolkit/build/sqs.py | 108 ++++++- structuretoolkit/common/helper.py | 39 ++- structuretoolkit/visualize.py | 31 +- 12 files changed, 867 insertions(+), 174 deletions(-) diff --git a/structuretoolkit/analyse/distance.py b/structuretoolkit/analyse/distance.py index 833631da8..01c694cde 100644 --- a/structuretoolkit/analyse/distance.py +++ b/structuretoolkit/analyse/distance.py @@ -10,7 +10,7 @@ def get_distances_array( p2: Optional[np.ndarray] = None, mic: bool = True, vectors: bool = False, -): +) -> np.ndarray: """ Return distance matrix of every position in p1 with every position in p2. If p2 is not set, it is assumed that distances between all @@ -19,13 +19,14 @@ def get_distances_array( returned. Args: - p1 (numpy.ndarray/list): Nx3 array of positions - p2 (numpy.ndarray/list): Nx3 array of positions - mic (bool): minimum image convention - vectors (bool): return vectors instead of distances + structure (ase.atoms.Atoms): The structure object + p1 (numpy.ndarray/list, optional): Nx3 array of positions. Defaults to None. + p2 (numpy.ndarray/list, optional): Nx3 array of positions. Defaults to None. + mic (bool, optional): Minimum image convention. Defaults to True. + vectors (bool, optional): Return vectors instead of distances. Defaults to False. + Returns: numpy.ndarray: NxN if vector=False and NxNx3 if vector=True - """ if p1 is None and p2 is not None: p1 = p2 @@ -48,16 +49,18 @@ def get_distances_array( return find_mic(structure=structure, v=diff_relative, vectors=vectors) -def find_mic(structure: Atoms, v: np.ndarray, vectors: bool = True): +def find_mic(structure: Atoms, v: np.ndarray, vectors: bool = True) -> np.ndarray: """ Find vectors following minimum image convention (mic). In principle this function does the same as ase.geometry.find_mic Args: - v (list/numpy.ndarray): 3d vector or a list/array of 3d vectors + structure (ase.atoms.Atoms): The structure object + v (numpy.ndarray/list): 3d vector or a list/array of 3d vectors vectors (bool): Whether to return vectors (distances are returned if False) - Returns: numpy.ndarray of the same shape as input with mic + Returns: + numpy.ndarray: numpy.ndarray of the same shape as input with mic """ if any(structure.pbc): v = np.einsum("ji,...j->...i", np.linalg.inv(structure.cell), v) diff --git a/structuretoolkit/analyse/dscribe.py b/structuretoolkit/analyse/dscribe.py index 34d9341b5..29cbc3131 100644 --- a/structuretoolkit/analyse/dscribe.py +++ b/structuretoolkit/analyse/dscribe.py @@ -23,6 +23,31 @@ def soap_descriptor_per_atom( only_physical_cores: bool = False, verbose: bool = False, ) -> np.ndarray: + """ + Calculates the SOAP descriptor for each atom in the given structure. + + Args: + structure (ase.atoms.Atoms): The atomic structure. + r_cut (float, optional): The cutoff radius. Defaults to None. + n_max (int, optional): The maximum number of radial basis functions. Defaults to None. + l_max (int, optional): The maximum degree of spherical harmonics. Defaults to None. + sigma (float, optional): The width parameter for the Gaussian-type orbital. Defaults to 1.0. + rbf (str, optional): The radial basis function. Defaults to "gto". + weighting (np.ndarray, optional): The weighting coefficients for the radial basis functions. Defaults to None. + average (str, optional): The type of averaging. Defaults to "off". + compression (dict, optional): The compression settings. Defaults to {"mode": "off", "species_weighting": None}. + species (list, optional): The list of chemical symbols. Defaults to None. + periodic (bool, optional): Whether the system is periodic. Defaults to True. + sparse (bool, optional): Whether to use sparse matrices. Defaults to False. + dtype (str, optional): The data type of the output. Defaults to "float64". + centers (np.ndarray, optional): The centers for the descriptor calculation. Defaults to None. + n_jobs (int, optional): The number of parallel jobs. Defaults to 1. + only_physical_cores (bool, optional): Whether to use only physical cores. Defaults to False. + verbose (bool, optional): Whether to print verbose output. Defaults to False. + + Returns: + np.ndarray: The SOAP descriptor for each atom. + """ from dscribe.descriptors import SOAP if species is None: diff --git a/structuretoolkit/analyse/neighbors.py b/structuretoolkit/analyse/neighbors.py index 353967a5d..3348211d8 100644 --- a/structuretoolkit/analyse/neighbors.py +++ b/structuretoolkit/analyse/neighbors.py @@ -4,7 +4,7 @@ import itertools import warnings -from typing import Optional +from typing import Dict, List, Optional, Tuple, Union import numpy as np from ase.atoms import Atoms @@ -56,8 +56,7 @@ class Tree: def __init__(self, ref_structure: Atoms): """ Args: - ref_structure (ase.atoms.Atoms): Reference - structure. + ref_structure (ase.atoms.Atoms): Reference structure. """ self._distances = None self._vectors = None @@ -95,7 +94,16 @@ def mode(self) -> str: if v: return k - def _set_mode(self, new_mode: str): + def _set_mode(self, new_mode: str) -> None: + """ + Set the mode of representing attributes. + + Args: + new_mode (str): The new mode to set. + + Raises: + KeyError: If the new mode is not found in the available modes. + """ if new_mode not in self._mode.keys(): raise KeyError( f"{new_mode} not found. Available modes: {', '.join(self._mode.keys())}" @@ -105,7 +113,10 @@ def _set_mode(self, new_mode: str): def __repr__(self) -> str: """ - Returns: __repr__ + Return a string representation of the Tree object. + + Returns: + str: A string representation of the Tree object. """ to_return = ( "Main attributes:\n" @@ -115,7 +126,13 @@ def __repr__(self) -> str: ) return to_return - def copy(self): + def copy(self) -> "Tree": + """ + Create a copy of the Tree object. + + Returns: + Tree: A copy of the Tree object. + """ new_neigh = Tree(self._ref_structure) new_neigh._distances = self._distances.copy() new_neigh._indices = self._indices.copy() @@ -135,7 +152,18 @@ def _reshape( value: np.ndarray, key: Optional[str] = None, ref_vector: Optional[np.ndarray] = None, - ): + ) -> np.ndarray: + """ + Reshape the given value based on the specified key and reference vector. + + Args: + value (np.ndarray): The value to reshape. + key (Optional[str]): The representation mode key. Defaults to None. + ref_vector (Optional[np.ndarray]): The reference vector. Defaults to None. + + Returns: + np.ndarray: The reshaped value. + """ if value is None: raise ValueError("Neighbors not initialized yet") if key is None: @@ -149,11 +177,22 @@ def _reshape( @property def distances(self) -> np.ndarray: - """Distances to neighboring atoms.""" + """ + Get the distances to neighboring atoms. + + Returns: + np.ndarray: The distances to neighboring atoms. + """ return self._reshape(self._distances) @property def _vecs(self) -> np.ndarray: + """ + Get the vectors to neighboring atoms. + + Returns: + np.ndarray: The vectors to neighboring atoms. + """ if self._vectors is None: self._vectors = self._get_vectors( positions=self._positions, @@ -164,17 +203,32 @@ def _vecs(self) -> np.ndarray: @property def vecs(self) -> np.ndarray: - """Vectors to neighboring atoms.""" + """ + Get the vectors to neighboring atoms. + + Returns: + np.ndarray: The vectors to neighboring atoms. + """ return self._reshape(self._vecs) @property def indices(self) -> np.ndarray: - """Indices of neighboring atoms.""" + """ + Get the indices of neighboring atoms. + + Returns: + np.ndarray: The indices of neighboring atoms. + """ return self._reshape(self._indices) @property def atom_numbers(self) -> np.ndarray: - """Indices of atoms.""" + """ + Get the indices of atoms. + + Returns: + np.ndarray: The indices of atoms. + """ n = np.zeros_like(self.filled.indices) n.T[:, :] = np.arange(len(n)) return self._reshape(n) @@ -190,13 +244,31 @@ def norm_order(self) -> int: return self._norm_order @norm_order.setter - def norm_order(self, value: int): + def norm_order(self, value: int) -> None: + """ + Set the norm order for the neighborhood search and shell recognition. + + Args: + value (int): The norm order value. + + Raises: + ValueError: If trying to change the norm_order after initialization. + """ raise ValueError( "norm_order cannot be changed after initialization. Re-initialize the Neighbor class" + " with the correct norm_order value" ) def _get_max_length(self, ref_vector: Optional[np.ndarray] = None) -> int: + """ + Get the maximum length of the reference vector. + + Args: + ref_vector (Optional[np.ndarray]): The reference vector. Defaults to None. + + Returns: + int: The maximum length of the reference vector. + """ if ref_vector is None: ref_vector = self.filled.distances if ( @@ -207,7 +279,19 @@ def _get_max_length(self, ref_vector: Optional[np.ndarray] = None) -> int: return None return max(len(dd[dd < np.inf]) for dd in ref_vector) - def _contract(self, value: np.ndarray, ref_vector: Optional[np.ndarray] = None): + def _contract( + self, value: np.ndarray, ref_vector: Optional[np.ndarray] = None + ) -> np.ndarray: + """ + Contract the given value based on the specified reference vector. + + Args: + value (np.ndarray): The value to contract. + ref_vector (Optional[np.ndarray]): The reference vector. Defaults to None. + + Returns: + np.ndarray: The contracted value. + """ if self._get_max_length(ref_vector=ref_vector) is None: return value return [ @@ -215,7 +299,16 @@ def _contract(self, value: np.ndarray, ref_vector: Optional[np.ndarray] = None): for vv, dist in zip(value, self.filled.distances) ] - def _allow_ragged_to_mode(self, new_bool: bool): + def _allow_ragged_to_mode(self, new_bool: bool) -> str: + """ + Set the representation mode based on the value of new_bool. + + Args: + new_bool (bool): The new value for the representation mode. + + Returns: + str: The updated representation mode. + """ if new_bool is None: return self.mode elif new_bool: @@ -223,18 +316,40 @@ def _allow_ragged_to_mode(self, new_bool: bool): return "filled" def _get_extended_positions(self) -> np.ndarray: + """ + Get the extended positions. + + Returns: + np.ndarray: The extended positions. + """ if self._extended_positions is None: return self._ref_structure.positions return self._extended_positions def _get_wrapped_indices(self) -> np.ndarray: + """ + Get the wrapped indices. + + Returns: + np.ndarray: The wrapped indices. + """ if self._wrapped_indices is None: return np.arange(len(self._ref_structure.positions)) return self._wrapped_indices def _get_wrapped_positions( self, positions: np.ndarray, distance_buffer: float = 1.0e-12 - ): + ) -> np.ndarray: + """ + Get the wrapped positions based on the given positions. + + Args: + positions (np.ndarray): The positions to wrap. + distance_buffer (float): The distance buffer. Defaults to 1.0e-12. + + Returns: + np.ndarray: The wrapped positions. + """ if not self.wrap_positions: return np.asarray(positions) x = np.array(positions).copy() @@ -251,7 +366,19 @@ def _get_distances_and_indices( num_neighbors: Optional[int] = None, cutoff_radius: float = np.inf, width_buffer: float = 1.2, - ): + ) -> Tuple[np.ndarray, np.ndarray]: + """ + Get the distances and indices of the neighbors for the given positions. + + Args: + positions (np.ndarray): The positions to get the neighbors for. + num_neighbors (Optional[int]): The number of neighbors to consider. Defaults to None. + cutoff_radius (float): The cutoff radius for neighbor search. Defaults to np.inf. + width_buffer (float): The width buffer for neighbor search. Defaults to 1.2. + + Returns: + Tuple[np.ndarray, np.ndarray]: The distances and indices of the neighbors. + """ num_neighbors = self._estimate_num_neighbors( num_neighbors=num_neighbors, cutoff_radius=cutoff_radius, @@ -294,8 +421,10 @@ def _get_distances_and_indices( @property def numbers_of_neighbors(self) -> int: """ - Get number of neighbors for each atom. Same number is returned if `cutoff_radius` was not - given in the initialization. + Get the number of neighbors for each atom. + + Returns: + int: The number of neighbors for each atom. Same number is returned if `cutoff_radius` was not given in the initialization. """ return np.sum(self.filled.distances < np.inf, axis=-1) @@ -307,7 +436,21 @@ def _get_vectors( distances: Optional[np.ndarray] = None, indices: Optional[np.ndarray] = None, width_buffer: float = 1.2, - ): + ) -> np.ndarray: + """ + Get the vectors of the neighbors for the given positions. + + Args: + positions (np.ndarray): The positions to get the neighbors for. + num_neighbors (Optional[int]): The number of neighbors to consider. Defaults to None. + cutoff_radius (float): The cutoff radius for neighbor search. Defaults to np.inf. + distances (Optional[np.ndarray]): The distances of the neighbors. Defaults to None. + indices (Optional[np.ndarray]): The indices of the neighbors. Defaults to None. + width_buffer (float): The width buffer for neighbor search. Defaults to 1.2. + + Returns: + np.ndarray: The vectors of the neighbors. + """ if distances is None or indices is None: distances, indices = self._get_distances_and_indices( positions=positions, @@ -330,16 +473,20 @@ def _estimate_num_neighbors( num_neighbors: Optional[int] = None, cutoff_radius: float = np.inf, width_buffer: float = 1.2, - ): + ) -> int: """ + Estimate the number of neighbors required for a given cutoff radius. Args: - num_neighbors (int): number of neighbors - width_buffer (float): width of the layer to be added to account for pbc. - cutoff_radius (float): self-explanatory + num_neighbors (Optional[int]): Number of neighbors. Defaults to None. + cutoff_radius (float): Cutoff radius. Defaults to np.inf. + width_buffer (float): Width of the layer to be added to account for PBC. Defaults to 1.2. Returns: - Number of atoms required for a given cutoff + int: Number of atoms required for the given cutoff. + + Raises: + ValueError: If num_neighbors or cutoff_radius is not specified. """ if ( @@ -370,16 +517,20 @@ def _estimate_width( num_neighbors: Optional[int] = None, cutoff_radius: float = np.inf, width_buffer: float = 1.2, - ): + ) -> float: """ + Estimate the width of the layer required for the given number of atoms. Args: - num_neighbors (int): number of neighbors - width_buffer (float): width of the layer to be added to account for pbc. - cutoff_radius (float): cutoff radius + num_neighbors (Optional[int]): Number of neighbors. Defaults to None. + cutoff_radius (float): Cutoff radius. Defaults to np.inf. + width_buffer (float): Width of the layer to be added to account for PBC. Defaults to 1.2. Returns: - Width of layer required for the given number of atoms + float: Width of layer required for the given number of atoms. + + Raises: + ValueError: If num_neighbors or cutoff_radius is not specified. """ if num_neighbors is None and cutoff_radius == np.inf: @@ -402,7 +553,7 @@ def get_neighborhood( num_neighbors: Optional[int] = None, cutoff_radius: float = np.inf, width_buffer: float = 1.2, - ): + ) -> "Tree": """ Get neighborhood information of `positions`. What it returns is in principle the same as `get_neighborhood` in `Atoms`. The only one difference is the reuse of the same Tree @@ -410,15 +561,13 @@ def get_neighborhood( structure changed in the meantime. Args: - position: Position in a box whose neighborhood information is analysed - num_neighbors (int): Number of nearest neighbors - cutoff_radius (float): Upper bound of the distance to which the search is to be done - width_buffer (float): Width of the layer to be added to account for pbc. + positions (np.ndarray): Positions in a box whose neighborhood information is analyzed. + num_neighbors (Optional[int]): Number of nearest neighbors. Defaults to None. + cutoff_radius (float): Upper bound of the distance to which the search is to be done. Defaults to np.inf. + width_buffer (float): Width of the layer to be added to account for pbc. Defaults to 1.2. Returns: - - structuretoolkit.analyse.neighbors.Tree: Neighbors instances with the neighbor indices, - distances and vectors + Tree: Neighbors instance with the neighbor indices, distances, and vectors. """ new_neigh = self.copy() @@ -437,7 +586,20 @@ def _get_neighborhood( cutoff_radius: float = np.inf, exclude_self: bool = False, width_buffer: float = 1.2, - ): + ) -> "Tree": + """ + Get the neighborhood information for the given positions. + + Args: + positions (np.ndarray): The positions to get the neighborhood for. + num_neighbors (int): The number of neighbors to consider. Defaults to 12. + cutoff_radius (float): The cutoff radius for neighbor search. Defaults to np.inf. + exclude_self (bool): Whether to exclude the position itself from the neighbors. Defaults to False. + width_buffer (float): The width buffer for neighbor search. Defaults to 1.2. + + Returns: + Tree: The Tree instance with the neighbor indices, distances, and vectors. + """ start_column = 0 if exclude_self: start_column = 1 @@ -458,7 +620,18 @@ def _get_neighborhood( self._positions = positions return self - def _check_width(self, width: float, pbc: list[bool, bool, bool]): + def _check_width(self, width: float, pbc: list[bool, bool, bool]) -> bool: + """ + Check if the width of the layer exceeds the specified value. + + Args: + width (float): The width of the layer. + pbc (list[bool, bool, bool]): The periodic boundary conditions. + + Returns: + bool: True if the width exceeds the specified value, False otherwise. + + """ if any(pbc) and np.prod(self.filled.distances.shape) > 0: if ( np.linalg.norm( @@ -556,7 +729,20 @@ def get_steinhardt_parameter( ) @staticmethod - def _get_all_possible_pairs(l: int): + def _get_all_possible_pairs(l: int) -> np.ndarray: + """ + Get all possible pairs of indices for a given number of groups. + + Args: + l (int): Number of groups. + + Returns: + np.ndarray: Array of all possible pairs of indices. + + Raises: + ValueError: If the number of groups is odd. + + """ if l % 2 != 0: raise ValueError("Pairs cannot be formed for an uneven number of groups.") all_arr = np.array(list(itertools.permutations(np.arange(l), l))) @@ -631,16 +817,23 @@ def __dir__(self): ) -class Neighbors(Tree): +class Neighbors: def __init__(self, ref_structure: Atoms, tolerance: int = 2): - super().__init__(ref_structure=ref_structure) + """ + Neighbors class for analyzing neighboring atoms in a structure. + + Args: + ref_structure (ase.Atoms): Reference structure. + tolerance (int): Tolerance for rounding distances (default: 2). + """ + self._ref_structure = ref_structure self._tolerance = tolerance self._cluster_vecs = None self._cluster_dist = None def __repr__(self): """ - Returns: __repr__ + Returns a string representation of the Neighbors object. """ to_return = super().__repr__() return to_return.replace("given positions", "each atom") @@ -651,7 +844,10 @@ def chemical_symbols(self) -> np.ndarray: Returns chemical symbols of the neighboring atoms. Undefined neighbors (i.e. if the neighbor distance is beyond the cutoff radius) are - considered as vacancies and are marked by 'v' + considered as vacancies and are marked by 'v'. + + Returns: + np.ndarray: Chemical symbols of neighboring atoms. """ chemical_symbols = np.tile(["v"], self.filled.indices.shape).astype(" np.ndarray: @property def shells(self) -> np.ndarray: """ - Returns the cell numbers of each atom according to the distances + Returns the cell numbers of each atom according to the distances. + + Returns: + np.ndarray: Shell indices. """ return self.get_local_shells(mode=self.mode) @@ -673,7 +872,7 @@ def get_local_shells( tolerance: Optional[int] = None, cluster_by_distances: bool = False, cluster_by_vecs: bool = False, - ): + ) -> np.ndarray: """ Set shell indices based on distances available to each atom. Clustering methods can be used at the same time, which will be useful at finite temperature results, but depending on how @@ -682,18 +881,16 @@ def get_local_shells( and does not execute the clustering method(-s) again. Args: - mode (str): Representation of the variable. Choose from 'filled', 'ragged' and - 'flattened'. - tolerance (int): decimals in np.round for rounding up distances + mode (str): Representation of the variable. Choose from 'filled', 'ragged' and 'flattened'. + tolerance (int): Decimals in np.round for rounding up distances. cluster_by_distances (bool): If True, `cluster_by_distances` is called first and the distances obtained from the clustered distances are used to calculate the shells. If cluster_by_vecs is True at the same - time, `cluster_by_distances` will use the clustered vectors for its clustering algorithm. For more, - see the DocString of `cluster_by_distances`. (default: False) + time, `cluster_by_distances` will use the clustered vectors for its clustering algorithm. cluster_by_vecs (bool): If True, `cluster_by_vectors` is called first and the distances obtained from - the clustered vectors are used to calculate the shells. (default: False) + the clustered vectors are used to calculate the shells. Returns: - shells (numpy.ndarray): shell indices + np.ndarray: Shell indices. """ if tolerance is None: tolerance = self._tolerance @@ -754,7 +951,7 @@ def get_global_shells( tolerance: Optional[int] = None, cluster_by_distances: bool = False, cluster_by_vecs: bool = False, - ): + ) -> np.ndarray: """ Set shell indices based on all distances available in the system instead of setting them according to the local distances (in contrast to shells defined @@ -767,16 +964,15 @@ def get_global_shells( Args: mode (str): Representation of the variable. Choose from 'filled', 'ragged' and 'flattened'. - tolerance (int): decimals in np.round for rounding up distances (default: 2) + tolerance (int): Decimals in np.round for rounding up distances. cluster_by_distances (bool): If True, `cluster_by_distances` is called first and the distances obtained from the clustered distances are used to calculate the shells. If cluster_by_vecs is True at the same - time, `cluster_by_distances` will use the clustered vectors for its clustering algorithm. For more, - see the DocString of `cluster_by_distances`. (default: False) + time, `cluster_by_distances` will use the clustered vectors for its clustering algorithm. cluster_by_vecs (bool): If True, `cluster_by_vectors` is called first and the distances obtained from - the clustered vectors are used to calculate the shells. (default: False) + the clustered vectors are used to calculate the shells. - Returns: - shells (numpy.ndarray): shell indices (cf. shells) + Returns:self.cluster_by_distances(use_vecs=cluster_by_vecs) + np.ndarray: Shell indices. """ if tolerance is None: tolerance = self._tolerance @@ -812,7 +1008,7 @@ def get_global_shells( def get_shell_matrix( self, - chemical_pair: Optional[list] = None, + chemical_pair: Optional[List[str]] = None, cluster_by_distances: bool = False, cluster_by_vecs: bool = False, ): @@ -1027,14 +1223,19 @@ def reset_clusters(self, vecs: bool = True, distances: bool = True): if distances: self._cluster_distances = None - def cluster_analysis(self, id_list: list, return_cluster_sizes: bool = False): + def cluster_analysis( + self, id_list: list, return_cluster_sizes: bool = False + ) -> Union[Dict[int, List[int]], Tuple[Dict[int, List[int]], List[int]]]: """ + Perform cluster analysis on a list of atom IDs. Args: - id_list: - return_cluster_sizes: + id_list (list): List of atom IDs to perform cluster analysis on. + return_cluster_sizes (bool): Whether to return the sizes of each cluster. Returns: + Union[Dict[int, List[int]], Tuple[Dict[int, List[int]], List[int]]]: Dictionary mapping cluster IDs to a list of atom IDs in each cluster. + If return_cluster_sizes is True, also returns a list of cluster sizes. """ self._cluster = [0] * len(self._ref_structure) @@ -1059,16 +1260,19 @@ def cluster_analysis(self, id_list: list, return_cluster_sizes: bool = False): return cluster_dict # sizes - def __probe_cluster(self, c_count: int, neighbors: list, id_list: list): + def __probe_cluster( + self, c_count: int, neighbors: List[int], id_list: List[int] + ) -> None: """ + Recursively probe the cluster and assign cluster IDs to neighbors. Args: - c_count: - neighbors: - id_list: + c_count (int): Cluster count. + neighbors (List[int]): List of neighbor IDs. + id_list (List[int]): List of atom IDs. Returns: - + None """ for nbr_id in neighbors: if self._cluster[nbr_id] == 0: @@ -1083,19 +1287,34 @@ def get_bonds( radius: float = np.inf, max_shells: Optional[int] = None, prec: float = 0.1, - ): + ) -> List[Dict[str, List[List[int]]]]: """ + Get the bonds in the structure. Args: - radius: - max_shells: - prec: minimum distance between any two clusters (if smaller considered to be single cluster) + radius (float): The maximum distance for a bond to be considered. + max_shells (int, optional): The maximum number of shells to consider for each atom. + prec (float): The minimum distance between any two clusters. If smaller, they are considered as a single cluster. Returns: - + List[Dict[str, List[List[int]]]]: A list of dictionaries, where each dictionary represents the shells around an atom. + The keys of the dictionary are the element symbols, and the values are lists of atom indices for each shell. """ - def get_cluster(dist_vec, ind_vec, prec=prec): + def get_cluster( + dist_vec: np.ndarray, ind_vec: np.ndarray, prec: float = prec + ) -> List[np.ndarray]: + """ + Get clusters from a distance vector and index vector. + + Args: + dist_vec (np.ndarray): The distance vector. + ind_vec (np.ndarray): The index vector. + prec (float): The minimum distance between any two clusters. + + Returns: + List[np.ndarray]: A list of arrays, where each array represents a cluster of indices. + """ ind_where = np.where(np.diff(dist_vec) > prec)[0] + 1 ind_vec_cl = [np.sort(group) for group in np.split(ind_vec, ind_where)] return ind_vec_cl @@ -1148,27 +1367,22 @@ def get_neighbors( width_buffer: float = 1.2, mode: str = "filled", norm_order: int = 2, -): +) -> Neighbors: """ + Get the neighbors of atoms in a structure. Args: - num_neighbors (int): number of neighbors - tolerance (int): tolerance (round decimal points) used for computing neighbor shells - id_list (list): list of atoms the neighbors are to be looked for - cutoff_radius (float): Upper bound of the distance to which the search must be done - width_buffer (float): width of the layer to be added to account for pbc. - mode (str): Representation of per-atom quantities (distances etc.). Choose from - 'filled', 'ragged' and 'flattened'. - norm_order (int): Norm to use for the neighborhood search and shell recognition. The - definition follows the conventional Lp norm (cf. - https://en.wikipedia.org/wiki/Lp_space). This is an feature and for anything - other than norm_order=2, there is no guarantee that this works flawlessly. + structure (Atoms): The structure to analyze. + num_neighbors (int): The number of neighbors to find for each atom. + tolerance (int): The tolerance (round decimal points) used for computing neighbor shells. + id_list (list): The list of atoms for which neighbors are to be found. + cutoff_radius (float): The upper bound of the distance to which the search must be done. + width_buffer (float): The width of the layer to be added to account for periodic boundary conditions. + mode (str): The representation of per-atom quantities (distances etc.). Choose from 'filled', 'ragged', and 'flattened'. + norm_order (int): The norm to use for the neighborhood search and shell recognition. Returns: - - structuretoolkit.analyse.neighbors.Neighbors: Neighbors instances with the neighbor - indices, distances and vectors - + Neighbors: An instance of the Neighbors class with the neighbor indices, distances, and vectors. """ neigh = _get_neighbors( structure=structure, @@ -1192,7 +1406,23 @@ def _get_neighbors( width_buffer: float = 1.2, get_tree: bool = False, norm_order: int = 2, -): +) -> Union[Neighbors, Tree]: + """ + Get the neighbors of atoms in a structure. + + Args: + structure (Atoms): The structure to analyze. + num_neighbors (int): The number of neighbors to find for each atom. + tolerance (int): The tolerance (round decimal points) used for computing neighbor shells. + id_list (list): The list of atoms for which neighbors are to be found. + cutoff_radius (float): The upper bound of the distance to which the search must be done. + width_buffer (float): The width of the layer to be added to account for periodic boundary conditions. + get_tree (bool): Whether to return a Tree instance instead of Neighbors. + norm_order (int): The norm to use for the neighborhood search and shell recognition. + + Returns: + Union[Neighbors, Tree]: An instance of the Neighbors class or Tree class with the neighbor indices, distances, and vectors. + """ if num_neighbors is not None and num_neighbors <= 0: raise ValueError("invalid number of neighbors") if width_buffer < 0: diff --git a/structuretoolkit/analyse/phonopy.py b/structuretoolkit/analyse/phonopy.py index 87c0e369c..d355a86af 100644 --- a/structuretoolkit/analyse/phonopy.py +++ b/structuretoolkit/analyse/phonopy.py @@ -2,6 +2,8 @@ # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. +from typing import List + import numpy as np from ase.atoms import Atoms @@ -19,18 +21,21 @@ def get_equivalent_atoms( structure: Atoms, symprec: float = 1e-5, angle_tolerance: float = -1.0 -): +) -> List[int]: """ - Args: (read phonopy.structure.spglib for more details) - symprec: - float: Symmetry search tolerance in the unit of length. - angle_tolerance: - float: Symmetry search tolerance in the unit of angle deg. - If the value is negative, an internally optimized routine - is used to judge symmetry. + Get the indices of atoms that are equivalent under symmetry operations. + + Args: + structure (Atoms): The atomic structure. + symprec (float, optional): Symmetry search tolerance in the unit of length. + angle_tolerance (float, optional): Symmetry search tolerance in the unit of angle deg. + If the value is negative, an internally optimized routine is used to judge symmetry. + + Returns: + List[int]: The indices of equivalent atoms. """ - import spglib as spg + import spglib from phonopy.structure.atoms import PhonopyAtoms positions = structure.get_scaled_positions() @@ -41,7 +46,7 @@ def get_equivalent_atoms( positions = np.reshape(np.array(positions), (natom, 3)) cell = np.reshape(np.array(cell), (3, 3)) unitcell = PhonopyAtoms(symbols=types, cell=cell, scaled_positions=positions) - ops = spg.get_symmetry( + ops = spglib.get_symmetry( cell=unitcell.totuple(), symprec=symprec, angle_tolerance=angle_tolerance ) return ops["equivalent_atoms"] diff --git a/structuretoolkit/analyse/pyscal.py b/structuretoolkit/analyse/pyscal.py index 193f1cacf..70fcdd739 100644 --- a/structuretoolkit/analyse/pyscal.py +++ b/structuretoolkit/analyse/pyscal.py @@ -2,7 +2,7 @@ # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. -from typing import Optional +from typing import Any, Dict, Optional, Tuple, Union import numpy as np from ase.atoms import Atoms @@ -25,10 +25,10 @@ def get_steinhardt_parameters( structure: Atoms, neighbor_method: str = "cutoff", cutoff: float = 0.0, - n_clusters: int = 2, + n_clusters: Optional[int] = 2, q: Optional[tuple] = None, averaged: bool = False, -): +) -> Union[Tuple[np.ndarray], Tuple[np.ndarray, np.ndarray]]: """ Calculate Steinhardts parameters @@ -42,8 +42,8 @@ def get_steinhardt_parameters( averaged (bool) : If True, calculates the averaged versions of the parameter. (Default is False.) Returns: - numpy.ndarray: (number of q's, number of atoms) shaped array of q parameters - numpy.ndarray: If `clustering=True`, an additional per-atom array of cluster ids is also returned + Tuple[numpy.ndarray]: (number of q's, number of atoms) shaped array of q parameters + Tuple[numpy.ndarray]: If `clustering=True`, an additional per-atom array of cluster ids is also returned """ sys = ase_to_pyscal(structure) q = (4, 6) if q is None else q @@ -69,11 +69,11 @@ def get_centro_symmetry_descriptors( Analyse centrosymmetry parameter Args: - structure: Atoms object - num_neighbors (int) : number of neighbors + structure (Atoms): The structure to analyze. + num_neighbors (int): Number of neighbors to consider. Default is 12. Returns: - csm (list) : list of centrosymmetry parameter + np.ndarray: Array of centrosymmetry parameters. """ sys = ase_to_pyscal(structure) return np.array(sys.calculate.centrosymmetry(nmax=num_neighbors)) @@ -81,22 +81,21 @@ def get_centro_symmetry_descriptors( def get_diamond_structure_descriptors( structure: Atoms, mode: str = "total", ovito_compatibility: bool = False -) -> np.ndarray: +) -> Union[Dict[str, int], np.ndarray]: """ Analyse diamond structure Args: - structure: Atoms object - mode ("total"/"numeric"/"str"): Controls the style and level - of detail of the output. - - total : return number of atoms belonging to each structure - - numeric : return a per atom list of numbers- 0 for unknown, + structure (Atoms): The structure to analyze. + mode (str): Controls the style and level of detail of the output. + - "total": return number of atoms belonging to each structure + - "numeric": return a per atom list of numbers- 0 for unknown, 1 fcc, 2 hcp, 3 bcc and 4 icosa - - str : return a per atom string of sructures - ovito_compatibility(bool): use ovito compatiblity mode + - "str": return a per atom string of structures + ovito_compatibility (bool): Use ovito compatibility mode. Returns: - (depends on `mode`) + Union[Dict[str, int], np.ndarray]: Depending on the `mode` parameter. """ sys = ase_to_pyscal(structure) diamond_dict = sys.analyze.diamond_structure() @@ -170,16 +169,15 @@ def get_adaptive_cna_descriptors( Args: structure (ase.atoms.Atoms): The structure to analyze. - mode ("total"/"numeric"/"str"): Controls the style and level - of detail of the output. - - total : return number of atoms belonging to each structure - - numeric : return a per atom list of numbers- 0 for unknown, + mode (str): Controls the style and level of detail of the output. + - "total": return number of atoms belonging to each structure + - "numeric": return a per atom list of numbers- 0 for unknown, 1 fcc, 2 hcp, 3 bcc and 4 icosa - - str : return a per atom string of sructures - ovito_compatibility(bool): use ovito compatiblity mode + - "str": return a per atom string of structures + ovito_compatibility (bool): Use ovito compatibility mode. Returns: - (depends on `mode`) + np.ndarray: Depending on the `mode` parameter. """ sys = ase_to_pyscal(structure) if mode not in ["total", "numeric", "str"]: @@ -223,7 +221,10 @@ def get_voronoi_volumes(structure: Atoms) -> np.ndarray: Calculate the Voronoi volume of atoms Args: - structure : (ase.atoms.Atoms): The structure to analyze. + structure (Atoms): The structure to analyze. + + Returns: + np.ndarray: Array of Voronoi volumes for each atom. """ sys = ase_to_pyscal(structure) sys.find.neighbors(method="voronoi") @@ -241,14 +242,15 @@ def find_solids( q: int = 6, right: bool = True, return_sys: bool = False, -): +) -> Union[int, Any]: """ Get the number of solids or the corresponding pyscal system. Calls necessary pyscal methods as described in https://pyscal.org/en/latest/methods/03_solidliquid.html. Args: + structure (Atoms): The structure to analyze. neighbor_method (str, optional): Method used to get neighborlist. See pyscal documentation. Defaults to "cutoff". - cutoff (int, optional): Adaptive if 0. Defaults to 0. + cutoff (float, optional): Adaptive if 0. Defaults to 0. bonds (float, optional): Number or fraction of bonds to consider atom as solid. Defaults to 0.5. threshold (float, optional): See pyscal documentation. Defaults to 0.5. avgthreshold (float, optional): See pyscal documentation. Defaults to 0.6. @@ -258,8 +260,7 @@ def find_solids( return_sys (bool, optional): Whether to return number of solid atoms or pyscal system. Defaults to False. Returns: - int: number of solids, - pyscal system: pyscal system when return_sys=True + Union[int, pyscal.system.System]: Number of solids or pyscal system when return_sys=True. """ sys = ase_to_pyscal(structure) sys.find.neighbors(method=neighbor_method, cutoff=cutoff) diff --git a/structuretoolkit/analyse/snap.py b/structuretoolkit/analyse/snap.py index dff6965a8..0259346f3 100644 --- a/structuretoolkit/analyse/snap.py +++ b/structuretoolkit/analyse/snap.py @@ -10,7 +10,7 @@ def get_per_atom_quad(linear_per_atom: np.ndarray) -> np.ndarray: """ - Calculate quadratic par-atom SNAP descriptors from the linear SNAP descriptors, by multiplying the individual + Calculate quadratic per-atom SNAP descriptors from the linear SNAP descriptors, by multiplying the individual components of the SNAP descriptors. Args: @@ -204,6 +204,15 @@ def _get_lammps_compatible_cell(cell: np.ndarray) -> np.ndarray: def _convert_mat(mat: np.ndarray) -> np.ndarray: + """ + Convert a matrix to a 1D array by taking the upper triangular elements. + + Args: + mat (np.ndarray): Input matrix + + Returns: + np.ndarray: 1D array containing the upper triangular elements of the matrix + """ mat[np.diag_indices_from(mat)] /= 2 return mat[np.triu_indices(len(mat))] diff --git a/structuretoolkit/analyse/spatial.py b/structuretoolkit/analyse/spatial.py index 22dcfcb40..2d3b4bc40 100644 --- a/structuretoolkit/analyse/spatial.py +++ b/structuretoolkit/analyse/spatial.py @@ -63,6 +63,16 @@ def get_mean_positions( def create_gridpoints( structure: Atoms, n_gridpoints_per_angstrom: int = 5 ) -> np.ndarray: + """ + Create grid points within the structure. + + Args: + structure (Atoms): The atomic structure. + n_gridpoints_per_angstrom (int): Number of grid points per angstrom. + + Returns: + np.ndarray: The grid points. + """ cell = get_vertical_length(structure=structure) n_points = (n_gridpoints_per_angstrom * cell).astype(int) positions = np.meshgrid( @@ -75,6 +85,17 @@ def create_gridpoints( def remove_too_close( positions: np.ndarray, structure: Atoms, min_distance: float = 1 ) -> np.ndarray: + """ + Remove positions that are too close to the neighboring atoms. + + Args: + positions (np.ndarray): The positions to be checked. + structure (Atoms): The atomic structure. + min_distance (float): The minimum distance allowed. + + Returns: + np.ndarray: The filtered positions. + """ neigh = get_neighborhood(structure=structure, positions=positions, num_neighbors=1) return positions[neigh.distances.flatten() > min_distance] @@ -82,6 +103,21 @@ def remove_too_close( def set_to_high_symmetry_points( positions: np.ndarray, structure: Atoms, neigh, decimals: int = 4 ) -> np.ndarray: + """ + Adjusts the positions to the nearest high symmetry points in the structure. + + Args: + positions (np.ndarray): The positions to be adjusted. + structure (Atoms): The atomic structure. + neigh: The neighborhood information. + decimals (int): The number of decimal places to round the positions. + + Returns: + np.ndarray: The adjusted positions. + + Raises: + ValueError: If high symmetry points could not be detected after 10 iterations. + """ for _ in range(10): neigh = neigh.get_neighborhood(positions) dx = np.mean(neigh.vecs, axis=-2) @@ -259,6 +295,19 @@ def __init__( def run_workflow( self, positions: Optional[np.ndarray] = None, steps: int = -1 ) -> np.ndarray: + """ + Run the workflow to obtain the interstitial positions. + + Args: + positions (numpy.ndarray, optional): Initial positions of the interstitial candidates. + If not provided, the initial positions stored in `self.initial_positions` will be used. + steps (int, optional): Number of steps to run in the workflow. If set to -1 (default), + all steps will be run. + + Returns: + numpy.ndarray: Final positions of the interstitial sites. + + """ if positions is None: positions = self.initial_positions.copy() for ii, ww in enumerate(self.workflow): @@ -279,6 +328,12 @@ def neigh(self): @property def positions(self) -> np.ndarray: + """ + Get the positions of the interstitial sites. + + Returns: + np.ndarray: Positions of the interstitial sites. + """ if self._positions is None: self._positions = self.run_workflow() self._neigh = self.neigh.get_neighborhood(self._positions) @@ -354,7 +409,27 @@ def get_interstitials( min_samples: Optional[int] = None, neigh_args: dict = {}, **kwargs, -): +) -> Interstitials: + """ + Create an instance of the Interstitials class. + + Args: + structure (Atoms): The atomic structure. + num_neighbors (int): The number of neighbors to consider. + n_gridpoints_per_angstrom (int, optional): The number of grid points per angstrom. Defaults to 5. + min_distance (float, optional): The minimum distance between interstitials. Defaults to 1. + use_voronoi (bool, optional): Whether to use Voronoi tessellation. Defaults to False. + x_eps (float, optional): The epsilon value for clustering. Defaults to 0.1. + l_values (np.ndarray, optional): The array of l values for Steinhardt parameter. Defaults to np.arange(2, 13). + q_eps (float, optional): The epsilon value for Steinhardt parameter. Defaults to 0.3. + var_ratio (float, optional): The variance ratio for clustering. Defaults to 5.0. + min_samples (Optional[int], optional): The minimum number of samples for clustering. Defaults to None. + neigh_args (dict, optional): Additional arguments for neighbor calculation. Defaults to {}. + **kwargs: Additional keyword arguments. + + Returns: + Interstitials: An instance of the Interstitials class. + """ return Interstitials( structure=structure, num_neighbors=num_neighbors, @@ -541,10 +616,22 @@ def get_voronoi_vertices( def _get_neighbors( structure: Atoms, - position_interpreter: callable, + position_interpreter: Callable, data_field: str, width_buffer: float = 10, ) -> np.ndarray: + """ + Get pairs of atom indices sharing the same Voronoi vertices/areas. + + Args: + structure (Atoms): The atomic structure. + position_interpreter (callable): The position interpreter function. + data_field (str): The data field to extract from the position interpreter. + width_buffer (float): Width of the layer to be added to account for pbc. + + Returns: + np.ndarray: Pair indices + """ positions, indices = get_extended_positions( structure=structure, width=width_buffer, return_indices=True ) diff --git a/structuretoolkit/analyse/strain.py b/structuretoolkit/analyse/strain.py index 516ac83e9..8d462f5a0 100644 --- a/structuretoolkit/analyse/strain.py +++ b/structuretoolkit/analyse/strain.py @@ -72,6 +72,14 @@ def crystal_phase(self) -> str: @property def _nullify_non_bulk(self) -> np.ndarray: + """ + Get a boolean array indicating which atoms have a different crystal structure + than the bulk. + + Returns: + np.ndarray: Boolean array indicating which atoms have a different crystal structure + than the bulk. + """ return np.array( self.structure.analyse.pyscal_cna_adaptive(mode="str") != self.crystal_phase ) @@ -79,6 +87,17 @@ def _nullify_non_bulk(self) -> np.ndarray: def _get_perpendicular_unit_vectors( self, vec: np.ndarray, vec_axis: Optional[np.ndarray] = None ) -> np.ndarray: + """ + Get the perpendicular unit vectors of the given vectors. + + Args: + vec (np.ndarray): The input vectors. + vec_axis (Optional[np.ndarray]): The axis vectors. If provided, the perpendicular + vectors will be calculated with respect to this axis. Defaults to None. + + Returns: + np.ndarray: The perpendicular unit vectors. + """ if vec_axis is not None: vec_axis = self._get_safe_unit_vectors(vec_axis) vec = np.array( @@ -90,11 +109,31 @@ def _get_perpendicular_unit_vectors( def _get_safe_unit_vectors( vectors: np.ndarray, minimum_value: float = 1.0e-8 ) -> np.ndarray: + """ + Get the unit vectors of the given vectors, ensuring their magnitude is above a minimum value. + + Args: + vectors (np.ndarray): The input vectors. + minimum_value (float): The minimum magnitude value. Defaults to 1.0e-8. + + Returns: + np.ndarray: The unit vectors. + """ v = np.linalg.norm(vectors, axis=-1) v += (v < minimum_value) * minimum_value return np.einsum("...i,...->...i", vectors, 1 / v) def _get_angle(self, v: np.ndarray, w: np.ndarray) -> np.ndarray: + """ + Calculate the angle between two vectors. + + Args: + v (np.ndarray): The first vector. + w (np.ndarray): The second vector. + + Returns: + np.ndarray: The angle between the two vectors. + """ v = self._get_safe_unit_vectors(v) w = self._get_safe_unit_vectors(w) prod = np.sum(v * w, axis=-1) @@ -109,6 +148,18 @@ def _get_rotation_from_vectors( vec_after: np.ndarray, vec_axis: Optional[np.ndarray] = None, ) -> np.ndarray: + """ + Calculate the rotation matrix that transforms the `vec_before` vectors to the `vec_after` vectors. + + Args: + vec_before (np.ndarray): The vectors before transformation. + vec_after (np.ndarray): The vectors after transformation. + vec_axis (Optional[np.ndarray]): The axis vectors. If provided, the perpendicular + vectors will be calculated with respect to this axis. Defaults to None. + + Returns: + np.ndarray: The rotation matrix. + """ v = self._get_perpendicular_unit_vectors(vec_before, vec_axis) w = self._get_perpendicular_unit_vectors(vec_after, vec_axis) if vec_axis is None: @@ -122,7 +173,12 @@ def _get_rotation_from_vectors( @property def rotations(self) -> np.ndarray: - """Rotation for each atom to find the correct pairs of coordinates.""" + """ + Rotation for each atom to find the correct pairs of coordinates. + + Returns: + np.ndarray: The rotation matrix for each atom. + """ if self._rotations is None: v = self.coords.copy()[:, 0, :] w_first = self.ref_coord[ @@ -149,6 +205,16 @@ def rotations(self) -> np.ndarray: def _get_best_match_indices( coords: np.ndarray, ref_coord: np.ndarray ) -> np.ndarray: + """ + Get the indices of the best matching coordinates in the reference coordinates. + + Args: + coords (np.ndarray): The local coordinates. + ref_coord (np.ndarray): The reference local coordinates. + + Returns: + np.ndarray: The indices of the best matching coordinates. + """ distances = np.linalg.norm( coords[:, :, None, :] - ref_coord[None, None, :, :], axis=-1 ) @@ -156,11 +222,32 @@ def _get_best_match_indices( @staticmethod def _get_majority_phase(structure: Atoms) -> np.ndarray: + """ + Get the majority crystal phase in the structure based on the common neighbor analysis (CNA) descriptors. + + Args: + structure (ase.atoms.Atoms): The structure to analyze. + + Returns: + np.ndarray: The crystal phase with the highest count. + """ cna = get_adaptive_cna_descriptors(structure=structure) return np.asarray([k for k in cna.keys()])[np.argmax([v for v in cna.values()])] @staticmethod def _get_number_of_neighbors(crystal_phase: str) -> int: + """ + Get the number of neighbors based on the crystal phase. + + Args: + crystal_phase (str): The crystal phase. + + Returns: + int: The number of neighbors. + + Raises: + ValueError: If the crystal structure is not recognized. + """ if crystal_phase == "bcc": return 8 elif crystal_phase == "fcc" or crystal_phase == "hcp": @@ -170,7 +257,12 @@ def _get_number_of_neighbors(crystal_phase: str) -> int: @property def ref_coord(self) -> np.ndarray: - """Reference local coordinates.""" + """ + Reference local coordinates. + + Returns: + np.ndarray: The reference local coordinates. + """ if self._ref_coord is None: self._ref_coord = get_neighbors( structure=self.ref_structure, num_neighbors=self.num_neighbors @@ -179,7 +271,12 @@ def ref_coord(self) -> np.ndarray: @property def coords(self) -> np.ndarray: - """Local coordinates of each atom.""" + """ + Local coordinates of each atom. + + Returns: + np.ndarray: The local coordinates of each atom. + """ if self._coords is None: self._coords = get_neighbors( structure=self.structure, num_neighbors=self.num_neighbors @@ -188,12 +285,23 @@ def coords(self) -> np.ndarray: @property def _indices(self) -> np.ndarray: + """ + Get the indices of the best matching coordinates in the reference coordinates. + + Returns: + np.ndarray: The indices of the best matching coordinates. + """ all_vecs = np.einsum("nij,nkj->nki", self.rotations, self.coords) return self._get_best_match_indices(all_vecs, self.ref_coord) @property def strain(self) -> np.ndarray: - """Strain value of each atom""" + """ + Calculate the strain value of each atom. + + Returns: + np.ndarray: The strain value of each atom. + """ Dinverse = np.einsum("ij,ik->jk", self.ref_coord, self.ref_coord) D = np.linalg.inv(Dinverse) J = np.einsum( diff --git a/structuretoolkit/analyse/symmetry.py b/structuretoolkit/analyse/symmetry.py index 773d05d5d..1b50938fa 100644 --- a/structuretoolkit/analyse/symmetry.py +++ b/structuretoolkit/analyse/symmetry.py @@ -266,6 +266,17 @@ def symmetrize_tensor(self, tensor: np.ndarray) -> np.ndarray: def _get_spglib_cell( self, use_elements: Optional[bool] = None, use_magmoms: Optional[bool] = None ) -> tuple: + """ + Get the cell information in the format required by spglib. + + Args: + use_elements (bool, optional): Whether to consider chemical elements. Defaults to None. + use_magmoms (bool, optional): Whether to consider magnetic moments. Defaults to None. + + Returns: + tuple: Tuple containing the lattice, positions, numbers, and magnetic moments (if applicable). + + """ lattice = np.array(self._structure.get_cell(), dtype="double", order="C") positions = np.array( self._structure.get_scaled_positions(wrap=False), dtype="double", order="C" @@ -297,15 +308,21 @@ def _get_spglib_cell( ) return lattice, positions, numbers - def _get_symmetry(self, symprec: float = 1e-5, angle_tolerance: float = -1.0): + def _get_symmetry( + self, symprec: float = 1e-5, angle_tolerance: float = -1.0 + ) -> dict: """ + Get the symmetry information of the structure. Args: - symprec (float): Symmetry search precision - angle_tolerance (float): Angle search tolerance + symprec (float): Symmetry search precision. + angle_tolerance (float): Angle search tolerance. Returns: + dict: Dictionary containing the symmetry information. + Raises: + SymmetryError: If the symmetry information cannot be obtained. """ sym = spglib.get_symmetry( @@ -336,14 +353,13 @@ def info(self): @property def spacegroup(self) -> dict: """ - - Args: - symprec: - angle_tolerance: + Get the space group information of the structure. Returns: + dict: Dictionary containing the space group information. - https://atztogo.github.io/spglib/python-spglib.html + Raises: + SymmetryError: If the space group information cannot be obtained. """ space_group = spglib.get_spacegroup( cell=self._get_spglib_cell(use_magmoms=False), @@ -412,6 +428,20 @@ def get_ir_reciprocal_mesh( is_shift: np.ndarray = np.zeros(3, dtype="intc"), is_time_reversal: bool = True, ) -> np.ndarray: + """ + Get the irreducible reciprocal mesh points. + + Args: + mesh (ndarray): The mesh grid. + is_shift (ndarray, optional): The shift of the mesh grid. Defaults to np.zeros(3, dtype="intc"). + is_time_reversal (bool, optional): Whether to consider time reversal symmetry. Defaults to True. + + Returns: + ndarray: The irreducible reciprocal mesh points. + + Raises: + SymmetryError: If the irreducible reciprocal mesh points cannot be obtained. + """ mesh = spglib.get_ir_reciprocal_mesh( mesh=mesh, cell=self._get_spglib_cell(), @@ -424,14 +454,36 @@ def get_ir_reciprocal_mesh( return mesh -def _get_inner_slicer(n, i): - s = [None for nn in range(n)] +def _get_inner_slicer(n: int, i: int) -> tuple: + """ + Get the inner slicer for the given dimensions. + + Args: + n (int): Total number of dimensions. + i (int): Index of the dimension to slice. + + Returns: + tuple: Inner slicer tuple. + + """ + s = [None for _ in range(n)] s[0] = slice(None) s[i] = slice(None) return tuple(s) -def _get_outer_slicer(shape, perm): +def _get_outer_slicer(shape: tuple, perm: np.ndarray) -> tuple: + """ + Get the outer slicer for the given shape and permutation. + + Args: + shape (tuple): Shape of the tensor. + perm (np.ndarray): Permutation array. + + Returns: + tuple: Outer slicer tuple. + + """ length = perm.shape[-1] s = [] n_3 = np.sum(np.asarray(shape) == length) + 1 @@ -445,7 +497,18 @@ def _get_outer_slicer(shape, perm): return tuple(s) -def _back_order(shape, length): +def _back_order(shape: tuple, length: int) -> np.ndarray: + """ + Get the back order of the shape. + + Args: + shape (tuple): Shape of the tensor. + length (int): Length of the tensor. + + Returns: + np.ndarray: Back order of the shape. + + """ order = [ii for ii, ss in enumerate(shape) if ss == length] if len(order) < 1: return np.arange(len(shape)) @@ -458,7 +521,19 @@ def _back_order(shape, length): return np.append(np.argsort(np.where([cond, ~cond])[1]) + 1, 0) -def _get_einsum_str(shape, length, omit_dots=True): +def _get_einsum_str(shape: tuple, length: int, omit_dots: bool = True) -> str: + """ + Get the einsum string for the given shape and length. + + Args: + shape (tuple): Shape of the tensor. + length (int): Length of the tensor. + omit_dots (bool, optional): Whether to omit dots in the einsum string. Defaults to True. + + Returns: + str: Einsum string. + + """ s = [string.ascii_lowercase[i] for i in range(len(shape))] s_rot = "" s_mul = "" diff --git a/structuretoolkit/build/sqs.py b/structuretoolkit/build/sqs.py index 394528816..b6a03a9ba 100644 --- a/structuretoolkit/build/sqs.py +++ b/structuretoolkit/build/sqs.py @@ -2,7 +2,7 @@ import random import warnings from multiprocessing import cpu_count -from typing import Dict, Iterable, Optional, Union +from typing import Dict, Iterable, Optional, Tuple, Union import numpy as np from ase.atoms import Atoms @@ -10,6 +10,17 @@ def chemical_formula(atoms: Atoms) -> str: + """ + Generate the chemical formula of an Atoms object. + + Args: + atoms (Atoms): The Atoms object representing the structure. + + Returns: + str: The chemical formula of the structure. + + """ + def group_symbols(): for species, same in itertools.groupby(atoms.get_chemical_symbols()): num_same = len(list(same)) @@ -19,13 +30,37 @@ def group_symbols(): def map_dict(f, d: Dict) -> Dict: + """ + Apply a function to each value in a dictionary. + + Args: + f: The function to apply. + d (Dict): The dictionary to apply the function to. + + Returns: + Dict: The dictionary with the function applied to each value. + + """ return {k: f(v) for k, v in d.items()} def mole_fractions_to_composition( mole_fractions: Dict[str, float], num_atoms: int ) -> Dict[str, int]: - # if the sum of x is less than 1 - 1/n then we are missing at least one atoms + """ + Convert mole fractions to composition. + + Args: + mole_fractions (Dict[str, float]): The mole fractions of each species. + num_atoms (int): The total number of atoms. + + Returns: + Dict[str, int]: The composition of each species. + + Raises: + ValueError: If the sum of mole fractions is not within the range (1 - 1/num_atoms, 1 + 1/num_atoms). + + """ if not (1.0 - 1 / num_atoms) < sum(mole_fractions.values()) < (1.0 + 1 / num_atoms): raise ValueError( "mole-fractions must sum up to one: {}".format(sum(mole_fractions.values())) @@ -78,8 +113,18 @@ def mole_fractions_to_composition( return composition -def remap_sro(species: Iterable[str], array: np.ndarray): - # remaps computed short-range order parameters to style of sqsgenerator=v0.0.5 +def remap_sro(species: Iterable[str], array: np.ndarray) -> Dict[str, list]: + """ + Remap computed short-range order parameters to the style of sqsgenerator=v0.0.5. + + Args: + species (Iterable[str]): The species in the structure. + array (np.ndarray): The computed short-range order parameters. + + Returns: + Dict[str, list]: The remapped short-range order parameters. + + """ species = tuple(sorted(species, key=lambda abbr: atomic_numbers[abbr])) return { "{}-{}".format(si, sj): array[:, i, j].tolist() @@ -90,14 +135,35 @@ def remap_sro(species: Iterable[str], array: np.ndarray): } -def remap_sqs_results(result): - # makes new interface compatible with old one +def remap_sqs_results( + result: Dict[str, Union[Atoms, np.ndarray]], +) -> Tuple[Atoms, Dict[str, list]]: + """ + Remap the results of SQS optimization. + + Args: + result (Dict[str, Union[Atoms, np.ndarray]]): The result of SQS optimization. + + Returns: + Tuple[Atoms, Dict[str, list]]: The remapped structure and short-range order parameters. + + """ return result["structure"], remap_sro( set(result["structure"].get_chemical_symbols()), result["parameters"] ) -def transpose(it): +def transpose(it: Iterable[Iterable]) -> Iterable[tuple]: + """ + Transpose an iterable of iterables. + + Args: + it (Iterable[Iterable]): The iterable to transpose. + + Returns: + Iterable[tuple]: The transposed iterable. + + """ return zip(*it) @@ -119,7 +185,33 @@ def sqs_structures( minimal: Optional[bool] = True, similar: Optional[bool] = True, return_statistics: Optional[bool] = False, -): +) -> Union[Atoms, Tuple[Atoms, Dict[str, list], int, float]]: + """ + Generate SQS structures. + + Args: + structure (Atoms): The initial structure. + mole_fractions (Dict[str, Union[float, int]]): The mole fractions of each species. + weights (Optional[Dict[int, float]]): The weights for each shell. + objective (Union[float, np.ndarray]): The target objective value. + iterations (Union[float, int]): The number of iterations. + output_structures (int): The number of output structures. + mode (str): The mode for selecting configurations. + num_threads (Optional[int]): The number of threads to use. + prefactors (Optional[Union[float, np.ndarray]]): The prefactors for each shell. + pair_weights (Optional[np.ndarray]): The pair weights. + rtol (Optional[float]): The relative tolerance. + atol (Optional[float]): The absolute tolerance. + which (Optional[Iterable[int]]): The indices of the shells to optimize. + shell_distances (Optional[Iterable[int]]): The distances for each shell. + minimal (Optional[bool]): Whether to minimize the objective function. + similar (Optional[bool]): Whether to generate similar structures. + return_statistics (Optional[bool]): Whether to return additional statistics. + + Returns: + Union[Atoms, Tuple[Atoms, Dict[str, list], int, float]]: The generated structures or a tuple containing the structures, short-range order parameters breakdown, number of iterations, and average cycle time. + + """ from sqsgenerator import sqs_optimize composition = mole_fractions_to_composition(mole_fractions, len(structure)) diff --git a/structuretoolkit/common/helper.py b/structuretoolkit/common/helper.py index 7d6c2ba3b..7aeb9ff3f 100644 --- a/structuretoolkit/common/helper.py +++ b/structuretoolkit/common/helper.py @@ -111,11 +111,28 @@ def get_wrapped_coordinates( def get_species_indices_dict(structure: Atoms) -> dict: - # As of Python version 3.7, dictionaries are ordered. + """ + Get a dictionary mapping element symbols to their corresponding indices in the structure. + + Args: + structure (ase.atoms.Atoms): The atomic structure. + + Returns: + dict: A dictionary mapping element symbols to their corresponding indices. + """ return {el: i for i, el in enumerate(structure.symbols.indices().keys())} def get_structure_indices(structure: Atoms) -> np.ndarray: + """ + Get the indices of the elements in the structure. + + Args: + structure (ase.atoms.Atoms): The atomic structure. + + Returns: + numpy.ndarray: The indices of the elements in the structure. + """ element_indices_dict = get_species_indices_dict(structure=structure) elements = np.array(structure.get_chemical_symbols()) indices = elements.copy() @@ -125,10 +142,30 @@ def get_structure_indices(structure: Atoms) -> np.ndarray: def select_index(structure: Atoms, element: str) -> np.ndarray: + """ + Select the indices of atoms in the structure that have a specific element. + + Args: + structure (ase.atoms.Atoms): The atomic structure. + element (str): The element symbol. + + Returns: + numpy.ndarray: The indices of atoms with the specified element. + """ return structure.symbols.indices()[element] def set_indices(structure: Atoms, indices: np.ndarray) -> Atoms: + """ + Set the indices of atoms in the structure to the specified values. + + Args: + structure (ase.atoms.Atoms): The atomic structure. + indices (numpy.ndarray): The indices of atoms to be set. + + Returns: + ase.atoms.Atoms: The modified atomic structure. + """ indices_dict = { v: k for k, v in get_species_indices_dict(structure=structure).items() } diff --git a/structuretoolkit/visualize.py b/structuretoolkit/visualize.py index 9a77c70c1..563038555 100644 --- a/structuretoolkit/visualize.py +++ b/structuretoolkit/visualize.py @@ -3,7 +3,7 @@ # Distributed under the terms of "New BSD License", see the LICENSE file. import warnings -from typing import Optional +from typing import Any, Optional import numpy as np from ase.atoms import Atoms @@ -38,7 +38,7 @@ def plot3d( scalar_field: Optional[np.ndarray] = None, scalar_start: Optional[float] = None, scalar_end: Optional[float] = None, - scalar_cmap: Optional = None, + scalar_cmap: Optional[Any] = None, vector_field: Optional[np.ndarray] = None, vector_color: Optional[np.ndarray] = None, magnetic_moments: bool = False, @@ -156,7 +156,16 @@ def plot3d( raise ValueError("plot method not recognized") -def _get_box_skeleton(cell: np.ndarray): +def _get_box_skeleton(cell: np.ndarray) -> np.ndarray: + """ + Generate the skeleton of a box defined by the unit cell. + + Args: + cell (np.ndarray): The unit cell of the structure. + + Returns: + np.ndarray: The skeleton of the box defined by the unit cell. + """ lines_dz = np.stack(np.meshgrid(*3 * [[0, 1]], indexing="ij"), axis=-1) # eight corners of a unit cube, paired as four z-axis lines @@ -167,7 +176,19 @@ def _get_box_skeleton(cell: np.ndarray): return all_lines @ cell -def _draw_box_plotly(fig, structure, px, go): +def _draw_box_plotly(fig: Any, structure: Atoms, px: Any, go: Any) -> Any: + """ + Draw the box skeleton of the atomic structure using Plotly. + + Args: + fig (go.Figure): The Plotly figure object. + structure (Atoms): The atomic structure. + px (Any): The Plotly express module. + go (Any): The Plotly graph objects module. + + Returns: + go.Figure: The updated Plotly figure object. + """ cell = get_cell(structure) data = fig.data for lines in _get_box_skeleton(cell): @@ -267,7 +288,7 @@ def _plot3d( scalar_field: Optional[np.ndarray] = None, scalar_start: Optional[float] = None, scalar_end: Optional[float] = None, - scalar_cmap: Optional = None, + scalar_cmap: Optional[Any] = None, vector_field: Optional[np.ndarray] = None, vector_color: Optional[np.ndarray] = None, magnetic_moments: bool = False, From adf6a54b21c92366675e4ce7c73656be8e99b3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Sun, 4 Aug 2024 07:11:16 +0200 Subject: [PATCH 09/44] fixes --- structuretoolkit/analyse/spatial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/structuretoolkit/analyse/spatial.py b/structuretoolkit/analyse/spatial.py index 2d3b4bc40..5dfb32dc8 100644 --- a/structuretoolkit/analyse/spatial.py +++ b/structuretoolkit/analyse/spatial.py @@ -2,7 +2,7 @@ # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. -from typing import Optional +from typing import Callable, Optional import numpy as np from ase.atoms import Atoms From 3c452f8dcedda1e04251ef38f17e3bece23599f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Sun, 4 Aug 2024 07:15:03 +0200 Subject: [PATCH 10/44] more fixes --- structuretoolkit/analyse/neighbors.py | 2 +- tests/pyiron.log | 0 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 tests/pyiron.log diff --git a/structuretoolkit/analyse/neighbors.py b/structuretoolkit/analyse/neighbors.py index 3348211d8..6d5d9e04f 100644 --- a/structuretoolkit/analyse/neighbors.py +++ b/structuretoolkit/analyse/neighbors.py @@ -817,7 +817,7 @@ def __dir__(self): ) -class Neighbors: +class Neighbors(Tree): def __init__(self, ref_structure: Atoms, tolerance: int = 2): """ Neighbors class for analyzing neighboring atoms in a structure. diff --git a/tests/pyiron.log b/tests/pyiron.log new file mode 100644 index 000000000..e69de29bb From bfcbf01984759f6117942a0dc623fbf11bf43fda Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 4 Aug 2024 07:15:49 +0200 Subject: [PATCH 11/44] Delete tests/pyiron.log --- tests/pyiron.log | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/pyiron.log diff --git a/tests/pyiron.log b/tests/pyiron.log deleted file mode 100644 index e69de29bb..000000000 From 498380d5e16d441158447ba1757550bfaeb40919 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 4 Aug 2024 07:20:32 +0200 Subject: [PATCH 12/44] Update neighbors.py --- structuretoolkit/analyse/neighbors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/structuretoolkit/analyse/neighbors.py b/structuretoolkit/analyse/neighbors.py index 6d5d9e04f..12532d902 100644 --- a/structuretoolkit/analyse/neighbors.py +++ b/structuretoolkit/analyse/neighbors.py @@ -826,7 +826,7 @@ def __init__(self, ref_structure: Atoms, tolerance: int = 2): ref_structure (ase.Atoms): Reference structure. tolerance (int): Tolerance for rounding distances (default: 2). """ - self._ref_structure = ref_structure + super().__init__(ref_structure=ref_structure) self._tolerance = tolerance self._cluster_vecs = None self._cluster_dist = None From 0d5400acd0d6ca4f97d9cde4fe6d772ed9939dea Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 4 Aug 2024 07:24:52 +0200 Subject: [PATCH 13/44] Update environment-lammps.yml --- .ci_support/environment-lammps.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index dc1384b3b..3147451eb 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -1,4 +1,5 @@ channels: - conda-forge dependencies: -- lammps =2024.06.27 +- lammps =2024.06.27=*openmpi* +- openmpi =4.1.6 From df165cdebea240e24b34d2e48059a40830378c96 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:22:38 +0000 Subject: [PATCH 14/44] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.5 → v0.5.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.5...v0.5.6) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 82cd15f5a..599886411 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.5 + rev: v0.5.6 hooks: - id: ruff name: ruff lint From a5648c378d4357a60da7210ef6bed323d562088b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 16:11:06 +0000 Subject: [PATCH 15/44] Bump pyscal3 from 3.2.6 to 3.2.7 Bumps [pyscal3](https://github.com/pyscal/pyscal3) from 3.2.6 to 3.2.7. - [Release notes](https://github.com/pyscal/pyscal3/releases) - [Commits](https://github.com/pyscal/pyscal3/compare/3.2.6...3.2.7) --- updated-dependencies: - dependency-name: pyscal3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1a4f70d4d..b3a105c2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ grainboundary = [ "aimsgb==1.1.1", "pymatgen==2024.7.18", ] -pyscal = ["pyscal3==3.2.6"] +pyscal = ["pyscal3==3.2.7"] nglview = ["nglview==3.1.2"] matplotlib = ["matplotlib==3.9.1"] plotly = ["plotly==5.23.0"] From aa54488f2c51efe6ebc9d78919a9770b02e8c61e Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Tue, 6 Aug 2024 16:11:23 +0000 Subject: [PATCH 16/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index c887bb06c..05b49f48a 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -13,7 +13,7 @@ dependencies: - phonopy =2.26.6 - plotly =5.23.0 - pymatgen =2024.7.18 -- pyscal3 =3.2.6 +- pyscal3 =3.2.7 - pyxtal =0.6.7 - scikit-learn =1.5.1 - scipy =1.14.0 From 1ea598109262d64296088b85c8a057692d842aed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:17:22 +0000 Subject: [PATCH 17/44] Bump pymatgen from 2024.7.18 to 2024.8.9 Bumps [pymatgen](https://github.com/materialsproject/pymatgen) from 2024.7.18 to 2024.8.9. - [Release notes](https://github.com/materialsproject/pymatgen/releases) - [Changelog](https://github.com/materialsproject/pymatgen/blob/master/docs/CHANGES.md) - [Commits](https://github.com/materialsproject/pymatgen/compare/v2024.7.18...v2024.8.9) --- updated-dependencies: - dependency-name: pymatgen dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b3a105c2e..e4a617b0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ Repository = "https://github.com/pyiron/structuretoolkit" dscribe = ["dscribe==2.1.1"] grainboundary = [ "aimsgb==1.1.1", - "pymatgen==2024.7.18", + "pymatgen==2024.8.9", ] pyscal = ["pyscal3==3.2.7"] nglview = ["nglview==3.1.2"] @@ -49,7 +49,7 @@ clusters = ["scikit-learn==1.5.1"] symmetry = ["spglib==2.5.0"] surface = [ "spglib==2.5.0", - "pymatgen==2024.7.18", + "pymatgen==2024.8.9", ] phonopy = [ "phonopy==2.26.6", From e186c163c75d5fbb2efd44be728a80e128d8f4f8 Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Mon, 12 Aug 2024 16:17:39 +0000 Subject: [PATCH 18/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 05b49f48a..d619c9bac 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -12,7 +12,7 @@ dependencies: - numpy =1.26.4 - phonopy =2.26.6 - plotly =5.23.0 -- pymatgen =2024.7.18 +- pymatgen =2024.8.9 - pyscal3 =3.2.7 - pyxtal =0.6.7 - scikit-learn =1.5.1 From c9a19a0c407cc233cf640df2161aeb43f92fec5c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 20:46:54 +0000 Subject: [PATCH 19/44] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.6 → v0.5.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.6...v0.5.7) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 599886411..c82a8e9b8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.6 + rev: v0.5.7 hooks: - id: ruff name: ruff lint From c37e5422eb41317c12c9619817950c4763b7318e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 16:12:04 +0000 Subject: [PATCH 20/44] Bump matplotlib from 3.9.1 to 3.9.2 Bumps [matplotlib](https://github.com/matplotlib/matplotlib) from 3.9.1 to 3.9.2. - [Release notes](https://github.com/matplotlib/matplotlib/releases) - [Commits](https://github.com/matplotlib/matplotlib/compare/v3.9.1...v3.9.2) --- updated-dependencies: - dependency-name: matplotlib dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b3a105c2e..8906bc32d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ grainboundary = [ ] pyscal = ["pyscal3==3.2.7"] nglview = ["nglview==3.1.2"] -matplotlib = ["matplotlib==3.9.1"] +matplotlib = ["matplotlib==3.9.2"] plotly = ["plotly==5.23.0"] clusters = ["scikit-learn==1.5.1"] symmetry = ["spglib==2.5.0"] From 2a6d157118e04756de0cfe7f4f4b569d2c2ca01e Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Tue, 13 Aug 2024 16:12:20 +0000 Subject: [PATCH 21/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 05b49f48a..1e5cf1e48 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -6,7 +6,7 @@ dependencies: - ase =3.23.0 - coverage - dscribe =2.1.1 -- matplotlib-base =3.9.1 +- matplotlib-base =3.9.2 - nglview =3.1.2 - notebook - numpy =1.26.4 From 91810484f7cbb92482c41079d8f481a80310c018 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:59:31 +0000 Subject: [PATCH 22/44] Bump pyxtal from 0.6.7 to 1.0.0 Bumps [pyxtal](https://github.com/qzhu2017/PyXtal) from 0.6.7 to 1.0.0. - [Release notes](https://github.com/qzhu2017/PyXtal/releases) - [Commits](https://github.com/qzhu2017/PyXtal/compare/v0.6.7...v1.0.0) --- updated-dependencies: - dependency-name: pyxtal dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e4a617b0e..3d4c7bb56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ phonopy = [ "phonopy==2.26.6", "spglib==2.5.0", ] -pyxtal = ["pyxtal==0.6.7"] +pyxtal = ["pyxtal==1.0.0"] [tool.setuptools.packages.find] include = ["structuretoolkit*"] From 508d533e67fcdc1422f4553c84fe1473aabc4b4c Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Fri, 16 Aug 2024 16:59:45 +0000 Subject: [PATCH 23/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index d619c9bac..cbe812412 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -14,7 +14,7 @@ dependencies: - plotly =5.23.0 - pymatgen =2024.8.9 - pyscal3 =3.2.7 -- pyxtal =0.6.7 +- pyxtal =1.0.0 - scikit-learn =1.5.1 - scipy =1.14.0 - spglib =2.5.0 From 7151517b20fdb7f8bad56590c4b920aa900f6db1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 17:04:54 +0000 Subject: [PATCH 24/44] Bump pyxtal from 1.0.0 to 1.0.2 Bumps [pyxtal](https://github.com/MaterSim/PyXtal) from 1.0.0 to 1.0.2. - [Release notes](https://github.com/MaterSim/PyXtal/releases) - [Commits](https://github.com/MaterSim/PyXtal/compare/v1.0.0...v1.0.2) --- updated-dependencies: - dependency-name: pyxtal dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b5ad064b4..310606d12 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ phonopy = [ "phonopy==2.26.6", "spglib==2.5.0", ] -pyxtal = ["pyxtal==1.0.0"] +pyxtal = ["pyxtal==1.0.2"] [tool.setuptools.packages.find] include = ["structuretoolkit*"] From 0ba505c79558d8246288737312998707b227c6a7 Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Mon, 19 Aug 2024 17:05:10 +0000 Subject: [PATCH 25/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index c3c56b09d..926420547 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -14,7 +14,7 @@ dependencies: - plotly =5.23.0 - pymatgen =2024.8.9 - pyscal3 =3.2.7 -- pyxtal =1.0.0 +- pyxtal =1.0.2 - scikit-learn =1.5.1 - scipy =1.14.0 - spglib =2.5.0 From 5d6f36e43f9a2de139b82e09a342e12a32979a1f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 20:51:50 +0000 Subject: [PATCH 26/44] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.7 → v0.6.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.7...v0.6.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c82a8e9b8..567df2c7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.7 + rev: v0.6.1 hooks: - id: ruff name: ruff lint From 2696ada30a271845d47d999c9a510295608aff63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:03:06 +0000 Subject: [PATCH 27/44] Bump scipy from 1.14.0 to 1.14.1 Bumps [scipy](https://github.com/scipy/scipy) from 1.14.0 to 1.14.1. - [Release notes](https://github.com/scipy/scipy/releases) - [Commits](https://github.com/scipy/scipy/compare/v1.14.0...v1.14.1) --- updated-dependencies: - dependency-name: scipy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 310606d12..f21a3af7e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ classifiers = [ dependencies = [ "ase==3.23.0", "numpy==1.26.4", - "scipy==1.14.0", + "scipy==1.14.1", ] dynamic = ["version"] From 4ca740748c646470ca790a578f10d781c4d52280 Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Wed, 21 Aug 2024 17:03:20 +0000 Subject: [PATCH 28/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- .ci_support/environment_mini.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 926420547..a2aa575f6 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -16,6 +16,6 @@ dependencies: - pyscal3 =3.2.7 - pyxtal =1.0.2 - scikit-learn =1.5.1 -- scipy =1.14.0 +- scipy =1.14.1 - spglib =2.5.0 - sqsgenerator =0.3 diff --git a/.ci_support/environment_mini.yml b/.ci_support/environment_mini.yml index ddd37cc33..f84d4bc6b 100644 --- a/.ci_support/environment_mini.yml +++ b/.ci_support/environment_mini.yml @@ -4,4 +4,4 @@ dependencies: - ase =3.23.0 - coverage - numpy =1.26.4 -- scipy =1.14.0 +- scipy =1.14.1 From 541cf9751d06906d2a498f03b2865695600316c9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 21:03:39 +0000 Subject: [PATCH 29/44] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.1 → v0.6.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.1...v0.6.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 567df2c7a..3a3900a85 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.1 + rev: v0.6.2 hooks: - id: ruff name: ruff lint From f927743bb640b248f7c2553af32fec7bbf97677a Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 27 Aug 2024 10:33:28 +0200 Subject: [PATCH 30/44] Remove conda default channel --- .github/workflows/deploy.yml | 15 ++++++--------- .github/workflows/mini.yml | 9 ++++----- .github/workflows/pypicheck.yml | 9 ++++----- .github/workflows/unittests.yml | 9 ++++----- .github/workflows/unittests_old.yml | 9 ++++----- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2dc2a87f0..a18f2f0a2 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -19,22 +19,19 @@ jobs: id-token: write steps: - uses: actions/checkout@v4 + - name: Conda config + run: echo -e "channels:\n - conda-forge\n" > .condarc - uses: conda-incubator/setup-miniconda@v3 with: python-version: "3.12" - mamba-version: "*" - channels: conda-forge - miniforge-variant: Mambaforge - channel-priority: strict - auto-update-conda: true + miniforge-version: latest + condarc-file: .condarc environment-file: .ci_support/environment.yml - - name: Convert dependencies - run: | - cp .ci_support/environment-old.yml environment.yml - python .ci_support/release.py; cat pyproject.toml - name: Build shell: bash -l {0} run: | + cp .ci_support/environment-old.yml environment.yml + python .ci_support/release.py; cat pyproject.toml pip install versioneer[toml]==0.29 python setup.py sdist bdist_wheel - name: Publish distribution 📦 to PyPI diff --git a/.github/workflows/mini.yml b/.github/workflows/mini.yml index 8491ace57..590012e77 100644 --- a/.github/workflows/mini.yml +++ b/.github/workflows/mini.yml @@ -17,16 +17,15 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Conda config + run: echo -e "channels:\n - conda-forge\n" > .condarc - name: Setup Mambaforge uses: conda-incubator/setup-miniconda@v3 with: python-version: '3.12' - miniforge-variant: Mambaforge - channels: conda-forge - channel-priority: strict - activate-environment: my-env + miniforge-version: latest + condarc-file: .condarc environment-file: .ci_support/environment_mini.yml - use-mamba: true - name: Test shell: bash -l {0} timeout-minutes: 30 diff --git a/.github/workflows/pypicheck.yml b/.github/workflows/pypicheck.yml index 32544cccd..3297c3afa 100644 --- a/.github/workflows/pypicheck.yml +++ b/.github/workflows/pypicheck.yml @@ -14,16 +14,15 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Conda config + run: echo -e "channels:\n - conda-forge\n" > .condarc - name: Setup Mambaforge uses: conda-incubator/setup-miniconda@v3 with: python-version: '3.12' - miniforge-variant: Mambaforge - channels: conda-forge - channel-priority: strict - activate-environment: my-env + miniforge-version: latest + condarc-file: .condarc environment-file: .ci_support/environment.yml - use-mamba: true - name: Pip check shell: bash -l {0} run: | diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml index 9fea82a5c..e6f5cee27 100644 --- a/.github/workflows/unittests.yml +++ b/.github/workflows/unittests.yml @@ -48,16 +48,15 @@ jobs: - name: Merge conda environment if: matrix.operating-system != 'windows-latest' run: tail --lines=+4 .ci_support/environment-lammps.yml >> .ci_support/environment.yml + - name: Conda config + run: echo -e "channels:\n - conda-forge\n" > .condarc - name: Setup Mambaforge uses: conda-incubator/setup-miniconda@v3 with: python-version: ${{ matrix.python-version }} - miniforge-variant: Mambaforge - channels: conda-forge - channel-priority: strict - activate-environment: my-env + miniforge-version: latest + condarc-file: .condarc environment-file: .ci_support/environment.yml - use-mamba: true - name: Test shell: bash -l {0} timeout-minutes: 30 diff --git a/.github/workflows/unittests_old.yml b/.github/workflows/unittests_old.yml index eb6ee6d85..030936745 100644 --- a/.github/workflows/unittests_old.yml +++ b/.github/workflows/unittests_old.yml @@ -13,16 +13,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Conda config + run: echo -e "channels:\n - conda-forge\n" > .condarc - name: Setup Mambaforge uses: conda-incubator/setup-miniconda@v3 with: python-version: '3.9' - miniforge-variant: Mambaforge - channels: conda-forge - channel-priority: strict - activate-environment: my-env + miniforge-version: latest + condarc-file: .condarc environment-file: .ci_support/environment-old.yml - use-mamba: true - name: Test shell: bash -l {0} timeout-minutes: 30 From 2869878c3953e768b130c6ca6dae9116e0c26403 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 27 Aug 2024 10:50:40 +0200 Subject: [PATCH 31/44] Update unittests.yml --- .github/workflows/unittests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml index e6f5cee27..2171ea8d8 100644 --- a/.github/workflows/unittests.yml +++ b/.github/workflows/unittests.yml @@ -49,6 +49,7 @@ jobs: if: matrix.operating-system != 'windows-latest' run: tail --lines=+4 .ci_support/environment-lammps.yml >> .ci_support/environment.yml - name: Conda config + shell: bash -l {0} run: echo -e "channels:\n - conda-forge\n" > .condarc - name: Setup Mambaforge uses: conda-incubator/setup-miniconda@v3 From e4201d060a61edcfb783361f5037d1920a99ce36 Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Tue, 27 Aug 2024 17:30:49 +0200 Subject: [PATCH 32/44] Use dataclass interface to spglib symmetry spglib.get_symmetry_dataset now returns a dataclass and throws warnings on __getitem__. This affects our Symmetry class when using the .info attribute. --- structuretoolkit/analyse/symmetry.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/structuretoolkit/analyse/symmetry.py b/structuretoolkit/analyse/symmetry.py index 1b50938fa..f2baf6932 100644 --- a/structuretoolkit/analyse/symmetry.py +++ b/structuretoolkit/analyse/symmetry.py @@ -3,6 +3,7 @@ # Distributed under the terms of "New BSD License", see the LICENSE file. import ast +import dataclasses import string from functools import cached_property from typing import Optional @@ -341,11 +342,11 @@ def info(self): https://atztogo.github.io/spglib/python-spglib.html """ - info = spglib.get_symmetry_dataset( + info = dataclasses.asdict(spglib.get_symmetry_dataset( cell=self._get_spglib_cell(use_magmoms=False), symprec=self._symprec, angle_tolerance=self._angle_tolerance, - ) + )) if info is None: raise SymmetryError(spglib.spglib.spglib_error.message) return info From 7edd439a3846107864ff925a17504ce0a995dc16 Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Wed, 28 Aug 2024 12:14:42 +0200 Subject: [PATCH 33/44] Make change backwards compatible spglib<2.5 returns a dict, not a dataclass, so apply asdict only when necessary. --- structuretoolkit/analyse/symmetry.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/structuretoolkit/analyse/symmetry.py b/structuretoolkit/analyse/symmetry.py index f2baf6932..643da0c1b 100644 --- a/structuretoolkit/analyse/symmetry.py +++ b/structuretoolkit/analyse/symmetry.py @@ -342,15 +342,18 @@ def info(self): https://atztogo.github.io/spglib/python-spglib.html """ - info = dataclasses.asdict(spglib.get_symmetry_dataset( + info = spglib.get_symmetry_dataset( cell=self._get_spglib_cell(use_magmoms=False), symprec=self._symprec, angle_tolerance=self._angle_tolerance, - )) + ) if info is None: raise SymmetryError(spglib.spglib.spglib_error.message) + if dataclasses.is_dataclass(info): + info = dataclasses.asdict(info) return info + @property def spacegroup(self) -> dict: """ From eadcf10e2ff3d1e81bf1e8f6c93bd424e8067e52 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 10:17:43 +0000 Subject: [PATCH 34/44] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- structuretoolkit/analyse/symmetry.py | 1 - 1 file changed, 1 deletion(-) diff --git a/structuretoolkit/analyse/symmetry.py b/structuretoolkit/analyse/symmetry.py index 643da0c1b..5488c23b2 100644 --- a/structuretoolkit/analyse/symmetry.py +++ b/structuretoolkit/analyse/symmetry.py @@ -353,7 +353,6 @@ def info(self): info = dataclasses.asdict(info) return info - @property def spacegroup(self) -> dict: """ From 9be392f984469d9cc99238477c87073db645eaf6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:54:09 +0000 Subject: [PATCH 35/44] Bump plotly from 5.23.0 to 5.24.0 Bumps [plotly](https://github.com/plotly/plotly.py) from 5.23.0 to 5.24.0. - [Release notes](https://github.com/plotly/plotly.py/releases) - [Changelog](https://github.com/plotly/plotly.py/blob/master/CHANGELOG.md) - [Commits](https://github.com/plotly/plotly.py/compare/v5.23.0...v5.24.0) --- updated-dependencies: - dependency-name: plotly dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f21a3af7e..cb98d0d18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ grainboundary = [ pyscal = ["pyscal3==3.2.7"] nglview = ["nglview==3.1.2"] matplotlib = ["matplotlib==3.9.2"] -plotly = ["plotly==5.23.0"] +plotly = ["plotly==5.24.0"] clusters = ["scikit-learn==1.5.1"] symmetry = ["spglib==2.5.0"] surface = [ From 858e0d78726fe528588ba740857f1c1537e78784 Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Fri, 30 Aug 2024 16:54:26 +0000 Subject: [PATCH 36/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index a2aa575f6..6f8395ff3 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -11,7 +11,7 @@ dependencies: - notebook - numpy =1.26.4 - phonopy =2.26.6 -- plotly =5.23.0 +- plotly =5.24.0 - pymatgen =2024.8.9 - pyscal3 =3.2.7 - pyxtal =1.0.2 From cfbe2ca092b13745c32c7997ae5b3becc5d36614 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 20:50:49 +0000 Subject: [PATCH 37/44] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.2 → v0.6.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.2...v0.6.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3a3900a85..4e18d6b43 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.2 + rev: v0.6.3 hooks: - id: ruff name: ruff lint From 54ab4f74035965417871fec84fb8546a9ea4adaa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 20:57:17 +0000 Subject: [PATCH 38/44] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.3 → v0.6.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.3...v0.6.4) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4e18d6b43..1763a968a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.3 + rev: v0.6.4 hooks: - id: ruff name: ruff lint From e2c7d7d25f85237c30cb8f389783fcd649ed38df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:31:07 +0000 Subject: [PATCH 39/44] Bump pyxtal from 1.0.2 to 1.0.3 Bumps [pyxtal](https://github.com/MaterSim/PyXtal) from 1.0.2 to 1.0.3. - [Release notes](https://github.com/MaterSim/PyXtal/releases) - [Commits](https://github.com/MaterSim/PyXtal/compare/v1.0.2...v1.0.3) --- updated-dependencies: - dependency-name: pyxtal dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index cb98d0d18..e39593784 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ phonopy = [ "phonopy==2.26.6", "spglib==2.5.0", ] -pyxtal = ["pyxtal==1.0.2"] +pyxtal = ["pyxtal==1.0.3"] [tool.setuptools.packages.find] include = ["structuretoolkit*"] From 0479ad6eb0617889b6cf9704e2579ae04187fd58 Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Tue, 10 Sep 2024 16:31:21 +0000 Subject: [PATCH 40/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 6f8395ff3..672839648 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -14,7 +14,7 @@ dependencies: - plotly =5.24.0 - pymatgen =2024.8.9 - pyscal3 =3.2.7 -- pyxtal =1.0.2 +- pyxtal =1.0.3 - scikit-learn =1.5.1 - scipy =1.14.1 - spglib =2.5.0 From 2bda56ede658375f2fd87f04c64724cba28d4632 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:27:49 +0000 Subject: [PATCH 41/44] Bump scikit-learn from 1.5.1 to 1.5.2 Bumps [scikit-learn](https://github.com/scikit-learn/scikit-learn) from 1.5.1 to 1.5.2. - [Release notes](https://github.com/scikit-learn/scikit-learn/releases) - [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.5.1...1.5.2) --- updated-dependencies: - dependency-name: scikit-learn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e39593784..abb1f0bf2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ pyscal = ["pyscal3==3.2.7"] nglview = ["nglview==3.1.2"] matplotlib = ["matplotlib==3.9.2"] plotly = ["plotly==5.24.0"] -clusters = ["scikit-learn==1.5.1"] +clusters = ["scikit-learn==1.5.2"] symmetry = ["spglib==2.5.0"] surface = [ "spglib==2.5.0", From 610a3085d0ce84fdfce78033815acae79769ba8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:28:03 +0000 Subject: [PATCH 42/44] Bump pymatgen from 2024.8.9 to 2024.9.10 Bumps [pymatgen](https://github.com/materialsproject/pymatgen) from 2024.8.9 to 2024.9.10. - [Release notes](https://github.com/materialsproject/pymatgen/releases) - [Changelog](https://github.com/materialsproject/pymatgen/blob/master/docs/CHANGES.md) - [Commits](https://github.com/materialsproject/pymatgen/compare/v2024.8.9...v2024.9.10) --- updated-dependencies: - dependency-name: pymatgen dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e39593784..d3518bc18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ Repository = "https://github.com/pyiron/structuretoolkit" dscribe = ["dscribe==2.1.1"] grainboundary = [ "aimsgb==1.1.1", - "pymatgen==2024.8.9", + "pymatgen==2024.9.10", ] pyscal = ["pyscal3==3.2.7"] nglview = ["nglview==3.1.2"] @@ -49,7 +49,7 @@ clusters = ["scikit-learn==1.5.1"] symmetry = ["spglib==2.5.0"] surface = [ "spglib==2.5.0", - "pymatgen==2024.8.9", + "pymatgen==2024.9.10", ] phonopy = [ "phonopy==2.26.6", From 980d8cf080c2cc329a2b7d485808bd4590b4da1e Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Wed, 11 Sep 2024 16:28:05 +0000 Subject: [PATCH 43/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 672839648..9c090ac94 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -15,7 +15,7 @@ dependencies: - pymatgen =2024.8.9 - pyscal3 =3.2.7 - pyxtal =1.0.3 -- scikit-learn =1.5.1 +- scikit-learn =1.5.2 - scipy =1.14.1 - spglib =2.5.0 - sqsgenerator =0.3 From 67be09da7dc0b7b1c39bcbd5951ae95e92e4c5e6 Mon Sep 17 00:00:00 2001 From: pyironrunner Date: Wed, 11 Sep 2024 16:28:19 +0000 Subject: [PATCH 44/44] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 672839648..8509cf651 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -12,7 +12,7 @@ dependencies: - numpy =1.26.4 - phonopy =2.26.6 - plotly =5.24.0 -- pymatgen =2024.8.9 +- pymatgen =2024.9.10 - pyscal3 =3.2.7 - pyxtal =1.0.3 - scikit-learn =1.5.1