File Exchange Pick of the Week

May 9th, 2008

Finding Local Extrema

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

3 Responses to “Finding Local Extrema”

  1. Nikos replied on :

    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]);
    
  2. Brett replied on :

    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

  3. manimala replied on :

    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?

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


Bob, Brett & Jiro share their favorite user-contributed submissions from the File Exchange.

  • Zach: Hi Doug and Les, I didn’t have a lot of time to mess with this, but I did find a work-around. I plotted...
  • hamed: k
  • Les: @Zach This isn’t exactly what you are looking for but at least it puts all three parameters on the same...
  • Zach: Thanks for your suggestions Doug. I’ll give that a shot and see what happens. I’ve seen many of...
  • Doug: @Zach, I would say to use plotYYY, because that is close to what you want, but using depth as Y makes sense....
  • Doug: @Teja, I think this will work: http://www.mathworks .com/access/helpdesk /help/techdoc/ref...
  • Gify: merry christmas :) nice christmas tree! Regards, Janet Gify
  • Teja: Dear Doug Is there anyway to plot a surface from nonuniform data without meshgrid and griddata? Basically i...
  • Zach: I’m working with geophysical data, so I’d like to produce a depth profile. The y-axis would be...
  • Doug: @Ashok First, please do not use variable names that are MATLAB commands (std and mean). Second, p(j) should be...

These postings are the author's and don't necessarily represent the opinions of The MathWorks.