Python中复信号的FFT结果与Mathematica中FFT结果相比出现“翻转”的光谱。

4

我有一个复杂信号,想要进行FFT变换。使用Mathematica软件,我得到了以下结果:

(* Some acquisition params *)
fS = 100. 10^6;
time = 10. 10^-6;
NbrSamp = Round[fS * time];

(* Generate signal *)
w0 = 2 \[Pi] 80 10^6;
ti = Subdivide[0., time, NbrSamp];
sig = Cos[w0 ti] + \[ImaginaryI] Sin[w0 ti];

(* Plot result of FFT *)
ListPlot[Abs@Fourier[sig], Joined -> True, PlotRange -> All, DataRange -> {0, fS}]

得到的光谱图

然而,当我在 Python 中执行相同的计算时,与 Mathematica 相比,我得到的光谱图是“翻转”的。为了得到相同的光谱图,我必须反转 FFT 的输出。我的代码如下:

import numpy as np
import matplotlib.pylab as plt
from scipy.fft import fft

# Some acquisition params
fs = 100e6
time = 10e-6
NbrSamp = round(fs*time)

# Generate signal
w0 = 2*np.pi*80e6
ti = np.arange(NbrSamp+1) / fs
sig = np.cos(w0*ti) + 1j*np.sin(w0*ti)

# calc FFT
sigFFT = fft(sig, norm = 'ortho')
freq = np.arange(0, NbrSamp+1) * fs / NbrSamp

# Plot result of FFT
plt.plot(freq, abs(sigFFT), label = "Actual result")
plt.plot(freq, abs(sigFFT[::-1]), label = "Flipped result")
plt.xlim(min(freq), max(freq))
plt.legend()
plt.show()

Python FFT结果

我的问题是为什么会出现这种情况,如何在Python中获得与Mathematica相同的结果,而无需翻转从FFT获得的数据? 由于我将拥有大量这样的信号,因此我希望避免进行此翻转操作。


需要小心的是,不要对x值做出错误的假设,它们有时可能会被循环移位。你读过scipy fft和Mathematica Fourier的文档吗? - Trilarion
2个回答

4

Mathematica的Fourier函数文档 中可以了解到:

  • 其他科学和技术领域使用其他定义。
  • 可以通过选项FourierParameters来指定不同的定义。
  • 使用FourierParameters->{a,b}设置,Fourier计算得出的离散傅里叶变换为<一些带有 exp(2πib) 的方程>。
  • {a,b}的一些常见选择包括{0,1}(默认值),{-1,1}(数据分析),{1,-1}(信号处理)。
  • 设置b=-1相当于同时对输入和输出列表进行共轭。

因此,默认情况下,Mathematica将b=0,但将b=-1设置可使其输出与Python匹配,后者使用更常见的信号处理定义。

要使Python的结果与Mathematica的结果匹配,请执行以下操作:

sigFFT = np.conj(fft(np.conj(sig), norm = 'ortho'))

请注意,此操作与翻转结果不同,因为零频率分量不受影响(输出数组的第一个元素),只有其余元素被翻转(并共轭)。
另外请注意,如果你只需要FFT的幅度,无需对输出进行共轭,因为abs(conj(x)) == abs(x)。

如果您只需要FFT的幅度,那么无需对输出进行共轭。但是对于OP所拥有的复杂输入而言,这并不正确。 - OverLordGoldDragon
@OverLordGoldDragon 我在那句话中的意思是提醒读者 abs(conj(x)) == abs(x)。仍然需要对 fft 函数的输入进行共轭处理。 - Cris Luengo
没错,你说的很有道理,谢谢。 - OverLordGoldDragon

2
文档 可以看出,Mathematica的傅里叶变换 Fourier 使用正号(顺时针旋转)指数,而大多数Python库使用负号(如维基百科中所述)。这是因为不同应用需要使用不同的符号。
这会导致输入和输出被“共轭”:fft_mathematica(x) == conj(fft_python(conj(x), norm='ortho'))。要直接对输出(即FFT bin)进行共轭操作,请交换正负号。
out = fft(x)
out[1:] = out[1:][::-1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接