Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

argrelextrema and flat extrema

Tags:

python

scipy

Function argrelextrema from scipy.signal does not detect flat extrema. Example:

import numpy as np
from scipy.signal import argrelextrema
data = np.array([ 0, 1, 2, 1, 0, 1, 3, 3, 1, 0 ])
argrelextrema(data, np.greater)
(array([2]),)

the first max (2) is detected, the second max (3, 3) is not detected.

Any workaround for this behaviour? Thanks.

like image 626
Marcus Avatar asked Nov 26 '15 11:11

Marcus


1 Answers

Short answer: Probably argrelextrema will not be flexible enough for your task. Consider writing your own function matching your needs.


Longer answer: Are you bound to use argrelextrema? If yes, then you can play around with the comparator and the order arguments of argrelextrema (see the reference).

For your easy example, it would be enough to chose np.greater_equal as comparator.

>>> data = np.array([ 0, 1, 2, 1, 0, 1, 3, 3, 1, 0 ])
>>> print(argrelextrema(data, np.greater_equal,order=1))
(array([2, 6, 7]),)

Note however that in this way

>>> data = np.array([ 0, 1, 2, 1, 0, 1, 3, 3, 4, 1, 0 ])
>>> print(argrelextrema(data, np.greater_equal,order=1))
(array([2, 6, 8]),)

behaves differently that you would probably like, finding the first 3 and the 4 as maxima, since argrelextrema now sees everything as a maximum that is greater or equal to its two nearest neighbors. You can now use the order argument to decide to how many neighbors this comparison must hold - choosing order=2 would change my upper example to only find 4 as a maximum.

>>> print(argrelextrema(data, np.greater_equal,order=2))
(array([2, 8]),)

There is, however, a downside to this - let's change the data once more:

>>> data = np.array([ 0, 1, 2, 1, 0, 1, 3, 3, 4, 1, 5 ])
>>> print(argrelextrema(data, np.greater_equal,order=2))
(array([ 2, 10]),)

Adding another peak as a last value keeps you from finding your peak at 4, as argrelextrema is now seeing a second-neighbor that is greater than 4 (which can be useful for noisy data, but not necessarily the behavior expected in all cases).


Using argrelextrema, you will always be limited to binary operations between a fixed number of neighbors. Note, however, that all argrelextrema is doing in your example above is to return n, if data[n] > data[n-1] and data[n] > data[n+1]. You could easily implement this yourself, and then refine the rules, for example by checking the second neighbor in case that the first neighbor has the same value.


For the sake of completeness, there seems to be a more elaborate function in scipy.signal, find_peaks_cwt. I have however no experience using it and can therefore not give you more details about it.

like image 127
pascal Avatar answered Nov 03 '22 02:11

pascal