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