File Exchange

## peakdet

version 1.2.0.0 (4.89 KB) by Marco Borges

### Marco Borges (view profile)

Detect Peaks and Depressions in a signal

Updated 20 Jan 2015

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.

Audain Desrosiers

Hasti Hayati

Philipp Metz

### Philipp Metz (view profile)

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;
++nmax;
mn = currval;
mnpos = i;
lookformax = 0;
}
}
else
{
if (currval > (mn + *pdelta))
{
tmpmn[nmin] = mnpos;
++nmin;
mx = currval;
mxpos = i;
lookformax = 1;
}
}
}
/* create output matrix (double array) */
/* Should have the same complexity as input */
plhs[0]=mxCreateDoubleMatrix(nmin,1,mxREAL);
plhs[1]=mxCreateDoubleMatrix(nmax,1,mxREAL);
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];
return;
}

Stephen Cobeldick

### Stephen Cobeldick (view profile)

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

Stephen Cobeldick

### Stephen Cobeldick (view profile)

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:

http://ww.mathworks.com/matlabcentral/fileexchange/25500-peakfinder

And even from MATLAB themselves:

http://www.mathworks.com/help/signal/ref/findpeaks.html