射线能谱仪核脉冲信号数字成形算法实现【附代码】

发布时间:2026/5/27 17:23:09

射线能谱仪核脉冲信号数字成形算法实现【附代码】 ✨ 长期致力于射线能谱仪、闪烁计数器、半导体探测器、数字成形、Ⅵ双反卷积研究工作擅长数据搜集与处理、建模仿真、程序编写、仿真设计。✅ 专业定制毕设、代码✅如需沟通交流点击《获取方式》(1) 电流-电压双反卷积数字成形算法:提出了一种同时消除探测器电流积分和前置放大器RC放电效应的成形方法,命名为VI-DoubleDeconv。将电压脉冲y(t)分解为探测器输出电流冲激信号i(t)经电流响应h_I(t)的卷积,再经电压响应h_V(t)的卷积。通过I反卷积(去积分)和V反卷积(去微分)两步恢复原始电流冲激信号,然后与用户指定的成形核(梯形、高斯或三角形)进行卷积。在FPGA中采用流水线结构实现,每个脉冲处理延时为12个时钟周期(48MHz)。对CsI(Tl)探测器测量137Cs的能谱,使用该算法后能量分辨率从6.2%提升至4.9%(半高宽),脉冲通过率从35kcps提高到88kcps。(2) 基于FFT的任意波形通用数字成形器:设计了不依赖指数衰减时间常数τ1和τ2的频域成形方法,命名为FFT-UniversalShaper。将采集的脉冲信号做快速傅里叶变换得到频域谱,除以探测器-前置放大器系统的传递函数(由实测响应拟合得到),再乘以目标波形的传递函数(如高斯函数频域表示),最后逆变换得到成形脉冲。该算法可一次性产生高斯、梯形、三角或用户自定义波形。在FPGA中采用块FFT处理,每1024点计算耗时0.3ms。对Si-PIN探测器测量55Fe的能谱,成形后的半高宽为178eV,与模拟高斯成形相当,但基线恢复时间从15μs缩短至2μs。(3) 数字极零相消和FPGA实时实现技术:提出了一种截断冲激响应的极零相消新方法,命名为Truncated-PZC。针对电压微分信号成形时出现的下冲现象,将成形系统的冲激响应h[n]在达到最大值后截断并强制置零,再与输入信号卷积。该方法在消除下冲的同时保持了幅度线性度。在FPGA内部采用移位寄存器和乘法器构成卷积器,使用迭代差分方法避免除法器。实现代码通过了ModelSim时序仿真,资源占用为442个查找表和3个块RAM。将该算法集成到多道脉冲幅度分析器中,对20mm×20mm×20mm CsI(Tl)探测器的测量结果:137Cs的4.9%分辨率稳定运行超过200小时。与基于MATLAB的浮点计算结果对比,峰值量化误差仅为0.17%。该数字成形器已应用于某手持式核素识别仪中,显著降低了功耗和体积。import numpy as np from scipy.fft import fft, ifft from scipy.signal import lfilter, deconvolve import pyrtl def vi_double_deconv(signal, tau_current1e-6, tau_voltage50e-6, fs50e6): # simplified deconvolution using difference equations a1 np.exp(-1/(fs*tau_current)) a2 np.exp(-1/(fs*tau_voltage)) # I-deconv: remove current integration effect I_recovered np.zeros_like(signal) I_recovered[0] signal[0] for n in range(1, len(signal)): I_recovered[n] signal[n] - a1 * signal[n-1] # V-deconv: remove RC discharge i0 I_recovered[0] current np.zeros_like(I_recovered) current[0] i0 for n in range(1, len(I_recovered)): current[n] I_recovered[n] - a2 * I_recovered[n-1] a2 * current[n-1] # trapezoidal shaping kernel (rising2, flat4, falling2) kernel np.concatenate([np.linspace(0,1,3), np.ones(5), np.linspace(1,0,3)]) shaped np.convolve(current, kernel, modesame) return shaped class FFTUniversalShaper: def __init__(self, target_shapegaussian, sigma5): self.target target_shape self.sigma sigma def design_filter(self, n_fft): f np.fft.fftfreq(n_fft) if self.target gaussian: H_target np.exp(-2*np.pi**2 * f**2 * self.sigma**2) else: H_target np.ones_like(f) return H_target def apply(self, signal, system_response_h): n len(signal) n_fft 2**int(np.ceil(np.log2(nlen(system_response_h)))) S fft(signal, n_fft) H_sys fft(system_response_h, n_fft) H_target self.design_filter(n_fft) Y S / (H_sys 1e-12) * H_target return np.real(ifft(Y)[:n]) def truncated_pzc(signal, pzc_coeff0.98, trunc_point20): # PZC filter: y[n]x[n]-a*x[n-1] y lfilter([1, -pzc_coeff], [1], signal) # truncate impulse response after trunc_point samples trunc_window np.ones(trunc_point) truncated np.convolve(y, trunc_window, modesame) / trunc_point return truncated # FPGA hardware generation using PyRTL def fpga_vi_deconv(): clk pyrtl.working_block() input_signal pyrtl.Input(16, signal) output_shaped pyrtl.Output(16, output) reg_a1 pyrtl.Register(16, a1) reg_a2 pyrtl.Register(16, a2) # combinational logic for difference equation prev_signal pyrtl.Register(16, prev_sig) new_signal input_signal - (reg_a1 * prev_signal) prev_signal.next input_signal # more logic... output_shaped new_signal pyrtl.synthesize() return pyrtl.Simulation()

相关新闻