功率谱密度图示例

在Matplotlib中绘制功率谱密度(PSD)。

PSD是信号处理领域中常见的图形。NumPy有许多用于计算PSD的有用库。下面,我们演示一些如何使用Matplotlib实现和可视化这一点的示例。

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import matplotlib.mlab as mlab
  4. import matplotlib.gridspec as gridspec
  5. # Fixing random state for reproducibility
  6. np.random.seed(19680801)
  7. dt = 0.01
  8. t = np.arange(0, 10, dt)
  9. nse = np.random.randn(len(t))
  10. r = np.exp(-t / 0.05)
  11. cnse = np.convolve(nse, r) * dt
  12. cnse = cnse[:len(t)]
  13. s = 0.1 * np.sin(2 * np.pi * t) + cnse
  14. plt.subplot(211)
  15. plt.plot(t, s)
  16. plt.subplot(212)
  17. plt.psd(s, 512, 1 / dt)
  18. plt.show()

功率谱密度图示例

将其与等效的Matlab代码进行比较,以完成相同的任务:

  1. dt = 0.01;
  2. t = [0:dt:10];
  3. nse = randn(size(t));
  4. r = exp(-t/0.05);
  5. cnse = conv(nse, r)*dt;
  6. cnse = cnse(1:length(t));
  7. s = 0.1*sin(2*pi*t) + cnse;
  8. subplot(211)
  9. plot(t,s)
  10. subplot(212)
  11. psd(s, 512, 1/dt)

下面,我们将展示一个稍微复杂一些的示例,演示填充如何影响产生的PSD。

  1. dt = np.pi / 100.
  2. fs = 1. / dt
  3. t = np.arange(0, 8, dt)
  4. y = 10. * np.sin(2 * np.pi * 4 * t) + 5. * np.sin(2 * np.pi * 4.25 * t)
  5. y = y + np.random.randn(*t.shape)
  6. # Plot the raw time series
  7. fig = plt.figure(constrained_layout=True)
  8. gs = gridspec.GridSpec(2, 3, figure=fig)
  9. ax = fig.add_subplot(gs[0, :])
  10. ax.plot(t, y)
  11. ax.set_xlabel('time [s]')
  12. ax.set_ylabel('signal')
  13. # Plot the PSD with different amounts of zero padding. This uses the entire
  14. # time series at once
  15. ax2 = fig.add_subplot(gs[1, 0])
  16. ax2.psd(y, NFFT=len(t), pad_to=len(t), Fs=fs)
  17. ax2.psd(y, NFFT=len(t), pad_to=len(t) * 2, Fs=fs)
  18. ax2.psd(y, NFFT=len(t), pad_to=len(t) * 4, Fs=fs)
  19. plt.title('zero padding')
  20. # Plot the PSD with different block sizes, Zero pad to the length of the
  21. # original data sequence.
  22. ax3 = fig.add_subplot(gs[1, 1], sharex=ax2, sharey=ax2)
  23. ax3.psd(y, NFFT=len(t), pad_to=len(t), Fs=fs)
  24. ax3.psd(y, NFFT=len(t) // 2, pad_to=len(t), Fs=fs)
  25. ax3.psd(y, NFFT=len(t) // 4, pad_to=len(t), Fs=fs)
  26. ax3.set_ylabel('')
  27. plt.title('block size')
  28. # Plot the PSD with different amounts of overlap between blocks
  29. ax4 = fig.add_subplot(gs[1, 2], sharex=ax2, sharey=ax2)
  30. ax4.psd(y, NFFT=len(t) // 2, pad_to=len(t), noverlap=0, Fs=fs)
  31. ax4.psd(y, NFFT=len(t) // 2, pad_to=len(t),
  32. noverlap=int(0.05 * len(t) / 2.), Fs=fs)
  33. ax4.psd(y, NFFT=len(t) // 2, pad_to=len(t),
  34. noverlap=int(0.2 * len(t) / 2.), Fs=fs)
  35. ax4.set_ylabel('')
  36. plt.title('overlap')
  37. plt.show()

功率谱密度图示例2

这是一个来自信号处理工具箱的MATLAB示例的移植版本,它显示了Matplotlib和MATLAB对PSD的缩放之间的一些差异。

  1. fs = 1000
  2. t = np.linspace(0, 0.3, 301)
  3. A = np.array([2, 8]).reshape(-1, 1)
  4. f = np.array([150, 140]).reshape(-1, 1)
  5. xn = (A * np.sin(2 * np.pi * f * t)).sum(axis=0)
  6. xn += 5 * np.random.randn(*t.shape)
  7. fig, (ax0, ax1) = plt.subplots(ncols=2, constrained_layout=True)
  8. yticks = np.arange(-50, 30, 10)
  9. yrange = (yticks[0], yticks[-1])
  10. xticks = np.arange(0, 550, 100)
  11. ax0.psd(xn, NFFT=301, Fs=fs, window=mlab.window_none, pad_to=1024,
  12. scale_by_freq=True)
  13. ax0.set_title('Periodogram')
  14. ax0.set_yticks(yticks)
  15. ax0.set_xticks(xticks)
  16. ax0.grid(True)
  17. ax0.set_ylim(yrange)
  18. ax1.psd(xn, NFFT=150, Fs=fs, window=mlab.window_none, pad_to=512, noverlap=75,
  19. scale_by_freq=True)
  20. ax1.set_title('Welch')
  21. ax1.set_xticks(xticks)
  22. ax1.set_yticks(yticks)
  23. ax1.set_ylabel('') # overwrite the y-label added by `psd`
  24. ax1.grid(True)
  25. ax1.set_ylim(yrange)
  26. plt.show()

功率谱密度图示例3

这是一个来自信号处理工具箱的MATLAB示例的移植版本,它显示了Matplotlib和MATLAB对PSD的缩放之间的一些差异。

它使用了一个复杂的信号,所以我们可以看到,复杂的PSD的工作正常。

  1. prng = np.random.RandomState(19680801) # to ensure reproducibility
  2. fs = 1000
  3. t = np.linspace(0, 0.3, 301)
  4. A = np.array([2, 8]).reshape(-1, 1)
  5. f = np.array([150, 140]).reshape(-1, 1)
  6. xn = (A * np.exp(2j * np.pi * f * t)).sum(axis=0) + 5 * prng.randn(*t.shape)
  7. fig, (ax0, ax1) = plt.subplots(ncols=2, constrained_layout=True)
  8. yticks = np.arange(-50, 30, 10)
  9. yrange = (yticks[0], yticks[-1])
  10. xticks = np.arange(-500, 550, 200)
  11. ax0.psd(xn, NFFT=301, Fs=fs, window=mlab.window_none, pad_to=1024,
  12. scale_by_freq=True)
  13. ax0.set_title('Periodogram')
  14. ax0.set_yticks(yticks)
  15. ax0.set_xticks(xticks)
  16. ax0.grid(True)
  17. ax0.set_ylim(yrange)
  18. ax1.psd(xn, NFFT=150, Fs=fs, window=mlab.window_none, pad_to=512, noverlap=75,
  19. scale_by_freq=True)
  20. ax1.set_title('Welch')
  21. ax1.set_xticks(xticks)
  22. ax1.set_yticks(yticks)
  23. ax1.set_ylabel('') # overwrite the y-label added by `psd`
  24. ax1.grid(True)
  25. ax1.set_ylim(yrange)
  26. plt.show()

功率谱密度图示例4

下载这个示例