function [xmax,imax,xmin,imin] = extrema(x) %EXTREMA Gets the global extrema points from a time series. % [XMAX,IMAX,XMIN,IMIN] = EXTREMA(X) returns the global minima and maxima % points of the vector X ignoring NaN's, where % XMAX - maxima points in descending order % IMAX - indexes of the XMAX % XMIN - minima points in descending order % IMIN - indexes of the XMIN % % DEFINITION (from http://en.wikipedia.org/wiki/Maxima_and_minima): % In mathematics, maxima and minima, also known as extrema, are points in % the domain of a function at which the function takes a largest value % (maximum) or smallest value (minimum), either within a given % neighbourhood (local extrema) or on the function domain in its entirety % (global extrema). % % Example: % x = 2*pi*linspace(-1,1); % y = cos(x) - 0.5 + 0.5*rand(size(x)); y(40:45) = 1.85; y(50:53)=NaN; % [ymax,imax,ymin,imin] = extrema(y); % plot(x,y,x(imax),ymax,'g.',x(imin),ymin,'r.') % % See also EXTREMA2, MAX, MIN % Written by % Lic. on Physics Carlos Adrián Vargas Aguilera % Physical Oceanography MS candidate % UNIVERSIDAD DE GUADALAJARA % Mexico, 2004 % % nubeobscura@hotmail.com % From : http://www.mathworks.com/matlabcentral/fileexchange % File ID : 12275 % Submited at: 2006-09-14 % 2006-11-11 : English translation from spanish. % 2006-11-17 : Accept NaN's. % 2007-04-09 : Change name to MAXIMA, and definition added. xmax = []; imax = []; xmin = []; imin = []; % Vector input? Nt = numel(x); if Nt ~= length(x) error('Entry must be a vector.') end % NaN's: inan = find(isnan(x)); indx = 1:Nt; if ~isempty(inan) indx(inan) = []; x(inan) = []; Nt = length(x); end % Difference between subsequent elements: dx = diff(x); % Is an horizontal line? if ~any(dx) return end % Flat peaks? Put the middle element: a = find(dx~=0); % Indexes where x changes lm = find(diff(a)~=1) + 1; % Indexes where a do not changes d = a(lm) - a(lm-1); % Number of elements in the flat peak a(lm) = a(lm) - floor(d/2); % Save middle elements a(end+1) = Nt; % Peaks? xa = x(a); % Serie without flat peaks b = (diff(xa) > 0); % 1 => positive slopes (minima begin) % 0 => negative slopes (maxima begin) xb = diff(b); % -1 => maxima indexes (but one) % +1 => minima indexes (but one) imax = find(xb == -1) + 1; % maxima indexes imin = find(xb == +1) + 1; % minima indexes imax = a(imax); imin = a(imin); nmaxi = length(imax); nmini = length(imin); % Maximum or minumim on a flat peak at the ends? if (nmaxi==0) && (nmini==0) if x(1) > x(Nt) xmax = x(1); imax = indx(1); xmin = x(Nt); imin = indx(Nt); elseif x(1) < x(Nt) xmax = x(Nt); imax = indx(Nt); xmin = x(1); imin = indx(1); end return end % Maximum or minumim at the ends? if (nmaxi==0) imax(1:2) = [1 Nt]; elseif (nmini==0) imin(1:2) = [1 Nt]; else if imax(1) < imin(1) imin(2:nmini+1) = imin; imin(1) = 1; else imax(2:nmaxi+1) = imax; imax(1) = 1; end if imax(end) > imin(end) imin(end+1) = Nt; else imax(end+1) = Nt; end end xmax = x(imax); xmin = x(imin); % NaN's: if ~isempty(inan) imax = indx(imax); imin = indx(imin); end % Same size as x: imax = reshape(imax,size(xmax)); imin = reshape(imin,size(xmin)); % Descending order: [temp,inmax] = sort(-xmax); clear temp xmax = xmax(inmax); imax = imax(inmax); [xmin,inmin] = sort(xmin); imin = imin(inmin); % Carlos Adrián Vargas Aguilera. nubeobscura@hotmail.com