幅度和相位频谱。移相使幅度保持不变

时间:2018-09-05 07:53:08

标签: python signal-processing fft ifft phase

我有在相关点具有相等间隔和相应测量值的数据。例如,这是我拥有的数据的摘录:

  y = [2.118,2.1289,   2.1374,   2.1458,   2.1542,   2.1615,   2.1627,   2.165   2.1687 ...]

两点之间的间隔是0.1

因此,我需要从数据中得出的是振幅频谱(振幅与频率)以及相位频谱(相位角与频率)。 另外,我应该将数据的相位偏移负90度(-pi / 2)。

在移动相位并保持振幅不变的情况下,我需要做反fft并获得新信号。我想用Python做到这一点。

能否请您举一个执行此操作的示例。

我使用的代码来自另一个SO问题,但是我做了一些修改

## Perform FFT WITH SCIPY
signalFFT = np.fft.fft(y)

## Get Power Spectral Density
signalPSD = np.abs(signalFFT) ** 2
signalPhase = np.angle(signalFFT)

## Shift the phase py +90 degrees
new_signalPhase =(180/np.pi)*np.angle(signalFFT)+90 


## Get frequencies corresponding to signal 
fftFreq = np.fft.fftfreq(len(signalPSD), 0.1)

## Get positive half of frequencies
i = fftFreq>0

##
plt.figurefigsize=(8,4)
#plt.plot(fftFreq[i], 10*np.log10(signalPSD[i]));

plt.plot(fftFreq[i], new_signalPhase[i]);
plt.ylim(-200, 200);
plt.xlabel('Frequency Hz');
plt.ylabel('Phase Angle')
plt.grid()
plt.show()

问题是我想重新生成具有相同幅度但相移的信号。我知道答案与ifft有关,但是我应该如何准备数据呢?您能给我建议进一步的步骤吗?

output

1 个答案:

答案 0 :(得分:0)

这是经过一些修改的代码。我们应用傅立叶变换,对变换后的信号进行相移,然后执行傅立叶逆变换,以产生相移的时域信号。

请注意,转换是通过 rfft() irfft()完成的,并且相移是通过将转换后的数据乘以 cmath来完成的.rect(1.,phase)。相移等效于将复数变换后的信号乘以exp(i * phase)。

在图形的左面板中,我们显示原始信号和移位信号。新信号超前90度。在右面板中,我们在左轴上显示功率谱。在此示例中,我们具有单个频率的功率。相位在右轴上绘制。但是同样,由于我们只有一个频率有功率,所以相位频谱在其他任何地方都显示出噪声。

#!/usr/bin/python

import matplotlib.pyplot as plt
import numpy as np
import cmath

# Generate a model signal
t0 = 1250.0
dt = 0.152
freq = (1./dt)/128

t = np.linspace( t0, t0+1024*dt, 1024, endpoint=False )
signal = np.sin( t*(2*np.pi)*freq )

## Fourier transform of real valued signal
signalFFT = np.fft.rfft(signal)

## Get Power Spectral Density
signalPSD = np.abs(signalFFT) ** 2
signalPSD /= len(signalFFT)**2

## Get Phase
signalPhase = np.angle(signalFFT)

## Phase Shift the signal +90 degrees
newSignalFFT = signalFFT * cmath.rect( 1., np.pi/2 )

## Reverse Fourier transform
newSignal = np.fft.irfft(newSignalFFT)

## Uncomment this line to restore the original baseline
# newSignal += signalFFT[0].real/len(signal)


# And now, the graphics -------------------

## Get frequencies corresponding to signal 
fftFreq = np.fft.rfftfreq(len(signal), dt)

plt.figure( figsize=(10, 4) )

ax1 = plt.subplot( 1, 2, 1 )
ax1.plot( t, signal, label='signal')
ax1.plot( t, newSignal, label='new signal')
ax1.set_ylabel( 'Signal' )
ax1.set_xlabel( 'time' )
ax1.legend()

ax2 = plt.subplot( 1, 2, 2 )
ax2.plot( fftFreq, signalPSD )
ax2.set_ylabel( 'Power' )
ax2.set_xlabel( 'frequency' )

ax2b = ax2.twinx()
ax2b.plot( fftFreq, signalPhase, alpha=0.25, color='r' )
ax2b.set_ylabel( 'Phase', color='r' )


plt.tight_layout()

plt.show()

这是图形输出。

Raw and shifted signals, power and phase spectrum