How to sort an array and find the two highest peaks after using find_peaks from Scipy

I am struggling find_peaks a little...

Im applying a cubic spline to some data, from which I want to extract some peaks. However, the data may have several peaks, while I only want the two largest. I can find the peaks

peak_data = signal.find_peaks(spline, height=0.3, distance=50)

I can use this to get the x and y values at the index points within peak_data

peak_vals = spline[peak_data[0]]
time_vals = xnew[peak_data[0]] # xnew being thee splined x-axis

I thought I could order the peak_vals and keep the first two values (ie highest and second highest peaks) and then use that to get the time from xnew which coincides with those values. However, I am unable to use .sort which returns

AttributeError: 'tuple' object has no attribute 'sort'

or sorted() which returns

TypeError: '>' not supported between instances of 'int' and 'dict'

I think this is because it is indexing from a Numpy array (the spline data) and therefore creates another numpy array which then does not work either of the sort commands.

The best I can manage is to iterate through to a new list and then grab the first two values from that:

peak_val1=[]

peak_vals = spline[peak_data[0]]
    for i in peak_val_d:
        peak_val1.append(i)
peak_val1.sort(reverse=True)
peak_val2 = peak_val1[0:2]

This works but seems a tremendously long winded way to do this given that I still need to index the time values. I'm sure that there must be a faster (simpler) way?

Added Note: I realise that find_peaks returns an index list, but it actually seems to contain both index's and max values in and array-dictionary?? (sorry Im very new to python and curly braces means dictionary but it doesn't look like a simple dict). Anyway... print(peak_data) returns both the index positions and their values.

(array([ 40, 145, 240, 446]), {'peak_heights': array([0.34588031, 0.43761898, 0.45778744, 0.74167977])})

Is there a way to directly access these data perhaps?

1 answer

  • answered 2018-10-10 06:26 nick.sculthorpe

    Just posting this incase anyone else has similar trouble and to remind myself to read the docs carefully in future!

    Assuming there are no additional arguments, find_peaks() returns a tuple containing and array of the indexes of the peak values, and a dictionary of the actual peak values. Once I realised this it's pretty simple to perform sequence unpacking to generate a separate array and dictionary. So if I began with

    peak_data = signal.find_peaks(spline, height=0.3, distance=50)
    

    all I needed to do was to unpack to two variables

    peak_index, dict_vals = peak_data
    

    Now I have the index and the values in the order they were identified.