0

I'm retrieving the arrays holding the power levels and frequencies, respectively, of a signal from the plt.psd() method:

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

enter image description here Please ignore the green and red signals. Just the blue one is relevant for this question.

I'm able to have the peakutils.peak.indexes() method return the X and Y coordinates of a number of the most significant peaks (of the blue signal):

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]))

enter image description here As can be seen, the coordinates fit the blue peaks quite nicely.

What I'm not satisfied with is the number of peak coordinates I receive from the peak.indexes() method. I'd like to have only the coordinates of all peaks above a certain power level returned, e.g., -25 (which would then be exactly 5 peaks for the blue signal). According to the documentation of the peak.indexes() method this is done by providing the desired value as thres parameter.

But no matter what I try as thres, the method seems to entirely ignore my value and instead solely rely on the min_dist parameter to determine the number of returned peaks.

  • What is wrong with my threshold value (which I believe means "peaks above the lower 60% of the plot" in my code now) and how do I correctly specify a certain power level (instead of a percentage value)?

[EDIT]

I figured out that apparently the thres parameter can only take positive values between float 0. and 1. So, by changing my line slightly as follows I can now influence the number of returned peaks as desired:

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

But that still leaves me with the question whether it's possible to somehow limit the result to the five highest peaks (provided num_of_peaks above thres >= 5).

I believe something like the following would return the five highest values:

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

Unfortunately, though, negative values seem to be interpreted as the highest values in my power_lvls array. Can this line be changed such that (+)10 would be considered higher than, e.g., -40? Or is there another (better?) solution?

[EDIT 2]

These are the values I get as the six "highest" peaks: enter image description here

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))

After trying various things for hours without any improvement I'm starting to think that these are neither valleys nor peaks, just some "random" values?! Which leads me to believe that there is a problem with my argsort line that I have to figure out first?!

[EDIT 3]

The bottleneck.partition() method seems to return the correct values (even if apparently it does so in random order, not from leftmost peak to rightmost peak):

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

enter image description here Luckily, the order of the peaks is not important for what I have planned to do with the coordinates. I do, however, have to figure out yet how to match the Y values I have now to their corresponding X values ...

Also, while I do have a solution now, for learning purposes it would still be interesting to know what was wrong with my argsort attempt.

4

2 回答 2

0

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

于 2018-03-26T00:44:29.727 回答
0

我想出了如何找到相应的 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]))

现在我有了我的“峰值过滤”(一种),我最初试图通过弄乱threspeakutils.peak.indexes() 的值来实现。上面的代码给了我想要的结果: 在此处输入图像描述

于 2018-03-26T22:16:53.823 回答