| |
from scipy.optimize import curve_fit # 在拟合时需要此函数库
import numpy as np
import matplotlib.pylab as plt
from math import *
plt.close('all')
然后读取数据并作图,本例中使用的横坐标数据为L,纵坐标数据为P
filename = 'coupler_2D_couplingLength.txt'
L = []
P = []
with open(filename, 'r') as file_to_read:
while True:
lines = file_to_read.readline()
if not lines:
break
pass
L_tmp, P_tmp = [float(i) for i in lines.split()]
L.append(L_tmp)
P.append(P_tmp)
pass
L = np.array(L)
P = np.array(P)
fig = plt.figure(figsize=(3.2,2.8))
plt.plot(L, P, linewidth = 2)
#plt.legend(fontsize = 'xx-small')
plt.xlabel('Waveguide length ($\mu m$)', fontsize = 12)
plt.ylabel('Normalized Power', fontsize = 12)
plt.title('Original input', fontsize = 12)
plt.rc('xtick', labelsize = 9)
plt.rc('ytick', labelsize = 9)
plt.tight_layout()
plt.show()
原始数据的图形如下:
下面对数据进行拟合,以得到精确的振幅,频率,相位和常数项。我们定义目标函数是sine函数:
# 定义希望拟合的函数类型
def fitSine(x, A, f, phi, c):
return A*np.cos(2*pi*f*x+phi) + c
# 进行拟合
fit_opt, fit_cov = curve_fit(fitSine, L, P)
# 提取拟合数据
coe_A = fit_opt[0]
coe_f = fit_opt[1]
coe_phi = fit_opt[2]
coe_c = fit_opt[3]
fitted_P = fitSine(L, coe_A, coe_f, coe_phi, coe_c)
# 作图
fig = plt.figure(figsize=(3.2,2.8))
plt.plot(L, fitted_P, linewidth = 2)
#plt.legend(fontsize = 'xx-small')
plt.xlabel('Waveguide length ($\mu m$)', fontsize = 12)
plt.ylabel('Normalized Power', fontsize = 12)
plt.title('Fitted curve', fontsize = 12)
plt.rc('xtick', labelsize = 9)
plt.rc('ytick', labelsize = 9)
plt.tight_layout()
plt.show()
得到的图像如下:
显然拟合的图像和原图相差甚远,这主要是因为默认的初始值没有选好。为了解决这个问题,我们可以手动输入初始值以提高精度。
对源代码进行如下修改:
A_g = input('Estimated amplitude: ')
f_g = input('Estimated frequency: ')
phi_g = input('Estimated phase: ')
c_g = input('Estimated offset: ')
a_guess = [A_g,f_g,phi_g, c_g]
fit_opt, fit_cov = curve_fit(fitSine, L, P,p0=a_guess)
在程序运行时,终端会提示输入估计值,假设我们采用以下估计值:
a_g = 0.5
f_g = 3e-3
phi_g = 0
c_g = 0.5
得到的图像如下:
拟合得到的数据如下:
A = 0.499733913
f = 0.00287385
phi = -2.60167e-7
c = 0.4999
经过初始值预测后的拟合就准确了很多。
参考资料: https://faculty1.coloradocollege.edu/~sburns/toolbox/DataFitting.html