matplotlib.mlab.psd() 函数中最大 PSD 频率箱的问题

在使用 matplotlib.mlab.psd() 函数时,开发人员发现返回的频率箱似乎不正确。
在这里插入图片描述

以下是测试代码:

import matplotlib.mlab as ml
import numpy as np

sampf = 500.
nfft = 2**4
testdat = np.random.randn(10000,)
p2, f2 = ml.psd(testdat, nfft, sampf, sides='twosided')
p1, f1 = ml.psd(testdat, nfft, sampf, sides='onesided')

print(testdat.shape)
print("Twosided")
print("\tbin1     : {:f} ".format(f2[0]))
print("\tbin2     : {:f} ".format(f2[1]))
print("\tbinlast  : {:f} ".format(f2[-1]))

print("onesided")
print("\tbin1     : {:f} ".format(f1[0]))
print("\tbin2     : {:f} ".format(f1[1]))
print("\tbinlast  : {:f} ".format(f1[-1]))

print("recreate")
f3 = np.arange(nfft) * (sampf / 2.) / nfft
print("\tbin1     : {:f} ".format(f3[0]))
print("\tbin2     : {:f} ".format(f3[1]))
print("\tbinlast  : {:f} ".format(f3[-1]))

输出结果如下:

Twosided
    bin1     : -250.000000
    bin2     : -218.750000
    binlast  : 218.750000
onesided
    bin1     : 0.000000
    bin2     : 31.250000
    binlast  : 250.000000
recreate
    bin1     : 0.000000
    bin2     : 15.625000
    binlast  : 234.375000

在双边模式下,最大频率 (binlast) 应该是采样频率的一半,但从输出结果可以看出,它与采样频率的一半相差一个箱位。
而在单边模式下,最大频率也比采样频率的一半小。

2、解决方案

根据一位答主提供的答案,这个问题与 matplotlib.mlab.psd() 函数的内部实现有关。

在单边模式下,matplotlib.mlab.psd() 函数不会返回负频率的箱位,因此最大频率只能达到采样频率的一半。

而在双边模式下,matplotlib.mlab.psd() 函数会返回负频率和正频率的箱位,但由于采样频率是偶数,因此最大频率无法达到采样频率的一半,而是会比采样频率的一半小一个箱位。

如果需要获得准确的频率箱位,可以使用以下方法:

import numpy as np

def psd(data, nfft=None, sampf=None, sides='default'):
  """
  Calculate the power spectral density (PSD) of a signal.

  Args:
    data: The input signal.
    nfft: The length of the FFT window.
    sampf: The sampling frequency.
    sides: The type of PSD to calculate. 'default' returns a two-sided PSD,
      'onesided' returns a one-sided PSD, and 'onlypositive' returns a PSD
      with only positive frequencies.

  Returns:
    A tuple containing the PSD and the corresponding frequencies.
  """

  # If no window is specified, use the entire signal.
  if nfft is None:
    nfft = len(data)

  # If no sampling frequency is specified, assume 1 Hz.
  if sampf is None:
    sampf = 1

  # Calculate the FFT of the signal.
  fft_data = np.fft.fft(data, nfft)

  # Calculate the power spectrum.
  psd = np.abs(fft_data)**2

  # If a one-sided PSD is requested, only return the positive frequencies.
  if sides == 'onesided':
    psd = psd[:nfft // 2 + 1]

  # If a positive-only PSD is requested, only return the positive frequencies.
  elif sides == 'onlypositive':
    psd = psd[:nfft // 2]

  # Calculate the corresponding frequencies.
  freqs = np.fft.fftfreq(nfft, d=1 / sampf)

  # If a one-sided PSD is requested, only return the positive frequencies.
  if sides == 'onesided':
    freqs = freqs[:nfft // 2 + 1]

  # If a positive-only PSD is requested, only return the positive frequencies.
  elif sides == 'onlypositive':
    freqs = freqs[:nfft // 2]

  return psd, freqs

通过这个函数可以准确地计算出PSD和相应的频率。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值