Code covered by the BSD License

### Highlights fromPeakFinder

4.85714

4.9 | 24 ratings Rate this file 371 Downloads (last 30 days) File Size: 3.55 KB File ID: #25500

# PeakFinder

06 Oct 2009 (Updated 14 Jun 2011)

Quickly finds local maxima (peaks) or minima (valleys) in a noisy signal.

### Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

File Information
Description

This function quickly finds local peaks or valleys (local extrema) in a noisy vector using a user defined magnitude threshold to determine if each peak is significantly larger (or smaller) than the data around it. The problem with the strictly derivative based peak finding algorithms is that if the signal is noisy many spurious peaks are found. However, more complex methods often take much longer for large data sets, require a large amount of user interaction, and still give highly variable results. This function attempts to use the alternating nature of the derivatives along with the user defined threshold to identify local maxima or minima in a vector quickly and robustly. The function is able to correctly identify the major peaks on a 1.5 million data point noisy sum of sinusoids in under a second as is shown in the example in the code comments.

Please don't hesitate to comment or contact me if you have suggestions about improvements that could be made to this function.

MATLAB release MATLAB 7.8 (R2009a)
Other requirements None
Tags for This File
Everyone's Tags
Tags I've Applied
17 Jun 2013

Best code ever.

02 Jun 2013
19 Apr 2013

I've tried several approaches to detecting peaks in noisy data; this one worked best, and is exceptionally fast. Very nice work!

18 Apr 2013

How should I cite this code?

09 Mar 2013
22 Feb 2013

hi team

I am very new at this. How do I make this code find multiple peaks?

Thanks

02 Nov 2012

good

08 Jun 2012
03 Jun 2012

Dear MATLAB users community,
I am a matlab newbie,I have x and y as vectors, I plotted them in MATLAB and now I need to detect the peaks and also find the corresponding peak locations. How can I use this code in my case?
Mitra

09 May 2012

Wang Feiran, to to find valleys you can use
peakfinder(data,[],[],-1)

03 May 2012
29 Apr 2012

Btw,the commend i was using is >>peakfinder(data) and i am a matlab newbie xD

29 Apr 2012

Btw,how to use this code to detect valley?Thanks

29 Apr 2012

Hello,i also have a problem with this code when i input the data under 1200 sampling frequency it doing well can detect all the peak points,but when i tried with other data under different sampling frequency sometimes it only can give me like half points some are missing,i don't know how to attach the image file,but can give me any help?

28 Apr 2012
12 Apr 2012

Hello all, I have a problem with this code when my SNR is less 1.9 dB I CANT DETECT MY PEAKS OF INTEREST. What i want to know is it not possible to detect peaks at such noisy conditions ???

12 Apr 2012

Joanne: That kind of error-message typically arises when Matlab does not know where the command resides (or when you misspelled it). Make sure that any m-file you wish to run are either in the current directory, and/or in your Matlab-path. If you have a separate folder for non-builtin m-files (such as peakfinder) that you wish to use, you can add that folder to the Matlab-path with the 'addpath' command, and put those m-files there.

10 Apr 2012

Sorry, I thought I'd written a longer message! I am also a MatLab newbie and am struggling to input the data and I get the above error message. Thanks if anyone can help. Jo

04 Apr 2012

I get the error:
Undefined function 'peakfinder' for input arguments of type
'double'.

28 Mar 2012

the code works well but some times it happens that peaks which are not required I mean after initializing a certain value for 'sel' the peaks which are not supposed to be detected (peaks created by noise) and sometimes they are not detected

12 Mar 2012

very quick and supportive response from the author. The output issue as listed above is due to my misunderstanding of the varargout. The other issue may also results from the Matlab setting rather than the code. Thank you, Nate.

12 Mar 2012

very useful code. However, it cannot output the PeakMag, but only the PeakLoc when I tried it recently. and after I used it several times with a vector, the acceptable number of the element seems to be locked. When used with other vectors having different numbers of elements,the extra elements cannot be shown in the plot and the output results. I hope someone can kindly explain this...

