diff --git a/db/db_clear_temp.m b/db/db_clear_temp.m new file mode 100644 index 0000000..f859802 --- /dev/null +++ b/db/db_clear_temp.m @@ -0,0 +1,20 @@ +function db = db_clear_temp(db, rs) + +% DB_CLEAR_TEMP allows to clear unused temporary files from disc +% (or remove from the database information about temporary files +% that no longer exist) + +if ~exist('rs', 'var') + rs = 1:length(db); +end +% remove unused temp files +for r = rs + [tmp, mtch, ind] = db_temp_get(db, r); + if ~mtch + db = db_remove_temp(db, r, 'all'); + else + temp_inds = 1:length(db(r).datainfo.tempfiles); + temp_inds(ind) = []; + db = db_remove_temp(db, r, temp_inds); + end +end \ No newline at end of file diff --git a/db/db_epoch.m b/db/db_epoch.m new file mode 100644 index 0000000..a199442 --- /dev/null +++ b/db/db_epoch.m @@ -0,0 +1,115 @@ +function EEG = db_epoch(EEG, db, r, segmentinfo) + +% DB_EPOCH is the function used by eegDb for epoching +% files are epoched automatically when they are recovered +% FIXHELPINFO + + +if femp(db(r), 'epoch') + + % defaults + % -------- + code_id = '\code:'; + cidlen = length(code_id); + + if ~exist('r', 'var') + r = 1; + end + + if ~exist('segmentinfo', 'var') + % is segment given: + if isfield(db(r).epoch, 'segment') && ... + ~isempty(db(r).epoch.segment) && isnumeric(db(r).epoch.segment) + segmentinfo = true; + end + end + + % windowing + % --------- + % (consecutive epochs, not event locked) + if femp(db(r).epoch, 'locked') && ~db(r).epoch.locked + + % ============== + % onesec options + options.fill = true; + + flds = {'filter', 'winlen', 'distance',... + 'leave', 'eventname'}; + + % checking fields for onesecepoch + for f = 1:length(flds) + if femp(db(r).epoch, flds{f}) + options.(flds{f}) = db(r).epoch.(flds{f}); + end + end + + % if prerej is present then no need to use distance + if femp(db(r).reject, 'pre') + options.distance = []; + end + + % =================== + % call to onesecepoch + EEG = onesecepoch(EEG, options); + clear options + + elseif ~isempty(db(r).epoch.events) && ... + ~isempty(db(r).epoch.limits) + + % ================== + % classical epoching + epoc = db(r).epoch.events; + + % checking for code generator of epochs + % ADD - function handle for epoching? + % or maybe not necessary - there is an + % option for user-defined function + if ischar(epoc) && length(epoc) > cidlen && ... + strcmp(epoc(1:cidlen), code_id) + + epoc = eval(epoc(cidlen+1:end)); + end + + EEG = db_fastepoch(EEG, epoc, db(r).epoch.limits); + + % ======================= + % checking for segmenting + if segmentinfo && ~nosegment + EEG = segmentEEG(EEG, db(r).epoch.segment); + end + end +end + +% CHANGE +% [ ] if we segment then orig_numep should be adjusted too +% [ ] instead of numep this all can be done in a smarter way +% 1) generally - onesec can add numep too +% 2) numep can be inferred from length of rejections +% in db(r)! +% 3) ... +% [ ] in the current version only onesecepoching is checked +% for while in future releases we want to include also +% conditional epoch extraction (only correct etc.) which +% is another prerej +% +% +% ====================== +% adding orig_numep info +% +% (this is later used when rejections are added +% using a recovered file that has some of the +% rejections already removed) +% +% if epoched signal add orig_numep +EEG.etc.orig_numep = size(EEG.data, 3); + +% if onesecepoch was perfromed add onesec info +if femp(db(r).epoch, 'locked') && ~db(r).epoch.locked + + % either prerej is nonempty % or what? + if femp(db(r).reject, 'pre') + % there is some info about prerej, + % we correct orig_numep + EEG.etc.orig_numep = EEG.etc.orig_numep - length(db(r).reject.pre); + end +end diff --git a/db/paths/db_remove_temp.m b/db/paths/db_remove_temp.m new file mode 100644 index 0000000..8f3257c --- /dev/null +++ b/db/paths/db_remove_temp.m @@ -0,0 +1,20 @@ +function db_remove_temp(db, r, optind) + +% +ind = optind; +if ischar(optind) + if strcmp(optind, 'all') + ind = 1:length(db(r).datainfo.tempfiles); + end +end +ind = ind(:)'; + +% remove file +for rmv = ind + pth = db_test_temp_path(db, r, rmv); + delete(fullfile(pth, db(r).datainfo... + .tempfiles(rmv).filename)); +end + +% clear info from the db +db(r).datainfo.tempfiles(ind) = []; diff --git a/db/paths/db_temp_get.m b/db/paths/db_temp_get.m new file mode 100644 index 0000000..6a401b2 --- /dev/null +++ b/db/paths/db_temp_get.m @@ -0,0 +1,106 @@ +function [tempdb, match, ind] = db_temp_get(db, r) + +% DB_TEMP_GET gives info on relevant tempfile for db +% record r. +% +% usage +% ----- +% temp = db_temp_get(db, r); +% +% input +% ----- +% db - *structure*; eegDb database +% r - *integer*; record number +% +% output +% ------ +% temp - *structure*; tempfile info, with fields: +% .filename +% .filepath +% .filter +% .cleanline +% .epoch + + + +tempdb = []; +match = 0; + +if femp(db(r).datainfo, 'tempfiles') + % some tempfiles are present, check which + % ones are present on disc + temp = db(r).datainfo.tempfiles; + tempok = false(1, length(temp)); + for t = 1:length(temp) + tempok(t) = ~isempty(db_test_temp_path(db, r, t)); + end + temp = temp(tempok); + + if isempty(temp) + return + end + + % check which tempfile matches the + % current database pipeline + + % get filtering and epoching from the current record: + tst = struct('filter', [], 'epoch', [], 'cleanline', []); + + % epoching + tst.epoch = db_getepoching(db(r)); + + % filtering (should CHANGE to db_get later on) + in = cellfun(@(x) femp(x, 'filter'), {db(r), db(r).datainfo}); + in(3) = femp(db(r).datainfo, 'filtered'); + + if any(in) + if in(1) + tst.filter = db(r).filter; + elseif in(2) + tst.filter = db(r).datainfo.filter; + elseif in(3) + tst.filter = db(r).datainfo.filtered; + end + end + + % cleanline + if femp(db(r).datainfo, 'cleanline') + tst.cleanline = db(r).datainfo.cleanline; + end + + % only filtering and epoching are considered + checkflds = {'cleanline', 'filter', 'epoch'}; + test_temp = false(length(checkflds), length(temp)); + + for f = 1:length(checkflds) + test_temp(f, :) = cellfun(@(x) isequal(x, ... + tst.(checkflds{f})), {temp.(checkflds{f})}); + end + good_temp = all(test_temp(1:2, :), 1); + best_temp = all(test_temp, 1); + + ind = []; + % choose first one matching (CHANGE!) + if any(best_temp) + ind = find(best_temp, 1); + match = 2; + elseif any(good_temp) + ind = find(good_temp, 1); + match = 1; + end + + if ~isempty(ind) + % give tempdb + tempdb = struct(); + tempdb.filename = temp(ind).filename; + if temp(ind).filepath(1) == '+' + tempdb.filepath = get_valid_path(temp(ind).filepath, ... + 'file', temp(ind).filename, 'dir', temp(ind).filepath(2:end)); + else + tempdb.filepath = temp(ind).filepath; + end + tempdb.filter = temp(ind).filter; + tempdb.epoch = temp(ind).epoch; + tempdb.cleanline = temp(ind).cleanline; + end +end diff --git a/db/paths/db_test_temp_path.m b/db/paths/db_test_temp_path.m new file mode 100644 index 0000000..0bd97d3 --- /dev/null +++ b/db/paths/db_test_temp_path.m @@ -0,0 +1,15 @@ +function pth = db_test_temp_path(db, r, t) + +temp = db(r).datainfo.tempfiles; +if temp(t).filepath(1) == '+' + % this uses a vild path from db(r).filepath + % and a subdir in it + pth = get_valid_path(db(r).filepath, ... + 'file', temp(t).filename, ... + 'dir', temp(t).filepath(2:end), ... + 'noerror', true)); +else + pth = get_valid_path(temp(t).filepath, ... + 'file', temp(t).filename, ... + 'noerror', true)); +end \ No newline at end of file diff --git a/db/paths/get_valid_path.m b/db/paths/get_valid_path.m index 8287b69..e6e5e69 100644 --- a/db/paths/get_valid_path.m +++ b/db/paths/get_valid_path.m @@ -1,6 +1,51 @@ -function pth = get_valid_path(PTH) +function pth = get_valid_path(PTH, varargin) -% FIXHELPINFO +% GET_VALID_PATH checks which path is valid on a given machine +% +% usage +% ----- +% pth = get_valid_path(PTH, ...); +% +% input +% ----- +% PTH - *string* or *cell array of strings*; path string(s) +% +% ... - additional key - value pairs +% +% key-value pairs +% --------------- +% 'file' - *string*; filename that should be present +% in the valid path +% 'dir' - *string*; directory that should be present +% in the valid path. In conjunction with 'file' +% option - the file has to be in the directory +% denoted by 'dir' +% 'noerror' - *logical*; whether NOT to throw an error when valid +% path was not found +% default: false (error is thrown) +% +% examples +% -------- +% check which path to Dropbox is correct on given machine: +% PTH = {'D:\Dropbox\', 'C:\Users\Kant\Dropbox\'}; +% validpath = get_valid_path(PTH); +% +% check which folder exists AND has file 'data.set' inside: +% PTH = {'C:\DATA\superstudy\', 'C:\DATA\otherstudy\'}; +% validpath = get_valid_path(PTH, 'file', 'data.set'); +% +% see also: isdir + +% additional args +pth = []; +opt.file = []; +opt.dir = []; +opt.noerror = false; +if nargin > 1 + opt = parse_arse(varargin, opt); +end +iffile = ~isempty(opt.file); +ifdir = ~isempty(opt.dir); % if not cell - close in a cell if ~iscell(PTH) @@ -11,13 +56,28 @@ fnd = false; for p = 1:length(PTH) % and test isdir() on them - if isdir(PTH{p}) - % if it is dir, stop looking - pth = PTH{p}; - fnd = true; - break + thispth = PTH{p}; + if ifdir + thispth = fullfile(thispth, opt.dir); + end + if isdir(thispth) + % if filecheck, check if file is present: + if iffile + fls = dir(thispth); + fileok = any(strcmp(opt.file, {fls(~[fls.isdir]).name})); + end + + % if everything ok - stop looking + if ~iffile || fileok + pth = thispth; + fnd = true; + break + end + end +end + +if ~opt.noerror + if ~fnd + error('Could not find the correct path'); end end -if ~fnd - error('Could not find the correct path'); -end \ No newline at end of file diff --git a/db/recoverEEG.m b/db/recoverEEG.m index 2bb9ed8..1e9fc61 100644 --- a/db/recoverEEG.m +++ b/db/recoverEEG.m @@ -1,4 +1,4 @@ -function EEG = recoverEEG(db, r, varargin) +function [EEG, orig_db] = recoverEEG(db, r, varargin) % RECOVEREEG recovers a file from raw data % according to db database @@ -18,8 +18,8 @@ % additional keys: % 'prerej' - remove only the prerejected % epochs -% 'loaded' - the file is loaded - look for corresponding -% modifications in the database and recover +% 'tempsave' - whether to save a temporary file to +% speed up later recovery % 'dir' - allows to pass the directory % where files reside (the path % stated in the database can be @@ -60,14 +60,6 @@ % covery. % -% VERSION info: -% 2014.01.27 --> compressed icaweights temp usage when -% interpolating -% 2014.03.25 --> moved interpolation before epoching -% added postfilter between interpolation -% and epoching -% 2014.06.22 --> changed path checking loop to db_path -% function call % TODOs: % [ ] path availability and eeglab inteface presence @@ -90,9 +82,6 @@ % visible % [ ] remove the paths to eeglab in 'local' or recover % previous path? -% [ ] CHANGE 'loaded' behavior - now it only adds ICA, -% should it perform other modifs (filtering, epoching, -% etc.)? How should 'loaded' generally work?? %% defaults: @@ -100,17 +89,19 @@ local = false; nofilter = false; loaded = false; addfilt = []; overr_dir = false; noICA = false; -code_id = '\code:'; ICAnorem = false; +ICAnorem = false; interp = false; segment = false; -nosegment = false; +nosegment = false; tempsave = false; +haspostfilter = femp(db(r), 'postfilter'); +orig_db = db; -cidlen = length(code_id); %% checking additional arguments if nargin > 2 % optional arguments args = {'interp', 'ICAnorem', 'prerej', 'local',... - 'loaded', 'nofilter', 'noICA', 'nosegment'}; + 'loaded', 'nofilter', 'noICA', 'nosegment', ... + 'tempsave'}; % simple argument checks for a = 1:length(args) @@ -135,10 +126,9 @@ reslt = strcmp('dir', varargin); if sum(reslt)>0 overr_dir = true; - path = varargin{find(reslt) + 1}; + additional_path = varargin{find(reslt) + 1}; end - %zmienilam cos - tzn co? [Miko] % ADD - check for path override end @@ -202,10 +192,24 @@ % end % end +% ====================== +% support for tempfiles: +tmp = db_temp_get(db, r); +got_temp = false; +if ~isempty(tmp) + got_temp = true; + db(r).filename = tmp.filename; + db(r).filepath = tmp.filepath; + db(r).filter = []; + if femp(tmp, 'epoch') + db(r).epoch = []; + end +end + % ==================================== % if user chooses to override filepath if overr_dir - db(r).filepath = path; + db(r).filepath = additional_path; end % ================================================ @@ -305,8 +309,7 @@ % checking filtering if ~nofilter % optional filtering: - if isfield(db(r), 'filter') && ... - ~isempty(db(r).filter) + if femp(db(r), 'filter') % setting up filter: filt = db(r).filter; @@ -367,6 +370,44 @@ end end +%% epoching if not haspostfilter +if ~haspostfilter + EEG = db_epoch(EEG, db, r, min(segment, ~nosegment)); + if ~got_temp && tempsave + % save temp + % CHANGE - multiple paths issue, CleanLine path issue + valid_path = get_valid_path(db(r).filepath, 'file', ... + db(r).filename); + temp_path = fullfile(valid_path, 'tempfiles'); + if ~isdir(temp_path) + mkdir(temp_path) + end + % ADD CHANGE - ensure that such tempfile is not present + EEG.filename = [num2str(randi(9999, 1)), '.set']; + EEG.filepath = temp_path; + pop_saveset(EEG, 'filepath', temp_path, ... + 'filename', EEG.filename); + + % add temp info to EEG.etc.temp + EEG.etc.temp.filter = db(r).filter; + EEG.etc.temp.epoch = db(r).epoch; + EEG.etc.temp.filepath = temp_path; + EEG.etc.temp.filename = EEG.filename; + + if femp(db(r).datainfo, 'cleanline') + EEG.etc.temp.cleanline = db(r).datainfo.cleanline; + else + EEG.etc.temp.cleanline = []; + end + if ~femp(orig_db(r).datainfo, 'tempfiles') + orig_db(r).datainfo.tempfiles = EEG.etc.temp; + else + flds = fields(orig_db(r).datainfo.tempfiles); + EEG.etc.temp = orderfields(EEG.etc.temp, flds); + orig_db(r).datainfo.tempfiles(end+1) = EEG.etc.temp; + end + end +end %% adding ICA info add_comprej = false; @@ -447,94 +488,10 @@ end %% epoching -if femp(db(r), 'epoch') - if femp(db(r).epoch, 'locked') && ~db(r).epoch.locked - - % ============== - % onesec options - options.filename = EEG; - options.fill = true; - - flds = {'filter', 'winlen', 'distance',... - 'leave', 'eventname'}; - - % checking fields for onesecepoch - for f = 1:length(flds) - if femp(db(r).epoch, flds{f}) - options.(flds{f}) = db(r).epoch.(flds{f}); - end - end - - % if prerej is present then no need to use distance - if femp(db(r).reject, 'pre') - options.distance = []; - end - - % =================== - % call to onesecepoch - EEG = onesecepoch(options); - clear options - - elseif ~isempty(db(r).epoch.events) && ... - ~isempty(db(r).epoch.limits) - - % ================== - % classical epoching - epoc = db(r).epoch.events; - - % checking for code generator of epochs - % ADD - function handle for epoching? - % or maybe not necessary - there is an - % option for user-defined function - if ischar(epoc) && length(epoc) > cidlen && ... - strcmp(epoc(1:cidlen), code_id) - - epoc = eval(epoc(cidlen+1:end)); - end - - EEG = db_fastepoch(EEG, epoc, db(r).epoch.limits); - - % ======================= - % checking for segmenting - if segment && ~nosegment - EEG = segmentEEG(EEG, db(r).epoch.segment); - end - end +if haspostfilter + EEG = db_epoch(EEG, db, r, min(segment, ~nosegment)); end -% CHANGE -% [ ] if we segment then orig_numep should be adjusted too -% [ ] instead of numep this all can be done in a smarter way -% 1) generally - onesec can add numep too -% 2) numep can be inferred from length of rejections -% in db(r)! -% 3) ... -% [ ] in the current version only onesecepoching is checked -% for while in future releases we want to include also -% conditional epoch extraction (only correct etc.) which -% is another prerej -% -% -% ====================== -% adding orig_numep info -% -% (this is later used when rejections are added -% using a recovered file that has some of the -% rejections already removed) -% -% if epoched signal add orig_numep -EEG.etc.orig_numep = size(EEG.data, 3); - -% if onesecepoch was perfromed add onesec info -if femp(db(r).epoch, 'locked') && ~db(r).epoch.locked - - % either prerej is nonempty % or what? - if femp(db(r).reject, 'pre') - % there is some info about prerej, - % we correct orig_numep - EEG.etc.orig_numep = EEG.etc.orig_numep - length(db(r).reject.pre); - end -end %% removing bad epochs if ~prerej && ~isempty(db(r).reject.all) diff --git a/deps/onesecepoch.m b/deps/onesecepoch.m index 42b6dd7..1e465b3 100644 --- a/deps/onesecepoch.m +++ b/deps/onesecepoch.m @@ -1,4 +1,4 @@ -function EEG = onesecepoch(options) +function EEG = onesecepoch(EEG, options) % onsecepoch - funkcja dzieli podany plik EEG na epoki % o podanej długości (w sekundach, domyślnie 1s) @@ -7,19 +7,17 @@ % więcej opcjonalnych parametrów niżej w 'PEŁNE OPCJE' % % do pookienkowania sygnału w najprostszej wersji wystarczy: -% options.filename = EEG; % wrzucamy do pola filename strukturę EEG -% EEG = onesecepoch(options); % dostajemy pookienkowane EEG +% EEG = onesecepoch(EEG); % dostajemy pookienkowane EEG % % !! jeżeli korzystamy z filtrowania: wymagana !! % !! jest wersja eeglaba 12.0100 lub nowsza !! % -% PEŁNE OPCJE: -% funkcja przyjmuje jako input strukurę o nast. polach: -% filename - nazwa pliku (albo struktura EEG) -% filepath - ścieżka dostępu do pliku (tylko jeżeli 'filename' -% jest nazwą pliku, a nie strukturą EEG) -% filter - opcjonalnie: wektor [dolny górny] próg filtrowania -% np. options.filter = [1 0]; (filtruje tylko górnoprzpustowo) +% INPUT +% ----- +% EEG - eeglab EEG structure +% +% options structure +% ----------------- % winlen - opcjonalnie: dlugosc okna do epokowania % leave - opcjonalnie: [true/false] - czy zostawiać w danych % pookienkowanych oryginalne eventy, czy też je wywa- @@ -40,21 +38,11 @@ % fill - opcjonalne: jeżeli wartość to prawda logiczna - dodaje do % EEG pola oznaczające opcje użyte do okienkowania % -% ===dodatkowa opcja=== -% zamiast nazwy pliku można w miejsce 'filename' wrzucić samą -% strkuturę EEG - wtedy wczytywanie pliku zostanie pominięte -% nie trzeba wtedy też dodawać do struktury z opcjami pola -% 'filepath' -% % ==założenie== % muszą być już wczytane ścieżki do eeglaba % funkcja nie uruchamia sama eeglaba -% wczytuje pojedynczo pliki aby można było ją -% łatwo dodać do dowolnej rutyny w ramach -% pipeline_coordinate (patrz: folder coordination -% w dropboxowym 'EEGlab scripts') -% -% coded by M. Magunski, march 2013 + +% coded by M. Magnuski, march 2013 % :) @@ -63,11 +51,6 @@ winlen = 1; leave_ev = true; fill = false; %% checks for optional parameters -% opcjonalnie pomijamy wczytywanie -if isfield(options, 'filename') && isstruct(options.filename) && ... - isfield(options.filename, 'data') && isfield(options.filename, 'srate') - load_set = false; -end % sprawdzamy czy podana została długość okna: if isfield(options, 'winlen') && ~isempty(options.winlen) @@ -86,7 +69,7 @@ end % checking fill -if isfield(options, 'fill') && ~isempty(options.fill) +if isfield(options, 'fill') && ~isempty(options.fill) fill = options.fill; end @@ -98,22 +81,6 @@ %% ~~WELCOME TO THE CODE~~ -%% loading (+filtering) -% getting EEG structure -if load_set - % wczytujemy plik - EEG = pop_loadset('filepath', options.filepath, 'filename',... - options.filename); -else - EEG = options.filename; - options.filename = []; -end - -% optional filtering -if isfield(options, 'filter') && ~isempty(options.filter) - EEG = pop_eegfiltnew(EEG, options.filter(1), options.filter(2)); -end - %% event checks % opcja zachowania oryginalnych eventów % (aby je widzieć gdy ręcznie odrzuca się okienka @@ -161,7 +128,7 @@ end -% czy checkset potrzebny? +% CHECK CHANGE TODO czy checkset potrzebny? EEG = eeg_checkset(EEG); % epokujemy @@ -355,9 +322,6 @@ end if fill - if isfield(options, 'filter') - EEG.onesecepoch.filter = options.filter; - end EEG.onesecepoch.initwins = ile_ev; EEG.onesecepoch.winlen = winlen; diff --git a/gui/compsel/linkfun_compexplore.m b/gui/compsel/linkfun_compexplore.m index 5f4e8e1..66fb640 100644 --- a/gui/compsel/linkfun_compexplore.m +++ b/gui/compsel/linkfun_compexplore.m @@ -42,7 +42,7 @@ function linkfun_compexplore(hObj) drawnow; % recover - h.EEG = recoverEEG(h.db, h.r, 'local', 'ICAnorem'); + [h.EEG, h.db] = recoverEEG(h.db, h.r, 'local', 'tempsave', 'ICAnorem'); h.rEEG = h.r; % update winrej handles diff --git a/gui/db_gui.m b/gui/db_gui.m index 82ca179..3fdb09b 100644 --- a/gui/db_gui.m +++ b/gui/db_gui.m @@ -198,64 +198,7 @@ function dataplot_butt_Callback(hObject, eventdata, handles) %#ok<*DEFNU,*INUSD> currf = handles.db(handles.r).versions.current; handles.db = db_updateversion(handles.db, handles.r, currf); - % CHANGE - this is a mess - % - whether r is recovered should be checked in a sepatate - % function (the same with recover if not present) - % - recovopts should be reworked - % - comparing EEG and current r/version should be - % smarter - - % first - recover data if not present - if isempty(handles.EEG) || handles.r ~= handles.rEEG || ... - ~db_recov_compare(handles.EEG.etc.recov, handles.db(handles.r)) ... - || ~isequal(handles.recovopts, handles.last_recovered_opts) - - % save recovery options: - handles.last_recovered_opts = handles.recovopts; - - % TXT display - set(handles.addit_text, 'String', 'Recovering EEG...'); - drawnow; - - % RECOVER EEG data - handles.EEG = recoverEEG(handles.db, handles.r, 'local', handles.recovopts{:}); - handles.rEEG = handles.r; - rEEG = handles.rEEG; - - % update prerej field - f = db_checkfields(handles.EEG, 1,... - {'onesecepoch'}, 'subfields', true); - if f.fsubf(1) - isprerej = find(strcmp('prerej', f.subfields{1})); - end - - % CHECK - in case of prerej, postrej division - % the following step is important because - % it allows for some prerej-postrej-removed - % calculations. However, it should not restric - % usage of databases that do not use onesecepoch - % Checking recov should be done only - % for databases using onesecepoch - % - % set this file as elligible to some - % operations (apply rejections, multisel, etc.) - if f.fsubf(1) && ~isempty(isprerej) ... - && f.subfnonempt{1}(isprerej) - handles.db(handles.r).reject.pre = handles... - .EEG.onesecepoch.prerej; - handles.recov(handles.r) = true; - end - clear f isprerej - - % Update handles structure - guidata(hObject, handles); - - % file recovered - set(handles.addit_text, 'String', 'EEG recovered'); - - % refresh gui (CHECK - do we need to?) - db_gui_refresh(handles); - end + handles = db_gui_recover(handles); % disable plotting set(hObject, 'Enable', 'off'); @@ -409,6 +352,8 @@ function col_butt_Callback(hObject, eventdata, handles) % --- Executes on button press in next_butt. function next_butt_Callback(hObject, eventdata, handles) +handles = guidata(hObject); + if handles.r < length(handles.db) handles.r = handles.r + 1; @@ -423,6 +368,8 @@ function next_butt_Callback(hObject, eventdata, handles) % --- Executes on button press in prev_butt. function prev_butt_Callback(hObject, eventdata, handles) +handles = guidata(hObject); + if handles.r > 1 handles.r = handles.r - 1; @@ -688,6 +635,7 @@ function runICA_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) % check selection +handles = guidata(hObject); if isempty(handles.selected) sel = handles.r; else @@ -779,7 +727,6 @@ function runICA_Callback(hObject, eventdata, handles) guidata(hObject, handles); end end - end end % update text display @@ -791,6 +738,7 @@ function runICA_Callback(hObject, eventdata, handles) % refresh GUI db_gui_refresh(handles); +end % -------------------------------------------------------------------- function vers_Callback(hObject, eventdata, handles) diff --git a/gui/db_gui_recover.m b/gui/db_gui_recover.m new file mode 100644 index 0000000..ada1b14 --- /dev/null +++ b/gui/db_gui_recover.m @@ -0,0 +1,61 @@ +function h = db_gui_recover(h) + +% CHANGE - this is a mess +% - recovopts should be reworked +% - comparing EEG and current r/version should be +% smarter + +% first - recover data if not present +if isempty(h.EEG) || h.r ~= h.rEEG || ... + ~db_recov_compare(h.EEG.etc.recov, h.db(h.r)) ... + || ~isequal(h.recovopts, h.last_recovered_opts) + + % save recovery options: + h.last_recovered_opts = h.recovopts; + + % TXT display + set(h.addit_text, 'String', 'Recovering EEG...'); + drawnow; + + % RECOVER EEG data + [h.EEG, h.db] = recoverEEG(h.db, h.r, ... + 'local', 'tempsave', h.recovopts{:}); + h.rEEG = h.r; + rEEG = h.rEEG; + + % update prerej field + f = db_checkfields(h.EEG, 1,... + {'onesecepoch'}, 'subfields', true); + if f.fsubf(1) + isprerej = find(strcmp('pre', f.subfields{1})); + end + + % CHECK - in case of prerej, postrej division + % the following step is important because + % it allows for some prerej-postrej-removed + % calculations. However, it should not restric + % usage of databases that do not use onesecepoch + % Checking recov should be done only + % for databases using onesecepoch + % + % set this file as elligible to some + % operations (apply rejections, multisel, etc.) + if f.fsubf(1) && ~isempty(isprerej) ... + && f.subfnonempt{1}(isprerej) + h.db(h.r).reject.pre = h... + .EEG.onesecepoch.prerej; + % ADD a hack to update h.EEG.etc.recov + % h.EEG.etc.recov = h.db(h.r); + h.recov(h.r) = true; + end + clear f isprerej + + % Update handles structure + guidata(h.figure1, h); + + % file recovered + set(h.addit_text, 'String', 'EEG recovered'); + + % refresh gui (CHECK - do we need to?) + db_gui_refresh(h); +end \ No newline at end of file