File Exchange

image thumbnail


version (4.89 KB) by Marco Borges
Detect Peaks and Depressions in a signal


Updated 20 Jan 2015

View License

peakdet returns peaks and depressions (local maxima and minimum) in the input signal. It can detect peaks/dep crossing the threshold or zero. Signal data requires a row or column vector with real-valued elements. If there are no local minimum/maxima returns empty.

Comments and Ratings (6)

Great work!
However, for-loops in Matlab are pretty slow. So I transfered a simplified version (just giving the positions) of this into a mex file:
[mnpos,mxpos] = mex_pekdet(vector,delta)
you get the values in matlab using
mxval = vector(mxpos)

#include <math.h>
#include "mex.h"
#include "stdio.h"
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
int n, nmax=0,nmin=0, lookformax = 1;
int i,mnpos,mxpos;
double mn,mx,currval;
double *pin=NULL, *pdelta=NULL, *poutmn=NULL,*poutmx=NULL;
double tmpmn[100]; // temporary arrays for max 100 peaks
double tmpmx[100];
//int status = 0;
/* Examine input arguments. */
if( nrhs != 2 || nlhs != 2)
mexErrMsgTxt("Usage: [mx,mn]=mex_peakdet(vector,delta)");

if ( mxIsClass(prhs[0], "sparse") || !mxIsNumeric(prhs[0]) )
{ /* check the type of input argument */
mexErrMsgTxt("Input must be full vector");

/* get input configuration */
n = mxGetNumberOfElements(prhs[0]);
mn = 1e20; mx = -1e20;

/* get pointers to the real parts of input and output */
pin = mxGetPr(prhs[0]);
pdelta = mxGetPr(prhs[1]);

// find local maxima by delta definition
for ( i = 0; i < n; ++i)
currval = pin[i];
if (currval > mx)
mx = currval;
mxpos = i+1;
if (currval < mn)
mn = currval;
mnpos = i+1;

if (lookformax)
if (currval < (mx-*pdelta))
tmpmx[nmax] = mxpos;
mn = currval;
mnpos = i;
lookformax = 0;
if (currval > (mn + *pdelta))
tmpmn[nmin] = mnpos;
mx = currval;
mxpos = i;
lookformax = 1;
/* create output matrix (double array) */
/* Should have the same complexity as input */
poutmn = mxGetPr(plhs[0]);
poutmx = mxGetPr(plhs[1]);

// write to output arrays
for (i = 0;i< nmin;++i)
poutmn[i] = tmpmn[i];
for (i = 0;i< nmax;++i)
poutmx[i] = tmpmx[i];

A very useful addition would be if this could handle matrices as well as vectors.

Peak finding is a very useful function to have, which is why there are more than fifty submissions on FEX offering some kind of peak detection (according to the search that I just made).

The code quality/algorithm is poor, in particular:

* Loops are used which could easily be vectorized. The function |diff| would achieve most of what the main loop does.

* No array preallocation: the peak-vectors are generated by concatenating new values onto the end of the vectors: this is slow, and a poor use of MATLAB.

There are much better peak finders on MATLAB FEX, such as:

And even from MATLAB themselves:


add minimum distance between any two peaks (local maximum)

accept row vector

MATLAB Release Compatibility
Created with R2012b
Compatible with any release
Platform Compatibility
Windows macOS Linux

Inspired: PeakPoints