利用Python实现光栅光谱仪测原子光谱实验仿真

        PASCO的实体实验效果不是很理想,和仿真差别还挺大的,可惜时间不太够没有深究实体实验不成功的原因(下图为实体实验结果图,氦的原子光谱,标注的是红外光)。

        

        实验仿真程序原理其实和迈克尔逊干涉仪的仿真差别不大,其中做了一些适当的简化,并不影响最后的实验结果:认为总光强是不同波长的光衍射后光强的叠加;不同波长的光入射前光强相等(其实是我没有查到相关数据。。。。原谅我还没开始学原子物理学)。

        仿真代码如下:

from tkinter import *
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import numpy as np


class GratingSpectrometerSimulation:

    def __init__(self):
        self.window = Tk()
        self.window.title("光栅光谱仪实验仿真")
        self.window.geometry("1500x750")
        self.window.resizable(False, False)
        self.fig = Figure()
        self.image = self.fig.add_subplot()
        self.image.set_title('The Experimental Result')
        self.fig_frame = Frame(self.window, width=500, height=500)
        self.fig_frame.place(x=20, y=150)
        self.canvas = FigureCanvasTkAgg(self.fig, self.fig_frame)
        self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=YES)
        self.toolbar = NavigationToolbar2Tk(self.canvas, self.fig_frame, pack_toolbar=False)
        self.toolbar.update()
        self.toolbar.pack(side=RIGHT)

        plt.ion()  # Open the interactive mode.
        mpl.use('TkAgg')  # Tkinter & matplotlib linker.
        self.window.bind('<ButtonRelease>', self.SettingsChange)

        self.slit_width_doublevar = DoubleVar()
        self.slit_width = 0.0002
        self.grating_constant_intvar = IntVar()
        self.grating_constant = 1 / 600
        self.grating_N_intvar = IntVar()
        self.grating_N = 20
        self.current_element = ''
        self.I = np.zeros(314000)

        self.button = {'H': Button(self.window, text='氢', activebackground='red', font=('', 20),
                                   command=self.SetElementH, relief=RAISED, height=2, width=4),
                       'He': Button(self.window, text='氦', activebackground='red', font=('', 20),
                                    command=self.SetElementHe, relief=RAISED, height=2, width=4),
                       'Ne': Button(self.window, text='氖', activebackground='red', font=('', 20),
                                    command=self.SetElementNe, relief=RAISED, height=2, width=4),
                       'Hg': Button(self.window, text='汞', activebackground='red', font=('', 20),
                                    command=self.SetElementHg, relief=RAISED, height=2, width=4)
                       }
        self.button['H'].place(x=300, y=20)
        self.button['He'].place(x=380, y=20)
        self.button['Ne'].place(x=460, y=20)
        self.button['Hg'].place(x=540, y=20)

        self.scale = [Scale(), Scale(), Scale()]
        self.scale[0] = Scale(self.window, length=400, orient=HORIZONTAL, activebackground='red', from_=1, to=400,
                              digits=3, resolution=1, label='光栅总缝数N', variable=self.grating_N_intvar)
        self.scale[0].set(20)
        self.scale[0].place(x=750, y=20)
        self.scale[1] = Scale(self.window, length=400, orient=HORIZONTAL, activebackground='red', from_=10, to=1000,
                              digits=4, resolution=10, label='光栅每mm缝数', variable=self.grating_constant_intvar)
        self.scale[1].set(600)
        self.scale[1].place(x=750, y=100)
        self.scale[2] = Scale(self.window, length=396, orient=HORIZONTAL, activebackground='red', from_=0.01, to=0.99,
                              digits=2, resolution=0.01, label='光栅缝宽占比', variable=self.slit_width_doublevar)
        self.scale[2].set(0.12)
        self.scale[2].place(x=750, y=180)

        self.label = [Label(), Label(), Label()]
        self.label_ = Label(self.window, text="请选择实验用灯:", font=("", 20))
        self.label_.place(x=20, y=30)
        self.label[0] = Label(self.window, text="光栅缝数:{:.0f}".format(self.grating_N), font=("", 20))
        self.label[0].place(x=1200, y=50)
        self.label[1] = Label(self.window, text="光栅常量:{:.5f}".format(self.grating_constant) + 'mm', font=("", 20))
        self.label[1].place(x=1200, y=130)
        self.label[2] = Label(self.window, text="光栅缝宽:{:.5f}".format(self.slit_width) + 'mm', font=("", 20))
        self.label[2].place(x=1200, y=210)

        self.element_wavelength = {'H': [397.01, 410.17, 434.05, 486.13, 656.28],
                                   'He': [388.87, 402.62, 447.15, 471.31, 492.19, 501.57, 587.56, 667.82, 706.52],
                                   'Ne': [585.25, 588.19, 614.31, 621.73, 626.65, 638.30, 640.23, 650.65],
                                   'Hg': [404.66, 435.83, 491.60, 546.07, 576.96, 579.07, 623.44]}

    def SetElementH(self):
        self.current_element = 'H'
        self.ImageRefresh()

    def SetElementHe(self):
        self.current_element = 'He'
        self.ImageRefresh()

    def SetElementNe(self):
        self.current_element = 'Ne'
        self.ImageRefresh()

    def SetElementHg(self):
        self.current_element = 'Hg'
        self.ImageRefresh()

    def SettingsChange(self, event):
        self.grating_N = self.grating_N_intvar.get()
        self.grating_constant = 1.0 / self.grating_constant_intvar.get()
        self.slit_width = self.slit_width_doublevar.get() * self.grating_constant
        self.label[0].config(text="光栅缝数:{:.0f}".format(self.grating_N))
        self.label[1].config(text="光栅常量:{:.5f}".format(self.grating_constant) + 'mm')
        self.label[2].config(text="光栅缝宽:{:.5f}".format(self.slit_width) + 'mm')

        if self.current_element != '' and not (20 < event.x < 620 and 150 < event.y < 750):
            self.ImageRefresh()

    def ImageRefresh(self):
        self.image.cla()
        self.I = np.zeros(314000)
        theta = np.linspace(-1.7, 1.7, 314000)
        for wave_length in self.element_wavelength[self.current_element]:
            alpha = np.pi * self.grating_constant * np.sin(theta) / wave_length * 1000000
            beta = np.pi * self.slit_width * np.sin(theta) / wave_length * 1000000
            self.I += (np.sinc(beta) ** 2) * ((np.sin(self.grating_N * alpha) / np.sin(alpha)) ** 2)

        self.image.set_title('The Experimental Result of ' + self.current_element)
        self.image.set_xlim(-np.pi / 2, np.pi / 2)
        self.image.set_xlabel('Angle/rad')
        self.image.set_ylabel('Relative Light Intensity')
        self.image.set_xticks([-np.pi / 2, -np.pi / 3, -np.pi / 6, 0, np.pi / 6, np.pi / 3, np.pi / 2])

        self.image.plot(theta, self.I)
        self.fig.canvas.draw()

    def Run(self):
        self.window.mainloop()


window = GratingSpectrometerSimulation()
window.Run()

        运行结果图:

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值