如何从完整发射光谱中模拟随机抽取光子并复现谱线分布
实现方案
核心逻辑
发射光谱的相对光强分布就是光子能量的概率密度分布,我们通过逆变换抽样方法就可以生成符合该分布的随机光子能量,百万次抽样后的统计结果会完全复现原光谱形状,单次输出为随机值,完全符合你的需求。
具体实现步骤
- 从你手头的发射光谱图中提取10~20组离散采样点,格式为
(光子能量, 相对光强),覆盖所有特征峰位置即可,不需要高精度采样 - 对离散点做插值得到连续的概率密度函数(PDF)
- 基于PDF计算累积分布函数(CDF)
- 通过CDF的逆函数对0~1区间的均匀随机数做变换,得到符合目标分布的光子能量
完整Python代码示例
import numpy as np from scipy.interpolate import interp1d import matplotlib.pyplot as plt # ---------------------- 替换为你自己的光谱数据 ---------------------- # 示例数据格式:[光子能量(eV), 相对光强],请替换为你从发射光谱提取的实际采样点 spectral_data = np.array([ [1.4, 8], [1.6, 72], [1.8, 210], [2.0, 460], # 主峰位置 [2.2, 290], [2.4, 85], [2.6, 12], [2.8, 3] ]) # ------------------------------------------------------------------- # 拆分能量和光强数组 energy_arr = spectral_data[:, 0] intensity_arr = spectral_data[:, 1] # 生成连续PDF插值函数 pdf_interp = interp1d(energy_arr, intensity_arr, kind='cubic', fill_value=0, bounds_error=False) # 生成精细能量网格计算归一化PDF e_grid = np.linspace(energy_arr.min(), energy_arr.max(), 1000) pdf = pdf_interp(e_grid) pdf = pdf / np.trapz(pdf, e_grid) # 归一化,确保PDF积分和为1 # 计算累积分布函数CDF cdf = np.cumsum(pdf) * (e_grid[1] - e_grid[0]) # 生成CDF逆插值函数,用于抽样 cdf_inv = interp1d(cdf, e_grid, fill_value=(energy_arr.min(), energy_arr.max()), bounds_error=False) def sample_photon_energy(sample_num=1): """ 生成指定数量的随机光子能量 :param sample_num: 要生成的光子数量,默认1个 :return: 符合光谱分布的光子能量数组 """ uniform_rand = np.random.uniform(0, 1, size=sample_num) return cdf_inv(uniform_rand) # 测试验证 if __name__ == "__main__": # 抽样100万次 sampled_energies = sample_photon_energy(1000000) # 对比抽样结果和原光谱 plt.figure(figsize=(8, 4)) plt.hist(sampled_energies, bins=50, density=True, alpha=0.6, label="百万次抽样统计结果") plt.plot(e_grid, pdf, "r--", linewidth=2, label="原发射光谱PDF") plt.xlabel("光子能量 (eV)") plt.ylabel("概率密度") plt.legend() plt.show()
注意事项
- 若你的光谱数据是按波长给出的,先通过公式
E = 1240 / λ换算为能量(E单位为eV,λ单位为nm)再处理 - 单次调用
sample_photon_energy()即可得到1个随机的光子能量值,调用sample_photon_energy(1000000)即可一次性得到百万个抽样结果 - 该方案为近似实现,精度完全满足你的需求,运行效率足够支撑百万次甚至更高量级的抽样
内容的提问来源于stack exchange,提问作者ruairi shannon
相关产品推荐
相关产品推荐

