IRootLab
An Open-Source MATLAB toolbox for vibrational biospectroscopy
sgs.m
Go to the documentation of this file.
1 %> @brief Base Sub-dataset Generation Specification (SGS) class
2 %>
3 %> This class generates index maps to sub-datasets, formulating these maps according to various
4 %> criteria, including cross-validation, random sub-sampling, and weighted sub-sampling.
5 %>
6 classdef sgs < irobj
7  properties
8  %> =0. Whether items from the same group (group) are to always remain together.
9  flag_group = 0;
10  %> =0. Whether to perform on each class separately.
11  flag_perclass = 0;
12  %> =0. Random seed. Only used if > 0.
13  %> if > 0, MATLAB's rand('twister', o.randseed) will be called before. This can be used to repeat sequences.
14  randomseed = 0;
15 
16  %> read-only
17  no_pieces;
18  end;
19 
20 
21 
22  properties(Access=protected)
23  flag_setup = 0;
24  data;
25  pieces;
26  %> Number of "units" in dataset. This may be a single value containing
27  %> the number of observations or groups, depending on .flag_group, or
28  %> a vector containing that information for each class, if .flag_perclass is
29  %> True.
30  no_unitss;
31  maps;
32 
33  %> Calculated upon setup, will be zero if flag_group but dataset has no groups
34  pr_flag_group;
35  end;
36 
37 
38  methods(Access=private)
39  %> Builds a 2D cell where rows are repetitions and columns are bites
40  %> repidxs is 1 1D cell of 2D cells. Within each 2D cells, rows are pieces and columns are bites, and elements
41  %> are indexes
42  function obsidxs = convert_to_obs(o, repidxs)
43  no_reps = length(repidxs);
44  no_bites = size(repidxs{1}, 2);
45  obsidxs = cell(no_reps, no_bites);
46  flag_verbose = o.no_reps > 20;
47 
48  if flag_verbose
49  ipro = progress2_open('SGS-convert_to_obs', [], 0, no_reps);
50  end;
51  for i = 1:no_reps
52  flag_mergeobs = 0; %> Switch for the second task inside the loop
53 
54  if o.pr_flag_group
55  if o.flag_perclass
56  %> In the grouped, per-class case, converts to per-piece observation to later use the common
57  %> fragment below
58  for j = 1:no_bites
59  for k = 1:o.no_pieces
60  repidxs{i}{k, j} = o.pieces(k).get_obsidxs_from_groupidxs(repidxs{i}{k, j});
61  end;
62  end;
63  flag_mergeobs = 1;
64  else
65  for j = 1:no_bites
66  obsidxs{i, j} = o.data.get_obsidxs_from_groupidxs(repidxs{i}{1, j});
67  end;
68  end;
69 
70  else
71  if o.flag_perclass
72  flag_mergeobs = 1;
73  else
74  obsidxs(i, :) = repidxs{i}(1, :);
75  end;
76  end;
77 
78  if flag_mergeobs
79  idxs_onerep = repidxs{i};
80  nos = arrayfun(@(a) length(a{1}), idxs_onerep);
81  no_perbite = sum(nos, 1);
82 
83  for j = 1:no_bites
84  obsidxs{i, j} = zeros(1, no_perbite(j));
85 
86  ptr = 1;
87  for k = 1:o.no_pieces
88 %> keyboard;
89  obsidxs{i, j}(ptr:ptr+nos(k, j)-1) = o.maps{k}(idxs_onerep{k, j});
90  ptr = ptr+nos(k, j);
91  end;
92  end;
93  end;
94 
95  if flag_verbose
96  ipro = progress2_change(ipro, [], [], i);
97  end;
98 
99  end;
100 
101  if flag_verbose
102  progress2_close(ipro);
103  end;
104  end;
105  end;
106 
107  methods(Access=protected)
108  %> Must be implemented at the descendants, this is essentially what is different for every different sgs method
109  %> This function is group-or-observation-unaware
110  %> Returns a 1D cell array or 2D cell arrays. Each element/2D cell array contains one row per piece and one
111  %> column per bite.
112  %> This function does not know if it is working with groups or observations
113  function idxs = get_repidxs(o)
114  end;
115 
116  %> Must be implemented at the descendants
117  function o = do_setup(o)
118  end;
119 
120  %> Data-independent validation
121  function o = do_assert(o)
122  end;
123  end;
124 
125  methods
126  function o = sgs(o)
127  o.classtitle = 'Sub-dataset Generation Specs';
128  o.color = [164, 100, 100]/255;
129  end;
130 
131  %> If hasn't been setup yet, will return a NaN
132  function z = get.no_pieces(o)
133  if ~o.flag_perclass
134  z = 1;
135  elseif isempty(o.pieces)
136  z = NaN; % irerror('Did not have contact with dataset yet!');
137  else
138  z = length(o.pieces);
139  end;
140  end;
141 
142  function o = setup(o, data)
143  o = o.assert();
144  o.data = data;
145 
146 
147  o.pr_flag_group = o.flag_group && ~isempty(data.groupcodes) && data.no_groups < data.no;
148  if o.flag_group && isempty(data.groupcodes)
149  irverbose('INFO: will not group rows because data groupcodes is empty!');
150  end;
151  if o.flag_group && data.no_groups == data.no
152  irverbose('INFO: will not group rows because number of groups equals number of spectra.');
153  end;
154 
155  %> Solves o.no_unitss
156  if o.flag_perclass
157  [o.pieces, o.maps] = data_split_classes(o.data);
158  if o.pr_flag_group
159  for i = 1:o.no_pieces
160  o.no_unitss(i) = o.pieces(i).no_groups;
161  if o.no_unitss(i) == 0; irerror('Number of groups in dataset piece is zero!'); end;
162  end;
163  else
164  for i = 1:o.no_pieces
165  o.no_unitss(i) = o.pieces(i).no;
166  if o.no_unitss(i) == 0; irerror('Dataset piece has no rows!'); end;
167  end;
168  end;
169  else
170  if o.pr_flag_group
171  o.no_unitss = o.data.no_groups;
172  if o.no_unitss == 0; irerror('Number of groups in dataset is zero!'); end;
173 
174  else
175  o.no_unitss = o.data.no;
176  if o.no_unitss == 0; irerror('Dataset has no rows!'); end;
177  end;
178  end;
179 
180  o = o.do_setup(); %> class-specific setup
181  o.flag_setup = 1;
182  end;
183 
184 
185 
186 
187  function obsidxs = get_obsidxs(o, data)
188  if o.randomseed > 0
189  try
190  s = RandStream.getDefaultStream; % Random stream used in random functions (default one).
191  catch
192  % 20150414 -- Above has been renamed; preserving
193  % backwards compatibility
194  % Reference:
195  % http://stackoverflow.com/questions/24640216/how-to-achieve-randstream-getdefaultstream-in-matlab2014a
196  s = RandStream.getGlobalStream;
197  end;
198  save_State = s.State; % Saves state to restore later.
199  reset(s, o.randomseed); % Resets state to one made from o.randomseed
200  end;
201 
202 % if ~o.flag_setup
203  % Of course I have to always call setup!
204  o = o.setup(data);
205 % end;
206  idxs = o.get_repidxs();
207  obsidxs = o.convert_to_obs(idxs);
208 
209  if o.randomseed > 0
210  set(s, 'State', save_State); % Restores default stream state so that random numbers can be generated as if nothing really happened here.
211  end;
212  end;
213 
214  %> Data-independent validation. Can be used at the GUI to check for parameter inconsistencies.
215  function o = assert(o)
216  o = do_assert(o);
217  end;
218  end;
219 end
function irverbose(in s, in level)
Base Sub-dataset Generation Specification (SGS) class.
Definition: sgs.m:6
function progress2_change(in prgrss, in title, in perc, in i, in n)
function progress2_open(in title, in perc, in i, in n)
function irerror(in s)
function progress2_close(in prgrss)
function data_split_classes(in data, in hierarchy)
Analysis Session (AS) base class.
Definition: as.m:6
Base class.
Definition: irobj.m:33