From b0ae99c425d4d59a674879b998b7c1ccbb475996 Mon Sep 17 00:00:00 2001 From: Nick Papior Date: Thu, 7 Nov 2024 14:13:57 +0100 Subject: [PATCH] enabled ellipsis here and there Should be improved so None fully gets removed. Signed-off-by: Nick Papior --- CHANGELOG.md | 6 ++++++ src/sisl/io/_multiple.py | 4 ++++ src/sisl/io/siesta/stdout.py | 25 +++++++++++++++---------- src/sisl/io/siesta/tests/test_stdout.py | 2 ++ 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0850e2a94..b2272f0cf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ we hit release version 1.0.0. ## [0.15.3] - YYYY-MM-DD +### Added +- enabled `...` when extracting slices of MD steps. + Here it is the same as `:`. But it also allows + inline arguments: `read_scf(imd=...)` where `imd=:` is not + allowed, partly fixes #835 + ## [0.15.2] - 2024-11-06 diff --git a/src/sisl/io/_multiple.py b/src/sisl/io/_multiple.py index abaaf21d56..565b642565 100644 --- a/src/sisl/io/_multiple.py +++ b/src/sisl/io/_multiple.py @@ -109,6 +109,10 @@ def __call__(self, *args, **kwargs): start = 0 stop = inf + if key is Ellipsis: + # Allow [...] to extract all" + key = slice(None) + if isinstance(key, Integral): if key >= 0: start = key diff --git a/src/sisl/io/siesta/stdout.py b/src/sisl/io/siesta/stdout.py index 4841abf3e9..c0b2d535eb 100644 --- a/src/sisl/io/siesta/stdout.py +++ b/src/sisl/io/siesta/stdout.py @@ -828,7 +828,7 @@ def read_data(self, *args, **kwargs) -> Any: def read_scf( self, key: str = "scf", - iscf: Optional[int] = -1, + iscf: Optional[Union[int, Ellipsis]] = -1, as_dataframe: bool = False, ret_header: bool = False, ): @@ -840,7 +840,7 @@ def read_scf( parse SCF information from Siesta SCF or TranSiesta SCF iscf : which SCF cycle should be stored. If ``-1`` only the final SCF step is stored, - for None *all* SCF cycles are returned. When `iscf` values queried are not found they + for `...`/`None` *all* SCF cycles are returned. When `iscf` values queried are not found they will be truncated to the nearest SCF step. as_dataframe: whether the information should be returned as a `pandas.DataFrame`. The advantage of this @@ -854,7 +854,9 @@ def read_scf( # These are the properties that are written in SIESTA scf props = ["iscf", "Eharris", "E_KS", "FreeEng", "dDmax", "Ef", "dHmax"] - if not iscf is None: + if iscf is Ellipsis: + iscf = None + elif iscf is not None: if iscf == 0: raise ValueError( f"{self.__class__.__name__}.read_scf requires iscf argument to *not* be 0!" @@ -1084,8 +1086,8 @@ def construct_data(d, data): def read_charge( self, name: Literal["voronoi", "hirshfeld", "mulliken", "mulliken:<5.2"], - iscf=Opt.ANY, - imd=Opt.ANY, + iscf: Union[Opt, int, Ellipsis] = Opt.ANY, + imd: Union[Opt, int, Ellipsis] = Opt.ANY, key_scf: str = "scf", as_dataframe: bool = False, ): @@ -1127,15 +1129,15 @@ def read_charge( ---------- name: the name of the charges that you want to read - iscf: int or Opt, optional + iscf: int or Opt or `...`, optional index (0-based) of the scf iteration you want the charges for. - If the enum specifier `Opt.ANY` or `Opt.ALL` are used, then + If the enum specifier `Opt.ANY` or `Opt.ALL`/`...` are used, then the returned quantities depend on what is present. If ``None/Opt.NONE`` it will not return any SCF charges. If both `imd` and `iscf` are ``None`` then only the final charges will be returned. imd: int or Opt, optional index (0-based) of the md step you want the charges for. - If the enum specifier `Opt.ANY` or `Opt.ALL` are used, then + If the enum specifier `Opt.ANY` or `Opt.ALL`/`...` are used, then the returned quantities depend on what is present. If ``None/Opt.NONE`` it will not return any MD charges. If both `imd` and `iscf` are ``None`` then only the final charges will be returned. @@ -1568,9 +1570,9 @@ def try_parse_int(s): md_scf_charge = pd.concat( [ pd.concat( - iscf, keys=pd.RangeIndex(1, len(iscf) + 1, name="iscf") + iscf_, keys=pd.RangeIndex(1, len(iscf_) + 1, name="iscf") ) - for iscf in md_scf_charge + for iscf_ in md_scf_charge ], keys=pd.RangeIndex(1, len(md_scf_charge) + 1, name="imd"), ) @@ -1605,6 +1607,9 @@ def _p(flag, found): flag : corrected flag """ + if flag is Ellipsis: + flag = Opt.ALL + if isinstance(flag, Opt): # correct flag depending on what `found` is # If the values have been found we diff --git a/src/sisl/io/siesta/tests/test_stdout.py b/src/sisl/io/siesta/tests/test_stdout.py index a6e3e8d475..3d4d096d50 100644 --- a/src/sisl/io/siesta/tests/test_stdout.py +++ b/src/sisl/io/siesta/tests/test_stdout.py @@ -40,6 +40,8 @@ def test_mgco3_md_out(sisl_files): assert len(out.read_geometry[:]()) == nOutputs assert len(out.read_force[:]()) == nOutputs assert len(out.read_stress[:]()) == nOutputs + # slicing using ellipsis (same as above) + assert len(out.read_stress[...]()) == nOutputs f0 = out.read_force() f = out.read_force[-1]()