Home > atmlab > math > find_extrema_with_prominence.m

find_extrema_with_prominence

PURPOSE ^

Locate local extrema with associated prominence

SYNOPSIS ^

function [local_min, local_max, prom_min, prom_max] = find_extrema_with_prominence(x, y)

DESCRIPTION ^

 Locate local extrema with associated prominence

 For a discrete set of data [x, y], locate all local maxima and minima in
 y = f(x). Additionally, for each local extremum, the one-dimensional
 topographic prominence is returned. Prominence is defined as the
 horizontal distance (delta-x) to the nearest extremum that is more
 extreme. For example, if local maxima are at (2, 8), (4, 6), (5, 7) and
 (10, 10), the prominence of (5, 7) is |5-2|=3, because it takes delta-x=3
 to go to the nearest larger maximum.

 WARNING: If a function is locally constant, this function will return
 wrong results! This function is still a work in progress and results
 might change dramatically in the near future (for the record: this lise
 was written 2012-09-20, if it's still there in 2013, please give Gerrit a
 kick)

 FORMAT

   [min, max, prom_min, prom_max] = find_extrema_with_prominence(x, y)

 IN
 
   x       vector with x-data (must be monotonically increasing)
   y       vector with y-data

 OUT

   min         logical true at local minima
   max         logical true at local maxima
   prom_min    vector with prominences corresponding to min
   prom_max    vector with prominences corresponding to max

 See also: plot_extrema_shaded

 Created by Gerrit Holl, 2012-09-20

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

DOWNLOAD ^

find_extrema_with_prominence.m

SOURCE CODE ^

0001 function [local_min, local_max, prom_min, prom_max] = find_extrema_with_prominence(x, y)
0002 % Locate local extrema with associated prominence
0003 %
0004 % For a discrete set of data [x, y], locate all local maxima and minima in
0005 % y = f(x). Additionally, for each local extremum, the one-dimensional
0006 % topographic prominence is returned. Prominence is defined as the
0007 % horizontal distance (delta-x) to the nearest extremum that is more
0008 % extreme. For example, if local maxima are at (2, 8), (4, 6), (5, 7) and
0009 % (10, 10), the prominence of (5, 7) is |5-2|=3, because it takes delta-x=3
0010 % to go to the nearest larger maximum.
0011 %
0012 % WARNING: If a function is locally constant, this function will return
0013 % wrong results! This function is still a work in progress and results
0014 % might change dramatically in the near future (for the record: this lise
0015 % was written 2012-09-20, if it's still there in 2013, please give Gerrit a
0016 % kick)
0017 %
0018 % FORMAT
0019 %
0020 %   [min, max, prom_min, prom_max] = find_extrema_with_prominence(x, y)
0021 %
0022 % IN
0023 %
0024 %   x       vector with x-data (must be monotonically increasing)
0025 %   y       vector with y-data
0026 %
0027 % OUT
0028 %
0029 %   min         logical true at local minima
0030 %   max         logical true at local maxima
0031 %   prom_min    vector with prominences corresponding to min
0032 %   prom_max    vector with prominences corresponding to max
0033 %
0034 % See also: plot_extrema_shaded
0035 %
0036 % Created by Gerrit Holl, 2012-09-20
0037 
0038 % $Id: find_extrema_with_prominence.m 7882 2012-09-20 15:34:42Z gerrit $
0039 
0040 errid = ['atmlab:' mfilename];
0041 
0042 % verify that x is monotonically increasing
0043 
0044 if all(~x(2:end) > x(1:end-1))
0045     error(errid, 'error in input: x is not monotonically increasing');
0046 end
0047 
0048 % something is a local maximum if it's larger-or-equal than the previous
0049 % and than the next element. The or-equal will result in neighbouring
0050 % maxima with 0 prominence; this will be checked for separately
0051 local_max = (y(2:end-1) > y(1:end-2)) & (y(2:end-1) > y(3:end));
0052 local_min = (y(2:end-1) < y(1:end-2)) & (y(2:end-1) < y(3:end));
0053 
0054 prom_max = get_prominence(x, y, local_max, 'max');
0055 prom_min = get_prominence(x, y, local_min, 'min');
0056 
0057 % check for neighbouring local maxima/minima, saddlepoints, etc.
0058 end
0059 
0060 function prominence = get_prominence(x, y, local_max, order)
0061 % for a vector of logicals, true for extrema, get the prominence for each
0062 %
0063 % get_prominence(x, y, local_max, order)
0064 %
0065 % 'order' must be 'max' or 'min' (strings)
0066 
0067 switch order
0068     case 'max'
0069         operation = @gt;
0070     case 'min'
0071         operation = @lt;
0072     otherwise
0073         error('atmlab:BUG', ...
0074             'Reached impossible place, crashing violently!');
0075 end
0076 
0077 pos_max_all = find(local_max);
0078 % there is probably a way to do this in a vectorised way. However,
0079 % Premature Optimisation Is The Root Off All Evil -- Donald Knuth
0080 
0081 prominence = zeros(size(pos_max_all));
0082 for i = 1:length(pos_max_all)
0083     pos_max = pos_max_all(i);
0084     x_here = x(pos_max_all(i));
0085     % find more extreme local extrema
0086     worse = operation(y(pos_max_all), y(pos_max));
0087     
0088     if any(worse)
0089         % x-values (e.g. frequencies) for values worse
0090         x_worse = x(pos_max_all(worse));
0091         prominence(i) = min(abs(x_here-x_worse));
0092     else
0093         prominence(i) = inf;
0094     end
0095 end
0096 
0097 % no = 1:length(pos_max_all);
0098 % maxima = [no(:) x(local_max) y(local_max)];
0099 % dist_left = [x(pos_max_all(1))-x(1); x(pos_max_all(2:end)) - x(pos_max_all(1:end-1))];
0100 % dist_right = [dist_left(2:end); x(end) - x(pos_max_all(end))];
0101 % prominence = min([dist_left dist_right], [], 2);
0102 
0103 end

Generated on Mon 15-Sep-2014 13:31:28 by m2html © 2005