numpy 如何用FFT给频域的正弦波加一个相移?

8zzbczxx  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(155)

我想在频域中移动一个正弦波
我的想法如下:
1.傅里叶变换
1.在频域中添加pi的相移
1.傅里叶逆变换
在代码中:

t=np.arange(0, 6 , 0.001)
values = A*np.sin(t)
ft_values= np.fft.fft(values)
ft_values_phase=ft_values+1j*np.pi
back_again= np.fft.ifft(ft_values_phase)
plt.subplot(211)
plt.plot(t,values)
plt.subplot(212)
plt.plot(t,back_again)

我本以为会有两幅图像,其中一个波被pi移位了,但我得到了这个结果
(无相移):

谢谢你的帮助!

fdx2calv

fdx2calv1#

你没有做相移。
您所做的是将一个6,000向量,例如P,与P(I)=jπ相加到V,即v的FFT。
我们写Ṽ=V+P
由于FFT(和IFFT)的线性,您所说的back_again

  • ṽ=IFFT(Ṽ)=IFFT(V)+IFFT(P)=v+p*

当然,其中p=ifft(P)是差值values-back_again-现在,让我们来看看什么是p

In [51]: P = np.pi*1j*np.ones(6000) 
    ...: p = np.fft.ifft(P) 
    ...: plt.plot(p.real*10**16, label='real(p)*10**16') 
    ...: plt.plot(p.imag, label='imag(p)') 
    ...: plt.legend();

如您所见,您修改了values,添加了的一个实部,它本质上是IFFT计算中的数值噪声(因此,曲线图没有变化,这给您提供了back_again实部)和一个虚构的尖峰,其高度毫不奇怪地等于π,对于t=0*。
常数的变换是ω=0处的尖峰,常数的反变换(在频域中)是t=0处的尖峰。
另一方面,如果你将每个FFT项乘以一个常量,你也会将时间域信号乘以相同的常量(记住,FFT和IFFT是线性的)。
要做你想做的事情,你必须记住,时间域中的移位只是(周期)信号与时移尖峰的(循环)卷积,所以你必须将信号的FFT乘以移位尖峰的FFT。
因为狄拉克分布的傅里叶变换*δ(t-a)ω(-iωa)*你必须将信号的FFT的每一项乘以一个与频率有关的项,exp(-iωa)=cos(ωa)-i·Sin(FFT A)(注:当然这些乘法项中的每一个都有单位幅度)。

举个例子

一些开场白

In [61]: import matplotlib.pyplot as plt 
    ...: import numpy as np                                                                                           
In [62]: def multiple_formatter(x, pos, den=60, number=np.pi, latex=r'\pi'): 
             ... # search on SO for an implementation
In [63]: def plot(t, x): 
    ...:     fig, ax = plt.subplots() 
    ...:     ax.plot(t, x) 
    ...:     ax.xaxis.set_major_formatter(plt.FuncFormatter(multiple_formatter)) 
    ...:     ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) 
    ...:     ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4))

计算周期为N的以n为中心的狄拉克分布的离散FT的函数

In [64]: def shift(n, N): 
    ...:     s = np.zeros(N) 
    ...:     s[n] = 1.0 
    ...:     return np.fft.fft(s)

让我们画出一个信号和移位的信号

In [65]: t = np.arange(4096)*np.pi/1024                                                                               
In [66]: v0 = np.sin(t)                                                                                               
In [67]: v1 = np.sin(t-np.pi/4)                                                                                       
In [68]: f, a = plot(t, v0)                                                                                           
In [69]: a.plot(t, v1, label='shifted by $\\pi/4$');                                                                   
In [70]: a.legend();

现在计算正确尖峰的快速傅立叶变换(注意π/4=(4π)/16)、移位信号的快速傅立叶变换、S.S.的快速傅立叶变换。最后画出我们的结果

In [71]: S = shift(4096//16-1, 4096)                                                                                  
In [72]: VS = np.fft.fft(v0)*S                                                                                        
In [73]: vs = np.fft.ifft(VS)                                                                                         
In [74]: f, ay = plot(t, v0)                                                                                          
In [75]: ay.plot(t, vs.real, label='shifted in frequency domain');                                                    
In [76]: ay.legend();

brtdzjyr

brtdzjyr2#

很好,这很有帮助!对于任何想要做同样的事情的人,下面是一个python文件:

import numpy as np
from matplotlib.pyplot import plot, legend
def shift(n, N): 
    s = np.zeros(N) 
    s[n] = 1.0 
    return np.fft.fft(s)  
t = np.linspace(0, 2*np.pi,1000) 
v0 = np.sin(t)                                                                                               
S = shift(1000//4, 1000)  # shift by pi/4
VS = np.fft.fft(v0)*S 
vs = np.fft.ifft(VS)
plot(t, v0 , label='original' )
plot(t,vs.real,label='shifted in frequency domain')
legend()

相关问题