From 6d22dd27f8fd4fa79ba55563a73c8e03261cef22 Mon Sep 17 00:00:00 2001 From: Timo Reents Date: Wed, 4 Dec 2024 15:41:42 +0100 Subject: [PATCH] DevOps: Update `github CI` and `pre-commit` A few changes have been made to update the github CI and the pre-commit hooks. * Use more python versions in the CI to ensure those are supported * The pre-commit hooks are updated to more recent versions, and additional (standard) hooks are introduced, e.g. EOF or double-quote fixer * pre-commit: `ruff` replaces `black` * pre-commit: `prospector` is enabled and all warnings/errors (e.g. pylint) have been adjusted accordingly --- .github/workflows/ci.yml | 5 +- .pre-commit-config.yaml | 32 +- docs/.gitignore | 2 +- docs/source/conf.py | 156 ++-- docs/source/index.rst | 1 - docs/source/module_guide/index.rst | 1 - seekpath/__init__.py | 45 +- seekpath/brillouinzone/brillouinzone.py | 78 +- seekpath/getpaths.py | 81 ++- seekpath/hpkot/__init__.py | 241 +++---- seekpath/hpkot/spg_db.py | 920 ++++++++++++------------ seekpath/hpkot/spg_mapping.py | 132 ++-- seekpath/hpkot/tools.py | 223 +++--- seekpath/util.py | 224 +++--- tests/test_brillouinzone.py | 34 +- tests/test_hpkot_get_primitive.py | 6 +- tests/test_paths_hpkot.py | 367 +++++----- 17 files changed, 1266 insertions(+), 1282 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97b98bd..6617073 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,9 @@ jobs: tests: runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v4 @@ -33,7 +36,7 @@ jobs: - name: Set up Python 3.8 uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: ${{ matrix.python-version }} - name: Install python dependencies run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9063423..d0cc86d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,19 +1,27 @@ +exclude: ^seekpath/hpkot/band_path_data + repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.2.3 + rev: v4.6.0 hooks: - id: trailing-whitespace + - id: end-of-file-fixer + - id: double-quote-string-fixer + +- repo: https://github.com/ikamensh/flynt/ + rev: 1.0.1 + hooks: + - id: flynt -- repo: https://github.com/ambv/black - rev: 23.3.0 +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.8.0 hooks: - - id: black + - id: ruff-format + - id: ruff + args: [--fix, --exit-non-zero-on-fix, --show-fixes] -#- repo: local -# hooks: -# - id: prospector -# language: system -# types: [file, python] -# name: prospector -# description: "This hook runs Prospector: https://github.com/landscapeio/prospector" -# entry: prospector +- repo: https://github.com/PyCQA/prospector + rev: v1.11.0 + hooks: + - id: prospector + language: system diff --git a/docs/.gitignore b/docs/.gitignore index d163863..567609b 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1 +1 @@ -build/ \ No newline at end of file +build/ diff --git a/docs/source/conf.py b/docs/source/conf.py index 3165bf9..0a608bf 100755 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -17,40 +17,40 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.mathjax", + 'sphinx.ext.autodoc', + 'sphinx.ext.mathjax', # 'sphinx.ext.intersphinx', - "sphinx.ext.viewcode", + 'sphinx.ext.viewcode', ] intersphinx_mapping = { # 'python': ('https://docs.python.org/2.7', None), } -nitpick_ignore = [("py:obj", "module")] +nitpick_ignore = [('py:obj', 'module')] # Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] +templates_path = ['_templates'] # The suffix of source filenames. -source_suffix = ".rst" +source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. # ~ master_doc = 'index' -master_doc = "index" +master_doc = 'index' # General information about the project. -project = "seekpath" +project = 'seekpath' copyright = ( - "2016-{}, Giovanni Pizzi, PAUL SCHERRER INSTITUT (Laboratory " - "for Materials Simulations), ECOLE POLYTECHNIQUE FEDERALE DE " - "LAUSANNE (Theory and Simulation of Materials (THEOS) and National Centre for " - "Computational Design and Discovery of Novel Materials (NCCR MARVEL)), " - "Switzerland. " - "All rights reserved.".format(time.localtime().tm_year) + '2016-{}, Giovanni Pizzi, PAUL SCHERRER INSTITUT (Laboratory ' + 'for Materials Simulations), ECOLE POLYTECHNIQUE FEDERALE DE ' + 'LAUSANNE (Theory and Simulation of Materials (THEOS) and National Centre for ' + 'Computational Design and Discovery of Novel Materials (NCCR MARVEL)), ' + 'Switzerland. ' + 'All rights reserved.'.format(time.localtime().tm_year) ) # The version info for the project you're documenting, acts as replacement for @@ -58,7 +58,7 @@ # built documents. # # The short X.Y version. -version = ".".join(seekpath.__version__.split(".")[:2]) +version = '.'.join(seekpath.__version__.split('.')[:2]) # The full version, including alpha/beta/rc tags. release = seekpath.__version__ @@ -77,7 +77,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ["doc.rst"] +exclude_patterns = ['doc.rst'] # ~ exclude_patterns = ['index.rst'] # The reST default role (used for this markup: `text`) to use for all @@ -96,7 +96,7 @@ show_authors = True # The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" +pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] @@ -185,7 +185,7 @@ # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -html_use_opensearch = "http://seekpath.readthedocs.io" +html_use_opensearch = 'http://seekpath.readthedocs.io' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None @@ -194,7 +194,7 @@ # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -html_search_language = "en" +html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value @@ -205,7 +205,7 @@ # html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = "seekpathdoc" +htmlhelp_basename = 'seekpathdoc' # -- Options for LaTeX output --------------------------------------------- @@ -277,13 +277,13 @@ # texinfo_no_detailmenu = False # NOTE: it is needed to have these lines before load_dbenv() -on_rtd = os.environ.get("READTHEDOCS", None) == "True" +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' if not on_rtd: # only import and set the theme if we're building docs locally try: import sphinx_rtd_theme - html_theme = "sphinx_rtd_theme" + html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] except ImportError: # No sphinx_rtd_theme installed @@ -292,60 +292,60 @@ # Warnings to ignore when using the -n (nitpicky) option # We should ignore any python built-in exception, for instance nitpick_ignore = [ - ("py:exc", "ArithmeticError"), - ("py:exc", "AssertionError"), - ("py:exc", "AttributeError"), - ("py:exc", "BaseException"), - ("py:exc", "BufferError"), - ("py:exc", "DeprecationWarning"), - ("py:exc", "EOFError"), - ("py:exc", "EnvironmentError"), - ("py:exc", "Exception"), - ("py:exc", "FloatingPointError"), - ("py:exc", "FutureWarning"), - ("py:exc", "GeneratorExit"), - ("py:exc", "IOError"), - ("py:exc", "ImportError"), - ("py:exc", "ImportWarning"), - ("py:exc", "IndentationError"), - ("py:exc", "IndexError"), - ("py:exc", "KeyError"), - ("py:exc", "KeyboardInterrupt"), - ("py:exc", "LookupError"), - ("py:exc", "MemoryError"), - ("py:exc", "NameError"), - ("py:exc", "NotImplementedError"), - ("py:exc", "OSError"), - ("py:exc", "OverflowError"), - ("py:exc", "PendingDeprecationWarning"), - ("py:exc", "ReferenceError"), - ("py:exc", "RuntimeError"), - ("py:exc", "RuntimeWarning"), - ("py:exc", "StandardError"), - ("py:exc", "StopIteration"), - ("py:exc", "SyntaxError"), - ("py:exc", "SyntaxWarning"), - ("py:exc", "SystemError"), - ("py:exc", "SystemExit"), - ("py:exc", "TabError"), - ("py:exc", "TypeError"), - ("py:exc", "UnboundLocalError"), - ("py:exc", "UnicodeDecodeError"), - ("py:exc", "UnicodeEncodeError"), - ("py:exc", "UnicodeError"), - ("py:exc", "UnicodeTranslateError"), - ("py:exc", "UnicodeWarning"), - ("py:exc", "UserWarning"), - ("py:exc", "VMSError"), - ("py:exc", "ValueError"), - ("py:exc", "Warning"), - ("py:exc", "WindowsError"), - ("py:exc", "ZeroDivisionError"), - ("py:obj", "str"), - ("py:obj", "list"), - ("py:obj", "tuple"), - ("py:obj", "int"), - ("py:obj", "float"), - ("py:obj", "bool"), - ("py:obj", "Mapping"), + ('py:exc', 'ArithmeticError'), + ('py:exc', 'AssertionError'), + ('py:exc', 'AttributeError'), + ('py:exc', 'BaseException'), + ('py:exc', 'BufferError'), + ('py:exc', 'DeprecationWarning'), + ('py:exc', 'EOFError'), + ('py:exc', 'EnvironmentError'), + ('py:exc', 'Exception'), + ('py:exc', 'FloatingPointError'), + ('py:exc', 'FutureWarning'), + ('py:exc', 'GeneratorExit'), + ('py:exc', 'IOError'), + ('py:exc', 'ImportError'), + ('py:exc', 'ImportWarning'), + ('py:exc', 'IndentationError'), + ('py:exc', 'IndexError'), + ('py:exc', 'KeyError'), + ('py:exc', 'KeyboardInterrupt'), + ('py:exc', 'LookupError'), + ('py:exc', 'MemoryError'), + ('py:exc', 'NameError'), + ('py:exc', 'NotImplementedError'), + ('py:exc', 'OSError'), + ('py:exc', 'OverflowError'), + ('py:exc', 'PendingDeprecationWarning'), + ('py:exc', 'ReferenceError'), + ('py:exc', 'RuntimeError'), + ('py:exc', 'RuntimeWarning'), + ('py:exc', 'StandardError'), + ('py:exc', 'StopIteration'), + ('py:exc', 'SyntaxError'), + ('py:exc', 'SyntaxWarning'), + ('py:exc', 'SystemError'), + ('py:exc', 'SystemExit'), + ('py:exc', 'TabError'), + ('py:exc', 'TypeError'), + ('py:exc', 'UnboundLocalError'), + ('py:exc', 'UnicodeDecodeError'), + ('py:exc', 'UnicodeEncodeError'), + ('py:exc', 'UnicodeError'), + ('py:exc', 'UnicodeTranslateError'), + ('py:exc', 'UnicodeWarning'), + ('py:exc', 'UserWarning'), + ('py:exc', 'VMSError'), + ('py:exc', 'ValueError'), + ('py:exc', 'Warning'), + ('py:exc', 'WindowsError'), + ('py:exc', 'ZeroDivisionError'), + ('py:obj', 'str'), + ('py:obj', 'list'), + ('py:obj', 'tuple'), + ('py:obj', 'int'), + ('py:obj', 'float'), + ('py:obj', 'bool'), + ('py:obj', 'Mapping'), ] diff --git a/docs/source/index.rst b/docs/source/index.rst index c3a6ad6..affa483 100755 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -24,4 +24,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - diff --git a/docs/source/module_guide/index.rst b/docs/source/module_guide/index.rst index 214362d..b179216 100644 --- a/docs/source/module_guide/index.rst +++ b/docs/source/module_guide/index.rst @@ -20,4 +20,3 @@ The HPKOT module .. automodule:: seekpath.hpkot.tools :members: - diff --git a/seekpath/__init__.py b/seekpath/__init__.py index ce2ab0d..0d3f810 100644 --- a/seekpath/__init__.py +++ b/seekpath/__init__.py @@ -1,3 +1,5 @@ +# pylint: disable=cyclic-import, wrong-import-position +# ruff: noqa: E402 """ The seekpath module contains routines to get automatically the path in a 3D Brillouin zone to plot band structures. @@ -7,21 +9,21 @@ Licence: MIT License, see LICENSE.txt file """ -__version__ = "2.1.0" -__author__ = "Giovanni Pizzi, PSI" +__version__ = '2.1.0' +__author__ = 'Giovanni Pizzi, PSI' __copyright__ = ( - "Copyright (c), 2016-2023, Giovanni Pizzi, PAUL SCHERRER INSTITUT " - "(Laboratory for Materials Simulations), EPFL " - "(Theory and Simulation of Materials (THEOS) and National Centre " - "for Computational Design and Discovery of Novel Materials " - "(NCCR MARVEL)), Switzerland." + 'Copyright (c), 2016-2023, Giovanni Pizzi, PAUL SCHERRER INSTITUT ' + '(Laboratory for Materials Simulations), EPFL ' + '(Theory and Simulation of Materials (THEOS) and National Centre ' + 'for Computational Design and Discovery of Novel Materials ' + '(NCCR MARVEL)), Switzerland.' ) -__credits__ = ["Yoyo Hinuma", "Jae-Mo Lihm"] -__license__ = "MIT license" +__credits__ = ['Yoyo Hinuma', 'Jae-Mo Lihm'] +__license__ = 'MIT license' __paper__ = ( - "Y. Hinuma, G. Pizzi, Y. Kumagai, F. Oba, I. Tanaka, " - "Band structure diagram paths based on crystallography, " - "Comp. Mat. Sci. 128, 140 (2017). DOI: 10.1016/j.commatsci.2016.10.015" + 'Y. Hinuma, G. Pizzi, Y. Kumagai, F. Oba, I. Tanaka, ' + 'Band structure diagram paths based on crystallography, ' + 'Comp. Mat. Sci. 128, 140 (2017). DOI: 10.1016/j.commatsci.2016.10.015' ) @@ -32,8 +34,6 @@ class SupercellWarning(UserWarning): original cell) is requested. """ - pass - from .getpaths import ( get_path, @@ -45,13 +45,14 @@ class SupercellWarning(UserWarning): from .hpkot import EdgeCaseWarning, SymmetryDetectionError from .brillouinzone import brillouinzone + __all__ = ( - "get_path", - "get_explicit_k_path", - "get_path_orig_cell", - "get_explicit_k_path_orig_cell", - "EdgeCaseWarning", - "SymmetryDetectionError", - "SupercellWarning", - "brillouinzone", + 'get_path', + 'get_explicit_k_path', + 'get_path_orig_cell', + 'get_explicit_k_path_orig_cell', + 'EdgeCaseWarning', + 'SymmetryDetectionError', + 'SupercellWarning', + 'brillouinzone', ) diff --git a/seekpath/brillouinzone/brillouinzone.py b/seekpath/brillouinzone/brillouinzone.py index 4b88a9b..8bd93b9 100644 --- a/seekpath/brillouinzone/brillouinzone.py +++ b/seekpath/brillouinzone/brillouinzone.py @@ -1,7 +1,8 @@ """Module to compute the Brillouin zone of a crystal.""" + from collections import defaultdict import warnings -from typing import Union, List, Dict +from typing import Union import numpy as np from scipy.spatial import Voronoi, ConvexHull, Delaunay @@ -23,17 +24,17 @@ def get_BZ( time being) """ warnings.warn( - "`get_BZ` is deprecated, use the `BZ` class instead, to represent a brillouine zone. " - "The faces and triangles can be accesses as attributes.", + '`get_BZ` is deprecated, use the `BZ` class instead, to represent a brillouine zone. ' + 'The faces and triangles can be accesses as attributes.', UserWarning, ) bz = BZ(b1, b2, b3) faces_data = { - "triangles_vertices": bz.triangles_vertices, - "triangles": bz.triangles, - "faces": bz.faces, + 'triangles_vertices': bz.triangles_vertices, + 'triangles': bz.triangles, + 'faces': bz.faces, } return faces_data @@ -94,11 +95,11 @@ def _get_missing_point(self, tr: Union[list, np.array], p1: int, p2: int) -> int for vertex in tr: if vertex not in (p1, p2): if missing is not None: - raise ValueError("Two missing points found...") + raise ValueError('Two missing points found...') missing = vertex if missing is None: - raise ValueError("No missing points!") + raise ValueError('No missing points!') return missing @@ -157,11 +158,11 @@ def _initialize_BZ( ## REORIENT TRIANGLES ## NOTE! TODO: I should do the same for faces - ret_data["triangles_vertices"] = hull.points.tolist() + ret_data['triangles_vertices'] = hull.points.tolist() ## Naive one # ret_data['triangles'] = hull.simplices.tolist() ## Instead, I orient them all - ret_data["triangles"] = [] + ret_data['triangles'] = [] for simplex in hull.simplices: points = np.array([hull.points[i] for i in simplex]) center = points.sum(axis=0) / float(len(points)) @@ -184,17 +185,16 @@ def _initialize_BZ( elif not is_up_inside and is_down_inside: correct_orientation = False else: - inside_outside_string = "inside" if is_up_inside else "outside" + inside_outside_string = 'inside' if is_up_inside else 'outside' print( - "WARNING! Both vectors are {}..." - " not changing orientation".format(inside_outside_string) + f'WARNING! Both vectors are {inside_outside_string}... not changing orientation' ) correct_orientation = True if correct_orientation: - ret_data["triangles"].append(simplex.tolist()) + ret_data['triangles'].append(simplex.tolist()) else: - ret_data["triangles"].append(simplex[::-1].tolist()) + ret_data['triangles'].append(simplex[::-1].tolist()) # print hull.area, hull.volume @@ -220,7 +220,8 @@ def _initialize_BZ( # List of found simplices that have been merged; will be used at the # end to add the triangles that have not been merged, if any - merged_simplices = [] + # TODO (was not commented out before but never used) + # merged_simplices = [] for (p1, p2), triangles in edges.items(): # I do it many times, but it's the easiest way (and anyway it's # a set, so it should be fast: I add a point to be merged with @@ -230,8 +231,7 @@ def _initialize_BZ( if len(triangles) != 2: # An edge shared by less (or more) than 2 triangles? - print("Warning!", p1, p2, triangles) - continue + print('Warning!', p1, p2, triangles) else: # Check if two triangles are coplanar: get the other two # vertices that are not on the shared edge @@ -341,14 +341,14 @@ def _initialize_BZ( [hull.points[point_idx].tolist() for point_idx in actual_points_idx] ) - ret_data["faces"] = faces + ret_data['faces'] = faces self._hull = hull self._delaunay = Delaunay(hull.points) - self._triangles_vertices = ret_data["triangles_vertices"] - self._triangles = ret_data["triangles"] - self._faces = ret_data["faces"] + self._triangles_vertices = ret_data['triangles_vertices'] + self._triangles = ret_data['triangles'] + self._faces = ret_data['faces'] def is_inside_bz(self, p: Union[list, np.array]) -> bool: """Check if a point is within the convex hull of the Brillouin zone. @@ -363,20 +363,20 @@ def is_inside_bz(self, p: Union[list, np.array]) -> bool: return self._delaunay.find_simplex(p) >= 0 -if __name__ == "__main__": - import matplotlib.pyplot as plt - from mpl_toolkits.mplot3d.art3d import Poly3DCollection +if __name__ == '__main__': + import matplotlib.pyplot as plt # pylint: disable=import-error + from mpl_toolkits.mplot3d.art3d import Poly3DCollection # pylint: disable=import-error # draw a vector - from matplotlib.patches import FancyArrowPatch - from mpl_toolkits.mplot3d import proj3d + from matplotlib.patches import FancyArrowPatch # pylint: disable=import-error + from mpl_toolkits.mplot3d import proj3d # pylint: disable=import-error class Arrow3D(FancyArrowPatch): def __init__(self, xs, ys, zs, *args, **kwargs): FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs) self._verts3d = xs, ys, zs - def do_3d_projection(self, renderer=None): + def do_3d_projection(self, renderer=None): # pylint: disable=unused-argument xs3d, ys3d, zs3d = self._verts3d xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M) self.set_positions((xs[0], ys[0]), (xs[1], ys[1])) @@ -396,18 +396,18 @@ def do_3d_projection(self, renderer=None): faces_count[len(face)] += 1 for num_sides in sorted(faces_count.keys()): - print("{} faces: {}".format(num_sides, faces_count[num_sides])) + print(f'{num_sides} faces: {faces_count[num_sides]}') fig = plt.figure() - ax = fig.add_subplot(111, projection="3d") + ax = fig.add_subplot(111, projection='3d') ax.add_collection( Poly3DCollection( - faces_coords, linewidth=1, alpha=0.9, edgecolor="k", facecolor="#ccccff" + faces_coords, linewidth=1, alpha=0.9, edgecolor='k', facecolor='#ccccff' ) ) # draw origin - ax.scatter([0], [0], [0], color="g", s=100) + ax.scatter([0], [0], [0], color='g', s=100) axes_length = 2 # Add axes @@ -418,8 +418,8 @@ def do_3d_projection(self, renderer=None): (0, 0), mutation_scale=20, lw=1, - arrowstyle="-|>", - color="k", + arrowstyle='-|>', + color='k', ) ) ax.add_artist( @@ -429,8 +429,8 @@ def do_3d_projection(self, renderer=None): (0, 0), mutation_scale=20, lw=1, - arrowstyle="-|>", - color="k", + arrowstyle='-|>', + color='k', ) ) ax.add_artist( @@ -440,8 +440,8 @@ def do_3d_projection(self, renderer=None): (0, axes_length), mutation_scale=20, lw=1, - arrowstyle="-|>", - color="k", + arrowstyle='-|>', + color='k', ) ) @@ -449,7 +449,7 @@ def do_3d_projection(self, renderer=None): ax.set_xlim(-1, 1) ax.set_ylim(-1, 1) ax.set_zlim(-1, 1) - ax.axis("off") + ax.axis('off') ax.view_init(elev=0, azim=60) plt.show() diff --git a/seekpath/getpaths.py b/seekpath/getpaths.py index bd3b21b..2f1d4c5 100644 --- a/seekpath/getpaths.py +++ b/seekpath/getpaths.py @@ -1,14 +1,13 @@ """ This module contains the main functions to get a path and an explicit path. """ + import numpy as np import warnings from . import SupercellWarning -def get_explicit_from_implicit( # pylint: disable=too-many-locals - seekpath_output, reference_distance -): +def get_explicit_from_implicit(seekpath_output, reference_distance): """ Given the output of ``get_path`` by seekpath, compute an "explicit" path, i.e. instead of just giving the endpoints and their coordinates, compute @@ -28,14 +27,14 @@ def get_explicit_from_implicit( # pylint: disable=too-many-locals kpoints_linearcoord = [] previous_linearcoord = 0.0 segments = [] - for start_label, stop_label in seekpath_output["path"]: - start_coord = np.array(seekpath_output["point_coords"][start_label]) - stop_coord = np.array(seekpath_output["point_coords"][stop_label]) + for start_label, stop_label in seekpath_output['path']: + start_coord = np.array(seekpath_output['point_coords'][start_label]) + stop_coord = np.array(seekpath_output['point_coords'][stop_label]) start_coord_abs = np.dot( - start_coord, seekpath_output["reciprocal_primitive_lattice"] + start_coord, seekpath_output['reciprocal_primitive_lattice'] ) stop_coord_abs = np.dot( - stop_coord, seekpath_output["reciprocal_primitive_lattice"] + stop_coord, seekpath_output['reciprocal_primitive_lattice'] ) segment_length = np.linalg.norm(stop_coord_abs - start_coord_abs) num_points = max(2, int(segment_length / reference_distance)) @@ -59,19 +58,19 @@ def get_explicit_from_implicit( # pylint: disable=too-many-locals elif i == num_points - 1: kpoints_labels.append(stop_label) else: - kpoints_labels.append("") + kpoints_labels.append('') kpoints_linearcoord.append(previous_linearcoord + segment_linearcoord[i]) previous_linearcoord += segment_length segment_end = len(kpoints_labels) segments.append((segment_start, segment_end)) - retdict["kpoints_rel"] = np.array(kpoints_rel) - retdict["kpoints_linearcoord"] = np.array(kpoints_linearcoord) - retdict["kpoints_labels"] = kpoints_labels - retdict["kpoints_abs"] = np.dot( - retdict["kpoints_rel"], seekpath_output["reciprocal_primitive_lattice"] + retdict['kpoints_rel'] = np.array(kpoints_rel) + retdict['kpoints_linearcoord'] = np.array(kpoints_linearcoord) + retdict['kpoints_labels'] = kpoints_labels + retdict['kpoints_abs'] = np.dot( + retdict['kpoints_rel'], seekpath_output['reciprocal_primitive_lattice'] ) - retdict["segments"] = segments + retdict['segments'] = segments return retdict @@ -79,7 +78,7 @@ def get_explicit_from_implicit( # pylint: disable=too-many-locals def get_path( structure, with_time_reversal=True, - recipe="hpkot", + recipe='hpkot', threshold=1.0e-7, symprec=1e-05, angle_tolerance=-1.0, @@ -176,7 +175,7 @@ def get_path( orthorhombic systems). In this case, still one of the valid cases is picked. """ - if recipe == "hpkot": + if recipe == 'hpkot': from . import hpkot res = hpkot.get_path( @@ -199,7 +198,7 @@ def get_explicit_k_path( structure, with_time_reversal=True, reference_distance=0.025, - recipe="hpkot", + recipe='hpkot', threshold=1.0e-7, symprec=1e-05, angle_tolerance=-1.0, @@ -304,7 +303,7 @@ def get_explicit_k_path( and typically in a graphical representation they are shown at the same coordinate, with a label ``R|X``). """ - if recipe == "hpkot": + if recipe == 'hpkot': from . import hpkot res = hpkot.get_path( @@ -325,14 +324,14 @@ def get_explicit_k_path( res, reference_distance=reference_distance ) for k, v in explicit_res.items(): - res["explicit_{}".format(k)] = v + res[f'explicit_{k}'] = v return res def get_path_orig_cell( structure, with_time_reversal=True, - recipe="hpkot", + recipe='hpkot', threshold=1.0e-7, symprec=1e-05, angle_tolerance=-1.0, @@ -422,31 +421,31 @@ def get_path_orig_cell( recipe=recipe, ) - is_supercell = abs(res["volume_original_wrt_prim"] - 1) > 0.1 + is_supercell = abs(res['volume_original_wrt_prim'] - 1) > 0.1 if is_supercell: warnings.warn( - "The provided cell is a supercell: the returned k-path is the " - "standard k-path of the associated primitive cell in the basis of " - "the supercell reciprocal lattice.", + 'The provided cell is a supercell: the returned k-path is the ' + 'standard k-path of the associated primitive cell in the basis of ' + 'the supercell reciprocal lattice.', SupercellWarning, ) # points in the output of get_path are in scaled coordinates of the # standardized primitive lattice - points_scaled_standard = res["point_coords"] + points_scaled_standard = res['point_coords'] # Convert points from scaled coordinates of the standardiced primitive # lattice to Cartesian coordinates points_cartesian = {} for pointname, coords in points_scaled_standard.items(): points_cartesian[pointname] = coords @ np.array( - res["reciprocal_primitive_lattice"] + res['reciprocal_primitive_lattice'] ) # Rotate points in Cartesian space for pointname, coords in points_cartesian.items(): - points_cartesian[pointname] = coords @ res["rotation_matrix"] + points_cartesian[pointname] = coords @ res['rotation_matrix'] # Convert points from Cartesian coordinates to the scaled coordinates # of the original lattice @@ -456,15 +455,15 @@ def get_path_orig_cell( points_scaled_original[pointname] = list(coords @ cell_orig.T / np.pi / 2) res_orig = { - "point_coords": points_scaled_original, - "path": res["path"], - "augmented_path": res["augmented_path"], - "is_supercell": is_supercell, - "has_inversion_symmetry": res["has_inversion_symmetry"], - "bravais_lattice": res["bravais_lattice"], - "bravais_lattice_extended": res["bravais_lattice_extended"], - "spacegroup_number": res["spacegroup_number"], - "spacegroup_international": res["spacegroup_international"], + 'point_coords': points_scaled_original, + 'path': res['path'], + 'augmented_path': res['augmented_path'], + 'is_supercell': is_supercell, + 'has_inversion_symmetry': res['has_inversion_symmetry'], + 'bravais_lattice': res['bravais_lattice'], + 'bravais_lattice_extended': res['bravais_lattice_extended'], + 'spacegroup_number': res['spacegroup_number'], + 'spacegroup_international': res['spacegroup_international'], } return res_orig @@ -474,7 +473,7 @@ def get_explicit_k_path_orig_cell( structure, with_time_reversal=True, reference_distance=0.025, - recipe="hpkot", + recipe='hpkot', threshold=1.0e-7, symprec=1e-05, angle_tolerance=-1.0, @@ -595,14 +594,14 @@ def get_explicit_k_path_orig_cell( # Set reciprocal_primitive_lattice as the reciprocal lattice of the original # cell. To be used only in the get_explicit_from_implicit function. - res["reciprocal_primitive_lattice"] = get_reciprocal_cell_rows(structure[0]) + res['reciprocal_primitive_lattice'] = get_reciprocal_cell_rows(structure[0]) explicit_res = get_explicit_from_implicit( res, reference_distance=reference_distance ) - res.pop("reciprocal_primitive_lattice") + res.pop('reciprocal_primitive_lattice') for k, v in explicit_res.items(): - res["explicit_{}".format(k)] = v + res[f'explicit_{k}'] = v return res diff --git a/seekpath/hpkot/__init__.py b/seekpath/hpkot/__init__.py index 6e7d195..35923e4 100644 --- a/seekpath/hpkot/__init__.py +++ b/seekpath/hpkot/__init__.py @@ -20,16 +20,12 @@ class EdgeCaseWarning(RuntimeWarning): symmetry, but ``a==b==c``. """ - pass - class SymmetryDetectionError(Exception): """ Error raised if spglib could not detect the symmetry. """ - pass - def get_path( structure, @@ -170,7 +166,7 @@ def get_path( ) if dataset is None: raise SymmetryDetectionError( - "Spglib could not detect the symmetry of the system" + 'Spglib could not detect the symmetry of the system' ) conv_lattice = dataset.std_lattice conv_positions = dataset.std_positions @@ -185,85 +181,83 @@ def get_path( # Get the properties of the spacegroup, needed to get the bravais_lattice properties = get_spgroup_data()[spgrp_num] - bravais_lattice = "{}{}".format(properties[0], properties[1]) + bravais_lattice = f'{properties[0]}{properties[1]}' has_inv = properties[2] # Implement all different extended Bravais lattices - if bravais_lattice == "cP": - if spgrp_num >= 195 and spgrp_num <= 206: - ext_bravais = "cP1" - elif spgrp_num >= 207 and spgrp_num <= 230: - ext_bravais = "cP2" + if bravais_lattice == 'cP': + if 195 <= spgrp_num <= 206: + ext_bravais = 'cP1' + elif 207 <= spgrp_num <= 230: + ext_bravais = 'cP2' else: raise ValueError( - "Internal error! should be cP, but the " - "spacegroup number is not in the correct range" + 'Internal error! should be cP, but the ' + 'spacegroup number is not in the correct range' ) - elif bravais_lattice == "cF": - if spgrp_num >= 195 and spgrp_num <= 206: - ext_bravais = "cF1" - elif spgrp_num >= 207 and spgrp_num <= 230: - ext_bravais = "cF2" + elif bravais_lattice == 'cF': + if 195 <= spgrp_num <= 206: + ext_bravais = 'cF1' + elif 207 <= spgrp_num <= 230: + ext_bravais = 'cF2' else: raise ValueError( - "Internal error! should be cF, but the " - "spacegroup number is not in the correct range" + 'Internal error! should be cF, but the ' + 'spacegroup number is not in the correct range' ) - elif bravais_lattice == "cI": - ext_bravais = "cI1" - elif bravais_lattice == "tP": - ext_bravais = "tP1" - elif bravais_lattice == "tI": + elif bravais_lattice == 'cI': + ext_bravais = 'cI1' + elif bravais_lattice == 'tP': + ext_bravais = 'tP1' + elif bravais_lattice == 'tI': if abs(c - a) < threshold: - warnings.warn("tI lattice, but a almost equal to c", EdgeCaseWarning) + warnings.warn('tI lattice, but a almost equal to c', EdgeCaseWarning) if c <= a: - ext_bravais = "tI1" + ext_bravais = 'tI1' else: - ext_bravais = "tI2" - elif bravais_lattice == "oP": - ext_bravais = "oP1" - elif bravais_lattice == "oF": + ext_bravais = 'tI2' + elif bravais_lattice == 'oP': + ext_bravais = 'oP1' + elif bravais_lattice == 'oF': if abs(1.0 / (a**2) - (1.0 / (b**2) + 1.0 / (c**2))) < threshold: warnings.warn( - "oF lattice, but 1/a^2 almost equal to 1/b^2 + 1/c^2", EdgeCaseWarning + 'oF lattice, but 1/a^2 almost equal to 1/b^2 + 1/c^2', EdgeCaseWarning ) if abs(1.0 / (c**2) - (1.0 / (a**2) + 1.0 / (b**2))) < threshold: warnings.warn( - "oF lattice, but 1/c^2 almost equal to 1/a^2 + 1/b^2", EdgeCaseWarning + 'oF lattice, but 1/c^2 almost equal to 1/a^2 + 1/b^2', EdgeCaseWarning ) if 1.0 / (a**2) > 1.0 / (b**2) + 1.0 / (c**2): - ext_bravais = "oF1" + ext_bravais = 'oF1' elif 1.0 / (c**2) > 1.0 / (a**2) + 1.0 / (b**2): - ext_bravais = "oF2" + ext_bravais = 'oF2' else: # 1/a^2, 1/b^2, 1/c^2 edges of a triangle - ext_bravais = "oF3" - elif bravais_lattice == "oI": + ext_bravais = 'oF3' + elif bravais_lattice == 'oI': # Sort a,b,c, first is the largest - sorted_vectors = sorted([(c, 1, "c"), (b, 3, "b"), (a, 2, "a")])[::-1] + sorted_vectors = sorted([(c, 1, 'c'), (b, 3, 'b'), (a, 2, 'a')])[::-1] if abs(sorted_vectors[0][0] - sorted_vectors[1][0]) < threshold: warnings.warn( - "oI lattice, but the two longest vectors {} and {} " - "have almost the same length".format( - sorted_vectors[0][2], sorted_vectors[1][2] - ), + f'oI lattice, but the two longest vectors {sorted_vectors[0][2]} and {sorted_vectors[1][2]} ' + 'have almost the same length', EdgeCaseWarning, ) - ext_bravais = "{}{}".format(bravais_lattice, sorted_vectors[0][1]) - elif bravais_lattice == "oC": + ext_bravais = f'{bravais_lattice}{sorted_vectors[0][1]}' + elif bravais_lattice == 'oC': if abs(b - a) < threshold: - warnings.warn("oC lattice, but a almost equal to b", EdgeCaseWarning) + warnings.warn('oC lattice, but a almost equal to b', EdgeCaseWarning) if a <= b: - ext_bravais = "oC1" + ext_bravais = 'oC1' else: - ext_bravais = "oC2" - elif bravais_lattice == "oA": + ext_bravais = 'oC2' + elif bravais_lattice == 'oA': if abs(b - c) < threshold: - warnings.warn("oA lattice, but b almost equal to c", EdgeCaseWarning) + warnings.warn('oA lattice, but b almost equal to c', EdgeCaseWarning) if b <= c: - ext_bravais = "oA1" + ext_bravais = 'oA1' else: - ext_bravais = "oA2" - elif bravais_lattice == "hP": + ext_bravais = 'oA2' + elif bravais_lattice == 'hP': if spgrp_num in [ 143, 144, @@ -281,43 +275,43 @@ def get_path( 162, 163, ]: - ext_bravais = "hP1" + ext_bravais = 'hP1' else: - ext_bravais = "hP2" - elif bravais_lattice == "hR": + ext_bravais = 'hP2' + elif bravais_lattice == 'hR': if abs(sqrt(3.0) * a - sqrt(2.0) * c) < threshold: warnings.warn( - "hR lattice, but sqrt(3)a almost equal to sqrt(2)c", EdgeCaseWarning + 'hR lattice, but sqrt(3)a almost equal to sqrt(2)c', EdgeCaseWarning ) if sqrt(3.0) * a <= sqrt(2.0) * c: - ext_bravais = "hR1" + ext_bravais = 'hR1' else: - ext_bravais = "hR2" - elif bravais_lattice == "mP": - ext_bravais = "mP1" - elif bravais_lattice == "mC": + ext_bravais = 'hR2' + elif bravais_lattice == 'mP': + ext_bravais = 'mP1' + elif bravais_lattice == 'mC': if abs(b - a * sqrt(1.0 - cosbeta**2)) < threshold: warnings.warn( - "mC lattice, but b almost equal to a*sin(beta)", EdgeCaseWarning + 'mC lattice, but b almost equal to a*sin(beta)', EdgeCaseWarning ) if b < a * sqrt(1.0 - cosbeta**2): - ext_bravais = "mC1" + ext_bravais = 'mC1' else: if ( abs(-a * cosbeta / c + a**2 * (1.0 - cosbeta**2) / b**2 - 1.0) < threshold ): warnings.warn( - "mC lattice, but -a*cos(beta)/c + " - "a^2*sin(beta)^2/b^2 almost equal to 1", + 'mC lattice, but -a*cos(beta)/c + ' + 'a^2*sin(beta)^2/b^2 almost equal to 1', EdgeCaseWarning, ) if -a * cosbeta / c + a**2 * (1.0 - cosbeta**2) / b**2 <= 1.0: # 12-face - ext_bravais = "mC2" + ext_bravais = 'mC2' else: - ext_bravais = "mC3" - elif bravais_lattice == "aP": + ext_bravais = 'mC3' + elif bravais_lattice == 'aP': # First step: cell that is Niggli reduced in reciprocal space # I use the default eps here, this could be changed reciprocal_cell_orig = get_reciprocal_cell_rows(conv_lattice) @@ -348,27 +342,27 @@ def get_path( # First change of vectors to have |ka3 kb3 cosgamma3| smallest real_cell3 = np.dot(np.array(real_cell2).T, M2).T reciprocal_cell3 = get_reciprocal_cell_rows(real_cell3) - ka3, kb3, kc3, coskalpha3, coskbeta3, coskgamma3 = get_cell_params( - reciprocal_cell3 - ) + _, _, _, coskalpha3, coskbeta3, coskgamma3 = get_cell_params(reciprocal_cell3) if abs(coskalpha3) < threshold: warnings.warn( - "aP lattice, but the k_alpha3 angle is almost equal " "to 90 degrees", + 'aP lattice, but the k_alpha3 angle is almost equal to 90 degrees', EdgeCaseWarning, ) if abs(coskbeta3) < threshold: warnings.warn( - "aP lattice, but the k_beta3 angle is almost equal " "to 90 degrees", + 'aP lattice, but the k_beta3 angle is almost equal to 90 degrees', EdgeCaseWarning, ) if abs(coskgamma3) < threshold: warnings.warn( - "aP lattice, but the k_gamma3 angle is almost equal " "to 90 degrees", + 'aP lattice, but the k_gamma3 angle is almost equal to 90 degrees', EdgeCaseWarning, ) # Make them all-acute or all-obtuse with the additional conditions # explained in HPKOT # Note: cos > 0 => angle < 90deg + + # pylint: disable=chained-comparison if coskalpha3 > 0.0 and coskbeta3 > 0.0 and coskgamma3 > 0.0: # 1a M3 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) elif coskalpha3 <= 0.0 and coskbeta3 <= 0.0 and coskgamma3 <= 0.0: # 1b @@ -387,36 +381,29 @@ def get_path( M3 = np.array([[-1, 0, 0], [0, -1, 0], [0, 0, 1]]) else: raise ValueError( - "Problem identifying M3 matrix in aP lattice!" - "Sign of cosines: cos(kalpha3){}0, " - "cos(kbeta3){}0, cos(kgamma3){}0".format( - ">=" if coskalpha3 >= 0 else "<", - ">=" if coskbeta3 >= 0 else "<", - ">=" if coskgamma3 >= 0 else "<", - ) + 'Problem identifying M3 matrix in aP lattice!' + f'Sign of cosines: cos(kalpha3){">=" if coskalpha3 >= 0 else "<"}0, ' + f'cos(kbeta3){">=" if coskbeta3 >= 0 else "<"}0, cos(kgamma3){">=" if coskgamma3 >= 0 else "<"}0' ) + # pylint: enable=chained-comparison real_cell_final = np.dot(real_cell3.T, M3).T reciprocal_cell_final = get_reciprocal_cell_rows(real_cell_final) - ka, kb, kc, coskalpha, coskbeta, coskgamma = get_cell_params( - reciprocal_cell_final - ) + _, _, _, coskalpha, coskbeta, coskgamma = get_cell_params(reciprocal_cell_final) if coskalpha <= 0.0 and coskbeta <= 0.0 and coskgamma <= 0.0: # all-obtuse - ext_bravais = "aP2" + ext_bravais = 'aP2' elif coskalpha >= 0.0 and coskbeta >= 0.0 and coskgamma >= 0.0: # all-acute - ext_bravais = "aP3" + ext_bravais = 'aP3' else: raise ValueError( - "Unexpected aP triclinic lattice, it neither " - "all-obtuse nor all-acute! Sign of cosines: cos(kalpha){}0, " - "cos(kbeta){}0, cos(kgamma){}0".format( - ">=" if coskalpha >= 0 else "<", - ">=" if coskbeta >= 0 else "<", - ">=" if coskgamma >= 0 else "<", - ) + 'Unexpected aP triclinic lattice, it neither ' + 'all-obtuse nor all-acute! Sign of cosines: cos(kalpha)' + f'{">=" if coskalpha >= 0 else "<"}0, ' + f'cos(kbeta){">=" if coskbeta >= 0 else "<"}0, cos(kgamma)' + f'{">=" if coskgamma >= 0 else "<"}0' ) # Get absolute positions @@ -429,19 +416,18 @@ def get_path( # TODO: implement the correct one (probably we need the matrix # out from niggli, and then we can combine it with M2 and M3??) # We set it to None for the time being to avoid confusion - transformation_matrix = None + + # transformation_matrix = None else: raise ValueError( - "Unknown type '{}' for spacegroup {}".format( - bravais_lattice, dataset.number - ) + f"Unknown type '{bravais_lattice}' for spacegroup {dataset.number}" ) # NOTE: we simply use spglib.find_primitive, because the # find_primitive of spglib follows a different convention for mC # and oA as explained in the HPKOT paper - (prim_lattice, prim_pos, prim_types), (P, invP), conv_prim_mapping = get_primitive( + (prim_lattice, prim_pos, prim_types), (P, invP), _ = get_primitive( structure=(conv_lattice, conv_positions, conv_types), bravais_lattice=bravais_lattice, ) @@ -473,52 +459,51 @@ def get_path( # If there is no inversion symmetry nor time-reversal symmetry, add # additional path - if not has_inv and not with_time_reversal: - augmented_path = True - else: - augmented_path = False + augmented_path = not has_inv and not with_time_reversal if augmented_path: for pointname, coords in list(points.items()): - if pointname == "GAMMA": + if pointname == 'GAMMA': continue - points["{}'".format(pointname)] = [-coords[0], -coords[1], -coords[2]] + points[f"{pointname}'"] = [-coords[0], -coords[1], -coords[2]] + points[f"{pointname}'"] = [-coords[0], -coords[1], -coords[2]] old_path = copy.deepcopy(path) for start_p, end_p in old_path: - if start_p == "GAMMA": + if start_p == 'GAMMA': new_start_p = start_p else: - new_start_p = "{}'".format(start_p) - if end_p == "GAMMA": + new_start_p = f"{start_p}'" + if end_p == 'GAMMA': new_end_p = end_p else: - new_end_p = "{}'".format(end_p) + new_end_p = f"{end_p}'" + new_end_p = f"{end_p}'" path.append((new_start_p, new_end_p)) return { - "point_coords": points, - "path": path, - "has_inversion_symmetry": has_inv, - "augmented_path": augmented_path, - "bravais_lattice": bravais_lattice, - "bravais_lattice_extended": ext_bravais, - "conv_lattice": conv_lattice, - "conv_positions": conv_positions, - "conv_types": conv_types, - "primitive_lattice": prim_lattice, - "primitive_positions": prim_pos, - "primitive_types": prim_types, - "reciprocal_primitive_lattice": get_reciprocal_cell_rows(prim_lattice), + 'point_coords': points, + 'path': path, + 'has_inversion_symmetry': has_inv, + 'augmented_path': augmented_path, + 'bravais_lattice': bravais_lattice, + 'bravais_lattice_extended': ext_bravais, + 'conv_lattice': conv_lattice, + 'conv_positions': conv_positions, + 'conv_types': conv_types, + 'primitive_lattice': prim_lattice, + 'primitive_positions': prim_pos, + 'primitive_types': prim_types, + 'reciprocal_primitive_lattice': get_reciprocal_cell_rows(prim_lattice), # The following: between conv and primitive, see docstring of # spg_mapping.get_P_matrix - "inverse_primitive_transformation_matrix": invP, - "primitive_transformation_matrix": P, + 'inverse_primitive_transformation_matrix': invP, + 'primitive_transformation_matrix': P, # For the time being disabled, not valid for aP lattices # (for which we would need the transformation matrix from niggli) #'transformation_matrix': transf_matrix, - "volume_original_wrt_conv": volume_conv_wrt_original, - "volume_original_wrt_prim": volume_conv_wrt_original * np.linalg.det(invP), - "spacegroup_number": dataset.number, - "spacegroup_international": dataset.international, - "rotation_matrix": dataset.std_rotation_matrix, + 'volume_original_wrt_conv': volume_conv_wrt_original, + 'volume_original_wrt_prim': volume_conv_wrt_original * np.linalg.det(invP), + 'spacegroup_number': dataset.number, + 'spacegroup_international': dataset.international, + 'rotation_matrix': dataset.std_rotation_matrix, } diff --git a/seekpath/hpkot/spg_db.py b/seekpath/hpkot/spg_db.py index 71a7785..feea7d4 100644 --- a/seekpath/hpkot/spg_db.py +++ b/seekpath/hpkot/spg_db.py @@ -6,467 +6,467 @@ # using spglib v.1.9.4. spgroup_data = { - 1: ("a", "P", False), - 2: ("a", "P", True), - 3: ("m", "P", False), - 4: ("m", "P", False), - 5: ("m", "C", False), - 6: ("m", "P", False), - 7: ("m", "P", False), - 8: ("m", "C", False), - 9: ("m", "C", False), - 10: ("m", "P", True), - 11: ("m", "P", True), - 12: ("m", "C", True), - 13: ("m", "P", True), - 14: ("m", "P", True), - 15: ("m", "C", True), - 16: ("o", "P", False), - 17: ("o", "P", False), - 18: ("o", "P", False), - 19: ("o", "P", False), - 20: ("o", "C", False), - 21: ("o", "C", False), - 22: ("o", "F", False), - 23: ("o", "I", False), - 24: ("o", "I", False), - 25: ("o", "P", False), - 26: ("o", "P", False), - 27: ("o", "P", False), - 28: ("o", "P", False), - 29: ("o", "P", False), - 30: ("o", "P", False), - 31: ("o", "P", False), - 32: ("o", "P", False), - 33: ("o", "P", False), - 34: ("o", "P", False), - 35: ("o", "C", False), - 36: ("o", "C", False), - 37: ("o", "C", False), - 38: ("o", "A", False), - 39: ("o", "A", False), - 40: ("o", "A", False), - 41: ("o", "A", False), - 42: ("o", "F", False), - 43: ("o", "F", False), - 44: ("o", "I", False), - 45: ("o", "I", False), - 46: ("o", "I", False), - 47: ("o", "P", True), - 48: ("o", "P", True), - 49: ("o", "P", True), - 50: ("o", "P", True), - 51: ("o", "P", True), - 52: ("o", "P", True), - 53: ("o", "P", True), - 54: ("o", "P", True), - 55: ("o", "P", True), - 56: ("o", "P", True), - 57: ("o", "P", True), - 58: ("o", "P", True), - 59: ("o", "P", True), - 60: ("o", "P", True), - 61: ("o", "P", True), - 62: ("o", "P", True), - 63: ("o", "C", True), - 64: ("o", "C", True), - 65: ("o", "C", True), - 66: ("o", "C", True), - 67: ("o", "C", True), - 68: ("o", "C", True), - 69: ("o", "F", True), - 70: ("o", "F", True), - 71: ("o", "I", True), - 72: ("o", "I", True), - 73: ("o", "I", True), - 74: ("o", "I", True), - 75: ("t", "P", False), - 76: ("t", "P", False), - 77: ("t", "P", False), - 78: ("t", "P", False), - 79: ("t", "I", False), - 80: ("t", "I", False), - 81: ("t", "P", False), - 82: ("t", "I", False), - 83: ("t", "P", True), - 84: ("t", "P", True), - 85: ("t", "P", True), - 86: ("t", "P", True), - 87: ("t", "I", True), - 88: ("t", "I", True), - 89: ("t", "P", False), - 90: ("t", "P", False), - 91: ("t", "P", False), - 92: ("t", "P", False), - 93: ("t", "P", False), - 94: ("t", "P", False), - 95: ("t", "P", False), - 96: ("t", "P", False), - 97: ("t", "I", False), - 98: ("t", "I", False), - 99: ("t", "P", False), - 100: ("t", "P", False), - 101: ("t", "P", False), - 102: ("t", "P", False), - 103: ("t", "P", False), - 104: ("t", "P", False), - 105: ("t", "P", False), - 106: ("t", "P", False), - 107: ("t", "I", False), - 108: ("t", "I", False), - 109: ("t", "I", False), - 110: ("t", "I", False), - 111: ("t", "P", False), - 112: ("t", "P", False), - 113: ("t", "P", False), - 114: ("t", "P", False), - 115: ("t", "P", False), - 116: ("t", "P", False), - 117: ("t", "P", False), - 118: ("t", "P", False), - 119: ("t", "I", False), - 120: ("t", "I", False), - 121: ("t", "I", False), - 122: ("t", "I", False), - 123: ("t", "P", True), - 124: ("t", "P", True), - 125: ("t", "P", True), - 126: ("t", "P", True), - 127: ("t", "P", True), - 128: ("t", "P", True), - 129: ("t", "P", True), - 130: ("t", "P", True), - 131: ("t", "P", True), - 132: ("t", "P", True), - 133: ("t", "P", True), - 134: ("t", "P", True), - 135: ("t", "P", True), - 136: ("t", "P", True), - 137: ("t", "P", True), - 138: ("t", "P", True), - 139: ("t", "I", True), - 140: ("t", "I", True), - 141: ("t", "I", True), - 142: ("t", "I", True), - 143: ("h", "P", False), - 144: ("h", "P", False), - 145: ("h", "P", False), - 146: ("h", "R", False), - 147: ("h", "P", True), - 148: ("h", "R", True), - 149: ("h", "P", False), - 150: ("h", "P", False), - 151: ("h", "P", False), - 152: ("h", "P", False), - 153: ("h", "P", False), - 154: ("h", "P", False), - 155: ("h", "R", False), - 156: ("h", "P", False), - 157: ("h", "P", False), - 158: ("h", "P", False), - 159: ("h", "P", False), - 160: ("h", "R", False), - 161: ("h", "R", False), - 162: ("h", "P", True), - 163: ("h", "P", True), - 164: ("h", "P", True), - 165: ("h", "P", True), - 166: ("h", "R", True), - 167: ("h", "R", True), - 168: ("h", "P", False), - 169: ("h", "P", False), - 170: ("h", "P", False), - 171: ("h", "P", False), - 172: ("h", "P", False), - 173: ("h", "P", False), - 174: ("h", "P", False), - 175: ("h", "P", True), - 176: ("h", "P", True), - 177: ("h", "P", False), - 178: ("h", "P", False), - 179: ("h", "P", False), - 180: ("h", "P", False), - 181: ("h", "P", False), - 182: ("h", "P", False), - 183: ("h", "P", False), - 184: ("h", "P", False), - 185: ("h", "P", False), - 186: ("h", "P", False), - 187: ("h", "P", False), - 188: ("h", "P", False), - 189: ("h", "P", False), - 190: ("h", "P", False), - 191: ("h", "P", True), - 192: ("h", "P", True), - 193: ("h", "P", True), - 194: ("h", "P", True), - 195: ("c", "P", False), - 196: ("c", "F", False), - 197: ("c", "I", False), - 198: ("c", "P", False), - 199: ("c", "I", False), - 200: ("c", "P", True), - 201: ("c", "P", True), - 202: ("c", "F", True), - 203: ("c", "F", True), - 204: ("c", "I", True), - 205: ("c", "P", True), - 206: ("c", "I", True), - 207: ("c", "P", False), - 208: ("c", "P", False), - 209: ("c", "F", False), - 210: ("c", "F", False), - 211: ("c", "I", False), - 212: ("c", "P", False), - 213: ("c", "P", False), - 214: ("c", "I", False), - 215: ("c", "P", False), - 216: ("c", "F", False), - 217: ("c", "I", False), - 218: ("c", "P", False), - 219: ("c", "F", False), - 220: ("c", "I", False), - 221: ("c", "P", True), - 222: ("c", "P", True), - 223: ("c", "P", True), - 224: ("c", "P", True), - 225: ("c", "F", True), - 226: ("c", "F", True), - 227: ("c", "F", True), - 228: ("c", "F", True), - 229: ("c", "I", True), - 230: ("c", "I", True), + 1: ('a', 'P', False), + 2: ('a', 'P', True), + 3: ('m', 'P', False), + 4: ('m', 'P', False), + 5: ('m', 'C', False), + 6: ('m', 'P', False), + 7: ('m', 'P', False), + 8: ('m', 'C', False), + 9: ('m', 'C', False), + 10: ('m', 'P', True), + 11: ('m', 'P', True), + 12: ('m', 'C', True), + 13: ('m', 'P', True), + 14: ('m', 'P', True), + 15: ('m', 'C', True), + 16: ('o', 'P', False), + 17: ('o', 'P', False), + 18: ('o', 'P', False), + 19: ('o', 'P', False), + 20: ('o', 'C', False), + 21: ('o', 'C', False), + 22: ('o', 'F', False), + 23: ('o', 'I', False), + 24: ('o', 'I', False), + 25: ('o', 'P', False), + 26: ('o', 'P', False), + 27: ('o', 'P', False), + 28: ('o', 'P', False), + 29: ('o', 'P', False), + 30: ('o', 'P', False), + 31: ('o', 'P', False), + 32: ('o', 'P', False), + 33: ('o', 'P', False), + 34: ('o', 'P', False), + 35: ('o', 'C', False), + 36: ('o', 'C', False), + 37: ('o', 'C', False), + 38: ('o', 'A', False), + 39: ('o', 'A', False), + 40: ('o', 'A', False), + 41: ('o', 'A', False), + 42: ('o', 'F', False), + 43: ('o', 'F', False), + 44: ('o', 'I', False), + 45: ('o', 'I', False), + 46: ('o', 'I', False), + 47: ('o', 'P', True), + 48: ('o', 'P', True), + 49: ('o', 'P', True), + 50: ('o', 'P', True), + 51: ('o', 'P', True), + 52: ('o', 'P', True), + 53: ('o', 'P', True), + 54: ('o', 'P', True), + 55: ('o', 'P', True), + 56: ('o', 'P', True), + 57: ('o', 'P', True), + 58: ('o', 'P', True), + 59: ('o', 'P', True), + 60: ('o', 'P', True), + 61: ('o', 'P', True), + 62: ('o', 'P', True), + 63: ('o', 'C', True), + 64: ('o', 'C', True), + 65: ('o', 'C', True), + 66: ('o', 'C', True), + 67: ('o', 'C', True), + 68: ('o', 'C', True), + 69: ('o', 'F', True), + 70: ('o', 'F', True), + 71: ('o', 'I', True), + 72: ('o', 'I', True), + 73: ('o', 'I', True), + 74: ('o', 'I', True), + 75: ('t', 'P', False), + 76: ('t', 'P', False), + 77: ('t', 'P', False), + 78: ('t', 'P', False), + 79: ('t', 'I', False), + 80: ('t', 'I', False), + 81: ('t', 'P', False), + 82: ('t', 'I', False), + 83: ('t', 'P', True), + 84: ('t', 'P', True), + 85: ('t', 'P', True), + 86: ('t', 'P', True), + 87: ('t', 'I', True), + 88: ('t', 'I', True), + 89: ('t', 'P', False), + 90: ('t', 'P', False), + 91: ('t', 'P', False), + 92: ('t', 'P', False), + 93: ('t', 'P', False), + 94: ('t', 'P', False), + 95: ('t', 'P', False), + 96: ('t', 'P', False), + 97: ('t', 'I', False), + 98: ('t', 'I', False), + 99: ('t', 'P', False), + 100: ('t', 'P', False), + 101: ('t', 'P', False), + 102: ('t', 'P', False), + 103: ('t', 'P', False), + 104: ('t', 'P', False), + 105: ('t', 'P', False), + 106: ('t', 'P', False), + 107: ('t', 'I', False), + 108: ('t', 'I', False), + 109: ('t', 'I', False), + 110: ('t', 'I', False), + 111: ('t', 'P', False), + 112: ('t', 'P', False), + 113: ('t', 'P', False), + 114: ('t', 'P', False), + 115: ('t', 'P', False), + 116: ('t', 'P', False), + 117: ('t', 'P', False), + 118: ('t', 'P', False), + 119: ('t', 'I', False), + 120: ('t', 'I', False), + 121: ('t', 'I', False), + 122: ('t', 'I', False), + 123: ('t', 'P', True), + 124: ('t', 'P', True), + 125: ('t', 'P', True), + 126: ('t', 'P', True), + 127: ('t', 'P', True), + 128: ('t', 'P', True), + 129: ('t', 'P', True), + 130: ('t', 'P', True), + 131: ('t', 'P', True), + 132: ('t', 'P', True), + 133: ('t', 'P', True), + 134: ('t', 'P', True), + 135: ('t', 'P', True), + 136: ('t', 'P', True), + 137: ('t', 'P', True), + 138: ('t', 'P', True), + 139: ('t', 'I', True), + 140: ('t', 'I', True), + 141: ('t', 'I', True), + 142: ('t', 'I', True), + 143: ('h', 'P', False), + 144: ('h', 'P', False), + 145: ('h', 'P', False), + 146: ('h', 'R', False), + 147: ('h', 'P', True), + 148: ('h', 'R', True), + 149: ('h', 'P', False), + 150: ('h', 'P', False), + 151: ('h', 'P', False), + 152: ('h', 'P', False), + 153: ('h', 'P', False), + 154: ('h', 'P', False), + 155: ('h', 'R', False), + 156: ('h', 'P', False), + 157: ('h', 'P', False), + 158: ('h', 'P', False), + 159: ('h', 'P', False), + 160: ('h', 'R', False), + 161: ('h', 'R', False), + 162: ('h', 'P', True), + 163: ('h', 'P', True), + 164: ('h', 'P', True), + 165: ('h', 'P', True), + 166: ('h', 'R', True), + 167: ('h', 'R', True), + 168: ('h', 'P', False), + 169: ('h', 'P', False), + 170: ('h', 'P', False), + 171: ('h', 'P', False), + 172: ('h', 'P', False), + 173: ('h', 'P', False), + 174: ('h', 'P', False), + 175: ('h', 'P', True), + 176: ('h', 'P', True), + 177: ('h', 'P', False), + 178: ('h', 'P', False), + 179: ('h', 'P', False), + 180: ('h', 'P', False), + 181: ('h', 'P', False), + 182: ('h', 'P', False), + 183: ('h', 'P', False), + 184: ('h', 'P', False), + 185: ('h', 'P', False), + 186: ('h', 'P', False), + 187: ('h', 'P', False), + 188: ('h', 'P', False), + 189: ('h', 'P', False), + 190: ('h', 'P', False), + 191: ('h', 'P', True), + 192: ('h', 'P', True), + 193: ('h', 'P', True), + 194: ('h', 'P', True), + 195: ('c', 'P', False), + 196: ('c', 'F', False), + 197: ('c', 'I', False), + 198: ('c', 'P', False), + 199: ('c', 'I', False), + 200: ('c', 'P', True), + 201: ('c', 'P', True), + 202: ('c', 'F', True), + 203: ('c', 'F', True), + 204: ('c', 'I', True), + 205: ('c', 'P', True), + 206: ('c', 'I', True), + 207: ('c', 'P', False), + 208: ('c', 'P', False), + 209: ('c', 'F', False), + 210: ('c', 'F', False), + 211: ('c', 'I', False), + 212: ('c', 'P', False), + 213: ('c', 'P', False), + 214: ('c', 'I', False), + 215: ('c', 'P', False), + 216: ('c', 'F', False), + 217: ('c', 'I', False), + 218: ('c', 'P', False), + 219: ('c', 'F', False), + 220: ('c', 'I', False), + 221: ('c', 'P', True), + 222: ('c', 'P', True), + 223: ('c', 'P', True), + 224: ('c', 'P', True), + 225: ('c', 'F', True), + 226: ('c', 'F', True), + 227: ('c', 'F', True), + 228: ('c', 'F', True), + 229: ('c', 'I', True), + 230: ('c', 'I', True), } centering = { - 1: "P", - 2: "P", - 3: "P", - 4: "P", - 5: "C", - 6: "P", - 7: "P", - 8: "C", - 9: "C", - 10: "P", - 11: "P", - 12: "C", - 13: "P", - 14: "P", - 15: "C", - 16: "P", - 17: "P", - 18: "P", - 19: "P", - 20: "C", - 21: "C", - 22: "F", - 23: "I", - 24: "I", - 25: "P", - 26: "P", - 27: "P", - 28: "P", - 29: "P", - 30: "P", - 31: "P", - 32: "P", - 33: "P", - 34: "P", - 35: "C", - 36: "C", - 37: "C", - 38: "A", - 39: "A", - 40: "A", - 41: "A", - 42: "F", - 43: "F", - 44: "I", - 45: "I", - 46: "I", - 47: "P", - 48: "P", - 49: "P", - 50: "P", - 51: "P", - 52: "P", - 53: "P", - 54: "P", - 55: "P", - 56: "P", - 57: "P", - 58: "P", - 59: "P", - 60: "P", - 61: "P", - 62: "P", - 63: "C", - 64: "C", - 65: "C", - 66: "C", - 67: "C", - 68: "C", - 69: "F", - 70: "F", - 71: "I", - 72: "I", - 73: "I", - 74: "I", - 75: "P", - 76: "P", - 77: "P", - 78: "P", - 79: "I", - 80: "I", - 81: "P", - 82: "I", - 83: "P", - 84: "P", - 85: "P", - 86: "P", - 87: "I", - 88: "I", - 89: "P", - 90: "P", - 91: "P", - 92: "P", - 93: "P", - 94: "P", - 95: "P", - 96: "P", - 97: "I", - 98: "I", - 99: "P", - 100: "P", - 101: "P", - 102: "P", - 103: "P", - 104: "P", - 105: "P", - 106: "P", - 107: "I", - 108: "I", - 109: "I", - 110: "I", - 111: "P", - 112: "P", - 113: "P", - 114: "P", - 115: "P", - 116: "P", - 117: "P", - 118: "P", - 119: "I", - 120: "I", - 121: "I", - 122: "I", - 123: "P", - 124: "P", - 125: "P", - 126: "P", - 127: "P", - 128: "P", - 129: "P", - 130: "P", - 131: "P", - 132: "P", - 133: "P", - 134: "P", - 135: "P", - 136: "P", - 137: "P", - 138: "P", - 139: "I", - 140: "I", - 141: "I", - 142: "I", - 143: "P", - 144: "P", - 145: "P", - 146: "R", - 147: "P", - 148: "R", - 149: "P", - 150: "P", - 151: "P", - 152: "P", - 153: "P", - 154: "P", - 155: "R", - 156: "P", - 157: "P", - 158: "P", - 159: "P", - 160: "R", - 161: "R", - 162: "P", - 163: "P", - 164: "P", - 165: "P", - 166: "R", - 167: "R", - 168: "P", - 169: "P", - 170: "P", - 171: "P", - 172: "P", - 173: "P", - 174: "P", - 175: "P", - 176: "P", - 177: "P", - 178: "P", - 179: "P", - 180: "P", - 181: "P", - 182: "P", - 183: "P", - 184: "P", - 185: "P", - 186: "P", - 187: "P", - 188: "P", - 189: "P", - 190: "P", - 191: "P", - 192: "P", - 193: "P", - 194: "P", - 195: "P", - 196: "F", - 197: "I", - 198: "P", - 199: "I", - 200: "P", - 201: "P", - 202: "F", - 203: "F", - 204: "I", - 205: "P", - 206: "I", - 207: "P", - 208: "P", - 209: "F", - 210: "F", - 211: "I", - 212: "P", - 213: "P", - 214: "I", - 215: "P", - 216: "F", - 217: "I", - 218: "P", - 219: "F", - 220: "I", - 221: "P", - 222: "P", - 223: "P", - 224: "P", - 225: "F", - 226: "F", - 227: "F", - 228: "F", - 229: "I", - 230: "I", + 1: 'P', + 2: 'P', + 3: 'P', + 4: 'P', + 5: 'C', + 6: 'P', + 7: 'P', + 8: 'C', + 9: 'C', + 10: 'P', + 11: 'P', + 12: 'C', + 13: 'P', + 14: 'P', + 15: 'C', + 16: 'P', + 17: 'P', + 18: 'P', + 19: 'P', + 20: 'C', + 21: 'C', + 22: 'F', + 23: 'I', + 24: 'I', + 25: 'P', + 26: 'P', + 27: 'P', + 28: 'P', + 29: 'P', + 30: 'P', + 31: 'P', + 32: 'P', + 33: 'P', + 34: 'P', + 35: 'C', + 36: 'C', + 37: 'C', + 38: 'A', + 39: 'A', + 40: 'A', + 41: 'A', + 42: 'F', + 43: 'F', + 44: 'I', + 45: 'I', + 46: 'I', + 47: 'P', + 48: 'P', + 49: 'P', + 50: 'P', + 51: 'P', + 52: 'P', + 53: 'P', + 54: 'P', + 55: 'P', + 56: 'P', + 57: 'P', + 58: 'P', + 59: 'P', + 60: 'P', + 61: 'P', + 62: 'P', + 63: 'C', + 64: 'C', + 65: 'C', + 66: 'C', + 67: 'C', + 68: 'C', + 69: 'F', + 70: 'F', + 71: 'I', + 72: 'I', + 73: 'I', + 74: 'I', + 75: 'P', + 76: 'P', + 77: 'P', + 78: 'P', + 79: 'I', + 80: 'I', + 81: 'P', + 82: 'I', + 83: 'P', + 84: 'P', + 85: 'P', + 86: 'P', + 87: 'I', + 88: 'I', + 89: 'P', + 90: 'P', + 91: 'P', + 92: 'P', + 93: 'P', + 94: 'P', + 95: 'P', + 96: 'P', + 97: 'I', + 98: 'I', + 99: 'P', + 100: 'P', + 101: 'P', + 102: 'P', + 103: 'P', + 104: 'P', + 105: 'P', + 106: 'P', + 107: 'I', + 108: 'I', + 109: 'I', + 110: 'I', + 111: 'P', + 112: 'P', + 113: 'P', + 114: 'P', + 115: 'P', + 116: 'P', + 117: 'P', + 118: 'P', + 119: 'I', + 120: 'I', + 121: 'I', + 122: 'I', + 123: 'P', + 124: 'P', + 125: 'P', + 126: 'P', + 127: 'P', + 128: 'P', + 129: 'P', + 130: 'P', + 131: 'P', + 132: 'P', + 133: 'P', + 134: 'P', + 135: 'P', + 136: 'P', + 137: 'P', + 138: 'P', + 139: 'I', + 140: 'I', + 141: 'I', + 142: 'I', + 143: 'P', + 144: 'P', + 145: 'P', + 146: 'R', + 147: 'P', + 148: 'R', + 149: 'P', + 150: 'P', + 151: 'P', + 152: 'P', + 153: 'P', + 154: 'P', + 155: 'R', + 156: 'P', + 157: 'P', + 158: 'P', + 159: 'P', + 160: 'R', + 161: 'R', + 162: 'P', + 163: 'P', + 164: 'P', + 165: 'P', + 166: 'R', + 167: 'R', + 168: 'P', + 169: 'P', + 170: 'P', + 171: 'P', + 172: 'P', + 173: 'P', + 174: 'P', + 175: 'P', + 176: 'P', + 177: 'P', + 178: 'P', + 179: 'P', + 180: 'P', + 181: 'P', + 182: 'P', + 183: 'P', + 184: 'P', + 185: 'P', + 186: 'P', + 187: 'P', + 188: 'P', + 189: 'P', + 190: 'P', + 191: 'P', + 192: 'P', + 193: 'P', + 194: 'P', + 195: 'P', + 196: 'F', + 197: 'I', + 198: 'P', + 199: 'I', + 200: 'P', + 201: 'P', + 202: 'F', + 203: 'F', + 204: 'I', + 205: 'P', + 206: 'I', + 207: 'P', + 208: 'P', + 209: 'F', + 210: 'F', + 211: 'I', + 212: 'P', + 213: 'P', + 214: 'I', + 215: 'P', + 216: 'F', + 217: 'I', + 218: 'P', + 219: 'F', + 220: 'I', + 221: 'P', + 222: 'P', + 223: 'P', + 224: 'P', + 225: 'F', + 226: 'F', + 227: 'F', + 228: 'F', + 229: 'I', + 230: 'I', } diff --git a/seekpath/hpkot/spg_mapping.py b/seekpath/hpkot/spg_mapping.py index ed7234c..2b59d91 100644 --- a/seekpath/hpkot/spg_mapping.py +++ b/seekpath/hpkot/spg_mapping.py @@ -9,22 +9,22 @@ def get_crystal_family(number): :param number: the spacegroup number, from 1 to 230 """ if not isinstance(number, int): - raise TypeError("number should be integer") + raise TypeError('number should be integer') if number < 1: - raise ValueError("number should be >= 1") + raise ValueError('number should be >= 1') if number <= 2: - return "a" # triclinic + return 'a' # triclinic if number <= 15: - return "m" # monoclinic + return 'm' # monoclinic if number <= 74: - return "o" # orthorhombic + return 'o' # orthorhombic if number <= 142: - return "t" # tetragonal + return 't' # tetragonal if number <= 194: - return "h" # trigonal + hexagonal + return 'h' # trigonal + hexagonal if number <= 230: - return "c" # cubic - raise ValueError("number should be <= 230") + return 'c' # cubic + raise ValueError('number should be <= 230') def pointgroup_has_inversion(number): @@ -60,7 +60,7 @@ def pointgroup_has_inversion(number): 31, ]: return False - raise ValueError("number should be between 1 and 32") + raise ValueError('number should be between 1 and 32') def pgnum_from_pgint(pgint): @@ -69,38 +69,38 @@ def pgnum_from_pgint(pgint): international pointgroup name. """ table = { - "C1": 1, - "C2": 3, - "C2h": 5, - "C2v": 7, - "C3": 16, - "C3h": 22, - "C3i": 17, - "C3v": 19, - "C4": 9, - "C4h": 11, - "C4v": 13, - "C6": 21, - "C6h": 23, - "C6v": 25, - "Ci": 2, - "Cs": 4, - "D2": 6, - "D2d": 14, - "D2h": 8, - "D3": 18, - "D3d": 20, - "D3h": 26, - "D4": 12, - "D4h": 15, - "D6": 24, - "D6h": 27, - "O": 30, - "Oh": 32, - "S4": 10, - "T": 28, - "Td": 31, - "Th": 29, + 'C1': 1, + 'C2': 3, + 'C2h': 5, + 'C2v': 7, + 'C3': 16, + 'C3h': 22, + 'C3i': 17, + 'C3v': 19, + 'C4': 9, + 'C4h': 11, + 'C4v': 13, + 'C6': 21, + 'C6h': 23, + 'C6v': 25, + 'Ci': 2, + 'Cs': 4, + 'D2': 6, + 'D2d': 14, + 'D2h': 8, + 'D3': 18, + 'D3d': 20, + 'D3h': 26, + 'D4': 12, + 'D4h': 15, + 'D6': 24, + 'D6h': 27, + 'O': 30, + 'Oh': 32, + 'S4': 10, + 'T': 28, + 'Td': 31, + 'Th': 29, } return table[pgint] @@ -129,7 +129,6 @@ def get_spgroup_data_realtime(): got in real time using spglib methods. """ - import json import spglib from .tools import get_dot_access_dataset @@ -178,33 +177,33 @@ def get_P_matrix(bravais_lattice): """ import numpy as np - if bravais_lattice in ["cP", "tP", "hP", "oP", "mP"]: + if bravais_lattice in ['cP', 'tP', 'hP', 'oP', 'mP']: P = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) invP = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) - elif bravais_lattice in ["cF", "oF"]: + elif bravais_lattice in ['cF', 'oF']: P = 1.0 / 2.0 * np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]) invP = np.array([[-1, 1, 1], [1, -1, 1], [1, 1, -1]]) - elif bravais_lattice in ["cI", "tI", "oI"]: + elif bravais_lattice in ['cI', 'tI', 'oI']: P = 1.0 / 2.0 * np.array([[-1, 1, 1], [1, -1, 1], [1, 1, -1]]) invP = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]) - elif bravais_lattice == "hR": + elif bravais_lattice == 'hR': P = 1.0 / 3.0 * np.array([[2, -1, -1], [1, 1, -2], [1, 1, 1]]) invP = np.array([[1, 0, 1], [-1, 1, 1], [0, -1, 1]]) - elif bravais_lattice == "oC": + elif bravais_lattice == 'oC': P = 1.0 / 2.0 * np.array([[1, 1, 0], [-1, 1, 0], [0, 0, 2]]) invP = np.array([[1, -1, 0], [1, 1, 0], [0, 0, 1]]) - elif bravais_lattice == "oA": + elif bravais_lattice == 'oA': P = 1.0 / 2.0 * np.array([[0, 0, 2], [1, 1, 0], [-1, 1, 0]]) invP = np.array([[0, 1, -1], [0, 1, 1], [1, 0, 0]]) - elif bravais_lattice == "mC": + elif bravais_lattice == 'mC': P = 1.0 / 2.0 * np.array([[1, -1, 0], [1, 1, 0], [0, 0, 2]]) invP = np.array([[1, 1, 0], [-1, 1, 0], [0, 0, 1]]) - elif bravais_lattice == "aP": + elif bravais_lattice == 'aP': # For aP, I should have already obtained the primitive cell P = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) invP = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) else: - raise ValueError("Invalid bravais_lattice {}".format(bravais_lattice)) + raise ValueError(f'Invalid bravais_lattice {bravais_lattice}') return P, invP @@ -293,10 +292,9 @@ def get_primitive(structure, bravais_lattice, wrap_to_zero_one=False): wrong_count = [group for group, cnt in group_count.items() if cnt != volume_ratio] if wrong_count: raise ValueError( - "Problem creating primitive cell, I found the " - "following group of atoms with len != {}: {}".format( - volume_ratio, ", ".join(str(_) for _ in wrong_count) - ) + 'Problem creating primitive cell, I found the ' + f'following group of atoms with len != {volume_ratio}:' + f' {", ".join(str(_) for _ in wrong_count)}' ) # These are the groups of equivalent atoms; values are the positions in # the list from 0 to N-1 @@ -309,17 +307,16 @@ def get_primitive(structure, bravais_lattice, wrap_to_zero_one=False): if len(type_set) != 1 ) if problematic_groups_idx: + problematic_groups_str = ', '.join( + [ + str(group) + for group_idx, group in enumerate(groups) + if group_idx in problematic_groups_idx + ] + ) raise ValueError( - "The following ids of atoms go on top of each other, " - "but they are of different type! {}".format( - ", ".join( - [ - str(group) - for group_idx, group in enumerate(groups) - if group_idx in problematic_groups_idx - ] - ) - ) + 'The following ids of atoms go on top of each other, ' + f'but they are of different type! {problematic_groups_str}' ) # All good, just return the first (no wrapping to [0..1[ yet) chosen_idx = np.array([group[0] for group in groups]) @@ -331,8 +328,7 @@ def get_primitive(structure, bravais_lattice, wrap_to_zero_one=False): conv_prim_atoms_mapping[at_idx] = prim_idx if -1 in conv_prim_atoms_mapping: raise ValueError( - "Unable to recreate correctly the atom mapping! " - "{}".format(conv_prim_atoms_mapping) + f'Unable to recreate correctly the atom mapping! {conv_prim_atoms_mapping}' ) prim_positions = prim_positions[chosen_idx] diff --git a/seekpath/hpkot/tools.py b/seekpath/hpkot/tools.py index 68044f5..41df745 100644 --- a/seekpath/hpkot/tools.py +++ b/seekpath/hpkot/tools.py @@ -18,32 +18,32 @@ def eval_expr_simple(expr, kparam): # pylint=disable: too-many-return-statement """ To evaluate expressions tha only require kparams and not a, b, c, ... """ - if expr == "0": + if expr == '0': return 0.0 - if expr == "1/2": + if expr == '1/2': return 1.0 / 2.0 - if expr == "1": + if expr == '1': return 1.0 - if expr == "-1/2": + if expr == '-1/2': return -1.0 / 2.0 - if expr == "1/4": + if expr == '1/4': return 1.0 / 4.0 - if expr == "3/8": + if expr == '3/8': return 3.0 / 8.0 - if expr == "3/4": + if expr == '3/4': return 3.0 / 4.0 - if expr == "5/8": + if expr == '5/8': return 5.0 / 8.0 - if expr == "1/3": + if expr == '1/3': return 1.0 / 3.0 try: return kparam[expr] except KeyError as exc: raise ValueError( - "Asking for evaluation of symbol '{}' in " - "eval_expr_simple but this has not been defined or not " - "yet computed".format(str(exc)) - ) + f"Asking for evaluation of symbol '{str(exc)}' in " + 'eval_expr_simple but this has not been defined or not ' + 'yet computed' + ) from exc def extend_kparam(kparam): @@ -57,11 +57,11 @@ def extend_kparam(kparam): kparam_extended = {} for key, val in kparam.items(): kparam_extended[key] = val - kparam_extended["-{}".format(key)] = -val - kparam_extended["1-{}".format(key)] = 1.0 - val - kparam_extended["-1+{}".format(key)] = -1.0 + val - kparam_extended["1/2-{}".format(key)] = 1.0 / 2.0 - val - kparam_extended["1/2+{}".format(key)] = 1.0 / 2.0 + val + kparam_extended[f'-{key}'] = -val + kparam_extended[f'1-{key}'] = 1.0 - val + kparam_extended[f'-1+{key}'] = -1.0 + val + kparam_extended[f'1/2-{key}'] = 1.0 / 2.0 - val + kparam_extended[f'1/2+{key}'] = 1.0 / 2.0 + val return kparam_extended @@ -89,30 +89,29 @@ def eval_expr( # pylint: disable=too-many-return-statements,unused-argument DB rather than parsing the string (to avoid additional dependencies and avoid the use of ``eval``). """ - from math import sqrt # sinalpha = sqrt(1.0 - cosalpha ** 2) sinbeta = sqrt(1.0 - cosbeta**2) # singamma = sqrt(1.0 - cosgamma ** 2) try: - if expr == "(a*a/b/b+(1+a/c*cosbeta)/sinbeta/sinbeta)/4": + if expr == '(a*a/b/b+(1+a/c*cosbeta)/sinbeta/sinbeta)/4': return (a * a / b / b + (1.0 + a / c * cosbeta) / sinbeta / sinbeta) / 4.0 - if expr == "1-Z*b*b/a/a": - Z = kparam["Z"] + if expr == '1-Z*b*b/a/a': + Z = kparam['Z'] return 1.0 - Z * b * b / a / a - if expr == "1/2-2*Z*c*cosbeta/a": - Z = kparam["Z"] + if expr == '1/2-2*Z*c*cosbeta/a': + Z = kparam['Z'] return 1.0 / 2.0 - 2.0 * Z * c * cosbeta / a - if expr == "E/2+a*a/4/b/b+a*c*cosbeta/2/b/b": - E = kparam["E"] + if expr == 'E/2+a*a/4/b/b+a*c*cosbeta/2/b/b': + E = kparam['E'] return E / 2.0 + a * a / 4.0 / b / b + a * c * cosbeta / 2.0 / b / b - if expr == "2*F-Z": - F = kparam["F"] - Z = kparam["Z"] + if expr == '2*F-Z': + F = kparam['F'] + Z = kparam['Z'] return 2.0 * F - Z - if expr == "c/2/a/cosbeta*(1-4*U+a*a*sinbeta*sinbeta/b/b)": - U = kparam["U"] + if expr == 'c/2/a/cosbeta*(1-4*U+a*a*sinbeta*sinbeta/b/b)': + U = kparam['U'] return ( c / 2.0 @@ -120,96 +119,96 @@ def eval_expr( # pylint: disable=too-many-return-statements,unused-argument / cosbeta * (1.0 - 4.0 * U + a * a * sinbeta * sinbeta / b / b) ) - if expr == "-1/4+W/2-Z*c*cosbeta/a": - W = kparam["W"] - Z = kparam["Z"] + if expr == '-1/4+W/2-Z*c*cosbeta/a': + W = kparam['W'] + Z = kparam['Z'] return -1.0 / 4.0 + W / 2.0 - Z * c * cosbeta / a - if expr == "(2+a/c*cosbeta)/4/sinbeta/sinbeta": + if expr == '(2+a/c*cosbeta)/4/sinbeta/sinbeta': return (2.0 + a / c * cosbeta) / 4.0 / sinbeta / sinbeta - if expr == "3/4-b*b/4/a/a/sinbeta/sinbeta": + if expr == '3/4-b*b/4/a/a/sinbeta/sinbeta': return 3.0 / 4.0 - b * b / 4.0 / a / a / sinbeta / sinbeta - if expr == "S-(3/4-S)*a*cosbeta/c": - S = kparam["S"] + if expr == 'S-(3/4-S)*a*cosbeta/c': + S = kparam['S'] return S - (3.0 / 4.0 - S) * a * cosbeta / c - if expr == "(1+a*a/b/b)/4": + if expr == '(1+a*a/b/b)/4': return (1.0 + a * a / b / b) / 4.0 - if expr == "-a*c*cosbeta/2/b/b": + if expr == '-a*c*cosbeta/2/b/b': return -a * c * cosbeta / 2.0 / b / b - if expr == "1+Z-2*M": - Z = kparam["Z"] - M = kparam["M"] + if expr == '1+Z-2*M': + Z = kparam['Z'] + M = kparam['M'] return 1.0 + Z - 2.0 * M - if expr == "X-2*D": - X = kparam["X"] - D = kparam["D"] + if expr == 'X-2*D': + X = kparam['X'] + D = kparam['D'] return X - 2 * D - if expr == "(1+a/c*cosbeta)/2/sinbeta/sinbeta": + if expr == '(1+a/c*cosbeta)/2/sinbeta/sinbeta': return (1.0 + a / c * cosbeta) / 2.0 / sinbeta / sinbeta - if expr == "1/2+Y*c*cosbeta/a": - Y = kparam["Y"] + if expr == '1/2+Y*c*cosbeta/a': + Y = kparam['Y'] return 1.0 / 2.0 + Y * c * cosbeta / a - if expr == "a*a/4/c/c": + if expr == 'a*a/4/c/c': return a * a / 4.0 / c / c - if expr == "5/6-2*D": - D = kparam["D"] + if expr == '5/6-2*D': + D = kparam['D'] return 5.0 / 6.0 - 2.0 * D - if expr == "1/3+D": - D = kparam["D"] + if expr == '1/3+D': + D = kparam['D'] return 1.0 / 3.0 + D - if expr == "1/6-c*c/9/a/a": + if expr == '1/6-c*c/9/a/a': return 1.0 / 6.0 - c * c / 9.0 / a / a - if expr == "1/2-2*Z": - Z = kparam["Z"] + if expr == '1/2-2*Z': + Z = kparam['Z'] return 1.0 / 2.0 - 2.0 * Z - if expr == "1/2+Z": - Z = kparam["Z"] + if expr == '1/2+Z': + Z = kparam['Z'] return 1.0 / 2.0 + Z - if expr == "(1+b*b/c/c)/4": + if expr == '(1+b*b/c/c)/4': return (1.0 + b * b / c / c) / 4.0 - if expr == "(1+c*c/b/b)/4": + if expr == '(1+c*c/b/b)/4': return (1.0 + c * c / b / b) / 4.0 - if expr == "(1+b*b/a/a)/4": + if expr == '(1+b*b/a/a)/4': return (1.0 + b * b / a / a) / 4.0 - if expr == "(1+a*a/b/b-a*a/c/c)/4": + if expr == '(1+a*a/b/b-a*a/c/c)/4': return (1.0 + a * a / b / b - a * a / c / c) / 4.0 - if expr == "(1+a*a/b/b+a*a/c/c)/4": + if expr == '(1+a*a/b/b+a*a/c/c)/4': return (1.0 + a * a / b / b + a * a / c / c) / 4.0 - if expr == "(1+c*c/a/a-c*c/b/b)/4": + if expr == '(1+c*c/a/a-c*c/b/b)/4': return (1.0 + c * c / a / a - c * c / b / b) / 4.0 - if expr == "(1+c*c/a/a+c*c/b/b)/4": + if expr == '(1+c*c/a/a+c*c/b/b)/4': return (1.0 + c * c / a / a + c * c / b / b) / 4.0 - if expr == "(1+b*b/a/a-b*b/c/c)/4": + if expr == '(1+b*b/a/a-b*b/c/c)/4': return (1.0 + b * b / a / a - b * b / c / c) / 4.0 - if expr == "(1+c*c/b/b-c*c/a/a)/4": + if expr == '(1+c*c/b/b-c*c/a/a)/4': return (1.0 + c * c / b / b - c * c / a / a) / 4.0 - if expr == "(1+a*a/c/c)/4": + if expr == '(1+a*a/c/c)/4': return (1.0 + a * a / c / c) / 4.0 - if expr == "(b*b-a*a)/4/c/c": + if expr == '(b*b-a*a)/4/c/c': return (b * b - a * a) / 4.0 / c / c - if expr == "(a*a+b*b)/4/c/c": + if expr == '(a*a+b*b)/4/c/c': return (a * a + b * b) / 4.0 / c / c - if expr == "(1+c*c/a/a)/4": + if expr == '(1+c*c/a/a)/4': return (1.0 + c * c / a / a) / 4.0 - if expr == "(c*c-b*b)/4/a/a": + if expr == '(c*c-b*b)/4/a/a': return (c * c - b * b) / 4.0 / a / a - if expr == "(b*b+c*c)/4/a/a": + if expr == '(b*b+c*c)/4/a/a': return (b * b + c * c) / 4.0 / a / a - if expr == "(a*a-c*c)/4/b/b": + if expr == '(a*a-c*c)/4/b/b': return (a * a - c * c) / 4.0 / b / b - if expr == "(c*c+a*a)/4/b/b": + if expr == '(c*c+a*a)/4/b/b': return (c * c + a * a) / 4.0 / b / b - if expr == "a*a/2/c/c": + if expr == 'a*a/2/c/c': return a * a / 2.0 / c / c raise ValueError( - "Unknown expression, define a new case:\n" - ' elif expr == "{0}":\n' - " return {0}".format(expr) + 'Unknown expression, define a new case:\n' + f' elif expr == "{expr}":\n' + f' return {expr}' ) except KeyError as exc: raise ValueError( - "Asking for evaluation of symbol '{}' but this has " - "not been defined or not yet computed".format(str(exc)) - ) + f"Asking for evaluation of symbol '{str(exc)}' but this has " + 'not been defined or not yet computed' + ) from exc def check_spglib_version(): @@ -225,27 +224,27 @@ def check_spglib_version(): """ try: import spglib - except ImportError: + except ImportError as exc: raise ValueError( - "spglib >= 1.9.4 is required for the creation " - "of the k-paths, but it could not be imported" - ) + 'spglib >= 1.9.4 is required for the creation ' + 'of the k-paths, but it could not be imported' + ) from exc - spg_version = Version(version("spglib")) + spg_version = Version(version('spglib')) - min_version = Version("1.9.4") - warning_version = Version("1.13") + min_version = Version('1.9.4') + warning_version = Version('1.13') if spg_version < min_version: - raise ValueError("Invalid spglib version, need >= 1.9.4") + raise ValueError('Invalid spglib version, need >= 1.9.4') if spg_version < warning_version: import warnings warnings.warn( - "You have a version of SPGLIB older than 1.13, " - "please consider upgrading to 1.13 or later since some bugs " - "have been fixed", + 'You have a version of SPGLIB older than 1.13, ' + 'please consider upgrading to 1.13 or later since some bugs ' + 'have been fixed', RuntimeWarning, ) @@ -259,14 +258,14 @@ def get_dot_access_dataset(dataset): To emulate it for older versions, this function is used. """ - spg_version = Version(version("spglib")) + spg_version = Version(version('spglib')) - if spg_version < Version("2.5.0"): + if spg_version < Version('2.5.0'): from types import SimpleNamespace return SimpleNamespace(**dataset) - else: - return dataset + + return dataset def get_cell_params(cell): @@ -340,32 +339,32 @@ def get_path_data(ext_bravais): # Get the data from the band_data folder this_folder = os.path.split(os.path.abspath(__file__))[0] - folder = os.path.join(this_folder, "band_path_data", ext_bravais) - path_file = os.path.join(folder, "path.txt") - points_file = os.path.join(folder, "points.txt") - kparam_file = os.path.join(folder, "k_vector_parameters.txt") - with open(kparam_file) as f: + folder = os.path.join(this_folder, 'band_path_data', ext_bravais) + path_file = os.path.join(folder, 'path.txt') + points_file = os.path.join(folder, 'points.txt') + kparam_file = os.path.join(folder, 'k_vector_parameters.txt') + with open(kparam_file, encoding='utf-8') as f: kparam_raw = [_.split() for _ in f.readlines() if _.strip()] - with open(points_file) as f: + with open(points_file, encoding='utf-8') as f: points_raw = [_.split() for _ in f.readlines()] - with open(path_file) as f: + with open(path_file, encoding='utf-8') as f: path_raw = [_.split() for _ in f.readlines()] # check if any(len(_) != 2 for _ in kparam_raw): - raise ValueError("Invalid line length in {}".format(kparam_file)) + raise ValueError(f'Invalid line length in {kparam_file}') if any(len(_) != 2 for _ in path_raw): - raise ValueError("Invalid line length in {}".format(path_file)) + raise ValueError(f'Invalid line length in {path_file}') if any(len(_) != 4 for _ in points_raw): - raise ValueError("Invalid line length in {}".format(points_file)) + raise ValueError(f'Invalid line length in {points_file}') # order must be preserved here kparam_def = [(_[0], _[1].strip()) for _ in kparam_raw] points_def = {} for label, kPx, kPy, kPz in points_raw: if label in points_def: raise ValueError( - "Internal error! Point {} defined multiple times " - "for Bravais lattice {}".format(label, ext_bravais) + f'Internal error! Point {label} defined multiple times ' + f'for Bravais lattice {ext_bravais}' ) points_def[label] = (kPx, kPy, kPz) path = [(_[0], _[1]) for _ in path_raw] @@ -374,11 +373,11 @@ def get_path_data(ext_bravais): for p1, p2 in path: if p1 not in points_def: raise ValueError( - "Point {} found in path (for {}) but undefined!".format(p1, ext_bravais) + f'Point {p1} found in path (for {ext_bravais}) but undefined!' ) if p2 not in points_def: raise ValueError( - "Point {} found in path (for {}) but undefined!".format(p2, ext_bravais) + f'Point {p2} found in path (for {ext_bravais}) but undefined!' ) return (kparam_def, points_def, path) diff --git a/seekpath/util.py b/seekpath/util.py index 32eac07..7b6178f 100644 --- a/seekpath/util.py +++ b/seekpath/util.py @@ -1,116 +1,116 @@ """Utilities (mapping of chemical elements to atomic number).""" atoms_num_dict = { - "H": 1, - "He": 2, - "Li": 3, - "Be": 4, - "B": 5, - "C": 6, - "N": 7, - "O": 8, - "F": 9, - "Ne": 10, - "Na": 11, - "Mg": 12, - "Al": 13, - "Si": 14, - "P": 15, - "S": 16, - "Cl": 17, - "Ar": 18, - "K": 19, - "Ca": 20, - "Sc": 21, - "Ti": 22, - "V": 23, - "Cr": 24, - "Mn": 25, - "Fe": 26, - "Co": 27, - "Ni": 28, - "Cu": 29, - "Zn": 30, - "Ga": 31, - "Ge": 32, - "As": 33, - "Se": 34, - "Br": 35, - "Kr": 36, - "Rb": 37, - "Sr": 38, - "Y": 39, - "Zr": 40, - "Nb": 41, - "Mo": 42, - "Tc": 43, - "Ru": 44, - "Rh": 45, - "Pd": 46, - "Ag": 47, - "Cd": 48, - "In": 49, - "Sn": 50, - "Sb": 51, - "Te": 52, - "I": 53, - "Xe": 54, - "Cs": 55, - "Ba": 56, - "La": 57, - "Ce": 58, - "Pr": 59, - "Nd": 60, - "Pm": 61, - "Sm": 62, - "Eu": 63, - "Gd": 64, - "Tb": 65, - "Dy": 66, - "Ho": 67, - "Er": 68, - "Tm": 69, - "Yb": 70, - "Lu": 71, - "Hf": 72, - "Ta": 73, - "W": 74, - "Re": 75, - "Os": 76, - "Ir": 77, - "Pt": 78, - "Au": 79, - "Hg": 80, - "Tl": 81, - "Pb": 82, - "Bi": 83, - "Po": 84, - "At": 85, - "Rn": 86, - "Fr": 87, - "Ra": 88, - "Ac": 89, - "Th": 90, - "Pa": 91, - "U": 92, - "Np": 93, - "Pu": 94, - "Am": 95, - "Cm": 96, - "Bk": 97, - "Cf": 98, - "Es": 99, - "Fm": 100, - "Md": 101, - "No": 102, - "Lr": 103, - "Rf": 104, - "Db": 105, - "Sg": 106, - "Bh": 107, - "Hs": 108, - "Mt": 109, - "Ds": 110, - "Rg": 111, - "Cn": 112, + 'H': 1, + 'He': 2, + 'Li': 3, + 'Be': 4, + 'B': 5, + 'C': 6, + 'N': 7, + 'O': 8, + 'F': 9, + 'Ne': 10, + 'Na': 11, + 'Mg': 12, + 'Al': 13, + 'Si': 14, + 'P': 15, + 'S': 16, + 'Cl': 17, + 'Ar': 18, + 'K': 19, + 'Ca': 20, + 'Sc': 21, + 'Ti': 22, + 'V': 23, + 'Cr': 24, + 'Mn': 25, + 'Fe': 26, + 'Co': 27, + 'Ni': 28, + 'Cu': 29, + 'Zn': 30, + 'Ga': 31, + 'Ge': 32, + 'As': 33, + 'Se': 34, + 'Br': 35, + 'Kr': 36, + 'Rb': 37, + 'Sr': 38, + 'Y': 39, + 'Zr': 40, + 'Nb': 41, + 'Mo': 42, + 'Tc': 43, + 'Ru': 44, + 'Rh': 45, + 'Pd': 46, + 'Ag': 47, + 'Cd': 48, + 'In': 49, + 'Sn': 50, + 'Sb': 51, + 'Te': 52, + 'I': 53, + 'Xe': 54, + 'Cs': 55, + 'Ba': 56, + 'La': 57, + 'Ce': 58, + 'Pr': 59, + 'Nd': 60, + 'Pm': 61, + 'Sm': 62, + 'Eu': 63, + 'Gd': 64, + 'Tb': 65, + 'Dy': 66, + 'Ho': 67, + 'Er': 68, + 'Tm': 69, + 'Yb': 70, + 'Lu': 71, + 'Hf': 72, + 'Ta': 73, + 'W': 74, + 'Re': 75, + 'Os': 76, + 'Ir': 77, + 'Pt': 78, + 'Au': 79, + 'Hg': 80, + 'Tl': 81, + 'Pb': 82, + 'Bi': 83, + 'Po': 84, + 'At': 85, + 'Rn': 86, + 'Fr': 87, + 'Ra': 88, + 'Ac': 89, + 'Th': 90, + 'Pa': 91, + 'U': 92, + 'Np': 93, + 'Pu': 94, + 'Am': 95, + 'Cm': 96, + 'Bk': 97, + 'Cf': 98, + 'Es': 99, + 'Fm': 100, + 'Md': 101, + 'No': 102, + 'Lr': 103, + 'Rf': 104, + 'Db': 105, + 'Sg': 106, + 'Bh': 107, + 'Hs': 108, + 'Mt': 109, + 'Ds': 110, + 'Rg': 111, + 'Cn': 112, } diff --git a/tests/test_brillouinzone.py b/tests/test_brillouinzone.py index c2195d4..0de3022 100644 --- a/tests/test_brillouinzone.py +++ b/tests/test_brillouinzone.py @@ -5,12 +5,10 @@ def has_scipy(): - try: - import scipy + import importlib - return True - except ImportError: - return False + scipy_spec = importlib.util.find_spec('scipy') + return scipy_spec is not None def is_same_point(p1, p2): @@ -73,8 +71,8 @@ def are_same_faces(faces1, faces2): return ( False, ( - "The two list of faces have different " - "length ({} vs. {})".format(len(faces1), len(faces2)) + 'The two list of faces have different ' + f'length ({len(faces1)} vs. {len(faces2)})' ), ) @@ -95,11 +93,11 @@ def are_same_faces(faces1, faces2): return ( False, ( - "The following item in the first list was not " - "found in the second one: {}".format(f1) + 'The following item in the first list was not ' + 'found in the second one: {}'.format(f1) ), ) - return True, "" + return True, '' class TestBZ(unittest.TestCase): @@ -107,7 +105,7 @@ class TestBZ(unittest.TestCase): Test the search for BZ faces """ - @unittest.skipIf(not has_scipy(), "No SciPy") + @unittest.skipIf(not has_scipy(), 'No SciPy') def test_cubic(self): b1 = [1, 0, 0] b2 = [0, 1, 0] @@ -164,17 +162,17 @@ def test_cubic(self): # The definition of triangles is not unique. I check directly the # faces (that should be obtained from the triangles - faces = bz["faces"] + faces = bz['faces'] # theFaces = [Face(f) for f in faces] # theExpectedFaces = [Face(f) for f in expected_faces] is_same, info = are_same_faces(faces, expected_faces) - self.assertTrue(is_same, "The two sets of faces are different: {}".format(info)) + self.assertTrue(is_same, f'The two sets of faces are different: {info}') is_same, info = are_same_faces(faces, unexpected_faces_1) - self.assertFalse(is_same, "The two sets of faces are not detected as different") + self.assertFalse(is_same, 'The two sets of faces are not detected as different') - @unittest.skipIf(not has_scipy(), "No SciPy") + @unittest.skipIf(not has_scipy(), 'No SciPy') def test_2(self): b1 = [1, 0, 0] b2 = [0, 1, 0] @@ -266,7 +264,7 @@ def test_2(self): # The definition of triangles is not unique. I check directly the # faces (that should be obtained from the triangles - faces = bz["faces"] + faces = bz['faces'] # To print the actual output # print "[" @@ -280,8 +278,8 @@ def test_2(self): # theFaces = [Face(f) for f in faces] # theExpectedFaces = [Face(f) for f in expected_faces] is_same, info = are_same_faces(faces, expected_faces) - self.assertTrue(is_same, "The two sets of faces are different: {}".format(info)) + self.assertTrue(is_same, f'The two sets of faces are different: {info}') -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/tests/test_hpkot_get_primitive.py b/tests/test_hpkot_get_primitive.py index 41cca0d..bb337b3 100644 --- a/tests/test_hpkot_get_primitive.py +++ b/tests/test_hpkot_get_primitive.py @@ -22,7 +22,7 @@ def test_primitive_bcc(self): atomic_numbers = [6, 6, 8, 8] system = (cell, positions, atomic_numbers) - prim, PinvP, mapping = get_primitive(system, "cI") + prim, PinvP, mapping = get_primitive(system, 'cI') self.assertEqual(mapping.tolist(), [0, 0, 1, 1]) self.assertAlmostEqual(prim[1].tolist(), [[0.0, 0.0, 0.0], [0.25, 0.0, 0.25]]) @@ -43,7 +43,7 @@ def test_primitive_oA(self): atomic_numbers = [6, 8, 8, 8, 6, 8] system = (cell, positions, atomic_numbers) - prim, PinvP, mapping = get_primitive(system, "oA") + prim, PinvP, mapping = get_primitive(system, 'oA') self.assertAlmostEqual( prim[0].tolist(), [[0.0, 1.5, -1.5], [0.0, 1.5, 1.5], [9.0, 0.0, 0.0]] @@ -81,7 +81,7 @@ def test_primitive_oA_with_wrapping(self): atomic_numbers = [6, 8, 8, 8, 6, 8] system = (cell, positions, atomic_numbers) - prim, PinvP, mapping = get_primitive(system, "oA", wrap_to_zero_one=True) + prim, PinvP, mapping = get_primitive(system, 'oA', wrap_to_zero_one=True) self.assertAlmostEqual( prim[0].tolist(), [[0.0, 1.5, -1.5], [0.0, 1.5, 1.5], [9.0, 0.0, 0.0]] diff --git a/tests/test_paths_hpkot.py b/tests/test_paths_hpkot.py index 8e59ba7..0d28b3b 100644 --- a/tests/test_paths_hpkot.py +++ b/tests/test_paths_hpkot.py @@ -1,4 +1,5 @@ """Test the HPKOT paths.""" + # pylint: disable=invalid-name,too-many-public-methods import numpy as np import unittest @@ -8,7 +9,7 @@ def simple_read_poscar(fname): """Read a POSCAR file.""" with open(fname) as f: - lines = [l.partition("!")[0] for l in f.readlines()] + lines = [line.partition('!')[0] for line in f.readlines()] alat = float(lines[1]) v1 = [float(_) * alat for _ in lines[2].split()] @@ -20,7 +21,7 @@ def simple_read_poscar(fname): num_atoms = [int(_) for _ in lines[6].split()] next_line = lines[7] - if next_line.strip().lower() != "direct": + if next_line.strip().lower() != 'direct': raise ValueError("This simple routine can only deal with 'direct' POSCARs") # Note: to support also cartesian, remember to multiply the coordinates # by alat @@ -63,8 +64,8 @@ def test_supercell(self): res = hpkot.get_path(system, with_time_reversal=False) # Just some basic checks... - self.assertEqual(res["volume_original_wrt_conv"], 2) - self.assertEqual(res["volume_original_wrt_prim"], 4) + self.assertEqual(res['volume_original_wrt_conv'], 2) + self.assertEqual(res['volume_original_wrt_prim'], 4) class TestSpglibSymprec(unittest.TestCase): @@ -95,7 +96,7 @@ def basic_test( else: res = hpkot.get_path(system, with_time_reversal=False, symprec=symprec) # Checks - self.assertEqual(res["bravais_lattice"], check_bravais_lattice) + self.assertEqual(res['bravais_lattice'], check_bravais_lattice) def test_symprec(self): """ @@ -106,11 +107,11 @@ def test_symprec(self): atomic_numbers = [6] self.basic_test( - cell, positions, atomic_numbers, check_bravais_lattice="tP", symprec=1.0e-8 + cell, positions, atomic_numbers, check_bravais_lattice='tP', symprec=1.0e-8 ) self.basic_test( - cell, positions, atomic_numbers, check_bravais_lattice="cP", symprec=1.0e-3 + cell, positions, atomic_numbers, check_bravais_lattice='cP', symprec=1.0e-3 ) @@ -129,42 +130,42 @@ def test_keys(self): # pylint: disable=no-self-use system = (cell, positions, atomic_numbers) - res = seekpath.get_explicit_k_path(system, recipe="hpkot") + res = seekpath.get_explicit_k_path(system, recipe='hpkot') known_keys = set( [ - "augmented_path", - "bravais_lattice", - "bravais_lattice_extended", - "conv_lattice", - "conv_positions", - "conv_types", - "explicit_kpoints_abs", - "explicit_kpoints_labels", - "explicit_kpoints_linearcoord", - "explicit_kpoints_rel", - "explicit_segments", - "has_inversion_symmetry", - "inverse_primitive_transformation_matrix", - "path", - "point_coords", - "primitive_lattice", - "primitive_positions", - "primitive_transformation_matrix", - "primitive_types", - "reciprocal_primitive_lattice", - "spacegroup_international", - "spacegroup_number", - "volume_original_wrt_conv", - "volume_original_wrt_prim", + 'augmented_path', + 'bravais_lattice', + 'bravais_lattice_extended', + 'conv_lattice', + 'conv_positions', + 'conv_types', + 'explicit_kpoints_abs', + 'explicit_kpoints_labels', + 'explicit_kpoints_linearcoord', + 'explicit_kpoints_rel', + 'explicit_segments', + 'has_inversion_symmetry', + 'inverse_primitive_transformation_matrix', + 'path', + 'point_coords', + 'primitive_lattice', + 'primitive_positions', + 'primitive_transformation_matrix', + 'primitive_types', + 'reciprocal_primitive_lattice', + 'spacegroup_international', + 'spacegroup_number', + 'volume_original_wrt_conv', + 'volume_original_wrt_prim', ] ) missing_known_keys = known_keys - set(res.keys()) if missing_known_keys: raise AssertionError( - "Some keys are not returned from the " - "get_explicit_k_path function: {}".format(", ".join(missing_known_keys)) + 'Some keys are not returned from the ' + 'get_explicit_k_path function: {}'.format(', '.join(missing_known_keys)) ) @@ -210,14 +211,13 @@ def basic_test( else: res = hpkot.get_path(system, with_time_reversal=False, symprec=symprec) # Checks - self.assertEqual(res["bravais_lattice"], check_bravais_lattice) + self.assertEqual(res['bravais_lattice'], check_bravais_lattice) # Checks on issued warnings relevant_w = [_ for _ in w if issubclass(_.category, hpkot.EdgeCaseWarning)] self.assertEqual( len(relevant_w), 1, - "Wrong number of warnings issued! " - "({} instead of 1)".format(len(relevant_w)), + f'Wrong number of warnings issued! ({len(relevant_w)} instead of 1)', ) if check_string is not None: self.assertIn(check_string, str(relevant_w[0].message)) @@ -230,7 +230,7 @@ def test_tI(self): positions = [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5], [0.0, 0.0, 0.1], [0.5, 0.5, 0.6]] atomic_numbers = [6, 6, 8, 8] - self.basic_test(cell, positions, atomic_numbers, check_bravais_lattice="tI") + self.basic_test(cell, positions, atomic_numbers, check_bravais_lattice='tI') def test_oF_first(self): """Test oF case.""" @@ -247,8 +247,8 @@ def test_oF_first(self): cell, positions, atomic_numbers, - check_bravais_lattice="oF", - check_string="but 1/a^2", + check_bravais_lattice='oF', + check_string='but 1/a^2', ) def test_oF_second(self): @@ -287,8 +287,8 @@ def test_oF_second(self): cell, positions, atomic_numbers, - check_bravais_lattice="oF", - check_string="but 1/c^2", + check_bravais_lattice='oF', + check_string='but 1/c^2', ) def test_oI_bc(self): @@ -300,8 +300,8 @@ def test_oI_bc(self): cell, positions, atomic_numbers, - check_bravais_lattice="oI", - check_string="but the two longest vectors b and c", + check_bravais_lattice='oI', + check_string='but the two longest vectors b and c', ) def test_oC(self): @@ -318,7 +318,7 @@ def test_oC(self): [0.5000000000000000, 0.6555394950000001, 0.2659032699999999], ] atomic_numbers = [6, 6, 6, 6, 8, 8, 8, 8] - self.basic_test(cell, positions, atomic_numbers, check_bravais_lattice="oC") + self.basic_test(cell, positions, atomic_numbers, check_bravais_lattice='oC') def test_oA(self): """Test oA case.""" @@ -332,7 +332,7 @@ def test_oA(self): [0.5000000000000000, 0.0000000000000000, 0.6263269549999999], ] atomic_numbers = [6, 6, 8, 8, 8, 8] - self.basic_test(cell, positions, atomic_numbers, check_bravais_lattice="oA") + self.basic_test(cell, positions, atomic_numbers, check_bravais_lattice='oA') # For full coverage, we should also implement the tests for the warnings # in the mC lattices, and for the oP warnings. @@ -365,9 +365,9 @@ def base_test(self, ext_bravais, with_inv): # Get the POSCAR with the example structure this_folder = os.path.split(os.path.abspath(hpkot.__file__))[0] - folder = os.path.join(this_folder, "band_path_data", ext_bravais) - poscar_with_inv = os.path.join(folder, "POSCAR_inversion") - poscar_no_inv = os.path.join(folder, "POSCAR_noinversion") + folder = os.path.join(this_folder, 'band_path_data', ext_bravais) + poscar_with_inv = os.path.join(folder, 'POSCAR_inversion') + poscar_no_inv = os.path.join(folder, 'POSCAR_noinversion') poscar = poscar_with_inv if with_inv else poscar_no_inv # asecell = ase.io.read(poscar) @@ -377,15 +377,15 @@ def base_test(self, ext_bravais, with_inv): res = hpkot.get_path(system, with_time_reversal=False) - self.assertEqual(res["bravais_lattice_extended"], ext_bravais) - self.assertEqual(res["has_inversion_symmetry"], with_inv) + self.assertEqual(res['bravais_lattice_extended'], ext_bravais) + self.assertEqual(res['has_inversion_symmetry'], with_inv) if self.verbose_tests: - print("*** {} (inv={})".format(ext_bravais, with_inv)) - for p1, p2 in res["path"]: + print(f'*** {ext_bravais} (inv={with_inv})') + for p1, p2 in res['path']: print( - " {} -- {}: {} -- {}".format( - p1, p2, res["point_coords"][p1], res["point_coords"][p2] + ' {} -- {}: {} -- {}'.format( + p1, p2, res['point_coords'][p1], res['point_coords'][p2] ) ) @@ -394,210 +394,210 @@ def test_aP2Y(self): Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) aP2. """ - self.base_test(ext_bravais="aP2", with_inv=True) + self.base_test(ext_bravais='aP2', with_inv=True) def test_aP2N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) aP2. """ - self.base_test(ext_bravais="aP2", with_inv=False) + self.base_test(ext_bravais='aP2', with_inv=False) def test_aP3Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) aP3. """ - self.base_test(ext_bravais="aP3", with_inv=True) + self.base_test(ext_bravais='aP3', with_inv=True) def test_aP3N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) aP3. """ - self.base_test(ext_bravais="aP3", with_inv=False) + self.base_test(ext_bravais='aP3', with_inv=False) def test_cF1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) cF1. """ - self.base_test(ext_bravais="cF1", with_inv=True) + self.base_test(ext_bravais='cF1', with_inv=True) def test_cF1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) cF1. """ - self.base_test(ext_bravais="cF1", with_inv=False) + self.base_test(ext_bravais='cF1', with_inv=False) def test_cF2Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) cF2. """ - self.base_test(ext_bravais="cF2", with_inv=True) + self.base_test(ext_bravais='cF2', with_inv=True) def test_cF2N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) cF2. """ - self.base_test(ext_bravais="cF2", with_inv=False) + self.base_test(ext_bravais='cF2', with_inv=False) def test_cI1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) cI1. """ - self.base_test(ext_bravais="cI1", with_inv=True) + self.base_test(ext_bravais='cI1', with_inv=True) def test_cI1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) cI1. """ - self.base_test(ext_bravais="cI1", with_inv=False) + self.base_test(ext_bravais='cI1', with_inv=False) def test_cP1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) cP1. """ - self.base_test(ext_bravais="cP1", with_inv=True) + self.base_test(ext_bravais='cP1', with_inv=True) def test_cP1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) cP1. """ - self.base_test(ext_bravais="cP1", with_inv=False) + self.base_test(ext_bravais='cP1', with_inv=False) def test_cP2Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) cP2. """ - self.base_test(ext_bravais="cP2", with_inv=True) + self.base_test(ext_bravais='cP2', with_inv=True) def test_cP2N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) cP2. """ - self.base_test(ext_bravais="cP2", with_inv=False) + self.base_test(ext_bravais='cP2', with_inv=False) def test_hP1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) hP1. """ - self.base_test(ext_bravais="hP1", with_inv=True) + self.base_test(ext_bravais='hP1', with_inv=True) def test_hP1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) hP1. """ - self.base_test(ext_bravais="hP1", with_inv=False) + self.base_test(ext_bravais='hP1', with_inv=False) def test_hP2Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) hP2. """ - self.base_test(ext_bravais="hP2", with_inv=True) + self.base_test(ext_bravais='hP2', with_inv=True) def test_hP2N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) hP2. """ - self.base_test(ext_bravais="hP2", with_inv=False) + self.base_test(ext_bravais='hP2', with_inv=False) def test_hR1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) hR1. """ - self.base_test(ext_bravais="hR1", with_inv=True) + self.base_test(ext_bravais='hR1', with_inv=True) def test_hR1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) hR1. """ - self.base_test(ext_bravais="hR1", with_inv=False) + self.base_test(ext_bravais='hR1', with_inv=False) def test_hR2Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) hR2. """ - self.base_test(ext_bravais="hR2", with_inv=True) + self.base_test(ext_bravais='hR2', with_inv=True) def test_hR2N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) hR2. """ - self.base_test(ext_bravais="hR2", with_inv=False) + self.base_test(ext_bravais='hR2', with_inv=False) def test_mC1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) mC1. """ - self.base_test(ext_bravais="mC1", with_inv=True) + self.base_test(ext_bravais='mC1', with_inv=True) def test_mC1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) mC1. """ - self.base_test(ext_bravais="mC1", with_inv=False) + self.base_test(ext_bravais='mC1', with_inv=False) def test_mC2Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) mC2. """ - self.base_test(ext_bravais="mC2", with_inv=True) + self.base_test(ext_bravais='mC2', with_inv=True) def test_mC2N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) mC2. """ - self.base_test(ext_bravais="mC2", with_inv=False) + self.base_test(ext_bravais='mC2', with_inv=False) def test_mC3Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) mC3. """ - self.base_test(ext_bravais="mC3", with_inv=True) + self.base_test(ext_bravais='mC3', with_inv=True) def test_mC3N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) mC3. """ - self.base_test(ext_bravais="mC3", with_inv=False) + self.base_test(ext_bravais='mC3', with_inv=False) def test_mP1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) mP1. """ - self.base_test(ext_bravais="mP1", with_inv=True) + self.base_test(ext_bravais='mP1', with_inv=True) def test_mP1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) mP1. """ - self.base_test(ext_bravais="mP1", with_inv=False) + self.base_test(ext_bravais='mP1', with_inv=False) # oA1Y does not exist by symmetry # def test_oA1Y(self): @@ -612,7 +612,7 @@ def test_oA1N(self): Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oA1. """ - self.base_test(ext_bravais="oA1", with_inv=False) + self.base_test(ext_bravais='oA1', with_inv=False) # oA2Y does not exist by symmetry # def test_oA2Y(self): @@ -627,49 +627,49 @@ def test_oA2N(self): Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oA2. """ - self.base_test(ext_bravais="oA2", with_inv=False) + self.base_test(ext_bravais='oA2', with_inv=False) def test_oC1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) oC1. """ - self.base_test(ext_bravais="oC1", with_inv=True) + self.base_test(ext_bravais='oC1', with_inv=True) def test_oC1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oC1. """ - self.base_test(ext_bravais="oC1", with_inv=False) + self.base_test(ext_bravais='oC1', with_inv=False) def test_oC2Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) oC2. """ - self.base_test(ext_bravais="oC2", with_inv=True) + self.base_test(ext_bravais='oC2', with_inv=True) def test_oC2N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oC2. """ - self.base_test(ext_bravais="oC2", with_inv=False) + self.base_test(ext_bravais='oC2', with_inv=False) def test_oF1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) oF1. """ - self.base_test(ext_bravais="oF1", with_inv=True) + self.base_test(ext_bravais='oF1', with_inv=True) def test_oF1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oF1. """ - self.base_test(ext_bravais="oF1", with_inv=False) + self.base_test(ext_bravais='oF1', with_inv=False) # oF2Y does not exist by symmetry # def test_oF2Y(self): @@ -684,35 +684,35 @@ def test_oF2N(self): Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oF2. """ - self.base_test(ext_bravais="oF2", with_inv=False) + self.base_test(ext_bravais='oF2', with_inv=False) def test_oF3Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) oF3. """ - self.base_test(ext_bravais="oF3", with_inv=True) + self.base_test(ext_bravais='oF3', with_inv=True) def test_oF3N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oF3. """ - self.base_test(ext_bravais="oF3", with_inv=False) + self.base_test(ext_bravais='oF3', with_inv=False) def test_oI1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) oI1. """ - self.base_test(ext_bravais="oI1", with_inv=True) + self.base_test(ext_bravais='oI1', with_inv=True) def test_oI1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oI1. """ - self.base_test(ext_bravais="oI1", with_inv=False) + self.base_test(ext_bravais='oI1', with_inv=False) # oI2Y does not exist by symmetry # def test_oI2Y(self): @@ -727,77 +727,77 @@ def test_oI2N(self): Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oI2. """ - self.base_test(ext_bravais="oI2", with_inv=False) + self.base_test(ext_bravais='oI2', with_inv=False) def test_oI3Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) oI3. """ - self.base_test(ext_bravais="oI3", with_inv=True) + self.base_test(ext_bravais='oI3', with_inv=True) def test_oI3N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oI3. """ - self.base_test(ext_bravais="oI3", with_inv=False) + self.base_test(ext_bravais='oI3', with_inv=False) def test_oP1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) oP1. """ - self.base_test(ext_bravais="oP1", with_inv=True) + self.base_test(ext_bravais='oP1', with_inv=True) def test_oP1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) oP1. """ - self.base_test(ext_bravais="oP1", with_inv=False) + self.base_test(ext_bravais='oP1', with_inv=False) def test_tI1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) tI1. """ - self.base_test(ext_bravais="tI1", with_inv=True) + self.base_test(ext_bravais='tI1', with_inv=True) def test_tI1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) tI1. """ - self.base_test(ext_bravais="tI1", with_inv=False) + self.base_test(ext_bravais='tI1', with_inv=False) def test_tI2Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) tI2. """ - self.base_test(ext_bravais="tI2", with_inv=True) + self.base_test(ext_bravais='tI2', with_inv=True) def test_tI2N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) tI2. """ - self.base_test(ext_bravais="tI2", with_inv=False) + self.base_test(ext_bravais='tI2', with_inv=False) def test_tP1Y(self): """ Obtain the k-path for a test system with inversion symmetry and Bravais lattice (extended) tP1. """ - self.base_test(ext_bravais="tP1", with_inv=True) + self.base_test(ext_bravais='tP1', with_inv=True) def test_tP1N(self): """ Obtain the k-path for a test system without inversion symmetry and Bravais lattice (extended) tP1. """ - self.base_test(ext_bravais="tP1", with_inv=False) + self.base_test(ext_bravais='tP1', with_inv=False) class TestPaths3D_HPKOT_Orig_Cell(unittest.TestCase): @@ -815,27 +815,26 @@ def base_test(self, system): accepted by spglib: (cell, positions, numbers), where (if N is the number of atoms). """ - import os from seekpath import get_path, get_path_orig_cell - res_standard = get_path(system, with_time_reversal=False, recipe="hpkot") + res_standard = get_path(system, with_time_reversal=False, recipe='hpkot') res_original = get_path_orig_cell( - system, with_time_reversal=False, recipe="hpkot" + system, with_time_reversal=False, recipe='hpkot' ) for key in [ - "path", - "augmented_path", - "bravais_lattice_extended", - "bravais_lattice", - "bravais_lattice_extended", - "spacegroup_number", - "spacegroup_international", + 'path', + 'augmented_path', + 'bravais_lattice_extended', + 'bravais_lattice', + 'bravais_lattice_extended', + 'spacegroup_number', + 'spacegroup_international', ]: self.assertEqual(res_original[key], res_standard[key]) - points_standard = res_standard["point_coords"] - points_original = res_original["point_coords"] + points_standard = res_standard['point_coords'] + points_original = res_original['point_coords'] self.assertEqual(set(points_original.keys()), set(points_standard.keys())) @@ -845,9 +844,9 @@ def base_test(self, system): for key in points_standard: k_cart_standard = ( np.array(points_standard[key]) - @ res_standard["reciprocal_primitive_lattice"] + @ res_standard['reciprocal_primitive_lattice'] ) - k_cart_standard = k_cart_standard @ res_standard["rotation_matrix"] + k_cart_standard = k_cart_standard @ res_standard['rotation_matrix'] reciprocal_original_lattice = np.linalg.inv(system[0]).T * 2 * np.pi k_cart_original = ( @@ -856,13 +855,13 @@ def base_test(self, system): np.testing.assert_array_almost_equal(k_cart_original, k_cart_standard) if self.verbose_tests: - for p1, p2 in res_original["path"]: + for p1, p2 in res_original['path']: print( - " {} -- {}: {} -- {}".format( + ' {} -- {}: {} -- {}'.format( p1, p2, - res_original["point_coords"][p1], - res_original["point_coords"][p2], + res_original['point_coords'][p1], + res_original['point_coords'][p2], ) ) @@ -887,8 +886,8 @@ def test_nonstandard_cubic(self): system = (cell, positions, atomic_numbers) res = self.base_test(system) - self.assertEqual(res["spacegroup_international"], "Pm-3m") - self.assertEqual(res["is_supercell"], False) + self.assertEqual(res['spacegroup_international'], 'Pm-3m') + self.assertEqual(res['is_supercell'], False) def test_nonstandard_fcc(self): """ @@ -909,8 +908,8 @@ def test_nonstandard_fcc(self): system = (cell, positions, atomic_numbers) res = self.base_test(system) - self.assertEqual(res["spacegroup_international"], "Fd-3m") - self.assertEqual(res["is_supercell"], False) + self.assertEqual(res['spacegroup_international'], 'Fd-3m') + self.assertEqual(res['is_supercell'], False) def test_nonstandard_tetragonal(self): """ @@ -933,14 +932,14 @@ def test_nonstandard_tetragonal(self): ) res = self.base_test(system) - self.assertEqual(res["spacegroup_international"], "P4mm") - self.assertEqual(res["is_supercell"], False) - np.testing.assert_almost_equal(res["point_coords"]["GAMMA"], [0.0, 0.0, 0.0]) - np.testing.assert_almost_equal(res["point_coords"]["A"], [0.5, 0.5, 0.5]) - np.testing.assert_almost_equal(res["point_coords"]["M"], [0.0, 0.5, 0.5]) - np.testing.assert_almost_equal(res["point_coords"]["R"], [0.5, 0.0, 0.5]) - np.testing.assert_almost_equal(res["point_coords"]["X"], [0.0, 0.0, 0.5]) - np.testing.assert_almost_equal(res["point_coords"]["Z"], [0.5, 0.0, 0.0]) + self.assertEqual(res['spacegroup_international'], 'P4mm') + self.assertEqual(res['is_supercell'], False) + np.testing.assert_almost_equal(res['point_coords']['GAMMA'], [0.0, 0.0, 0.0]) + np.testing.assert_almost_equal(res['point_coords']['A'], [0.5, 0.5, 0.5]) + np.testing.assert_almost_equal(res['point_coords']['M'], [0.0, 0.5, 0.5]) + np.testing.assert_almost_equal(res['point_coords']['R'], [0.5, 0.0, 0.5]) + np.testing.assert_almost_equal(res['point_coords']['X'], [0.0, 0.0, 0.5]) + np.testing.assert_almost_equal(res['point_coords']['Z'], [0.5, 0.0, 0.0]) def test_nonstandard_monoclinic(self): """ @@ -961,8 +960,8 @@ def test_nonstandard_monoclinic(self): system = (cell, positions, atomic_numbers) res = self.base_test(system) - self.assertEqual(res["spacegroup_international"], "Pm") - self.assertEqual(res["is_supercell"], False) + self.assertEqual(res['spacegroup_international'], 'Pm') + self.assertEqual(res['is_supercell'], False) def test_nonstandard_cubic_supercell(self): """ @@ -987,22 +986,21 @@ def test_nonstandard_cubic_supercell(self): with warnings.catch_warnings(record=True) as w: res = self.base_test(system) - self.assertEqual(res["is_supercell"], True) + self.assertEqual(res['is_supercell'], True) # Checks on issued warnings relevant_w = [_ for _ in w if issubclass(_.category, SupercellWarning)] self.assertEqual( len(relevant_w), 1, - "Wrong number of warnings issued! " - "({} instead of 1)".format(len(relevant_w)), + f'Wrong number of warnings issued! ({len(relevant_w)} instead of 1)', ) - check_string = "The provided cell is a supercell: the returned" + check_string = 'The provided cell is a supercell: the returned' if check_string is not None: self.assertIn(check_string, str(relevant_w[0].message)) - self.assertEqual(res["spacegroup_international"], "Pm-3m") + self.assertEqual(res['spacegroup_international'], 'Pm-3m') def test_no_symmetrization(self): """ @@ -1020,12 +1018,12 @@ def test_no_symmetrization(self): res_standard = seekpath.get_path(system) res_original = seekpath.get_path_orig_cell(system) - self.assertEqual(res_standard["spacegroup_international"], "Pm-3m") - self.assertEqual(res_original["spacegroup_international"], "Pm-3m") + self.assertEqual(res_standard['spacegroup_international'], 'Pm-3m') + self.assertEqual(res_original['spacegroup_international'], 'Pm-3m') xk_R = np.array([0.5, 0.5, 0.5]) - np.testing.assert_almost_equal(res_standard["point_coords"]["R"], xk_R) - self.assertGreater(np.sum(abs(res_original["point_coords"]["R"] - xk_R)), 1e-7) + np.testing.assert_almost_equal(res_standard['point_coords']['R'], xk_R) + self.assertGreater(np.sum(abs(res_original['point_coords']['R'] - xk_R)), 1e-7) class TestExplicitPaths_Orig_Cell(unittest.TestCase): @@ -1043,28 +1041,28 @@ def test_keys(self): # pylint: disable=no-self-use system = (cell, positions, atomic_numbers) - res = seekpath.get_explicit_k_path_orig_cell(system, recipe="hpkot") + res = seekpath.get_explicit_k_path_orig_cell(system, recipe='hpkot') known_keys = set( [ - "augmented_path", - "explicit_kpoints_abs", - "explicit_kpoints_labels", - "explicit_kpoints_linearcoord", - "explicit_kpoints_rel", - "explicit_segments", - "is_supercell", - "path", - "point_coords", + 'augmented_path', + 'explicit_kpoints_abs', + 'explicit_kpoints_labels', + 'explicit_kpoints_linearcoord', + 'explicit_kpoints_rel', + 'explicit_segments', + 'is_supercell', + 'path', + 'point_coords', ] ) missing_known_keys = known_keys - set(res.keys()) if missing_known_keys: raise AssertionError( - "Some keys are not returned from the " - "get_explicit_k_path_orig_cell function: {}".format( - ", ".join(missing_known_keys) + 'Some keys are not returned from the ' + 'get_explicit_k_path_orig_cell function: {}'.format( + ', '.join(missing_known_keys) ) ) @@ -1088,47 +1086,46 @@ def test_path(self): # pylint: disable=no-self-use system = (cell, positions, atomic_numbers) - res_standard = seekpath.get_explicit_k_path(system, recipe="hpkot") + res_standard = seekpath.get_explicit_k_path(system, recipe='hpkot') with warnings.catch_warnings(record=True) as w: res_original = seekpath.get_explicit_k_path_orig_cell( - system, recipe="hpkot" + system, recipe='hpkot' ) - self.assertEqual(res_original["is_supercell"], True) + self.assertEqual(res_original['is_supercell'], True) # Checks on issued warnings relevant_w = [_ for _ in w if issubclass(_.category, SupercellWarning)] self.assertEqual( len(relevant_w), 1, - "Wrong number of warnings issued! " - "({} instead of 1)".format(len(relevant_w)), + f'Wrong number of warnings issued! ({len(relevant_w)} instead of 1)', ) - check_string = "The provided cell is a supercell: the returned" + check_string = 'The provided cell is a supercell: the returned' if check_string is not None: self.assertIn(check_string, str(relevant_w[0].message)) - self.assertEqual(res_original["path"], res_standard["path"]) - self.assertEqual(res_original["augmented_path"], res_standard["augmented_path"]) + self.assertEqual(res_original['path'], res_standard['path']) + self.assertEqual(res_original['augmented_path'], res_standard['augmented_path']) self.assertEqual( - res_original["explicit_kpoints_labels"], - res_standard["explicit_kpoints_labels"], + res_original['explicit_kpoints_labels'], + res_standard['explicit_kpoints_labels'], ) self.assertEqual( - res_original["explicit_segments"], res_standard["explicit_segments"] + res_original['explicit_segments'], res_standard['explicit_segments'] ) self.assertEqual( - res_original["explicit_kpoints_abs"].shape, - res_standard["explicit_kpoints_abs"].shape, + res_original['explicit_kpoints_abs'].shape, + res_standard['explicit_kpoints_abs'].shape, ) self.assertEqual( - res_original["explicit_kpoints_rel"].shape, - res_standard["explicit_kpoints_rel"].shape, + res_original['explicit_kpoints_rel'].shape, + res_standard['explicit_kpoints_rel'].shape, ) np.testing.assert_array_almost_equal( - res_original["explicit_kpoints_linearcoord"], - res_standard["explicit_kpoints_linearcoord"], + res_original['explicit_kpoints_linearcoord'], + res_standard['explicit_kpoints_linearcoord'], ) # Test that the k path for the original cell in Cartesian coordinates @@ -1137,10 +1134,10 @@ def test_path(self): # pylint: disable=no-self-use # "explicit_kpoints_abs", # "explicit_kpoints_rel", reciprocal_original_lattice = np.linalg.inv(system[0]).T * 2 * np.pi - for ik in range(len(res_original["explicit_kpoints_abs"])): - k_abs = res_original["explicit_kpoints_abs"][ik] - k_rel = res_original["explicit_kpoints_rel"][ik] - k_abs_standard = res_standard["explicit_kpoints_abs"][ik] + for ik in range(len(res_original['explicit_kpoints_abs'])): + k_abs = res_original['explicit_kpoints_abs'][ik] + k_rel = res_original['explicit_kpoints_rel'][ik] + k_abs_standard = res_standard['explicit_kpoints_abs'][ik] # Test k_abs and k_rel are consistent with the unit cell np.testing.assert_array_almost_equal( k_abs, k_rel @ reciprocal_original_lattice @@ -1149,5 +1146,5 @@ def test_path(self): # pylint: disable=no-self-use # Test k_abs is identical to that of the standardized cell rotated # by the rotation matrix. np.testing.assert_array_almost_equal( - k_abs, k_abs_standard @ res_standard["rotation_matrix"] + k_abs, k_abs_standard @ res_standard['rotation_matrix'] )