Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

拟合双曲线测试

110 views
ubuntu2204
Kernel: Python 3 (system-wide)

zx

import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit from matplotlib import rc from mpl_toolkits.axes_grid1.inset_locator import inset_axes from mpl_toolkits.axes_grid1.inset_locator import mark_inset # Enable LaTeX and set font to Times New Roman rc('text', usetex=True) rc('font', family='serif') rc('font', serif='Times New Roman') rc('font', size=14) # 数据 data = np.array([[162, 0.58, 0.53, 0.65, 0.60], [164, 0.58, 0.53, 0.65, 0.58], [167, 0.60, 0.53, 0.68, 0.62], [170, 0.60, 0.56, 0.66, 0.63], [174, 0.60, 0.58, 0.66, 0.64], [177, 0.62, 0.60, 0.67, 0.65], [180, 0.67, 0.62, 0.67, 0.66], [183, 0.72, 0.62, 0.69, 0.60]]) # 定义双曲线方程 def hyperbola(x, a, b, h): return a * np.sqrt(b**2 + (x - h)**2) # 初始参数估计 initial_guess = (1, 1, 270) # 使用 curve_fit 进行拟合 params, covariance = curve_fit(hyperbola, data[:, 0], 0.5*data[:, 1], p0=initial_guess) # 拟合结果 a, b, h = params print(params) print(h,b**2) print() print('束腰位置',h) print('发散角',np.arctan(a)) print('腰斑半径',a*b) print('乘积',4*a*b*a) # 绘制拟合结果和原始数据 x_range = np.linspace(0, 320, 100) fig, axs = plt.subplots(1, 1, figsize=(12, 5), dpi=150) # 小图 axins = axs.inset_axes((0.06,0.4,0.22,0.22)) axins.scatter(data[:, 0], 0.5*data[:, 2], label='Data',s=30) axins.plot(x_range, hyperbola(x_range, a, b, h), 'r', label='Fit') axins.set_xlim(160, 190) axins.set_ylim(0.2, 0.6) # 大图 axs.plot(x_range, hyperbola(x_range, a, b, h), 'r', label=r'Fit') axs.plot(x_range, -hyperbola(x_range, a, b, h), 'r', label='') axs.scatter(data[:, 0], 0.5*data[:, 1], label='Data', s=30) axs.plot(x_range, a*(x_range-h),'g',ls='--', lw=1) axs.plot(x_range,-a*(x_range-h),'g',ls='--', lw=1) # axs.set_xticks(np.linspace(0,250,11)) # axs.set_xlim(-10, 290) # axs.set_ylim(-0.8, 0.8) axs.set_xlabel('$z$(cm)') axs.set_ylabel('$y$(mm)') axs.legend() # plt.savefig('plot/fit.pdf') plt.show()
[1.20607137e-02 2.40848075e+01 1.66143792e+02] 166.14379201010706 580.0779500771101 束腰位置 166.14379201010706 发散角 0.01206012891463003 腰斑半径 0.29047996602945286 乘积 0.014013582766151755
Image in a Jupyter notebook

拟合双曲线 zy

