求可提取直方图多峰值及对应峰宽的适配函数
多峰直方图的峰值与对应峰宽提取实现方案
核心实现流程
1. 直方图数据预处理
- 首先对原始直方图的计数值做平滑处理,避免高频噪声产生伪峰,推荐使用
scipy.signal.savgol_filter(萨维茨基-戈莱滤波),相比普通滑动平均可以更好保留峰的形态与边界,窗口大小建议设置为奇数,取值为你预期最小峰覆盖bin数的1/3左右,多项式阶数默认取2~3即可。 - 如果直方图存在连续的基线抬高,可以用非对称最小二乘法(ALS)拟合基线后扣除,避免基线偏移导致峰高、峰宽计算出现系统性偏差。
2. 多峰自动检测
直接调用scipy.signal.find_peaks函数即可完成多峰的自动识别,无需手动框选单峰范围,可配置核心参数:
height:峰值的最小高度阈值,过滤低于阈值的噪声峰distance:两个峰之间的最小bin间距,避免同一个峰被识别为多个prominence:峰的突出度,即峰顶到两侧谷底的最小高度差,过滤和基线几乎齐平的假峰
函数会直接返回所有有效峰的索引,你可以直接通过索引拿到对应bin的横坐标(物理值)和峰值计数值,也就是你需要的峰值最大值。
3. 峰宽自动计算
find_peaks支持直接输出峰的半高全宽(FWHM)参数,调用时添加widths参数即可,返回结果包含:
- 每个峰的半高全宽数值(单位为bin,你可以乘以bin的步长转换为实际物理单位)
- 每个峰半高处的左右边界位置,可用于后续的单峰拟合优化
如果需要更高精度的峰宽结果,可以针对每个识别到的峰,截取其左右半宽边界范围内的bin数据,调用你现有的高斯拟合函数批量处理即可,无需手动选范围。
最小可运行示例代码
import numpy as np from scipy.signal import find_peaks, savgol_filter # 模拟直方图数据:bin_edges是每个bin的边界,counts是每个bin的计数值 # 实际使用时替换为你自己的直方图数据 counts, bin_edges = np.histogram(np.random.normal(0, 1, 10000).tolist() + np.random.normal(3, 0.8, 7000).tolist(), bins=100) bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2 # 1. 平滑处理 smooth_counts = savgol_filter(counts, window_length=5, polyorder=2) # 2. 峰检测+峰宽计算 peaks, properties = find_peaks(smooth_counts, height=100, distance=5, prominence=50, width=1) # 输出结果 peak_values = smooth_counts[peaks] # 峰值最大值 peak_positions = bin_centers[peaks] # 峰值位置 peak_fwhm = properties['widths'] * (bin_edges[1] - bin_edges[0]) # 转换为实际物理单位的半高全宽
内容的提问来源于stack exchange,提问作者nichtnachmachen2
相关产品推荐
相关产品推荐

