IRootLab
An Open-Source MATLAB toolbox for vibrational biospectroscopy
error_ellipse2.m
Go to the documentation of this file.
1 %>@ingroup graphicsapi maths
2 %>@file
3 %>@brief error ellipse, "ellipse walls" version
4 %>
5 %> @verbatim
6 %> ERROR_ELLIPSE(C22) - Given a 2x2 covariance matrix, plot the
7 %> associated error ellipse, at the origin. It returns a graphics handle
8 %> of the ellipse that was drawn.
9 %>
10 %> ERROR_ELLIPSE(C33) - Given a 3x3 covariance matrix, plot the
11 %> associated error ellipsoid, at the origin, as well as its projections
12 %> onto the three axes. Returns a vector of 4 graphics handles, for the
13 %> three ellipses (in the X-Y, Y-Z, and Z-X planes, respectively) and for
14 %> the ellipsoid.
15 %>
16 %> ERROR_ELLIPSE(C,MU) - Plot the ellipse, or ellipsoid, centered at MU,
17 %> a vector whose length should match that of C (which is 2x2 or 3x3).
18 %>
19 %> ERROR_ELLIPSE(...,'Property1',Value1,'Name2',Value2,...) sets the
20 %> values of specified properties, including:
21 %> 'C' - Alternate method of specifying the covariance matrix
22 %> 'mu' - Alternate method of specifying the ellipse (-oid) center
23 %> 'conf' - A value betwen 0 and 1 specifying the confidence interval.
24 %> the default is 0.5 which is the 50%> error ellipse.
25 %> 'scale' - Allow the plot the be scaled to difference units.
26 %> 'style' - A plotting style used to format ellipses.
27 %> 'clip' - specifies a clipping ruleRadii. Portions of the ellipse, -oid,
28 %> outside the ruleRadii will not be shown.
29 %>
30 %> NOTES: C must be positive definite for this function to work properly.
31 %> @endverbatim
32 function h=error_ellipse2(varargin)
33 global SCALE;
34 
35 default_properties = struct(...
36  'C', [], ... % The covaraince matrix (required)
37  'mu', [], ... % Center of ellipse (optional)
38  'conf', 0.5, ... % Percent confidence/100
39  'scale', 1, ... % Scale factor, e.g. 1e-3 to plot m as km
40  'style', '', ... % Plot style
41  'clip', inf, ...
42  'xyz', [0, 0, 0]); % Clipping ruleRadii
43 
44 if length(varargin) >= 1 & isnumeric(varargin{1})
45  default_properties.C = varargin{1};
46  varargin(1) = [];
47 end
48 
49 if length(varargin) >= 1 & isnumeric(varargin{1})
50  default_properties.mu = varargin{1};
51  varargin(1) = [];
52 end
53 
54 if length(varargin) >= 1 & isnumeric(varargin{1})
55  default_properties.conf = varargin{1};
56  varargin(1) = [];
57 end
58 
59 if length(varargin) >= 1 & isnumeric(varargin{1})
60  default_properties.scale = varargin{1};
61  varargin(1) = [];
62 end
63 
64 if length(varargin) >= 1 & ~ischar(varargin{1})
65  irerror('Invalid parameter/value pair arguments.')
66 end
67 
68 prop = getopt(default_properties, varargin{:});
69 C = prop.C;
70 
71 if isempty(prop.mu)
72  mu = zeros(length(C),1);
73 else
74  mu = prop.mu;
75 end
76 
77 conf = prop.conf;
78 scale = prop.scale;
79 style = prop.style;
80 
81 if conf <= 0 | conf >= 1
82  irerror('conf parameter must be in range 0 to 1, exclusive')
83 end
84 
85 [r,c] = size(C);
86 if r ~= c | (r ~= 2 & r ~= 3)
87  irerror(['Don''t know what to do with ',num2str(r),'x',num2str(c),' matrix'])
88 end
89 
90 x0=mu(1);
91 y0=mu(2);
92 
93 % Compute quantile for the desired percentile
94 k = sqrt(qchisq(conf,r)); % r is the number of dimensions (degrees of freedom)
95 
96 hold_state = get(gca,'nextplot');
97 
98 if r==3 & c==3
99  z0=mu(3);
100 
101  % Make the matrix has positive eigenvalues - else it's not a valid covariance matrix!
102  if any(eig(C) <=0)
103  irerror('The covariance matrix must be positive definite (it has non-positive eigenvalues)')
104  end
105 
106  % C is 3x3; extract the 2x2 matricies, and plot the associated error
107  % ellipses. They are drawn in space, around the ellipsoid; it may be
108  % preferable to draw them on the axes.
109  Cxy = C(1:2,1:2);
110  Cyz = C(2:3,2:3);
111  Czx = C([3 1],[3 1]);
112 
113 % zz = get(gca, 'ZLim');
114 % zmin = zz(1);
115 % xx = get(gca, 'XLim');
116 % xmax = xx(2);
117 % yy = get(gca, 'YLim');
118 % ymax = yy(2);
119 %
120 
121 
122  % Julio Trevisan 09/12/2009: Let's draw them in the axes!
123 
124  [x,y,z] = getpoints(Cxy,prop.clip);
125  z = 0*z+prop.xyz(3);
126  h1=plot3(x0+k*x,y0+k*y, z, 'Color', prop.style, 'LineWidth', scaled(2));hold on
127 
128  [y,z,x] = getpoints(Cyz,prop.clip);
129  x = 0*x+prop.xyz(1);
130  h2=plot3(x, y0+k*y,z0+k*z, 'Color', prop.style, 'LineWidth', scaled(2));hold on
131 
132  [z,x,y] = getpoints(Czx,prop.clip);
133  y = 0*y+prop.xyz(2);
134  h3=plot3(x0+k*x, y, z0+k*z, 'Color', prop.style, 'LineWidth', scaled(2));hold on
135 
136 
137 
138 
139 % [eigvec,eigval] = eig(C);
140 %
141 % [X,Y,Z] = ellipsoid(0,0,0,1,1,1);
142 % XYZ = [X(:),Y(:),Z(:)]*sqrt(eigval)*eigvec';
143 %
144 % X(:) = scale*(k*XYZ(:,1)+x0);
145 % Y(:) = scale*(k*XYZ(:,2)+y0);
146 % Z(:) = scale*(k*XYZ(:,3)+z0);
147 % h4=surf(X,Y,Z);
148 % colormap gray
149 % alpha(0.3)
150 % camlight
151 % if nargout
152 % h=[h1 h2 h3 h4];
153 % end
154 elseif r==2 & c==2
155  % Make the matrix has positive eigenvalues - else it's not a valid covariance matrix!
156  if any(eig(C) <=0)
157  irerror('The covariance matrix must be positive definite (it has non-positive eigenvalues)')
158  end
159 
160  [x,y,z] = getpoints(C,prop.clip);
161  h1=plot(scale*(x0+k*x),scale*(y0+k*y),prop.style);
162  set(h1,'zdata',z+1)
163  if nargout
164  h=h1;
165  end
166 else
167  irerror('C (covaraince matrix) must be specified as a 2x2 or 3x3 matrix)')
168 end
169 %axis equal
170 
171 set(gca,'nextplot',hold_state);
172 
173 %---------------------------------------------------------------
174 % getpoints - Generate x and y points that define an ellipse, given a 2x2
175 % covariance matrix, C. z, if requested, is all zeros with same shape as
176 % x and y.
177 function [x,y,z] = getpoints(C,clipping_ruleRadii)
178 
179 n=100; % Number of points around ellipse
180 p=0:pi/n:2*pi; % angles around a circle
181 
182 [eigvec,eigval] = eig(C); % Compute eigen-stuff
183 xy = [cos(p'),sin(p')] * sqrt(eigval) * eigvec'; % Transformation
184 x = xy(:,1);
185 y = xy(:,2);
186 z = zeros(size(x));
187 
188 % Clip data to a bounding ruleRadii
189 if nargin >= 2
190  r = sqrt(sum(xy.^2,2)); % Euclidian distance (distance from center)
191  x(r > clipping_ruleRadii) = nan;
192  y(r > clipping_ruleRadii) = nan;
193  z(r > clipping_ruleRadii) = nan;
194 end
195 
196 %---------------------------------------------------------------
197 function x=qchisq(P,n)
198 % QCHISQ(P,N) - quantile of the chi-square distribution.
199 if nargin<2
200  n=1;
201 end
202 
203 s0 = P==0;
204 s1 = P==1;
205 s = P>0 & P<1;
206 x = 0.5*ones(size(P));
207 x(s0) = -inf;
208 x(s1) = inf;
209 x(~(s0|s1|s))=nan;
210 
211 for ii=1:14
212  dx = -(pchisq(x(s),n)-P(s))./dchisq(x(s),n);
213  x(s) = x(s)+dx;
214  if all(abs(dx) < 1e-6)
215  break;
216  end
217 end
218 
219 %---------------------------------------------------------------
220 function F=pchisq(x,n)
221 % PCHISQ(X,N) - Probability function of the chi-square distribution.
222 if nargin<2
223  n=1;
224 end
225 F=zeros(size(x));
226 
227 if rem(n,2) == 0
228  s = x>0;
229  k = 0;
230  for jj = 0:n/2-1;
231  k = k + (x(s)/2).^jj/factorial(jj);
232  end
233  F(s) = 1-exp(-x(s)/2).*k;
234 else
235  for ii=1:numel(x)
236  if x(ii) > 0
237  F(ii) = quadl(@dchisq,0,x(ii),1e-6,0,n);
238  else
239  F(ii) = 0;
240  end
241  end
242 end
243 
244 %---------------------------------------------------------------
245 function f=dchisq(x,n)
246 % DCHISQ(X,N) - Density function of the chi-square distribution.
247 if nargin<2
248  n=1;
249 end
250 f=zeros(size(x));
251 s = x>=0;
252 f(s) = x(s).^(n/2-1).*exp(-x(s)/2)./(2^(n/2)*gamma(n/2));
253 
254 %---------------------------------------------------------------
255 function properties = getopt(properties,varargin)
256 %GETOPT - Process paired optional arguments as 'prop1',val1,'prop2',val2,...
257 %
258 % getopt(properties,varargin) returns a modified properties structure,
259 % given an initial properties structure, and a list of paired arguments.
260 % Each argumnet pair should be of the form property_name,val where
261 % property_name is the name of one of the field in properties, and val is
262 % the value to be assigned to that structure field.
263 %
264 % No validation of the values is performed.
265 %
266 % EXAMPLE:
267 % properties = struct('zoom',1.0,'aspect',1.0,'gamma',1.0,'file',[],'bg',[]);
268 % properties = getopt(properties,'aspect',0.76,'file','mydata.dat')
269 % would return:
270 % properties =
271 % zoom: 1
272 % aspect: 0.7600
273 % gamma: 1
274 % file: 'mydata.dat'
275 % bg: []
276 %
277 % Typical usage in a function:
278 % properties = getopt(properties,varargin{:})
279 
280 % Process the properties (optional input arguments)
281 prop_names = fieldnames(properties);
282 TargetField = [];
283 for ii=1:length(varargin)
284 
285  arg = varargin{ii};
286  if isempty(TargetField)
287  if ~ischar(arg)
288  irerror('Propery names must be character strings');
289  end
290  f = find(strcmp(prop_names, arg));
291  if length(f) == 0
292  irerror('%s ',['invalid property ''',arg,'''; must be one of:'],prop_names{:});
293  end
294  TargetField = arg;
295  else
296  % properties.(TargetField) = arg; % Ver 6.5 and later only
297  properties = setfield(properties, TargetField, arg); % Ver 6.1 friendly
298  TargetField = '';
299  end
300 end
301 if ~isempty(TargetField)
302  irerror('Property names and values must be specified in pairs.');
303 end
304 
Property TargetField
function pchisq(in x, in n)
function getopt(in properties, in varargin)
function irerror(in s)
function getpoints(in C, in clipping_ruleRadii)
function distribution(in x, in no_points, in range, in wid)
function error_ellipse2(in varargin)
function dchisq(in x, in n)
function scaled(in i)
function qchisq(in P, in n)
Analysis Session (AS) base class.
Definition: as.m:6