Search code examples
pythonnumpysignals

Find plateau in Numpy array


I am looking for an efficient way to detect plateaus in otherwise very noisy data. The plateaus are always relatively broad A simple example of what this data could look like:

test=np.random.uniform(0.9,1,100)
test[10:20]=0
plt.plot(test)

enter image description here

Note that there can be multiple plateaus (which should all be detected) which can have different values.

I've tried using scipy.signal.argrelextrema, but it doesn't seem to be doing what I want it to:

peaks=argrelextrema(test,np.less,order=25)
plt.vlines(peaks,ymin=0, ymax=1)

enter image description here

I don't need the exact interval of the plateau- a rough range estimate would be enough, as long as that estimate is bigger or equal than the actual plateau range. It should be relatively efficient however.


Solution

  • There is a method scipy.signal.find_peaks that you can try, here is an exmple

    import numpy
    from scipy.signal import find_peaks
    
    test = numpy.random.uniform(0.9, 1.0, 100)
    test[10 : 20] = 0
    peaks, peak_plateaus = find_peaks(- test, plateau_size = 1)
    

    although find_peaks only finds peaks, it can be used to find valleys if the array is negated, then you do the following

    for i in range(len(peak_plateaus['plateau_sizes'])):
        if peak_plateaus['plateau_sizes'][i] > 1:
            print('a plateau of size %d is found' % peak_plateaus['plateau_sizes'][i])
            print('its left index is %d and right index is %d' % (peak_plateaus['left_edges'][i], peak_plateaus['right_edges'][i]))
    

    it will print

    a plateau of size 10 is found
    its left index is 10 and right index is 19