import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit from matplotlib import rc from mpl_toolkits.axes_grid1.inset_locator import inset_axes from mpl_toolkits.axes_grid1.inset_locator import mark_inset # Enable LaTeX and set font to Times New Roman rc('text', usetex=True) rc('font', family='serif') rc('font', serif='Times New Roman') rc('font', size=14) # 数据 data = np.array([[162, 0.58, 0.53, 0.65, 0.60], [164, 0.58, 0.53, 0.65, 0.58], [167, 0.60, 0.53, 0.68, 0.62], [170, 0.60, 0.56, 0.66, 0.63], [174, 0.60, 0.58, 0.66, 0.64], [177, 0.62, 0.60, 0.67, 0.65], [180, 0.67, 0.62, 0.67, 0.66], [183, 0.72, 0.62, 0.69, 0.60]]) # 定义双曲线方程 def hyperbola(x, a, b, h): return a * np.sqrt(b**2 + (x - h)**2) # 初始参数估计 initial_guess = (1, 1, 170) # 使用 curve_fit 进行拟合 params, covariance = curve_fit(hyperbola, data[:, 0], 0.5 * data[:, 2], p0=initial_guess) # 拟合结果 a, b, h = params print(params) print(h, b**2) print() print('束腰位置', h) print('发散角', np.arctan(a)) print('腰斑半径', a * b) print('乘积', 4 * a * b * a) # 绘制拟合结果和原始数据 x_range = np.linspace(0, 280, 100) fig, axs = plt.subplots(1, 1, figsize=(12, 5), dpi=150) # 小图 axins = axs.inset_axes((0.06, 0.4, 0.22, 0.22)) axins.scatter(data[:, 0], 0.5 * data[:, 2], label='Data', s=30) axins.plot(x_range, hyperbola(x_range, a, b, h), 'r', label='Fit') axins.set_xlim(160, 190) axins.set_ylim(0.2, 0.6) # 大图 axs.plot(x_range, hyperbola(x_range, a, b, h), 'r', label=r'Fit') axs.plot(x_range, -hyperbola(x_range, a, b, h), 'r', label='') axs.scatter(data[:, 0], 0.5 * data[:, 2], label='Data', s=30) axs.plot(x_range, a * (x_range - h), 'g', ls='--', lw=1) axs.plot(x_range, -a * (x_range - h), 'g', ls='--', lw=1) axs.set_xticks(np.linspace(0, 250, 11)) axs.set_xlim(-10, 290) axs.set_ylim(-0.8, 0.8) axs.set_xlabel('$z$(cm)') axs.set_ylabel('$y$(mm)') axs.legend() # plt.savefig('plot/fit.pdf') plt.show()
[4.45632506e-03 5.24602268e+01 1.35771435e+02] 135.77143472830133 2752.075400454776 束腰位置 135.77143472830133 发散角 0.004456295559258453 腰斑半径 0.23377982343272427 乘积 0.00416719554091469
Image in a Jupyter notebook

现在计算另一组e2e^{-2} 的拟合

zy

import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit from matplotlib import rc from mpl_toolkits.axes_grid1.inset_locator import inset_axes from mpl_toolkits.axes_grid1.inset_locator import mark_inset # Enable LaTeX and set font to Times New Roman rc('text', usetex=True) rc('font', family='serif') rc('font', serif='Times New Roman') rc('font', size=14) # 数据 data = np.array([[162, 0.58, 0.53, 0.65, 0.60], [164, 0.58, 0.53, 0.65, 0.58], [167, 0.60, 0.53, 0.68, 0.62], [170, 0.60, 0.56, 0.66, 0.63], [174, 0.60, 0.58, 0.66, 0.64], [177, 0.62, 0.60, 0.67, 0.65], [180, 0.67, 0.62, 0.67, 0.66] # [183, 0.72, 0.62, 0.69, 0.60] ]) # 定义双曲线方程 def hyperbola(x, a, b, h): return a * np.sqrt(b**2 + (x - h)**2) # 初始参数估计 initial_guess = (1, 1, 200) # 使用 curve_fit 进行拟合 params, covariance = curve_fit(hyperbola, data[:, 0], 0.5*data[:, 4], p0=initial_guess) # 拟合结果 a, b, h = params print(params) print(h,b**2) print() print('束腰位置',h) print('发散角',np.arctan(a)) print('腰斑半径',abs(a*b)) print('乘积',4*a*b*a) # 绘制拟合结果和原始数据 x_range = np.linspace(-310, 115, 100) fig, axs = plt.subplots(1, 1, figsize=(14, 5), dpi=150) # # 小图 # axins = axs.inset_axes((0.06,0.4,0.22,0.22)) # axins.scatter(data[:, 0], 0.5*data[:, 4], label='Data',s=30) # axins.plot(x_range, hyperbola(x_range, a, b, h), 'r', label='Fit') # axins.set_xlim(160, 190) # axins.set_ylim(0.2, 0.6) # 大图 axs.plot(x_range, hyperbola(x_range, a, b, h), 'r', label=r'$y=(%f)\sqrt{(%f)^2+(x - %f)^2}$' % (a, b, h)) axs.plot(x_range, -hyperbola(x_range, a, b, h), 'r', label='') # axs.scatter(data[:, 0], 0.5*data[:, 4], label='Data', s=30) axs.plot(x_range, a*(x_range-h),'g',ls='--', lw=1,label='asymptotic line') axs.plot(x_range,-a*(x_range-h),'g',ls='--', lw=1) # axs.set_xticks(np.linspace(0,250,11)) # axs.set_xlim(-10, 290) # axs.set_ylim(-0.8, 0.8) axs.set_xlabel('$z$(cm)') axs.set_ylabel('$y$(mm)') axs.legend() # plt.savefig('plot/fit.pdf') plt.show()
[1.96390132e-03 1.11522685e-01 1.12675876e+01] 11.267587594685258 0.01243730922969959 束腰位置 11.267587594685258 发散角 0.001963898790815637 腰斑半径 0.0002190195474474025 乘积 1.7205311095595984e-06
Image in a Jupyter notebook

