为什么 peakutils.peak.indexes() 似乎忽略了提供的阈值?

Why does peakutils.peak.indexes() seem to ignore the provided threshold value?

我正在检索分别保存来自 plt.psd() 方法的信号的功率电平和频率的数组:

Pxx, freqs = plt.psd(signals[0], NFFT=2048, Fs=sdr.sample_rate/1e6, Fc=sdr.center_freq/1e6, scale_by_freq=True, color="green")

请忽略绿色和红色信号。只有蓝色的与这个问题相关。

我可以使用 peakutils.peak.indexes() 方法 return 许多最重要的峰(蓝色信号)的 X 和 Y 坐标:

power_lvls = 10*log10(Pxx/(sdr.sample_rate/1e6))
indexes = peakutils.peak.indexes(np.array(power_lvls), thres=0.6/max(power_lvls), min_dist=120)
print("\nX: {}\n\nY: {}\n".format(freqs[indexes], np.array(power_lvls)[indexes]))

可以看出,坐标非常适合蓝色峰。

我不满意的是我从 peak.indexes() 方法收到的峰值坐标的数量。我希望只有超过特定功率水平 returned 的所有峰值的坐标,例如 -25(这对于蓝色信号来说正好是 5 个峰值)。根据 peak.indexes() 方法的文档,这是通过提供所需的值作为 thres 参数来完成的。

但无论我如何尝试 thres,该方法似乎完全忽略了我的值,而是完全依赖 min_dist 参数来确定 returned 峰的数量.

[编辑]

我发现 thres 参数显然只能在浮点数 0 和 1 之间取正值。 因此,通过如下稍微更改我的线,我现在可以根据需要影响 returned 峰的数量:

indexes = peakutils.peak.indexes(np.array(power_lvls), thres=0.4, min_dist=1)

但这仍然给我留下了一个问题,是否有可能以某种方式将结果限制在五个最高峰(前提是 num_of_peaks 大于 thres >= 5)。

我相信像下面这样的东西会 return 五个最高值:

print(power_lvls[np.argsort(power_lvls[indexes])[-5:]])

不幸的是,负值似乎被解释为我的 power_lvls 数组中的最高值。是否可以更改此行,使 (+)10 被视为高于 -40 等?或者还有其他(更好的?)解决方案吗?

[编辑 2]

这些是我作为六个 "highest" 峰值得到的值:

power_lvls = 10*log10(Pxx/(sdr.sample_rate/1e6))+10*log10(8/3)
indexes = peakutils.indexes(power_lvls, thres=0.35, min_dist=1)

power_lvls_max = power_lvls[np.argsort(power_lvls[indexes])[-6:]]
print("Highest Peaks in Signal:\nX: \n\nY: {}\n".format(power_lvls_max))

在尝试了几个小时的各种事情而没有任何改善之后,我开始认为这些既不是谷也不是峰,只是一些 "random" 值?!这让我相信我必须首先弄清楚我的 argsort 行有问题吗?!

[编辑 3]

bottleneck.partition() 方法似乎 return 正确的值(即使显然它是以随机顺序执行的,而不是从最左峰到最右峰):

import bottleneck as bn
power_lvls_max = -bn.partition(-power_lvls[indexes], 6)[:6]

幸运的是,峰的顺序对于我计划用坐标做的事情并不重要。但是,我确实必须弄清楚如何将我现在拥有的 Y 值与其相应的 X 值相匹配...

此外,虽然我现在确实有解决方案,但出于学习目的,了解我的 argsort 尝试有什么问题仍然很有趣。

解决这个问题的一个简单方法是在处理之前向 Pxx 向量添加一个常数(例如 +50 dB)。这样你就可以避免 negative-valued 峰值。处理完成后,您可以再次减去常数以获得正确的峰值。

我想通了如何找到相应的 X 值并获得六个最高峰的完整坐标:

power_lvls = 10*log10(Pxx/(sdr.sample_rate/1e6))+10*log10(8/3)
indexes = peakutils.indexes(power_lvls, thres=0.35, min_dist=1)
print("Peaks in Signal 1\nX: {}\n\nY: {}\n".format(freqs[indexes], power_lvls[indexes]))
power_lvls_max = -bn.partition(-power_lvls[indexes], 6)[:6]
check = np.isin(power_lvls, power_lvls_max)
indexes_max = np.where(check)
print("Highest Peaks in Signal 1:\nX: {}\n\nY: {}\n".format(freqs[indexes_max], power_lvls[indexes_max]))

现在我有了我的 "peak filtering"(有点),我最初试图通过弄乱 peakutils.peak.indexes() 的 thres 值来实现。上面的代码只给了我想要的结果: