使用 matplotlib 绘制正弦波的傅立叶变换

Plot a fourier transform of a sin wav with matplotlib

我正在尝试根据 scipy documentation

绘制符号波的傅立叶变换
import numpy as np
import matplotlib.pyplot as plt
import scipy.fft

def sinWav(amp, freq, time, phase=0):
    return amp * np.sin(2 * np.pi * (freq * time - phase))

def plotFFT(f, speriod, time):
    """Plots a fast fourier transform

    Args:
        f (np.arr): A signal wave
        speriod (int): Number of samples per second
        time ([type]): total seconds in wave
    """

    N = speriod * time
    # sample spacing
    T = 1.0 / 800.0
    x = np.linspace(0.0, N*T, N, endpoint=False)

    yf = scipy.fft.fft(f)
    xf = scipy.fft.fftfreq(N, T)[:N//2]
    plt.plot(xf, 2.0/N * np.abs(yf[0:N//2]))
    plt.grid()
    plt.xlim([1,3])
    plt.show()


speriod = 1000
time  = {
    0: np.arange(0, 4, 1/speriod),
    1: np.arange(4, 8, 1/speriod),
    2: np.arange(8, 12, 1/speriod)
}

signal = np.concatenate([
    sinWav(amp=0.25, freq=2, time=time[0]),
    sinWav(amp=1, freq=2, time=time[1]),
    sinWav(amp=0.5, freq=2, time=time[2])
])   # generate signal

plotFFT(signal, speriod, 12)

期望输出

我想要一个像这样的傅立叶变换图

当前输出

但它看起来像这样


额外

这是我正在处理的正弦波

import numpy as np
import matplotlib.pyplot as plt
import scipy.fft

def sinWav(amp, freq, time, phase=0):
    return amp * np.sin(2 * np.pi * (freq * time - phase))

def plotFFT(f, speriod, time):
    """Plots a fast fourier transform

    Args:
        f (np.arr): A signal wave
        speriod (int): Number of samples per second
        time ([type]): total seconds in wave
    """

    N = speriod * time
    # sample spacing
    T = 1.0 / 800.0
    x = np.linspace(0.0, N*T, N, endpoint=False)

    yf = scipy.fft.fft(f)
    xf = scipy.fft.fftfreq(N, T)[:N//2]

    amplitudes = 1/speriod* np.abs(yf[:N//2])
  
    plt.plot(xf, amplitudes)
    plt.grid()
    plt.xlim([1,3])
    plt.show()


speriod = 800
time  = {
    0: np.arange(0, 4, 1/speriod),
    1: np.arange(4, 8, 1/speriod),
    2: np.arange(8, 12, 1/speriod)
}

signal = np.concatenate([
    sinWav(amp=0.25, freq=2, time=time[0]),
    sinWav(amp=1, freq=2, time=time[1]),
    sinWav(amp=0.5, freq=2, time=time[2])
])   # generate signal

plotFFT(signal, speriod, 12)

你应该有你想要的。您的振幅未正确计算,因为您的分辨率和周期不一致。

更长的数据采集:

import numpy as np
import matplotlib.pyplot as plt
import scipy.fft

def sinWav(amp, freq, time, phase=0):
    return amp * np.sin(2 * np.pi * (freq * time - phase))

def plotFFT(f, speriod, time):
    """Plots a fast fourier transform

    Args:
        f (np.arr): A signal wave
        speriod (int): Number of samples per second
        time ([type]): total seconds in wave
    """

    N = speriod * time
    # sample spacing
    T = 1.0 / 800.0
    x = np.linspace(0.0, N*T, N, endpoint=False)

    yf = scipy.fft.fft(f)
    xf = scipy.fft.fftfreq(N, T)[:N//2]

    amplitudes = 1/(speriod*4)* np.abs(yf[:N//2])
  
    plt.plot(xf, amplitudes)
    plt.grid()
    plt.xlim([1,3])
    plt.show()


speriod = 800
time  = {
    0: np.arange(0, 4*4, 1/speriod),
    1: np.arange(4*4, 8*4, 1/speriod),
    2: np.arange(8*4, 12*4, 1/speriod)
}

signal = np.concatenate([
    sinWav(amp=0.25, freq=2, time=time[0]),
    sinWav(amp=1, freq=2, time=time[1]),
    sinWav(amp=0.5, freq=2, time=time[2])
])   # generate signal

plotFFT(signal, speriod, 48)

您也可以交互式绘制此图。您可能需要安装 pip install scikit-dsp-comm

# !pip install scikit-dsp-comm
# Make an interactive version of the above
from ipywidgets import interact, interactive
import numpy as np
import matplotlib.pyplot as plt
from scipy import fftpack

plt.rcParams['figure.figsize'] = [10, 8]

font = {'weight' : 'bold',
        'size'   : 14}
plt.rc('font', **font)


def pulse_plot(fm = 1000, Fs = 2010):
    tlen = 1.0  # length in seconds
    # generate time axis
    tt = np.arange(np.round(tlen*Fs))/float(Fs)
    # generate sine
    xt = np.sin(2*np.pi*fm*tt)
    plt.subplot(211)
    plt.plot(tt[:500], xt[:500], '-b')
    plt.plot(tt[:500], xt[:500], 'or', label='xt values')
    plt.ylabel('$x(t)$')
    plt.xlabel('t [sec]')
    strt2 = 'Sinusoidal Waveform $x(t)$'
    strt2 = strt2 + ', $f_m={}$ Hz, $F_s={}$ Hz'.format(fm, Fs)
    plt.title(strt2)
    plt.legend()
    plt.grid()
    X = fftpack.fft(xt)
    freqs = fftpack.fftfreq(len(xt)) * Fs
    plt.subplot(212)
    N = xt.size
    # DFT
    X = np.fft.fft(xt)
    X_db = 20*np.log10(2*np.abs(X)/N)
    #f = np.fft.fftfreq(N, 1/Fs)
    f = np.arange(0, N)*Fs/N
    plt.plot(f, X_db, 'b')
    plt.xlabel('Frequency in Hertz [Hz]')
    plt.ylabel('Frequency Domain\n (Spectrum) Magnitude')
    plt.grid()
    plt.tight_layout()
    
    
interactive_plot = interactive(pulse_plot,fm = (1000,20000,1000), Fs = (1000,40000,10));
output = interactive_plot.children[-1]
# output.layout.height = '350px'
interactive_plot