02 Dec 2011

Hi, I find this routine very good and useful. However, for my problem I would need the start-end information about each peak so I could select just the peaks and work with them, How can I get this information?

22 Sep 2011

Really nice

12 Aug 2011
11 Aug 2011
18 Jun 2011

Hi. I need to find peaks in a waveform and calculate the inter-pulse interval and the pulse rate from the position of the peaks. My data are sounds recorded at 24000Hz and saved in .wav files. This code seems to be doing exactly what I want but since I’m a matlab newbie I’m not quite sure how to input my data. Do you have any suggestions?
I hope this is the right place to post this message, otherwise I apologise.

14 Jun 2011

Thanks for catching that Tim. You were exactly right, the redundancy is an artifact from when I preallocated the matrix for speed. However, I essentially replaced this statement with the leftMin variable which is why you got the same results. The end effect is that the second part of that conditional can simply be eliminated.

Thanks again for your help and an updated version with the addition of a user defined threshold should be available shortly.

09 Feb 2011

I think I found a mistake in the code. Or at least something strange:

if foundPeak && (x(ii) > peakMag(end) || leftMin < peakMag(end)-thresh)

The second part, x(ii) > peakMag(end), is rather strange, since peakMag(end) will ALWAYS be equal to zero, since peakMag was preallocated with zeros. I guess this is a remainder from the time before you preallocated peakMag for speed.

I replaced the mistake with the following:

if foundPeak && (x(ii) > peakMag(cInd-1) || leftMin < peakMag(cInd-1)-thresh)

The strange thing is that the results luckily stay exactly the same, which is good but strange at the same time. There is probably some redundancy in the code.

In any case, your method was more or less what I was looking for. Just need to make some small adaptations to it for my purpose, of course leaving all credits to you. Thanks!

17 Jun 2010

fantastic code, very effective even with highly noise data.

notably, it might be worth including an histogram based thresholding for a more optimal threshold selection.

27 May 2010

Does anyone know of a comparable code that finds extrema in 2D or 3D data?

28 Apr 2010

thanks

02 Dec 2009

The bugs were fixed quickly. Thanks Nate!

30 Nov 2009

I was happily using peakfinder until I had severe trouble with a dataset beginning with repeated values.
I've boiled it down to a short example:

t = [49 49 54 49 -57 46 -96 -10 39 0];
startI1 = 1;
[Loc1, Peak1] = peakfinder(t(startI1:end),20);
startI2 = 2;
[Loc2, Peak2] = peakfinder(t(startI2:end),20);

figure
plot(t,'b.-')
hold on
plot(Loc1-1+startI1,Peak1,'ro')
plot(Loc2-1+startI2,Peak2,'go')

Problems:
1) The first call returns a wrong result (Loc1 = 2, Peak1 = 49).
2) The second call returns all three peaks, but the last one appears twice (Loc2 = [2 5 8 8].', Peak2 = [54 46 39 39].').

I hope these issues can be fixed as peakfinder works promisingly fast.
A minor suggestion: if the input is a row vector the output should be a row vector, too.

Regards
Andres

16 Nov 2009
06 Nov 2009

Updated code to make it slightly faster.

06 Nov 2009

Updated algorithm to make it slightly faster.

11 Nov 2009

Fixed example and error checking code. Thanks to Jiro Doke for catching my mistakes.

01 Dec 2009

Fixed problems with repeated initial values, repeated final values, and other directional issues. Thanks to Andres for his help finding and debugging these problems.

08 Dec 2009

Added support for monotone increase/decreasing functions and empty inputs. Thanks again to Andres for the debugging help.

08 Oct 2010

Updated the error checking on the threshold level.

14 Jun 2011

Removed redundancy (thanks Tim) and added thresholding option (thanks Femi).