Switch to unified view

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