如何计算自相关时间信号的相位谱

时间:2019-03-03 14:42:06

标签: python numpy matplotlib

赞赏一些有关如何计算自相关时间信号的相位谱的帮助。作为输入,我有一个时间序列飞行员,每2毫秒采样70秒。我可以计算出该信号的自相关,该自相关在时间零附近对称。功率谱看起来很好(除了缩放),但相位谱滞后于-200弧度。由于它在零时滞周围是对称的,因此我期望零相位频谱。问题是我不知道如何通知phase_spectrum信号是对称的,没有它我将无法理解相移。我该怎么解决?

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.mlab import window_none

file_name = 'pilot_signal.csv'
dt = 2/1000 # sampling interval is 2 ms
df = 1/dt # sampling frequency

pilot_df = pd.read_csv(file_name)
time = pilot_df['Time']
amplitude = pilot_df['Amplitude']

fig, ax = plt.subplots(nrows=4, ncols=1, figsize=(12, 7))

ax[0].set_title('pilot')
ax[0].set_xlim(0, 30000) # first 3 seconds only
ax[0].set_ylim(-175, 175)
ax[0].plot(time, amplitude)

ax[1].set_title('autocorrelation')
max_lag = 250
corr_function = np.correlate(amplitude, amplitude, mode='full')
corr_function = corr_function[(len(amplitude)-1)-(max_lag-1):(len(amplitude)-1)+max_lag]
time_lags = np.arange(-(max_lag-1), max_lag)
ax[1].plot(time_lags, corr_function)

ax[2].set_title('magnitude')
ax[2].set_xlim(0, 100)
scale = 'linear'  #  'dB' # or 'default'
ax[2].magnitude_spectrum(corr_function, Fs=df, scale=scale, window=window_none)

ax[3].set_title('phase')
ax[3].set_xlim(0, 100)
ax[3].phase_spectrum(corr_function, Fs=df, window=window_none)

plt.tight_layout()
plt.show()

结果: enter image description here

1 个答案:

答案 0 :(得分:0)

按照我自己的问题并按照注释中的建议获得正确的相位响应,首先需要对相关函数进行重新排序,从而使相关函数的正一半成为重新排序后的相关函数的前一半,并且负数部分变为下半部分。我对此的解决方案是:

cf_reordered = np.concatenate((corr_function[max_lag-1:], corr_function[0:max_lag-1]))

其中max_lag是t = 0之前,t = 0和len(cf_reordered) = 2*max_lag - 1之后的样本

(在程序中max_lag为257)

将所有示例程序放在一起,如下所示。因此,它还会检查相位值是否为模数2 * pi,并将其映射到-pi和+ pi之间。现在相位为2 Hz至90 Hz之间的零相位,这是正确的扫描范围,如底部结果所示。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.mlab import window_none

# values of the sweep are stored in pilot_signal.csv with following parameters:
# - sweep length: 64 seconds
# - start frequency: 2 Hz
# - end frequency: 90 Hz
# - amplitude between -100 and 100

file_name = 'pilot_signal.csv'
dt = 2/1000 # sampling interval is 2 ms
df = 1/dt # sampling frequency
pi = np.pi

pilot_df = pd.read_csv(file_name)
time = pilot_df['Time']
amplitude = pilot_df['Amplitude']

fig, ax = plt.subplots(nrows=5, ncols=1, figsize=(12, 7))

ax[0].set_title('pilot')
ax[0].set_xlim(0, 30000) # first 3 seconds only (expressed in ms)
ax[0].set_ylim(-150, 150)
ax[0].plot(time, amplitude)

ax[1].set_title('autocorrelation')
max_lag = 257
corr_function = np.correlate(amplitude, amplitude, mode='full') / len(amplitude)
corr_function = corr_function[(len(amplitude)-1)-(max_lag-1):(len(amplitude)-1)+max_lag]
time_lags = np.arange(-(max_lag-1), max_lag)
ax[1].plot(time_lags, corr_function)

ax[2].set_title('autocorrelation re-ordered')
cf_reordered = np.concatenate((corr_function[max_lag-1:], corr_function[0:max_lag-1]))
time_lags = np.arange(0, 2*max_lag-1)
ax[2].plot(time_lags, cf_reordered)
print(len(corr_function))
print(len(cf_reordered))

ax[3].set_title('magnitude')
ax[3].set_xlim(0, 100)
scale = 'linear'  #  'dB' # or 'default'
ax[3].magnitude_spectrum(corr_function, Fs=df, scale=scale, window=window_none)

ax[4].set_title('phase')
ax[4].set_ylim(-4, +4)
ax[4].set_xlim(0, 100)
# get the phase spectrum values and frequencies values; plot invisible and use a non default color
cf_phase_values, cf_freq, _ = ax[4].phase_spectrum(cf_reordered, Fs=df, window=window_none, visible=False, color='r')

# check for modulus 2*pi and keep values between -pi and pi
cf_phase_values = np.mod(cf_phase_values, 2*pi)
cf_phase_values[cf_phase_values>pi] -= 2*pi

ax[4].plot(cf_freq, cf_phase_values)

plt.tight_layout()
plt.show()

结果: enter image description here