You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何傅里叶变换子图中出现多余水平线?技术问询

FFT绘图时子图底部出现不明水平线的解决方法

问题描述

我正在绘制一组信号的傅里叶变换,每组数据仅包含一组y值,每个子图应仅显示一条曲线,但当前每个子图底部都出现了一条来源不明的水平线。

问题代码

def GenerateFFT(parsedData,T):
    colors = ["red","green","blue","purple","orange","cyan","pink","black"]
    parsedDataY=parsedData[1:]

    print(parsedDataY[len(parsedDataY)-1])
    fig, ax = plt.subplots(len(parsedDataY),sharex=True,sharey=True)
    #FourierValues = [[] for _ in range(4)]
    for i in range(len(parsedDataY)):
        signal = np.array(parsedDataY[i],dtype=float)
        N=signal.size   
        print(f"Signal Size at i={i}: {N}")
        
        x=np.arange(30.0,49.035,.005) # 此段代码未被使用,可删除
        
        fourier =  np.fft.fft(signal)  
        fourierFreq = np.fft.fftfreq(n=signal.size,d=1.0/T)

        #FourierValues[i].append(fourier)

        print(np.sqrt(np.sqrt(fourier.real**2+fourier.imag**2)).tolist)
        ax[i].plot(fourierFreq,np.sqrt(fourier.real**2+fourier.imag**2),color=colors[i],linewidth=.75)
        ax[i].set_yscale("log")
        ax[i].set_xbound(lower=-10,upper=10)
    plt.setp(ax, xlim=(0,10),ylim=ax[0].get_ylim())
    fig.suptitle("Fourier Transforms of Monochromatic Wavetrains with Amplitude Modulation",fontweight="bold")
    fig.supxlabel("Frequency (Hz)",fontweight="bold")
    fig.supylabel("Amplitude (cm) on Logarithmic Scale",fontweight="bold")
    
    plt.show()

注:parsedData为二维数组,parsedData[0]为时间步长值,其余索引对应y值数组。

问题原因

  1. 绘制了完整FFT频率范围:np.fft.fftfreq返回的频率包含正负两部分,直接绘制全部频率时,曲线会在正频率终点与负频率起点间产生跨x轴的跳跃线。虽通过xlim=(0,10)截断x轴,但这条跳跃线的部分片段会在子图底部异常显示。
  2. 冗余的x轴范围设置:同时使用set_xbound和plt.setp(ax, xlim=...)重复设置x轴范围,可能引发绘图逻辑冲突。
  3. 未处理信号异常值:若原始信号存在NaN/inf,FFT结果会出现异常幅值,在对数刻度下可能表现为底部水平线。

修复后的代码

def GenerateFFT(parsedData,T):
    colors = ["red","green","blue","purple","orange","cyan","pink","black"]
    parsedDataY=parsedData[1:]

    print(parsedDataY[-1])
    fig, ax = plt.subplots(len(parsedDataY), sharex=True, sharey=True)
    
    for i in range(len(parsedDataY)):
        signal = np.array(parsedDataY[i], dtype=float)
        # 处理信号中的NaN/inf值,避免FFT结果异常
        signal = np.nan_to_num(signal)
        N = signal.size   
        print(f"Signal Size at i={i}: {N}")
        
        fourier = np.fft.fft(signal)  
        fourierFreq = np.fft.fftfreq(n=signal.size, d=1.0/T)
        # 简化FFT幅值计算,与原公式结果一致
        fourier_amp = np.abs(fourier)

        # 筛选正频率部分,仅绘制有效范围的曲线
        positive_mask = fourierFreq > 0
        ax[i].plot(fourierFreq[positive_mask], fourier_amp[positive_mask], color=colors[i], linewidth=.75)
        ax[i].set_yscale("log")
    
    # 统一设置x轴范围,移除冗余的set_xbound
    plt.setp(ax, xlim=(0,10), ylim=ax[0].get_ylim())
    fig.suptitle("Fourier Transforms of Monochromatic Wavetrains with Amplitude Modulation", fontweight="bold")
    fig.supxlabel("Frequency (Hz)", fontweight="bold")
    fig.supylabel("Amplitude (cm) on Logarithmic Scale", fontweight="bold")
    
    plt.show()

关键修改点

  • 仅绘制正频率部分的FFT结果,消除正负频率间的跳跃线。
  • 用np.abs(fourier)简化幅值计算,效率更高且结果一致。
  • 添加np.nan_to_num(signal)处理信号异常值,避免FFT产生无效幅值。
  • 删除未使用的冗余代码,移除重复的x轴范围设置,统一用plt.setp控制轴范围。

内容的提问来源于stack exchange,提问作者Riderdie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 16:04:57