I am trying to fit my data with a Voigt function. I used the code given below. But the fit is not there with a right range.. and I do not know how to set the range to fit. Can anyone help me pls?
import numpy as np
import matplotlib.pyplot as plt
from scipy import asarray as exp
from numpy import genfromtxt
data= genfromtxt ('calibration.txt')
x=data[:,0]
y=data[:,1]
plt.xlim(0,1)
plt.ylim(0,1.25)
plt.xlabel("Voltage [V]")
plt.ylabel("Intensity")
def V(amp,x, sigma, gamma,a,b):
"""
Return the Voigt line shape at x with Lorentzian component HWHM gamma
and Gaussian component sigma, a&b as the center.
"""
return amp*np.exp(-(x-a)**2/(2*(sigma)**2))+gamma/np.pi/((x-b)**2+(gamma)**2)
amp,sigma, gamma,a,b =0.9, 0.1,0.04, 0.5,0.5
plt.plot(x,y,'b.',x, V(amp, x, sigma, gamma,a,b))
plt.show()
and here is the link to my data https://www.dropbox.com/s/vm9ta6samnlc0s2/calibration.txt?dl=0 Thank you for any help. PS: The program produces the plot given below: https://www.dropbox.com/s/3rbuq4v7gcc92m7/figure_1.png?dl=0
I am not really sure what you are doing or trying to do, but this is how I would do it ( assuming that the sigma and gamma are the same for all peaks. Did not think to much if this makes sense in a Fabry-Perot)
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
def cauchy(x, x0, g):
return 1. / ( np.pi * g * ( 1 + ( ( x - x0 )/ g )**2 ) )
def gauss( x, x0, s):
return 1./ np.sqrt(2 * np.pi * s**2 ) * np.exp( - (x-x0)**2 / ( 2 * s**2 ) )
def pseudo_voigt( x, x0, s, g, a ):
fg = 2 * s * np.sqrt( 2 * np.log(2) )
fl = 2 * g
f = ( fg**5 + 2.69269 * fg**4 * fl + 2.42843 * fg**3 * fl**2 + 4.47163 * fg**2 * fl**3 + 0.07842 * fg * fl**4+ fl**5)**(1./5.)
eta = 1.36603 * ( fl / f ) - 0.47719 * ( fl / f )**2 + 0.11116 * ( f / fl )**3
return a * ( eta * cauchy( x, x0, f) + ( 1 - eta ) * gauss( x, x0, f ) )
def all_peaks(x, mus, amps, s, g ):
out = 0
for m, a in zip( mus, amps ):
out += pseudo_voigt( x, m, s, g, a )
return out
def res( params, xData, yData):
mus = params[0:5]
amp = params[5:10]
sig = params[-3]
gam = params[-2]
off = params[-1]
yth = np.fromiter( ( abs( off ) + all_peaks( x , mus, amp, sig, gam) for x in xData ), np.float )
diff = yth - yData
return diff
sigma, gamma = 0.007, 0.02
offset = 0.01
muList = [ 0.5, 2.6, 4.8, 6.8, 8.9 ]
ampList = [ .135 ] * 5
data = np.loadtxt( 'calibration.txt' )
x = data[ :,0 ]
y = data[ :,1 ]
sol, err = leastsq( res, muList + ampList + [sigma , gamma, offset ], args=(x, y) )
print sol
plt.xlabel( "Voltage [V]" )
plt.ylabel( "Intensity" )
plt.plot( x,y,ls='', marker='o' )
plt.plot( x, sol[-1] + all_peaks( x, sol[0:5],sol[5:10], sol[-3], sol[-2]) )
plt.show()
which gives
[
4.97681822e-01 2.63788309e+00 4.74796088e+00 6.83620027e+00 8.90127524e+00
1.28754082e-01 1.35709531e-01 1.34679136e-01 1.35460544e-01 1.39491029e-01
5.61700040e-03 1.93814469e-02 9.99057213e-03
]
and the following graph