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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With