Search code examples
pythonscipysampling

matplotlib argrelmax doesn't find all maxes


I have a project where I'm sampling analog data and attempting to analyze with matplotlib. Currently, my analog data source is a potentiometer hooked up to a microcontroller, but that's not really relevant to the issue. Here's my code

arrayFront = RunningMean(array(dataFront), 15)
arrayRear = RunningMean(array(dataRear), 15)
x = linspace(0, len(arrayFront), len(arrayFront))  # Generate x axis
y = linspace(0, len(arrayRear), len(arrayRear))  # Generate x axis
min_vals_front = scipy.signal.argrelmin(arrayFront, order=2)[0]  # Min
min_vals_rear = scipy.signal.argrelmin(arrayRear, order=2)[0]  # Min
max_vals_front = scipy.signal.argrelmax(arrayFront, order=2)[0]  # Max
max_vals_rear = scipy.signal.argrelmax(arrayRear, order=2)[0]  # Max
maxvalfront = max(arrayFront[max_vals_front])
maxvalrear = max(arrayRear[max_vals_rear])
minvalfront = min(arrayFront[min_vals_front])
minvalrear = min(arrayRear[min_vals_rear])
plot(x, arrayFront, label="Front Pressures")
plot(y, arrayRear, label="Rear Pressures")
plot(x[min_vals_front], arrayFront[min_vals_front], "x")
plot(x[max_vals_front], arrayFront[max_vals_front], "o")
plot(y[min_vals_rear], arrayRear[min_vals_rear], "x")
plot(y[max_vals_rear], arrayRear[max_vals_rear], "o")
xlim(-25, len(arrayFront) + 25)
ylim(-1000, 7000)
legend(loc='upper left')
show()

dataFront and dataRear are python lists that hold the sampled data from 2 potentiometers. RunningMean is a function that calls:

convolve(x, ones((N,)) / N, mode='valid')

The problem is that the argrelmax (and min) functions don't always find all the maxes and mins. Sometimes it doesn't find ANY max or mins, and that causes me problems in this block of code

maxvalfront = max(arrayFront[max_vals_front])
maxvalrear = max(arrayRear[max_vals_rear])
minvalfront = min(arrayFront[min_vals_front])
minvalrear = min(arrayRear[min_vals_rear])

because the [min_vals_(blank)] variables are empty. Does anyone have any idea what is happening here, and what I can do to fix the problem? Thanks in advance.

Here's one of graphs of data where not all the maxes and mins are found:

enter image description here


Solution

  • signal.argrelmin is a thin wrapper around signal.argrelextrema with comparator=np.less. np.less(a, b) returns the truth value of a < b element-wise. Notice that np.less requires a to be strictly less than b for it to be True.

    Your data has the same minimum value at a lot of neighboring locations. At the local minima, the inequality between local minimum and its neighbors does not satisfy a strictly less than relationship; instead it only satisfies a strictly less than or equal to relationship.

    Therefore, to find these extrema use signal.argrelmin with comparator=np.less_equal. For example, using a snippet from your data:

    import numpy as np
    from scipy import signal
    
    arrayRear = np.array([-624.59309896, -624.59309896, -624.59309896,
                          -625., -625., -625.,])
    
    print(signal.argrelmin(arrayRear, order=2)[0])
    # []
    
    print(signal.argrelextrema(arrayRear, np.less_equal)[0])
    # [0 1 3 4 5]
    
    print(signal.argrelextrema(arrayRear, np.less_equal, order=2)[0])
    # [0 3 4 5]