Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@
.. _cmake: https://cmake.org
.. _scikit-build-core: https://scikit-build-core.readthedocs.io/en/latest/
.. _netcdf4-py: https://github.com/Unidata/netcdf4-python
.. _pyyaml: https://pyyaml.org/wiki/PyYAMLDocumentation
.. _numpy: https://www.numpy.org/
.. _scipy: https://docs.scipy.org/doc/scipy
.. _pyparsing: https://github.com/pyparsing/pyparsing
Expand Down
1 change: 1 addition & 0 deletions docs/quickstart/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ to run sisl, so generally one shouldn't worry about getting correct
packages etc. Here the more detailed requirements are listed.

- `Python`_ 3.9 or above
- `pyyaml`_
- `numpy`_
- `scipy`_
- `xarray`_
Expand Down
4 changes: 2 additions & 2 deletions docs/toolbox/basis/basis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Then, one can directly run the optimization:

.. code-block:: bash

stoolbox basis optim --geometry input.fdf
stoolbox basis optimize --geometry input.fdf

with ``input.fdf`` being the input file for the calculation. This will use all the default
values. Since there are many possible tweaks, we invite you to read carefully the help
Expand Down Expand Up @@ -56,7 +56,7 @@ Then, you can pass it directly to the optimization using the ``--config`` option

.. code-block:: bash

stoolbox basis optim --geometry input.fdf --config my_config.yaml
stoolbox basis optimize --geometry input.fdf --config my_config.yaml

