Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

thomson_fitting error with lmfit==1.3.0 #2620

Closed
pheuer opened this issue Apr 5, 2024 · 3 comments
Closed

thomson_fitting error with lmfit==1.3.0 #2620

pheuer opened this issue Apr 5, 2024 · 3 comments
Assignees
Labels
needed for release Must be address/merged before next release priority: high Issues & PRs with significant urgency and importance that should be addressed soon
Milestone

Comments

@pheuer
Copy link
Member

pheuer commented Apr 5, 2024

Bug description

I'm looking into this: I can reproduce this error locally by upgrading my lmfit version from 1.2.0 to 1.3.0 (the latter is what PlasmaPy is now running on, at least in CI). The error occurs in thomson_fitting.ipynb:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[9], line 2
      1 fit_kws = {}
----> 2 epw_result = epw_model.fit(
      3     epw_skw,
      4     params=params,
      5     wavelengths=epw_wavelengths.to(u.m).value,
      6     method="differential_evolution",
      7     fit_kws=fit_kws,
      8 )

File ~\anaconda3\envs\dev311\Lib\site-packages\lmfit\model.py:1174, in Model.fit(self, data, params, weights, method, iter_cb, scale_covar, verbose, fit_kws, nan_policy, calc_covar, max_nfev, coerce_farray, **kwargs)
   1168     fit_kws = {}
   1170 output = ModelResult(self, params, method=method, iter_cb=iter_cb,
   1171                      scale_covar=scale_covar, fcn_kws=kwargs,
   1172                      nan_policy=self.nan_policy, calc_covar=calc_covar,
   1173                      max_nfev=max_nfev, **fit_kws)
-> 1174 output.fit(data=data, weights=weights)
   1175 output.components = self.components
   1176 return output

File ~\anaconda3\envs\dev311\Lib\site-packages\lmfit\model.py:1559, in ModelResult.fit(self, data, params, weights, method, nan_policy, **kwargs)
   1557 self.userargs = (self.data, self.weights)
   1558 self.userkws.update(kwargs)
-> 1559 self.init_fit = self.model.eval(params=self.params, **self.userkws)
   1560 _ret = self.minimize(method=self.method)
   1561 self.model.post_fit(_ret)

File ~\anaconda3\envs\dev311\Lib\site-packages\lmfit\model.py:997, in Model.eval(self, params, **kwargs)
    964 def eval(self, params=None, **kwargs):
    965     """Evaluate the model with supplied parameters and keyword arguments.
    966 
    967     Parameters
   (...)
    995 
    996     """
--> 997     return coerce_arraylike(self.func(**self.make_funcargs(params, kwargs)))

File ~\GitHub\PlasmaPy\plasmapy\diagnostics\thomson.py:685, in _spectral_density_model(wavelengths, settings, **params)
    678 """
    679 lmfit Model function for fitting Thomson spectra.
    680 
    681 For descriptions of arguments, see the `thomson_model` function.
    682 """
    684 # LOAD FROM SETTINGS
--> 685 ion_z = settings["ion_z"]
    686 ion_mass = settings["ion_mass"]
    687 probe_vec = settings["probe_vec"]

TypeError: 'NoneType' object is not subscriptable

Raised in #2618

No helpful details in the lmfit release log, although 1.3.0 released yesterday, so that tracks with the sudden change
https://lmfit.github.io/lmfit-py/whatsnew.html#version-1-3-0-release-notes-april-4-2024

@pheuer pheuer self-assigned this Apr 5, 2024
@namurphy namurphy added needed for release Must be address/merged before next release priority: high Issues & PRs with significant urgency and importance that should be addressed soon labels Apr 5, 2024
@namurphy namurphy added this to the v2024.5.0 milestone Apr 5, 2024
@pheuer
Copy link
Member Author

pheuer commented Apr 5, 2024

I think this is a bug in lmfit 1.3.0. The documentation states that additional keywords to Model are passed to the model function, but this clearly isn't happening based on the following minimal non-working example. I will open an issue on the lmfit repository

import numpy as np
from lmfit import Model, Parameters

# Define some data
x = np.linspace(0,1,num=10)
data = 10*x+2



# Parameters list with one parameter
params = Parameters()
params.add("b", value=5, vary=True, min=0.5, max=25)


# Dictionary of constants to be passed to model function through **kws
# of `Model`
settings = {'a':2}


# Define a model function that takes the parameters and the settings keyword
def _model(x, settings=None, **params):
    
    # TypeError is raised here because `settings` keyword is not being 
    # passed through to `_model`, so `settings=None`
    a = settings['a']
    b = params['b']
    
    return x*b + a


model = Model(
     _model,
     independent_vars=["x"],
     settings=settings,
 )


# Try to fit
# This raises an exception
result = model.fit(
    data,
    params=params,
    x=x,
    method="leastsq",
)

print(result.best_values)

@pheuer
Copy link
Member Author

pheuer commented Apr 5, 2024

If lmfit doesn't want to restore this functionality (or it takes a while to get that in their release version), the following fix would work (around line 1007 of thomson.py). The lambda function provides a work around way of passing settings into _spectral_density_model

_spectral_density_model_lambda = lambda wavelengths, **params: _model(wavelengths, settings=settings, **params)

 return Model(
        _spectral_density_model_lambda,
        independent_vars=["wavelengths"],
        nan_policy="omit",
        )

@pheuer
Copy link
Member Author

pheuer commented Apr 6, 2024

Closed by #2623

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needed for release Must be address/merged before next release priority: high Issues & PRs with significant urgency and importance that should be addressed soon
Projects
None yet
Development

No branches or pull requests

2 participants