Hello lmfit community, how do i set the initial condition of amplitude in modeling a continuum normalized absorption line to start from 1(continuum) not 0? I have attached the weird one i'm getting which i want to correct, thank you.

155 views
Skip to first unread message

ZIHABAKE Daniel

unread,
Jun 3, 2022, 10:14:40 AM6/3/22
to lmfit-py
NaID.pdf

Matt Newville

unread,
Jun 3, 2022, 11:51:07 AM6/3/22
to lmfit-py

This group is intended for questions and discussion about the use of and design of the lmfit python library for optimization and curve-fitting.  Any topic related to curve-fitting and Python is acceptable.  

If you are posting a question about lmfit not working for you as you would expect, please include in your post: 
  • a minimal and complete example.  Please see https://stackoverflow.com/help/mcve for more details.
  • the fit report from lmfit, if you have one.
  • If an error occurs, include the full traceback.
  • It's OK to post an image of data and fit, but if you are including code or output, this must be in plain text.  Do not post an image of text.  
We expect that users of lmfit are familiar with Python and numpy and are smart people who know how to ask questions in a way that can be answered. If you are asking a question about why something "didn't work" or didn't give results you expect, we expect you to explain what you did, what you expected, and what you got. This usually means posting a minimal example that shows the problem.

Message has been deleted

ZIHABAKE Daniel

unread,
Jun 4, 2022, 7:52:18 AM6/4/22
to lmfit-py
Sorry for not clarifying the problem, i'm a masters student not experienced in programming.
My question is " i want to fit multi-Gaussian components to my continuum normalized data with picks at 5875, 5890, and 5896 angstrom where sigma of 5890 and 5896 has to be the same.
By setting initial parameter of amplitude and fit i get output amplitude which is measured from 0 not from 1(continuum level),  i would like to know how i can fix the amplitude to be measured from 1. The attached is data.
thank you.

import matplotlib.pyplot as plt
from numpy import exp, loadtxt, pi, sqrt
from lmfit import Model, Parameters
data = loadtxt('Data.txt')
x = data[:, 0]
y = data[:, 1]

#selected region for fitting
mask = (x>= 5875) & (x <= 5910)
mask = (x>= 5850) & (x <= 5950)
xarray, yarray = x[mask], y[mask]
x=xarray
y=yarray

#defining a multi-Gaussian components function 
def gaussian(x, amp1, cen1, wid1, amp2, cen2, wid2, amp3, cen3, wid3):
    g1=(amp1 / (sqrt(2*pi) * wid1)) * exp(-(x-cen1)**2 / (2*wid2**2))
    g2=(amp2 / (sqrt(2*pi) * wid2)) * exp(-(x-cen2)**2 / (2*wid2**2))
    g3=(amp3 / (sqrt(2*pi) * wid3)) * exp(-(x-cen3)**2 / (2*wid3**2))
    return g1+g2+g3
gmodel = Model(gaussian)

params = Parameters()
params.add('amp1', vale=0.8, min=0.7, max=0.3)
params.add('cen1', vale=5890, min=5887, max=5894)
params.add('wid1', vale=3.0 , min=1, max=4)
params.add('amp2', vale=0.9, min=1, max=0.7)
params.add('cen2', vale=5896, min=5891, max=5902)
params.add('wid2', vale=3.0 , min=2, max=4)
params.add('amp3', vale=1.06, min=1, max=1.7)
params.add('cen3', vale=5875, min=5870, max=5890)
params.add('wid3', vale=3.0 , min=2, max=4)


result = gmodel.fit(y, params, x=x)
print(result.fit_report())
plt.plot(x, y, 'b', label='observed')
plt.ylim(ymin=-1, ymax=1.5)
plt.plot(x, result.best_fit, 'r-', label='best fit')
plt.xlabel('wavelength[$\AA$]')
plt.ylabel('flux[erg cm-2 s-1 $\AA$ -1]')

