大家好,我是用Python对数据进行2D FFT变换,详情如下:
二维 FFT前,我首先导入了一个 627*2300的矩阵A。该矩阵每一行,是一个采样的时间点,间隔为10 ps,即,第0行是t = 0,第1行是t = 10 ps,以此类推,但时间数据并没有记录在矩阵当中。
矩阵横向2300列是一个空间采样。如一条纳米线,x是长度,2300列是沿着纳米线的头到位,记录了每一个位置的振幅。采样的间隔是4 nm,既第0列是x=0位置的振幅,第1列是x=4 nm位置的振幅,以此类推。同时间,记录位置的数据并没有记录在矩阵中。
通过2维FFT,想要得到横坐标是空间FFT后的波矢k,纵坐标是时间FFT后的频率frequency,颜色深浅代表FFT后的信号振幅大小。
4.操作相关代码如下
import numpy as np
import matplotlib.pyplot as plt
import mayavi.mlab as mlab
A=np.loadtxt(path) #import data file.
A=np.reshape(A,(-1,2300)) #each row is one time point,A是627*2300的矩阵
C=np.fft.fft2(A) # 2D FFT
plt.imshow(np.log(np.abs(np.fft.fftshift(C))**2),aspect='auto')
plt.show()
最后出图如图
可以看到,最后画出的2D FFT图中,横纵坐标依然是我原本矩阵的行列数,纵坐标是0-627,横坐标是0-2300。这个数据与实际结果不符。实际情况下纵坐标应该是时间间隔为10 ps的627个时间点经过FFT后转化成的frequency (我用origin里手动做了一次FFT,纵坐标范围应该在-52 GHz ~ 52 GHz),横坐标应该是空间长度间隔4 nm的2300个数据点经过FFT后得到的k空间波矢坐标值(-0.125 ~ 0.125 nm-1).
############
请问一下我该如何让python在做FFT的时候,考虑实际的采样时间和空间间隔,给出真实的横纵坐标轴呢?谢谢!
(1)你所做的 FFT 显示图像是功率谱图,表征频率的能量;
(2)FFT 功率谱的值往往相差多个数量级,无法在灰度图中表示,因为灰度图的分辨率只有 [0,255],因此还要通过对数变换为功率谱的对数图像;
(3)由于图像傅里叶变换其实只是借用频率域变换的概念,图像并不是真正的频率信号,通常对 FFT 功率谱不标注坐标轴;
(4)如果一定要标坐标轴,空间取样和频率间隔是相互对应的,频率域所对应的离散变量间的间隔为: du=1/MdT,dv=1/NdZ。
即频域中样本之间的间隔,与空间样本之间的间隔及样本数量的乘积成反比。
M,N 是图像像素宽度、高度,dT, dZ 是连续函数 f(x,y) 在 t,z 轴的样本间的间隔,即两个相邻像素之间的距离。由图像(照片) 的 dpi可以获得。
(5)进行以上准备后,就可以求出坐标轴了。FFT 频谱图像的左上角为 (0,0),对应着直流分量的频谱,能量较高亮(发白),其它位置几乎都是黑色。由于进行了对数处理,所以坐标标注以对数表示比较方便。
(6)但是,fftshift() 进行了中心化处理,把低频移到中心,也就是说 图像中心的频域坐标为 (0,0),对应着频率为 0 的直流分量的频谱。而从中心向四周的任何方向都是增大,所以这个坐标如果一定要标比较特殊,中心为 0,横坐标向左向右都是对数增大,纵坐标向上向下都是对数增大。注意图像也是上下对称,左右对称的。
(1)np.log(np.abs(np.fft.fftshift(C))*2)——你已经对 频率谱 进行了对数处理(np.log),所以坐标轴当然应该用 对数表示
(2)我说的意思是,中心化处理后的图像是不适合用通常的坐标轴表示的。以横坐标为例,中心表示频率为 0,向左是 10^1,10^2,...,向右也是 10^1,10^2,...,图像的左右是完全对称的。
(3)未做对数处理前,频率域相邻两点间距是 du=1/MdT,即 1/10ps4 nm,单位也并不是真正的频率——因为二维傅立叶变换只是借用并推广傅立叶变换,而不是真正的信号处理。