zx

import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit from matplotlib import rc from mpl_toolkits.axes_grid1.inset_locator import inset_axes from mpl_toolkits.axes_grid1.inset_locator import mark_inset # Enable LaTeX and set font to Times New Roman rc('text', usetex=True) rc('font', family='serif') rc('font', serif='Times New Roman') rc('font', size=14) # 数据 data = np.array([[162, 0.58, 0.53, 0.65, 0.60], [164, 0.58, 0.53, 0.65, 0.58], [167, 0.60, 0.53, 0.68, 0.62], [170, 0.60, 0.56, 0.66, 0.63], [174, 0.60, 0.58, 0.66, 0.64], [177, 0.62, 0.60, 0.67, 0.65], [180, 0.67, 0.62, 0.67, 0.66], [183, 0.72, 0.62, 0.69, 0.60] ]) # 定义双曲线方程 def hyperbola(x, a, b, h): return a * np.sqrt(b**2 + (x - h)**2) # 初始参数估计 initial_guess = (1, 1, 170) # 使用 curve_fit 进行拟合 params, covariance = curve_fit(hyperbola, data[:, 0], 0.5*data[:, 3], p0=initial_guess) # 拟合结果 a, b, h = params print(params) print(h,b**2) print() print('束腰位置',h) print('发散角',np.arctan(a)) print('腰斑半径',a*b) print('乘积',4*a*b*a) # 绘制拟合结果和原始数据 x_range = np.linspace(0, 320, 100) fig, axs = plt.subplots(1, 1, figsize=(14, 5), dpi=150) # 小图 axins = axs.inset_axes((0.06,0.4,0.22,0.22)) axins.scatter(data[:, 0], 0.5*data[:, 3], label='Data',s=30) axins.plot(x_range, hyperbola(x_range, a, b, h), 'r', label='Fit') axins.set_xlim(160, 190) axins.set_ylim(0.2, 0.6) # 大图 axs.plot(x_range, hyperbola(x_range, a, b, h), 'r', label=r'$y=(%.4f)\sqrt{(%.2f)^2+(x - %.2f)^2}$' % (a, b, h)) axs.plot(x_range, -hyperbola(x_range, a, b, h), 'r', label='') axs.scatter(data[:, 0], 0.5*data[:, 3], label='Data', s=30) axs.plot(x_range, a*(x_range-h),'g',ls='--', lw=1,label='asymptotic line') axs.plot(x_range,-a*(x_range-h),'g',ls='--', lw=1) # axs.set_xticks(np.linspace(0,250,11)) # axs.set_xlim(-10, 290) # axs.set_ylim(-0.8, 0.8) axs.set_xlabel('$z$(cm)') axs.set_ylabel('$y$(mm)') axs.legend() # plt.savefig('plot/fit.pdf') plt.show()
[3.42026929e-03 9.53722416e+01 1.53647414e+02] 153.64741408003593 9095.86447601708 束腰位置 153.64741408003593 发散角 0.003420255957231344 腰斑半径 0.32619874960913886 乘积 0.004462750268357089
Image in a Jupyter notebook

