python-lmfit/lmfit-pr965-asteval.patch

358 lines
12 KiB
Diff
Raw Normal View History

From e62b1784e7516f543402c013cfd532d6003aa859 Mon Sep 17 00:00:00 2001
From: Matthew Newville <newville@cars.uchicago.edu>
Date: Sun, 4 Aug 2024 20:34:44 -0500
Subject: [PATCH 1/9] BUG: fix typo in 'create_uvars' method
Closes: #962
---
lmfit/parameter.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lmfit/parameter.py b/lmfit/parameter.py
index a7ec9a65..243d4227 100644
--- a/lmfit/parameter.py
+++ b/lmfit/parameter.py
@@ -515,9 +515,9 @@ def create_uvars(self, covar=None):
vindex += 1
vnames.append(par.name)
vbest.append(par.value)
- if getattr(par, 'sdterr', None) is None and covar is not None:
+ if getattr(par, 'stderr', None) is None and covar is not None:
par.stderr = sqrt(covar[vindex, vindex])
- uvars[par.name] = ufloat(par.value, getattr(par, 'sdterr', 0.0))
+ uvars[par.name] = ufloat(par.value, getattr(par, 'stderr', 0.0))
corr_uvars = None
if covar is not None:
From 7fd4e42e84b3ab8f0bdc05274aa270d4ded765bf Mon Sep 17 00:00:00 2001
From: Matthew Newville <newville@cars.uchicago.edu>
Date: Sun, 11 Aug 2024 12:40:21 -0500
Subject: [PATCH 2/9] MAINT: 'uncertainties' fails if 'stderr' is None, so set
to zero
---
lmfit/parameter.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lmfit/parameter.py b/lmfit/parameter.py
index 243d4227..cd6d9626 100644
--- a/lmfit/parameter.py
+++ b/lmfit/parameter.py
@@ -517,7 +517,10 @@ def create_uvars(self, covar=None):
vbest.append(par.value)
if getattr(par, 'stderr', None) is None and covar is not None:
par.stderr = sqrt(covar[vindex, vindex])
- uvars[par.name] = ufloat(par.value, getattr(par, 'stderr', 0.0))
+ stderr = getattr(par, 'stderr', 0.0)
+ if stderr is None:
+ stderr = 0.0
+ uvars[par.name] = ufloat(par.value, stderr)
corr_uvars = None
if covar is not None:
From b812b4731805f9d85d717aff0ad34031c747d1d4 Mon Sep 17 00:00:00 2001
From: Matthew Newville <newville@cars.uchicago.edu>
Date: Sun, 11 Aug 2024 12:44:30 -0500
Subject: [PATCH 3/9] MAINT: asteval no longer raises NameError to Python
- so we suppress 'asteval' expections to stderr and look for them when creating parameters
---
lmfit/parameter.py | 25 +++++++++++++++++++++++--
tests/test_parameters.py | 3 +--
2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/lmfit/parameter.py b/lmfit/parameter.py
index cd6d9626..77ba882c 100644
--- a/lmfit/parameter.py
+++ b/lmfit/parameter.py
@@ -27,6 +27,20 @@ def check_ast_errors(expr_eval):
expr_eval.raise_exception(None)
+class Writer:
+ """Replace 'stdout' and 'stderr' for asteval."""
+ def __init__(self, **kws):
+ self.messages = []
+ for k, v in kws.items():
+ setattr(self, k, v)
+
+ def write(self, msg):
+ """Internal writer."""
+ o = msg.strip()
+ if len(o) > 0:
+ self.messages.append(msg)
+
+
def asteval_with_uncertainties(*vals, obj=None, pars=None, names=None, **kwargs):
"""Calculate object value, given values for variables.
@@ -76,8 +90,9 @@ def __init__(self, usersyms=None):
"""
super().__init__(self)
-
- self._asteval = Interpreter()
+ self._ast_msgs = Writer()
+ self._asteval = Interpreter(writer=self._ast_msgs,
+ err_writer=self._ast_msgs)
_syms = {}
_syms.update(SCIPY_FUNCTIONS)
@@ -86,6 +101,9 @@ def __init__(self, usersyms=None):
for key, val in _syms.items():
self._asteval.symtable[key] = val
+ def _writer(self, msg):
+ self._asteval_msgs.append(msg)
+
def copy(self):
"""Parameters.copy() should always be a deepcopy."""
return self.__deepcopy__(None)
@@ -433,6 +451,9 @@ def add(self, name, value=None, vary=True, min=-inf, max=inf, expr=None,
self.__setitem__(name, Parameter(value=value, name=name, vary=vary,
min=min, max=max, expr=expr,
brute_step=brute_step))
+ if len(self._asteval.error) > 0:
+ err = self._asteval.error[0]
+ raise err.exc(err.msg)
def add_many(self, *parlist):
"""Add many parameters, using a sequence of tuples.
diff --git a/tests/test_parameters.py b/tests/test_parameters.py
index 7e12b1f0..998341e3 100644
--- a/tests/test_parameters.py
+++ b/tests/test_parameters.py
@@ -39,8 +39,7 @@ def assert_parameter_attributes(par, expected):
def test_check_ast_errors():
"""Assert that an exception is raised upon AST errors."""
pars = lmfit.Parameters()
-
- msg = r"at expr='<_?ast.Module object at"
+ msg = "name 'par2' is not defined"
with pytest.raises(NameError, match=msg):
pars.add('par1', expr='2.0*par2')
From 05fb78e8ebab8d3cc3360f3eb1ee852c8f4a7528 Mon Sep 17 00:00:00 2001
From: reneeotten <reneeotten@users.noreply.github.com>
Date: Fri, 16 Aug 2024 10:50:54 -0400
Subject: [PATCH 4/9] DOC: tweak 'sphinx-gallery' settings
---
doc/conf.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/conf.py b/doc/conf.py
index 1a36156b..972b552b 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -167,7 +167,7 @@
'examples_dirs': '../examples',
'gallery_dirs': 'examples',
'filename_pattern': r'(\\|/)documentation|(\\|/)example_',
- 'ignore_pattern': r'(\\|/)doc_',
+ 'ignore_pattern': 'doc_',
'ignore_repr_types': r'matplotlib',
'image_srcset': ["3x"],
}
From 07d65bf8ebcf013e7b47ce0c4930aa39d7cd2cc3 Mon Sep 17 00:00:00 2001
From: reneeotten <reneeotten@users.noreply.github.com>
Date: Fri, 16 Aug 2024 10:51:28 -0400
Subject: [PATCH 5/9] MAINT: update pre-commit hooks
---
.pre-commit-config.yaml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ee53e906..bad4bf3f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,7 +2,7 @@ exclude: 'doc/conf.py'
repos:
- repo: https://github.com/asottile/pyupgrade
- rev: v3.16.0
+ rev: v3.17.0
hooks:
- id: pyupgrade
args: [--py38-plus]
@@ -12,18 +12,18 @@ repos:
hooks:
- id: check-ast
- id: check-builtin-literals
+ - id: check-docstring-first
- id: check-case-conflict
- id: check-merge-conflict
- id: check-toml
+ - id: check-yaml
- id: debug-statements
- id: end-of-file-fixer
- id: mixed-line-ending
- id: trailing-whitespace
- - id: fix-encoding-pragma
- args: [--remove]
- repo: https://github.com/PyCQA/flake8
- rev: 7.1.0
+ rev: 7.1.1
hooks:
- id: flake8
additional_dependencies: [flake8-deprecated, flake8-mutable, Flake8-pyproject]
From 805263ddfac4f877dfd2c4e834155bd274020e3d Mon Sep 17 00:00:00 2001
From: reneeotten <reneeotten@users.noreply.github.com>
Date: Fri, 16 Aug 2024 10:53:22 -0400
Subject: [PATCH 6/9] CI: update to latest NumPy version
---
azure-pipelines.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 314d8704..01bc9d6e 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -256,7 +256,7 @@ stages:
displayName: 'Install build, pip, setuptools, wheel, pybind11, and cython'
- script: |
export PATH=/home/vsts/.local/bin:$PATH
- export numpy_version=2.0.0
+ export numpy_version=2.0.1
wget https://github.com/numpy/numpy/releases/download/v${numpy_version}/numpy-${numpy_version}.tar.gz
tar xzvf numpy-${numpy_version}.tar.gz
cd numpy-${numpy_version}
From 16f8cbd176ed5b9f5e1ac6a369c7bd75dbd5046a Mon Sep 17 00:00:00 2001
From: reneeotten <reneeotten@users.noreply.github.com>
Date: Fri, 16 Aug 2024 12:39:05 -0400
Subject: [PATCH 7/9] BLD: remove redundant wheel dependency
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index e41e844b..9578466d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,5 +1,5 @@
[build-system]
-requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"]
+requires = ["setuptools>=45", "setuptools_scm>=6.2"]
build-backend = "setuptools.build_meta"
[project]
From d6810a558887956f598d58d9876be8fe96090d6d Mon Sep 17 00:00:00 2001
From: reneeotten <reneeotten@users.noreply.github.com>
Date: Fri, 16 Aug 2024 18:06:34 -0400
Subject: [PATCH 8/9] DOC: update names of the documentation examples in
Gallery
- also rename the file doc_uvars_params.py to follow the usual naming
conventions
---
doc/doc_examples_to_gallery.py | 13 ++++++++-----
doc/model.rst | 2 +-
...{doc_uvars_params.py => doc_parameters_uvars.py} | 4 ++--
3 files changed, 11 insertions(+), 8 deletions(-)
rename examples/{doc_uvars_params.py => doc_parameters_uvars.py} (96%)
diff --git a/doc/doc_examples_to_gallery.py b/doc/doc_examples_to_gallery.py
index 4cfeb5bc..49695ffd 100755
--- a/doc/doc_examples_to_gallery.py
+++ b/doc/doc_examples_to_gallery.py
@@ -5,7 +5,7 @@
- create a "documentation" directory within "examples"
- add a README.txt file
-- copy the examples from the documentation, bu remove the "doc_" from the
+- copy the examples from the documentation, removing the "doc_" from the
filename
- add the required docstring to the files for proper rendering
- copy the data files
@@ -46,12 +46,15 @@ def copy_data_files(src_dir, dest_dir):
)
for fn in files:
+ sname = fn.name[4:]
+ lmfit_class, *description = sname[:-3].split('_')
+ gallery_name = f"{lmfit_class.capitalize()} - {' '.join(description)}"
script_text = fn.read_text()
- gallery_file = examples_documentation_dir / fn.name[4:]
- msg = "" # add optional message f
- gallery_file.write_text(f'"""\n{fn.name}\n{"=" * len(fn.name)}\n\n'
+ gallery_file = examples_documentation_dir / sname
+ msg = "" # add optional message
+ gallery_file.write_text(f'"""\n{gallery_name}\n{"=" * len(gallery_name)}\n\n'
f'{msg}\n"""\n{script_text}')
# make sure the saved Models and ModelResult are available
@@ -67,5 +70,5 @@ def copy_data_files(src_dir, dest_dir):
os.chdir(doc_dir)
-# # data files for the other Gallery examples
+# data files for the other Gallery examples
copy_data_files(examples_documentation_dir, doc_dir)
diff --git a/doc/model.rst b/doc/model.rst
index 5c8ae340..e5d6506a 100644
--- a/doc/model.rst
+++ b/doc/model.rst
@@ -1166,7 +1166,7 @@ that taking correlations between Parameters into account when performing
calculations can have a noticeable influence on the resulting uncertainties.
-.. jupyter-execute:: ../examples/doc_uvars_params.py
+.. jupyter-execute:: ../examples/doc_parameters_uvars.py
Note that the :meth:`Model.post_fit` does not need to be limited to this
diff --git a/examples/doc_uvars_params.py b/examples/doc_parameters_uvars.py
similarity index 96%
rename from examples/doc_uvars_params.py
rename to examples/doc_parameters_uvars.py
index 124c3024..1c4f2da8 100644
--- a/examples/doc_uvars_params.py
+++ b/examples/doc_parameters_uvars.py
@@ -1,4 +1,4 @@
-# <examples/doc_uvars_params.py>
+# <examples/doc_parameters_uvars.py>
import numpy as np
from lmfit.models import ExponentialModel, GaussianModel
@@ -67,4 +67,4 @@ def post_fit(result):
out = mod.fit(y, pars, x=x)
print(out.fit_report(min_correl=0.5))
-# <end examples/doc_uvars_params.py>
+# <end examples/doc_parameters_uvars.py>
From ff436c270d07433a7ae404fe76bc9c627b4edc3f Mon Sep 17 00:00:00 2001
From: reneeotten <reneeotten@users.noreply.github.com>
Date: Fri, 16 Aug 2024 22:02:40 -0400
Subject: [PATCH 9/9] BLD: remove numexpr dependency (again)
---
pyproject.toml | 1 -
1 file changed, 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 9578466d..cacdb8a4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -59,7 +59,6 @@ doc = [
"matplotlib",
"numdifftools",
"pandas",
- "numexpr", # note: Pandas appears to need numexpr to build our docs
"Pillow",
"pycairo;platform_system=='Windows'",
"Sphinx",