黃信娥,劉夢禹,狄佳雨,錢磊
(天津科技大學(xué),天津,300452)
光柵衍射不僅是波動光學(xué)的重點內(nèi)容,而且是進一步學(xué)習(xí)激光醫(yī)學(xué)、全息學(xué)、通信學(xué)等專業(yè)領(lǐng)域知識的基礎(chǔ)0,在天文學(xué)、激光器、光通訊、信息存儲、新能源等現(xiàn)代光學(xué)乃至現(xiàn)代物理學(xué)和科學(xué)技術(shù)等諸多領(lǐng)域中具有廣泛的應(yīng)用[2][3]。隨著國家政策對光學(xué)器件產(chǎn)業(yè)的支持,拓展光學(xué)儀器國際市場需求日益強烈。因此,掌握光柵衍射的基本原理對未來的生產(chǎn)實踐以及打破光領(lǐng)域科技壁壘意義非凡。
但光柵衍射的實驗操作不僅需要特定的儀器和場所,實驗現(xiàn)象也會受到許多非相關(guān)因素的影響。隨著計算機的日益普及,計算機仿真技術(shù)作為虛擬實驗已成為認識客觀世界規(guī)律的新型手段[4]。
目前大多數(shù)實驗室選擇的光學(xué)專業(yè)軟件為seelight、zemax 等,其容易受到操作平臺與軟件版本的限制,安裝時不得不考慮兼容性問題;而且大多數(shù)支持自主開發(fā)功能的仿真平臺受語言限制,如MATLAB App Designer 依賴于MATLAB 語言;一些獨立開發(fā)的光學(xué)仿真軟件存在未實現(xiàn)可見光漸變算法、未全面考慮衍射參數(shù)影響等缺陷。
因此針對以上不足,本文提出利用PythonGUI 編程設(shè)計仿真模擬程序,該語言的跨平臺性較高。利用QTDesigner 構(gòu)件程序框架、設(shè)計圖像用戶界面,輕松實現(xiàn)了實驗數(shù)據(jù)的交互式顯示。
在構(gòu)建物理實驗程序時,需要利用Python 的基本語法,調(diào)用PyQt5、Numpy、Matplotlib 等Python 提供的科學(xué)計算庫,以及使用PyQt5 自帶的QtDesigner 編輯器來輔助開發(fā)。
本文利用QtDesigner 進行排版,搭建程序UI 界面,并且自動生成代碼,搭建的程序UI 界面如圖1 所示。

圖1 程序UI 界面
保存該文件將會生成后綴為.ui 的文件,但如需生成后綴為.py的代碼頁,只需在上方工具欄的“窗體”中選擇“View Python Code”,保存即可。
程序界面如圖2 所示,需要創(chuàng)建以下控件并且綁定固定方法實現(xiàn)對應(yīng)交互功能。

圖2 控件類型
(1)按鈕QPushButton
QPushButton 類是用來創(chuàng)建可按壓的按鈕,在程序中用來實現(xiàn)打開新窗口、切換模式等功能。

表1 QPushButton類按鈕及實現(xiàn)效果
(2)標(biāo)簽QLabel
QLabel 類可以顯示讀取文字。

表2 QLabel類標(biāo)簽及實現(xiàn)效果
(3)滾動數(shù)值條QSpinBox
QSpinBox 類用來顯示當(dāng)前參數(shù)數(shù)值,不僅可以輸入值,還可以連續(xù)變化數(shù)值。

