|
a |
|
b/functions/adminfunc/eeg_checkset.m |
|
|
1 |
% EEG_CHECKSET - check the consistency of the fields of an EEG dataset |
|
|
2 |
% Also: See EEG dataset structure field descriptions below. |
|
|
3 |
% |
|
|
4 |
% Usage: >> [EEGOUT,changes] = eeg_checkset(EEG); % perform all checks |
|
|
5 |
% except 'makeur' |
|
|
6 |
% >> [EEGOUT,changes] = eeg_checkset(EEG, 'keyword'); % perform 'keyword' check(s) |
|
|
7 |
% |
|
|
8 |
% Inputs: |
|
|
9 |
% EEG - EEGLAB dataset structure or (ALLEEG) array of EEG structures |
|
|
10 |
% |
|
|
11 |
% Optional keywords: |
|
|
12 |
% 'icaconsist' - if EEG contains several datasets, check whether they have |
|
|
13 |
% the same ICA decomposition |
|
|
14 |
% 'epochconsist' - if EEG contains several datasets, check whether they have |
|
|
15 |
% identical epoch lengths and time limits. |
|
|
16 |
% 'chanconsist' - if EEG contains several datasets, check whether they have |
|
|
17 |
% the same number of channels and channel labels. |
|
|
18 |
% 'data' - check whether EEG contains data (EEG.data) |
|
|
19 |
% 'loaddata' - load data array (if necessary) |
|
|
20 |
% 'savedata' - save data array (if necessary - see EEG.saved below) |
|
|
21 |
% 'contdata' - check whether EEG contains continuous data |
|
|
22 |
% 'epoch' - check whether EEG contains epoched or continuous data |
|
|
23 |
% 'ica' - check whether EEG contains an ICA decomposition |
|
|
24 |
% 'besa' - check whether EEG contains component dipole locations |
|
|
25 |
% 'event' - check whether EEG contains an event array |
|
|
26 |
% 'makeur' - remake the EEG.urevent structure |
|
|
27 |
% 'checkur' - check whether the EEG.urevent structure is consistent |
|
|
28 |
% with the EEG.event structure |
|
|
29 |
% 'chanlocsize' - check the EEG.chanlocs structure length; show warning if |
|
|
30 |
% necessary. |
|
|
31 |
% 'chanlocs_homogeneous' - check whether EEG contains consistent channel |
|
|
32 |
% information; if not, correct it.This option |
|
|
33 |
% calls eeg_checkchanlocs. |
|
|
34 |
% 'eventconsistency' - check whether EEG.event information are consistent; |
|
|
35 |
% rebuild event* subfields of the 'EEG.epoch' structure |
|
|
36 |
% (can be time consuming). |
|
|
37 |
% Outputs: |
|
|
38 |
% EEGOUT - output EEGLAB dataset or dataset array |
|
|
39 |
% changes - change code: 'no' = no changes; 'yes' = the EEG |
|
|
40 |
% structure was modified |
|
|
41 |
% |
|
|
42 |
% =========================================================== |
|
|
43 |
% The structure of an EEG dataset under EEGLAB (as of v5.03): |
|
|
44 |
% |
|
|
45 |
% Basic dataset information: |
|
|
46 |
% EEG.setname - descriptive name|title for the dataset |
|
|
47 |
% EEG.filename - filename of the dataset file on disk |
|
|
48 |
% EEG.filepath - filepath (directory/folder) of the dataset file(s) |
|
|
49 |
% EEG.trials - number of epochs (or trials) in the dataset. |
|
|
50 |
% If data are continuous, this number is 1. |
|
|
51 |
% EEG.pnts - number of time points (or data frames) per trial (epoch). |
|
|
52 |
% If data are continuous (trials=1), the total number |
|
|
53 |
% of time points (frames) in the dataset |
|
|
54 |
% EEG.nbchan - number of channels |
|
|
55 |
% EEG.srate - data sampling rate (in Hz) |
|
|
56 |
% EEG.xmin - epoch start latency|time (in sec. relative to the |
|
|
57 |
% time-locking event at time 0) |
|
|
58 |
% EEG.xmax - epoch end latency|time (in seconds) |
|
|
59 |
% EEG.times - vector of latencies|times in milliseconds (one per time point) |
|
|
60 |
% EEG.ref - ['common'|'averef'|integer] reference channel type or number |
|
|
61 |
% EEG.history - cell array of ascii pop-window commands that created |
|
|
62 |
% or modified the dataset |
|
|
63 |
% EEG.comments - comments about the nature of the dataset (edit this via |
|
|
64 |
% menu selection Edit > About this dataset) |
|
|
65 |
% EEG.etc - miscellaneous (technical or temporary) dataset information |
|
|
66 |
% EEG.saved - ['yes'|'no'] 'no' flags need to save dataset changes before exit |
|
|
67 |
% |
|
|
68 |
% The data: |
|
|
69 |
% EEG.data - two-dimensional continuous data array (chans, frames) |
|
|
70 |
% ELSE, three-dim. epoched data array (chans, frames, epochs) |
|
|
71 |
% |
|
|
72 |
% The channel locations sub-structures: |
|
|
73 |
% EEG.chanlocs - structure array containing names and locations |
|
|
74 |
% of the channels on the scalp |
|
|
75 |
% EEG.urchanlocs - original (ur) dataset chanlocs structure containing |
|
|
76 |
% all channels originally collected with these data |
|
|
77 |
% (before channel rejection) |
|
|
78 |
% EEG.chaninfo - structure containing additional channel info |
|
|
79 |
% EEG.ref - type of channel reference ('common'|'averef'|+/-int] |
|
|
80 |
% EEG.splinefile - location of the spline file used by HEADPLOT to plot |
|
|
81 |
% data scalp maps in 3-D |
|
|
82 |
% |
|
|
83 |
% The event and epoch sub-structures: |
|
|
84 |
% EEG.event - event structure containing times and nature of experimental |
|
|
85 |
% events recorded as occurring at data time points |
|
|
86 |
% EEG.urevent - original (ur) event structure containing all experimental |
|
|
87 |
% events recorded as occurring at the original data time points |
|
|
88 |
% (before data rejection) |
|
|
89 |
% EEG.epoch - epoch event information and epoch-associated data structure array (one per epoch) |
|
|
90 |
% EEG.eventdescription - cell array of strings describing event fields. |
|
|
91 |
% EEG.epochdescription - cell array of strings describing epoch fields. |
|
|
92 |
% --> See the http://sccn.ucsd.edu/eeglab/maintut/eeglabscript.html for details |
|
|
93 |
% |
|
|
94 |
% ICA (or other linear) data components: |
|
|
95 |
% EEG.icasphere - sphering array returned by linear (ICA) decomposition |
|
|
96 |
% EEG.icaweights - unmixing weights array returned by linear (ICA) decomposition |
|
|
97 |
% EEG.icawinv - inverse (ICA) weight matrix. Columns gives the projected |
|
|
98 |
% topographies of the components to the electrodes. |
|
|
99 |
% EEG.icaact - ICA activations matrix (components, frames, epochs) |
|
|
100 |
% Note: [] here means that 'compute_ica' option has been set |
|
|
101 |
% to 0 under 'File > Memory options' In this case, |
|
|
102 |
% component activations are computed only as needed. |
|
|
103 |
% EEG.icasplinefile - location of the spline file used by HEADPLOT to plot |
|
|
104 |
% component scalp maps in 3-D |
|
|
105 |
% EEG.chaninfo.icachansind - indices of channels used in the ICA decomposition |
|
|
106 |
% EEG.dipfit - array of structures containing component map dipole models |
|
|
107 |
% |
|
|
108 |
% Variables indicating membership of the dataset in a studyset: |
|
|
109 |
% EEG.subject - studyset subject code |
|
|
110 |
% EEG.group - studyset group code |
|
|
111 |
% EEG.condition - studyset experimental condition code |
|
|
112 |
% EEG.run - studyset run number |
|
|
113 |
% EEG.session - studyset session number |
|
|
114 |
% |
|
|
115 |
% Variables used for manual and semi-automatic data rejection: |
|
|
116 |
% EEG.specdata - data spectrum for every single trial |
|
|
117 |
% EEG.specica - data spectrum for every single trial |
|
|
118 |
% EEG.stats - statistics used for data rejection |
|
|
119 |
% EEG.stats.kurtc - component kurtosis values |
|
|
120 |
% EEG.stats.kurtg - global kurtosis of components |
|
|
121 |
% EEG.stats.kurta - kurtosis of accepted epochs |
|
|
122 |
% EEG.stats.kurtr - kurtosis of rejected epochs |
|
|
123 |
% EEG.stats.kurtd - kurtosis of spatial distribution |
|
|
124 |
% EEG.reject - statistics used for data rejection |
|
|
125 |
% EEG.reject.entropy - entropy of epochs |
|
|
126 |
% EEG.reject.entropyc - entropy of components |
|
|
127 |
% EEG.reject.threshold - rejection thresholds |
|
|
128 |
% EEG.reject.icareject - epochs rejected by ICA criteria |
|
|
129 |
% EEG.reject.gcompreject - rejected ICA components |
|
|
130 |
% EEG.reject.sigreject - epochs rejected by single-channel criteria |
|
|
131 |
% EEG.reject.elecreject - epochs rejected by raw data criteria |
|
|
132 |
% |
|
|
133 |
% Author: Arnaud Delorme, CNL / Salk Institute, 2001 |
|
|
134 |
% |
|
|
135 |
% See also: EEGLAB |
|
|
136 |
|
|
|
137 |
% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu |
|
|
138 |
% |
|
|
139 |
% This file is part of EEGLAB, see http://www.eeglab.org |
|
|
140 |
% for the documentation and details. |
|
|
141 |
% |
|
|
142 |
% Redistribution and use in source and binary forms, with or without |
|
|
143 |
% modification, are permitted provided that the following conditions are met: |
|
|
144 |
% |
|
|
145 |
% 1. Redistributions of source code must retain the above copyright notice, |
|
|
146 |
% this list of conditions and the following disclaimer. |
|
|
147 |
% |
|
|
148 |
% 2. Redistributions in binary form must reproduce the above copyright notice, |
|
|
149 |
% this list of conditions and the following disclaimer in the documentation |
|
|
150 |
% and/or other materials provided with the distribution. |
|
|
151 |
% |
|
|
152 |
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
|
153 |
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
|
154 |
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
|
155 |
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
|
156 |
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
|
157 |
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
|
158 |
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
|
159 |
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
|
160 |
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
|
161 |
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
|
|
162 |
% THE POSSIBILITY OF SUCH DAMAGE. |
|
|
163 |
|
|
|
164 |
% 01-25-02 reformated help & license -ad |
|
|
165 |
% 01-26-02 chandeg events and trial condition format -ad |
|
|
166 |
% 01-27-02 debug when trial condition is empty -ad |
|
|
167 |
% 02-15-02 remove icawinv recompute for pop_epoch -ad & ja |
|
|
168 |
% 02-16-02 remove last modification and test icawinv separately -ad |
|
|
169 |
% 02-16-02 empty event and epoch check -ad |
|
|
170 |
% 03-07-02 add the eeglab options -ad |
|
|
171 |
% 03-07-02 corrected typos and rate/point calculation -ad & ja |
|
|
172 |
% 03-15-02 add channel location reading & checking -ad |
|
|
173 |
% 03-15-02 add checking of ICA and epochs with pop_up windows -ad |
|
|
174 |
% 03-27-02 recorrected rate/point calculation -ad & sm |
|
|
175 |
|
|
|
176 |
function [EEGFINAL, res] = eeg_checkset( EEG, varargin ) |
|
|
177 |
msg = ''; |
|
|
178 |
res = 'no'; |
|
|
179 |
com = sprintf('EEG = eeg_checkset( EEG );'); |
|
|
180 |
|
|
|
181 |
if nargin < 1 |
|
|
182 |
help eeg_checkset; |
|
|
183 |
return; |
|
|
184 |
end |
|
|
185 |
|
|
|
186 |
EEGFINAL = EEG; |
|
|
187 |
warning backtrace off |
|
|
188 |
if isempty(EEG), return; end |
|
|
189 |
if ~isfield(EEG, 'data'), return; end |
|
|
190 |
|
|
|
191 |
% checking multiple datasets |
|
|
192 |
% -------------------------- |
|
|
193 |
if length(EEG) > 1 |
|
|
194 |
|
|
|
195 |
if length(EEG) > 5000 |
|
|
196 |
disp('Too many datasets, aborting check') |
|
|
197 |
return; |
|
|
198 |
end |
|
|
199 |
|
|
|
200 |
if nargin > 1 |
|
|
201 |
switch varargin{1} |
|
|
202 |
case 'epochconsist' % test epoch consistency |
|
|
203 |
% ---------------------- |
|
|
204 |
res = 'no'; |
|
|
205 |
datasettype = unique_bc( [ EEG.trials ] ); |
|
|
206 |
if datasettype(1) == 1 && length(datasettype) == 1, return; % continuous data |
|
|
207 |
elseif datasettype(1) == 1, return; % continuous and epoch data |
|
|
208 |
end |
|
|
209 |
|
|
|
210 |
allpnts = unique_bc( [ EEG.pnts ] ); |
|
|
211 |
allxmin = unique_bc( [ EEG.xmin ] ); |
|
|
212 |
if length(allpnts) == 1 && length(allxmin) == 1, res = 'yes'; end |
|
|
213 |
return; |
|
|
214 |
|
|
|
215 |
case 'chanconsist' % test channel number and name consistency |
|
|
216 |
% ---------------------------------------- |
|
|
217 |
res = 'yes'; |
|
|
218 |
chanlen = unique_bc( [ EEG.nbchan ] ); |
|
|
219 |
anyempty = unique_bc( cellfun( 'isempty', { EEG.chanlocs }) ); |
|
|
220 |
if length(chanlen) == 1 && all(anyempty == 0) |
|
|
221 |
tmpchanlocs = EEG(1).chanlocs; |
|
|
222 |
channame1 = { tmpchanlocs.labels }; |
|
|
223 |
for i = 2:length(EEG) |
|
|
224 |
tmpchanlocs = EEG(i).chanlocs; |
|
|
225 |
channame2 = { tmpchanlocs.labels }; |
|
|
226 |
if length(intersect(channame1, channame2)) ~= length(channame1), res = 'no'; end |
|
|
227 |
end |
|
|
228 |
else res = 'no'; |
|
|
229 |
end |
|
|
230 |
|
|
|
231 |
% Field 'datachan in 'urchanlocs' is removed, if exist |
|
|
232 |
if isfield(EEG, 'urchanlocs') && ~all(cellfun(@isempty,{EEG.urchanlocs})) && isfield([EEG.urchanlocs], 'datachan') |
|
|
233 |
[EEG.urchanlocs] = deal(rmfield([EEG.urchanlocs], 'datachan')); |
|
|
234 |
end |
|
|
235 |
return; |
|
|
236 |
|
|
|
237 |
case 'icaconsist' % test ICA decomposition consistency |
|
|
238 |
% ---------------------------------- |
|
|
239 |
res = 'yes'; |
|
|
240 |
anyempty = unique_bc( cellfun( 'isempty', { EEG.icaweights }) ); |
|
|
241 |
if length(anyempty) == 1 && anyempty(1) == 0 |
|
|
242 |
ica1 = EEG(1).icawinv; |
|
|
243 |
for i = 2:length(EEG) |
|
|
244 |
if ~isequal(EEG(1).icawinv, EEG(i).icawinv) |
|
|
245 |
res = 'no'; |
|
|
246 |
end |
|
|
247 |
end |
|
|
248 |
else res = 'no'; |
|
|
249 |
end |
|
|
250 |
return; |
|
|
251 |
|
|
|
252 |
end |
|
|
253 |
end |
|
|
254 |
|
|
|
255 |
end |
|
|
256 |
|
|
|
257 |
% reading these option take time because |
|
|
258 |
% of disk access |
|
|
259 |
% -------------- |
|
|
260 |
eeglab_options; |
|
|
261 |
|
|
|
262 |
% rename fields for backward compatibility in future versions |
|
|
263 |
if isfield(EEG, 'nchans') |
|
|
264 |
for iEEG = 1:length(EEG) |
|
|
265 |
EEG(iEEG).nbchan = EEG.nchans; |
|
|
266 |
end |
|
|
267 |
end |
|
|
268 |
if isfield(EEG, 'chanlocs') |
|
|
269 |
for iEEG = 1:length(EEG) |
|
|
270 |
if isfield(EEG(iEEG).chanlocs, 'label') |
|
|
271 |
for iChan = 1:length(EEG(iEEG).chanlocs) |
|
|
272 |
EEG(iEEG).chanlocs(iChan).labels = EEG(iEEG).chanlocs(iChan).label; |
|
|
273 |
end |
|
|
274 |
EEG(iEEG).chanlocs = rmfield(EEG(iEEG).chanlocs, 'label'); |
|
|
275 |
end |
|
|
276 |
end |
|
|
277 |
end |
|
|
278 |
|
|
|
279 |
% standard checking |
|
|
280 |
% ----------------- |
|
|
281 |
ALLEEG = EEG; |
|
|
282 |
for inddataset = 1:length(ALLEEG) |
|
|
283 |
|
|
|
284 |
EEG = ALLEEG(inddataset); |
|
|
285 |
|
|
|
286 |
% additional checks |
|
|
287 |
% ----------------- |
|
|
288 |
res = -1; % error code |
|
|
289 |
if ~isempty( varargin) |
|
|
290 |
for index = 1:length( varargin ) |
|
|
291 |
switch varargin{ index } |
|
|
292 |
case 'data',; % already done at the top |
|
|
293 |
case 'contdata', |
|
|
294 |
if EEG.trials > 1 |
|
|
295 |
errordlg2(strvcat('Error: function only works on continuous data'), 'Error'); |
|
|
296 |
return; |
|
|
297 |
end |
|
|
298 |
case 'ica', |
|
|
299 |
if isempty(EEG.icaweights) |
|
|
300 |
errordlg2(strvcat('Error: no ICA decomposition. use menu "Tools > Run ICA" first.'), 'Error'); |
|
|
301 |
return; |
|
|
302 |
end |
|
|
303 |
case 'epoch', |
|
|
304 |
if EEG.trials == 1 |
|
|
305 |
errordlg2(strvcat('Extract epochs before running that function', 'Use Tools > Extract epochs'), 'Error'); |
|
|
306 |
return |
|
|
307 |
end |
|
|
308 |
case 'besa', |
|
|
309 |
if ~isfield(EEG, 'sources') |
|
|
310 |
errordlg2(strvcat('No dipole information', '1) Export component maps: Tools > Localize ... BESA > Export ...' ... |
|
|
311 |
, '2) Run BESA to localize the equivalent dipoles', ... |
|
|
312 |
'3) Import the BESA dipoles: Tools > Localize ... BESA > Import ...'), 'Error'); |
|
|
313 |
return |
|
|
314 |
end |
|
|
315 |
case 'event', |
|
|
316 |
if isempty(EEG.event) |
|
|
317 |
errordlg2(strvcat('Requires events. You need to add events first.', ... |
|
|
318 |
'Use "File > Import event info" or "File > Import epoch info"', ... |
|
|
319 |
'Install plugin VidEd to manually add events as you scroll the data.' ), 'Error'); |
|
|
320 |
return; |
|
|
321 |
end |
|
|
322 |
case 'chanloc', |
|
|
323 |
tmplocs = EEG.chanlocs; |
|
|
324 |
if isempty(tmplocs) || ~isfield(tmplocs, 'theta') || all(cellfun('isempty', { tmplocs.theta })) |
|
|
325 |
errordlg2( strvcat('This functionality requires channel location information.', ... |
|
|
326 |
'Enter the channel file name via "Edit > Edit dataset info".', ... |
|
|
327 |
'For channel file format, see ''>> help readlocs'' from the command line.'), 'Error'); |
|
|
328 |
return; |
|
|
329 |
end |
|
|
330 |
case 'chanlocs_homogeneous', |
|
|
331 |
tmplocs = EEG.chanlocs; |
|
|
332 |
if isempty(tmplocs) || ~isfield(tmplocs, 'theta') || all(cellfun('isempty', { tmplocs.theta })) |
|
|
333 |
errordlg2( strvcat('This functionality requires channel location information.', ... |
|
|
334 |
'Enter the channel file name via "Edit > Edit dataset info".', ... |
|
|
335 |
'For channel file format, see ''>> help readlocs'' from the command line.'), 'Error'); |
|
|
336 |
return; |
|
|
337 |
end |
|
|
338 |
if ~isfield(EEG.chanlocs, 'X') || isempty(EEG.chanlocs(1).X) |
|
|
339 |
EEG = eeg_checkchanlocs(EEG); |
|
|
340 |
% EEG.chanlocs = convertlocs(EEG.chanlocs, 'topo2all'); |
|
|
341 |
res = ['EEG = eeg_checkset(EEG, ''chanlocs_homogeneous''); ' ]; |
|
|
342 |
end |
|
|
343 |
case 'chanlocsize', |
|
|
344 |
if ~isempty(EEG.chanlocs) |
|
|
345 |
if length(EEG.chanlocs) > EEG.nbchan |
|
|
346 |
questdlg2(strvcat('Warning: there is one more electrode location than', ... |
|
|
347 |
'data channels. EEGLAB will consider the last electrode to be the', ... |
|
|
348 |
'common reference channel. If this is not the case, remove the', ... |
|
|
349 |
'extra channel'), 'Warning', 'Ok', 'Ok'); |
|
|
350 |
end |
|
|
351 |
end |
|
|
352 |
case 'makeur', |
|
|
353 |
if ~isempty(EEG.event) |
|
|
354 |
if isfield(EEG.event, 'urevent'), |
|
|
355 |
EEG.event = rmfield(EEG.event, 'urevent'); |
|
|
356 |
disp('eeg_checkset note: re-creating the original event table (EEG.urevent)'); |
|
|
357 |
else |
|
|
358 |
disp('eeg_checkset note: creating the original event table (EEG.urevent)'); |
|
|
359 |
end |
|
|
360 |
EEG.urevent = EEG.event; |
|
|
361 |
for index = 1:length(EEG.event) |
|
|
362 |
EEG.event(index).urevent = index; |
|
|
363 |
end |
|
|
364 |
end |
|
|
365 |
case 'checkur', |
|
|
366 |
if ~isempty(EEG.event) |
|
|
367 |
if isfield(EEG.event, 'urevent') && ~isempty(EEG.urevent) |
|
|
368 |
urlatencies = [ EEG.urevent.latency ]; |
|
|
369 |
[newlat tmpind] = sort(urlatencies); |
|
|
370 |
if ~isequal(newlat, urlatencies) |
|
|
371 |
EEG.urevent = EEG.urevent(tmpind); |
|
|
372 |
[tmp tmpind2] = sort(tmpind); |
|
|
373 |
for index = 1:length(EEG.event) |
|
|
374 |
EEG.event(index).urevent = tmpind2(EEG.event(index).urevent); |
|
|
375 |
end |
|
|
376 |
end |
|
|
377 |
end |
|
|
378 |
end |
|
|
379 |
case 'eventconsistency', |
|
|
380 |
%[EEG res] = eeg_checkset(EEG); |
|
|
381 |
if ~isempty(EEG.event) |
|
|
382 |
|
|
|
383 |
% check events (slow) |
|
|
384 |
% ------------ |
|
|
385 |
if isfield(EEG.event, 'type') |
|
|
386 |
eventInds = arrayfun(@(x)isempty(x.type), EEG.event); |
|
|
387 |
if any(eventInds) |
|
|
388 |
eventInds = find(eventInds); |
|
|
389 |
eventInds = eventInds(:)'; % make row vector |
|
|
390 |
if all(arrayfun(@(x)isnumeric(x.type), EEG.event)) |
|
|
391 |
for ind = eventInds, EEG.event(ind).type = NaN; end |
|
|
392 |
else for ind = eventInds, EEG.event(ind).type = 'empty'; end |
|
|
393 |
end |
|
|
394 |
end |
|
|
395 |
if ~all(arrayfun(@(x)ischar(x.type), EEG.event)) && ~all(arrayfun(@(x)isnumeric(x.type), EEG.event)) |
|
|
396 |
disp('Warning: converting all event types to strings'); |
|
|
397 |
for ind = 1:length(EEG.event) |
|
|
398 |
EEG.event(ind).type = num2str(EEG.event(ind).type); |
|
|
399 |
end |
|
|
400 |
EEG = eeg_checkset(EEG, 'eventconsistency'); |
|
|
401 |
end |
|
|
402 |
|
|
|
403 |
end |
|
|
404 |
|
|
|
405 |
% Removing events with NaN latency |
|
|
406 |
% -------------------------------- |
|
|
407 |
if isfield(EEG.event, 'latency') |
|
|
408 |
nanindex = find(isnan([ EEG.event.latency ])); |
|
|
409 |
if ~isempty(nanindex) |
|
|
410 |
EEG.event(nanindex) = []; |
|
|
411 |
trialtext = ''; |
|
|
412 |
for inan = 1:length(nanindex) |
|
|
413 |
trialstext = [trialtext ' ' num2str(nanindex(inan))]; |
|
|
414 |
end |
|
|
415 |
disp(sprintf(['eeg_checkset: Event(s) with NaN latency were deleted \nDeleted event index(es):[' trialstext ']'])); |
|
|
416 |
end |
|
|
417 |
end |
|
|
418 |
|
|
|
419 |
% remove the events which latency are out of boundary |
|
|
420 |
% --------------------------------------------------- |
|
|
421 |
if isempty(EEG.event), return; end |
|
|
422 |
if isfield(EEG.event, 'latency') |
|
|
423 |
if isfield(EEG.event, 'type') |
|
|
424 |
if eeg_isboundary(EEG.event(1)) && isfield(EEG.event, 'duration') |
|
|
425 |
if EEG.event(1).duration < 1 |
|
|
426 |
EEG.event(1) = []; |
|
|
427 |
elseif EEG.event(1).latency > 0 && EEG.event(1).latency < 1 |
|
|
428 |
EEG.event(1).latency = 0.5; |
|
|
429 |
end |
|
|
430 |
end |
|
|
431 |
end |
|
|
432 |
|
|
|
433 |
try |
|
|
434 |
tmpevent = EEG.event; |
|
|
435 |
alllatencies = [tmpevent.latency]; |
|
|
436 |
catch |
|
|
437 |
error('Checkset: error empty latency entry for new events added by user'); |
|
|
438 |
end |
|
|
439 |
I1 = find(alllatencies < 0.5); |
|
|
440 |
I2 = find(alllatencies > EEG.pnts*EEG.trials+1); % The addition of 1 was included |
|
|
441 |
% because, if data epochs are extracted from -1 to |
|
|
442 |
% time 0, this allow to include the last event in |
|
|
443 |
% the last epoch (otherwise all epochs have an |
|
|
444 |
% event except the last one |
|
|
445 |
if (length(I1) + length(I2)) > 0 |
|
|
446 |
fprintf('eeg_checkset warning: %d/%d events had out-of-bounds latencies and were removed\n', ... |
|
|
447 |
length(I1) + length(I2), length(EEG.event)); |
|
|
448 |
EEG.event(union(I1, I2)) = []; |
|
|
449 |
end |
|
|
450 |
end |
|
|
451 |
if isempty(EEG.event), return; end |
|
|
452 |
|
|
|
453 |
% save information for non latency fields updates |
|
|
454 |
% ----------------------------------------------- |
|
|
455 |
difffield = []; |
|
|
456 |
if ~isempty(EEG.event) && isfield(EEG.event, 'epoch') |
|
|
457 |
% remove fields with empty epochs |
|
|
458 |
% ------------------------------- |
|
|
459 |
removeevent = []; |
|
|
460 |
try |
|
|
461 |
tmpevent = EEG.event; |
|
|
462 |
allepochs = [ tmpevent.epoch ]; |
|
|
463 |
removeevent = find( allepochs < 1 | allepochs > EEG.trials); |
|
|
464 |
if ~isempty(removeevent) |
|
|
465 |
disp([ 'eeg_checkset warning: ' int2str(length(removeevent)) ' event had invalid epoch numbers and were removed']); |
|
|
466 |
end |
|
|
467 |
catch |
|
|
468 |
for indexevent = 1:length(EEG.event) |
|
|
469 |
if isempty( EEG.event(indexevent).epoch ) || ~isnumeric(EEG.event(indexevent).epoch) ... |
|
|
470 |
|| EEG.event(indexevent).epoch < 1 || EEG.event(indexevent).epoch > EEG.trials |
|
|
471 |
removeevent = [removeevent indexevent]; |
|
|
472 |
disp([ 'eeg_checkset warning: event ' int2str(indexevent) ' has an invalid epoch number: removed']); |
|
|
473 |
end |
|
|
474 |
end |
|
|
475 |
end |
|
|
476 |
EEG.event(removeevent) = []; |
|
|
477 |
end |
|
|
478 |
if isempty(EEG.event), return; end |
|
|
479 |
|
|
|
480 |
% Duration set to 0 if empty |
|
|
481 |
% -------------------------- |
|
|
482 |
if isfield(EEG.event, 'duration') |
|
|
483 |
emptyDur = cellfun(@isempty, { EEG.event.duration }); |
|
|
484 |
if any(emptyDur) |
|
|
485 |
for indexevent = find(emptyDur) |
|
|
486 |
EEG.event(indexevent).duration = 0; |
|
|
487 |
end |
|
|
488 |
end |
|
|
489 |
end |
|
|
490 |
|
|
|
491 |
% uniformize fields (str or int) if necessary |
|
|
492 |
% ------------------------------------------- |
|
|
493 |
fnames = fieldnames(EEG.event); |
|
|
494 |
for fidx = 1:length(fnames) |
|
|
495 |
fname = fnames{fidx}; |
|
|
496 |
if ~strcmpi(fname, 'mffkeys') && ~strcmpi(fname, 'mffkeysbackup') |
|
|
497 |
tmpevent = EEG.event; |
|
|
498 |
allvalues = { tmpevent.(fname) }; |
|
|
499 |
try |
|
|
500 |
% find indices of numeric values among values of this event property |
|
|
501 |
valreal = ~cellfun('isclass', allvalues, 'char'); |
|
|
502 |
catch |
|
|
503 |
valreal = mycellfun('isclass', allvalues, 'double'); |
|
|
504 |
end |
|
|
505 |
|
|
|
506 |
format = 'ok'; |
|
|
507 |
if ~all(valreal) % all valreal ok |
|
|
508 |
format = 'str'; |
|
|
509 |
if all(valreal == 0) % all valreal=0 ok |
|
|
510 |
format = 'ok'; |
|
|
511 |
end |
|
|
512 |
end |
|
|
513 |
if strcmp(format, 'str') |
|
|
514 |
fprintf('eeg_checkset note: event field format ''%s'' made uniform\n', fname); |
|
|
515 |
allvalues = cellfun(@num2str, allvalues, 'uniformoutput', false); |
|
|
516 |
[EEG.event(valreal).(fname)] = deal(allvalues{find(valreal)}); |
|
|
517 |
end |
|
|
518 |
end |
|
|
519 |
end |
|
|
520 |
|
|
|
521 |
% check boundary events |
|
|
522 |
% --------------------- |
|
|
523 |
tmpevent = EEG.event; |
|
|
524 |
if isfield(tmpevent, 'type') && ~isnumeric(tmpevent(1).type) |
|
|
525 |
boundsInd = eeg_findboundaries(EEG); |
|
|
526 |
if ~isempty(boundsInd) |
|
|
527 |
bounds = [ tmpevent(boundsInd).latency ]; |
|
|
528 |
% remove last event if necessary |
|
|
529 |
if EEG.trials==1 %this if block added by James Desjardins (Jan 13th, 2014) |
|
|
530 |
if round(bounds(end)-0.5) > size(EEG.data,2), EEG.event(boundsInd(end)) = []; bounds(end) = []; end; % remove final boundary if any |
|
|
531 |
end |
|
|
532 |
% The first boundary below need to be kept for |
|
|
533 |
% urevent latency calculation |
|
|
534 |
% if bounds(1) < 0, EEG.event(bounds(1)) = []; end; % remove initial boundary if any |
|
|
535 |
indDoublet = find(bounds(2:end)-bounds(1:end-1)==0); |
|
|
536 |
if ~isempty(indDoublet) |
|
|
537 |
disp('Warning: duplicate boundary event removed'); |
|
|
538 |
if isfield(EEG.event, 'duration') |
|
|
539 |
for indBound = 1:length(indDoublet) |
|
|
540 |
EEG.event(boundsInd(indDoublet(indBound)+1)).duration = EEG.event(boundsInd(indDoublet(indBound)+1)).duration+EEG.event(boundsInd(indDoublet(indBound))).duration; |
|
|
541 |
end |
|
|
542 |
end |
|
|
543 |
EEG.event(boundsInd(indDoublet)) = []; |
|
|
544 |
end |
|
|
545 |
end |
|
|
546 |
end |
|
|
547 |
if isempty(EEG.event), return; end |
|
|
548 |
|
|
|
549 |
% check that numeric format is double (Matlab 7) |
|
|
550 |
% ----------------------------------- |
|
|
551 |
allfields = fieldnames(EEG.event); |
|
|
552 |
if ~isempty(EEG.event) |
|
|
553 |
for index = 1:length(allfields) |
|
|
554 |
tmpval = EEG.event(1).(allfields{index}); |
|
|
555 |
if isnumeric(tmpval) && ~isa(tmpval, 'double') |
|
|
556 |
for indexevent = 1:length(EEG.event) |
|
|
557 |
tmpval = getfield(EEG.event, { indexevent }, allfields{index} ); |
|
|
558 |
EEG.event = setfield(EEG.event, { indexevent }, allfields{index}, double(tmpval)); |
|
|
559 |
end |
|
|
560 |
end |
|
|
561 |
end |
|
|
562 |
end |
|
|
563 |
|
|
|
564 |
% check duration field, replace empty by 0 |
|
|
565 |
% ---------------------------------------- |
|
|
566 |
if isfield(EEG.event, 'duration') |
|
|
567 |
tmpevent = EEG.event; |
|
|
568 |
try |
|
|
569 |
valempt = cellfun('isempty' , { tmpevent.duration }); |
|
|
570 |
catch |
|
|
571 |
valempt = mycellfun('isempty', { tmpevent.duration }); |
|
|
572 |
end |
|
|
573 |
if any(valempt) |
|
|
574 |
for index = find(valempt) |
|
|
575 |
EEG.event(index).duration = 0; |
|
|
576 |
end |
|
|
577 |
end |
|
|
578 |
end |
|
|
579 |
|
|
|
580 |
% resort events |
|
|
581 |
% ------------- |
|
|
582 |
if isfield(EEG.event, 'latency') |
|
|
583 |
try |
|
|
584 |
if isfield(EEG.event, 'epoch') |
|
|
585 |
TMPEEG = pop_editeventvals(EEG, 'sort', { 'epoch' 0 'latency' 0 }); |
|
|
586 |
else |
|
|
587 |
TMPEEG = pop_editeventvals(EEG, 'sort', { 'latency' 0 }); |
|
|
588 |
end |
|
|
589 |
if ~isequal(TMPEEG.event, EEG.event) |
|
|
590 |
EEG = TMPEEG; |
|
|
591 |
disp('eeg_checkset note: events'' order (re)sorted by time'); |
|
|
592 |
end |
|
|
593 |
catch |
|
|
594 |
disp('eeg_checkset: problem when attempting to resort event latencies.'); |
|
|
595 |
end |
|
|
596 |
end |
|
|
597 |
|
|
|
598 |
% check latency of first event |
|
|
599 |
% ---------------------------- |
|
|
600 |
if ~isempty(EEG.event) |
|
|
601 |
if isfield(EEG.event, 'latency') |
|
|
602 |
if EEG.event(1).latency < 0.5 |
|
|
603 |
EEG.event(1).latency = 0.5; |
|
|
604 |
end |
|
|
605 |
end |
|
|
606 |
end |
|
|
607 |
|
|
|
608 |
% build epoch structure |
|
|
609 |
% --------------------- |
|
|
610 |
try, |
|
|
611 |
if EEG.trials > 1 && ~isempty(EEG.event) |
|
|
612 |
% erase existing event-related fields |
|
|
613 |
% ------------------------------ |
|
|
614 |
if ~isfield(EEG,'epoch') |
|
|
615 |
EEG.epoch = []; |
|
|
616 |
end |
|
|
617 |
if ~isempty(EEG.epoch) |
|
|
618 |
if length(EEG.epoch) ~= EEG.trials |
|
|
619 |
disp('Warning: number of epoch entries does not match number of dataset trials;'); |
|
|
620 |
disp(' user-defined epoch entries will be erased.'); |
|
|
621 |
EEG.epoch = []; |
|
|
622 |
else |
|
|
623 |
fn = fieldnames(EEG.epoch); |
|
|
624 |
EEG.epoch = rmfield(EEG.epoch,fn(strncmp('event',fn,5))); |
|
|
625 |
end |
|
|
626 |
end |
|
|
627 |
|
|
|
628 |
% set event field |
|
|
629 |
% --------------- |
|
|
630 |
tmpevent = EEG.event; |
|
|
631 |
eventepoch = [tmpevent.epoch]; |
|
|
632 |
epochevent = cell(1,EEG.trials); |
|
|
633 |
destdata = epochevent; |
|
|
634 |
EEG.epoch(length(epochevent)).event = []; |
|
|
635 |
for k=1:length(epochevent) |
|
|
636 |
epochevent{k} = find(eventepoch==k); |
|
|
637 |
end |
|
|
638 |
tmpepoch = EEG.epoch; |
|
|
639 |
[tmpepoch.event] = epochevent{:}; |
|
|
640 |
EEG.epoch = tmpepoch; |
|
|
641 |
maxlen = max(cellfun(@length,epochevent)); |
|
|
642 |
|
|
|
643 |
% copy event information into the epoch array |
|
|
644 |
% ------------------------------------------- |
|
|
645 |
eventfields = fieldnames(EEG.event)'; |
|
|
646 |
eventfields = eventfields(~strcmp(eventfields,'epoch')); |
|
|
647 |
tmpevent = EEG.event; |
|
|
648 |
for k = 1:length(eventfields) |
|
|
649 |
fname = eventfields{k}; |
|
|
650 |
switch fname |
|
|
651 |
case 'latency' |
|
|
652 |
sourcedata = round(eeg_point2lat([tmpevent.(fname)],[tmpevent.epoch],EEG.srate, [EEG.xmin EEG.xmax]*1000, 1E-3) * 10^8 )/10^8; |
|
|
653 |
sourcedata = num2cell(sourcedata); |
|
|
654 |
case 'duration' |
|
|
655 |
sourcedata = num2cell([tmpevent.(fname)]/EEG.srate*1000); |
|
|
656 |
otherwise |
|
|
657 |
sourcedata = {tmpevent.(fname)}; |
|
|
658 |
end |
|
|
659 |
if maxlen == 1 |
|
|
660 |
destdata = cell(1,length(epochevent)); |
|
|
661 |
destdata(~cellfun('isempty',epochevent)) = sourcedata([epochevent{:}]); |
|
|
662 |
else |
|
|
663 |
for l=1:length(epochevent) |
|
|
664 |
destdata{l} = sourcedata(epochevent{l}); |
|
|
665 |
end |
|
|
666 |
end |
|
|
667 |
tmpepoch = EEG.epoch; |
|
|
668 |
[tmpepoch.(['event' fname])] = destdata{:}; |
|
|
669 |
EEG.epoch = tmpepoch; |
|
|
670 |
end |
|
|
671 |
end |
|
|
672 |
catch |
|
|
673 |
errordlg2(['Warning: minor problem encountered when generating' 10 ... |
|
|
674 |
'the EEG.epoch structure (used only in user scripts)']); return; |
|
|
675 |
end |
|
|
676 |
end |
|
|
677 |
case { 'loaddata' 'savedata' 'chanconsist' 'icaconsist' 'epochconsist' }, res = ''; |
|
|
678 |
otherwise, error('eeg_checkset: unknown option'); |
|
|
679 |
end |
|
|
680 |
end |
|
|
681 |
end |
|
|
682 |
|
|
|
683 |
res = []; |
|
|
684 |
|
|
|
685 |
% check name consistency |
|
|
686 |
% ---------------------- |
|
|
687 |
if ~isempty(EEG.setname) |
|
|
688 |
if ~ischar(EEG.setname) |
|
|
689 |
EEG.setname = ''; |
|
|
690 |
else |
|
|
691 |
if size(EEG.setname,1) > 1 |
|
|
692 |
disp('eeg_checkset warning: invalid dataset name, removed'); |
|
|
693 |
EEG.setname = ''; |
|
|
694 |
end |
|
|
695 |
end |
|
|
696 |
else |
|
|
697 |
EEG.setname = ''; |
|
|
698 |
end |
|
|
699 |
|
|
|
700 |
% checking history and convert if necessary |
|
|
701 |
% ----------------------------------------- |
|
|
702 |
if isfield(EEG, 'history') && size(EEG.history,1) > 1 |
|
|
703 |
allcoms = cellstr(EEG.history); |
|
|
704 |
EEG.history = deblank(allcoms{1}); |
|
|
705 |
for index = 2:length(allcoms) |
|
|
706 |
EEG.history = [ EEG.history 10 deblank(allcoms{index}) ]; |
|
|
707 |
end |
|
|
708 |
end |
|
|
709 |
|
|
|
710 |
% read data if necessary |
|
|
711 |
% ---------------------- |
|
|
712 |
if ischar(EEG.data) && nargin > 1 |
|
|
713 |
if strcmpi(varargin{1}, 'loaddata') |
|
|
714 |
|
|
|
715 |
EEG.data = eeg_getdatact(EEG); |
|
|
716 |
|
|
|
717 |
end |
|
|
718 |
end |
|
|
719 |
|
|
|
720 |
% save data if necessary |
|
|
721 |
% ---------------------- |
|
|
722 |
if nargin > 1 |
|
|
723 |
|
|
|
724 |
% datfile available? |
|
|
725 |
% ------------------ |
|
|
726 |
datfile = 0; |
|
|
727 |
if isfield(EEG, 'datfile') |
|
|
728 |
if ~isempty(EEG.datfile) |
|
|
729 |
datfile = 1; |
|
|
730 |
end |
|
|
731 |
end |
|
|
732 |
|
|
|
733 |
% save data |
|
|
734 |
% --------- |
|
|
735 |
if strcmpi(varargin{1}, 'savedata') && option_storedisk |
|
|
736 |
error('eeg_checkset: cannot call savedata any more'); |
|
|
737 |
|
|
|
738 |
% the code below is deprecated |
|
|
739 |
if ~ischar(EEG.data) % not already saved |
|
|
740 |
disp('Writing previous dataset to disk...'); |
|
|
741 |
|
|
|
742 |
if datfile |
|
|
743 |
tmpdata = reshape(EEG.data, EEG.nbchan, EEG.pnts*EEG.trials); |
|
|
744 |
floatwrite( tmpdata', fullfile(EEG.filepath, EEG.datfile), 'ieee-le'); |
|
|
745 |
EEG.data = EEG.datfile; |
|
|
746 |
end |
|
|
747 |
EEG.icaact = []; |
|
|
748 |
|
|
|
749 |
% saving dataset |
|
|
750 |
% -------------- |
|
|
751 |
filename = fullfile(EEG(1).filepath, EEG(1).filename); |
|
|
752 |
if ~ischar(EEG.data) && option_single, EEG.data = single(EEG.data); end |
|
|
753 |
v = version; |
|
|
754 |
if str2num(v(1)) >= 7, save( filename, '-v6', '-mat', 'EEG'); % Matlab 7 |
|
|
755 |
else save( filename, '-mat', 'EEG'); |
|
|
756 |
end |
|
|
757 |
if ~ischar(EEG.data), EEG.data = 'in set file'; end |
|
|
758 |
|
|
|
759 |
% res = sprintf('%s = eeg_checkset( %s, ''savedata'');', inputname(1), inputname(1)); |
|
|
760 |
res = ['EEG = eeg_checkset( EEG, ''savedata'');']; |
|
|
761 |
end |
|
|
762 |
end |
|
|
763 |
end |
|
|
764 |
|
|
|
765 |
% numerical format |
|
|
766 |
% ---------------- |
|
|
767 |
if isnumeric(EEG.data) |
|
|
768 |
v = version; |
|
|
769 |
EEG.icawinv = double(EEG.icawinv); % required for dipole fitting, otherwise it crashes |
|
|
770 |
EEG.icaweights = double(EEG.icaweights); |
|
|
771 |
EEG.icasphere = double(EEG.icasphere); |
|
|
772 |
if ~isempty(findstr(v, 'R11')) || ~isempty(findstr(v, 'R12')) || ~isempty(findstr(v, 'R13')) |
|
|
773 |
EEG.data = double(EEG.data); |
|
|
774 |
EEG.icaact = double(EEG.icaact); |
|
|
775 |
else |
|
|
776 |
try, |
|
|
777 |
if isa(EEG.data, 'double') && option_single |
|
|
778 |
EEG.data = single(EEG.data); |
|
|
779 |
EEG.icaact = single(EEG.icaact); |
|
|
780 |
end |
|
|
781 |
catch, |
|
|
782 |
disp('WARNING: EEGLAB ran out of memory while converting dataset to single precision.'); |
|
|
783 |
disp(' Save dataset (preferably saving data to a separate file; see File > Memory options).'); |
|
|
784 |
disp(' Then reload it.'); |
|
|
785 |
end |
|
|
786 |
end |
|
|
787 |
end |
|
|
788 |
|
|
|
789 |
% verify the type of the variables |
|
|
790 |
% -------------------------------- |
|
|
791 |
% data dimensions ------------------------- |
|
|
792 |
if isnumeric(EEG.data) && ~isempty(EEG.data) |
|
|
793 |
if ~isequal(size(EEG.data,1), EEG.nbchan) |
|
|
794 |
disp( [ 'eeg_checkset warning: number of rows in data (' int2str(size(EEG.data,1)) ... |
|
|
795 |
') does not match the number of channels (' int2str(EEG.nbchan) '): corrected' ]); |
|
|
796 |
res = com; |
|
|
797 |
EEG.nbchan = size(EEG.data,1); |
|
|
798 |
end |
|
|
799 |
|
|
|
800 |
if (ndims(EEG.data)) < 3 && (EEG.pnts > 1) |
|
|
801 |
if mod(size(EEG.data,2), EEG.pnts) ~= 0 |
|
|
802 |
fprintf(2, 'eeg_checkset error: binary data file likely truncated, importing anyway...\n'); |
|
|
803 |
if EEG.trials > 1 |
|
|
804 |
EEG.trials = floor(size(EEG.data,2)/EEG.pnts); |
|
|
805 |
EEG.data(:,EEG.trials*EEG.pnts+1:end) = []; |
|
|
806 |
res = com; |
|
|
807 |
else |
|
|
808 |
EEG.pnts = size(EEG.data,2); |
|
|
809 |
res = com; |
|
|
810 |
end |
|
|
811 |
else |
|
|
812 |
if EEG.trials > 1 |
|
|
813 |
disp( 'eeg_checkset note: data array made 3-D'); |
|
|
814 |
res = com; |
|
|
815 |
end |
|
|
816 |
if size(EEG.data,2) ~= EEG.pnts |
|
|
817 |
EEG.data = reshape(EEG.data, EEG.nbchan, EEG.pnts, size(EEG.data,2)/EEG.pnts); |
|
|
818 |
end |
|
|
819 |
end |
|
|
820 |
end |
|
|
821 |
|
|
|
822 |
% size of data ----------- |
|
|
823 |
if size(EEG.data,3) ~= EEG.trials |
|
|
824 |
disp( ['eeg_checkset warning: 3rd dimension size of data (' int2str(size(EEG.data,3)) ... |
|
|
825 |
') does not match the number of epochs (' int2str(EEG.trials) '), corrected' ]); |
|
|
826 |
res = com; |
|
|
827 |
EEG.trials = size(EEG.data,3); |
|
|
828 |
end |
|
|
829 |
if size(EEG.data,2) ~= EEG.pnts |
|
|
830 |
disp( [ 'eeg_checkset warning: number of columns in data (' int2str(size(EEG.data,2)) ... |
|
|
831 |
') does not match the number of points (' int2str(EEG.pnts) '): corrected' ]); |
|
|
832 |
res = com; |
|
|
833 |
EEG.pnts = size(EEG.data,2); |
|
|
834 |
end |
|
|
835 |
end |
|
|
836 |
|
|
|
837 |
% xmin must be 0 for continuous data or |
|
|
838 |
% pop_select does not behave correctly when |
|
|
839 |
% removing data points |
|
|
840 |
% -------------------- |
|
|
841 |
if EEG.trials == 1 && EEG.xmin ~= 0 |
|
|
842 |
EEG.xmin = 0; |
|
|
843 |
fprintf( 'eeg_checkset note: xmin set to 0 for continuous data\n'); |
|
|
844 |
res = com; |
|
|
845 |
end |
|
|
846 |
|
|
|
847 |
% parameters consistency |
|
|
848 |
% ------------------------- |
|
|
849 |
if round(EEG.srate*(EEG.xmax-EEG.xmin)+1) ~= EEG.pnts |
|
|
850 |
fprintf( 'eeg_checkset note: upper time limit (xmax) adjusted so (xmax-xmin)*srate+1 = number of frames\n'); |
|
|
851 |
if EEG.srate == 0 |
|
|
852 |
EEG.srate = 1; |
|
|
853 |
end |
|
|
854 |
EEG.xmax = (EEG.pnts-1)/EEG.srate+EEG.xmin; |
|
|
855 |
res = com; |
|
|
856 |
end |
|
|
857 |
|
|
|
858 |
% deal with event arrays |
|
|
859 |
% ---------------------- |
|
|
860 |
if ~isfield(EEG, 'event'), EEG.event = []; res = com; end |
|
|
861 |
if ~isempty(EEG.event) |
|
|
862 |
if EEG.trials > 1 && ~isfield(EEG.event, 'epoch') |
|
|
863 |
if popask( [ 'eeg_checkset error: the event info structure does not contain an ''epoch'' field.' ... |
|
|
864 |
'Should EEGLAB attempt to abort operation ?' 10 '(press Cancel to fix the problem from the commandline)']) |
|
|
865 |
error('eeg_checkset error(): user abort'); |
|
|
866 |
%res = com; |
|
|
867 |
%EEG.event = []; |
|
|
868 |
%EEG = eeg_checkset(EEG); |
|
|
869 |
%return; |
|
|
870 |
else |
|
|
871 |
res = com; |
|
|
872 |
return; |
|
|
873 |
%error('eeg_checkset error: no epoch field in event structure'); |
|
|
874 |
end |
|
|
875 |
end |
|
|
876 |
else |
|
|
877 |
EEG.event = []; |
|
|
878 |
end |
|
|
879 |
if isfield(EEG, 'urevent') && ~isempty(EEG.urevent) && ~isfield(EEG.event, 'urevent') && ~isempty(EEG.event) |
|
|
880 |
warning('Inconsistency between urevent (backup) and event structures, removing urevent structure'); |
|
|
881 |
EEG.urevent = []; |
|
|
882 |
end |
|
|
883 |
if isempty(EEG.event) |
|
|
884 |
EEG.eventdescription = {}; |
|
|
885 |
end |
|
|
886 |
if ~isfield(EEG, 'eventdescription') || ~iscell(EEG.eventdescription) |
|
|
887 |
EEG.eventdescription = cell(1, length(fieldnames(EEG.event))); |
|
|
888 |
res = com; |
|
|
889 |
else |
|
|
890 |
if ~isempty(EEG.event) |
|
|
891 |
if length(EEG.eventdescription) > length( fieldnames(EEG.event)) |
|
|
892 |
EEG.eventdescription = EEG.eventdescription(1:length( fieldnames(EEG.event))); |
|
|
893 |
elseif length(EEG.eventdescription) < length( fieldnames(EEG.event)) |
|
|
894 |
EEG.eventdescription(end+1:length( fieldnames(EEG.event))) = {''}; |
|
|
895 |
end |
|
|
896 |
end |
|
|
897 |
end |
|
|
898 |
% create urevent if continuous data |
|
|
899 |
% --------------------------------- |
|
|
900 |
%if ~isempty(EEG.event) && ~isfield(EEG, 'urevent') |
|
|
901 |
% EEG.urevent = EEG.event; |
|
|
902 |
% disp('eeg_checkset note: creating the original event table (EEG.urevent)'); |
|
|
903 |
% for index = 1:length(EEG.event) |
|
|
904 |
% EEG.event(index).urevent = index; |
|
|
905 |
% end |
|
|
906 |
%end |
|
|
907 |
if isfield(EEG, 'urevent') && isfield(EEG.urevent, 'urevent') |
|
|
908 |
EEG.urevent = rmfield(EEG.urevent, 'urevent'); |
|
|
909 |
end |
|
|
910 |
|
|
|
911 |
% deal with epoch arrays |
|
|
912 |
% ---------------------- |
|
|
913 |
if ~isfield(EEG, 'epoch'), EEG.epoch = []; res = com; end |
|
|
914 |
|
|
|
915 |
% check if only one epoch |
|
|
916 |
% ----------------------- |
|
|
917 |
if EEG.trials == 1 |
|
|
918 |
if isfield(EEG.event, 'epoch') |
|
|
919 |
EEG.event = rmfield(EEG.event, 'epoch'); res = com; |
|
|
920 |
end |
|
|
921 |
if ~isempty(EEG.epoch) |
|
|
922 |
EEG.epoch = []; res = com; |
|
|
923 |
end |
|
|
924 |
end |
|
|
925 |
|
|
|
926 |
if ~isfield(EEG, 'epochdescription'), EEG.epochdescription = {}; res = com; end |
|
|
927 |
if ~isempty(EEG.epoch) |
|
|
928 |
if isstruct(EEG.epoch), l = length( EEG.epoch); |
|
|
929 |
else l = size( EEG.epoch, 2); |
|
|
930 |
end |
|
|
931 |
if l ~= EEG.trials |
|
|
932 |
if popask( [ 'eeg_checkset error: the number of epoch indices in the epoch array/struct (' ... |
|
|
933 |
int2str(l) ') is different from the number of epochs in the data (' int2str(EEG.trials) ').' 10 ... |
|
|
934 |
'Should EEGLAB attempt to abort operation ?' 10 '(press Cancel to fix the problem from the commandline)']) |
|
|
935 |
error('eeg_checkset error: user abort'); |
|
|
936 |
%res = com; |
|
|
937 |
%EEG.epoch = []; |
|
|
938 |
%EEG = eeg_checkset(EEG); |
|
|
939 |
%return; |
|
|
940 |
else |
|
|
941 |
res = com; |
|
|
942 |
return; |
|
|
943 |
%error('eeg_checkset error: epoch structure size invalid'); |
|
|
944 |
end |
|
|
945 |
end |
|
|
946 |
else |
|
|
947 |
EEG.epoch = []; |
|
|
948 |
end |
|
|
949 |
|
|
|
950 |
% check ica |
|
|
951 |
% --------- |
|
|
952 |
if ~isfield(EEG, 'icachansind') |
|
|
953 |
if isempty(EEG.icaweights) |
|
|
954 |
EEG.icachansind = []; res = com; |
|
|
955 |
else |
|
|
956 |
EEG.icachansind = [1:EEG.nbchan]; res = com; |
|
|
957 |
end |
|
|
958 |
elseif isempty(EEG.icachansind) |
|
|
959 |
if ~isempty(EEG.icaweights) |
|
|
960 |
EEG.icachansind = [1:EEG.nbchan]; res = com; |
|
|
961 |
end |
|
|
962 |
end |
|
|
963 |
if ~isempty(EEG.icasphere) |
|
|
964 |
if ~isempty(EEG.icaweights) |
|
|
965 |
if size(EEG.icaweights,2) ~= size(EEG.icasphere,1) |
|
|
966 |
if popask( [ 'eeg_checkset error: number of columns in weights array (' int2str(size(EEG.icaweights,2)) ')' 10 ... |
|
|
967 |
'does not match the number of rows in the sphere array (' int2str(size(EEG.icasphere,1)) ')' 10 ... |
|
|
968 |
'Should EEGLAB remove ICA information ?' 10 '(press Cancel to fix the problem from the commandline)']) |
|
|
969 |
res = com; |
|
|
970 |
EEG.icasphere = []; |
|
|
971 |
EEG.icaweights = []; |
|
|
972 |
EEG = eeg_checkset(EEG); |
|
|
973 |
return; |
|
|
974 |
else |
|
|
975 |
error('eeg_checkset error: user abort'); |
|
|
976 |
res = com; |
|
|
977 |
return; |
|
|
978 |
%error('eeg_checkset error: invalid weight and sphere array sizes'); |
|
|
979 |
end |
|
|
980 |
end |
|
|
981 |
if isnumeric(EEG.data) |
|
|
982 |
if length(EEG.icachansind) ~= size(EEG.icasphere,2) |
|
|
983 |
if popask( [ 'eeg_checkset error: number of elements in ''icachansind'' (' int2str(length(EEG.icachansind)) ')' 10 ... |
|
|
984 |
'does not match the number of columns in the sphere array (' int2str(size(EEG.icasphere,2)) ')' 10 ... |
|
|
985 |
'Should EEGLAB remove ICA information ?' 10 '(press Cancel to fix the problem from the commandline)']) |
|
|
986 |
res = com; |
|
|
987 |
EEG.icasphere = []; |
|
|
988 |
EEG.icaweights = []; |
|
|
989 |
EEG = eeg_checkset(EEG); |
|
|
990 |
return; |
|
|
991 |
else |
|
|
992 |
error('eeg_checkset error: user abort'); |
|
|
993 |
res = com; |
|
|
994 |
return; |
|
|
995 |
%error('eeg_checkset error: invalid weight and sphere array sizes'); |
|
|
996 |
end |
|
|
997 |
end |
|
|
998 |
if isempty(EEG.icaact) || (size(EEG.icaact,1) ~= size(EEG.icaweights,1)) || (size(EEG.icaact,2) ~= size(EEG.data,2)) |
|
|
999 |
EEG.icaweights = double(EEG.icaweights); |
|
|
1000 |
EEG.icawinv = double(EEG.icawinv); |
|
|
1001 |
|
|
|
1002 |
% scale ICA components to RMS microvolt |
|
|
1003 |
if option_scaleicarms |
|
|
1004 |
if ~isempty(EEG.icawinv) |
|
|
1005 |
if mean(mean(abs(pinv(EEG.icaweights * EEG.icasphere)-EEG.icawinv))) < 0.0001 |
|
|
1006 |
disp('Scaling components to RMS microvolt'); |
|
|
1007 |
scaling = repmat(sqrt(mean(EEG(1).icawinv(:,:).^2))', [1 size(EEG.icaweights,2)]); |
|
|
1008 |
EEG.etc.icaweights_beforerms = EEG.icaweights; |
|
|
1009 |
EEG.etc.icasphere_beforerms = EEG.icasphere; |
|
|
1010 |
|
|
|
1011 |
EEG.icaweights = EEG.icaweights .* scaling; |
|
|
1012 |
EEG.icawinv = pinv(EEG.icaweights * EEG.icasphere); |
|
|
1013 |
end |
|
|
1014 |
end |
|
|
1015 |
end |
|
|
1016 |
|
|
|
1017 |
if ~isempty(EEG.data) && option_computeica |
|
|
1018 |
fprintf('eeg_checkset: recomputing the ICA activation matrix ...\n'); |
|
|
1019 |
res = com; |
|
|
1020 |
% Make compatible with Matlab 7 |
|
|
1021 |
if any(isnan(EEG.data(:))) |
|
|
1022 |
tmpdata = EEG.data(EEG.icachansind,:); |
|
|
1023 |
fprintf('eeg_checkset: recomputing ICA ignoring NaN indices ...\n'); |
|
|
1024 |
tmpindices = find(~sum(isnan(tmpdata))); % was: tmpindices = find(~isnan(EEG.data(1,:))); |
|
|
1025 |
EEG.icaact = zeros(size(EEG.icaweights,1), size(tmpdata,2)); EEG.icaact(:) = NaN; |
|
|
1026 |
EEG.icaact(:,tmpindices) = (EEG.icaweights*EEG.icasphere)*tmpdata(:,tmpindices); |
|
|
1027 |
else |
|
|
1028 |
EEG.icaact = (EEG.icaweights*EEG.icasphere)*EEG.data(EEG.icachansind,:); % automatically does single or double |
|
|
1029 |
end |
|
|
1030 |
EEG.icaact = reshape( EEG.icaact, size(EEG.icaact,1), EEG.pnts, EEG.trials); |
|
|
1031 |
end |
|
|
1032 |
end |
|
|
1033 |
if ~isempty(EEG.icaact) |
|
|
1034 |
if EEG.trials*EEG.pnts < 1000 |
|
|
1035 |
tmpact = (EEG.icaweights * EEG.icasphere) * EEG.data(EEG.icachansind,:); |
|
|
1036 |
else |
|
|
1037 |
% special MATLAB calculation kicks in above 1000 |
|
|
1038 |
% (otherwise difference on the order of 0.0000001%) |
|
|
1039 |
tmpact = (EEG.icaweights * EEG.icasphere) * EEG.data(EEG.icachansind,1:1000); |
|
|
1040 |
end |
|
|
1041 |
if mean(abs(tmpact(:,1) - EEG.icaact(:,1))) > 0.000001 |
|
|
1042 |
backtraceState = warning('backtrace'); |
|
|
1043 |
warning('backtrace', 'off') |
|
|
1044 |
warning('ICA activities and weights mismatch, click on the link below for more information', 'verbose') |
|
|
1045 |
fprintf('<a href="https://eeglab.org/others/TIPS_and_FAQ.html#ica-activity-warning">https://eeglab.org/others/TIPS_and_FAQ.html#ica-activity-warning</a>\n') |
|
|
1046 |
if isstruct(backtraceState) |
|
|
1047 |
warning('backtrace', backtraceState.state); |
|
|
1048 |
end |
|
|
1049 |
end |
|
|
1050 |
end |
|
|
1051 |
end |
|
|
1052 |
if isempty(EEG.icawinv) |
|
|
1053 |
EEG.icawinv = pinv(EEG.icaweights*EEG.icasphere); % a priori same result as inv |
|
|
1054 |
res = com; |
|
|
1055 |
end |
|
|
1056 |
else |
|
|
1057 |
disp( [ 'eeg_checkset warning: weights matrix cannot be empty if sphere matrix is not, correcting ...' ]); |
|
|
1058 |
res = com; |
|
|
1059 |
EEG.icasphere = []; |
|
|
1060 |
end |
|
|
1061 |
if option_computeica |
|
|
1062 |
if ~isempty(EEG.icaact) && ndims(EEG.icaact) < 3 && (EEG.trials > 1) |
|
|
1063 |
disp( [ 'eeg_checkset note: independent component made 3-D' ]); |
|
|
1064 |
res = com; |
|
|
1065 |
EEG.icaact = reshape(EEG.icaact, size(EEG.icaact,1), EEG.pnts, EEG.trials); |
|
|
1066 |
end |
|
|
1067 |
else |
|
|
1068 |
if ~isempty(EEG.icaact) |
|
|
1069 |
fprintf('eeg_checkset: removing ICA activation matrix (as per edit options) ...\n'); |
|
|
1070 |
end |
|
|
1071 |
EEG.icaact = []; |
|
|
1072 |
end |
|
|
1073 |
else |
|
|
1074 |
if ~isfield(EEG, 'icaweights') || ~isempty( EEG.icaweights ), EEG.icaweights = []; res = com; end |
|
|
1075 |
if ~isfield(EEG, 'icawinv') || ~isempty( EEG.icawinv ), EEG.icawinv = []; res = com; end |
|
|
1076 |
if ~isfield(EEG, 'icaact') || ~isempty( EEG.icaact ), EEG.icaact = []; res = com; end |
|
|
1077 |
end |
|
|
1078 |
if isempty(EEG.icaact) |
|
|
1079 |
EEG.icaact = []; |
|
|
1080 |
end |
|
|
1081 |
|
|
|
1082 |
% ------------- |
|
|
1083 |
% check chanlocs |
|
|
1084 |
% ------------- |
|
|
1085 |
if ~isfield(EEG, 'chaninfo') |
|
|
1086 |
EEG.chaninfo = []; |
|
|
1087 |
end |
|
|
1088 |
if ~isempty( EEG.chanlocs ) |
|
|
1089 |
|
|
|
1090 |
% reference (use EEG structure) |
|
|
1091 |
% --------- |
|
|
1092 |
if ~isfield(EEG, 'ref') |
|
|
1093 |
EEG.ref = ''; |
|
|
1094 |
end |
|
|
1095 |
if isequal(EEG.ref, 'averef') |
|
|
1096 |
EEG.ref = 'average'; |
|
|
1097 |
res = com; |
|
|
1098 |
end |
|
|
1099 |
if isequal(EEG.ref, 'average') |
|
|
1100 |
ref = 'average'; |
|
|
1101 |
else ref = ''; |
|
|
1102 |
end |
|
|
1103 |
if ~isfield( EEG.chanlocs, 'ref') |
|
|
1104 |
EEG.chanlocs(1).ref = ref; |
|
|
1105 |
end |
|
|
1106 |
if isfield(EEG.chanlocs, 'ref') && ~isempty(EEG.chanlocs(1).ref) |
|
|
1107 |
if ~isequal(EEG.chanlocs(1).ref, EEG.ref) |
|
|
1108 |
EEG.ref = EEG.chanlocs(1).ref; |
|
|
1109 |
res = com; |
|
|
1110 |
end |
|
|
1111 |
end |
|
|
1112 |
charrefs = cellfun('isclass',{EEG.chanlocs.ref},'char'); |
|
|
1113 |
if any(charrefs), ref = ''; end |
|
|
1114 |
for tmpind = find(~charrefs) |
|
|
1115 |
EEG.chanlocs(tmpind).ref = ref; |
|
|
1116 |
end |
|
|
1117 |
if ~isstruct( EEG.chanlocs) |
|
|
1118 |
if exist( EEG.chanlocs ) ~= 2 |
|
|
1119 |
disp( [ 'eeg_checkset warning: channel file does not exist or is not in Matlab path: filename removed from EEG struct' ]); |
|
|
1120 |
EEG.chanlocs = []; |
|
|
1121 |
res = com; |
|
|
1122 |
else |
|
|
1123 |
res = com; |
|
|
1124 |
try, EEG.chanlocs = readlocs( EEG.chanlocs ); |
|
|
1125 |
disp( [ 'eeg_checkset: channel file read' ]); |
|
|
1126 |
catch, EEG.chanlocs = []; end |
|
|
1127 |
end |
|
|
1128 |
else |
|
|
1129 |
if ~isfield(EEG.chanlocs,'labels') |
|
|
1130 |
disp('eeg_checkset warning: no field label in channel location structure, removing it'); |
|
|
1131 |
EEG.chanlocs = []; |
|
|
1132 |
res = com; |
|
|
1133 |
end |
|
|
1134 |
end |
|
|
1135 |
if isstruct( EEG.chanlocs) |
|
|
1136 |
if length( EEG.chanlocs) ~= EEG.nbchan && length( EEG.chanlocs) ~= EEG.nbchan+1 && ~isempty(EEG.data) |
|
|
1137 |
disp( [ 'eeg_checkset warning: number of channels different in data and channel file/struct: channel file/struct removed' ]); |
|
|
1138 |
EEG.chanlocs = []; |
|
|
1139 |
res = com; |
|
|
1140 |
end |
|
|
1141 |
end |
|
|
1142 |
|
|
|
1143 |
% general checking of channels |
|
|
1144 |
% ---------------------------- |
|
|
1145 |
EEG = eeg_checkchanlocs(EEG); |
|
|
1146 |
if EEG.nbchan ~= length(EEG.chanlocs) |
|
|
1147 |
EEG.chanlocs = []; |
|
|
1148 |
EEG.chaninfo = []; |
|
|
1149 |
disp('Warning: the size of the channel location structure does not match with'); |
|
|
1150 |
disp(' number of channels. Channel information have been removed.'); |
|
|
1151 |
end |
|
|
1152 |
end |
|
|
1153 |
EEG.chaninfo.icachansind = EEG.icachansind; % just a copy for programming convenience |
|
|
1154 |
|
|
|
1155 |
%if ~isfield(EEG, 'urchanlocs') |
|
|
1156 |
% EEG.urchanlocs = EEG.chanlocs; |
|
|
1157 |
% for index = 1:length(EEG.chanlocs) |
|
|
1158 |
% EEG.chanlocs(index).urchan = index; |
|
|
1159 |
% end |
|
|
1160 |
% disp('eeg_checkset note: creating backup chanlocs structure (urchanlocs)'); |
|
|
1161 |
%end |
|
|
1162 |
|
|
|
1163 |
% Field 'datachan in 'urchanlocs' is removed, if exist |
|
|
1164 |
if isfield(EEG, 'urchanlocs') && ~isempty(EEG.urchanlocs) && isfield(EEG.urchanlocs, 'datachan') |
|
|
1165 |
EEG.urchanlocs = rmfield(EEG.urchanlocs, 'datachan'); |
|
|
1166 |
end |
|
|
1167 |
|
|
|
1168 |
% check reference |
|
|
1169 |
% --------------- |
|
|
1170 |
if ~isfield(EEG, 'ref') |
|
|
1171 |
EEG.ref = 'common'; |
|
|
1172 |
end |
|
|
1173 |
if ischar(EEG.ref) && strcmpi(EEG.ref, 'common') |
|
|
1174 |
if length(EEG.chanlocs) > EEG.nbchan |
|
|
1175 |
disp('Extra common reference electrode location detected'); |
|
|
1176 |
EEG.ref = EEG.nbchan+1; |
|
|
1177 |
end |
|
|
1178 |
end |
|
|
1179 |
|
|
|
1180 |
% DIPFIT structure |
|
|
1181 |
% ---------------- |
|
|
1182 |
if isfield(EEG,'dipfit') |
|
|
1183 |
try |
|
|
1184 |
% check if dipfitdefs is present |
|
|
1185 |
dipfitdefs; |
|
|
1186 |
if isfield(EEG.dipfit, 'vol') && ~isfield(EEG.dipfit, 'hdmfile') |
|
|
1187 |
if exist('pop_dipfit_settings') |
|
|
1188 |
disp('Old DIPFIT structure detected: converting to DIPFIT 2 format'); |
|
|
1189 |
EEG.dipfit.hdmfile = template_models(1).hdmfile; |
|
|
1190 |
EEG.dipfit.coordformat = template_models(1).coordformat; |
|
|
1191 |
EEG.dipfit.mrifile = template_models(1).mrifile; |
|
|
1192 |
EEG.dipfit.chanfile = template_models(1).chanfile; |
|
|
1193 |
EEG.dipfit.coord_transform = []; |
|
|
1194 |
EEG.saved = 'no'; |
|
|
1195 |
res = com; |
|
|
1196 |
end |
|
|
1197 |
end |
|
|
1198 |
if isfield(EEG.dipfit, 'hdmfile') |
|
|
1199 |
if length(EEG.dipfit.hdmfile) > 8 |
|
|
1200 |
if strcmpi(EEG.dipfit.hdmfile(end-8), template_models(1).hdmfile(end-8)), EEG.dipfit.hdmfile = template_models(1).hdmfile; end |
|
|
1201 |
if strcmpi(EEG.dipfit.hdmfile(end-8), template_models(2).hdmfile(end-8)), EEG.dipfit.hdmfile = template_models(2).hdmfile; end |
|
|
1202 |
end |
|
|
1203 |
if length(EEG.dipfit.mrifile) > 8 |
|
|
1204 |
if strcmpi(EEG.dipfit.mrifile(end-8), template_models(1).mrifile(end-8)), EEG.dipfit.mrifile = template_models(1).mrifile; end |
|
|
1205 |
if strcmpi(EEG.dipfit.mrifile(end-8), template_models(2).mrifile(end-8)), EEG.dipfit.mrifile = template_models(2).mrifile; end |
|
|
1206 |
end |
|
|
1207 |
if length(EEG.dipfit.chanfile) > 8 |
|
|
1208 |
if strcmpi(EEG.dipfit.chanfile(end-8), template_models(1).chanfile(end-8)), EEG.dipfit.chanfile = template_models(1).chanfile; end |
|
|
1209 |
if strcmpi(EEG.dipfit.chanfile(end-8), template_models(2).chanfile(end-8)), EEG.dipfit.chanfile = template_models(2).chanfile; end |
|
|
1210 |
end |
|
|
1211 |
end |
|
|
1212 |
|
|
|
1213 |
if isfield(EEG.dipfit, 'coord_transform') |
|
|
1214 |
if isempty(EEG.dipfit.coord_transform) |
|
|
1215 |
EEG.dipfit.coord_transform = [0 0 0 0 0 0 1 1 1]; |
|
|
1216 |
end |
|
|
1217 |
elseif ~isempty(EEG.dipfit) |
|
|
1218 |
EEG.dipfit.coord_transform = [0 0 0 0 0 0 1 1 1]; |
|
|
1219 |
end |
|
|
1220 |
catch |
|
|
1221 |
e = lasterror; |
|
|
1222 |
if ~strcmp(e.identifier,'MATLAB:UndefinedFunction') |
|
|
1223 |
% if we got some error aside from dipfitdefs not being present, rethrow it |
|
|
1224 |
rethrow(e); |
|
|
1225 |
end |
|
|
1226 |
end |
|
|
1227 |
else |
|
|
1228 |
EEG.dipfit = []; res = com; |
|
|
1229 |
end |
|
|
1230 |
|
|
|
1231 |
% check events (fast) |
|
|
1232 |
% ------------ |
|
|
1233 |
if isfield(EEG.event, 'type') |
|
|
1234 |
tmpevent = EEG.event(1:min(length(EEG.event), 100)); |
|
|
1235 |
if ~all(cellfun(@ischar, { tmpevent.type })) && ~all(cellfun(@isnumeric, { tmpevent.type })) |
|
|
1236 |
disp('Warning: converting all event types to strings'); |
|
|
1237 |
for ind = 1:length(EEG.event) |
|
|
1238 |
EEG.event(ind).type = num2str(EEG.event(ind).type); |
|
|
1239 |
end |
|
|
1240 |
EEG = eeg_checkset(EEG, 'eventconsistency'); |
|
|
1241 |
end |
|
|
1242 |
end |
|
|
1243 |
|
|
|
1244 |
% EEG.times (only for epoched datasets) |
|
|
1245 |
% --------- |
|
|
1246 |
if ~isfield(EEG, 'times') || isempty(EEG.times) || length(EEG.times) ~= EEG.pnts |
|
|
1247 |
EEG.times = linspace(EEG.xmin*1000, EEG.xmax*1000, EEG.pnts); |
|
|
1248 |
EEG.saved = 'no'; |
|
|
1249 |
end |
|
|
1250 |
|
|
|
1251 |
if ~isfield(EEG, 'history'), EEG.history = ''; res = com; end |
|
|
1252 |
if ~isfield(EEG, 'splinefile'), EEG.splinefile = ''; res = com; end |
|
|
1253 |
if ~isfield(EEG, 'icasplinefile'), EEG.icasplinefile = ''; res = com; end |
|
|
1254 |
if ~isfield(EEG, 'saved'), EEG.saved = 'no'; res = com; end |
|
|
1255 |
if ~isfield(EEG, 'subject'), EEG.subject = ''; res = com; end |
|
|
1256 |
if ~isfield(EEG, 'condition'), EEG.condition = ''; res = com; end |
|
|
1257 |
if ~isfield(EEG, 'group'), EEG.group = ''; res = com; end |
|
|
1258 |
if ~isfield(EEG, 'run'), EEG.run = []; res = com; end |
|
|
1259 |
if ~isfield(EEG, 'session'), EEG.session = []; res = com; end |
|
|
1260 |
if ~isfield(EEG, 'urchanlocs'), EEG.urchanlocs = []; res = com; end |
|
|
1261 |
if ~isfield(EEG, 'specdata'), EEG.specdata = []; res = com; end |
|
|
1262 |
if ~isfield(EEG, 'specicaact'), EEG.specicaact = []; res = com; end |
|
|
1263 |
if ~isfield(EEG, 'comments'), EEG.comments = ''; res = com; end |
|
|
1264 |
if ~isfield(EEG, 'etc' ), EEG.etc = []; res = com; end |
|
|
1265 |
if ~isfield(EEG, 'urevent' ), EEG.urevent = []; res = com; end |
|
|
1266 |
if ~isfield(EEG, 'datfile' ), EEG.datfile = ''; res = com; end |
|
|
1267 |
if ~isfield(EEG, 'roi' ), EEG.roi = []; res = com; end |
|
|
1268 |
if ~isfield(EEG, 'ref') || isempty(EEG.ref), EEG.ref = 'common'; res = com; end |
|
|
1269 |
|
|
|
1270 |
% create fields if absent |
|
|
1271 |
% ----------------------- |
|
|
1272 |
if ~isfield(EEG, 'reject'), EEG.reject.rejjp = []; res = com; end |
|
|
1273 |
|
|
|
1274 |
listf = { 'rejjp' 'rejkurt' 'rejmanual' 'rejthresh' 'rejconst', 'rejfreq' ... |
|
|
1275 |
'icarejjp' 'icarejkurt' 'icarejmanual' 'icarejthresh' 'icarejconst', 'icarejfreq'}; |
|
|
1276 |
for index = 1:length(listf) |
|
|
1277 |
name = listf{index}; |
|
|
1278 |
elecfield = [name 'E']; |
|
|
1279 |
if ~isfield(EEG.reject, elecfield), EEG.reject.(elecfield) = []; res = com; end |
|
|
1280 |
if ~isfield(EEG.reject, name) |
|
|
1281 |
EEG.reject.(name) = []; |
|
|
1282 |
res = com; |
|
|
1283 |
elseif ~isempty(EEG.reject.(name)) && isempty(EEG.reject.(elecfield)) |
|
|
1284 |
% check if electrode array is empty with rejection array is not |
|
|
1285 |
nbchan = fastif(strcmp(name, 'ica'), size(EEG.icaweights,1), EEG.nbchan); |
|
|
1286 |
EEG.reject = setfield(EEG.reject, elecfield, zeros(nbchan, length(getfield(EEG.reject, name)))); res = com; |
|
|
1287 |
end |
|
|
1288 |
end |
|
|
1289 |
if ~isfield(EEG.reject, 'rejglobal'), EEG.reject.rejglobal = []; res = com; end |
|
|
1290 |
if ~isfield(EEG.reject, 'rejglobalE'), EEG.reject.rejglobalE = []; res = com; end |
|
|
1291 |
|
|
|
1292 |
% track version of EEGLAB |
|
|
1293 |
% ----------------------- |
|
|
1294 |
tmpvers = eeg_getversion; |
|
|
1295 |
if ~isfield(EEG.etc, 'eeglabvers') || ~isequal(EEG.etc.eeglabvers, tmpvers) |
|
|
1296 |
EEG.etc.eeglabvers = tmpvers; |
|
|
1297 |
EEG = eeg_hist( EEG, ['EEG.etc.eeglabvers = ''' tmpvers '''; % this tracks which version of EEGLAB is being used, you may ignore it'] ); |
|
|
1298 |
res = com; |
|
|
1299 |
end |
|
|
1300 |
|
|
|
1301 |
% default colors for rejection |
|
|
1302 |
% ---------------------------- |
|
|
1303 |
if ~isfield(EEG.reject, 'rejmanualcol'), EEG.reject.rejmanualcol = [1.0000 1 0.783]; res = com; end |
|
|
1304 |
if ~isfield(EEG.reject, 'rejthreshcol'), EEG.reject.rejthreshcol = [0.8487 1.0000 0.5008]; res = com; end |
|
|
1305 |
if ~isfield(EEG.reject, 'rejconstcol'), EEG.reject.rejconstcol = [0.6940 1.0000 0.7008]; res = com; end |
|
|
1306 |
if ~isfield(EEG.reject, 'rejjpcol'), EEG.reject.rejjpcol = [1.0000 0.6991 0.7537]; res = com; end |
|
|
1307 |
if ~isfield(EEG.reject, 'rejkurtcol'), EEG.reject.rejkurtcol = [0.6880 0.7042 1.0000]; res = com; end |
|
|
1308 |
if ~isfield(EEG.reject, 'rejfreqcol'), EEG.reject.rejfreqcol = [0.9596 0.7193 1.0000]; res = com; end |
|
|
1309 |
if ~isfield(EEG.reject, 'disprej'), EEG.reject.disprej = { }; end |
|
|
1310 |
|
|
|
1311 |
if ~isfield(EEG, 'stats'), EEG.stats.jp = []; res = com; end |
|
|
1312 |
if ~isfield(EEG.stats, 'jp'), EEG.stats.jp = []; res = com; end |
|
|
1313 |
if ~isfield(EEG.stats, 'jpE'), EEG.stats.jpE = []; res = com; end |
|
|
1314 |
if ~isfield(EEG.stats, 'icajp'), EEG.stats.icajp = []; res = com; end |
|
|
1315 |
if ~isfield(EEG.stats, 'icajpE'), EEG.stats.icajpE = []; res = com; end |
|
|
1316 |
if ~isfield(EEG.stats, 'kurt'), EEG.stats.kurt = []; res = com; end |
|
|
1317 |
if ~isfield(EEG.stats, 'kurtE'), EEG.stats.kurtE = []; res = com; end |
|
|
1318 |
if ~isfield(EEG.stats, 'icakurt'), EEG.stats.icakurt = []; res = com; end |
|
|
1319 |
if ~isfield(EEG.stats, 'icakurtE'), EEG.stats.icakurtE = []; res = com; end |
|
|
1320 |
|
|
|
1321 |
% component rejection |
|
|
1322 |
% ------------------- |
|
|
1323 |
if ~isfield(EEG.stats, 'compenta'), EEG.stats.compenta = []; res = com; end |
|
|
1324 |
if ~isfield(EEG.stats, 'compentr'), EEG.stats.compentr = []; res = com; end |
|
|
1325 |
if ~isfield(EEG.stats, 'compkurta'), EEG.stats.compkurta = []; res = com; end |
|
|
1326 |
if ~isfield(EEG.stats, 'compkurtr'), EEG.stats.compkurtr = []; res = com; end |
|
|
1327 |
if ~isfield(EEG.stats, 'compkurtdist'), EEG.stats.compkurtdist = []; res = com; end |
|
|
1328 |
if ~isfield(EEG.reject, 'threshold'), EEG.reject.threshold = [0.8 0.8 0.8]; res = com; end |
|
|
1329 |
if ~isfield(EEG.reject, 'threshentropy'), EEG.reject.threshentropy = 600; res = com; end |
|
|
1330 |
if ~isfield(EEG.reject, 'threshkurtact'), EEG.reject.threshkurtact = 600; res = com; end |
|
|
1331 |
if ~isfield(EEG.reject, 'threshkurtdist'), EEG.reject.threshkurtdist = 600; res = com; end |
|
|
1332 |
if ~isfield(EEG.reject, 'gcompreject'), EEG.reject.gcompreject = []; res = com; end |
|
|
1333 |
if length(EEG.reject.gcompreject) ~= size(EEG.icaweights,1) |
|
|
1334 |
EEG.reject.gcompreject = zeros(1, size(EEG.icaweights,1)); |
|
|
1335 |
end |
|
|
1336 |
|
|
|
1337 |
% remove old fields |
|
|
1338 |
% ----------------- |
|
|
1339 |
if isfield(EEG, 'averef'), EEG = rmfield(EEG, 'averef'); end |
|
|
1340 |
if isfield(EEG, 'rt' ), EEG = rmfield(EEG, 'rt'); end |
|
|
1341 |
|
|
|
1342 |
% store in new structure |
|
|
1343 |
% ---------------------- |
|
|
1344 |
if isstruct(EEG) |
|
|
1345 |
if ~exist('ALLEEGNEW','var') |
|
|
1346 |
ALLEEGNEW = EEG; |
|
|
1347 |
else |
|
|
1348 |
ALLEEGNEW(inddataset) = EEG; |
|
|
1349 |
end |
|
|
1350 |
end |
|
|
1351 |
end |
|
|
1352 |
|
|
|
1353 |
% recorder fields |
|
|
1354 |
% --------------- |
|
|
1355 |
fieldorder = { 'setname' ... |
|
|
1356 |
'filename' ... |
|
|
1357 |
'filepath' ... |
|
|
1358 |
'subject' ... |
|
|
1359 |
'group' ... |
|
|
1360 |
'condition' ... |
|
|
1361 |
'session' ... |
|
|
1362 |
'comments' ... |
|
|
1363 |
'nbchan' ... |
|
|
1364 |
'trials' ... |
|
|
1365 |
'pnts' ... |
|
|
1366 |
'srate' ... |
|
|
1367 |
'xmin' ... |
|
|
1368 |
'xmax' ... |
|
|
1369 |
'times' ... |
|
|
1370 |
'data' ... |
|
|
1371 |
'icaact' ... |
|
|
1372 |
'icawinv' ... |
|
|
1373 |
'icasphere' ... |
|
|
1374 |
'icaweights' ... |
|
|
1375 |
'icachansind' ... |
|
|
1376 |
'chanlocs' ... |
|
|
1377 |
'urchanlocs' ... |
|
|
1378 |
'chaninfo' ... |
|
|
1379 |
'ref' ... |
|
|
1380 |
'event' ... |
|
|
1381 |
'urevent' ... |
|
|
1382 |
'eventdescription' ... |
|
|
1383 |
'epoch' ... |
|
|
1384 |
'epochdescription' ... |
|
|
1385 |
'reject' ... |
|
|
1386 |
'stats' ... |
|
|
1387 |
'specdata' ... |
|
|
1388 |
'specicaact' ... |
|
|
1389 |
'splinefile' ... |
|
|
1390 |
'icasplinefile' ... |
|
|
1391 |
'dipfit' ... |
|
|
1392 |
'history' ... |
|
|
1393 |
'saved' ... |
|
|
1394 |
'etc' }; |
|
|
1395 |
|
|
|
1396 |
for fcell = fieldnames(EEG)' |
|
|
1397 |
fname = fcell{1}; |
|
|
1398 |
if ~any(strcmp(fieldorder,fname)) |
|
|
1399 |
fieldorder{end+1} = fname; |
|
|
1400 |
end |
|
|
1401 |
end |
|
|
1402 |
|
|
|
1403 |
try |
|
|
1404 |
ALLEEGNEW = orderfields(ALLEEGNEW, fieldorder); |
|
|
1405 |
catch |
|
|
1406 |
disp('Couldn''t order data set fields properly.'); |
|
|
1407 |
end |
|
|
1408 |
|
|
|
1409 |
if exist('ALLEEGNEW','var') |
|
|
1410 |
EEGFINAL = ALLEEGNEW; |
|
|
1411 |
end |
|
|
1412 |
|
|
|
1413 |
if ~isa(EEG, 'eegobj') && option_eegobject |
|
|
1414 |
EEGFINAL = eegobj(EEG); |
|
|
1415 |
end |
|
|
1416 |
|
|
|
1417 |
return; |
|
|
1418 |
|
|
|
1419 |
function num = popask( text ) |
|
|
1420 |
ButtonName=questdlg2( text, ... |
|
|
1421 |
'Confirmation', 'Cancel', 'Yes','Yes'); |
|
|
1422 |
switch lower(ButtonName), |
|
|
1423 |
case 'cancel', num = 0; |
|
|
1424 |
case 'yes', num = 1; |
|
|
1425 |
end |
|
|
1426 |
|
|
|
1427 |
function res = mycellfun(com, vals, classtype); |
|
|
1428 |
res = zeros(1, length(vals)); |
|
|
1429 |
switch com |
|
|
1430 |
case 'isempty', |
|
|
1431 |
for index = 1:length(vals), res(index) = isempty(vals{index}); end |
|
|
1432 |
case 'isclass' |
|
|
1433 |
if strcmp(classtype, 'double') |
|
|
1434 |
for index = 1:length(vals), res(index) = isnumeric(vals{index}); end |
|
|
1435 |
else |
|
|
1436 |
error('unknown cellfun command'); |
|
|
1437 |
end |
|
|
1438 |
otherwise error('unknown cellfun command'); |
|
|
1439 |
end |
|
|
1440 |
|
|
|
1441 |
|