我使用FFTW(fftw_plan_dft_r2c_3d
)运行了3D傅里叶变换,我想在每个频率上总结变换值的(对数),包括不重复的频率实际存储在输出数组中(我理解大小为Nx x Ny x (Nz/2 + 1)
)。如果不重复计算,我该怎么做?
答案 0 :(得分:3)
好问题。对不起,我的回答有点啰嗦,我想确保我不犯任何错误。在这里 -
如果对所有“切片”进行双重计算,复数到复数3D FFT的对数和幅度之和将等于实数到复数3D FFT的对数总和。 (前者的最后一个维度)是前者所缺少的。
Nz
是偶数,则表示重复计算除第一个和最后一个切片以外的所有切片。Nz
为奇数,则重复计算除第一个以外的所有切片。(这是因为偶数长度的实数到复数DFT包括-π弧度角频率(对应于-1的相量),而奇数长度则不包括它。我永远不会记住这种模式,所以我总是在单位圆周围绘制N = 4对N = 3个相量,以提醒自己是否奇数或甚至包括-πrad。)
这是使用Numpy / Python的想法的实验验证,我认为其符合FFTW的实数到复数的FFT:通过Nx = 10
Ny = 20
实数Nz = 8
生成Nz
。计算其复杂到复杂的3D FFT(由N乘Nz复数阵列产生Nx)和其实际到复杂的3D FFT(通过Ny产生Nx乘以(Nz / 2 + 1)复数数组)。如果你对除了第一个和第一个之外的所有数据进行重复计算,则验证前者的对数和的总和是相同与后者的对数和。最后一片,因为import numpy as np
import numpy.fft as fft
Nx = 10
Ny = 20
Nz = 8
x = np.random.randn(Nx, Ny, Nz)
Xf = fft.fftn(x)
Xfr = fft.rfftn(x)
energyProduct1 = np.log10(np.abs(Xf)).sum()
lastSlice = -1 if Nz % 2 is 0 else None
energyProduct2 = np.log10(np.abs(np.dstack((Xfr, Xfr[:, :, 1:lastSlice])))).sum()
print('Difference: %g' % (energyProduct1 - energyProduct2))
# Difference: -4.54747e-13
是偶数。
代码:
Nz
如果用奇数np.dstack((Xfr, Xfr[:, :, 1:lastSlice))
重新运行它,你会发现复数到复数和实数之间的差异仍在机器精度为0之内。
rfftn
(dstack
的文档,fft.rfftn
)将Nz
输出与第二维倒数第二个切片堆叠在倒数第二个 - 倒数第二个,因为Nz
是偶数,你不想重复计算0或-πDFT箱。
当然,另一种方法是计算实数到复数数组的对数和, double ,然后减去第一个切片上的对数和大小(如果Nz
是偶数)是最后一个切片。
tl; dr 将实际到复数输出的对数幅度相加。加倍它。从该结果中减去第一个切片(在第三维中)的和 - 对数量值。如果Nz
是奇数,那么你已经完成了。如果if 'xyz' in 'oiurwernjfndj xyz iekjerk':
print True
是偶数,也会减去最后一个切片的sum-log-magnitude。