表3 QSpinBox類滾動條及實現(xiàn)效果
(4)表盤QDial
QDial 類可以創(chuàng)建一個旋鈕。QDial 和QSpinBox 功能基本一致,語法大體相同,但需要注意,同一個參數(shù)變化時,滾動數(shù)值條和表盤變化需一致,即改變滾動數(shù)值條數(shù)值時,表盤需變化到相應(yīng)數(shù)值;改變表盤數(shù)值時,滾動數(shù)值條也需變化到相應(yīng)數(shù)值。
在MainWindow 窗口類中書寫方法以實現(xiàn)該功能,代碼示例如下:
# 以spinbox 為例配置參數(shù)
self.spinbox_x = QSpinBox(self.centralwidget)
self.spinbox_x.setObjectName(u"spinbox_x")
self.spinbox_x.setMinimum(1)
self.spinbox_x.setMaximum(100)
self.spinbox_x.setSingleStep(1)
self.spinbox_x.setValue(10)
self.spinbox_x.setStyleSheet("background-color:#313034; color:white;border:2px solid" "#423f48;")
當(dāng)表盤數(shù)值改變時,滾動數(shù)值條相應(yīng)改變,并觸發(fā)相關(guān)函數(shù)。
①繪圖窗口MPLWIDGET。
②MPLWIDGET 窗口是自定義的類,利用該類實現(xiàn)用matplotlib 將光柵光譜圖和光強分布圖呈現(xiàn)出來。
③新建代碼頁mplwidget,在各個UI 代碼頁前加上from mplwidget import MPL_WIDGET,代碼如下:
# MPL_WIDGET
class MplCanvas(FigureCanvas):
def __init__(self, dpi=100):
self.fig = Figure(dpi=dpi)
self.ax = self.fig.add_subplot(211) FigureCanvas.__init__(self, self.fig)
FigureCanvas.setSizePolicy(
self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
class MPL_WIDGET(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.canvas = MplCanvas()
self.navi_toolbar=NavigationToolbar(self.canvas, self)
self.navi_toolbar.setStyleSheet("backgroundcolor:white;")
self.vbl = QVBoxLayout()
self.vbl.addWidget(self.canvas)
self.vbl.addWidget(self.navi_toolbar)
self.setLayout(self.vbl)
該仿真模擬程序通過調(diào)用tkinter 庫實現(xiàn)界面交互,點擊主界面的切換按鈕,即可實現(xiàn)“主界面、Dsi&Ssd 界面和狹縫界面”這三種不同功能界面的切換。用戶在仿真不同的實驗時會顯示相應(yīng)的參數(shù)設(shè)置控件,通過直接在交互界面的組合框內(nèi)輸入或通過定位旋鈕設(shè)置參數(shù)范圍內(nèi)的數(shù)值,便可實時動態(tài)地觀測光譜圖或光強分布圖的變化,從而定性分析各個物理量對光柵衍射實驗結(jié)果的影響。
當(dāng)復(fù)色光照射時,不同波長所對應(yīng)顏色的光的同一級亮線,除零級為白光外,其它均不重合,即有色散,此即為光柵的分光原理[5]。
多年來,許多研究者致力于發(fā)展升級實現(xiàn)光柵衍射色散的儀器,陳振宇等人[6]基于RPi 設(shè)計的可見光光譜儀能基本準(zhǔn)確地表現(xiàn)光源的光譜特性,但由于該光譜儀分辨率有限,無法分辨出低壓鈉燈的雙波長。隨著計算機的發(fā)展,許多研究者開始利用仿真實驗?zāi)M分光現(xiàn)象,但大部分作者[7][8]做出的光學(xué)圖像顏色單一,即入射特定波長的光沒有顏色漸變過程,實驗結(jié)果和視覺效果不佳。
本文以汞燈的主要光譜線波長為例,根據(jù)其波長與顏色的映射關(guān)系計算光強,得到衍射條紋[9]。在主界面開發(fā)模擬不同波長的單色光入射和可見光范圍內(nèi)的連續(xù)復(fù)色光入射的功能,輔助研究色散和判斷影響色分辨率的因素。
利用 Python 語言可編寫出如下的可見光顏色漸變仿真程序:
# make_cmap
def cmap(self):
def getRGB(dWave, maxPix=1, gamma=1):
waveArea = [380, 440, 490, 510, 580, 645, 780]
minusWave = [0, 440, 440, 510, 510, 645, 780]
deltWave = [1, 60, 50, 20, 70, 65, 35]
for p in range(len(waveArea)):
if dWave < waveArea[p]: break
pVar = abs(minusWave[p] - dWave) / deltWave[p]
rgbs = [[0, 0, 0], [pVar, 0, 1], [0, pVar, 1], [0, 1, pVar],[pVar, 1, 0], [1, pVar, 0], [1, 0, 0], [0, 0, 0]]
if (dWave >= 380) & (dWave < 420):
alpha = 0.3 + 0.7 * (dWave - 380) / (420 - 380)
elif (dWave >= 420) & (dWave < 701):
alpha = 1.0
elif (dWave >= 701) & (dWave < 780):
alpha = 0.3 + 0.7 * (780 - dWave) / (780 - 700)
else:
alpha = 0
return [maxPix * (c * alpha) ** gamma for c in rgbs[p]]
def drawSpec():
pic = zeros([1, 361, 3])
rgb = [getRGB(d) for d in range(400, 761)]
pic = (pic + rgb)
plt.imshow(pic, aspect='auto')
plt.yticks([])
# plt.tick_params(axis='x',colors='w')
plt.xticks(range(0, 361, 50), ['400', '450', '500', '550', '600', '650', '700', '750'])
return pic
pic = drawSpec()
cdict = pic[0]
proj = dict()
for i in range(400, 761):
proj[i] = cdict[i - 400]
return proj
若把可調(diào)參數(shù)設(shè)置為狹縫總數(shù)N=10,遮光寬度b=15μm,透光寬度a=5μm,透鏡焦距f=40mm,分別仿真“入射波長為579nm 的單色光、同時入射波長為708nm 和579nm 的離散復(fù)色光、入射可見光范圍內(nèi)的連續(xù)復(fù)色光”實驗,運行程序,即可得出如圖 3(a)~(b)所示的可見光顏色漸變仿真實驗結(jié)果。

圖 3 (a-b)見光顏色漸變仿真實驗結(jié)果
光柵是由大量等寬等間距的平行狹縫構(gòu)成的具有納米
光柵衍射強度分布公式為:
其中,I0為單縫衍射零級處的衍射光強,
根據(jù)以上公式算法,利用 Python 語言可編寫出如下的仿真程序:
# 入射光數(shù)量
self.lamda = self.spinbox_l.value() * 1.E-6
# 透光寬度a um
self.a = self.spinbox_a.value() * 1.E-3
# 遮光寬度b um
# 屏幕寬度
self.s = self.spinbox_x.value()
# 狹縫數(shù)N
self.N = self.spinbox_n.value()
# 焦距f
self.f = 40
# 遮光寬度b um
self.b = self.spinbox_d.value() * 1.E-3
# 光柵常數(shù) nm
self.d = (self.a + self.b)
"'邏輯計算"'
self.x = np.round(linspace(-self.s, self.s, 1000 * self.s), 3)
self.u = ((pi * self.a) / self.lamda) * (self.x / ((self.x ** 2 + self.f ** 2) ** 0.5))
self.I = (((sin(self.u) / self.u) ** 2) * ((sin(self.d * self.u * self.N / self.a) /
sin(self.d * self.u / self.a)) ** 2))
下面利用該程序從波長,狹縫總數(shù),透光寬度,遮光寬度和缺級現(xiàn)象這5 個角度對光強分布和譜線特征進行全面地模擬仿真。
2.2.1 波長λ 對光柵衍射實驗結(jié)果的影響
實驗給定狹縫總數(shù)N=10,透光寬度a=5μm,遮光寬度b=15μm,圖樣寬度為10nm,透鏡焦距f=40mm,改變參數(shù)數(shù)值,使得依次入射波長為434nm,577nm,708nm的單色光。實驗結(jié)果如圖4 所示。

圖4 不同波長的光柵衍射圖樣
實驗結(jié)果為:光波長越長,各級條紋間距越寬,主(次)極大的半角寬度也越大。
2.2.2 狹縫總數(shù)對光柵衍射實驗結(jié)果的影響
實驗給定波長λ=546nm,透光寬度a=5μm,遮光寬度b=15μm,圖樣寬度為10nm,透鏡焦距f=40mm,改變狹縫總數(shù),使得狹縫數(shù)目N=1,N=2,N=6,N=20。實驗結(jié)果如圖5 所示。

圖5 不同狹縫總數(shù)的光柵衍射圖樣
實驗結(jié)果為:當(dāng)狹縫數(shù)目為1 時,形成單縫衍射;當(dāng)狹縫數(shù)目為2 時,形成雙縫干涉。狹縫數(shù)目越多,主極大亮線的半角寬度越小,且銳度越大。次極大線寬和亮度變小。
2.2.3 透光寬度對光柵衍射實驗結(jié)果的影響
實驗給定狹縫總數(shù)N=10,波長λ=546nm,遮光寬度b=15μm,圖樣寬度為10nm,透鏡焦距f=40mm,改變透光寬度參數(shù)數(shù)值,使得透光寬度a=3μm,a=5μm,a=11μm。實驗結(jié)果如圖6 所示。

圖6 不同透光寬度的光柵衍射圖樣
實驗結(jié)果為:隨著各透光寬度a 的增加,中央明紋寬度減小,但并不改變明條紋所在位置,衍射效應(yīng)變?nèi)酢?/p>
2.2.4 遮光寬度對光柵衍射實驗結(jié)果的影響
遮光寬度的大小與會直接影響到單縫衍射因子的變化,對多光束干涉條紋的強度起到了重要的調(diào)制作用。實驗給定狹縫總數(shù)N=10,波長λ=607nm,透光寬度a=5μm,圖樣寬度為10nm,透鏡焦距f=40mm,改變遮光寬度參數(shù)數(shù)值,使得遮光寬度b=5μm,b=15μm,b=18μm。實驗結(jié)果如圖7 所示。

