IRootLab
An Open-Source MATLAB toolbox for vibrational biospectroscopy
irconfusion.m
Go to the documentation of this file.
1 %> @file
2 %>@ingroup misc
3 
4 %> @brief Class representing a Confusion matrix.
5 classdef irconfusion < irlog
6  properties
7  %> List of all class labels matching the one of the classifier used. It is always used as a reference at least
8  %> to renumber the classes of the @c estimato dataset passed to @c do_record() .
9  %> least
10  collabels = {};
11  %> Grouping of rows in the confusion matrix.
12  rowlabels = {};
13  %> The matrix itself. The first column must represent rejected items
14  C = [];
15  %> Whether or not the values are expressed in percentages.
16  flag_perc = 1;
17  %> =0. Whether to show the "Rejected" column even if there is no rejected item
18  flag_force_rejected = 0;
19  end;
20 
21  properties
22  %> Whether there is any rejected item, i.e. a nonzero element in the first column. This is automatically calculated
23  flag_rejected;
24  %> WHether to show the rejected column. Calculated based on @ref flag_force_rejected and @ref flag_rejected
25  flag_show_rejected;
26  end;
27 
28  methods
29  function flag = get.flag_rejected(o)
30  flag = ~isempty(o.C) && any(o.C(:, 1) > 0);
31  end;
32 
33  function flag = get.flag_show_rejected(o)
34  flag = o.flag_rejected || o.flag_force_rejected;
35  end;
36  end;
37 
38  methods(Access=protected)
39  %> Automatically detects if confusion matrix has hits or percentages
40  function s = do_get_html(o)
41  s = o.get_html_table();
42  end;
43  end;
44 
45  methods
46  function o = irconfusion()
47  o.classtitle = 'Confusion Matrix';
48  end;
49 
50  function z = get_flag_sortable(o)
51  n1 = numel(o.collabels);
52  n2 = numel(o.rowlabels);
53  z = n1 == n2 && sum(strcmp(o.collabels, o.rowlabels)) == n1;
54  end;
55 
56  %> Automatically detects if confusion matrix has hits or percentages
57  function s = get_html_table(o)
58  CC = o.C;
59  s = html_confusion(CC, o.rowlabels, o.collabels, o.flag_perc, o.flag_show_rejected);
60  end;
61 
62 
63  %> This sorting is made to group rows/columns. It was used in one of the presentations to Unilever
64  %> @param no_levels Number of levels in index key
65  function o = sort(o, no_levels)
66  if ~o.get_flag_sortable()
67  irerror('Cannot sort, collabels and rowslabels are different!');
68  end;
69 
70  if ~exist('no_levels', 'var')
71  no_levels = 3;
72  end;
73 
74  n = numel(o.collabels);
75 
76  CC = o.C(:, 2:end);
77  CC2 = CC;
78 
79  % Normalizes for keymaking
80  ma = max(CC(:));
81  if ma == 0
82  ma = 1;
83  end;
84  Ctemp = CC(:); Ctemp(Ctemp == 0) = [];
85  mi = min(Ctemp);
86  CC3 = (CC+eye(n))/ma; % This one just for the key values: diagonals have maximum weight!
87  CC = CC/ma; % This one to find the columns to be used as keys
88 
89 
90  ii = 1:numel(o.collabels); %#ok<NASGU>
91  iifinal = 1:numel(o.collabels); %#ok<NASGU>
92 
93  flag_col = 1;
94  if flag_col
95  dimmax = 1;
96  else
97  dimmax = 2; %#ok<UNRCH>
98  end;
99 
100  % Finds a list of columns to use as index keys
101  vk = zeros(1, no_levels);
102  CCtemp = CC; %#ok<NASGU>
103  iitemp = 1:n;
104  for j = 1:no_levels
105  [vv1, ii1] = max(CC(iitemp, iitemp), [], dimmax); %#ok<NASGU> % column maxima
106  [vv2, ii2] = max(vv1);
107  vk(j) = iitemp(ii2);
108  iitemp(ii2) = [];
109  end;
110 
111 
112  % Makes a key vector for indexing
113  k = zeros(1, n);
114  M = 10^(ceil(log10(ma))-log10(mi)+1);
115  mult = 1;
116  for j = no_levels:-1:1
117  if flag_col
118  k = k+mult*CC3(:, vk(j))';
119  else
120  k = k+mult*CC3(vk(j), :); %#ok<UNRCH>
121  end;
122  mult = mult*M;
123  end;
124 
125  [val, idxs] = sort(k, 'descend');
126 
127  o.collabels = o.collabels(idxs); % Somehow stupid since collabels and ...
128  o.rowlabels = o.rowlabels(idxs); % ... rowlabels need be the same, but anyway ...
129  CC2 = CC2(idxs, :);
130  CC2 = CC2(:, idxs);
131  o.C(:, 2:end) = CC2;
132  end;
133 
134 
135  %> Visualization. Draws figure with circles whose area are proportional to the percentuals of the corresponding
136  %> cells of the matrix
137  function o = draw_balls(o)
138  global FONTSIZE;
139 
140  FULLDIAM = 0.8; % Diameter of an 100% ball
141  MINPERC_BALL = 0.02; % Minimum percentage to draw a ball
142  MINPERC_TEXT = 0.1; % Minimum percentage to write percentage text
143 
144  Ccalc = o.C;
145  Cshow = Ccalc;
146  [ni, nj] = size(Ccalc);
147 
148  % What to show
149  sperc = '';
150  if o.flag_perc
151  sperc = '%';
152  Cshow = round(Cshow*100)/100; % To make 2 decimal places only
153  end;
154 
155  % What to use for calculation (normalizes to 0-1)
156  Ccalc = normalize_rows(Ccalc);
157 
158  % Makes header strings.
159  c = ['rejected' o.collabels];
160 
161 
162  % Other calculations
163  yspacing = 1.3;
164  xlim = [0, nj+1-(1-o.flag_show_rejected)]; % x-limits
165  ylim = [0, (ni-1)*yspacing+2];
166  flag_same = compare(o.collabels, o.rowlabels);
167 
168  hh = [];
169  hh2 = [];
170  hhtext1 = [];
171  hhtext2 = [];
172  for i = 1:ni % row loop
173 
174  ypos = (i-1)*yspacing+1;
175 
176  plot(xlim, ypos*[1, 1], 'k', 'LineWidth', scaled(3)); % Horizontal line
177  hold on;
178  hh(end+1) = text(xlim(1)-0.1, ypos, o.rowlabels{i}, 'HorizontalAlignment', 'right'); % Descriptive text
179  hhtext1(end+1) = hh(end);
180 
181  k = 0; % graphics column (whereas j is the matrix column)
182  for j = iif(o.flag_show_rejected, 1, 2):nj % column loop
183  k = k+1;
184 
185  if i == 1
186  hh(end+1) = text(k, -0.1, c{j}, 'HorizontalAlignment', 'right', 'Rotation', 270);
187  hhtext2(end+1) = hh(end);
188 
189 % plot(k*[1, 1], ylim, 'k', 'LineWidth', scaled(3)); % Vertical line
190  end;
191 
192  if Ccalc(i, j) > MINPERC_BALL
193  diam = sqrt(FULLDIAM*Ccalc(i, j));
194  pos = [k-diam/2, ypos-diam/2, diam, diam];
195  if j == 1
196  color_ = [1, 1, 1]*.3;
197  elseif flag_same
198  if i == j-1
199  color_ = [0, 0.7, 0];
200  else
201  color_ = [1, 0, 0];
202  end;
203  else
204  color_ = find_color(j-1);
205  end;
206  rectangle('Position', pos, 'LineStyle', '-', 'LineWidth', scaled(2), 'FaceColor', color_, 'Curvature', [1, 1]);%, 'LineColor', 'k');
207 
208  if Ccalc(i, j) >= MINPERC_TEXT
209  hh2(end+1) = text(k, ypos-diam/2, [sprintf('%g', Cshow(i, j)), sperc], 'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom');
210  end;
211  end;
212  end;
213  end;
214  plot(xlim([1, 2, 2, 1, 1]), ylim([1, 1, 2, 2, 1]), 'Color', [0, 0, 0], 'LineWidth', scaled(2)); % Box
215 
216  axis equal;
217  axis off;
218  set(gca, 'YDir', 'reverse');
219  set(gca, 'XTick', [], 'YTick', []);
220  format_frank(gcf, 1, [hh, hh2]);
221  for i = 1:numel(hh2)
222  set(hh2, 'FontSize', FONTSIZE*scaled(.75));
223  end;
224 
225  % Let's attempt to make all the ticks/(row/column titles)/(class labels) to appear
226  maximize_window([], 1, .9); % Have to do this, because the Extent property below gives values relative to the gca(), and this changes according to the size of the figure on screen
227  pause(0.2); % Has to wait until the window maximization takes place
228  maxwid = -Inf;
229  for i = 1:ni
230 % set(hhtext1(i), 'Unit', 'Normalized');
231  p = get(hhtext1(i), 'Extent');
232  maxwid = max([maxwid, p(3)]);
233  end;
234  maxhei = -Inf;
235  for i = 1:numel(hhtext2)
236 % set(hhtext2(i), 'Unit', 'Normalized');
237  p = get(hhtext2(i), 'Extent');
238  maxhei = max([maxhei, p(4)]);
239  end;
240 
241  xlim(1) = xlim(1)-maxwid-0.1;
242  ylim(1) = ylim(1)-maxhei-0.1;
243 
244  set(gca, 'Xlim', xlim, 'YLim', ylim, 'position', [0.025, 0.025, 0.95, 0.95]);
245 %
246 % maxhei = -Inf;
247 % for i = 1:ni
248 % % set(hhtext2(i), 'Unit', 'Normalized');
249 % p = get(hhtext2(i), 'Extent');
250 % maxhei = max([maxhei, p(4)]);
251 % end;
252 %
253 %
254 % totalwid = maxwid+1;
255 % totalhei = maxhei+1;
256 % x = maxwid/totalwid;
257 % y = maxhei/totalhei;
258 %
259 % p = get(gca, 'Position');
260 % p(1) = x;
261 % p(3) = 1-x;
262 % p(2) = 0.025;
263 % p(4) = .975-y;
264 % if all(p([2, 4]) > 0)
265 % set(gca, 'Position', p);
266 % end;
267 %
268  end;
269  end;
270 end
function maximize_window(in h, in aspectratio, in normalizedsize)
function html_confusion(in CC, in rowlabels, in collabels, in flag_perc, in flag_rejected, in flag_color, in SS)
function irerror(in s)
Dataset representing estimation.
Definition: estimato.m:4
Class representing a Confusion matrix.
Definition: irconfusion.m:5
Analysis Session (AS) base class.
Definition: as.m:6
Log base class.
Definition: irlog.m:5