IRootLab
An Open-Source MATLAB toolbox for vibrational biospectroscopy
mergetool.m
Go to the documentation of this file.
1 %> @ingroup guigroup mainguis codegen
2 %> @file
3 %> @brief Tool to merge several single-spectrum files into a dataset.
4 %> @image html Screenshot-mergetool.png
5 %>
6 %> <b>Directory containing multiple files</b> - directory containing multiple single-spectrum files.
7 %> @note make sure that this directory contains <b>only</b> the files of interest. View files, sort by <b>size</b> and checks extremities to detect unusual
8 %> file sizes. These may be invalid spectra.
9 %> @attention Never use directory names nor file names containing single quotes (" ' "). They are not handled properly by mergetool, and will cause the operation to fail.
10 %>
11 %> <b>File type</b> - Currently supported types are:
12 %> @arg "Pirouette .DAT" text format
13 %> @arg OPUS binary format
14 %> @arg Wire TXT format
15 %>
16 %> <b>File filter</b> - wildcard filter. Examples: <code>*.*</code>; <code>*.dat</code>; <code>*.DAT</code>
17 %>
18 %> <b>Group code trimming dot (right-to-left)</b> - allows you control over trimming off part of the filename for the <b>group code</b> of each spectrum.
19 %> For example, you may have several files like:
20 %> @verbatim
21 %> sample1.000.dat
22 %> sample1.001.dat
23 %> sample1.002.dat
24 %> ^ ^
25 %> | |
26 %> | 1 first dot (left-to-right)
27 %> |
28 %> 2 second dot
29 %> @endverbatim
30 %> All these are spectra from the same group (named "sample1"). Specifying "2" for the trimming dot will get rid of
31 %> everything after the 2nd last dot counting from right to left. Thus, all spectra will have group code "sample1".
32 %>
33 %> <h3>Image building options</h3>
34 %> If <b>Build image is checked</b>, the image <b>height</b> needs to be informed. The width is automatically calculated as the number of files in the directory divided by the informed <b>height</b>.
35 %> @note To build an image, the files need to have a sequential numbering between dots, as above.
36 
37 %> @cond
38 function varargout = mergetool(varargin)
39 % Last Modified by GUIDE v2.5 24-Nov-2012 11:42:47
40 
41 % Begin initialization code - DO NOT EDIT
42 gui_Singleton = 1;
43 gui_State = struct('gui_Name', mfilename, ...
44  'gui_Singleton', gui_Singleton, ...
45  'gui_OpeningFcn', @mergetool_OpeningFcn, ...
46  'gui_OutputFcn', @mergetool_OutputFcn, ...
47  'gui_LayoutFcn', [] , ...
48  'gui_Callback', []);
49 if nargin && ischar(varargin{1})
50  gui_State.gui_Callback = str2func(varargin{1});
51 end
52 
53 if nargout
54  [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
55 else
56  gui_mainfcn(gui_State, varargin{:});
57 end
58 % End initialization code - DO NOT EDIT
59 
60 
61 % --- Executes just before mergetool is made visible.
62 function mergetool_OpeningFcn(hObject, eventdata, handles, varargin) %#ok<*INUSL>
63 
64 % Choose default command line output for mergetool
65 handles.output = hObject;
66 
67 setup_load();
68 path_assert();
69 global PATH;
70 set(handles.editPath, 'String', PATH.data_spectra);
71 guidata(hObject, handles); % Update handles structure
72 gui_set_position(hObject);
73 check_hsc();
74 
75 
76 % --- Outputs from this function are returned to the command line.
77 function varargout = mergetool_OutputFcn(hObject, eventdata, handles)
78 varargout{1} = handles.output;
79 
80 
81 %=======================================================================================================================
82 
83 
84 %==============================
85 function handles = find_handles()
86 H = findall(0, 'Name', 'mergetool');
87 if isempty(H)
88  irerror('mergetool not open');
89 end;
90 handles = guidata(H);
91 
92 %==============================
93 function add_log(s)
94 handles = find_handles();
95 a = get(handles.editStatus2, 'String');
96 s = {s};
97 set(handles.editStatus2, 'String', [a; s]);
98 
99 %==============================
100 function morasse_lah(handles, filename, idx1, idx2, msg)
101 add_log(filename);
102 % SLASH = '/';
103 add_log([repmat(' ', 1, idx1-1), repmat('-', 1, idx2-idx1+1)]);
104 add_log([repmat(' ', 1, idx2-1), '|']);
105 add_log([repmat(' ', 1, idx2-1), msg]);
106 
107 
108 
109 %==============================
110 % Reads parameters from mergetool window edit boxes; performs minor checks
111 %
112 % Returns a stru with .filetype, .wild, .trimdot, .flag_image, .height
113 function stru = get_window_settings()
114 handles = find_handles();
115 stypes = {'pir', 'opus', 'wire'};
116 try
117  stru.filetype = stypes{get(handles.popupmenu_type, 'value')};
118  stru.wild = get_wild();
119  stru.trimdot = eval(get(handles.editTrimdot, 'String'));
120  stru.flag_image = get(handles.checkbox_flag_image, 'Value');
121  stru.height = eval(get(handles.edit_height, 'String'));
122 
123  if isempty(stru.height)
124  stru.height = 0;
125  end;
126 
127  if stru.flag_image
128  if stru.height <= 0
129  irerror('Please specify height');
130  end;
131 
132  if stru.trimdot < 1
133  irerror('For image building, "Group code trimming dot" needs be at least 1!');
134  end;
135  end;
136 catch ME
137  irerror(sprintf('Error in window settings:\n%s', ME.message));
138 end;
139 
140 %==============================
141 function do_checks(handles)
142 set(handles.editStatus2, 'String', '');
143 add_log('==> Checking... ==>');
144 try
145  stru = get_window_settings();
146 
147  [filenames, groupcodes] = resolve_dir(stru.wild, stru.trimdot, stru.flag_image);
148  no_files = numel(filenames);
149 
150  add_log(sprintf('Number of files: %d', no_files));
151  add_log(sprintf('Number of groups: %d', numel(unique(groupcodes))));
152 
153  if no_files > 0
154  filename = filenames{1};
155  idxs = find([filename, '.'] == '.');
156  if numel(idxs) < stru.trimdot+1
157  irerror(sprintf('File name such as "%s" has only %d dot%s, whereas "Group code trimming dot" is %d!', filename, numel(idxs)-1, iif(numel(idxs)-1 > 1, 's', ''), stru.trimdot));
158  end;
159  idx1 = 1;
160  idx2 = idxs(end-stru.trimdot)-1;
161  code = filename(1:idx2);
162  morasse_lah(handles, filename, idx1, idx2, ['Group code ("', code, '")']);
163 
164  if stru.flag_image
165  idx1 = idxs(end-stru.trimdot)+1;
166  idx2 = idxs(end-stru.trimdot+1)-1;
167  sorderref = filename(idx1:idx2);
168  morasse_lah(handles, filename, idx1, idx2, ['Sequence number for image pixels ("', sorderref, '")']);
169  orderref = str2double(sorderref);
170  if isnan(orderref)
171  irerror(sprintf('File part "%s" should be a number!', sorderref));
172  end;
173 
174  if stru.flag_image
175  if stru.height <= 0
176  irerror('Please specify image height!');
177  end;
178 
179  if no_files/stru.height ~= floor(no_files/stru.height)
180  irerror(sprintf('Invalid image height: %d not divisible by %d!', no_files, stru.height));
181  end;
182 
183  add_log(sprintf('Image width: %d', no_files/stru.height));
184  end;
185  end;
186  else
187  irerror('No files!');
188  end;
189 
190  [filenames, groupcodes] = resolve_dir(stru.wild, stru.trimdot, stru.flag_image); %#ok<NASGU>
191 
192  add_log('===> ...Passed!');
193 catch ME
194  add_log(['===> ...Checking error: ', ME.message]);
195  send_error(ME);
196 end;
197 
198 
199 function path_ = get_wild()
200 handles = find_handles();
201 % handles structure with handles and user data (see GUIDATA)
202 
203 path_ = get(handles.editPath, 'String');
204 filter = get(handles.editFilter, 'String');
205 if isempty(path_)
206  path_ = '.';
207 end;
208 if path_(end) ~= '/'
209  path_ = [path_ '/'];
210 end;
211 
212 path_ = [path_ filter];
213 
214 
215 %=======================================================================================================================
216 
217 
218 
219 
220 
221 
222 %####
223 function editPath_Callback(hObject, eventdata, handles)
224 set(handles.textStatus, 'String', '?');
225 set(handles.editStatus2, 'String', '?');
226 
227 %#####
228 function pushbuttonGo_Callback(hObject, eventdata, handles)
229 set(handles.editStatus2, 'String', '');
230 do_checks(handles);
231 
232 % Pre-check with get_wild() only
233 path_ = get_wild();
234 a = dir(path_);
235 if length(a) == 0 %#ok<ISMT>
236  msgbox('No files found in specified directory!');
237 else
238  try
239  % Check-n-load vars from GUI
240  stru = get_window_settings();
241 
242  [filenames, groupcodes] = resolve_dir(stru.wild, stru.trimdot, stru.flag_image); %#ok<NASGU>
243  no_files = numel(filenames);
244 
245  % Creates dataset in workspace
246  name_new = find_varname('ds');
247 
248  s_code = sprintf('[%s, flag_error] = %s2data(''%s'', %d, %d, %d);', ...
249  name_new, stru.filetype, path_, stru.trimdot, stru.flag_image, stru.height); % Line of MATLAB code
250 
251  evalin('base', s_code);
252 
253  ds = evalin('base', [name_new ';']);
254  flag_error = evalin('base', 'flag_error;');
255 
256  add_log(sprintf('Imported: %d', no_files-flag_error));
257  add_log(sprintf('Failed: %d', flag_error));
258  add_log(sprintf('Total: %d', no_files));
259  if flag_error
260  ss = 'Finished with errors. Check MATLAB command window output.';
261  if flag_error > 7 && flag_error/no_files > 0.51
262  add_log(sprintf('A large amount of files failed to import. Maybe the files are of a different type?'));
263  end;
264  else
265  ss = 'Success!';
266  end;
267  add_log(sprintf('%s! Variable name in workspace: %s; Number of rows: %d', ss, name_new, ds.no));
268 
269  path_assert();
270  global PATH; %#ok<TLEV>
271  PATH.data_spectra = get(handles.editPath, 'String');
272  setup_write();
273  catch ME
274  send_error(ME);
275  end;
276 end;
277 
278 
279 %#####
280 function pushbuttonOpen_Callback(hObject, eventdata, handles) %#ok<*DEFNU>
281 o = uigetdir(get(handles.editPath, 'String'));
282 
283 if ~(isnumeric(o) && o == 0)
284  set(handles.editPath, 'String', o);
285 end;
286 
287 %#####
288 function pushbuttonLaunch_Callback(hObject, eventdata, handles)
289 datatool();
290 
291 %#####
292 function pushbutton_check_Callback(hObject, eventdata, handles)
293 do_checks(handles);
294 
295 %#####
296 function pushbuttonLaunchObjtool_Callback(hObject, eventdata, handles)
297 objtool();
298 
299 %#####
300 function pushbutton_detect_Callback(hObject, eventdata, handles)
301 s = detect_spectrum_type(get_wild());
302 if ~isempty(s)
303  handles = find_handles();
304  i_type = find(strcmp(s, {'pir', 'opus', 'wire'}));
305  set(handles.popupmenu_type, 'Value', i_type);
306  add_log(sprintf('Detected file type: "%s"', s));
307 else
308  msgbox('Could not detect file type in specified directory.');
309 end;
310 
311 %------------------------------------------------------------------------------------------------------------------------------------------
312 
313 function editFilter_Callback(hObject, eventdata, handles) %#ok<*INUSD>
314 function editFilter_CreateFcn(hObject, eventdata, handles)
315 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
316  set(hObject,'BackgroundColor','white');
317 end
318 function editTrimdot_Callback(hObject, eventdata, handles)
319 function editTrimdot_CreateFcn(hObject, eventdata, handles)
320 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
321  set(hObject,'BackgroundColor','white');
322 end
323 
324 
325 function editStatus2_Callback(hObject, eventdata, handles)
326 function editStatus2_CreateFcn(hObject, eventdata, handles)
327 function checkbox_flag_image_Callback(hObject, eventdata, handles)
328 function edit_height_Callback(hObject, eventdata, handles)
329 function edit_height_CreateFcn(hObject, eventdata, handles)
330 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
331  set(hObject,'BackgroundColor','white');
332 end
333 function popupmenu_type_Callback(hObject, eventdata, handles)
334 function popupmenu_type_CreateFcn(hObject, eventdata, handles)
335 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
336  set(hObject,'BackgroundColor','white');
337 end
338 function editPath_CreateFcn(hObject, eventdata, handles)
339 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
340  set(hObject,'BackgroundColor','white');
341 end
342 function editTarget_Callback(hObject, eventdata, handles)
343 function editTarget_CreateFcn(hObject, eventdata, handles)
344 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
345  set(hObject,'BackgroundColor','white');
346 end
347 
348 
349 
350 %> @endcond
function send_error(in ME)
function irerror(in s)
function objtool(in varargin)
function resolve_dir(in wild, in trimdot, in flag_image)
function check_hsc()
function detect_spectrum_type(in wild)
function iif(in cond, in x1, in x2)
function setup_write()
function gui_set_position(in hObject)
Analysis Session (AS) base class.
Definition: as.m:6
function path_assert()
function find_varname(in prefix)
function setup_load()