plt.legend(loc='best')
plt.savefig('NaID-He.pdf')
plt.show()
Data.txt

Matt Newville

unread,
Jun 4, 2022, 9:37:48 AM6/4/22
to lmfit-py
On Sat, Jun 4, 2022 at 6:52 AM ZIHABAKE Daniel <dziha...@gmail.com> wrote:
Sorry for not clarifying the problem, i'm a masters student not experienced in programming.
My question is " i want to fit multi-Gaussian components to my continuum normalized data with picks at 5875, 5890, and 5896 angstrom where sigma of 5890 and 5896 has to be the same.
By setting initial parameter of amplitude and fit i get output amplitude which is measured from 0 not from 1(continuum level),  i would like to know how i can fix the amplitude to be measured from 1. The attached is data.
thank you.


I think the problems are basically:

1. with 
    params.add('amp1', vale=0.8, min=0.7, max=0.3)
You want 'value' not 'vale', and 'min' needs to be less than max.  More importantly, don't set bounds to be too small.

2.  Your data is not represented well by 3 Gaussians.  You need some offset (I guess linear) too.  Also, the Gaussians will have negative amplitudes (see point 1).   

Try this (you can probably improve the plot):

###
from numpy import loadtxt
import matplotlib.pyplot as plt
from lmfit import Parameters
from lmfit.models import GaussianModel, LinearModel


data = loadtxt('Data.txt')
x = data[:, 0]
y = data[:, 1]

#selected region for fitting
mask = (x>= 5875) & (x <= 5910)
mask = (x>= 5850) & (x <= 5950)
xarray, yarray = x[mask], y[mask]
x=xarray
y=yarray

#  Note: use builtin models
gmodel = ( GaussianModel(prefix='p1_') +  GaussianModel(prefix='p2_') +
                   GaussianModel(prefix='p3_') +   LinearModel(prefix='off_'))

#  Note: many fewer bounds:
params = Parameters()
params.add('off_intercept', value=1)
params.add('off_slope', value=0)
params.add('p1_amplitude', value=-7)
params.add('p1_center', value=5890, min=5887, max=5894)
params.add('p1_sigma', value=3.0 , min=0)
params.add('p2_amplitude', value=-1)
params.add('p2_center', value=5896, min=5891, max=5902)
params.add('p2_sigma', value=3.0 , min=0)
params.add('p3_amplitude', value=0.5)
params.add('p3_center', value=5875, min=5870, max=5890)
params.add('p3_sigma', value=3.0 , min=0)


result = gmodel.fit(y, params, x=x)
print(result.fit_report())

comps = result.eval_components(x=x)


plt.plot(x, y, 'b', label='observed')
plt.ylim(ymin=-1, ymax=1.5)
plt.plot(x, result.best_fit, 'r--', label='best fit')
plt.plot(x, comps['p1_']+comps['off_'], 'b-', label='p1')
plt.plot(x, comps['p2_']+comps['off_'], 'g-', label='p3')
plt.plot(x, comps['p3_']+comps['off_'], 'k-', label='p2')
plt.plot(x, comps['off_'], 'k-', label='offset')

plt.xlabel(r'wavelength [$\rm \AA$]')
plt.ylabel(r'flux [$\rm erg / (cm^{2} \, s \, \AA)]')

plt.legend(loc='best')
plt.savefig('NaID-He.pdf')
plt.show()
###

--Matt 

NaID-He.pdf

ZIHABAKE Daniel

unread,
Jun 4, 2022, 9:58:50 AM6/4/22
to lmfi...@googlegroups.com
Thank you very much, let me try it.

--
You received this message because you are subscribed to a topic in the Google Groups "lmfit-py" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/lmfit-py/tP4gTJGW7qM/unsubscribe.
To unsubscribe from this group and all its topics, 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/CA%2B7ESbq0_yFLxV5bNxLFPMCoMQ43KwZ%3Db4vZkPTNnXq9YG7_8g%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages