diff --git a/.github/workflows/validate_release_tag.py b/.github/workflows/validate_release_tag.py index 384066e..772da8f 100644 --- a/.github/workflows/validate_release_tag.py +++ b/.github/workflows/validate_release_tag.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Validate that the version in the tag label matches the version of the package.""" + import argparse import ast from pathlib import Path @@ -17,8 +18,11 @@ def get_version_from_module(content: str) -> str: try: return next( - ast.literal_eval(statement.value) for statement in module.body if isinstance(statement, ast.Assign) - for target in statement.targets if isinstance(target, ast.Name) and target.id == '__version__' + ast.literal_eval(statement.value) + for statement in module.body + if isinstance(statement, ast.Assign) + for target in statement.targets + if isinstance(target, ast.Name) and target.id == '__version__' ) except StopIteration as exception: raise IOError('Unable to find the `__version__` attribute in the module.') from exception diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 429a8b1..b36ead2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,50 +1,30 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: 'v4.2.0' + rev: v4.2.0 hooks: - - id: double-quote-string-fixer - id: end-of-file-fixer - id: fix-encoding-pragma - id: mixed-line-ending - id: trailing-whitespace -- repo: https://github.com/ikamensh/flynt/ - rev: '0.76' +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.5.5 hooks: - - id: flynt + - id: ruff + args: [ --fix ] + - id: ruff-format - repo: https://github.com/pycqa/isort rev: '5.12.0' hooks: - id: isort -- repo: https://github.com/pre-commit/mirrors-yapf - rev: 'v0.32.0' +- repo: https://github.com/pre-commit/mirrors-mypy + rev: 'v1.11.0' hooks: - - id: yapf - name: yapf + - id: mypy types: [python] - args: ['-i'] - additional_dependencies: ['toml'] - -- repo: local - hooks: - - id: mypy - name: mypy - entry: mypy - args: [--config-file=pyproject.toml] - language: python - types: [python] - require_serial: true - pass_filenames: true files: >- (?x)^( src/.*py| )$ - - - id: pylint - name: pylint - entry: pylint - language: system - types: [python] - exclude: "^(doc/)|(.utils/)" diff --git a/pyproject.toml b/pyproject.toml index 756092a..618f657 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ Source = 'https://github.com/aiidateam/qe-tools' [project.optional-dependencies] dev = [ 'codecov', - 'mypy==0.930', + 'mypy~=1.11', 'pre-commit', 'timeout-decorator', 'pylint~=2.16.0', @@ -60,10 +60,6 @@ exclude = [ '.pre-commit-config.yaml', ] -[tool.flynt] -line-length = 120 -fail-on-change = true - [tool.isort] force_sort_within_sections = true include_trailing_comma = true @@ -78,54 +74,28 @@ warn_unused_ignores = true warn_redundant_casts = true no_warn_no_return = true show_traceback = true - -[[tool.mypy.overrides]] -module = 'qe_tools.*' follow_imports = 'skip' -check_untyped_defs = true [[tool.mypy.overrides]] module = [ 'scipy.*', + 'numpy.*' ] +ignore_errors = true ignore_missing_imports = true -[tool.pylint.format] -max-line-length = 120 +[tool.ruff] +line-length = 120 +indent-width = 4 +target-version = "py38" -[tool.pylint.basic] -good-names = [ - 'a', - 'b', - 'c', - 'e', - 'f', - 'i', - 'i', - 'j', - 'k', - 's', - 'u', - 'v', - 'tx', - 'ty', - 'tz', - 'v1', - 'v2', +[tool.ruff.lint] +ignore = [ + 'E731' ] - -[tool.pylint.messages_control] -disable = [ - 'fixme', - 'import-error', - 'missing-function-docstring', - 'missing-module-docstring', - 'too-few-public-methods', - 'too-many-public-methods', - 'use-dict-literal', - 'unnecessary-lambda-assignment', -] +[tool.ruff.format] +quote-style = 'single' [tool.pytest.ini_options] testpaths = [ @@ -134,12 +104,3 @@ testpaths = [ filterwarnings = [ 'ignore:WARNING the new order is not taken into account !!:UserWarning', ] - -[tool.yapf] -align_closing_bracket_with_visual_indent = true -based_on_style = 'google' -coalesce_brackets = true -column_limit = 120 -dedent_closing_brackets = true -indent_dictionary_value = false -split_arguments_when_comma_terminated = true diff --git a/src/qe_tools/__init__.py b/src/qe_tools/__init__.py index 054f9e2..c51ef3b 100644 --- a/src/qe_tools/__init__.py +++ b/src/qe_tools/__init__.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """A set of useful tools to manage Quantum ESPRESSO files.""" + from ._constants import DEFAULT as CONSTANTS # isort:skip from . import converters, exceptions, parsers, extractors # isort:skip diff --git a/src/qe_tools/_constants.py b/src/qe_tools/_constants.py index de8f04f..c2cbf93 100644 --- a/src/qe_tools/_constants.py +++ b/src/qe_tools/_constants.py @@ -17,15 +17,14 @@ ## These have been put here from the one of QE, taken directly from ## those in aiida.common.constants bohr_to_ang=0.52917720859, - ang_to_m=1.e-10, + ang_to_m=1.0e-10, ry_to_ev=13.6056917253, - ry_si=4.35974394 / 2. * 10**(-18), + ry_si=4.35974394 / 2.0 * 10 ** (-18), timeau_to_sec=2.418884326155573e-17, invcm_to_THz=0.0299792458, - ## Values taken from https://gitlab.com/QEF/q-e/-/blob/develop/Modules/constants.f90 - ha_si=4.3597447222071e-18, # J - bohr_si=0.529177210903e-10, # m + ha_si=4.3597447222071e-18, # J + bohr_si=0.529177210903e-10, # m # From the definition of Quantum ESPRESSO, conversion from atomic mass # units to Rydberg units: # REAL(DP), PARAMETER :: AMU_SI = 1.660538782E-27_DP ! Kg @@ -35,6 +34,6 @@ amu_Ry=911.4442421323, ) -DEFAULT.hartree_to_ev = DEFAULT.ry_to_ev * 2. +DEFAULT.hartree_to_ev = DEFAULT.ry_to_ev * 2.0 DEFAULT.bohr_si = DEFAULT.bohr_to_ang * DEFAULT.ang_to_m -DEFAULT.au_gpa = DEFAULT.ha_si / (DEFAULT.bohr_si**3.) / 1.0e9 +DEFAULT.au_gpa = DEFAULT.ha_si / (DEFAULT.bohr_si**3.0) / 1.0e9 diff --git a/src/qe_tools/_qe_version.py b/src/qe_tools/_qe_version.py index bb86fea..d1e5fb8 100644 --- a/src/qe_tools/_qe_version.py +++ b/src/qe_tools/_qe_version.py @@ -20,6 +20,7 @@ class _LatestVersionImpl: The object is implemented as a singleton, meaning it can only be instantiated once. """ + __instance_count = 0 def __init__(self): @@ -40,7 +41,7 @@ def __gt__(self, other): def parse_version( - qe_version: Optional[Union[str, _LatestVersionImpl, Version]] = None + qe_version: Optional[Union[str, _LatestVersionImpl, Version]] = None, ) -> Union[_LatestVersionImpl, Version]: """Parse the QE version string to a comparable object. diff --git a/src/qe_tools/converters/_structure.py b/src/qe_tools/converters/_structure.py index 72c1a58..a0ad579 100644 --- a/src/qe_tools/converters/_structure.py +++ b/src/qe_tools/converters/_structure.py @@ -2,7 +2,7 @@ __all__ = ('get_parameters_from_cell',) -from typing import Dict, Iterable, Optional, Union +from typing import Dict, Iterable, Optional import numpy as np import scipy.linalg as la @@ -20,7 +20,7 @@ def get_parameters_from_cell( cell: CellT, tolerance: float = 1e-4, using_celldm: bool = False, - qe_version: Optional[str] = None + qe_version: Optional[str] = None, ) -> ParametersT: """ Get the cell parameters from a given `ibrav` and cell. Only the @@ -67,7 +67,13 @@ def get_parameters_from_cell( parameters = _get_parameters_from_cell_bare(ibrav=ibrav, cell=cell) - _check_parameters(ibrav=ibrav, cell=cell, parameters=parameters, tolerance=tolerance, qe_version=qe_version) + _check_parameters( + ibrav=ibrav, + cell=cell, + parameters=parameters, + tolerance=tolerance, + qe_version=qe_version, + ) if using_celldm: parameters = _convert_to_celldm(parameters, ibrav=ibrav) @@ -98,7 +104,7 @@ def _get_parameters_from_cell_bare( # pylint: disable=too-many-branches parameters = {A: la.norm(v1), C: la.norm(v3)} elif ibrav in [5, -5]: parameters = {A: la.norm(v1)} - parameters[cosAB] = np.dot(v1, v2) / parameters[A]**2 + parameters[cosAB] = np.dot(v1, v2) / parameters[A] ** 2 elif ibrav == 6: parameters = {A: la.norm(v1), C: la.norm(v3)} elif ibrav == 7: @@ -136,20 +142,25 @@ def _get_parameters_from_cell_bare( # pylint: disable=too-many-branches def _check_parameters( - *, ibrav: int, parameters: ParametersT, cell: CellT, tolerance: float, qe_version: Optional[str] = None + *, + ibrav: int, + parameters: ParametersT, + cell: CellT, + tolerance: float, + qe_version: Optional[str] = None, ) -> None: """ Check that the parameters describe the given cell. """ - system_dict = {'ibrav': ibrav, **parameters} # type: Dict[str, Union[int, float]] + system_dict = {'ibrav': ibrav, **parameters} cell_reconstructed = _get_cell_from_parameters( cell_parameters=None, # this is only used for ibrav=0 system_dict=system_dict, alat=parameters['a'], using_celldm=False, - qe_version=qe_version + qe_version=qe_version, ) - if not np.allclose(cell_reconstructed, cell, rtol=0, atol=tolerance): # type: ignore[arg-type] + if not np.allclose(cell_reconstructed, cell, rtol=0, atol=tolerance): raise ValueError( f'The cell {cell_reconstructed} constructed with ibrav={ibrav}, parameters={parameters} does not match ' f'the input cell{cell}.' diff --git a/src/qe_tools/parsers/_input_base.py b/src/qe_tools/parsers/_input_base.py index f939592..4ac19df 100644 --- a/src/qe_tools/parsers/_input_base.py +++ b/src/qe_tools/parsers/_input_base.py @@ -6,7 +6,7 @@ """ import re -from typing import List, Tuple +from typing import List import numpy as np @@ -16,7 +16,7 @@ RE_FLAGS = re.MULTILINE | re.VERBOSE | re.IGNORECASE -__all__ = tuple() # type: Tuple[str, ...] +__all__: tuple = tuple() NUMBER_PATTERN = r""" (?: @@ -204,7 +204,7 @@ def __init__(self, content, *, qe_version=None, validate_species_names=True): atomic_positions=self.atomic_positions, atomic_species=self.atomic_species, cell_parameters=self.cell_parameters, - qe_version=self._qe_version + qe_version=self._qe_version, ) def as_dict(self) -> dict: @@ -234,17 +234,21 @@ def _str2val(valstr): | # or \d+[\.]?\d* ) # 10.53 or 10. or 10 (?:[dEeE][-+]?[0-9]+)? # optional exponent - """, re.X + """, + re.X, ) # Strip any white space characters before analyzing. valstr = valstr.strip() # Define a tuple of regular expressions to match and their corresponding # conversion functions. - re_fn_tuple = ((re.compile(r'[.](true|t)[.]', - re.I), lambda s: True), (re.compile(r'[.](false|f)[.]', re.I), lambda s: False), - (float_re, lambda s: float(s.replace('d', 'e').replace('D', 'E'))), (re.compile(r'[-+]?\d+$'), int), - (re.compile(r"""['"].*['"]"""), lambda s: str(s.strip("\'\"")))) + re_fn_tuple = ( + (re.compile(r'[.](true|t)[.]', re.I), lambda s: True), + (re.compile(r'[.](false|f)[.]', re.I), lambda s: False), + (float_re, lambda s: float(s.replace('d', 'e').replace('D', 'E'))), + (re.compile(r'[-+]?\d+$'), int), + (re.compile(r"""['"].*['"]"""), lambda s: str(s.strip('\'"'))), + ) # Convert valstr to a value. val = None for regex, conversion_fn in re_fn_tuple: @@ -252,7 +256,7 @@ def _str2val(valstr): # conversion_fn. if regex.match(valstr): try: - val = conversion_fn(valstr) # type: ignore[operator] + val = conversion_fn(valstr) except ValueError as error: raise ValueError(f'Error converting {repr(valstr)} to a value') from error if val is None: @@ -302,7 +306,8 @@ def _parse_namelists(txt): [\S\s]*? # match any line non-greedily ) # save the group of text between nmlst ^ [ \t]* / [ \t]* $\n # match line w/ "/" as only non-whitespace char - """, re.M | re.X + """, + re.M | re.X, ) # Define the re to match and extract all of the key = val pairs inside # a block of namelist text. @@ -312,7 +317,8 @@ def _parse_namelists(txt): = # equals sign separates key and value [ \t]* (\S+?) [ \t]* # match and store value [\n,] # return or comma separates "key = value" pairs - """, re.M | re.X + """, + re.M | re.X, ) # Scan through the namelists... params_dict = {} @@ -393,7 +399,7 @@ def str01_to_bool(s): # Define re for the card block. # NOTE: This will match card block lines w/ or w/out force modifications. atomic_positions_block_re = re.compile( - fr""" + rf""" ^ \s* ATOMIC_POSITIONS \s* # Atomic positions start with that string [{{(]? \s* (?P\S+?)? \s* [)}}]? \s* $\n # The units are after the string in optional brackets (?P # This is the block of positions @@ -419,7 +425,8 @@ def str01_to_bool(s): [\n] # line break at the end )+ # A positions block should be one or more lines ) - """, re.X | re.M + """, + re.X | re.M, ) # atomic_positions_block_re_ = re.compile( @@ -440,7 +447,7 @@ def str01_to_bool(s): # Define re for atomic positions without force modifications. atomic_positions_w_constraints_re = re.compile( - fr""" + rf""" ^ # Linestart [ \t]* # Optional white space (?P[A-Za-z]+[A-Za-z0-9]{{0,2}})\s+ # get the symbol, max 3 chars, starting with a char @@ -461,7 +468,8 @@ def str01_to_bool(s): (?P[01]?) # Get fx [ \t]* (?P[01]?) # Get fx - """, re.X | re.M + """, + re.X | re.M, ) # Find the card block and extract units and the lines of the block. match = atomic_positions_block_re.search(txt) @@ -488,10 +496,10 @@ def str01_to_bool(s): # First, try using the re for lines without force modifications. Set the # default force modification to the default (True) for each atom. # PROBLEM this changes the order of the atoms, which is unwanted! - #~ for match in atomic_positions_re.finditer(blockstr): - #~ names.append(match.group('name')) - #~ positions.append(map(fortfloat, match.group('x', 'y', 'z'))) - #~ fixed_coords.append(3 * [False]) # False <--> not fixed (the default) + # ~ for match in atomic_positions_re.finditer(blockstr): + # ~ names.append(match.group('name')) + # ~ positions.append(map(fortfloat, match.group('x', 'y', 'z'))) + # ~ fixed_coords.append(3 * [False]) # False <--> not fixed (the default) # Next, try using the re for lines with force modifications. for match in atomic_positions_w_constraints_re.finditer(blockstr): positions.append(list(map(fortfloat, match.group('x', 'y', 'z')))) @@ -503,12 +511,12 @@ def str01_to_bool(s): # lines in blockstr # LK removed this check since lines can be commented out, and that is fine. # n_lines = len(blockstr.rstrip().split('\n')) - #~ if len(names) != n_lines: - #~ raise ParsingError( - #~ 'Only {} atomic positions were parsed from the {} lines of the ' - #~ 'ATOMIC_POSITIONS card block:\n{}'.format(len(names), n_lines, - #~ blockstr) - #~ ) + # ~ if len(names) != n_lines: + # ~ raise ParsingError( + # ~ 'Only {} atomic positions were parsed from the {} lines of the ' + # ~ 'ATOMIC_POSITIONS card block:\n{}'.format(len(names), n_lines, + # ~ blockstr) + # ~ ) info_dict = dict(units=units, names=names, positions=positions, fixed_coords=fixed_coords) return info_dict @@ -545,7 +553,7 @@ def _parse_cell_parameters(txt): """ # Define re for the card block. cell_parameters_block_re = re.compile( - fr""" + rf""" ^ [ \t]* CELL_PARAMETERS [ \t]* [{{(]? \s* (?P[a-z]*) \s* [)}}]? \s* [\n] @@ -573,11 +581,12 @@ def _parse_cell_parameters(txt): [\n] # line break at the end ){{3}} # I need exactly 3 vectors ) - """, RE_FLAGS + """, + RE_FLAGS, ) cell_vector_regex = re.compile( - fr""" + rf""" ^ # Linestart [ \t]* # Optional white space (?P # Get x @@ -591,21 +600,22 @@ def _parse_cell_parameters(txt): (?P # Get z {NUMBER_PATTERN} ) - """, re.X | re.M + """, + re.X | re.M, ) - #~ cell_parameters_block_re = re.compile(r""" - #~ ^ [ \t]* CELL_PARAMETERS [ \t]* - #~ [{(]? [ \t]* (?P\S+?)? [ \t]* [)}]? [ \t]* $\n - #~ (?P - #~ (?: - #~ ^ [ \t]* \S+ [ \t]+ \S+ [ \t]+ \S+ [ \t]* $\n? - #~ ){3} - #~ ) - #~ """, RE_FLAGS) + # ~ cell_parameters_block_re = re.compile(r""" + # ~ ^ [ \t]* CELL_PARAMETERS [ \t]* + # ~ [{(]? [ \t]* (?P\S+?)? [ \t]* [)}]? [ \t]* $\n + # ~ (?P + # ~ (?: + # ~ ^ [ \t]* \S+ [ \t]+ \S+ [ \t]+ \S+ [ \t]* $\n? + # ~ ){3} + # ~ ) + # ~ """, RE_FLAGS) # Define re for the info contained in the block. - #~ atomic_species_re = re.compile(r""" - #~ ^ [ \t]* (\S+) [ \t]+ (\S+) [ \t]+ (\S+) [ \t]* $\n? - #~ """, RE_FLAGS) + # ~ atomic_species_re = re.compile(r""" + # ~ ^ [ \t]* (\S+) [ \t]+ (\S+) [ \t]+ (\S+) [ \t]* $\n? + # ~ """, RE_FLAGS) # Find the card block and extract units and the lines of the block. match = cell_parameters_block_re.search(txt) if not match: @@ -701,14 +711,16 @@ def _validate_species_name(atom_name, pseudo_file_name): ^ [ \t]* \S+ [ \t]+ \S+ [ \t]+ \S+ [ \t]* $\n? )+ ) - """, RE_FLAGS + """, + RE_FLAGS, ) # Define re for the info contained in the block. atomic_species_re = re.compile( r""" ^ [ \t]* (?P\S+) [ \t]+ (?P\S+) [ \t]+ (?P\S+) [ \t]* $\n? - """, RE_FLAGS + """, + RE_FLAGS, ) # Find the card block and extract units and the lines of the block. try: @@ -737,12 +749,8 @@ def _validate_species_name(atom_name, pseudo_file_name): def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-statements,too-many-branches - cell_parameters, - system_dict, - alat, - using_celldm, - *, - qe_version=None): + cell_parameters, system_dict, alat, using_celldm, *, qe_version=None +): """ A function to get the cell from cell parameters and SYSTEM card dictionary as read by _parse_namelists. @@ -802,7 +810,7 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state cosg = system_dict['celldm(4)'] else: cosg = system_dict['cosab'] - sing = np.sqrt(1. - cosg**2) + sing = np.sqrt(1.0 - cosg**2) if ibrav in ( 5, -5, @@ -814,7 +822,7 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state cosb = system_dict['celldm(5)'] else: cosb = system_dict['cosac'] - sinb = np.sqrt(1. - cosb**2) + sinb = np.sqrt(1.0 - cosb**2) if ibrav in (14,): if using_celldm: cosa = system_dict['celldm(4)'] @@ -824,7 +832,7 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state cosg = system_dict['celldm(6)'] else: cosg = system_dict['cosab'] - sing = np.sqrt(1. - cosg**2) + sing = np.sqrt(1.0 - cosg**2) except Exception as e: raise InputValidationError( f'\nException {type(e)} raised when searching for\nkey {e} in qeinput, necessary when ibrav = {ibrav}' @@ -846,8 +854,7 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state elif cell_unit == 'alat': if alat is None: raise InputValidationError( - 'You have specified units of alat for the cell, \n' - 'but you have not provided a value for alat' + 'You have specified units of alat for the cell, \n' 'but you have not provided a value for alat' ) cell = alat * cell elif cell_unit == '': @@ -868,31 +875,49 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state elif ibrav == 2: # 2 cubic F (fcc) # v1 = (a/2)(-1,0,1), v2 = (a/2)(0,1,1), v3 = (a/2)(-1,1,0) - cell = 0.5 * alat * np.array([ - [-1., 0., 1.], - [0., 1., 1.], - [-1., 1., 0.], - ]) + cell = ( + 0.5 + * alat + * np.array( + [ + [-1.0, 0.0, 1.0], + [0.0, 1.0, 1.0], + [-1.0, 1.0, 0.0], + ] + ) + ) elif ibrav == 3: # cubic I (bcc) # v1 = (a/2)(1,1,1), v2 = (a/2)(-1,1,1), v3 = (a/2)(-1,-1,1) - cell = 0.5 * alat * np.array([ - [1., 1., 1.], - [-1., 1., 1.], - [-1., -1., 1.], - ]) + cell = ( + 0.5 + * alat + * np.array( + [ + [1.0, 1.0, 1.0], + [-1.0, 1.0, 1.0], + [-1.0, -1.0, 1.0], + ] + ) + ) elif ibrav == -3: # cubic I (bcc), more symmetric axis: # v1 = (a/2)(-1,1,1), v2 = (a/2)(1,-1,1), v3 = (a/2)(1,1,-1) - cell = 0.5 * alat * np.array([ - [-1., 1., 1.], - [1., -1., 1.], - [1., 1., -1.], - ]) + cell = ( + 0.5 + * alat + * np.array( + [ + [-1.0, 1.0, 1.0], + [1.0, -1.0, 1.0], + [1.0, 1.0, -1.0], + ] + ) + ) elif ibrav == 4: # 4 Hexagonal and Trigonal P celldm(3)=c/a # v1 = a(1,0,0), v2 = a(-1/2,sqrt(3)/2,0), v3 = a(0,0,c/a) - cell = alat * np.array([[1., 0., 0.], [-0.5, 0.5 * np.sqrt(3.), 0.], [0., 0., c / alat]]) + cell = alat * np.array([[1.0, 0.0, 0.0], [-0.5, 0.5 * np.sqrt(3.0), 0.0], [0.0, 0.0, c / alat]]) elif ibrav == 5: # 5 Trigonal R, 3fold axis c celldm(4)=cos(alpha) # The crystallographic vectors form a three-fold star around @@ -901,10 +926,10 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state # where c=cos(alpha) is the cosine of the angle alpha between # any pair of crystallographic vectors, tx, ty, tz are: # tx=sqrt((1-c)/2), ty=sqrt((1-c)/6), tz=sqrt((1+2c)/3) - tx = np.sqrt((1. - cosa) / 2.) - ty = np.sqrt((1. - cosa) / 6.) - tz = np.sqrt((1. + 2. * cosa) / 3.) - cell = alat * np.array([[tx, -ty, tz], [0., 2 * ty, tz], [-tx, -ty, tz]]) + tx = np.sqrt((1.0 - cosa) / 2.0) + ty = np.sqrt((1.0 - cosa) / 6.0) + tz = np.sqrt((1.0 + 2.0 * cosa) / 3.0) + cell = alat * np.array([[tx, -ty, tz], [0.0, 2 * ty, tz], [-tx, -ty, tz]]) elif ibrav == -5: # -5 Trigonal R, 3fold axis <111> celldm(4)=cos(alpha) # The crystallographic vectors form a three-fold star around @@ -916,20 +941,20 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state # Note: if you prefer x,y,z as axis in the cubic limit, # set u = tz + 2*sqrt(2)*ty, v = tz - sqrt(2)*ty # See also the note in flib/latgen.f90 - tx = np.sqrt((1. - cosa) / 2.) - ty = np.sqrt((1. - cosa) / 6.) - tz = np.sqrt((1. + 2. * cosa) / 3.) - u = tz - 2. * np.sqrt(2.) * ty - v = tz + np.sqrt(2.) * ty - cell = alat / np.sqrt(3.) * np.array([[u, v, v], [v, u, v], [v, v, u]]) + tx = np.sqrt((1.0 - cosa) / 2.0) + ty = np.sqrt((1.0 - cosa) / 6.0) + tz = np.sqrt((1.0 + 2.0 * cosa) / 3.0) + u = tz - 2.0 * np.sqrt(2.0) * ty + v = tz + np.sqrt(2.0) * ty + cell = alat / np.sqrt(3.0) * np.array([[u, v, v], [v, u, v], [v, v, u]]) elif ibrav == 6: # 6 Tetragonal P (st) celldm(3)=c/a # v1 = a(1,0,0), v2 = a(0,1,0), v3 = a(0,0,c/a) - cell = alat * np.array([[1., 0., 0.], [0., 1., 0.], [0., 0., c / alat]]) + cell = alat * np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, c / alat]]) elif ibrav == 7: # 7 Tetragonal I (bct) celldm(3)=c/a # v1=(a/2)(1,-1,c/a), v2=(a/2)(1,1,c/a), v3=(a/2)(-1,-1,c/a) - cell = 0.5 * alat * np.array([[1., -1., c / alat], [1., 1., c / alat], [-1., -1., c / alat]]) + cell = 0.5 * alat * np.array([[1.0, -1.0, c / alat], [1.0, 1.0, c / alat], [-1.0, -1.0, c / alat]]) elif ibrav == 8: # 8 Orthorhombic P celldm(2)=b/a # celldm(3)=c/a @@ -939,11 +964,11 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state # 9 Orthorhombic base-centered(bco) celldm(2)=b/a # celldm(3)=c/a # v1 = (a/2, b/2,0), v2 = (-a/2,b/2,0), v3 = (0,0,c) - cell = np.array([[0.5 * alat, 0.5 * b, 0.], [-0.5 * alat, 0.5 * b, 0.], [0., 0., c]]) + cell = np.array([[0.5 * alat, 0.5 * b, 0.0], [-0.5 * alat, 0.5 * b, 0.0], [0.0, 0.0, c]]) elif ibrav == -9: # -9 as 9, alternate description # v1 = (a/2,-b/2,0), v2 = (a/2,-b/2,0), v3 = (0,0,c) - cell = np.array([[0.5 * alat, 0.5 * b, 0.], [0.5 * alat, -0.5 * b, 0.], [0., 0., c]]) + cell = np.array([[0.5 * alat, 0.5 * b, 0.0], [0.5 * alat, -0.5 * b, 0.0], [0.0, 0.0, c]]) elif ibrav == 91: # 91 Orthorhombic one-face base-centered A-type # celldm(2)=b/a @@ -954,27 +979,38 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state # 10 Orthorhombic face-centered celldm(2)=b/a # celldm(3)=c/a # v1 = (a/2,0,c/2), v2 = (a/2,b/2,0), v3 = (0,b/2,c/2) - cell = np.array([[0.5 * alat, 0., 0.5 * c], [0.5 * alat, 0.5 * b, 0.], [0., 0.5 * b, 0.5 * c]]) + cell = np.array( + [ + [0.5 * alat, 0.0, 0.5 * c], + [0.5 * alat, 0.5 * b, 0.0], + [0.0, 0.5 * b, 0.5 * c], + ] + ) elif ibrav == 11: # 11 Orthorhombic body-centered celldm(2)=b/a # celldm(3)=c/a # v1=(a/2,b/2,c/2), v2=(-a/2,b/2,c/2), v3=(-a/2,-b/2,c/2) - cell = np.array([[0.5 * alat, 0.5 * b, 0.5 * c], [-0.5 * alat, 0.5 * b, 0.5 * c], - [-0.5 * alat, -0.5 * b, 0.5 * c]]) + cell = np.array( + [ + [0.5 * alat, 0.5 * b, 0.5 * c], + [-0.5 * alat, 0.5 * b, 0.5 * c], + [-0.5 * alat, -0.5 * b, 0.5 * c], + ] + ) elif ibrav == 12: # 12 Monoclinic P, unique axis c celldm(2)=b/a # celldm(3)=c/a, # celldm(4)=cos(ab) # v1=(a,0,0), v2=(b*cos(gamma),b*sin(gamma),0), v3 = (0,0,c) # where gamma is the angle between axis a and b. - cell = np.array([[alat, 0., 0.], [b * cosg, b * sing, 0.], [0., 0., c]]) + cell = np.array([[alat, 0.0, 0.0], [b * cosg, b * sing, 0.0], [0.0, 0.0, c]]) elif ibrav == -12: # -12 Monoclinic P, unique axis b celldm(2)=b/a # celldm(3)=c/a, # celldm(5)=cos(ac) # v1 = (a,0,0), v2 = (0,b,0), v3 = (c*cos(beta),0,c*sin(beta)) # where beta is the angle between axis a and c - cell = np.array([[alat, 0., 0.], [0., b, 0.], [c * cosb, 0., c * sinb]]) + cell = np.array([[alat, 0.0, 0.0], [0.0, b, 0.0], [c * cosb, 0.0, c * sinb]]) elif ibrav == 13: # 13 Monoclinic base-centered celldm(2)=b/a # celldm(3)=c/a, @@ -983,7 +1019,13 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state # v2 = (b*cos(gamma), b*sin(gamma), 0), # v3 = ( a/2, 0, c/2), # where gamma is the angle between axis a and b - cell = np.array([[0.5 * alat, 0., -0.5 * c], [b * cosg, b * sing, 0.], [0.5 * alat, 0., 0.5 * c]]) + cell = np.array( + [ + [0.5 * alat, 0.0, -0.5 * c], + [b * cosg, b * sing, 0.0], + [0.5 * alat, 0.0, 0.5 * c], + ] + ) elif ibrav == -13: # -13 Monoclinic base-centered celldm(2)=b/a # (unique axis b) celldm(3)=c/a, @@ -995,9 +1037,21 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state # IMPORTANT NOTICE: until QE v.6.4.1, axis for ibrav=-13 had a # different definition: v1(now) = v2(old), v2(now) = -v1(old) if qe_version >= parse_version('6.5'): - cell = np.array([[0.5 * alat, 0.5 * b, 0], [-0.5 * alat, 0.5 * b, 0], [c * cosb, 0, c * sinb]]) + cell = np.array( + [ + [0.5 * alat, 0.5 * b, 0], + [-0.5 * alat, 0.5 * b, 0], + [c * cosb, 0, c * sinb], + ] + ) else: - cell = np.array([[0.5 * alat, -0.5 * b, 0], [0.5 * alat, 0.5 * b, 0], [c * cosb, 0, c * sinb]]) + cell = np.array( + [ + [0.5 * alat, -0.5 * b, 0], + [0.5 * alat, 0.5 * b, 0], + [c * cosb, 0, c * sinb], + ] + ) elif ibrav == 14: # 14 Triclinic celldm(2)= b/a, # celldm(3)= c/a, @@ -1012,23 +1066,30 @@ def _get_cell_from_parameters( # pylint: disable=too-many-locals,too-many-state # where alpha is the angle between axis b and c # beta is the angle between axis a and c # gamma is the angle between axis a and b - cell = np.array([[alat, 0., 0.], [b * cosg, b * sing, 0.], - [ - c * cosb, c * (cosa - cosb * cosg) / sing, - c * np.sqrt(1. + 2. * cosa * cosb * cosg - cosa**2 - cosb**2 - cosg**2) / sing - ]]) + cell = np.array( + [ + [alat, 0.0, 0.0], + [b * cosg, b * sing, 0.0], + [ + c * cosb, + c * (cosa - cosb * cosg) / sing, + c * np.sqrt(1.0 + 2.0 * cosa * cosb * cosg - cosa**2 - cosb**2 - cosg**2) / sing, + ], + ] + ) return cell def _parse_structure( # pylint: disable=too-many-arguments,too-many-branches,too-many-locals - txt=None, - namelists=None, - atomic_species=None, - atomic_positions=None, - cell_parameters=None, - *, - qe_version=None): + txt=None, + namelists=None, + atomic_species=None, + atomic_positions=None, + cell_parameters=None, + *, + qe_version=None, +): """ This function parses a Quantum ESPRESSO input file and returns a dictionary of parsed information. @@ -1117,7 +1178,10 @@ def _parse_structure( # pylint: disable=too-many-arguments,too-many-branches,to ) ######### DEFINE SITES ###################### return dict( - positions=positions.tolist(), species=atomic_species, cell=cell.tolist(), atom_names=atomic_positions['names'] + positions=positions.tolist(), + species=atomic_species, + cell=cell.tolist(), + atom_names=atomic_positions['names'], ) @@ -1146,14 +1210,14 @@ def _strip_comment(string, comment_characters=('!',), quote_characters=('"', "'" raise ValueError('I still cannot cope with newlines in the string...') # Check if we are entering/existing a string if in_string and char == string_quote: - #print("EXIT") + # print("EXIT") in_string = False string_quote = None elif not in_string and char in quote_characters: - #print("ENTER") + # print("ENTER") in_string = True string_quote = char - #print(char, in_string, string_quote) + # print(char, in_string, string_quote) # We found a comment, return until here (without the comment) if not in_string and char in comment_characters: diff --git a/src/qe_tools/parsers/_pw_input.py b/src/qe_tools/parsers/_pw_input.py index 0be5981..feaa544 100644 --- a/src/qe_tools/parsers/_pw_input.py +++ b/src/qe_tools/parsers/_pw_input.py @@ -155,7 +155,11 @@ def __init__(self, content, *, qe_version=None, validate_species_names=True): parsing the content. """ - super().__init__(content, qe_version=qe_version, validate_species_names=validate_species_names) + super().__init__( + content, + qe_version=qe_version, + validate_species_names=validate_species_names, + ) # Parse the K_POINTS card. self.k_points = parse_k_points(self._input_txt) @@ -163,9 +167,11 @@ def __init__(self, content, *, qe_version=None, validate_species_names=True): def as_dict(self) -> dict: """Return parsed data as dictionary.""" dictionary = super().as_dict() - dictionary.update({ - 'k-points': self.k_points, - }) + dictionary.update( + { + 'k-points': self.k_points, + } + ) return dictionary @@ -228,13 +234,15 @@ def parse_k_points(txt): ^ [ \t]* \S+ [ \t]+ \S+ [ \t]+ \S+ [ \t]+ \S+ [ \t]* $\n? )+ ) - """, RE_FLAGS + """, + RE_FLAGS, ) # Define re for the info contained in the special-type block. k_points_special_re = re.compile( r""" ^ [ \t]* (\S+) [ \t]+ (\S+) [ \t]+ (\S+) [ \t]+ (\S+) [ \t]* $\n? - """, RE_FLAGS + """, + RE_FLAGS, ) # Define re for the automatic-type card block and its line of info. k_points_automatic_block_re = re.compile( @@ -242,13 +250,15 @@ def parse_k_points(txt): ^ [ \t]* K_POINTS [ \t]* [{(]? [ \t]* automatic [ \t]* [)}]? [ \t]* $\n ^ [ \t]* (\S+) [ \t]+ (\S+) [ \t]+ (\S+) [ \t]+ (\S+) [ \t]+ (\S+) [ \t]+ (\S+) [ \t]* $\n? - """, RE_FLAGS + """, + RE_FLAGS, ) # Define re for the gamma-type card block. (There is no block info.) k_points_gamma_block_re = re.compile( r""" ^ [ \t]* K_POINTS [ \t]* [{(]? [ \t]* gamma [ \t]* [)}]? [ \t]* $\n - """, RE_FLAGS + """, + RE_FLAGS, ) # Try finding the card block using all three types. info_dict = {} @@ -271,7 +281,7 @@ def parse_k_points(txt): if match: info_dict['type'] = 'automatic' info_dict['points'] = list(map(int, match.group(1, 2, 3))) - info_dict['offset'] = [0. if x == 0 else 0.5 for x in map(int, match.group(4, 5, 6))] + info_dict['offset'] = [0.0 if x == 0 else 0.5 for x in map(int, match.group(4, 5, 6))] else: match = k_points_gamma_block_re.search(txt) if match: diff --git a/src/qe_tools/parsers/pw.py b/src/qe_tools/parsers/pw.py new file mode 100644 index 0000000..9860702 --- /dev/null +++ b/src/qe_tools/parsers/pw.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +"""Parser for the output of the Quantum ESPRESSO pw.x code.""" + +from importlib.resources import files +from pathlib import Path +from xml.etree import ElementTree + +import numpy +import pint +from xmlschema import XMLSchema + +from qe_tools import CONSTANTS +from qe_tools.parsers import schemas + + +class PwParser: + """Parser for the output of the Quantum ESPRESSO pw.x code.""" + + def __init__(self, raw_data: dict = None): + self.raw_data = raw_data or {} + + def parse_xml(self, xml_file: str | Path): + """Parse the XML output of Quantum ESPRESSO pw.x.""" + + xml_parsed = ElementTree.parse(xml_file) + + element_root = xml_parsed.getroot() + schema_filename = ( + element_root.get('{http://www.w3.org/2001/XMLSchema-instance}schemaLocation').split()[1].split('/')[-1] + ) + + # Fix a bug of QE v6.8: the output XML is not consistent with schema, see + # https://github.com/aiidateam/aiida-quantumespresso/pull/717 + try: + if element_root.find('general_info').find('creator').get('VERSION') == '6.8': + root = xml_parsed.getroot() + timing_info = root.find('./timing_info') + partial_pwscf = timing_info.find("partial[@label='PWSCF'][@calls='0']") + try: + timing_info.remove(partial_pwscf) + except (TypeError, ValueError): + pass + except AttributeError: + pass + + # Fix issue for QE v7.0: The scheme file name was not updated to `qes_211101.xsd` in the `xsi.schemaLocation` + # element, see https://github.com/aiidateam/aiida-quantumespresso/pull/774 + try: + if element_root.find('general_info').find('creator').get('VERSION') == '7.0': + schema_filename = 'qes_211101.xsd' + except AttributeError: + pass + + self.raw_data['xml'] = XMLSchema(str(files(schemas) / schema_filename)).to_dict(xml_parsed) + + def parse_stdout(self, output_file: str | Path): + pass + + @classmethod + def from_dir(cls, directory: str | Path): + pass + + def get_output_ase(self): + """Convert the parsed data to ASE objects.""" + from ase import Atoms + + ureg = pint.UnitRegistry() + + converted_outputs = {} + + xml_dict = self.raw_data.get('xml') + + try: + cell = ( + numpy.array([v for v in xml_dict['output']['atomic_structure']['cell'].values()]) + * CONSTANTS.bohr_to_ang + ) + symbols = [el['@name'] for el in xml_dict['output']['atomic_structure']['atomic_positions']['atom']] + positions = ( + numpy.array([el['$'] for el in xml_dict['output']['atomic_structure']['atomic_positions']['atom']]) + * CONSTANTS.bohr_to_ang + ) + + converted_outputs['ase_structure'] = Atoms( + cell=cell, + positions=positions, + symbols=symbols, + pbc=True, + ) + except KeyError: + pass + + try: + converted_outputs['energy'] = xml_dict['output']['total_energy']['etot'] * CONSTANTS.ry_to_ev * ureg.eV + except KeyError: + pass + + try: + converted_outputs['forces'] = ( + numpy.array(xml_dict['output']['forces']['$']).reshape(xml_dict['output']['forces']['@dims']) + * 2 + * CONSTANTS.ry_to_ev + / CONSTANTS.bohr_to_ang + * ureg.eV + / ureg.angstrom + ) + except KeyError: + pass + + return converted_outputs diff --git a/src/qe_tools/parsers/schemas/__init__.py b/src/qe_tools/parsers/schemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/qe_tools/parsers/schemas/qes_030920.xsd b/src/qe_tools/parsers/schemas/qes_030920.xsd new file mode 100644 index 0000000..dfa8335 --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_030920.xsd @@ -0,0 +1,1036 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qe_tools/parsers/schemas/qes_190304.xsd b/src/qe_tools/parsers/schemas/qes_190304.xsd new file mode 100644 index 0000000..10442e6 --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_190304.xsd @@ -0,0 +1,1005 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qe_tools/parsers/schemas/qes_191206.xsd b/src/qe_tools/parsers/schemas/qes_191206.xsd new file mode 100644 index 0000000..8fc3ffa --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_191206.xsd @@ -0,0 +1,1006 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qe_tools/parsers/schemas/qes_200420.xsd b/src/qe_tools/parsers/schemas/qes_200420.xsd new file mode 100644 index 0000000..dfa8335 --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_200420.xsd @@ -0,0 +1,1036 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qe_tools/parsers/schemas/qes_210716.xsd b/src/qe_tools/parsers/schemas/qes_210716.xsd new file mode 100644 index 0000000..dfa8335 --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_210716.xsd @@ -0,0 +1,1036 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qe_tools/parsers/schemas/qes_211101.xsd b/src/qe_tools/parsers/schemas/qes_211101.xsd new file mode 100644 index 0000000..52d0793 --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_211101.xsd @@ -0,0 +1,1204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qe_tools/parsers/schemas/qes_220603.xsd b/src/qe_tools/parsers/schemas/qes_220603.xsd new file mode 100644 index 0000000..038176a --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_220603.xsd @@ -0,0 +1,1348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qe_tools/parsers/schemas/qes_230310.xsd b/src/qe_tools/parsers/schemas/qes_230310.xsd new file mode 100644 index 0000000..a68aad3 --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_230310.xsd @@ -0,0 +1,1370 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qe_tools/parsers/schemas/qes_240411.xsd b/src/qe_tools/parsers/schemas/qes_240411.xsd new file mode 100644 index 0000000..160930f --- /dev/null +++ b/src/qe_tools/parsers/schemas/qes_240411.xsd @@ -0,0 +1,1391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_cell_conversion.py b/tests/test_cell_conversion.py index 39e8c79..678e547 100644 --- a/tests/test_cell_conversion.py +++ b/tests/test_cell_conversion.py @@ -33,7 +33,7 @@ def case_structure_generator(path): return ins, None, ValueError outs = {} - for key in (['a', 'b', 'c', 'cosab', 'cosac', 'cosbc'] + [f'celldm({i})' for i in range(1, 7)]): + for key in ['a', 'b', 'c', 'cosab', 'cosac', 'cosbc'] + [f'celldm({i})' for i in range(1, 7)]: if key in system_dict: outs[key] = system_dict[key] diff --git a/tests/test_parsers.py b/tests/test_parsers.py index 119072c..43a9e0c 100755 --- a/tests/test_parsers.py +++ b/tests/test_parsers.py @@ -123,7 +123,9 @@ def singletest(self, label, parser='pw', qe_version=None, validate_species_names # that the parser properly copes with them with open(fname, 'rb') as in_file: res_obj = ParserClass( - in_file.read().decode('utf-8'), qe_version=qe_version, validate_species_names=validate_species_names + in_file.read().decode('utf-8'), + qe_version=qe_version, + validate_species_names=validate_species_names, ) structure = res_obj.structure @@ -317,7 +319,7 @@ def mytest(): mytest() ##Wyckoff position input (crystal_sg) not supported by this parser - #def test_lattice_wyckoff_sio2(self): + # def test_lattice_wyckoff_sio2(self): # self.singletest(label='lattice_wyckoff_sio2') @@ -377,7 +379,10 @@ def print_test_comparison(label, parser='pw', write=False): try: label = sys.argv[2] except IndexError: - print('Pass as filename (and optionally pw or cp to specify a parser, default: pw)', file=sys.stderr) + print( + 'Pass as filename (and optionally pw or cp to specify a parser, default: pw)', + file=sys.stderr, + ) sys.exit(1) try: parser = sys.argv[3] @@ -385,7 +390,10 @@ def print_test_comparison(label, parser='pw', write=False): parser = 'pw' # pylint: disable=invalid-name print_test_comparison(label, parser=parser, write=True) else: - print('If you pass additional parameters, they must be --write-ref