圖7 不同遮光寬度的光柵衍射圖樣
實驗結(jié)果為:隨著各縫寬b 的增加,主極大的位置、半角寬度及主極大條紋的間距沒有發(fā)生變化,但是主極大的光強度逐漸降低。
2.2.5 缺級現(xiàn)象
當(dāng)在θ 角位置既滿足干涉明條紋條件,也滿足單縫衍射暗紋條件時,出現(xiàn)光強度為零的“干涉加強”,此現(xiàn)象即為缺級現(xiàn)象[13]。實驗給定狹縫總數(shù)N=10,波長λ=607nm,圖樣寬度為15nm,透鏡焦距f=40mm。改變透光寬度和遮光寬度數(shù)值,使得光柵常數(shù)與透光寬度的比值為d/a=3,d/a=4,d/a=5。實驗結(jié)果如圖8 所示。

圖8 缺級現(xiàn)象
實驗結(jié)果為:圖8(a)的缺級現(xiàn)象出現(xiàn)在k 為3 的整數(shù)倍位置;圖8(b)的缺級現(xiàn)象出現(xiàn)在k 為4 的整數(shù)倍位置;圖8(c)的缺級現(xiàn)象出現(xiàn)在k 為5 的整數(shù)倍位置。
光柵衍射是縫間干涉和單縫衍射的綜合效應(yīng)[14]。因此,程序設(shè)計了“Dsi&Ssd 界面”來展示基于在主界面操作下的光柵衍射實驗條件的單縫衍射因子和縫間干涉因子的相對光強圖。
利用 Python 語言可編寫出如下的單縫衍射和縫間干涉仿真程序:
lamda = self.lamda
a = self.a
s = self.s
f = self.f
b = self.b
d = self.d
N = self.N
x = np.round(linspace(-s, s, 1000 * s), 3)
# 繪圖
mpl2d = self.View_2.canvas
mpl2d.fig.clear()
mpl2d.fig.patch.set_facecolor('k')
"""邏輯計算"""
# 單縫衍射
u = ((pi * a) / lamda) * (x / ((x ** 2 + f ** 2) ** 0.5))
I_diff = (sin(u) / u)
** 2
# 多光干涉
A_x = 0
A_y = 0
for i in range(1, N):
A_x += cos((i - 1) * 2 * pi * d * (x / (f ** 2 + x ** 2) ** 0.5) / lamda)
A_y += sin((i - 1) * 2 * pi * d * (x / (f ** 2 + x ** 2) ** 0.5) / lamda)
I_int = A_x ** 2 + A_y ** 2
# 總光強
I = I_int * I_diff
# 單縫衍射
self.fig_1 = mpl2d.fig.add_subplot(2, 1, 1)
# self.fig_1.set_alpha(0.5)
self.fig_1.spines['right'].set_color('white')
self.fig_1.spines['top'].set_color('white')
self.fig_1.spines['bottom'].set_color('white')
self.fig_1.spines['left'].set_color('white')
self.fig_1.set_facecolor((37/255, 36/255, 36/255))
self.fig_1.plot(x, I_diff,color='w')
self.fig_1.set_xticks([])
self.fig_1.tick_params(axis='x', colors='w')
self.fig_1.tick_params(axis='y', colors='w')
# 縫間干涉
self.fig_2 = mpl2d.fig.add_subplot(2, 1, 2)
self.fig_2.set_facecolor((37/255, 36/255, 36/255))
self.fig_2.plot(x, I_int, color='w')
self.fig_2.spines['right'].set_color('white')
self.fig_2.spines['top'].set_color('white')
self.fig_2.spines['bottom'].set_color('white')
self.fig_2.spines['left'].set_color('white')
self.fig_2.tick_params(axis='x', colors='w')
self.fig_2.tick_params(axis='y', colors='w')
若在主界面把可調(diào)參設(shè)置為 N=10,b=15μm,a=5μm,λ=579nm,運行程序,模擬光柵衍射實驗。點擊“Dsi&Ssd”按鈕,切換界面,即可得到該實驗條件下如圖9 所示的單縫衍射因子和縫間干涉因子的相對光強圖。

