Skip to content

Commit 5fc3bdb

Browse files
committed
Pearson4 model now functional, amplitude and fwhm added
1 parent 1671567 commit 5fc3bdb

3 files changed

Lines changed: 126 additions & 22 deletions

File tree

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
from lmfit import Model
2+
from lmfit import Parameter
23
from lmfit.models import guess_from_peak, update_param_vals
3-
from pearsonivamplitudeparametrizationhpw import PearsonIVAmplitudeParametrizationHPW
4-
from voigtareaparametrizationnu import VoigtAreaParametrizationNu
4+
from ramanchada2.fitting_functions.pearsonivamplitudeparametrizationhpw import (
5+
PearsonIVAmplitudeParametrizationHPW,
6+
)
7+
from ramanchada2.fitting_functions.voigtareaparametrizationnu import (
8+
VoigtAreaParametrizationNu,
9+
)
510
import numpy as np
611

712

@@ -11,25 +16,80 @@ class PearsonIVParametrizationHPWModel(Model):
1116
`sigma` (:math:`\sigma`), `expon` (:math:`m`) and `skew` (:math:`\nu`).
1217
"""
1318

14-
def __init__(self, independent_vars=['x'], prefix='', nan_policy='raise',
15-
**kwargs):
16-
kwargs.update({'prefix': prefix, 'nan_policy': nan_policy,
17-
'independent_vars': independent_vars})
19+
def __init__(self, independent_vars=["x"], prefix="", nan_policy="raise", **kwargs):
20+
kwargs.update(
21+
{
22+
"prefix": prefix,
23+
"nan_policy": nan_policy,
24+
"independent_vars": independent_vars,
25+
}
26+
)
1827
super().__init__(PearsonIVAmplitudeParametrizationHPW.GetYOfOneTerm, **kwargs)
1928
self._set_paramhints_prefix()
2029

2130
def _set_paramhints_prefix(self):
22-
self.set_param_hint('expon', value=1.5, min=0.5 + 1 / 1024.0, max=1000)
23-
self.set_param_hint('skew', value=0.0, min=-1000, max=1000)
31+
self.set_param_hint("expon", value=1.5, min=0.5 + 1 / 1024.0, max=1000)
32+
self.set_param_hint("skew", value=0.0, min=-1000, max=1000)
2433

2534
def guess(self, data, x, negative=False, **kwargs):
2635
"""Estimate initial model parameter values from data."""
2736
pars = guess_from_peak(self, data, x, negative)
28-
pars[f'{self.prefix}height'].set(value=pars[f'{self.prefix}amplitude'] / pars[f'{self.prefix}sigma'])
29-
pars[f'{self.prefix}expon'].set(value=1)
30-
pars[f'{self.prefix}skew'].set(value=0.0)
3137
return update_param_vals(pars, self.prefix, **kwargs)
3238

39+
def make_params(self, verbose=False, **kwargs):
40+
pars = super().make_params(verbose=verbose, **kwargs)
41+
pars[f"{self.prefix}height"].set(
42+
value=kwargs[f"{self.prefix}amplitude"] / kwargs[f"{self.prefix}sigma"]
43+
)
44+
pars[f"{self.prefix}expon"].set(value=1.0)
45+
pars[f"{self.prefix}skew"].set(value=0.0)
46+
return pars
47+
48+
def fit(
49+
self,
50+
data,
51+
params=None,
52+
weights=None,
53+
method="leastsq",
54+
iter_cb=None,
55+
scale_covar=True,
56+
verbose=False,
57+
fit_kws=None,
58+
nan_policy=None,
59+
calc_covar=True,
60+
max_nfev=None,
61+
**kwargs,
62+
):
63+
"""overwrite fit in order to amend area and fwhm to the parameters"""
64+
result = super().fit(
65+
data,
66+
params=params,
67+
weights=weights,
68+
method=method,
69+
iter_cb=iter_cb,
70+
scale_covar=scale_covar,
71+
verbose=verbose,
72+
fit_kws=fit_kws,
73+
nan_policy=nan_policy,
74+
calc_covar=calc_covar,
75+
max_nfev=max_nfev,
76+
**kwargs,
77+
)
78+
pahf = PearsonIVAmplitudeParametrizationHPW.GetPositionAreaHeightFWHMFromPeakParameters(
79+
result.params[f"{self.prefix}height"],
80+
result.params[f"{self.prefix}center"],
81+
result.params[f"{self.prefix}sigma"],
82+
result.params[f"{self.prefix}expon"],
83+
result.params[f"{self.prefix}skew"],
84+
result.covar
85+
)
86+
p1 = Parameter(f"{self.prefix}amplitude", value=pahf.Area)
87+
p1.stderr = pahf.AreaStdDev
88+
p2 = Parameter(f"{self.prefix}fwhm", value=pahf.FWHM)
89+
p2.stderr = pahf.FWHMStdDev
90+
result.params.add_many(p1, p2)
91+
return result
92+
3393

3494
class VoigtAreaParametrizationNuModel(Model):
3595
r"""A model based on a Voigt distribution function.
@@ -41,22 +101,26 @@ class VoigtAreaParametrizationNuModel(Model):
41101
For more information, see: https://en.wikipedia.org/wiki/Voigt_profile
42102
"""
43103

44-
def __init__(self, independent_vars=['x'], prefix='', nan_policy='raise',
45-
**kwargs):
46-
kwargs.update({'prefix': prefix, 'nan_policy': nan_policy,
47-
'independent_vars': independent_vars})
104+
def __init__(self, independent_vars=["x"], prefix="", nan_policy="raise", **kwargs):
105+
kwargs.update(
106+
{
107+
"prefix": prefix,
108+
"nan_policy": nan_policy,
109+
"independent_vars": independent_vars,
110+
}
111+
)
48112
super().__init__(VoigtAreaParametrizationNu.GetYOfOneTerm, **kwargs)
49113
self._set_paramhints_prefix()
50114

51115
def _set_paramhints_prefix(self):
52-
self.set_param_hint('sigma', min=np.tiny)
53-
self.set_param_hint('nu', min=0, max=1)
116+
self.set_param_hint("sigma", min=np.tiny)
117+
self.set_param_hint("nu", min=0, max=1)
54118

55-
fexpr = ("2.0*{pre:s}sigma")
56-
self.set_param_hint('fwhm', expr=fexpr.format(pre=self.prefix))
119+
fexpr = "2.0*{pre:s}sigma"
120+
self.set_param_hint("fwhm", expr=fexpr.format(pre=self.prefix))
57121

58122
def guess(self, data, x, negative=False, **kwargs):
59123
"""Estimate initial model parameter values from data."""
60124
pars = guess_from_peak(self, data, x, negative)
61-
pars[f'{self.prefix}nu'].set(value=1.0)
125+
pars[f"{self.prefix}nu"].set(value=1.0)
62126
return update_param_vals(pars, self.prefix, **kwargs)

src/ramanchada2/fitting_functions/pearsonivamplitudeparametrizationhpw.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ def GetParameterNamesForPeak(self, indexOfPeak):
7373

7474
def GetYOfOneTerm(x, height=1.0, center=0.0, sigma=1.0, expon=1.0, skew=0.0):
7575
"""Returns the y-value of one peak in dependence on x and the peak parameters."""
76-
arg = np.sqrt((np.power(2, 1 / expon) - 1) * (1 + skew * skew)) * (x - center) / sigma - skew
76+
arg = (
77+
np.sqrt((np.power(2, 1 / expon) - 1) * (1 + skew * skew))
78+
* (x - center)
79+
/ sigma
80+
- skew
81+
)
7782
return height * np.exp(
7883
expon
7984
* (
@@ -397,12 +402,28 @@ def GetPositionAreaHeightFWHMFromSinglePeakParameters(
397402
wm = parameters[f"w{indexOfPeak}"]
398403
m = parameters[f"m{indexOfPeak}"]
399404
vm = parameters[f"v{indexOfPeak}"]
405+
400406
if cv is not None:
401407
cv = cv[
402408
indexOfPeak * 5: (indexOfPeak + 1) * 5,
403409
indexOfPeak * 5: (indexOfPeak + 1) * 5,
404410
]
411+
return PearsonIVAmplitudeParametrizationHPW.GetPositionAreaHeightFWHMFromPeakParameters(
412+
amp, loc, wm, m, vm, cv
413+
)
405414

415+
def GetPositionAreaHeightFWHMFromPeakParameters(amp, loc, wm, m, vm, cv=None):
416+
"""
417+
Get position, area, height, and FWHM of one peak from the peak parameters.
418+
If the covariance matrix is given, the corresponding errors are calculated.
419+
420+
Parameters
421+
----------
422+
amp, loc, wm, m, vm:
423+
Peak parameters height, center, sigma, m, v
424+
cv: np.array
425+
Covariance matrix of the fit (5 x 5 matrix)
426+
"""
406427
area = PearsonIVAmplitudeParametrizationHPW.GetArea(amp, wm, m, vm)
407428
pos = loc
408429
height = amp

tests/fitting_functions/test_pearsonivamplitudeparametrizationhpw.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from ramanchada2.fitting_functions.pearsonivamplitudeparametrizationhpw import (
22
PearsonIVAmplitudeParametrizationHPW,
3-
)
3+
)
4+
from ramanchada2.fitting_functions.models import PearsonIVParametrizationHPWModel
45
import lmfit
56
import numpy as np
67

@@ -456,3 +457,21 @@ def test_fit_with_derivatives_twoterms_linearbaseline():
456457
np.testing.assert_almost_equal(out1.params["w1"], w1, 12)
457458
np.testing.assert_almost_equal(out1.params["m1"], m1, 12)
458459
np.testing.assert_almost_equal(out1.params["v1"], v1, 12)
460+
461+
462+
def test_fit_with_model_oneterm():
463+
x = np.linspace(0, 99, 100)
464+
a = 7
465+
pos = 50
466+
w = 5
467+
m = 16 / 11.0
468+
v = 1 / 4.0
469+
data = PearsonIVAmplitudeParametrizationHPW.GetYOfOneTerm(x, a, pos, w, m, v)
470+
model = PearsonIVParametrizationHPWModel(x=x)
471+
params = model.guess(data, x)
472+
result = model.fit(data, x=x, params=params)
473+
np.testing.assert_almost_equal(result.params["height"], a, 7)
474+
np.testing.assert_almost_equal(result.params["center"], pos, 7)
475+
np.testing.assert_almost_equal(result.params["sigma"], w, 7)
476+
np.testing.assert_almost_equal(result.params["expon"], m, 7)
477+
np.testing.assert_almost_equal(result.params["skew"], v, 7)

0 commit comments

Comments
 (0)