绘制在窄范围内采样的复杂信号的频谱的正确方法是什么?

rol*_*254 1 python signal-processing numpy fft scipy

我有一些我很想绘制的复杂数据(设定频率周围的小带宽),但我对如何继续解释在特定范围内采样的复杂信号感到有些困惑。

因此,例如,这是我编写的代码(以及我对问题的相当糟糕的尝试),因此我有一个干净的示例来试验人工信号,该示例生成 78 KHz 波的复杂表示。我想要做的是得到一个以 120 KHz 为中心,跨度从 70 到 170 KHz 的图,模拟真实接收器的窄采样范围。

import numpy as np
import matplotlib.pyplot as plt

#sampling rate, samples/second; 100 KHz
rate = 100*10**3
#sample spacing in time, seconds/sample
interval = np.true_divide(1, rate)
#length of the fourier transform
n = 256
#time vector
t = np.linspace(0.0, n*interval, n)

#frequency of artificial signal; 78 KHz
f = 78*10**3
#complex signal
s = np.exp(1j*2*np.pi*f*t)

#dft of the data
dft = np.fft.fft(s)
#frequency bins
x = np.fft.fftfreq(n, d=interval)
#center zero-frequency component in data; take absolute values
dft = np.abs(np.fft.fftshift(dft))
#center zero frequency component in bins; naively add the center frequency, 120 KHz
x = np.fft.fftshift(x) + 120*10**3

plt.plot(x, dft)
plt.show()
Run Code Online (Sandbox Code Playgroud)

输出是错误的,正如对模仿特定频率范围的粗略尝试所预期的那样。

由上面的代码片段绘制的图

PS不同的情节,与f = 88*10*83- 为什么这里的幅度突然发生了变化?

编辑:我的帖子已被标记为与一个纯粹与绘图相关的主题重复,而我实际上是在处理和/或带通滤波数据的反演。

Fin*_*ood 7

奈奎斯特频率和混叠

您的信号应该是 +78 kHz 的(复杂)指数振荡,以 100 kHz 采样。这不起作用。相反,您看到的是 -22 kHz (78 kHz - 100 kHz) 处的混叠频率。您必须确保信号的任何频率都不会高于采样频率的一半。例如,对于 78 kHz 的信号,采用 200 kHz 的采样频率。

import numpy as np
from matplotlib import pyplot as plt

sample_frequency = 200e3  # 200 kHz
sample_interval = 1 / sample_frequency
samples = 256  # you don't necessarily have to use a power of 2
time = np.linspace(0, samples*sample_interval, samples)

signal_frequency = 78e3  # 78 kHz
signal = np.exp(2j*np.pi*signal_frequency*time)
Run Code Online (Sandbox Code Playgroud)

FFT 和 fftfreq

np.fft.fftfreq已经返回正确的频率,添加“中心频率”没有意义。不要这样做。

signal_spectrum = np.fft.fftshift(np.fft.fft(signal))
freqs = np.fft.fftshift(np.fft.fftfreq(samples, d=sample_interval))
Run Code Online (Sandbox Code Playgroud)

绘图

您问题的绘图部分仅与设置轴有关。使用plt.xlim.

plt.figure(figsize=(10,5))
plt.plot(freqs / 1e3, np.abs(signal_spectrum))  # in kHz
plt.xlim(70, 170)
Run Code Online (Sandbox Code Playgroud)

信号频谱

绘制的线在 100 kHz 之前结束,因为如上所述,您的信号不能具有高于半采样频率的频率部分。

频谱幅度

由于您的信号是时间离散的(几个单个样本,不是连续函数),因此您的频谱是连续的。的离散傅里叶变换,但是,只返回连续光谱的离散样本。如果您通过采样点拟合一条曲线,其峰值对于不同频率将具有相同的幅度。

或者,您可以通过对信号进行零填充来增加 FFT 采样点的数量(查看numpy.fft.fft文档):

signal_spectrum = np.fft.fftshift(np.fft.fft(signal, 10*samples))
freqs = np.fft.fftshift(np.fft.fftfreq(10*samples, d=sample_interval))

plt.figure(figsize=(10,5))
plt.plot(freqs / 1e3, np.abs(signal_spectrum))  # in kHz
plt.xlim(65, 95).
plt.grid()
Run Code Online (Sandbox Code Playgroud)

有泄漏的补零信号的频谱

如果您问自己为什么频谱看起来如此波纹,请查看频谱泄漏