圖9 單縫衍射因子和縫間干涉因子的相對光強圖
有研究表明有意改變光柵的刻槽間距(即選擇性地遮擋狹縫)和曲率以及基底面形,能提高光柵的分辨力和改善光學(xué)系統(tǒng)的成像的特性,并能節(jié)省輔助透鏡、減少雜散光、增加出射光強和提高光學(xué)系統(tǒng)的性能,使光路更為簡便[15~16]。因此程序在探究光柵狹縫總數(shù)對衍射圖樣影響的基礎(chǔ)上,設(shè)計了“探究遮擋不同位置的狹縫時對透射光強的影響”,為選擇性地遮擋狹縫提供實驗手段。
該實驗分為無規(guī)律遮擋和有規(guī)律遮擋兩大類。無規(guī)律遮擋包括隨機分布30%、隨機分布50%、隨機分布70%;有規(guī)律遮擋包括滿足間隙分布和斐波那契分布。通過對比遮擋前后的光強分布圖,可探究遮擋不同位置時狹縫對透射光強的影響。
該部分采用振幅矢量法和圖解法來完成光強分布的計算。如圖10 與圖11 所示,A1為在P 點產(chǎn)生的、振幅為A1和初相位為α的振幅矢量。假設(shè)各次波(Ai)到達P 點都有相同的振幅A,令A(yù)=1,相應(yīng)的相位差以第一條光所在的方向為x 軸正方向建立坐標(biāo)系,則第i 條光在x 方向的分量為:

