From 0e406657e188dbe97bd8e9d99051fcf887f05e02 Mon Sep 17 00:00:00 2001 From: Nick Papior Date: Mon, 15 Jan 2024 08:19:04 +0100 Subject: [PATCH] added information to fdf file, more to come we should add more of these here and there. fdf content will still only be shown when 'track' is True Signed-off-by: Nick Papior --- pyproject.toml | 1 + src/sisl/io/_exceptions.py | 8 ++-- src/sisl/io/siesta/fdf.py | 93 ++++++++++++++++++------------------- src/sisl/io/siesta/sile.py | 10 ++-- src/sisl/io/tbtrans/sile.py | 1 - src/sisl/io/tbtrans/tbt.py | 2 +- 6 files changed, 58 insertions(+), 57 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5e9d50c223..5e2d38b726 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -280,6 +280,7 @@ known_first_party = ["sisl_toolbox", "sisl"] line_length = 88 overwrite_in_place = true extend_skip = ["src/sisl/__init__.py"] +multi_line_output = "VERTICAL_HANGING_INDENT" [tool.black] line-length = 88 diff --git a/src/sisl/io/_exceptions.py b/src/sisl/io/_exceptions.py index 14604be5a6..09ab2cd6a8 100644 --- a/src/sisl/io/_exceptions.py +++ b/src/sisl/io/_exceptions.py @@ -12,6 +12,7 @@ "SileError", "SileWarning", "SileInfo", + "MissingInputSileException", "MissingInputSileError", "MissingInputSileInfo", "MissingInputSileWarning", @@ -61,10 +62,7 @@ class MissingInputSileException(SislException): """ def __init__( - self, - executable: str, - inputs: InputsType, - method: Callable, + self, executable: str, inputs: InputsType, method: Callable, msg: str = "" ): # Formulate the error message try: @@ -80,7 +78,7 @@ def parse(v): str_except = "\n".join(map(parse, inputs)) super().__init__( - f"Data from method '{name}' failed due to missing output values.\n\n" + f"{msg}\nData from method '{name}' failed due to missing output values.\n\n" f"This is because of missing options in the input file for executable {executable}.\n" f"Please read up on the following flags in the manual of '{executable}' to figure out " f"how to retrieve the expected quantities:\n{str_except}" diff --git a/src/sisl/io/siesta/fdf.py b/src/sisl/io/siesta/fdf.py index 45a51fbd4c..f799ef7293 100644 --- a/src/sisl/io/siesta/fdf.py +++ b/src/sisl/io/siesta/fdf.py @@ -3,6 +3,7 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import gzip import itertools as itools +import logging import warnings from datetime import datetime from os.path import isfile @@ -49,7 +50,7 @@ from .orb_indx import orbindxSileSiesta from .siesta_grid import gridncSileSiesta from .siesta_nc import ncSileSiesta -from .sile import SileSiesta +from .sile import MissingFDFSiestaInfo, SileSiesta from .struct import structSileSiesta from .xv import xvSileSiesta @@ -61,6 +62,7 @@ _LOGICAL = _LOGICAL_FALSE + _LOGICAL_TRUE Bohr2Ang = unit_convert("Bohr", "Ang") +_log = logging.getLogger(__name__) def _parse_output_order(order, output, order_True, order_False): @@ -114,18 +116,21 @@ def _listify_str(arg): def _track(method, msg): + msg_str = str(msg) + _log.info(msg_str.split("\n", maxsplit=1)[0]) if method.__self__.track: - info(f"{method.__self__.__class__.__name__}.{method.__name__}: {msg}") + info(msg) -def _track_file(method, f, msg=None): +def _track_file(method, f, msg=None, inputs=None, executable="siesta"): if msg is None: if f.is_file(): - msg = f"reading file {f}" + msg = f"{method.__self__.__class__.__name__}.{method.__name__}: file '{f}' exists." else: - msg = f"could not find file {f}" - if method.__self__.track: - info(f"{method.__self__.__class__.__name__}.{method.__name__}: {msg}") + msg = f"{method.__self__.__class__.__name__}.{method.__name__}: file '{f}' does not exist." + elif isinstance(msg, str): + msg = MissingFDFSiestaInfo(executable, inputs, method, msg) + _track(method, msg) @set_module("sisl.io.siesta") @@ -726,7 +731,6 @@ def read_lattice_nsc(self, *args, **kwargs): for f in order: v = getattr(self, f"_r_lattice_nsc_{f.lower()}")(*args, **kwargs) if v is not None: - _track(self.read_lattice_nsc, f"found file {f}") return v warn( "number of supercells could not be read from output files. Assuming molecule cell " @@ -736,14 +740,16 @@ def read_lattice_nsc(self, *args, **kwargs): def _r_lattice_nsc_nc(self, *args, **kwargs): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_lattice_nsc_nc, f) + _track_file(self._r_lattice_nsc_nc, f, [("CDF.Save", "True")]) if f.is_file(): return ncSileSiesta(f).read_lattice_nsc() return None def _r_lattice_nsc_orb_indx(self, *args, **kwargs): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".ORB_INDX") - _track_file(self._r_lattice_nsc_orb_indx, f) + _track_file( + self._r_lattice_nsc_orb_indx, f, inputs=[("Write.OrbitalIndex", "True")] + ) if f.is_file(): return orbindxSileSiesta(f).read_lattice_nsc() return None @@ -778,7 +784,6 @@ def read_lattice(self, output=False, *args, **kwargs): for f in order: v = getattr(self, f"_r_lattice_{f.lower()}")(*args, **kwargs) if v is not None: - _track(self.read_lattice, f"found file {f}") return v return None @@ -817,7 +822,7 @@ def _r_lattice_fdf(self, *args, **kwargs): def _r_lattice_nc(self): # Read supercell from <>.nc file f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_lattice_nc, f) + _track_file(self._r_lattice_nc, f, inputs=[("CDF.Save", "True")]) if f.is_file(): return ncSileSiesta(f).read_lattice() return None @@ -847,14 +852,14 @@ def _r_lattice_struct(self, *args, **kwargs): def _r_lattice_tshs(self, *args, **kwargs): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".TSHS") - _track_file(self._r_lattice_tshs, f) + _track_file(self._r_lattice_tshs, f, inputs=[("TS.HS.Save", "True")]) if f.is_file(): return tshsSileSiesta(f).read_lattice() return None def _r_lattice_onlys(self, *args, **kwargs): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".onlyS") - _track_file(self._r_lattice_onlys, f) + _track_file(self._r_lattice_onlys, f, inputs=[("TS.S.Save", "True")]) if f.is_file(): return onlysSileSiesta(f).read_lattice() return None @@ -915,7 +920,7 @@ def _r_force_tsfac(self, *args, **kwargs): def _r_force_nc(self, *args, **kwargs): """Read forces from the nc file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_force_nc, f) + _track_file(self._r_force_nc, f, inputs=[("CDF.Save", "True")]) if f.is_file(): return ncSileSiesta(f).read_force() return None @@ -939,7 +944,7 @@ def read_force_constant(self, *args, **kwargs): def _r_force_constant_nc(self, *args, **kwargs): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_force_constant_nc, f) + _track_file(self._r_force_constant_nc, f, inputs=[("CDF.Save", "True")]) if f.is_file(): if not "FC" in ncSileSiesta(f).groups: return None @@ -970,7 +975,7 @@ def read_fermi_level(self, *args, **kwargs): fermi-level """ order = _parse_output_order( - kwargs.pop("order", None), True, ["nc", "TSDE", "TSHS", "EIG", "bands"], [] + kwargs.pop("order", None), True, ("nc", "TSDE", "TSHS", "EIG", "bands"), [] ) for f in order: v = getattr(self, f"_r_fermi_level_{f.lower()}")(*args, **kwargs) @@ -982,21 +987,21 @@ def read_fermi_level(self, *args, **kwargs): def _r_fermi_level_nc(self): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_fermi_level_nc, f) + _track_file(self._r_fermi_level_nc, f, inputs=[("CDF.Save", "True")]) if isfile(f): return ncSileSiesta(f).read_fermi_level() return None def _r_fermi_level_tsde(self): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".TSDE") - _track_file(self._r_fermi_level_tsde, f) + _track_file(self._r_fermi_level_tsde, f, inputs=[("TS.DE.Save", "True")]) if isfile(f): return tsdeSileSiesta(f).read_fermi_level() return None def _r_fermi_level_tshs(self): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".TSHS") - _track_file(self._r_fermi_level_tshs, f) + _track_file(self._r_fermi_level_tshs, f, inputs=[("TS.HS.Save", "True")]) if isfile(f): return tshsSileSiesta(f).read_fermi_level() return None @@ -1434,8 +1439,6 @@ def read_geometry(self, output=False, *args, **kwargs): for f in order: v = getattr(self, f"_r_geometry_{f.lower()}")(*args, **kwargs) if v is not None: - if self.track: - info(f"{self.file}(read_geometry) found in file={f}") return v return None @@ -1462,7 +1465,7 @@ def _r_geometry_xv(self, *args, **kwargs): def _r_geometry_struct(self, *args, **kwargs): """Returns `Geometry` object from the STRUCT_* files""" geom = None - for end in ["STRUCT_NEXT_ITER", "STRUCT_OUT", "STRUCT_IN"]: + for end in ("STRUCT_NEXT_ITER", "STRUCT_OUT", "STRUCT_IN"): f = self.dir_file(self.get("SystemLabel", default="siesta") + f".{end}") _track_file(self._r_geometry_struct, f) if f.is_file(): @@ -1484,7 +1487,7 @@ def _r_geometry_struct(self, *args, **kwargs): def _r_geometry_nc(self): # Read geometry from <>.nc file f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_geometry_nc, f) + _track_file(self._r_geometry_nc, f, inputs=[("CDF.Save", "True")]) if f.is_file(): return ncSileSiesta(f).read_geometry() return None @@ -1492,7 +1495,7 @@ def _r_geometry_nc(self): def _r_geometry_tshs(self): # Read geometry from <>.TSHS file f = self.dir_file(self.get("SystemLabel", default="siesta") + ".TSHS") - _track_file(self._r_geometry_tshs, f) + _track_file(self._r_geometry_tshs, f, inputs=[("TS.HS.Save", "True")]) if f.is_file(): # Default to a geometry with the correct atomic numbers etc. return tshsSileSiesta(f).read_geometry(geometry=self.read_geometry(False)) @@ -1501,7 +1504,7 @@ def _r_geometry_tshs(self): def _r_geometry_hsx(self): # Read geometry from <>.TSHS file f = self.dir_file(self.get("SystemLabel", default="siesta") + ".HSX") - _track_file(self._r_geometry_hsx, f) + _track_file(self._r_geometry_hsx, f, inputs=[("Save.HS", "True")]) if f.is_file(): # Default to a geometry with the correct atomic numbers etc. return hsxSileSiesta(f).read_geometry(geometry=self.read_geometry(False)) @@ -1670,15 +1673,13 @@ def read_grid(self, name, *args, **kwargs): name, *args, **kwargs ) if v is not None: - if self.track: - info(f"{self.file}(read_grid) found in file={f}") return v return None def _r_grid_nc(self, name, *args, **kwargs): # Read grid from the <>.nc file f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_grid_nc, f) + _track_file(self._r_grid_nc, f, inputs=[("CDF.Save", "True")]) if f.is_file(): # Capitalize correctly name = { @@ -1844,10 +1845,10 @@ def _r_basis_ion(self): def _r_basis_orb_indx(self): f = self.dir_file(self.get("SystemLabel", default="siesta") + ".ORB_INDX") - _track_file(self._r_basis_orb_indx, f) + _track_file(self._r_basis_orb_indx, f, inputs=[("Write.OrbitalIndex", "True")]) if f.is_file(): - info( - f"Siesta basis information is read from {f}, the radial functions are not accessible." + warn( + f"Siesta basis information is read from '{f}'; radial functions are not accessible." ) return orbindxSileSiesta(f).read_basis(atoms=self._r_basis_fdf()) return None @@ -2071,14 +2072,13 @@ def read_density_matrix(self, *args, **kwargs): for f in order: DM = getattr(self, f"_r_density_matrix_{f.lower()}")(*args, **kwargs) if DM is not None: - _track(self.read_density_matrix, f"found file {f}") return DM return None def _r_density_matrix_nc(self, *args, **kwargs): """Try and read the density matrix by reading the <>.nc""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_density_matrix_nc, f) + _track_file(self._r_density_matrix_nc, f, inputs=[("CDF.Save", "True")]) DM = None if f.is_file(): # this *should* also contain the overlap matrix @@ -2088,7 +2088,7 @@ def _r_density_matrix_nc(self, *args, **kwargs): def _r_density_matrix_tsde(self, *args, **kwargs): """Read density matrix from the TSDE file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".TSDE") - _track_file(self._r_density_matrix_tsde, f) + _track_file(self._r_density_matrix_tsde, f, inputs=[("TS.DE.Save", "True")]) DM = None if f.is_file(): if "geometry" not in kwargs: @@ -2129,14 +2129,13 @@ def read_energy_density_matrix(self, *args, **kwargs): *args, **kwargs ) if EDM is not None: - _track(self.read_energy_density_matrix, f"found file {f}") return EDM return None def _r_energy_density_matrix_nc(self, *args, **kwargs): """Read energy density matrix by reading the <>.nc""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_energy_density_matrix_nc, f) + _track_file(self._r_energy_density_matrix_nc, f, inputs=[("CDF.Save", "True")]) if f.is_file(): return ncSileSiesta(f).read_energy_density_matrix(*args, **kwargs) return None @@ -2144,7 +2143,9 @@ def _r_energy_density_matrix_nc(self, *args, **kwargs): def _r_energy_density_matrix_tsde(self, *args, **kwargs): """Read energy density matrix from the TSDE file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".TSDE") - _track_file(self._r_energy_density_matrix_tsde, f) + _track_file( + self._r_energy_density_matrix_tsde, f, inputs=[("TS.DE.Save", "True")] + ) EDM = None if f.is_file(): if "geometry" not in kwargs: @@ -2172,14 +2173,13 @@ def read_overlap(self, *args, **kwargs): for f in order: v = getattr(self, f"_r_overlap_{f.lower()}")(*args, **kwargs) if v is not None: - _track(self.read_overlap, f"found file {f}") return v return None def _r_overlap_nc(self, *args, **kwargs): """Read overlap from the nc file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_overlap_nc, f) + _track_file(self._r_overlap_nc, f, inputs=[("CDF.Save", "True")]) if f.is_file(): return ncSileSiesta(f).read_overlap(*args, **kwargs) return None @@ -2187,7 +2187,7 @@ def _r_overlap_nc(self, *args, **kwargs): def _r_overlap_tshs(self, *args, **kwargs): """Read overlap from the TSHS file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".TSHS") - _track_file(self._r_overlap_tshs, f) + _track_file(self._r_overlap_tshs, f, inputs=[("TS.HS.Save", "True")]) S = None if f.is_file(): if "geometry" not in kwargs: @@ -2199,7 +2199,7 @@ def _r_overlap_tshs(self, *args, **kwargs): def _r_overlap_hsx(self, *args, **kwargs): """Read overlap from the HSX file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".HSX") - _track_file(self._r_overlap_hsx, f) + _track_file(self._r_overlap_hsx, f, inputs=[("Save.HS", "True")]) S = None if f.is_file(): if "geometry" not in kwargs: @@ -2211,7 +2211,7 @@ def _r_overlap_hsx(self, *args, **kwargs): def _r_overlap_onlys(self, *args, **kwargs): """Read overlap from the onlyS file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".onlyS") - _track_file(self._r_overlap_onlys, f) + _track_file(self._r_overlap_onlys, f, inputs=[("TS.S.Save", "True")]) S = None if f.is_file(): if "geometry" not in kwargs: @@ -2238,14 +2238,13 @@ def read_hamiltonian(self, *args, **kwargs): for f in order: H = getattr(self, f"_r_hamiltonian_{f.lower()}")(*args, **kwargs) if H is not None: - _track(self.read_hamiltonian, f"found file {f}") return H return None def _r_hamiltonian_nc(self, *args, **kwargs): """Read Hamiltonian from the nc file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".nc") - _track_file(self._r_hamiltonian_nc, f) + _track_file(self._r_hamiltonian_nc, f, inputs=[("CDF.Save", "True")]) if f.is_file(): return ncSileSiesta(f).read_hamiltonian(*args, **kwargs) return None @@ -2253,7 +2252,7 @@ def _r_hamiltonian_nc(self, *args, **kwargs): def _r_hamiltonian_tshs(self, *args, **kwargs): """Read Hamiltonian from the TSHS file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".TSHS") - _track_file(self._r_hamiltonian_tshs, f) + _track_file(self._r_hamiltonian_tshs, f, inputs=[("TS.HS.Save", "True")]) H = None if f.is_file(): if "geometry" not in kwargs: @@ -2265,7 +2264,7 @@ def _r_hamiltonian_tshs(self, *args, **kwargs): def _r_hamiltonian_hsx(self, *args, **kwargs): """Read Hamiltonian from the HSX file""" f = self.dir_file(self.get("SystemLabel", default="siesta") + ".HSX") - _track_file(self._r_hamiltonian_hsx, f) + _track_file(self._r_hamiltonian_hsx, f, inputs=[("Save.HS", "True")]) H = None if f.is_file(): if hsxSileSiesta(f).version == 0: diff --git a/src/sisl/io/siesta/sile.py b/src/sisl/io/siesta/sile.py index bc68ae4690..761aec2bde 100644 --- a/src/sisl/io/siesta/sile.py +++ b/src/sisl/io/siesta/sile.py @@ -1,9 +1,6 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. -from functools import wraps -from typing import Callable, List, Union - try: from . import _siesta @@ -15,6 +12,7 @@ from ..sile import ( MissingInputSileError, + MissingInputSileInfo, Sile, SileBin, SileCDF, @@ -27,6 +25,7 @@ "SileCDFSiesta", "SileBinSiesta", "MissingFDFSiestaError", + "MissingFDFSiestaInfo", "missing_input_fdf", ] @@ -36,6 +35,11 @@ class MissingFDFSiestaError(MissingInputSileError): pass +@set_module("sisl.io.siesta") +class MissingFDFSiestaInfo(MissingInputSileInfo): + pass + + @set_module("sisl.io.siesta") def missing_input_fdf( inputs, executable: str = "siesta", when_exception: Exception = KeyError diff --git a/src/sisl/io/tbtrans/sile.py b/src/sisl/io/tbtrans/sile.py index 876ccaa0d1..1d62c702a2 100644 --- a/src/sisl/io/tbtrans/sile.py +++ b/src/sisl/io/tbtrans/sile.py @@ -1,7 +1,6 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. -from functools import wraps from sisl._internal import set_module from sisl.io.siesta import MissingFDFSiestaError diff --git a/src/sisl/io/tbtrans/tbt.py b/src/sisl/io/tbtrans/tbt.py index 1b41fb7ff5..ba4336d19a 100644 --- a/src/sisl/io/tbtrans/tbt.py +++ b/src/sisl/io/tbtrans/tbt.py @@ -9,7 +9,7 @@ from io import StringIO import itertools -from functools import reduce, wraps +from functools import reduce from typing import List, Optional, Union import numpy as np