**Installing the optimizers:** The default optimizer is BADS (https://github.com/acerbilab/bads)
which is the one that we have found works best to optimize basis sets. The optimizer is however
Expand Down
4 changes: 2 additions & 2 deletions src/sisl/_core/periodictable.py
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@
return ""

if row.ndim == 0:
return conv(row[()], col[()])
return np.asarray(conv(row, col), dtype=str)

Check warning on line 903 in src/sisl/_core/periodictable.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_core/periodictable.py#L903

Added line #L903 was not covered by tests
return np.asarray(list(map(conv, row, col)), dtype=str)

@classmethod
Expand Down Expand Up @@ -939,7 +939,7 @@
return -1

if Z.ndim == 0:
return conv(Z[()])
return np.asarray(conv(Z[()]), dtype=int)

Check warning on line 942 in src/sisl/_core/periodictable.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_core/periodictable.py#L942

Added line #L942 was not covered by tests
return np.asarray(list(map(conv, Z)), dtype=int)

@classmethod
Expand Down
12 changes: 11 additions & 1 deletion src/sisl/_lib/_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,24 @@
try:
from rich_argparse import RawTextRichHelpFormatter

SislHelpFormatter = RawTextRichHelpFormatter

Check warning on line 15 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L15

Added line #L15 was not covered by tests
except ImportError:
SislHelpFormatter = argparse.RawDescriptionHelpFormatter


def is_optional(field):
"""Check whether the annotation for a parameter is an Optional type."""
return typing.get_origin(field) is Union and type(None) in typing.get_args(field)
return is_union(field) and type(None) in typing.get_args(field)

Check warning on line 22 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L22

Added line #L22 was not covered by tests


def is_union(field):
"""Check whether the annotation for a parameter is an Union type."""
return typing.get_origin(field) is Union

Check warning on line 27 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L27

Added line #L27 was not covered by tests


def is_literal(field):
"""Check whether the annotation for a parameter is a Literal type."""
return typing.get_origin(field) is Literal

Check warning on line 32 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L32

Added line #L32 was not covered by tests


def get_optional_arg(field):
Expand All @@ -35,17 +40,17 @@
E.g.: Optional[int] -> int
E.g.: Optional[Union[int, str]] -> raises ValueError
"""
if not is_optional(field):
return field

Check warning on line 44 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L43-L44

Added lines #L43 - L44 were not covered by tests

args = typing.get_args(field)
if len(args) > 2:
raise ValueError("Optional type must have at most 2 arguments")
for arg in args:
if arg is not type(None):
return arg

Check warning on line 51 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L46-L51

Added lines #L46 - L51 were not covered by tests

raise ValueError("No non-None type found in Union")

Check warning on line 53 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L53

Added line #L53 was not covered by tests


def get_literal_args(field):
Expand All @@ -53,7 +58,7 @@

E.g.: Literal[1, 2, 3] -> (1, 2, 3)
"""
return typing.get_args(field)

Check warning on line 61 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L61

Added line #L61 was not covered by tests


class NotPassedArg:
Expand All @@ -64,51 +69,51 @@
"""

def __init__(self, val):
self.val = val

Check warning on line 72 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L72

Added line #L72 was not covered by tests

def __repr__(self):
return repr(self.val)

Check warning on line 75 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L75

Added line #L75 was not covered by tests

def __str__(self):
return str(self.val)

Check warning on line 78 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L78

Added line #L78 was not covered by tests

def __eq__(self, other):
return self.val == other

Check warning on line 81 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L81

Added line #L81 was not covered by tests

def __getattr__(self, name):
return getattr(self.val, name)

Check warning on line 84 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L84

Added line #L84 was not covered by tests


def get_runner(func):
"""Wraps a function to receive the args parsed from argparse"""

def _runner(args):

Check warning on line 90 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L90

Added line #L90 was not covered by tests

# Get the config argument. If present, load the arguments
# from the config (yaml) file.
config = getattr(args, "config", None)
config_args = {}
if config is not None:
import yaml

Check warning on line 97 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L94-L97

Added lines #L94 - L97 were not covered by tests

with open(args.config, "r") as f:
config_args = yaml.safe_load(f)

Check warning on line 100 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L99-L100

Added lines #L99 - L100 were not covered by tests

# Build the final arguments dictionary, using the arguments of the
# config file as defaults.
final_args = {}
for k, v in vars(args).items():
if k in ("runner", "config"):
continue
elif isinstance(v, NotPassedArg):
final_args[k] = config_args.get(k, v.val)

Check warning on line 109 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L104-L109

Added lines #L104 - L109 were not covered by tests
else:
final_args[k] = v

Check warning on line 111 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L111

Added line #L111 was not covered by tests

# And call the function
return func(**final_args)

Check warning on line 114 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L114

Added line #L114 was not covered by tests

return _runner

Check warning on line 116 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L116

Added line #L116 was not covered by tests


def get_argparse_parser(
Expand Down Expand Up @@ -154,28 +159,28 @@
"""

# Check if the function needs to be added as a subparser
is_sub = not subp is None

Check warning on line 162 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L162

Added line #L162 was not covered by tests

# Get the function's information
fdoc = FunctionDoc(func)
signature = inspect.signature(func)

Check warning on line 166 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L165-L166

Added lines #L165 - L166 were not covered by tests

# Initialize parser
title = "".join(fdoc["Summary"])
parser_help = "\n".join(fdoc["Extended Summary"])
if is_sub:
p = subp.add_parser(

Check warning on line 172 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L169-L172

Added lines #L169 - L172 were not covered by tests
name or func.__name__.replace("_", "-"),
description=parser_help,
help=title,
**parser_kwargs,
)
else:
p = argparse.ArgumentParser(title, **parser_kwargs)

Check warning on line 179 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L179

Added line #L179 was not covered by tests

# Add the config argument to load the arguments from a YAML file
if add_config:
p.add_argument(

Check warning on line 183 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L182-L183

Added lines #L182 - L183 were not covered by tests
"--config",
"-c",
type=str,
Expand All @@ -183,26 +188,31 @@
help="Path to a YAML file containing the arguments for the command",
)

group = p.add_argument_group("Function arguments")

Check warning on line 191 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L191

Added line #L191 was not covered by tests

# Add all the function's parameters to the parser
parameters_help = {p.name: p.desc for p in fdoc["Parameters"]}
for param in signature.parameters.values():

Check warning on line 195 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L194-L195

Added lines #L194 - L195 were not covered by tests

arg_names = [f"--{param.name.replace('_', '-')}"]
if param.name in arg_aliases:
arg_names.append(f"-{arg_aliases[param.name]}")

Check warning on line 199 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L197-L199

Added lines #L197 - L199 were not covered by tests

annotation = param.annotation
if is_optional(annotation):
annotation = get_optional_arg(annotation)

Check warning on line 203 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L201-L203

Added lines #L201 - L203 were not covered by tests

choices = None
if is_literal(annotation):
choices = get_literal_args(annotation)
annotation = type(choices[0])

Check warning on line 208 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L205-L208

Added lines #L205 - L208 were not covered by tests

# If the annotation is some-kind of union, just replace
# it with a string...
if is_union(annotation):
annotation = str

Check warning on line 213 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L212-L213

Added lines #L212 - L213 were not covered by tests

group.add_argument(

Check warning on line 215 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L215

Added line #L215 was not covered by tests
*arg_names,
type=annotation,
default=NotPassedArg(param.default),
Expand All @@ -212,9 +222,9 @@
help="\n".join(parameters_help.get(param.name, [])),
)

if is_sub:
defaults = {"runner": get_runner(func), **defaults}

Check warning on line 226 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L225-L226

Added lines #L225 - L226 were not covered by tests

p.set_defaults(**defaults)

Check warning on line 228 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L228

Added line #L228 was not covered by tests

return p

Check warning on line 230 in src/sisl/_lib/_argparse.py

View check run for this annotation

Codecov / codecov/patch

src/sisl/_lib/_argparse.py#L230

Added line #L230 was not covered by tests
6 changes: 6 additions & 0 deletions src/sisl_toolbox/siesta/minimizer/_atom_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import sisl as si
from sisl._internal import set_module
from sisl.messages import info
from sisl.utils import NotNonePropertyDict

from ._variable import Variable
Expand Down Expand Up @@ -323,6 +324,7 @@ def basis(self):

# get options for this shell
opts = self.opts[(n, l)]

line = f"n={n} {l} {len(orbs)}"
for key, value in opts.items():
if key == "pol":
Expand All @@ -342,6 +344,8 @@ def basis(self):
# explicit radius, convert to Bohr
ri *= _Ang2Bohr
line += f" {ri:.10f}"
else:
info("Omitting soft-confinement due to V0 < 0.001 eV")

elif key == "split":
# split-norm value
Expand All @@ -363,6 +367,8 @@ def basis(self):
line += f" {yukawa/_Ang2Bohr:.10f}"
if not width is None:
line += f" {width*_Ang2Bohr:.10f}"
else:
info("Omitting charge-confinement due to Z < 0.005 e")
else:
raise ValueError(f"Unknown option for n={n} l={l}: {key}")
block.append(line)
Expand Down
9 changes: 5 additions & 4 deletions src/sisl_toolbox/siesta/minimizer/_minimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@

_log = logging.getLogger(__name__)

# TODO we should have some kind of checks for the bounds, whether they
# make sense or not.


def _convert_optimize_result(minimizer, result):
"""Convert optimize result to conform to the scaling procedure performed"""
Expand Down Expand Up @@ -350,15 +353,13 @@
It uses the pybads package to perform the minimization.
"""

def run(self, options={}, get_hard_bounds: Callable = lambda x: x, **kwargs):
def run(self, options={}, func_hard_bounds: Callable = lambda x: x, **kwargs):
from pybads.bads import BADS

bounds = self.normalize_bounds()
bounds = np.array(bounds)

bounds[bounds == 0] = 0.5

hard_bounds = get_hard_bounds(bounds)
hard_bounds = func_hard_bounds(bounds)

with self:

Expand All @@ -374,8 +375,8 @@
# They do a deep copy of the arguments at the end, when generating the result.
# This might be a problem if the arguments are not pickleable. E.g. the minimizer function
# is associated with the minimizer object, which might contain siles.
try:
opt = bads.optimize()

Check notice

Code scanning / CodeQL

Unused local variable Note

Variable opt is not used.
except TypeError:

Check notice

Code scanning / CodeQL

Empty except Note

'except' clause does nothing but pass and there is no explanatory comment.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason for try ... pass? Don't we want it to scream at the user if it fails?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is explained in the comment above, basically their final saving or whatever (I don't remember exactly what it was) uses pickle and it can fail, but I guess we didn't need it because we do our own saving of the optimization.

pass

Expand Down
Loading
Loading