I'm trying to fit a Lorentzian function with more than Imaginary part of Silicon, but the curve_fit function it not working properly, not fitting any peaks with this message.
D:\anacode\lib\site-packages\scipy\optimize\minpack.py:447: RuntimeWarning: Number of calls to function has reached maxfev = 3400.
warnings.warn(errors[info][0], RuntimeWarning)
How can I fit it?
I used code of this answer: How can I fit a good Lorentzian on python using scipy.optimize.curve_fit?
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.optimize import leastsq
def lorentzian( w, w0, w_p, gam ):
return w * gam * pow(w_p,2) / ( (w*gam)**2 + ( pow(w,2) - pow(w0,2) )**2)
def multi_lorentz( x, params ):
off = params[0]
paramsRest = params[1:]
assert not ( len( paramsRest ) % 3 ) #0,1,2가 아니면 assert error 발생
return off + sum( [ lorentzian( x, *paramsRest[ i : i+3 ] ) for i in range( 0, len( paramsRest ), 3 ) ] )
def res_multi_lorentz( params, xData, yData ):
diff = [ multi_lorentz( x, params ) - y for x, y in zip( xData, yData ) ]
return diff
xData, yData = np.loadtxt('E2_Silicon.dat', unpack=True )
xData=xData[2400:]
yData=yData[2400:]
generalWidth = 1
yDataLoc = yData
startValues = [ min( yData ) ]
counter = 0
while max( yDataLoc ) - min( yDataLoc ) >1:
counter += 1
if counter > 20: ### max 20 peak...emergency break to avoid infinite loop
break
maxP = np.argmax( yDataLoc )
maxY = yData[ maxP ]
x0 = xData[ maxP ]
startValues += [ x0, np.sqrt(maxY*x0), generalWidth ]
popt, ier = leastsq( res_multi_lorentz, startValues, args=( xData, yData ) )
yDataLoc = [ y - multi_lorentz( x, popt ) for x,y in zip( xData, yData ) ]
#if ier == 6, find 6 set of lorentzian parameters
print(popt)
testData = [ multi_lorentz(x, popt ) for x in xData ]
fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.plot( xData, yData )
ax.plot( xData, testData )
plt.show()
MyData: https://drive.google.com/file/d/19lSJKn6ZTeZlLVgii794hQZg2AKgbTBK/view?usp=sharing