Voigt fitting data, but incorrectly reporting fit as initial guesses for FWHM and height

85 views
Skip to first unread message

Elizabeth Allan-Cole

unread,
May 16, 2023, 1:11:13 PM5/16/23
to lmfit-py
Hello, 

I'm having an issue with the fit report reporting the initial guesses for FWHM and height of a Voight fit. 

I have read the "Why are Parameter values sometimes stuck at initial values?" section in the FAQ and adjusted the initial guesses to be close to the final values; however, I am also working on edge cases in my data right now where I have two peaks that differ drastically in height occasionally, but not all the. 

The example that I am including shows that the fit found the large and small peaks in the plot, but the fit report is showing the initial guesses for height and fwhm. From looking at the fit these are clearly not the correct values that the model found based on the plot. I have played around with the initial guesses and added a way to vary the height in my original longer script to permutate through peak height guesses, but this has not helped reporting the values. 

I was wondering if this was an over constrained system, but ultimately I would like to constrain the fwhm to have a maximum to prevent broad peak fitting that should be part of the background. 

Please let me know how to fix this issue and get the values to report correctly.

Thank you! 
Elizabeth 

Information on fit below: 
I am including a minimal example script and one data file to show the problems I am encountering. 
  • Script: 'Minimal_example_fit_report_incorrect_initial_guess.py'
    • To run, locate inputs starting on line 170
    • Change file path in line 175 to local data file storage path
  • Data File: 'GoodFit.chi'
    • Shows an example of the model finding a fit that is good. 
    • Fit report, problem shown highlighted in yellow
      • [[Model]]
            ((Model(linear, prefix='b_') + Model(voigt, prefix='v0_')) + Model(voigt, prefix='v1_'))
        [[Fit Statistics]]
            # fitting method   = leastsq
            # function evals   = 248
            # data points      = 44
            # variables        = 14
            chi-square         = 18.0256099
            reduced chi-square = 0.60085366
            Akaike info crit   = -11.2654290
            Bayesian info crit = 13.7132259
            R-squared          = 0.99975130
        ##  Warning: uncertainties could not be estimated:
            v0_fwhm:       at initial value
            v0_height:     at initial value
            v1_gamma:      at boundary
            v1_fwhm:       at initial value
            v1_height:     at initial value
        [[Variables]]
            b_slope:      -70.5935504 (init = 0)
            b_intercept:   253.168042 (init = 50)
            v0_amplitude:  3.83510227 (init = 5)
            v0_center:     1.81160330 (init = 1.7875)
            v0_sigma:      0.00425600 (init = 0.005)
            v0_gamma:      0.00593615 (init = 0.005)
            v0_fwhm:       0.02000000 (init = 0.02)
            v0_height:     150.000000 (init = 150)

            v1_amplitude:  0.05497377 (init = 5)
            v1_center:     1.87896071 (init = 1.84375)
            v1_sigma:      0.00437008 (init = 0.005)
            v1_gamma:      1.8712e-12 (init = 0.005)
            v1_fwhm:       0.02000000 (init = 0.02)
            v1_height:     150.000000 (init = 150)

    • Plot shown below of good fit
Figure 2023-05-16 105956.png
Minimal_example_fit_report_incorrect_initial_guess.py
GoodFit.chi

Matt Newville

unread,
May 16, 2023, 1:59:14 PM5/16/23
to lmfi...@googlegroups.com
Hi Elizabeth, 

I think the problem is that you are setting 'fwhm' and 'height' to be variables (vary=True) for the two Voigt functions.  Those parameters are not actually used in by the fit function, which is why they end up not being moved from their initial values.

If you just comment out or remove the lines like

       pars[pref+'height'].set(value=height, vary=True, expr='', min = 0, max = height * 5)
       pars[pref+'fwhm'].set(value=fwhm, vary=True, expr='', min = 0, max = fwhm * 1.5)

I think your fit should work.  In that case the 'height' and 'fwhm' parameters will be derived from the `sigma` and `amplitude` parameters.

I'm not sure why one of the `gamma` parameters gets stuck at the boundary of zero.  I have seen similar cases where allowing `gamma` and `sigma` to vary independently for a Voigt function does not work that well.  In those cases (or for those peaks), I usually revert to having `gamma=sigma` or using a Gaussian.

Cheers,

--
You received this message because you are subscribed to the Google Groups "lmfit-py" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lmfit-py+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lmfit-py/95e99a81-dd26-4db0-81fd-e7674519a17fn%40googlegroups.com.


--
--Matt Newville <newville at cars.uchicago.edu630-327-7411

Elizabeth Allan-Cole

unread,
May 16, 2023, 2:37:42 PM5/16/23
to lmfit-py
Hi Matt, 

Thank you for getting back to me, I originally didn't have the constraints on the height and fwhm in my code, and they were reporting correctly. I also re-ran it and confirmed again that they report actual fit numbers when I comments them out.

My issue is that I would like to be able to constrain them in some way because I am ending up with some fits that are not finding the smaller peak or are fitting a very broad peak instead. 

Here is a different data set that is not fitting the smaller peak well: 

 Figure 2023-05-16 121613.png
I would like to constrain the fwhm to fit the second smaller peak more similarly to the 'GoodFit.chi' in my above example. The broad green peak is not accurately fitting and I have been having a hard time feeding parameters into this type of example. Is there a way to constrain these parameters to prevent this type of fit and have the small peak fit more accurately? Or do you have any ideas how to approach this better?

