用Python的Scipy库5分钟实现APSD与CPSD分析:工程师的实战指南

在振动测试、声学工程或通信系统设计中,功率谱分析是诊断信号特征的核心工具。但传统教材中繁琐的傅里叶变换推导和数学公式,往往让工程师们望而却步。本文将展示如何用Python的Scipy库, 跳过理论推导直接获得可落地的分析结果 ——从生成测试信号到绘制专业级频谱图,整个过程不超过20行代码。

1. 环境准备与数据生成

1.1 基础库安装

确保已安装以下Python库(推荐使用Anaconda环境):

pip install numpy scipy matplotlib

1.2 模拟真实场景信号

我们构造一个包含1Hz主频、高斯噪声和干扰谐波的复合信号:

import numpy as np
import matplotlib.pyplot as plt

fs = 1000  # 采样频率1kHz
t = np.arange(0, 5, 1/fs)  # 5秒时长

# 构造测试信号:基波+噪声+干扰
signal = (1.5 * np.sin(2*np.pi*50*t) +         # 主频50Hz
          0.3 * np.random.randn(len(t)) +       # 高斯噪声
          0.8 * np.cos(2*np.pi*120*t))          # 120Hz干扰

提示:实际工程数据可直接替换此处的 signal 数组,保持相同采样率即可

2. 自功率谱密度(APSD)分析

2.1 Welch方法核心参数解析

Scipy的 welch 函数提供三个关键参数:

  • fs :采样频率(必须与实际一致)
  • nperseg :每段样本数(决定频率分辨率)
  • window :窗函数类型(默认'Hann')
from scipy.signal import welch

f, Pxx = welch(signal, fs=fs, nperseg=1024, 
               window='hann', scaling='density')

plt.figure(figsize=(10,4))
plt.semilogy(f, Pxx)
plt.xlabel('Frequency [Hz]')
plt.ylabel('PSD [V**2/Hz]')
plt.grid(True)

2.2 参数选择黄金法则

参数 推荐值 作用
nperseg 1024-4096 值越大频率分辨率越高
noverlap nperseg//2 50%重叠降低方差
window 'hann'/'flattop' 抑制频谱泄漏

3. 互功率谱密度(CPSD)实战

3.1 双通道信号相关性分析

假设我们有两个传感器采集的振动信号:

# 生成相位差45度的相关信号
signal1 = np.sin(2*np.pi*30*t) 
signal2 = np.sin(2*np.pi*30*t + np.pi/4) 

f, Cxy = csd(signal1, signal2, fs=fs, nperseg=512)
coherence = np.abs(Cxy)**2 / (Pxx1 * Pxx2)  # 相干性计算

3.2 结果可视化技巧

fig, (ax1, ax2) = plt.subplots(2, 1)

# 幅值谱
ax1.semilogy(f, np.abs(Cxy))
ax1.set_ylabel('CPSD [V**2/Hz]')

# 相位谱
ax2.plot(f, np.angle(Cxy, deg=True)) 
ax2.set_xlabel('Frequency [Hz]')
ax2.set_ylabel('Phase [deg]')

4. 工程应用中的避坑指南

4.1 常见问题排查表

现象 可能原因 解决方案
频谱毛刺多 噪声过大 增加nperseg
幅值偏低 窗函数损耗 改用'flattop'窗
频率偏移 采样率错误 检查fs参数

4.2 高级技巧三则

  1. 降噪处理 :在计算PSD前先进行带通滤波

    from scipy.signal import butter, filtfilt
    b, a = butter(4, [20, 80], fs=fs, btype='band')
    signal_filt = filtfilt(b, a, signal)
    
  2. 批量分析 :用 spectrogram 实现时频分析

    f, t, Sxx = spectrogram(signal, fs=fs)
    plt.pcolormesh(t, f, 10*np.log10(Sxx))
    
  3. 单位转换 :将PSD转换为dB尺度

    Pxx_dB = 10 * np.log10(Pxx / (1e-6)**2)  # 转换为μV^2/Hz
    

在最近的风机振动监测项目中,我们发现当 nperseg 设置为2048时,能够清晰识别出轴承的故障特征频率(约87Hz),而默认的256点设置则完全无法检测。这印证了参数选择对结果的决定性影响—— 没有放之四海而皆准的默认值,只有最适合当前数据的配置

更多推荐