我想将一个函数与傅立叶空间中的数值积分进行整合。
以下代码显示了一个工作示例:
import numpy as np
from pylab import *
from numpy.fft import fft, ifft, fftshift, ifftshift
N = 2**16
x = np.linspace(- np.pi , np.pi,N)
y = np.exp(-x**2) # function f(x)
ys = np.exp(-x**2) * (-2*x) # derivative f'(x)
T = x[-1] - x[0] # the whole range
w = (np.arange(N) - N /2.) / T + 0.00000001 # slightly shifted
# integration
fourier = ifft(ifftshift(1./ ( 2 * np.pi * 1j * w) * fftshift(fft(ys)) ) )
# differentiation
fourier2 = ifft(ifftshift(( 2 * np.pi * 1j * w) * fftshift(fft(fourier)) ) )
您可能会注意到+ 0.00000001
频率定义中的w
。我需要它,因为否则我会生成ZeroDivisionError或numpy警告。这是一种解决方法,对于上面的示例似乎没有问题,但它无法解决我遇到的更复杂的问题。一位同事告诉我,如果我得到移位频率值(np.arange(N) - N /2. + 1./2) / T
的fft,我可以简单地避开它。如何在numpy中做到这一点?有没有办法指定numpy fft的输出网格?
谢谢!
答案 0 :(得分:4)
问题是w
包含0(应该如此),并除以w
。 w
中的0是" DC"频率;它对应于傅立叶级数的常数项。
如果将函数与具有系数A0的非零DC分量集成,则结果函数包括A0 * t形式的项,该项不在此傅里叶技术适用的周期函数的空间中。因此,您必须假设输入的DC分量为0.在这种情况下,当除以w
时,您将得到(0 + 0j)/ 0,即(nan+nanj)
。如果输入的DC分量不为零,则您将获得(inf+nanj)
。无论哪种方式,解决方案都是简单地忽略你得到的任何东西,并在用ifft
反转之前将DC傅立叶系数设置为0。
有几种方法可以实现这一点。一种方法是更改这些行:
w = (np.arange(N) - N /2.) / T + 0.00000001 # slightly shifted
# integration
fourier = ifft(ifftshift(1./ ( 2 * np.pi * 1j * w) * fftshift(fft(ys)) ) )
到此(我添加了几个中间变量):
w = (np.arange(N) - N /2.) / T
# integration
Fys = fft(ys)
with np.errstate(divide="ignore", invalid="ignore"):
modFys = ifftshift(1./ (2 * np.pi * 1j * w) * fftshift(Fys))
# modFys[0] will hold the result of dividing the DC component of y by 0, so it
# will be nan or inf. Setting modFys[0] to 0 amounts to choosing a specific
# constant of integration.
modFys[0] = 0
fourier = ifft(modFys).real
我也接受了ifft
结果的真实部分。从理论上讲,虚部应该都是0;在实践中,由于正常的不精确浮点运算,它们将非常小但非零。
顺便说一下,如果您不想实现自己的此技术版本,可以使用scipy.fftpack.diff
。