python - 在 x 轴上移动频谱图
问题描述
我的信号从-1 秒开始。
但是,在绘制频谱图时,第一个 bin 边缘从 0 开始(中点在 0.25) 如何更改它以便在 x 轴上绘制时准确表示我的数据?
使用xextent=(time[0] + 0.125, time[-1])
似乎可以解决这个问题。但是,我不确定是什么变量决定了 bin 宽度,因此担心这可能会随着不同采样率、点数等的其他数据集而改变。
示例代码:
import numpy as np
import matplotlib.pyplot as plt
import signal
time = np.linspace(-1, 16, 65536)
signal = np.sin(2 * np.pi * time)
fig = plt.figure()
ax_top = fig.add_subplot(211)
ax_spec = fig.add_subplot(212)
ax_top.plot(time, signal)
ax_top.set_xlim(-1, 10)
ax_spec.set_xlim(-1, 10)
Pxx, freqs, bins, cax = ax_spec.specgram(signal, NFFT=2048, Fs=4096, noverlap=2048 / 2, mode='magnitude', pad_to=2048 * 16)
ax_spec.set_xticks(np.arange(time[0], time[-1], 1))
ax_top.set_xticks(np.arange(time[0], time[-1], 1))
plt.show()
解决方案
我将稍微简化您的示例,减少手动设置,以确保轴正确开箱即用:
import numpy as np
import matplotlib.pyplot as plt
time = np.linspace(-1, 16, 65536)
signal = np.sin(2 * np.pi * time)
fig, ax = plt.subplots(constrained_layout=True)
# In your case, use this instead:
#fig, (ax_top, ax_spec) = plt.subplots(2, 1, constrained_layout=True)
ax.plot(time, 1024 * signal + 1024, c='r')
Pxx, freqs, bins, cax = ax.specgram(signal, NFFT=2048, Fs=4096, noverlap=2048/2, mode='magnitude', pad_to=2048*16)
plt.show()
目标是使信号和图像的时间轴对齐。
频谱图代码的重要部分在matplotlib.mlab._spectral_helper
. 频谱图中的每一列都来自一个由matplotlib.mlab._stride_windows
. 时间窗口是NFFT
样本宽度,因此n
第 th 个时间箱的中心位于0.5 * (time[0] + time[NFFT - 1]) + n * (NFFT - noverlap) * dt
。您可以在 中看到此计算mlab._spectral_helper
。唯一的区别dt
是假定为1 / Fs
,并且假定起点为零。
回到 的代码specgram
,您可以看到xextent
只有在您不手动设置时才会用必要的半像素填充它。总而言之,这意味着您的图像只是移动了-time[0]
. 您可以使用 模拟相同的班次xextent
。
在我展示如何做到这一点之前,请记住您的值Fs
不正确:
>>> 1 / np.diff(time).mean()
3855.0
发生这种情况是因为Fs
应该是(len(time) - 1) / (time[-1] - time[0])
,不管其他任何事情。您可以从两个样本案例中轻松直观地理解这一点。当您手动将半像素填充应用于范围的边缘时,这将很有用。下面的填充代码直接取自以下情况xextent = None
:
time = np.linspace(-1, 16, 65536)
signal = np.sin(2 * np.pi * time)
fs = (len(time) - 1) / (time[-1] - time[0])
half_pixel = 512 / fs # (NFFT-noverlap) / Fs / 2
half_bin = 1024 / fs # NFFT / Fs / 2
xextent = (time[0] - half_pixel + half_bin, time[-1] + half_pixel - half_bin)
fig, ax = plt.subplots(constrained_layout=True)
ax.plot(time, (fs / 4) * (signal + 1), c='r')
Pxx, freqs, bins, cax = ax.specgram(signal, NFFT=2048, Fs=fs, noverlap=2048 / 2, mode='magnitude', pad_to=2048 * 16, xextent=xextent)
plt.show()
果然,图像完全位于信号图的中心,信号的末端伸出图像边缘正好半个时间窗口:
推荐阅读
- c++ - 不带引号的 LLDB 摘要字符串
- android - Android 位置 GPS 追踪
- imagemagick - 可以在 AWS Linux 2 中添加对 PHP 的 imagick webp 支持吗?
- php - 从 2 个数据透视表返回数据
- python - Python获取字符串的位置和接下来的X行
- javascript - Javascript 和 React:如何调用或引用函数?
- python-3.x - 我无法让这段代码工作,谁能告诉我我做错了什么?subl 说第 18 行有一个错误,但真的无法弄清楚
- python - python中的逻辑回归-初学者-重塑数据集
- vim - vim 中那些奇怪的标签“<++>”有什么用?
- facebook - 如何使用Oauth2连接和使用facebook营销api