用Python实现不精确的傅里叶变换

用Python实现不精确的傅里叶变换,python,scipy,transform,fft,continuous-fourier,Python,Scipy,Transform,Fft,Continuous Fourier,我的目标是对一个分布进行傅里叶变换。这是一个物理问题,我试图将函数从位置空间转换为动量空间。然而,我发现当我尝试使用scipys fft进行傅里叶变换时,它会变得参差不齐,而预期的是平滑的形状。我认为这与抽样有关,但我无法找出问题所在 这就是转换后的函数当前的样子: 这就是它的大致外观(它的宽度可能略有不同,但在平滑度方面应该类似): 下面是用于生成蓝色图像的代码: from scipy.fft import fft, fftfreq, fftshift import numpy as np

我的目标是对一个分布进行傅里叶变换。这是一个物理问题,我试图将函数从位置空间转换为动量空间。然而,我发现当我尝试使用scipys fft进行傅里叶变换时,它会变得参差不齐,而预期的是平滑的形状。我认为这与抽样有关,但我无法找出问题所在

这就是转换后的函数当前的样子:

这就是它的大致外观(它的宽度可能略有不同,但在平滑度方面应该类似):

下面是用于生成蓝色图像的代码:

from scipy.fft import fft, fftfreq, fftshift
import numpy as np
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack
import scipy
from scipy import interpolate
from scipy import integrate
# number of signal points
x = np.load('xvalues.npy') #Previously generated x values
y=np.load('function_to_be_transformed.npy') #Previously generated function (with same number of values as x)
y = np.asarray(y).squeeze() 
f = interpolate.interp1d(x, y) #interpolating data to make accessible function

N = 80000
# sample spacing
T = 1.0 / 80000.0
x = np.linspace(-N*T, N*T, N)
y=f(x)
yf = fft(y)
xf = fftfreq(N, T)
xf = fftshift(xf)
yplot = fftshift(yf)
import matplotlib.pyplot as plt
plt.plot(x,np.abs(f(x))**2)
plt.xlabel('x')
plt.ylabel(r'$|\Psi(x)|^2$')
plt.savefig("firstPo.eps", format="eps")
plt.show()

plt.plot(xf, np.abs(1.0/N * np.abs(yplot))**2)
plt.xlim(right=100.0)  # adjust the right leaving left unchanged
plt.xlim(left=-100.0)  # adjust the left leaving right unchanged
#plt.grid()
plt.ylabel(r'$|\phi(p)|^2$')
plt.xlabel('p')
plt.savefig("firstMo.eps", format="eps")
plt.show()

更新
如果有人能提供进一步的建议,那就太好了,因为我仍然有困难。根据@ScottStensland的评论,我试图找到一个正弦波的FT,看看我是否发现了任何问题,然后将这个例子重新改造到我最初的问题上。 以下是sin(x)FT的结果:

这是意料之中的(我想)。但是,当我通过初始示例将代码改装回时,我得到了以下结果(上图是我的初始发行版):

sin(x)示例的代码如下所示:

对于我自己的一次尝试:

#Interpolated Function
# sin wave
import numpy as np
from numpy import arange
from numpy.fft import rfft
from math import sin,pi
import matplotlib.pyplot as plt
x = np.linspace(-1.0,1.0,1001) #Previously generated x values
y=np.load('function_to_be_transformed.npy') #Previously generated function (with same number of values as x)
y = np.asarray(y).squeeze()
N=1001
x=np.arange(-1.0,1.0,2.0/N)

#y=map(f,x)
#print(y)
plt.plot(x,y)
plt.show()
c=rfft(y)       
plt.plot(abs(c))    
plt.show()
相关文件如下:
问题在于,无论
N
有多大,您想要解决的细节的分辨率都是有限的。您需要扩展原始x的限制,使用插值重新采样在那里没有任何作用。下面是一个运行示例:我创建了一个与您类似的数据集。查看当离开
x
限制时,如果将
loc
设置为2、50、80会发生什么情况

从scipy.fftpack导入fft、fftshift、fftfreq、ifft
loc=2
x=np.linspace(-13013010000)
y1=np.exp(-(x-loc)**2)/(2**2))
y2=np.exp(-(x+loc)**2)/(2**2))
y=y1+y2
plt.图()
平面图(x,y)
xf=fft换档(fftfreq(len(x),np.diff(x)[0]))
yf=ifft(y)
plt.图()
plt.绘图(FFT换档(xf),np.防抱死制动系统(yf))
plt.xlim(-0.5,.5)
随着尖峰之间的距离越来越远,您需要扩展域的限制以实现相同的分辨率

将此应用于您的示例:

将numpy导入为np
将matplotlib.pyplot作为plt导入
从scipy.interpolate导入interp1d
从scipy.fftpack导入fft、ifft、fftfreq、fftshift
x=np.load('xvalues.npy')
y=np.load('function_to_be_transformed.npy').ravel()
f=interp1d(x,y,fill_value=“extraction”)
N=1000000
#我做了一个更大的域名
x=np.linspace(10*x[0],10*x[-1],N)
y=f(x)
xf=fft换档(fftfreq(len(x),np.diff(x)[0]))
yf=ifft(y)
plt.图()
plt.绘图(FFT换档(xf),np.防抱死制动系统(yf))
plt.xlim(-30,30)

请注意,外推是危险的,在本例中它恰好起作用。在执行此操作之前,您始终希望确保外推确实返回您想要的曲线,并且不会弄乱任何东西。

当加快傅立叶变换的速度时,通常从简单的正弦曲线开始作为时域输入非常有用。。。将其输入fft调用,并将其绘制为频域数据。。。确认您看到的是与已知输入匹配的已知频率。。。然后将频域数据输入傅里叶逆变换,合成时域信号,该信号应与原始正弦曲线输入匹配或非常接近。。。使用这个简单的已知输入非常有助于从代码中找出纠结,并获得许多选项的赏识,这些选项可用于绘制频谱,而无需先插值。同时绘制插值信号,确保其看起来与您认为的一样。我不知道你的输入x和y值是什么样子,你确定你的输入x从-1变为1吗?如果不是,你可能会切断部分数据,甚至是推断。我觉得整个插值数据业务都很糟糕。你不应该这么做。@CrisLuengo谢谢你的回答,我已经检查过了,插值图与我最初绘制的数组完全相同。输入肯定从1变为-1,我只是插值,因为我不知道如何直接变换数组。@ScottStensland谢谢你的回答,我将尝试一下正弦波,看看是否能找到修复的方法it@ScottStensland我听从了你的建议,似乎得到了一个类似的、参差不齐的结果(虽然它为正弦波的变换返回了一条平滑的曲线)。
#Interpolated Function
# sin wave
import numpy as np
from numpy import arange
from numpy.fft import rfft
from math import sin,pi
import matplotlib.pyplot as plt
x = np.linspace(-1.0,1.0,1001) #Previously generated x values
y=np.load('function_to_be_transformed.npy') #Previously generated function (with same number of values as x)
y = np.asarray(y).squeeze()
N=1001
x=np.arange(-1.0,1.0,2.0/N)

#y=map(f,x)
#print(y)
plt.plot(x,y)
plt.show()
c=rfft(y)       
plt.plot(abs(c))    
plt.show()