Finding Local Extrema / Peaks From a Noisy Data
I’m trying to locate and measure the positive peaks in a noisy data sets. I compared some command and popular method and found the findpeak method produced the best result.
Simplest Method – Clean Signal
% Sample data t = 0:0.01:10; x = sin(2*t) - 3*cos(3.8*t); % Method 1 figure; dx = diff(x); % get differences between consecutive points pkIDX = (dx(1:end-1) >= 0) & (dx(2:end) < 0); % look for slope changes pkIDX = [dx(1)<0, pkIDX, dx(end)>=0]; % deal with edges plot(t, x, t(pkIDX), x(pkIDX), 'ro');
This was an eye-opener and was the moment I experienced the power of vector operation for the first time. The way I code in MATLAB had changed from that point on. … So when I see “peak finding”, it brings back memories.
This works fine with simplest data
There are quite a few File Exchange entries for finding peaks (and valleys), including two previous POTW selections: FPEAK and EXTREMA. But I really like peakfinder by Nate. Not only does his code deal with noisy data (my algorithm above will be useless if the signal is noisy), but also his coding practice is quite solid. He has a great help section, robust error-checking of input arguments, and variable input and output arguments for ease of use.
Simpliest Method – Noisy Signal
xNoise = x + 0.3*sin(40*t); % add a few more bumps % Method 1 with noise figure; dx = diff(xNoise); % get differences between consecutive points pkIDX = (dx(1:end-1) >= 0) & (dx(2:end) < 0); % look for slope changes pkIDX = [dx(1)<0, pkIDX, dx(end)>=0]; % deal with edges plot(t, xNoise, t(pkIDX), x(pkIDX), 'ro');
The simplest method failed to work when the the data is noisy
Noisy Signal – PeakFinder Method
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.
% Method 2 with noise, using peakfinder figure; peakfinder(xNoise);
PeakFinder works very well with Noisy data
Noisy Signal – fpeak Method
figure; pk=fpeak(t,xNoise,100); plot(t, xNoise, pk(:,1), pk(:,2), 'ro');
fpeak method works fine but also reported the minimum data points, it requires more inputs than the PeakFinder method hence increased unnecessary complexity.
Noisy Signal – extrma Method
% Method 4 with noise, using extrma figure; [ymax,imax,ymin,imin] = extrema(xNoise); plot(t, xNoise, t(imax),ymax,'ro')
Extrma method simplify reported too many peaks, works no better than the simplest method.
Reference & Further Reading:
- Download PeakFinder from Exchange
- Peak Finding and Measurement
-
Finding Local Extrema From File Exchange Pick of the Week

