Python:如何对“非结构化”二维傅立叶变换数据进行插值

时间:2019-07-05 22:44:45

标签: python multidimensional-array scipy fft interpolation

我的目标是对函数的离散连续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])都是不按升序排列的一维数组。

wxwy上我想对F进行插值(例如对函数finterp的插值),以便在调用finterp(w_x, w_y)时返回插值,w_xw_ywx的域内,并且在wy的范围内,但其他情况下是任意的。我已经研究了scipy.interpolate提供的各种插值方法,但是在我看来,它们中的任何一个都不能处理这种类型的数据结构(坐标轴被定义为乱序一维数组和函数值在2D数组中)。

这有点抽象,所以在这里我组成了一个简单的示例,其结构与上述类似。假设我们希望在给定以下数据的情况下,在区域f(x, y) = x + yx = [-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)重新排列数据以使xy升序,而排列后的z使得z[i][j]等于重新排列的x[i], y[j]求值的函数?

1 个答案:

答案 0 :(得分:1)

以下代码显示如何使用fftshift来更改fft2fftfreq的输出,从而使频率轴单调递增。应用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+Nk-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范围内的频率。