I included this data file as well for reference and titled it 'BadFit.chi' and should run with the script I provided above. 

Fit report for  'BadFit.chi' file (with NO constraints on fwhm and height): 
[[Model]]
    ((Model(linear, prefix='b_') + Model(voigt, prefix='v0_')) + Model(voigt, prefix='v1_'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 1100

    # data points      = 44
    # variables        = 10
    chi-square         = 46.4462509
    reduced chi-square = 1.36606620
    Akaike info crit   = 22.3806691
    Bayesian info crit = 40.2225654
    R-squared          = 0.99915789
[[Variables]]
    b_slope:      -455.510990 +/- 853.770782 (187.43%) (init = 0)
    b_intercept:   875.491181 +/- 1356.21147 (154.91%) (init = 50)
    v0_amplitude:  3.36444842 +/- 0.16176741 (4.81%) (init = 5)
    v0_center:     1.80921576 +/- 5.7947e-05 (0.00%) (init = 1.825)
    v0_sigma:      0.00478056 +/- 3.9917e-04 (8.35%) (init = 0.005)
    v0_gamma:      0.00562803 +/- 6.3554e-04 (11.29%) (init = 0.005)
    v0_fwhm:       0.01843397 +/- 2.3781e-04 (1.29%) == '1.0692*v0_gamma+sqrt(0.8664*v0_gamma**2+5.545083*v0_sigma**2)'
    v0_height:     134.233208 +/- 2.31161478 (1.72%) == '(v0_amplitude/(max(1e-15, v0_sigma*sqrt(2*pi))))*wofz((1j*v0_gamma)/(max(1e-15, v0_sigma*sqrt(2)))).real'
    v1_amplitude:  34.2055448 +/- 143.988349 (420.95%) (init = 5)
    v1_center:     1.90000000 +/- 0.06515399 (3.43%) (init = 1.8625)
    v1_sigma:      0.01000000 +/- 0.10369425 (1036.94%) (init = 0.005)
    v1_gamma:      0.11825431 +/- 0.16863318 (142.60%) (init = 0.005)
    v1_fwhm:       0.23900002 +/- 0.29810280 (124.73%) == '1.0692*v1_gamma+sqrt(0.8664*v1_gamma**2+5.545083*v1_sigma**2)'
    v1_height:     91.4276729 +/- 266.643666 (291.64%) == '(v1_amplitude/(max(1e-15, v1_sigma*sqrt(2*pi))))*wofz((1j*v1_gamma)/(max(1e-15, v1_sigma*sqrt(2)))).real'
[[Correlations]] (unreported correlations are < 0.100)
    C(b_slope, b_intercept)       = -1.000
    C(b_slope, v1_center)         = -0.997
    C(b_intercept, v1_center)     = 0.996
    C(v1_amplitude, v1_center)    = 0.994
    C(b_slope, v1_amplitude)      = -0.993
    C(b_intercept, v1_amplitude)  = 0.991
    C(v1_amplitude, v1_gamma)     = 0.985
    C(v0_sigma, v0_gamma)         = -0.968
    C(v0_amplitude, v0_gamma)     = 0.966
    C(v1_center, v1_gamma)        = 0.964
    C(b_slope, v1_gamma)          = -0.959
    C(b_intercept, v1_gamma)      = 0.955
    C(v0_amplitude, v0_sigma)     = -0.886
    C(v1_sigma, v1_gamma)         = -0.738
    C(v1_amplitude, v1_sigma)     = -0.623
    C(b_slope, v1_sigma)          = 0.547
    C(v1_center, v1_sigma)        = -0.541
    C(b_intercept, v1_sigma)      = -0.537
    C(v0_amplitude, v1_gamma)     = -0.535
    C(v0_amplitude, v1_amplitude) = -0.461
    C(v0_amplitude, v1_sigma)     = 0.454
    C(v0_amplitude, v1_center)    = -0.429
    C(v0_gamma, v1_gamma)         = -0.409
    C(b_slope, v0_amplitude)      = 0.384
    C(b_intercept, v0_amplitude)  = -0.375
    C(b_intercept, v0_center)     = -0.367
    C(b_slope, v0_center)         = 0.366
    C(v0_center, v1_center)       = -0.363
    C(v0_center, v1_amplitude)    = -0.354
    C(v0_gamma, v1_amplitude)     = -0.345
    C(v0_gamma, v1_sigma)         = 0.332
    C(v0_center, v1_gamma)        = -0.323
    C(v0_gamma, v1_center)        = -0.318
    C(v0_sigma, v1_gamma)         = 0.313
    C(b_slope, v0_gamma)          = 0.276
    C(b_intercept, v0_gamma)      = -0.268
    C(v0_sigma, v1_amplitude)     = 0.258
    C(v0_sigma, v1_sigma)         = -0.245
    C(v0_sigma, v1_center)        = 0.236
    C(b_slope, v0_sigma)          = -0.198
    C(b_intercept, v0_sigma)      = 0.191
    C(v0_amplitude, v0_center)    = 0.142
    C(v0_center, v0_gamma)        = 0.112
BadFit.chi
Reply all
Reply to author
Forward
0 new messages