You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

151 lines
4.3 KiB

%PEAK Find peaks in vector
%
% YP = PEAK(Y, OPTIONS) are the values of the maxima in the vector Y.
%
% [YP,I] = PEAK(Y, OPTIONS) as above but also returns the indices of the maxima
% in the vector Y.
%
% [YP,XP] = PEAK(Y, X, OPTIONS) as above but also returns the corresponding
% x-coordinates of the maxima in the vector Y. X is the same length of Y
% and contains the corresponding x-coordinates.
%
% Options::
% 'npeaks',N Number of peaks to return (default all)
% 'scale',S Only consider as peaks the largest value in the horizontal
% range +/- S points.
% 'interp',N Order of interpolation polynomial (default no interpolation)
% 'plot' Display the interpolation polynomial overlaid on the point data
%
% Notes::
% - To find minima, use PEAK(-V).
% - The interp options fits points in the neighbourhood about the peak with
% an N'th order polynomial and its peak position is returned. Typically
% choose N to be odd.
%
% See also PEAK2.
% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Machine Vision Toolbox for Matlab (MVTB).
%
% MVTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% MVTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with MVTB. If not, see <http://www.gnu.org/licenses/>.
% Copyright (c) Peter Corke 1/96
function [yp,xpout] = peak(y, varargin)
% process input options
opt.npeaks = [];
opt.scale = 1;
opt.interp = 0;
opt.plot = false;
[opt,args] = tb_optparse(opt, varargin);
% if second argument is a matrix we take this as the corresponding x
% coordinates
if ~isempty(args)
x = args{1};
x = x(:);
if length(x) ~= length(y)
error('second argument must be same length as first');
end
else
x = [1:length(y)]';
end
y = y(:);
% find the maxima
if opt.scale > 1
% compare to a moving window max filtered version
k = find(y' == filt1d(y, 'max', 'width', opt.scale*2+1));
else
% take the zero crossings
dv = diff(y);
k = find( ([dv; 0]<0) & ([0; dv]>0) );
end
% sort the maxima into descending magnitude
[m,i] = sort(y(k), 'descend');
k = k(i); % indice of the maxima
if opt.npeaks
k = k(1:opt.npeaks);
end
% optionally plot the discrete data
if opt.plot
plot(x, y, '-o');
hold on
end
% interpolate the peaks if required
if opt.interp
if opt.interp < 2
error('interpolation polynomial must be at least second order');
end
xp = [];
yp = [];
N = opt.interp;
N2 = round(N/2);
% for each previously identified peak x(i), y(i)
for i=k'
% fit a polynomial to the local neighbourhood
try
pp = polyfit(x(i-N2:i+N2), y(i-N2:i+N2), N);
catch
% handle situation where neighbourhood falls off the data
% vector
warning('Peak at %f too close to start or finish of data, skipping', x(i));
continue;
end
% find the roots of the polynomial closest to the coarse peak
r = roots( polydiff(pp) );
[mm,j] = min(abs(r-x(i)));
xx = r(j);
% store x, y for the refined peak
xp = [xp; xx];
yp = [y; polyval(pp, xx)];
if opt.plot
% overlay the fitted polynomial and refined peak
xr = linspace(x(i-N2), x(i+N2), 50);
plot(xr, polyval(pp, xr), 'r');
plot(xx, polyval(pp, xx), 'rd');
end
end
else
xp = x(k);
end
if opt.plot
grid
xlabel('x');
ylabel('y');
hold off
end
% return values
yp = y(k)';
if nargout > 1
xpout = xp';
end