【问题标题】:Smoothing a curve with many peaks with Gaussian使用高斯平滑具有许多峰值的曲线
【发布时间】:2020-11-09 09:42:56
【问题描述】:

我的光谱数据有一些非常尖锐的峰,如蓝色曲线所示。我想让峰更平滑一点,就像图中的橙色曲线一样。

我认为最简单的方法是将我的数据点与高斯卷积。我知道numpyscipy 都有convolve 函数,但我不确定是否需要1D 或2D 卷积来获得我需要的东西。到目前为止,我尝试了来自scipyconvolve1dgaussian_filter1d 以及来自numpyconvolve。它们都没有改善连接数据点的锐线。我也不知道如何选择正确的 sigma 或权重...

包含数据点的文本文件是here

橙色曲线是从可视化程序生成的,我希望能够自己使用python而不是使用程序来生成它。

编辑:

file 的新链接

【问题讨论】:

  • 是数据的“斜坡”(即从 1500 到 3100)的一部分,还是只是来自plt.plot 连接点的人工制品?
  • 那张图片的代码是什么?
  • @DanielF 不,该区域只是连接两个数据点。
  • 查看您的数据我非常怀疑黄色图表是否反映了实际情况。无论程序在做什么,对于手头数据的定量数据分析都是非常危险的。
  • @mikuszefski 我增加了橙色图的强度,使其更加清晰(这样橙色和蓝色不会重叠并且它们有清晰的线条)。这是光谱数据,所以我们关心的是峰值在哪里。该程序是许多人通常用于此类数据分析的程序,所以我认为应该没问题...您为什么认为它很危险?

标签: python numpy scipy convolution


【解决方案1】:

看起来您想要一个“内核密度估计器”,由以下人员实现:

from scipy.stats import gaussian_kde

X = np.random.rand(50) * 3500
Y = np.random.rand(50) * 50
xi = linspace(0, 3500, 1000)

kde = gaussian_kde(X, weights = Y, bw_method = .01)  #tune `bw_method` to get the bandwidth you want
plt.plot(xi, kde.pdf(xi))

您可能还需要调整图表的y 缩放比例以符合您的要求

【讨论】:

  • 所以在你的例子中X是蓝色曲线的x坐标,xi是橙色曲线的x坐标,kde.pdf(xi)是橙色曲线的y坐标曲线。但是我只有蓝色曲线的 X 坐标......所以我不明白你的例子对我有什么帮助,除非你也告诉我我应该为 xi 使用什么。
  • 我无法从我的工作计算机访问您的文本文件所在的网站,因此您可能应该在问题本身中包含您拥有的数据(至少是一个示例)。
【解决方案2】:

这是手动复制 OP 中给出的橙色曲线。原来它是与洛伦兹而不是高斯复杂的。


import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import find_peaks
from scipy.optimize import curve_fit

def gs( x, x0, a, s ):
    return a * np.exp( -( x - x0 )**2 / ( 2 * s**2 ) )

def cs( x, x0, a, s ):
    return a / ( ( x - x0 )**2 + s**2 )

conrange = 40000 

### gasiian is no good
# ~condata = np.fromiter( ( gs(x, 0, 1, 1800 ) for x in np.arange( -5000, 5000 ) ), np.float )
### Cauchy looks much better
condata = np.fromiter( 
    ( 
        cs( x, 0, 1, 2000 ) for x in np.arange( -conrange, conrange ) 
    ), np.float
)
### shift can be zero. 
### Amplitude does not matter as it will be scaled later anyway
### width matters of course, but is adjusted manually for the moment.

data = np.loadtxt("ir_data.txt")
xdata = data[:, 0]
ydata = data[:, 1]

xdataint = np.fromiter( ( int( x* 100 ) for x in xdata ), int ) 
xmin = xdataint[0]
xmax = xdataint[-1]
xfilled = np.arange( xmin , xdataint[-1] + 1 )
yfilled = np.zeros( len( xfilled ), dtype=np.float )
xfloat = np.fromiter( ( x / 100. for x in xfilled), float ) 


for x, y in zip( xdataint, ydata ):
    yfilled[ x - xmin ] = y
### just putting a manual scale here, but the real one can be calculated
### from the convolution properties
yc = 1e6 * np.convolve( condata, yfilled, mode="full" )

xfull = np.arange(
    -conrange + xmin, xmin + conrange + len( xfilled ) - 1
)
xfloat = np.fromiter( ( 0.01 * x for x in xfull ), float )

fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.plot( xdata, ydata, ls='', marker='o', ms=2 )
ax.plot( xfloat, yc, ls='-')
plt.show()

免责声明

这是初步结果,仅应 OP 作者的要求发布。可能会有所改进。

【讨论】:

    猜你喜欢
    • 2020-06-04
    • 2022-01-02
    • 1970-01-01
    • 2021-01-17
    • 2016-01-28
    • 2018-07-23
    • 1970-01-01
    • 2014-08-17
    相关资源
    最近更新 更多