我测量了一个与测量设备的轮廓卷积的信号。现在我想删除这个贡献以获得“真实”信号。我正在尝试用 Python 来做到这一点。为此,我正在使用该scipy.signal.deconvolve
功能。为了了解如何使用它,我从Stack Overflow 中的这个问题开始,特别是Cleb 的回答。所以我写了一个玩具脚本来玩。
玩具示例
import numpy as np
import scipy.signal
import plotly.graph_objects as go
from plotly.subplots import make_subplots
x = np.arange(0., 20.01, 0.01)
original = np.zeros(len(x))
original[900:1100] = 1
filter_sigma = .2
filter_from_measuring_apparatus = np.exp(-(x-x.mean())**2/2/filter_sigma**2)
filter_from_measuring_apparatus = filter_from_measuring_apparatus[filter_from_measuring_apparatus>.1]
filter_for_deconv = filter_from_measuring_apparatus
measured = scipy.signal.convolve(original, filter_from_measuring_apparatus, mode='full') / filter_from_measuring_apparatus.sum()
deconvoluted, remainder = scipy.signal.deconvolve(measured, filter_for_deconv)
deconvoluted *= filter_for_deconv.sum()
signals = [original, filter_from_measuring_apparatus, measured, filter_for_deconv, deconvoluted]
labels = ['original', 'filter_from_measuring_apparatus', 'measured', 'filter_for_deconv', 'deconvoluted']
fig = make_subplots(rows = len(signals), shared_xaxes = True, vertical_spacing = 0.02)
for fig_row,(signal, label) in enumerate(zip(signals, labels)):
fig.add_trace(
go.Scatter(
x = [i for i in range(len(signal))],
y = signal,
name = label,
),
row = fig_row+1,
col = 1,
)
fig.show()
这个玩具示例的输出如下所示:
这是我们都期望的,很好。我正在削减高斯filter_from_measuring_apparatus
,>0.1
因为在ImportanceOfBeingErnest 的回答中,他说“过滤器应该比任何地方都大得多”,这是可以理解的,因为在某些时候它会分裂。
现实生活中的测量仪器,但仍然没有噪音
所以现在我想进入现实生活。在现实生活中,测量设备的过滤器可以是任何东西,特别是“不是到处都比零大得多”的高斯。所以我只修改filter_from_measuring_apparatus
:
import numpy as np
import scipy.signal
import plotly.graph_objects as go
from plotly.subplots import make_subplots
x = np.arange(0., 20.01, 0.01)
original = np.zeros(len(x))
original[900:1100] = 1
filter_sigma = .2
filter_from_measuring_apparatus = np.exp(-(x-x.mean())**2/2/filter_sigma**2)
filter_for_deconv = filter_from_measuring_apparatus[filter_from_measuring_apparatus>.1] # The filter I will use for deconv is still "much bigger than zero".
measured = scipy.signal.convolve(original, filter_from_measuring_apparatus, mode='full') / filter_from_measuring_apparatus.sum()
deconvoluted, remainder = scipy.signal.deconvolve(measured, filter_for_deconv)
deconvoluted *= filter_for_deconv.sum()
deconvoluted[(deconvoluted<-2)|(deconvoluted>2)] = float('NaN') # Remove so we can see in the plot.
signals = [original, filter_from_measuring_apparatus, measured, filter_for_deconv, deconvoluted]
labels = ['original', 'filter_from_measuring_apparatus', 'measured', 'filter_for_deconv', 'deconvoluted']
fig = make_subplots(rows = len(signals), shared_xaxes = True, vertical_spacing = 0.02)
for fig_row,(signal, label) in enumerate(zip(signals, labels)):
fig.add_trace(
go.Scatter(
x = [i for i in range(len(signal))],
y = signal,
name = label,
),
row = fig_row+1,
col = 1,
)
fig.show()
现在输出如下所示:
为什么会这样?我希望输出与前一种情况非常相似,因为measured
信号几乎相同(只是更长)。
添加噪声,为测量仪器保留玩具过滤器
现在让我回到使用假设备滤波器的玩具示例,但在测量中添加(非常小的)噪声:
import numpy as np
import scipy.signal
import plotly.graph_objects as go
from plotly.subplots import make_subplots
x = np.arange(0., 20.01, 0.01)
original = np.zeros(len(x))
original[900:1100] = 1
filter_sigma = .2
filter_from_measuring_apparatus = np.exp(-(x-x.mean())**2/2/filter_sigma**2)
filter_from_measuring_apparatus = filter_from_measuring_apparatus[filter_from_measuring_apparatus>.1]
filter_for_deconv = filter_from_measuring_apparatus
measured = scipy.signal.convolve(original, filter_from_measuring_apparatus, mode='full') / filter_from_measuring_apparatus.sum()
measured += 0.001*(np.random.randn(len(measured))**2)**.5 # Add some noise to the measurement, as I am measuring power the noise is only positive.
deconvoluted, remainder = scipy.signal.deconvolve(measured, filter_for_deconv)
deconvoluted *= filter_for_deconv.sum()
deconvoluted[(deconvoluted<-2)|(deconvoluted>2)] = float('NaN') # Remove so we can see in the plot.
signals = [original, filter_from_measuring_apparatus, measured, filter_for_deconv, deconvoluted]
labels = ['original', 'filter_from_measuring_apparatus', 'measured', 'filter_for_deconv', 'deconvoluted']
fig = make_subplots(rows = len(signals), shared_xaxes = True, vertical_spacing = 0.02)
for fig_row,(signal, label) in enumerate(zip(signals, labels)):
fig.add_trace(
go.Scatter(
x = [i for i in range(len(signal))],
y = signal,
name = label,
),
row = fig_row+1,
col = 1,
)
fig.show()
产生输出:
WTF?!?!?! 噪声是信号的1/1000强,在measured
信号图中几乎看不到,怎么可能在反卷积后产生如此剧烈的废话?
当然,同时将测量设备的真实过滤器和噪声结合起来只会使结果变差。
所以我的问题是,该deconvolve
功能应该如何在现实生活中使用?或者我应该如何在 Python 中做我想做的事情?我将不胜感激解决我的玩具示例的答案。