圖10 光柵衍射原理圖

圖11 振幅矢量法
則第i 條光在y 方向的分量為:
光在x 方向和y 方向的分量之和分別為:
多光干涉光強為:
加入衍射的影響后光強為:
基于上述原理開發(fā)“狹縫界面”——“遮擋不同位置的狹縫對透射光強的影響”創(chuàng)新實驗,利用 Python 語言可編寫出如下仿真程序:
# 遮擋
A_xs = A_x
A_ys = A_y
if len(self.idset) != 0:
for i in self.idset:
i = 2 * i if i > 0 else -2 * i + 1
A_xs -= cos((i - 1)*2*pi*d*(x/(f**2+x**2)**0.5)/lamda)
A_ys -=sin((i-1)*2*pi*d*(x/(f**2+x**2)**0.5)/lamda)
I_ints = A_xs**2+A_ys**2
I_s=np.round(I_ints*I_diff, 3)
self.fig_2=mpl2d.fig.add_subplot(2, 1, 2)
self.fig_2.set_facecolor((37/255, 36/255, 36/255))
self.fig_2.plot(x, I_s,color='w')
self.fig_2.axis([-s, s, -1, 1.1*max(I)])
self.fig_2.spines['right'].set_color('white')
self.fig_2.spines['top'].set_color('white')
self.fig_2.spines['bottom'].set_color('white')
self.fig_2.spines['left'].set_color('white')
self.fig_2.tick_params(axis='x', colors='w')
self.fig_2.tick_params(axis='y', colors='w')
通過改變狹縫總數(shù)以及遮擋規(guī)律,可得到如圖12 所示的不同光強分布圖。

圖12 遮擋不同位置狹縫對透射光強的影響
應(yīng)用該理論的聚焦和消像差性能對核心色散元件和聚焦元件的制作和研究具有一定的指導(dǎo)意義[17],并且在未來的空間光譜儀、等離子體診斷、同步輻射單色儀、光纖通信等領(lǐng)域的生產(chǎn)實踐中具有其獨特的應(yīng)用價值[18~19]。
作為一款基于C/S 架構(gòu)模式的軟件,PythonGUI 能良好地運行于多平臺中,如Unix、Windows 和Macintosh等等,程序最終通過軟件包安裝的方式集成到桌面上[20],具有操作容易、計算功能強大以及無延遲反應(yīng)等優(yōu)勢,有助于解決疫情背景下實驗條件受限的問題;該程序包含了較為完善的光柵衍射仿真模擬體系,有助于加強用戶對光柵衍射知識的理解,培養(yǎng)了自主研究的綜合創(chuàng)新能力,為推進創(chuàng)新實驗的設(shè)計開辟了新路徑。