|
import sys |
|
from numpy import NaN, Inf, arange, isscalar, asarray, array |
|
|
|
def peakdet(v, delta, x = None): |
|
""" |
|
Converted from MATLAB script at http://billauer.co.il/peakdet.html |
|
|
|
Returns two arrays |
|
|
|
function [maxtab, mintab]=peakdet(v, delta, x) |
|
%PEAKDET Detect peaks in a vector |
|
% [MAXTAB, MINTAB] = PEAKDET(V, DELTA) finds the local |
|
% maxima and minima ("peaks") in the vector V. |
|
% MAXTAB and MINTAB consists of two columns. Column 1 |
|
% contains indices in V, and column 2 the found values. |
|
% |
|
% With [MAXTAB, MINTAB] = PEAKDET(V, DELTA, X) the indices |
|
% in MAXTAB and MINTAB are replaced with the corresponding |
|
% X-values. |
|
% |
|
% A point is considered a maximum peak if it has the maximal |
|
% value, and was preceded (to the left) by a value lower by |
|
% DELTA. |
|
|
|
% Eli Billauer, 3.4.05 (Explicitly not copyrighted). |
|
% This function is released to the public domain; Any use is allowed. |
|
|
|
""" |
|
maxtab = [] |
|
mintab = [] |
|
|
|
if x is None: |
|
x = arange(len(v)) |
|
|
|
v = asarray(v) |
|
|
|
if len(v) != len(x): |
|
sys.exit('Input vectors v and x must have same length') |
|
|
|
if not isscalar(delta): |
|
sys.exit('Input argument delta must be a scalar') |
|
|
|
if delta <= 0: |
|
sys.exit('Input argument delta must be positive') |
|
|
|
mn, mx = Inf, -Inf |
|
mnpos, mxpos = NaN, NaN |
|
|
|
lookformax = True |
|
|
|
for i in arange(len(v)): |
|
this = v[i] |
|
if this > mx: |
|
mx = this |
|
mxpos = x[i] |
|
if this < mn: |
|
mn = this |
|
mnpos = x[i] |
|
|
|
if lookformax: |
|
if this < mx-delta: |
|
maxtab.append((mxpos, mx)) |
|
mn = this |
|
mnpos = x[i] |
|
lookformax = False |
|
else: |
|
if this > mn+delta: |
|
mintab.append((mnpos, mn)) |
|
mx = this |
|
mxpos = x[i] |
|
lookformax = True |
|
|
|
return array(maxtab), array(mintab) |
|
|
|
if __name__=="__main__": |
|
from matplotlib.pyplot import plot, scatter, show |
|
series = [0,0,0,2,0,0,0,-2,0,0,0,2,0,0,0,-2,0] |
|
maxtab, mintab = peakdet(series,.3) |
|
plot(series) |
|
scatter(array(maxtab)[:,0], array(maxtab)[:,1], color='blue') |
|
scatter(array(mintab)[:,0], array(mintab)[:,1], color='red') |
|
show() |
Great script. Gave me a few good ideas about how to find peaks, but I think you should note that it if your signal starts with a minima you will systematically miss that one. Just remove the need for the: 'If lookoformax' statement and replace with some other logic and you can find the first peak, even if it's a minima. Doing this also means that you almost always will have a false hit on the first or one of the first samples and will need to pop that peak from the results.
Changed this logic, added another test criteria to find the peaks and I also made a peak finder routine which divided the signal into different sections by looking for zero crossings and finding the peak in each section.