Many times, I've wanted a quick way to find the local minima or maxima in my data. Carlos Adrian Vargas Aguilera's submission EXTREMA makes it easy to do, and is Brett's selection for the Pick of the Week.
Contents
The Problem:
This morning, I was asked to help a customer find local peaks (minima and maxima) in a trace from some sort of medical device. The particulars of the signal are not really relevant here; what is important is that the signal was large and jagged, with many local extrema. This clearly was not something the customer--or I!--wanted to do manually. Moreover, of course, there might be more traces on which we would want to repeat the analysis, so any algorithm we developed should be able to be incorporated in an automation routine. My first thought was to search MATLAB's documentation for extrema detection. I found that the Signal Processing Blockset has a Peak Detection Block that finds local minima and maxima, but that solution, of course, requires Simulink. Being the MATLAB geek that I am, I wanted to do this entirely in m-code. Next, though implementing my own algorithm wouldn't be too difficult, I thought to search for someone else's implementation of an extrema detector. (No sense reinventing the wheel!)
Finding local maxima and minima
A quick search turned up Carlos's highly rated, much-downloaded EXTREMA. I happily grabbed his code and took it for a test spin. Result: problem solved! Consider the following artificial noisy data:
t= 0:pi/16:8*pi; y = sin(t).*rand(size(t)); plot(t,y)
Now consider how easy it is to find the extrema with Carlos's EXTREMA function:
figure plot(t,y) [ymax,imax,ymin,imin] = extrema(y); hold on plot(t(imax),ymax,'r*',t(imin),ymin,'g*')
What about smoothing those data?
By the way, given a noisy source, it might also be nice to have a way to smooth the data. A quick search for SMOOTH in MATLAB's help browser shows how to do that with the always-useful Curve Fitting Toolbox:
y2 = smooth(y,20); figure plot(t,y2) [ymax2,imax2,ymin2,imin2] = extrema(y2); hold on plot(t(imax2),ymax2,'r*',t(imin2),ymin2,'g*') hold off
(Note that there are lots of options for SMOOTH. I've just implemented a [default] moving average filter, using a 20-point sliding neighborhood.)
Carlos also bundled EXTREMA with a second function called EXTREMA2 that extends the functionality to three-dimensional data, and he provided a nice graphic that shows off the utility of his code. I see that his functions also inspired another submission, called MinimaMaxima3D. Very nice work, Carlos!
Get
the MATLAB code
Published with MATLAB® 7.6



Hey Doug,
I really enjoy reading your blog. I just wanted to point out that this task can be done in just 9 lines of code, compared to over 100 in Carlos’ file! The code that follows behaves a bit differently when a straight part is encountered within the data (detects 2 extrema at its endspoints, instead of placing a single extremum at its middle), but other than that it does the same thing! I don’t reinvent the wheel for sure, probably helping it roll faster :)
Cheers
N
function [Imin,Imax]=FindExtrema(Y) Y = [NaN;Y(:);NaN]; D = diff(Y); S = D(1:end-1).*D(2:end); I = find(S0); In(D(In)<0)-1 ; Io(D(Io)<0)-1]); Imin=sort([I(D(I)0)-1; Io(D(Io)>0)-1]);Nikos,
Thanks for the reply. While Carlos’s file could be tightened up, note that it does a lot of very nice error checking, and deals with edge cases that might wreak havoc on your code–if indeed it were working. Your code won’t run as posted (there are some bugs in there!); but I’d encourage you to polish your algorithm a bit and post it to the File Exchange.
Brett
the blog was very useful
is there any structure availbele to implement this work?
that is any architecture or block diagram to find the local maxima and minima for a given signal?