用python将费米函数与高斯函数的卷积拟合到真实数据

用python将费米函数与高斯函数的卷积拟合到真实数据,python,optimization,scipy,curve-fitting,convolution,Python,Optimization,Scipy,Curve Fitting,Convolution,我最近在处理光电发射数据,希望通过将费米函数与高斯函数的卷积拟合到真实数据来估计仪器分辨率。现在我忽略了我还必须有一个背景。 我试着根据我在书中找到的东西做一个分析 不幸的是,我现在陷入困境,恳请您帮助。我提供了一个小例子,即我模拟的数据(通过眼睛判断)实际上是真实数据的良好表示,除了缺少背景外: import array as ar import math from math import e, sqrt, pi import pylab as plt from numpy import ar

我最近在处理光电发射数据,希望通过将费米函数与高斯函数的卷积拟合到真实数据来估计仪器分辨率。现在我忽略了我还必须有一个背景。 我试着根据我在书中找到的东西做一个分析

不幸的是,我现在陷入困境,恳请您帮助。我提供了一个小例子,即我模拟的数据(通过眼睛判断)实际上是真实数据的良好表示,除了缺少背景外:

import array as ar
import math
from math import e, sqrt, pi
import pylab as plt
from numpy import array, linspace, arange, zeros, ceil, amax, amin, argmax, argmin, abs
from numpy import polyfit, polyval, seterr, trunc, mean
from numpy.linalg import norm
from scipy.interpolate import interp1d
import scipy.optimize
import numpy as np
import matplotlib.pyplot as plt

kb = 8.6173e-5 # Boltzmann k in eV/K


def f(e,scale,T=300,muf=0):
    return scale*(1.0 / (np.exp((-e - muf)/(kb*T)) + 1)) # -e due to binding energy scale

def gaussian(x, mu, sig,scale):
    return scale*(np.exp(-np.power(-x - mu, 2.) / (2 * np.power(sig, 2.))))  # -x due to binding energy scale




Points=10000 # If i change the points the "modelt data" doesn not look good anymore?
espan = np.linspace(-10, 10, Points)


# simulate the fermi edge data such that is close to the read real data
# note that it actually is a convoluiton of a fermi and a gaussian function.
Sim_data = np.random.normal((8.07+np.convolve(f(espan,scale=1.05), gaussian(espan, mu=0, sig=0.3,scale=1.05),mode="same")),10)

# min max norm not ( not used for now )
# Sim_data_norm = ((Sim_data - Sim_data.min()) / (Sim_data.max() - Sim_data.min()))


# convolution
# I know the actual data was meassured at T=300K so i preset this value in the fermi function
# The position of the fermi function and the gaussian should be 0 so mu and muf are set to 0
# i guess x_values would have to be replaced for the x axis of my real data later?
def Gaus_fermi_convolution(size,sigC,scaleC,xC=espan):
    return size* np.convolve(gaussian(x=xC,sig=sigC,scale=scaleC,mu=0), f(e=espan,scale=scaleC,T=300,muf=0), mode="same") 

# try to fit
lowerBounds = [0.0, 0.0,0.0] # A, B, C ,D lower bounds
upperBounds = [440.0, 0.6,440.0] # A, B, C, D upper bounds

popt, pcov = scipy.optimize.curve_fit(Gaus_fermi_convolution, espan, Sim_data,bounds=[lowerBounds, upperBounds])
Opt_size,Opt_sigC,Opt_scaleC = popt

# Print out the coefficients determined by the optimization
print(Opt_size,Opt_sigC,Opt_scaleC)

# Plotting 
plt.plot(espan,Sim_data)
#The result is clearly wrong
plt.plot(espan,Gaus_fermi_convolution(size=Opt_size,sigC=Opt_sigC,scaleC=Opt_scaleC,xC=espan))

plt.xlim([2, -2])
plt.xlabel( r'$Binding \: Energy  \: [eV]$')
plt.ylabel(r'$Intensity\: [arb. u.] $')
plt.show()

两个问题。1) 我发现拟合数据范围和打印数据范围不一样,因为打印X轴限制在-2到2之间。[-2,2]是否也是所需的拟合范围?2) scipy默认初始参数值均为1.0,其中一个边界为0.0到0.6,这是故意的吗?如果我将定义
espan=np.linspace(-10,10,Points)
仅更改为
espan=np.linspace(-2,2,Points)
不知何故,协同进化不会产生一个能够很好地表示我想要实际拟合的数据的结果。我只对实际数据从-2到2的区域拟合感兴趣。如果我理解正确的话,我设定的界为0.6的参数是高斯函数的sigC参数,这是有意的。两个问题。1) 我发现拟合数据范围和打印数据范围不一样,因为打印X轴限制在-2到2之间。[-2,2]是否也是所需的拟合范围?2) scipy默认初始参数值均为1.0,其中一个边界为0.0到0.6,这是故意的吗?如果我将定义
espan=np.linspace(-10,10,Points)
仅更改为
espan=np.linspace(-2,2,Points)
不知何故,协同进化不会产生一个能够很好地表示我想要实际拟合的数据的结果。我只对实际数据从-2到2的区域拟合感兴趣。如果我理解正确的话,我设置的界为0.6的参数是高斯函数的sigC参数,这是有意的。