我的目标是对函数的离散连续2D傅里叶变换进行插值。问题似乎在于,每个维度的频率都没有严格按照升序输出(请参见here)。
fft.fft2
函数接受一个2D数组,在我的情况下,该数组(我们称之为A
)的结构使得A[i][j] = fun(x[i], y[j])
,fun
是被改造。在将fft.fft2
应用于A
之后,输出的是数组F
,其尺寸与原始数组相同,因此与F[i][j]
对应的频率坐标为(w_x[i], w_y[j])
,其中w_x = fft.fftfreq(F.shape[0])
和w_y = fft.fftfreq(F.shape[1])
都是不按升序排列的一维数组。
在wx
和wy
上我想对F
进行插值(例如对函数finterp
的插值),以便在调用finterp(w_x, w_y)
时返回插值,w_x
和w_y
在wx
的域内,并且在wy
的范围内,但其他情况下是任意的。我已经研究了scipy.interpolate提供的各种插值方法,但是在我看来,它们中的任何一个都不能处理这种类型的数据结构(坐标轴被定义为乱序一维数组和函数值在2D数组中)。
这有点抽象,所以在这里我组成了一个简单的示例,其结构与上述类似。假设我们希望在给定以下数据的情况下,在区域f(x, y) = x + y
和x = [-1, 1]
上构造一个连续函数y = [-1, 1]
:
import numpy as np
# note that below z[i][j] corresponds to what we want f(x[i], y[j]) to be
x = np.array([0, 1, -1])
y = np.array([0, 1, -1])
z = np.array([0, 1, -1],[1, 2, 0],[-1, 0, -2])
我们知道 z[i][j]
对应于x[i], y[j]
中评估的函数。如何要么(a)在给定其原始结构的情况下直接对数据进行插值,要么(b)重新排列数据以使x
和y
升序,而排列后的z
使得z[i][j]
等于重新排列的x[i], y[j]
求值的函数?
答案 0 :(得分:1)
以下代码显示如何使用fftshift
来更改fft2
和fftfreq
的输出,从而使频率轴单调递增。应用fftshift
后,可以使用数组进行插值。我添加了数组的显示,以便您可以验证数据本身是否不变。原点从数组的左上角移到数组的中间,将负频率从右侧移到左侧。
import numpy as np
import matplotlib.pyplot as pp
x = np.array([0, 1, -1])
y = np.array([0, 1, -1])
z = np.array([[0, 1, -1],[1, 2, 0],[-1, 0, -2]])
f = np.fft.fft2(z)
w_x = np.fft.fftfreq(f.shape[0])
w_y = np.fft.fftfreq(f.shape[1])
pp.figure()
pp.imshow(np.abs(f))
pp.xticks(np.arange(0,len(w_x)), np.round(w_x,2))
pp.yticks(np.arange(0,len(w_y)), np.round(w_y,2))
f = np.fft.fftshift(f)
w_x = np.fft.fftshift(w_x)
w_y = np.fft.fftshift(w_y)
pp.figure()
pp.imshow(np.abs(f))
pp.xticks(np.arange(0,len(w_x)), np.round(w_x,2))
pp.yticks(np.arange(0,len(w_y)), np.round(w_y,2))
pp.show()
另一种方法是不使用fftfreq
来确定您的频率,而是手动计算它们。默认情况下,FFT计算k=[0..N-1]
的DFT。由于周期性,k
处的DFT等于k+N
和k-N
处的DFT,因此通常将其输出解释为具有k=[N//2...(N-1)//2]
(但布置不同以匹配k=[0..N-1]
);这是k
返回的fftfreq
(返回k/N
)。
因此,您可以改说
N = f.shape[0]
w_x = np.linspace(0, N, N, endpoint=False) / N
现在您没有任何负频率,而是具有[0,N-1]/N
范围内的频率。