My goal is to interpolate the discretized continuous 2D Fourier transform of a function. The problem seems to be that the frequencies in each dimension are not output in strictly ascending order (see here ).
The fft.fft2
function accepts a 2D array, where in my case the array (let's call it A
) is structured such that A[i][j] = fun(x[i], y[j])
, fun
being the function to be transformed. After applying fft.fft2
to A
, output is an array F
of the same dimensions as the original array, such that the frequency coordinate corresponding to F[i][j]
is (w_x[i], w_y[j])
, where w_x = fft.fftfreq(F.shape[0])
and w_y = fft.fftfreq(F.shape[1])
, both of these being 1D arrays which are not in ascending order.
Over wx
and wy
I am wanting to interpolate F
(say to a function finterp
) such that the interpolated value is returned upon calling finterp(w_x, w_y)
, w_x
and w_y
being within the domain of wx
and range of wy
, but otherwise arbitrary. I've looked into the varieties of interpolation available through scipy.interpolate , but it doesn't seem to me that any of them can deal with this type of data structure (the coordinate axes being defined as out-of-order 1D arrays and the function values being in a 2D array).
This is a little abstract, so here I've made up a simple example which is similar in structure to the above. Suppose we are wishing to construct a continuous function f(x, y) = x + y
over the region x = [-1, 1]
and y = [-1, 1]
given the following data:
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]
we know corresponds to the function evaluated at x[i], y[j]
. How can one either (a) interpolate this data directly, given its original structure, or (b) rearrange the data so that x
and y
are in ascending order, and the arranged z
is such that z[i][j]
is equal to the function evaluated at the rearranged x[i], y[j]
?
The following code shows how to use fftshift
to change the output of fft2
and fftfreq
so that the frequency axes are monotonically increasing. After applying fftshift
, you can use the arrays for interpolation. I've added display of the arrays so that you can verify that the data itself is unchanged. The origin is shifted from the top-left corner to the middle of the array, moving the negative frequencies from the right side to the left side.
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()
An alternative approach is to not use fftfreq
to determine your frequencies, but compute them by hand. The FFT, by default, computes the DFT for k=[0..N-1]
. Because of the periodicity, with the DFT at k
equal to the DFT at k+N
and kN
, its output is often interpreted to have k=[N//2...(N-1)//2]
instead (but arranged differently to match k=[0..N-1]
); this is the k
that fftfreq
returns (it returns k/N
).
Thus, you can instead say
N = f.shape[0]
w_x = np.linspace(0, N, N, endpoint=False) / N
Now you don't have any negative frequencies, and instead have frequencies in the range [0,N-1]/N
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.