-
Notifications
You must be signed in to change notification settings - Fork 8
/
extrema.m
146 lines (128 loc) · 3.5 KB
/
extrema.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
%
% 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. [email protected]