【问题标题】:How to add a phase shift to a sin wave in the frequency domain with fft?如何使用fft在频域中为正弦波添加相移?
【发布时间】:2019-12-02 14:52:30
【问题描述】:

我想在频域中移动一个正弦波

我的想法如下:

  1. 傅里叶变换
  2. 在频域中添加 pi 的相移
  3. 傅里叶逆变换

在代码中:

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 移动,但是我得到了这个结果

(无相移):

感谢您的帮助!

【问题讨论】:

  • 你缩放了幅度,没有应用相移。我建议你再看看相移方程。

标签: python numpy fft phase


【解决方案1】:

很好,有帮助! 对于任何想要做同样的事情的人,这是在一个 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()

【讨论】:

    【解决方案2】:

    你没有进行相移。

    您所做的是添加一个 6000 向量,例如 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 处的尖峰。 p>

    正如我在已删除的评论中所说,如果您不为每个 FFT 项添加一个常量,而是将它们一个常量,您将信号乘以相同的常数(请记住,FFT 和 IFFT 是线性的)。

    要做您想做的事,您必须记住,时域中的偏移只是(周期)信号与时移尖峰的(循环)卷积,因此您必须乘以信号的 FFT通过移位尖峰的 FFT。

    因为狄拉克分布 δ(ta) 的傅里叶变换是 exp(-iωa),您必须将信号的 FFT 的每一项乘以一个频率依赖项。


    一个例子

    一些准备工作

    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 为中心的狄拉克分布的离散FT 的函数,持续时间为N

    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();
    

    现在计算正确尖峰的 FFT(注意 π/4 = (4π)/16)、移位信号的 FFT、s.s. 的 FFT 的 IFFT。最后绘制我们的结果

    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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-11
      • 2019-06-18
      • 1970-01-01
      相关资源
      最近更新 更多