python、matplotlib:specgram 数据数组值与 specgram 图不匹配
python, matplotlib: specgram data array values does not match specgram plot
我正在使用 matplotlib.pyplot.specgram 和 matplotlib.pyplot.pcolormesh 绘制地震信号的频谱图。
背景信息 - 使用 pcolormesh 的原因是我需要对频谱图数据数组进行算术运算,然后重新绘制生成的频谱图(对于三分量地震图 - 东、北和垂直 -我需要计算出水平光谱幅度并将垂直光谱除以水平光谱)。使用频谱图阵列数据比使用单个振幅频谱更容易做到这一点
我发现在进行算术运算后的频谱图具有意想不到的值。经过进一步调查,事实证明使用 pyplot.specgram 方法绘制的频谱图与使用 pyplot.pcolormesh 绘制的频谱图和 pyplot.specgram 方法返回的数据数组相比具有不同的值。两者 plots/arrays 应该包含相同的值,我不明白为什么它们不一样。
示例:
的剧情
plt.subplot(513)
PxN, freqsN, binsN, imN = plt.specgram(trN.data, NFFT = 20000, noverlap = 0, Fs = trN.stats.sampling_rate, detrend = 'mean', mode = 'magnitude')
plt.title('North')
plt.xlabel('Time [s]')
plt.ylabel('Frequency [Hz]')
plt.clim(0, 150)
plt.colorbar()
#np.savetxt('PxN.txt', PxN)
看起来和
的剧情不一样
plt.subplot(514)
plt.pcolormesh(binsZ, freqsZ, PxN)
plt.clim(0,150)
plt.colorbar()
即使 "PxN" 数据数组(即每个段的频谱图数据值)由第一种方法生成并在第二种方法中重新使用。
有人知道为什么会这样吗?
P.S。我意识到我对 NFFT 的价值不是一个平方数,但在我编码的这个阶段并不重要。
P.P.S。我不知道 "imN" 数组(pyplot.specgram 的第四个返回变量)是什么以及它的用途....
首先,让我们举例说明您所描述的内容,以便其他人
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
# Brownian noise sequence
x = np.random.normal(0, 1, 10000).cumsum()
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(8, 10))
values, ybins, xbins, im = ax1.specgram(x, cmap='gist_earth')
ax1.set(title='Specgram')
fig.colorbar(im, ax=ax1)
mesh = ax2.pcolormesh(xbins, ybins, values, cmap='gist_earth')
ax2.axis('tight')
ax2.set(title='Raw Plot of Returned Values')
fig.colorbar(mesh, ax=ax2)
plt.show()
量级差异
您会立即注意到标绘值的大小差异。
默认情况下,plt.specgram
不会绘制 "raw" 值 returns。相反,它将它们缩放到分贝(换句话说,它绘制了振幅的 10 * log10
)。如果您不希望它缩放,则需要指定 scale="linear"
。然而,为了查看频率组成,对数刻度将最有意义。
考虑到这一点,让我们模仿一下 specgram
的作用:
plotted = 10 * np.log10(values)
fig, ax = plt.subplots()
mesh = ax.pcolormesh(xbins, ybins, plotted, cmap='gist_earth')
ax.axis('tight')
ax.set(title='Plot of * log_{10}(values)$')
fig.colorbar(mesh)
plt.show()
改用对数色标
或者,我们可以在图像上使用对数范数并得到类似的结果,但更清楚地表明颜色值在对数尺度上:
from matplotlib.colors import LogNorm
fig, ax = plt.subplots()
mesh = ax.pcolormesh(xbins, ybins, values, cmap='gist_earth', norm=LogNorm())
ax.axis('tight')
ax.set(title='Log Normalized Plot of Values')
fig.colorbar(mesh)
plt.show()
imshow
对比 pcolormesh
最后,请注意,我们展示的示例没有应用插值,而原始 specgram
图应用了插值。 specgram
使用 imshow
,而我们一直在使用 pcolormesh
进行绘图。在这种情况下(常规网格间距)我们可以使用其中任何一种。
在这种情况下,imshow
和 pcolormesh
都是很好的选择。但是,如果您使用的是大型数组,imshow
的性能会好得多。因此,您可能会考虑使用它,即使您不想插值(例如 interpolation='nearest'
关闭插值)。
举个例子:
extent = [xbins.min(), xbins.max(), ybins.min(), ybins.max()]
fig, ax = plt.subplots()
mesh = ax.imshow(values, extent=extent, origin='lower', aspect='auto',
cmap='gist_earth', norm=LogNorm())
ax.axis('tight')
ax.set(title='Log Normalized Plot of Values')
fig.colorbar(mesh)
plt.show()
我正在使用 matplotlib.pyplot.specgram 和 matplotlib.pyplot.pcolormesh 绘制地震信号的频谱图。
背景信息 - 使用 pcolormesh 的原因是我需要对频谱图数据数组进行算术运算,然后重新绘制生成的频谱图(对于三分量地震图 - 东、北和垂直 -我需要计算出水平光谱幅度并将垂直光谱除以水平光谱)。使用频谱图阵列数据比使用单个振幅频谱更容易做到这一点
我发现在进行算术运算后的频谱图具有意想不到的值。经过进一步调查,事实证明使用 pyplot.specgram 方法绘制的频谱图与使用 pyplot.pcolormesh 绘制的频谱图和 pyplot.specgram 方法返回的数据数组相比具有不同的值。两者 plots/arrays 应该包含相同的值,我不明白为什么它们不一样。
示例:
的剧情plt.subplot(513)
PxN, freqsN, binsN, imN = plt.specgram(trN.data, NFFT = 20000, noverlap = 0, Fs = trN.stats.sampling_rate, detrend = 'mean', mode = 'magnitude')
plt.title('North')
plt.xlabel('Time [s]')
plt.ylabel('Frequency [Hz]')
plt.clim(0, 150)
plt.colorbar()
#np.savetxt('PxN.txt', PxN)
看起来和
的剧情不一样plt.subplot(514)
plt.pcolormesh(binsZ, freqsZ, PxN)
plt.clim(0,150)
plt.colorbar()
即使 "PxN" 数据数组(即每个段的频谱图数据值)由第一种方法生成并在第二种方法中重新使用。
有人知道为什么会这样吗?
P.S。我意识到我对 NFFT 的价值不是一个平方数,但在我编码的这个阶段并不重要。
P.P.S。我不知道 "imN" 数组(pyplot.specgram 的第四个返回变量)是什么以及它的用途....
首先,让我们举例说明您所描述的内容,以便其他人
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
# Brownian noise sequence
x = np.random.normal(0, 1, 10000).cumsum()
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(8, 10))
values, ybins, xbins, im = ax1.specgram(x, cmap='gist_earth')
ax1.set(title='Specgram')
fig.colorbar(im, ax=ax1)
mesh = ax2.pcolormesh(xbins, ybins, values, cmap='gist_earth')
ax2.axis('tight')
ax2.set(title='Raw Plot of Returned Values')
fig.colorbar(mesh, ax=ax2)
plt.show()
量级差异
您会立即注意到标绘值的大小差异。
默认情况下,plt.specgram
不会绘制 "raw" 值 returns。相反,它将它们缩放到分贝(换句话说,它绘制了振幅的 10 * log10
)。如果您不希望它缩放,则需要指定 scale="linear"
。然而,为了查看频率组成,对数刻度将最有意义。
考虑到这一点,让我们模仿一下 specgram
的作用:
plotted = 10 * np.log10(values)
fig, ax = plt.subplots()
mesh = ax.pcolormesh(xbins, ybins, plotted, cmap='gist_earth')
ax.axis('tight')
ax.set(title='Plot of * log_{10}(values)$')
fig.colorbar(mesh)
plt.show()
改用对数色标
或者,我们可以在图像上使用对数范数并得到类似的结果,但更清楚地表明颜色值在对数尺度上:
from matplotlib.colors import LogNorm
fig, ax = plt.subplots()
mesh = ax.pcolormesh(xbins, ybins, values, cmap='gist_earth', norm=LogNorm())
ax.axis('tight')
ax.set(title='Log Normalized Plot of Values')
fig.colorbar(mesh)
plt.show()
imshow
对比 pcolormesh
最后,请注意,我们展示的示例没有应用插值,而原始 specgram
图应用了插值。 specgram
使用 imshow
,而我们一直在使用 pcolormesh
进行绘图。在这种情况下(常规网格间距)我们可以使用其中任何一种。
在这种情况下,imshow
和 pcolormesh
都是很好的选择。但是,如果您使用的是大型数组,imshow
的性能会好得多。因此,您可能会考虑使用它,即使您不想插值(例如 interpolation='nearest'
关闭插值)。
举个例子:
extent = [xbins.min(), xbins.max(), ybins.min(), ybins.max()]
fig, ax = plt.subplots()
mesh = ax.imshow(values, extent=extent, origin='lower', aspect='auto',
cmap='gist_earth', norm=LogNorm())
ax.axis('tight')
ax.set(title='Log Normalized Plot of Values')
fig.colorbar(mesh)
plt.show()