简体   繁体   English

具有意外结果的频谱图(Python,scipy.signal)

[英]Spectogram with unexpected results (Python, scipy.signal)

I'm looking for a clarification of what I get wrong in my understanding or implementation of spectogram plotting.我正在寻找澄清我在理解或实施光谱图时遇到的问题。

To be sure that I get everything correct I started with a toy example, so I generated a very simple signal (sum of three periodic signals of different frequency and phase shift, no noise) as fallow:为了确保一切正确,我从一个玩具示例开始,所以我生成了一个非常简单的信号(不同频率和相移的三个周期信号的总和,无噪声)作为休闲信号:

import numpy as np
sampling_rate = 1.0 / 1000
duration = 2
t = np.arange(0, duration, sampling_rate)

# Signal 1 
A_1 = 0.8 # amplitude of the cosine wave
f_1 = 100 # frequency of the cosine wave
phase_1 = 30  #desired phase shift of the cosine in degrees
phi_1 = phase_1*np.pi/180
s1 = A_1*np.cos(2*np.pi*f_1*t+phi_1)

# Signal 2 
A_2 = 0.3 # amplitude of the cosine wave
f_2 = 8 # frequency of the cosine wave
phase_2 = 45  #desired phase shift of the cosine in degrees
phi_2 = phase_2*np.pi/180
s2 = A_2*np.cos(2*np.pi*f_2*t+phi_2)

# Signal 3 
A_3 = 0.1 # amplitude of the cosine wave
f_3 = 60 # frequency of the cosine wave
phase_3 = -10  #desired phase shift of the cosine in degrees
phi_3 = phase_3*np.pi/180
s3 = A_3*np.cos(2*np.pi*f_3*t+phi_3)

# Result
x = s1 + s2 + s3

I expected that the spectrogram from the "x" signal would be three horizontal lines corresponding to the three frequencies of the generated signal.我预计“x”信号的频谱图将是三个水平线,对应于生成信号的三个频率。 The signal doesn't change over time so I expected results similar to FFT, but in a different representation.信号不会随时间而变化,因此我期望结果类似于 FFT,但表示形式不同。

But after plotting it with the code below:但是在用下面的代码绘制它之后:

from scipy import signal
import matplotlib.pyplot as plt

freqs, times, spectrogram = signal.spectrogram(x)

plt.figure(figsize=(8, 6))
plt.imshow(spectrogram, aspect='auto', cmap='hot_r', origin='lower')
plt.title('Spectrogram')
plt.ylabel('Frequency band')
plt.xlabel('Time window')
plt.tight_layout()

I get something quite unexpected:我得到了一些非常出乎意料的东西:

意外的频谱图结果

The found frequencies do not make sense.找到的频率没有意义。

So my question is: where I made a mistake?所以我的问题是:我在哪里犯了错误? My expectations were wrong?我的预期错了吗? My implementation is spoiled somehow?我的实现以某种方式被破坏了? Maybe someone can recommend me a good source of knowledge on this topic?也许有人可以向我推荐有关该主题的良好知识来源?

Thank you very much in advance for your time and help.非常感谢您的时间和帮助。

I find an answer before I ask this question, so instead of deleting the whole post, I will share my result with you.在我问这个问题之前我找到了答案,所以我不会删除整个帖子,而是与你分享我的结果。 I hope somebody can benefit from it.我希望有人能从中受益。

The plot is good but the axis are badly signed. plot 很好,但轴签名错误。 If you strain your eyes, you will notice that there are in fact three bars, (the weakest is around 15).如果你睁大眼睛,你会注意到实际上有三个条,(最弱的在 15 左右)。 The visibility of the line is proportional to the amplitude value of the component signal, which makes sense because of the color codes for the amplitude.线的可见性与分量信号的幅度值成正比,这是有道理的,因为幅度的颜色代码。 So now is quite easy to notice that the y axis is for some reason divided by 4. A similar problem is with the x-axis, which is even more understandable when you realize that we are not giving information about the sampling frequency anywhere.所以现在很容易注意到 y 轴由于某种原因除以 4。类似的问题是 x 轴,当您意识到我们没有在任何地方提供有关采样频率的信息时,这更容易理解。

So now we can correct this problems, and changes color palette as fallow:所以现在我们可以纠正这个问题,并将调色板更改为休闲:

freqs, times, spectrogram = signal.spectrogram(x,fs=1./sampling_rate)

plt.figure(figsize=(8, 6))

plt.pcolormesh(times, freqs, spectrogram, shading='gouraud')
plt.ylabel('Frequency [Hz]')
plt.ylim([0,110])
plt.xlabel('Time [sec]')

plt.tight_layout()
plt.show()

Which brings us to the expected result(Amplitude for s2 multiplied by two):这给我们带来了预期的结果(s2 的振幅乘以 2):

光谱图

I hope that's helpful.我希望这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM