From c3d86166fe00e7761a1ab20e2d96700072b54e69 Mon Sep 17 00:00:00 2001 From: Toon Verstraelen Date: Thu, 13 Jun 2024 20:35:33 +0200 Subject: [PATCH 1/2] Build documentation with the --nitpicky option --- .github/workflows/sphinx.yaml | 2 +- docs/Makefile | 2 +- docs/conf.py | 5 +++-- docs/gen_inputs.py | 2 +- docs/make.bat | 1 + docs/requirements.txt | 1 + iodata/api.py | 11 ++++----- iodata/attrutils.py | 7 +++--- iodata/basis.py | 27 +++++++++++----------- iodata/docstrings.py | 42 ++++++++++++++++------------------- iodata/formats/chgcar.py | 12 +++++----- iodata/formats/cp2klog.py | 35 ++++++++++++++--------------- iodata/formats/cube.py | 23 +++++++++---------- iodata/formats/fchk.py | 15 ++++++------- iodata/formats/gamess.py | 8 +++---- iodata/formats/gaussianlog.py | 10 ++++----- iodata/formats/json.py | 4 +--- iodata/formats/mol2.py | 6 +++-- iodata/formats/molden.py | 10 +++++---- iodata/formats/molekel.py | 8 ++++--- iodata/formats/orcalog.py | 12 +++++----- iodata/formats/qchemlog.py | 10 +++++---- iodata/formats/wfn.py | 19 ++++++++-------- iodata/iodata.py | 30 ++++++++++++------------- iodata/orbitals.py | 8 +++---- iodata/overlap.py | 20 +++++++---------- iodata/test/common.py | 25 +++++++++++---------- iodata/test/test_attrutils.py | 2 +- iodata/utils.py | 26 ++++++++++++---------- pyproject.toml | 1 + 30 files changed, 190 insertions(+), 194 deletions(-) diff --git a/.github/workflows/sphinx.yaml b/.github/workflows/sphinx.yaml index ba4f1330..763ca0f4 100644 --- a/.github/workflows/sphinx.yaml +++ b/.github/workflows/sphinx.yaml @@ -45,7 +45,7 @@ jobs: - name: Run sphinx run: | cd docs - python -m sphinx -M html . _build -W --keep-going --fresh-env + python -m sphinx -M html . _build -W --keep-going --fresh-env --nitpicky - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: diff --git a/docs/Makefile b/docs/Makefile index d4bb2cbb..5a33029d 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -3,7 +3,7 @@ # You can set these variables from the command line, and also # from the environment for the first two. -SPHINXOPTS ?= +SPHINXOPTS ?= -W --keep-going --nitpicky SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build diff --git a/docs/conf.py b/docs/conf.py index 6e7b8ef3..96248c9f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,6 +7,7 @@ import runpy import sys +from intersphinx_registry import get_intersphinx_mapping from packaging.version import Version from sphinx.ext.apidoc import main as main_api_doc @@ -38,6 +39,7 @@ templates_path = ["_templates"] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +intersphinx_mapping = get_intersphinx_mapping(packages={"python", "numpy", "scipy"}) # -- Options for HTML output ------------------------------------------------- @@ -56,8 +58,7 @@ "inherited-members": True, "ignore-module-all": True, } - - +napoleon_use_rtype = False add_module_names = False diff --git a/docs/gen_inputs.py b/docs/gen_inputs.py index 1c10db87..f879736f 100755 --- a/docs/gen_inputs.py +++ b/docs/gen_inputs.py @@ -63,7 +63,7 @@ def main(): for line in lines[2:]: print(line, file=file) - print_section(f":py:func:`iodata.formats.{modname}.write_input`", "-", file=file) + print_section(f":py:func:`iodata.inputs.{modname}.write_input`", "-", file=file) fn = getattr(module, "write_input", None) print("- Requires", format_words(fn.required), file=file) if fn.optional: diff --git a/docs/make.bat b/docs/make.bat index 954237b9..7c06d8df 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -4,6 +4,7 @@ pushd %~dp0 REM Command file for Sphinx documentation +set SPHINXOPTS="-W --keep-going --nitpicky" if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) diff --git a/docs/requirements.txt b/docs/requirements.txt index 0241678f..cd8784fe 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,6 @@ # Requirements for building documentation on RTD furo +intersphinx-registry packaging setuptools_scm sphinx_autodoc_typehints diff --git a/iodata/api.py b/iodata/api.py index 66e44502..838fa21d 100644 --- a/iodata/api.py +++ b/iodata/api.py @@ -61,8 +61,7 @@ def _select_format_module(filename: str, attrname: str, fmt: Optional[str] = Non Returns ------- - format_module - The module implementing the required file format. + The module implementing the required file format. """ basename = os.path.basename(filename) @@ -101,8 +100,7 @@ def _select_input_module(fmt: str) -> ModuleType: Returns ------- - format_module - The module implementing the required input format. + The module implementing the required input format. """ if fmt in INPUT_MODULES: @@ -131,8 +129,7 @@ def load_one(filename: str, fmt: Optional[str] = None, **kwargs) -> IOData: Returns ------- - out - The instance of IOData with data loaded from the input files. + The instance of IOData with data loaded from the input files. """ format_module = _select_format_module(filename, "load_one", fmt) @@ -163,7 +160,7 @@ def load_many(filename: str, fmt: Optional[str] = None, **kwargs) -> Iterator[IO Yields ------ - out + IOData An instance of IOData with data for one frame loaded for the file. """ diff --git a/iodata/attrutils.py b/iodata/attrutils.py index 3e157aed..54df6acb 100644 --- a/iodata/attrutils.py +++ b/iodata/attrutils.py @@ -18,6 +18,8 @@ # -- """Utilities for building attr classes.""" +from typing import Callable + import numpy as np __all__ = ["convert_array_to", "validate_shape"] @@ -34,7 +36,7 @@ def converter(array): return converter -def validate_shape(*shape_requirements: tuple): +def validate_shape(*shape_requirements: tuple) -> Callable: """Return a validator for the shape of an array or the length of an iterable. Parameters @@ -49,8 +51,7 @@ def validate_shape(*shape_requirements: tuple): Returns ------- - validator - A validator function for the attr library. + A validator function for the attr library. Notes ----- diff --git a/iodata/basis.py b/iodata/basis.py index dd1420f9..00941078 100644 --- a/iodata/basis.py +++ b/iodata/basis.py @@ -72,9 +72,8 @@ def angmom_sti(char: Union[str, list[str]]) -> Union[int, list[int]]: Returns ------- - angmom - An integer representation of the angular momentum. If a list of str - char is given, a list of integers in returned. + An integer representation of the angular momentum. + If a list of str char is given, a list of integers in returned. """ return ANGMOM_CHARS.index(char.lower()) @@ -91,9 +90,8 @@ def angmom_its(angmom: Union[int, list[int]]) -> Union[str, list[str]]: Returns ------- - char - The string representation of the angular momentum. If a list of integer - angmom is given, a list of str is returned. + The string representation of the angular momentum. + If a list of integer angmom is given, a list of str is returned. """ if angmom < 0: @@ -113,15 +111,16 @@ class Shell: kinds: list[str] = attrs.field(validator=validate_shape(("coeffs", 1))) """ - List of strings describing the kind of contractions: 'c' for Cartesian - and 'p' for pure. Pure functions are only allowed for angmom>1. - The length equals the number of contractions: len(angmoms)=ncon. + List of strings describing the kind of contractions: + ``'c'`` for Cartesian and ``'p'`` for pure. + Pure functions are only allowed for ``angmom > 1``. + The length equals the number of contractions (``ncon = len(kinds)``). """ - exponents: NDArray = attrs.field(validator=validate_shape(("coeffs", 0))) + exponents: NDArray[float] = attrs.field(validator=validate_shape(("coeffs", 0))) """The array containing the exponents of the primitives, with shape (nprim,).""" - coeffs: NDArray = attrs.field(validator=validate_shape(("exponents", 0), ("kinds", 0))) + coeffs: NDArray[float] = attrs.field(validator=validate_shape(("exponents", 0), ("kinds", 0))) """ The array containing the coefficients of the normalized primitives in each contraction; shape = (nprim, ncon). @@ -222,7 +221,7 @@ def get_segmented(self): def convert_convention_shell( conv1: list[str], conv2: list[str], reverse=False -) -> tuple[NDArray, NDArray]: +) -> tuple[NDArray[int], NDArray[int]]: """Return a permutation vector and sign changes to convert from 1 to 2. The transformation from convention 1 to convention 2 can be done applying @@ -284,7 +283,7 @@ def convert_convention_shell( def convert_conventions( molbasis: MolecularBasis, new_conventions: dict[str, list[str]], reverse=False -) -> tuple[NDArray, NDArray]: +) -> tuple[NDArray[int], NDArray[int]]: """Return a permutation vector and sign changes to convert from 1 to 2. The transformation from molbasis.convention to the new convention can be done @@ -334,7 +333,7 @@ def convert_conventions( return np.array(permutation), np.array(signs) -def iter_cart_alphabet(n: int) -> NDArray: +def iter_cart_alphabet(n: int) -> NDArray[int]: """Loop over powers of Cartesian basis functions in alphabetical order. See https://theochem.github.io/horton/2.1.1/tech_ref_gaussian_basis.html diff --git a/iodata/docstrings.py b/iodata/docstrings.py index 364d668c..fe347006 100644 --- a/iodata/docstrings.py +++ b/iodata/docstrings.py @@ -18,7 +18,7 @@ # -- """Docstring decorators for file format implementations.""" -from typing import Optional +from typing import Callable, Optional __all__ = [ "document_load_one", @@ -36,7 +36,7 @@ def _document_load( ifpresent: Optional[list[str]] = None, kwdocs: Optional[dict[str, str]] = None, notes: Optional[str] = None, -): +) -> Callable: if kwdocs is None: kwdocs = {} ifpresent = ifpresent or [] @@ -76,6 +76,7 @@ def decorator(func): lit The line iterator to read the data from. {kwdocs} + Returns ------- result: dict @@ -84,7 +85,6 @@ def decorator(func): Notes ----- - {notes} """ @@ -96,7 +96,7 @@ def document_load_one( ifpresent: Optional[list[str]] = None, kwdocs: Optional[dict[str, str]] = None, notes: Optional[str] = None, -): +) -> Callable: """Decorate a load_one function to generate a docstring. Parameters @@ -116,8 +116,7 @@ def document_load_one( Returns ------- - decorator - A decorator function. + A decorator function. """ if kwdocs is None: @@ -133,6 +132,7 @@ def document_load_one( lit The line iterator to read the data from. {kwdocs} + Yields ------ result: dict @@ -141,7 +141,6 @@ def document_load_one( Notes ----- - {notes} """ @@ -153,7 +152,7 @@ def document_load_many( ifpresent: Optional[list[str]] = None, kwdocs: Optional[dict[str, str]] = None, notes: Optional[str] = None, -): +) -> Callable: """Decorate a load_many function to generate a docstring. Parameters @@ -173,8 +172,7 @@ def document_load_many( Returns ------- - decorator - A decorator function. + A decorator function. """ if kwdocs is None: @@ -189,7 +187,7 @@ def _document_dump( optional: Optional[list[str]] = None, kwdocs: Optional[dict[str, str]] = None, notes: Optional[str] = None, -): +) -> Callable: if kwdocs is None: kwdocs = {} optional = optional or [] @@ -233,9 +231,9 @@ def decorator(func): An IOData instance which must have the following attributes initialized: {required}.{optional} {kwdocs} + Notes ----- - {notes} """ @@ -247,7 +245,7 @@ def document_dump_one( optional: Optional[list[str]] = None, kwdocs: Optional[dict[str, str]] = None, notes: Optional[str] = None, -): +) -> Callable: """Decorate a dump_one function to generate a docstring. Parameters @@ -267,8 +265,7 @@ def document_dump_one( Returns ------- - decorator - A decorator function. + A decorator function. """ if kwdocs is None: @@ -287,9 +284,9 @@ def document_dump_one( An iterator over IOData instances which must have the following attributes initialized: {required}.{optional} {kwdocs} + Notes ----- - {notes} """ @@ -301,7 +298,7 @@ def document_dump_many( optional: Optional[list[str]] = None, kwdocs: Optional[dict[str, str]] = None, notes: Optional[str] = None, -): +) -> Callable: """Decorate a dump_many function to generate a docstring. Parameters @@ -321,8 +318,7 @@ def document_dump_many( Returns ------- - decorator - A decorator function. + A decorator function. """ if kwdocs is None: @@ -336,7 +332,7 @@ def _document_write( required: list[str], optional: Optional[list[str]] = None, notes: Optional[str] = None, -): +) -> Callable: if optional is None: optional = [] @@ -383,6 +379,7 @@ def decorator(func): input format is used. **kwargs Keyword arguments are passed on to the input-specific write_input function. + Notes ----- @@ -396,7 +393,7 @@ def document_write_input( required: list[str], optional: Optional[list[str]] = None, notes: Optional[str] = None, -): +) -> Callable: """Decorate a write_input function to generate a docstring. Parameters @@ -412,8 +409,7 @@ def document_write_input( Returns ------- - decorator - A decorator function. + A decorator function. """ return _document_write(WRITE_INPUT_DOC_TEMPLATE, fmt, required, optional, notes) diff --git a/iodata/formats/chgcar.py b/iodata/formats/chgcar.py index 619e1c53..766f27e6 100644 --- a/iodata/formats/chgcar.py +++ b/iodata/formats/chgcar.py @@ -38,7 +38,9 @@ PATTERNS = ["CHGCAR*", "AECCAR*"] -def _load_vasp_header(lit: LineIterator) -> tuple[str, NDArray, NDArray, NDArray]: +def _load_vasp_header( + lit: LineIterator, +) -> tuple[str, NDArray[float], NDArray[int], NDArray[float]]: """Load the cell and atoms from a VASP file format. Parameters @@ -48,8 +50,7 @@ def _load_vasp_header(lit: LineIterator) -> tuple[str, NDArray, NDArray, NDArray Returns ------- - out - Output Contains ``title``, ``cellvecs``, ``atnums``, ``atcoords``. + Tuple with ``title``, ``cellvecs``, ``atnums``, ``atcoords``. Notes ----- @@ -104,9 +105,8 @@ def _load_vasp_grid(lit: LineIterator) -> dict: Returns ------- - out - Output dictionary containing ``title``, ``atcoords``, ``atnums``, - ``cellvecs`` & ``cube`` keys and their corresponding values. + oDictionary containing ``title``, ``atcoords``, ``atnums``, ``cellvecs`` & ``cube`` + keys and their corresponding values. """ # Load header diff --git a/iodata/formats/cp2klog.py b/iodata/formats/cp2klog.py index 14423d2d..38a33fc1 100644 --- a/iodata/formats/cp2klog.py +++ b/iodata/formats/cp2klog.py @@ -43,7 +43,9 @@ } -def _get_cp2k_norm_corrections(ell: int, alphas: Union[float, NDArray]) -> Union[float, NDArray]: +def _get_cp2k_norm_corrections( + ell: int, alphas: Union[float, NDArray[float]] +) -> Union[float, NDArray[float]]: """Compute the corrections for the normalization of the basis functions. This correction is needed because the CP2K atom code works with a different @@ -82,8 +84,7 @@ def _read_cp2k_contracted_obasis(lit: LineIterator) -> MolecularBasis: Returns ------- - obasis - The orbital basis. + The orbital basis. """ shells = [] @@ -128,9 +129,8 @@ def _read_cp2k_uncontracted_obasis(lit: LineIterator) -> MolecularBasis: Returns ------- - obasis - The orbital basis parameters read from the file. Can be used to - initialize a GOBasis object. + The orbital basis parameters read from the file. + Can be used to initialize a GOBasis object. """ # Load the relevant data from the file @@ -172,9 +172,7 @@ def _read_cp2k_obasis(lit: LineIterator) -> dict: Returns ------- - out - The atomic orbital basis data which can be used to initialize a - ``GOBasis`` class. + The atomic orbital basis data which can be used to initialize a ``GOBasis`` class. """ next(lit) # Skip empty line @@ -235,7 +233,7 @@ def _read_cp2k_occupations_energies( def _read_cp2k_orbital_coeffs( lit: LineIterator, oe: list[tuple[int, int, float, float]] -) -> dict[tuple[int, int], NDArray]: +) -> dict[tuple[int, int], NDArray[float]]: """Read the expansion coefficients of the orbital from an open CP2K ATOM output. Parameters @@ -248,8 +246,7 @@ def _read_cp2k_orbital_coeffs( Returns ------- - result - Key is an (l, s) pair and value is an array with orbital coefficients. + Dictionary in which keys are an (l, s) pair and values are arrays with orbital coefficients. """ allcoeffs = {} @@ -280,8 +277,10 @@ def _get_norb_nel(oe: list[tuple[int, int, float, float]]) -> tuple[int, float]: Returns ------- - Tuple - Number of orbitals and electrons + norb + The number of orbitals. + nelec + The number of electrons. """ norb = 0 @@ -293,11 +292,11 @@ def _get_norb_nel(oe: list[tuple[int, int, float, float]]) -> tuple[int, float]: def _fill_orbitals( - orb_coeffs: NDArray, - orb_energies: NDArray, - orb_occupations: NDArray, + orb_coeffs: NDArray[float], + orb_energies: NDArray[float], + orb_occupations: NDArray[float], oe: list[tuple[int, int, float, float]], - coeffs: dict[tuple[int, int], NDArray], + coeffs: dict[tuple[int, int], NDArray[float]], obasis: MolecularBasis, restricted: bool, ): diff --git a/iodata/formats/cube.py b/iodata/formats/cube.py index df190970..36d71f27 100644 --- a/iodata/formats/cube.py +++ b/iodata/formats/cube.py @@ -43,7 +43,7 @@ def _read_cube_header( lit: LineIterator, -) -> tuple[str, NDArray, NDArray, NDArray, dict[str, NDArray], NDArray]: +) -> tuple[str, NDArray[float], NDArray[int], NDArray[float], dict[str, NDArray], NDArray[float]]: """Load header data from a CUBE file object. Parameters @@ -53,9 +53,7 @@ def _read_cube_header( Returns ------- - out - The output tuple contains title, atcoords, atnums, cellvecs, ugrid & - atcorenums. + Tuple with ``title``, ``atcoords``, ``atnums``, ``cellvecs``, ``ugrid`` & ``atcorenums``. """ # Read the title @@ -63,7 +61,7 @@ def _read_cube_header( # skip the second line next(lit) - def read_grid_line(line: str) -> tuple[int, NDArray]: + def read_grid_line(line: str) -> tuple[int, NDArray[float]]: """Read a grid line from the cube file.""" words = line.split() return ( @@ -84,7 +82,7 @@ def read_grid_line(line: str) -> tuple[int, NDArray]: cellvecs = axes * shape.reshape(-1, 1) cube = {"origin": origin, "axes": axes, "shape": shape} - def read_atom_line(line: str) -> tuple[int, float, NDArray]: + def read_atom_line(line: str) -> tuple[int, float, NDArray[float]]: """Read an atomic number and coordinate from the cube file.""" words = line.split() return ( @@ -107,7 +105,7 @@ def read_atom_line(line: str) -> tuple[int, float, NDArray]: return title, atcoords, atnums, cellvecs, cube, atcorenums -def _read_cube_data(lit: LineIterator, cube: dict[str, NDArray]): +def _read_cube_data(lit: LineIterator, cube: dict[str, NDArray[float]]): """Load cube data from a CUBE file object. Parameters @@ -117,8 +115,7 @@ def _read_cube_data(lit: LineIterator, cube: dict[str, NDArray]): Returns ------- - out - The cube data array. + The cube data array. """ cube["data"] = np.zeros(tuple(cube["shape"]), float) @@ -151,10 +148,10 @@ def load_one(lit: LineIterator) -> dict: def _write_cube_header( f: TextIO, title: str, - atcoords: NDArray, - atnums: NDArray, + atcoords: NDArray[float], + atnums: NDArray[int], cube: dict[str, NDArray], - atcorenums: NDArray, + atcorenums: NDArray[float], ): print(title, file=f) print("OUTER LOOP: X, MIDDLE LOOP: Y, INNER LOOP: Z", file=f) @@ -170,7 +167,7 @@ def _write_cube_header( print(f"{atnums[i]:5d} {q: 11.6f} {x: 11.6f} {y: 11.6f} {z: 11.6f}", file=f) -def _write_cube_data(f: TextIO, cube_data: NDArray, block_size: int): +def _write_cube_data(f: TextIO, cube_data: NDArray[float], block_size: int): counter = 0 for value in cube_data.flat: f.write(f" {value: 12.5E}") diff --git a/iodata/formats/fchk.py b/iodata/formats/fchk.py index baf1bb9a..6b76273c 100644 --- a/iodata/formats/fchk.py +++ b/iodata/formats/fchk.py @@ -369,9 +369,9 @@ def _load_fchk_low(lit: LineIterator, label_patterns: Optional[list[str]] = None Returns ------- - fields - The data read from the FCHK file. Keys are the field names and values - are either scalar or array data. Arrays are always one-dimensional. + A dictionary with data read from the FCHK file. + Keys are the field names and values are either scalar or array data. + Arrays are always one-dimensional. """ # Read the two-line header @@ -474,7 +474,7 @@ def _load_dm(label: str, fchk: dict, result: dict, key: str): result[key] = _triangle_to_dense(fchk[label]) -def _triangle_to_dense(triangle: NDArray) -> NDArray: +def _triangle_to_dense(triangle: NDArray[float]) -> NDArray[float]: """Convert a symmetric matrix in triangular storage to a dense square matrix. Parameters @@ -486,8 +486,7 @@ def _triangle_to_dense(triangle: NDArray) -> NDArray: Returns ------- - ndarray - a square symmetric matrix. + A square symmetric matrix. """ nrow = int(np.round((np.sqrt(1 + 8 * len(triangle)) - 1) / 2)) @@ -513,7 +512,7 @@ def _dump_real_scalars(name: str, val: float, f: TextIO): print(f"{name:40} R {float(val): 16.8E}", file=f) -def _dump_integer_arrays(name: str, val: NDArray, f: TextIO): +def _dump_integer_arrays(name: str, val: NDArray[int], f: TextIO): """Dumper for a array of integers.""" nval = val.size if nval != 0: @@ -528,7 +527,7 @@ def _dump_integer_arrays(name: str, val: NDArray, f: TextIO): k = 0 -def _dump_real_arrays(name: str, val: NDArray, f: TextIO): +def _dump_real_arrays(name: str, val: NDArray[float], f: TextIO): """Dumper for a array of float.""" nval = val.size if nval != 0: diff --git a/iodata/formats/gamess.py b/iodata/formats/gamess.py index 608bc916..d87b0d41 100644 --- a/iodata/formats/gamess.py +++ b/iodata/formats/gamess.py @@ -47,7 +47,7 @@ def _read_data(lit: LineIterator) -> tuple[str, str, list[str]]: return title, symmetry, symbols -def _read_coordinates(lit: LineIterator, result: dict[str]) -> tuple[NDArray, NDArray]: +def _read_coordinates(lit: LineIterator, result: dict[str]) -> tuple[NDArray[int], NDArray[float]]: """Extract ``numbers`` and ``coordinates`` from the punch file.""" for _ in range(2): next(lit) @@ -68,7 +68,7 @@ def _read_coordinates(lit: LineIterator, result: dict[str]) -> tuple[NDArray, ND return numbers, coordinates -def _read_energy(lit: LineIterator, result: dict[str]) -> tuple[float, NDArray]: +def _read_energy(lit: LineIterator, result: dict[str]) -> tuple[float, NDArray[float]]: """Extract ``energy`` and ``gradient`` from the punch file.""" energy = float(next(lit).split()[1]) natom = len(result["symbols"]) @@ -82,7 +82,7 @@ def _read_energy(lit: LineIterator, result: dict[str]) -> tuple[float, NDArray]: return energy, gradient -def _read_hessian(lit: LineIterator, result: dict[str]) -> NDArray: +def _read_hessian(lit: LineIterator, result: dict[str]) -> NDArray[float]: """Extract ``hessian`` from the punch file.""" # check that $HESS is not already parsed if "athessian" in result: @@ -103,7 +103,7 @@ def _read_hessian(lit: LineIterator, result: dict[str]) -> NDArray: return hessian -def _read_masses(lit: LineIterator, result: dict[str]) -> NDArray: +def _read_masses(lit: LineIterator, result: dict[str]) -> NDArray[float]: """Extract ``masses`` from the punch file.""" natom = len(result["symbols"]) masses = np.zeros(natom, float) diff --git a/iodata/formats/gaussianlog.py b/iodata/formats/gaussianlog.py index 6a2815fb..7ed2ee80 100644 --- a/iodata/formats/gaussianlog.py +++ b/iodata/formats/gaussianlog.py @@ -74,7 +74,7 @@ def load_one(lit: LineIterator) -> dict: return result -def _load_twoindex_g09(lit: LineIterator, nbasis: int) -> NDArray: +def _load_twoindex_g09(lit: LineIterator, nbasis: int) -> NDArray[float]: """Load a two-index operator from a GAUSSIAN LOG file format. Parameters @@ -86,8 +86,7 @@ def _load_twoindex_g09(lit: LineIterator, nbasis: int) -> NDArray: Returns ------- - out - The output (nbasis, nbasis) array of operator. + Operator array with shape ``(nbasis, nbasis)``. """ result = np.zeros((nbasis, nbasis)) @@ -107,7 +106,7 @@ def _load_twoindex_g09(lit: LineIterator, nbasis: int) -> NDArray: return result -def _load_fourindex_g09(lit: LineIterator, nbasis: int) -> NDArray: +def _load_fourindex_g09(lit: LineIterator, nbasis: int) -> NDArray[float]: """Load a four-index operator from a GAUSSIAN LOG file. Parameters @@ -119,8 +118,7 @@ def _load_fourindex_g09(lit: LineIterator, nbasis: int) -> NDArray: Returns ------- - out - The (nbasis, nbasis, nbasis, nbasis) array of operator. + Operator array with shape ``(nbasis, nbasis, nbasis, nbasis)``. """ result = np.zeros((nbasis, nbasis, nbasis, nbasis)) diff --git a/iodata/formats/json.py b/iodata/formats/json.py index 49a4d9c6..cb84d6c1 100644 --- a/iodata/formats/json.py +++ b/iodata/formats/json.py @@ -609,8 +609,7 @@ def _parse_json(json_in: dict, lit: LineIterator) -> dict: Returns ------- - out - Dictionary with IOData attributes. + Dictionary with IOData attributes. """ # Remove all null entries and empty dicts in json @@ -981,7 +980,6 @@ def _load_qcschema_basis(_result: dict, _lit: LineIterator) -> dict: basis_dict ... - Raises ------ NotImplementedError diff --git a/iodata/formats/mol2.py b/iodata/formats/mol2.py index 7e481bff..6e2b7317 100644 --- a/iodata/formats/mol2.py +++ b/iodata/formats/mol2.py @@ -84,7 +84,9 @@ def load_one(lit: LineIterator) -> dict: return result -def _load_helper_atoms(lit: LineIterator, natoms: int) -> tuple[NDArray, NDArray, NDArray, tuple]: +def _load_helper_atoms( + lit: LineIterator, natoms: int +) -> tuple[NDArray[int], NDArray[float], NDArray[float], tuple]: """Load element numbers, coordinates and atomic charges.""" atnums = np.empty(natoms) atcoords = np.empty((natoms, 3)) @@ -111,7 +113,7 @@ def _load_helper_atoms(lit: LineIterator, natoms: int) -> tuple[NDArray, NDArray return atnums, atcoords, atchgs, attypes -def _load_helper_bonds(lit: LineIterator, nbonds: int) -> NDArray: +def _load_helper_bonds(lit: LineIterator, nbonds: int) -> NDArray[int]: """Load bond information. Each line in a bond definition has the following structure diff --git a/iodata/formats/molden.py b/iodata/formats/molden.py index 134ab80c..29534f37 100644 --- a/iodata/formats/molden.py +++ b/iodata/formats/molden.py @@ -226,7 +226,9 @@ def _load_low(lit: LineIterator) -> dict: return result -def _load_helper_atoms(lit: LineIterator, cunit: float) -> tuple[NDArray, NDArray, NDArray]: +def _load_helper_atoms( + lit: LineIterator, cunit: float +) -> tuple[NDArray[int], NDArray[float], NDArray[float]]: """Load element numbers and coordinates.""" atnums = [] atcorenums = [] @@ -356,9 +358,9 @@ def _load_helper_coeffs(lit: LineIterator) -> tuple: def _is_normalized_properly( obasis: MolecularBasis, - atcoords: NDArray, - orb_alpha: NDArray, - orb_beta: NDArray, + atcoords: NDArray[float], + orb_alpha: NDArray[float], + orb_beta: NDArray[float], norm_threshold: float = 1e-4, ) -> bool: """Test the normalization of the occupied and virtual orbitals. diff --git a/iodata/formats/molekel.py b/iodata/formats/molekel.py index ddee0b5f..7ad8db11 100644 --- a/iodata/formats/molekel.py +++ b/iodata/formats/molekel.py @@ -57,7 +57,7 @@ def _load_helper_charges(lit: LineIterator) -> dict: return {"mulliken": np.array(atcharges)} -def _load_helper_atoms(lit: LineIterator) -> tuple[NDArray, NDArray]: +def _load_helper_atoms(lit: LineIterator) -> tuple[NDArray[int], NDArray[float]]: atnums = [] atcoords = [] for line in lit: @@ -106,7 +106,9 @@ def _load_helper_obasis(lit: LineIterator) -> MolecularBasis: return MolecularBasis(shells, CONVENTIONS, "L2") -def _load_helper_coeffs(lit: LineIterator, nbasis: int) -> tuple[NDArray, NDArray]: +def _load_helper_coeffs( + lit: LineIterator, nbasis: int +) -> tuple[NDArray[float], NDArray[float], list]: coeffs = [] energies = [] irreps = [] @@ -144,7 +146,7 @@ def _load_helper_coeffs(lit: LineIterator, nbasis: int) -> tuple[NDArray, NDArra return np.hstack(coeffs), np.array(energies), irreps -def _load_helper_occ(lit: LineIterator) -> NDArray: +def _load_helper_occ(lit: LineIterator) -> NDArray[float]: occs = [] for line in lit: if line.strip() == "$END": diff --git a/iodata/formats/orcalog.py b/iodata/formats/orcalog.py index d6c38513..2d71f607 100644 --- a/iodata/formats/orcalog.py +++ b/iodata/formats/orcalog.py @@ -88,7 +88,7 @@ def _helper_number_atoms(lit: LineIterator) -> int: return natom -def _helper_geometry(lit: TextIO, natom: int) -> tuple[NDArray, NDArray]: +def _helper_geometry(lit: TextIO, natom: int) -> tuple[NDArray[int], NDArray[float]]: """Load coordinates form a ORCA output file format. Parameters @@ -98,10 +98,10 @@ def _helper_geometry(lit: TextIO, natom: int) -> tuple[NDArray, NDArray]: Returns ------- - atnums: int + atnums The atomic numbers. - atcoords: array_like - The atcoords in an array of size (natom, 3). + atcoords + The atcoords in an array with shape ``(natom, 3)``. """ atcoords = np.zeros((natom, 3)) @@ -120,7 +120,7 @@ def _helper_geometry(lit: TextIO, natom: int) -> tuple[NDArray, NDArray]: return atnums, atcoords -def _helper_scf_energies(lit: TextIO) -> tuple[NDArray, NDArray]: +def _helper_scf_energies(lit: TextIO) -> NDArray[float]: """Load energies from each SCF cycle from a ORCA output file format. Parameters @@ -130,7 +130,7 @@ def _helper_scf_energies(lit: TextIO) -> tuple[NDArray, NDArray]: Returns ------- - energies: array_like + energies The energies of each scf cycle in 1D-array. """ diff --git a/iodata/formats/qchemlog.py b/iodata/formats/qchemlog.py index 320f9d46..0f98289d 100644 --- a/iodata/formats/qchemlog.py +++ b/iodata/formats/qchemlog.py @@ -308,7 +308,9 @@ def _helper_orbital_energies_unrestricted(lit: LineIterator) -> tuple: return subdata -def _helper_section(start: str, end: str, lit: LineIterator, backward: bool = False) -> NDArray: +def _helper_section( + start: str, end: str, lit: LineIterator, backward: bool = False +) -> NDArray[float]: """Load data between starting and ending strings.""" data = [] for line in lit: @@ -325,7 +327,7 @@ def _helper_section(start: str, end: str, lit: LineIterator, backward: bool = Fa return np.array(data, dtype=float) -def _helper_mulliken(lit: LineIterator) -> NDArray: +def _helper_mulliken(lit: LineIterator) -> NDArray[float]: """Load mulliken net atomic charges.""" # skip line between 'Ground-State Mulliken Net Atomic Charges' line & atomic charge entries while True: @@ -359,7 +361,7 @@ def _helper_dipole_moments(lit: LineIterator) -> tuple: return dipole, quadrupole, dipole_tol -def _helper_polar(lit: LineIterator) -> NDArray: +def _helper_polar(lit: LineIterator) -> NDArray[float]: """Load polarizability matrix.""" next(lit) polarizability_tensor = [] @@ -370,7 +372,7 @@ def _helper_polar(lit: LineIterator) -> NDArray: return np.array(polarizability_tensor, dtype=float) -def _helper_hessian(lit: LineIterator, natom: int) -> NDArray: +def _helper_hessian(lit: LineIterator, natom: int) -> NDArray[float]: """Load hessian matrix.""" # hessian in Cartesian coordinates, shape(3 * natom, 3 * natom) col_idx = [int(i) for i in next(lit).split()] diff --git a/iodata/formats/wfn.py b/iodata/formats/wfn.py index 1948e150..b1719cb8 100644 --- a/iodata/formats/wfn.py +++ b/iodata/formats/wfn.py @@ -138,7 +138,7 @@ def _load_helper_num(lit: LineIterator) -> list[int]: return num_mo, nprim, num_atoms -def _load_helper_atoms(lit: LineIterator, num_atoms: int) -> tuple[NDArray, NDArray]: +def _load_helper_atoms(lit: LineIterator, num_atoms: int) -> tuple[NDArray[int], NDArray[float]]: """Read the coordinates of the atoms.""" atnums = np.empty(num_atoms, int) atcoords = np.empty((num_atoms, 3), float) @@ -175,7 +175,7 @@ def _load_helper_section( return np.array(section, dtype=dtype) -def _load_helper_mo(lit: LineIterator, nprim: int) -> tuple[int, float, float, NDArray]: +def _load_helper_mo(lit: LineIterator, nprim: int) -> tuple[int, float, float, NDArray[float]]: """Read one section of MO information.""" line = next(lit) if not line.startswith("MO"): @@ -202,7 +202,7 @@ def _load_helper_energy(lit: LineIterator) -> float: return energy, virial -def _load_helper_multiwfn(lit: LineIterator, num_mo: int) -> NDArray: +def _load_helper_multiwfn(lit: LineIterator, num_mo: int) -> NDArray[int]: """Read MO spin information from MULTIWFN extension.""" for line in lit: if "$MOSPIN $END" in line: @@ -259,8 +259,11 @@ def load_wfn_low(lit: LineIterator) -> tuple: def build_obasis( - icenters: NDArray, type_assignments: NDArray, exponents: NDArray, lit: LineIterator -) -> tuple[MolecularBasis, NDArray]: + icenters: NDArray[int], + type_assignments: NDArray[int], + exponents: NDArray[float], + lit: LineIterator, +) -> tuple[MolecularBasis, NDArray[int]]: """Construct a basis set using the arrays read from a WFN or WFX file. Parameters @@ -352,7 +355,7 @@ def build_obasis( return obasis, permutation -def get_mocoeff_scales(obasis: MolecularBasis) -> NDArray: +def get_mocoeff_scales(obasis: MolecularBasis) -> NDArray[float]: """Get the L2-normalization of the un-normalized Cartesian basis functions. Parameters @@ -362,9 +365,7 @@ def get_mocoeff_scales(obasis: MolecularBasis) -> NDArray: Returns ------- - scales - Scaling factors to be multiplied into the molecular orbital - coefficients. + Scaling factors to be multiplied into the molecular orbital coefficients. """ scales = [] diff --git a/iodata/iodata.py b/iodata/iodata.py index 10bd1eb8..a268e418 100644 --- a/iodata/iodata.py +++ b/iodata/iodata.py @@ -42,21 +42,21 @@ class IOData: values are arrays with atomic charges (size N). """ - atcoords: Optional[NDArray] = attrs.field( + atcoords: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape("natom", 3)), ) """A (N, 3) float array with Cartesian coordinates of the atoms.""" - _atcorenums: Optional[NDArray] = attrs.field( + _atcorenums: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape("natom")), ) """ - A (N,) float array with pseudo-potential core charges. The matrix - elements corresponding to ghost atoms are zero. + A (N,) float array with pseudo-potential core charges. + The matrix elements corresponding to ghost atoms are zero. """ atffparams: dict = attrs.field(factory=dict) @@ -68,14 +68,14 @@ class IOData: etc. Not all of them have to be present, depending on the use case. """ - atfrozen: Optional[NDArray] = attrs.field( + atfrozen: Optional[NDArray[bool]] = attrs.field( default=None, converter=convert_array_to(bool), validator=attrs.validators.optional(validate_shape("natom")), ) """A (N,) bool array with frozen atoms. (All atoms are free if thisattribute is not set.)""" - atgradient: Optional[NDArray] = attrs.field( + atgradient: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape("natom", 3)), @@ -85,21 +85,21 @@ class IOData: Cartesian atomic displacements. """ - athessian: Optional[NDArray] = attrs.field( + athessian: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape(None, None)), ) """A (3*N, 3*N) array containing the energy Hessian w.r.t Cartesian atomic displacements.""" - atmasses: Optional[NDArray] = attrs.field( + atmasses: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape("natom")), ) """A (N,) float array with atomic masses.""" - atnums: Optional[NDArray] = attrs.field( + atnums: Optional[NDArray[int]] = attrs.field( default=None, converter=convert_array_to(int), validator=attrs.validators.optional(validate_shape("natom")), @@ -115,7 +115,7 @@ class IOData: when implementing a load function for basis set definitions. """ - bonds: Optional[NDArray] = attrs.field( + bonds: Optional[NDArray[int]] = attrs.field( default=None, converter=convert_array_to(int), validator=attrs.validators.optional(validate_shape(None, 3)), @@ -127,7 +127,7 @@ class IOData: of bond types are defined in ``iodata.periodic``. """ - cellvecs: Optional[NDArray] = attrs.field( + cellvecs: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape(None, 3)), @@ -151,7 +151,7 @@ class IOData: energy: Optional[float] = attrs.field(default=None) """The total energy (electronic + nn).""" - extcharges: NDArray = attrs.field( + extcharges: NDArray[float] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape(None, 4)), @@ -282,14 +282,14 @@ def __attrs_post_init__(self): # Public interfaces to private attributes @property - def atcorenums(self) -> NDArray: - """Return effective core charges.""" + def atcorenums(self) -> NDArray[float]: + """Effective core charges.""" if self._atcorenums is None and self.atnums is not None: self.atcorenums = self.atnums.astype(float) return self._atcorenums @atcorenums.setter - def atcorenums(self, atcorenums): + def atcorenums(self, atcorenums: NDArray): if atcorenums is None: if self.nelec is not None and self._atcorenums is not None: # Set _charge because charge can no longer be derived from diff --git a/iodata/orbitals.py b/iodata/orbitals.py index 425aadda..beb5a4a8 100644 --- a/iodata/orbitals.py +++ b/iodata/orbitals.py @@ -110,7 +110,7 @@ class MolecularOrbitals: This is expected to be equal to `norba` for the `restricted` kind. """ - occs: Optional[NDArray] = attrs.field( + occs: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape("norb")), @@ -120,7 +120,7 @@ class MolecularOrbitals: The length equals the number of columns of coeffs. (optional) """ - coeffs: Optional[NDArray] = attrs.field( + coeffs: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape(None, "norb")), @@ -133,7 +133,7 @@ class MolecularOrbitals: total number of orbitals. (optional) """ - energies: Optional[NDArray] = attrs.field( + energies: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.optional(validate_shape("norb")), @@ -145,7 +145,7 @@ class MolecularOrbitals: ) """Irreducible representation. The length equals the number of columns of coeffs. (optional)""" - occs_aminusb: Optional[NDArray] = attrs.field( + occs_aminusb: Optional[NDArray[float]] = attrs.field( default=None, converter=convert_array_to(float), validator=attrs.validators.and_( diff --git a/iodata/overlap.py b/iodata/overlap.py index ea3b4d46..96f4a823 100644 --- a/iodata/overlap.py +++ b/iodata/overlap.py @@ -66,10 +66,10 @@ def factorial2(n: Union[int, NDArray[int]]) -> Union[int, NDArray[int]]: def compute_overlap( obasis0: MolecularBasis, - atcoords0: NDArray, + atcoords0: NDArray[float], obasis1: Optional[MolecularBasis] = None, - atcoords1: Optional[NDArray] = None, -) -> NDArray: + atcoords1: Optional[NDArray[float]] = None, +) -> NDArray[float]: r"""Compute overlap matrix for the given molecular basis set(s). .. math:: @@ -97,8 +97,7 @@ def compute_overlap( Returns ------- - overlap - The matrix with overlap integrals, ``shape=(obasis0.nbasis, obasis1.nbasis)``. + The matrix with overlap integrals, ``shape=(obasis0.nbasis, obasis1.nbasis)``. """ if obasis0.primitive_normalization != "L2": @@ -266,7 +265,7 @@ def compute_overlap_gaussian_1d(self, x1, x2, n1, n2, two_at): return value -def _compute_cart_shell_normalizations(shell: Shell) -> NDArray: +def _compute_cart_shell_normalizations(shell: Shell) -> NDArray[float]: """Return normalization constants for the primitives in a given shell. Parameters @@ -276,9 +275,7 @@ def _compute_cart_shell_normalizations(shell: Shell) -> NDArray: Returns ------- - NDArray - The normalization constants, always for Cartesian functions, even when - shell is pure. + The normalization constants, always for Cartesian functions, even when shell is pure. """ shell = attrs.evolve(shell, kinds=["c"] * shell.ncon) @@ -290,7 +287,7 @@ def _compute_cart_shell_normalizations(shell: Shell) -> NDArray: return np.array(result) -def gob_cart_normalization(alpha: NDArray, n: NDArray) -> NDArray: +def gob_cart_normalization(alpha: NDArray, n: NDArray) -> NDArray[float]: """Compute normalization of exponent. Parameters @@ -302,8 +299,7 @@ def gob_cart_normalization(alpha: NDArray, n: NDArray) -> NDArray: Returns ------- - NDArray - The normalization constant for the gaussian cartesian basis. + The normalization constants for the gaussian cartesian basis. """ return np.sqrt( diff --git a/iodata/test/common.py b/iodata/test/common.py index e528cc6b..13225096 100644 --- a/iodata/test/common.py +++ b/iodata/test/common.py @@ -26,9 +26,11 @@ import numpy as np import pytest from numpy.testing import assert_allclose, assert_equal +from numpy.typing import NDArray from ..api import load_one from ..basis import convert_conventions +from ..iodata import IOData from ..overlap import compute_overlap from ..utils import FileFormatWarning @@ -64,18 +66,18 @@ def compute_mulliken_charges(iodata): @contextmanager -def truncated_file(fn_orig, nline, nadd, tmpdir): +def truncated_file(fn_orig: str, nline: int, nadd: int, tmpdir: str): """Make a temporary truncated copy of a file. Parameters ---------- - fn_orig : str + fn_orig The file to be truncated. - nline : int + nline The number of lines to retain. - nadd : int + nadd The number of empty lines to add. - tmpdir : str + tmpdir A temporary directory where the truncated file is stored. """ @@ -146,16 +148,16 @@ def compare_mols(mol1, mol2, atol=1.0e-8, rtol=0.0): assert key not in d2 -def check_orthonormal(mo_coeffs, ao_overlap, atol=1e-5): +def check_orthonormal(mo_coeffs: NDArray[float], ao_overlap: NDArray[float], atol: float = 1e-5): """Check that molecular orbitals are orthogonal and normalized. Parameters ---------- - mo_coeffs : NDArray, shape=(nbasis, mo_count) + mo_coeffs Molecular orbital coefficients. - ao_overlap : NDArray, shape=(nbasis, nbasis) + ao_overlap Atomic orbital overlap matrix. - atol : float + atol Absolute tolerance in deviation from identity matrix. """ @@ -168,7 +170,7 @@ def check_orthonormal(mo_coeffs, ao_overlap, atol=1e-5): def load_one_warning( filename: str, fmt: Optional[str] = None, match: Optional[str] = None, **kwargs -): +) -> IOData: """Call load_one, catching expected FileFormatWarning. Parameters @@ -186,8 +188,7 @@ def load_one_warning( Returns ------- - out - The instance of IOData with data loaded from the input files. + The instance of IOData with data loaded from the input files. """ with as_file(files("iodata.test.data").joinpath(filename)) as fn: diff --git a/iodata/test/test_attrutils.py b/iodata/test/test_attrutils.py index d4e99935..4051370f 100644 --- a/iodata/test/test_attrutils.py +++ b/iodata/test/test_attrutils.py @@ -31,7 +31,7 @@ class FooBar: """Just a silly class for testing convert_array_to.""" - spam: NDArray = attrs.field(converter=convert_array_to(float)) + spam: NDArray[float] = attrs.field(converter=convert_array_to(float)) def test_convert_array_to_init(): diff --git a/iodata/utils.py b/iodata/utils.py index ac144d12..6abb0b68 100644 --- a/iodata/utils.py +++ b/iodata/utils.py @@ -138,16 +138,16 @@ def back(self, line): class Cube: """The volumetric data from a cube (or similar) file.""" - origin: NDArray = attrs.field(validator=validate_shape(3)) + origin: NDArray[float] = attrs.field(validator=validate_shape(3)) """A 3D vector with the origin of the axes frame.""" - axes: NDArray = attrs.field(validator=validate_shape(3, 3)) + axes: NDArray[float] = attrs.field(validator=validate_shape(3, 3)) """ A (3, 3) array where each row represents the spacing between two neighboring grid points along the first, second and third axis, respectively. """ - data: NDArray = attrs.field(validator=validate_shape(None, None, None)) + data: NDArray[float] = attrs.field(validator=validate_shape(None, None, None)) """A (K, L, M) array of data on a uniform grid""" @property @@ -157,7 +157,7 @@ def shape(self): def set_four_index_element( - four_index_object: NDArray, i0: int, i1: int, i2: int, i3: int, value: float + four_index_object: NDArray[float], i0: int, i1: int, i2: int, i3: int, value: float ): """Assign values to a four index object, account for 8-fold index symmetry. @@ -184,20 +184,20 @@ def set_four_index_element( four_index_object[i3, i0, i1, i2] = value -def volume(cellvecs: NDArray) -> float: +def volume(cellvecs: NDArray[float]) -> float: """Calculate the (generalized) cell volume. Parameters ---------- cellvecs - A numpy matrix of shape (x,3) where x is in {1,2,3}. Each row is one - cellvector. + A numpy matrix of shape (x,3) where x is in {1,2,3}. + Each row is one cellvector. Returns ------- - volume - In case of 3D, the cell volume. In case of 2D, the cell area. In case of - 1D, the cell length. + In case of 3D, the cell volume. + In case of 2D, the cell area. + In case of 1D, the cell length. """ nvecs = cellvecs.shape[0] @@ -210,7 +210,9 @@ def volume(cellvecs: NDArray) -> float: raise ValueError("Argument cellvecs should be of shape (x, 3), where x is in {1, 2, 3}") -def derive_naturals(dm: NDArray, overlap: NDArray) -> tuple[NDArray, NDArray]: +def derive_naturals( + dm: NDArray[float], overlap: NDArray[float] +) -> tuple[NDArray[float], NDArray[float]]: """Derive natural orbitals from a given density matrix. Parameters @@ -242,7 +244,7 @@ def derive_naturals(dm: NDArray, overlap: NDArray) -> tuple[NDArray, NDArray]: return coeffs, occs -def check_dm(dm: NDArray, overlap: NDArray, eps: float = 1e-4, occ_max: float = 1.0): +def check_dm(dm: NDArray[float], overlap: NDArray[float], eps: float = 1e-4, occ_max: float = 1.0): """Check if the density matrix has eigenvalues in the proper range. Parameters diff --git a/pyproject.toml b/pyproject.toml index c726792d..2b9d9660 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ dynamic = ["version"] [project.optional-dependencies] dev = [ "furo", + "intersphinx-registry", "packaging", "pre-commit", "pytest", From e5c31794f833ead3c90adb325c9d7ae1d121253f Mon Sep 17 00:00:00 2001 From: Toon Verstraelen Date: Thu, 13 Jun 2024 20:44:22 +0200 Subject: [PATCH 2/2] Update iodata/formats/fchk.py Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- iodata/formats/fchk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iodata/formats/fchk.py b/iodata/formats/fchk.py index 6b76273c..76e38d63 100644 --- a/iodata/formats/fchk.py +++ b/iodata/formats/fchk.py @@ -369,7 +369,7 @@ def _load_fchk_low(lit: LineIterator, label_patterns: Optional[list[str]] = None Returns ------- - A dictionary with data read from the FCHK file. + A dictionary containing data read from the FCHK file. Keys are the field names and values are either scalar or array data. Arrays are always one-dimensional.