总结一下

结果是这样的

0.1zx0.1zyexp(-2)zxexp(-2)zy
束腰位置166.14379321744875135.77143472830133153.64741408003593-149.50041250213079
半发散角0.0120601294578501980.0044562955592584530.0034202559572313440.0009677407307937164
腰斑半径0.290479967671804340.233779823432724270.326198749609138860.00043790568567500304
发散角和腰斑的乘积0.0140135834766535960.004167195540914690.0044627502683570891.6951172022670231e-6
  1. 四种方式,两个zox面算得的束腰位置较为接近,两个zoy平面计算结果相去甚远。

  2. 从乘积上看,两种计算结果应该是一个数量级

  3. 现在将两个yoz平面画到一张图上

import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit from matplotlib import rc from mpl_toolkits.axes_grid1.inset_locator import inset_axes from mpl_toolkits.axes_grid1.inset_locator import mark_inset # Enable LaTeX and set font to Times New Roman rc('text', usetex=True) rc('font', family='serif') rc('font', serif='Times New Roman') rc('font', size=14) # 数据 data = np.array([[162, 0.58, 0.53, 0.65, 0.60], [164, 0.58, 0.53, 0.65, 0.58], [167, 0.60, 0.53, 0.68, 0.62], [170, 0.60, 0.56, 0.66, 0.63], [174, 0.60, 0.58, 0.66, 0.64], [177, 0.62, 0.60, 0.67, 0.65], [180, 0.67, 0.62, 0.67, 0.66], [183, 0.72, 0.62, 0.69, 0.60] ]) z = data[:, 0] x1 = data[:, 1] y1 = data[:, 2] x2 = data[:, 3] y2 = data[:, 4] # 定义双曲线方程 hyperbola = lambda x, a, b, h : a * np.sqrt(b**2 + (x-h)**2) # 初始参数估计 initial_guess = (1, 1, 170) # 使用 curve_fit 进行拟合 params, covariance = curve_fit(hyperbola, data[:, 0], 0.5*data[:, 3], p0=initial_guess) # 拟合结果 a, b, h = params print(params) print(h,b**2) print() print('束腰位置',h) print('发散角',np.arctan(a)) print('腰斑半径',a*b) print('乘积',4*a*b*a) # 绘制拟合结果和原始数据 x_range = np.linspace(0, 320, 100) fig, axs = plt.subplots(1, 1, figsize=(14, 5), dpi=150) # # 小图 # axins = axs.inset_axes((0.06,0.4,0.22,0.22)) # axins.scatter(data[:, 0], 0.5*data[:, 3], label='Data',s=30) # axins.plot(x_range, hyperbola(x_range, a, b, h), 'r', label='Fit') # axins.set_xlim(160, 190) # axins.set_ylim(0.2, 0.6) # 大图 axs.plot(x_range, hyperbola(x_range, a, b, h), 'r', label=r'$y=(%.4f)\sqrt{(%.2f)^2+(x - %.2f)^2}$' % (a, b, h)) axs.plot(x_range, -hyperbola(x_range, a, b, h), 'r', label='') axs.scatter(data[:, 0], 0.5*data[:, 3], label='Data', s=30) axs.plot(x_range, a*(x_range-h),'g',ls='--', lw=1,label='asymptotic line') axs.plot(x_range,-a*(x_range-h),'g',ls='--', lw=1) # axs.set_xticks(np.linspace(0,250,11)) # axs.set_xlim(-10, 290) # axs.set_ylim(-0.8, 0.8) axs.set_xlabel('$z$(cm)') axs.set_ylabel('$y$(mm)') axs.legend() # plt.savefig('plot/fit.pdf') plt.show()
[3.42026929e-03 9.53722416e+01 1.53647414e+02] 153.64741408003593 9095.86447601708 束腰位置 153.64741408003593 发散角 0.003420255957231344 腰斑半径 0.32619874960913886 乘积 0.004462750268357089
Image in a Jupyter notebook