Code covered by the BSD License  

Highlights from
PeakFinder

4.88889

4.9 | 10 ratings Rate this file 257 Downloads (last 30 days) File Size: 3.55 KB File ID: #25500
image thumbnail

PeakFinder

by Nate Yoder

 

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

| Watch this File

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
Add New Tags Please login to tag files.
Comments and Ratings (13)
16 Nov 2009 Morvan  
30 Nov 2009 Andres

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

02 Dec 2009 Andres

The bugs were fixed quickly. Thanks Nate!

28 Apr 2010 antonio Acampora

thanks

27 May 2010 Nicholas

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

17 Jun 2010 David

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.

09 Feb 2011 Tim

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!

14 Jun 2011 Nate Yoder

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.

18 Jun 2011 Elisa

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.

11 Aug 2011 Estella Liu  
12 Aug 2011 Robert  
22 Sep 2011 mohammad

 Really nice

02 Dec 2011 Diana

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?

Thanks in advance

Please login to add a comment or rating.
Updates
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).

Tag Activity for this File
Tag Applied By Date/Time
signal processing Nate Yoder 06 Oct 2009 10:53:35
maxima Nate Yoder 06 Oct 2009 10:53:36
minima Nate Yoder 06 Oct 2009 10:53:36
peaks Nate Yoder 06 Oct 2009 10:53:36
valleys Nate Yoder 06 Oct 2009 10:53:36
troughs Nate Yoder 06 Oct 2009 10:53:36
physics Nate Yoder 06 Oct 2009 10:53:36
extrema Nate Yoder 06 Oct 2009 10:53:36
chemistry Nate Yoder 06 Oct 2009 10:53:36
local Nate Yoder 06 Oct 2009 10:53:36
local max Nate Yoder 05 Nov 2009 08:55:19
local maxima Nate Yoder 05 Nov 2009 08:55:19
peak finder Nate Yoder 10 Nov 2009 15:46:32
potw Shari Freedman 13 Nov 2009 09:30:39
chemistry Pär 17 Dec 2009 08:01:24
extrema Pär 17 Dec 2009 08:01:26
local max Pär 17 Dec 2009 08:01:30
peaks Jose Ercolino 26 May 2010 15:34:08
extrema Jose Ercolino 26 May 2010 15:34:20
maxima Jose Ercolino 26 May 2010 15:34:26
minima Jose Ercolino 26 May 2010 15:34:28
noise Jose Ercolino 26 May 2010 18:52:21
chemistry SCUT Ye 25 Dec 2010 23:39:09
signal processing Paul Hampikian 10 Jan 2011 10:56:12
pick of the week Jiro Doke 11 Feb 2011 20:05:18
peak finder saksham nayar 02 Oct 2011 12:39:16
peak finder Diana 02 Dec 2011 10:03:58

Contact us at files@mathworks.com