如何使用 fft 在频域中向正弦波添加相移?
How to add a phase shift to a sin wave in the frequency domain with fft?
我想在频域中移动一个正弦波
我的想法是:
- 傅里叶变换
- 在频域中添加 pi 的相移
- 逆傅里叶变换
在代码中:
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,但是我得到了这个结果
(无相移):
感谢您的帮助!
你没有进行相移。
你所做的是添加一个 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
的 real 部分)和单个 imaginary 尖峰,它的高度毫不奇怪地等于 π,因为t=0.
常数的变换是 ω=0 处的尖峰,常数(在频域中)的反变换是 t=0 处的尖峰.
正如我在删除的评论中所说,如果您不对每个 FFT 项 添加 一个常数,而是 将它们乘以 一个常数也将信号乘以相同的常数(记住,FFT 和 IFFT 是线性的)。
要做你想做的事,你必须记住时域中的偏移只是(周期性)信号与时移尖峰的(循环)卷积,所以你必须乘以 FFT移位尖峰的 FFT 信号。
因为狄拉克分布的傅立叶变换 δ(t-a) 是 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
为中心的 Dirac 分布的离散 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,FFT 的 IFFT 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();
很好,很有帮助!
对于任何想做同样事情的人,这里是一个 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()
我想在频域中移动一个正弦波
我的想法是:
- 傅里叶变换
- 在频域中添加 pi 的相移
- 逆傅里叶变换
在代码中:
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,但是我得到了这个结果
(无相移):
感谢您的帮助!
你没有进行相移。
你所做的是添加一个 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
的 real 部分)和单个 imaginary 尖峰,它的高度毫不奇怪地等于 π,因为t=0.
常数的变换是 ω=0 处的尖峰,常数(在频域中)的反变换是 t=0 处的尖峰.
正如我在删除的评论中所说,如果您不对每个 FFT 项 添加 一个常数,而是 将它们乘以 一个常数也将信号乘以相同的常数(记住,FFT 和 IFFT 是线性的)。
要做你想做的事,你必须记住时域中的偏移只是(周期性)信号与时移尖峰的(循环)卷积,所以你必须乘以 FFT移位尖峰的 FFT 信号。
因为狄拉克分布的傅立叶变换 δ(t-a) 是 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
为中心的 Dirac 分布的离散 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,FFT 的 IFFT 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();
很好,很有帮助! 对于任何想做同样事情的人,这里是一个 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()