初学者正在尝试使用python去拟合一组单波长的瞬态吸收数据,但是拟合的结果非常不好,不知道是因为设置的参数不对,还是因为卷积的方法不对,还是代码的运行逻辑就有问题。
拟合的方程式是(一个高斯型的仪器响应函数IRt(t)卷积一个动力学方程),动力学方程是由四个单指数衰减+最后平台的方程:
我写的高斯函数和动力学的形式是:
使用的公式是跟书上来的:
其中每个小写的字母是对应的时间,最后D是常数,所以我将时间改成无穷大,我的代码如下:
import numpy as np
import pandas as pd
from scipy import interpolate
import pylab as pl
from scipy.signal import convolve
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
from scipy.special import erf
#得到矩阵 (输出矩阵无问题)
def load_csv(path):
data_read = pd.read_csv(path)
list = data_read.values.tolist()
data = np.array(list)
print(data.shape)
# print(data)
return data
def move_last_column_to_first(arr):
reversed_arr = [row[::-1] for row in arr]
A = [row[-1] for row in reversed_arr]
reversed_arr = np.delete(reversed_arr,[-1],1)
reversed_arr = np.insert(reversed_arr, 0, A, axis=1)
return reversed_arr
mat1 = np.array(move_last_column_to_first(load_csv("E:\\Data\\PY101\\PY101 mat\\3000 640pr.csv")))
row, column = np.shape(mat1)
def normalization(arr):
for i in range (1,row):
a = np.max(arr[i,1:])
for j in range(1,column):
arr[i,j]/=a
#定义函数
def Convolution_solo(t, u, sigma, a, A):
y1 = 0.5 * np.exp(-(1/a)*(t-u-0.5*(1/a)*sigma**2))
y2 = 1 + erf((t-(u+(1/a)*sigma**2))/(2**0.5))
return A * y1 * y2
def Convolution_Exp3(t, Amplitude, u, sigma, A, a, B, b, C, c, D, d):
y1 = Convolution_solo(t, u, sigma, a, A)
y2 = Convolution_solo(t, u, sigma, b, B)
y3 = Convolution_solo(t, u, sigma, c, C)
y4 = Convolution_solo(t, u, sigma, d, D)
return Amplitude * (y1 + y2 + y3 + y4)
def Gaussian(t, Amplitude, u,sigma):
y = Amplitude*np.exp(-np.power(t - u, 2) / (2 * np.power(sigma, 2)))
return y
time = mat1[0, 1:]#时间点
a1 = mat1[1, 1:] #-8.5
weights = [0.00000001 for i in a1]
# 设置初始参数 p0
values = np.array(load_csv("E:\Data\PY101\para\para6.csv"))
bounds = np.delete(values, 1, axis=0)
# 使用 curve_fit 进行数据拟合
popt, pcov = curve_fit(Convolution_Exp3, time, a1, p0 = values[1,:], maxfev=10000, sigma = weights, absolute_sigma=True, bounds=bounds)
print(popt)
bounds_2 = np.insert(values, 3, popt, axis=0)
pd.DataFrame(bounds_2).to_csv('E:\Data\PY101\para\\final6.csv')
Amplitude, u, sigma, A, a, B, b, C, c, D, d = popt[0],popt[1],popt[2], popt[3], popt[4], popt[5], popt[6], popt[7], popt[8], popt[9], popt[10]
y = Convolution_Exp3(time, Amplitude, u, sigma, A, a, B, b, C, c, D, d)
y1 = Gaussian(time, Amplitude, u, sigma)
plt.scatter(time, a1, marker='o',label='real', color='blue')
plt.scatter(time, y ,marker='o',label='curve_fit', color='green')
plt.scatter(time, y1 ,marker='^',label='Gaussian', color='red')
plt.legend()
plt.show()
给出的valus如下:(1:min,2:initial;3:max;4:实验给出的值)
u | sigma | A | a | B | b | C | c | D | d |
-0.5 | 0.04 | 0 | 0.01 | 0 | 3 | 0 | 110 | -1 | 100000.1 |
0.1 | 0.05 | 2 | 0.1 | 1 | 10 | 1 | 401.587 | 0.16 | 100000.2 |
0.5 | 0.2 | 5 | 0.3 | 5 | 60 | 5 | 500 | 1 | 100000.3 |
0.084196 | 0.2 | 1.57E-06 | 0.198219 | 0.482104 | 3 | 0.260399 | 135.1791 | 0.17248 | 100000.3 |
1.已经知道sigma的值一般是不会大于0.2ps的,如果大于说明仪器响应函数要大于0.2*2.3~400fs这是不可能的
拟合结果如下:
主要是最前面哪个蓝线的尖尖应该是一个很快的动力学,但是好像拟合到gaussian数据里头了,最快的大概只有100fs左右的动力学好像没有拟合上,我的代码是哪里出问题了么?还是我对curve_fit函数使用方法不正确,我也有考虑将gaussian加上一个Amplitude参数来控制大小会不会好一点呢,求助ww