Switch to unified view

a b/functions/adminfunc/eeg_getdatact.m
1
% EEG_GETDATACT - get EEG data from a specified dataset or
2
%                  component activity
3
%
4
% Usage:
5
%       >> signal = eeg_getdatact( EEG );
6
%       >> signal = eeg_getdatact( EEG, 'key', 'val');
7
%
8
% Inputs:
9
%   EEG       - Input dataset
10
%
11
% Optional input:
12
%   'channel'   - [integer array] read only specific channels.
13
%                 Default is to read all data channels.
14
%   'component' - [integer array] read only specific components
15
%   'projchan'  - [integer or cell array] channel(s) onto which the component
16
%                 should be projected.
17
%   'rmcomps'   - [integer array] remove selected components from data
18
%                 channels. This is only to be used with channel data not
19
%                 when selecting components.
20
%   'trialindices' - [integer array] only read specific trials. Default is
21
%                 to read all trials.
22
%   'samples'   - [integer array] only read specific samples. Default is
23
%                 to read all samples.
24
%   'reshape'   - ['2d'|'3d'] reshape data. Default is '3d' when possible.
25
%   'verbose'   - ['on'|'off'] verbose mode. Default is 'on'.
26
%
27
% Outputs:
28
%   signal      - EEG data or component activity
29
%
30
% Author: Arnaud Delorme, SCCN & CERCO, CNRS, 2008-
31
%
32
% See also: EEG_CHECKSET
33
34
% Copyright (C) 15 Feb 2002 Arnaud Delorme, Salk Institute, arno@salk.edu
35
%
36
% This file is part of EEGLAB, see http://www.eeglab.org
37
% for the documentation and details.
38
%
39
% Redistribution and use in source and binary forms, with or without
40
% modification, are permitted provided that the following conditions are met:
41
%
42
% 1. Redistributions of source code must retain the above copyright notice,
43
% this list of conditions and the following disclaimer.
44
%
45
% 2. Redistributions in binary form must reproduce the above copyright notice,
46
% this list of conditions and the following disclaimer in the documentation
47
% and/or other materials provided with the distribution.
48
%
49
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
50
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
53
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
59
% THE POSSIBILITY OF SUCH DAMAGE.
60
61
function [data, boundaries] = eeg_getdatact( EEG, varargin)
62
63
data = [];
64
if nargin < 1
65
    help eeg_getdatact;
66
    return;
67
end
68
69
% reading data from several datasets and concatenating it
70
% -------------------------------------------------------
71
if iscell(EEG) || (~ischar(EEG) && length(EEG) > 1)
72
    % decode some arguments
73
    % ---------------------
74
    trials  = cell(1,length(EEG));
75
    rmcomps = cell(1,length(EEG));
76
    for iArg = length(varargin)-1:-2:1
77
        if strcmpi(varargin{iArg}, 'trialindices')
78
            trials = varargin{iArg+1};
79
            varargin(iArg:iArg+1) = [];
80
        elseif strcmpi(varargin{iArg}, 'rmcomps')
81
            rmcomps = varargin{iArg+1};
82
            varargin(iArg:iArg+1) = [];
83
        end
84
    end
85
    if isnumeric(rmcomps), rmtmp = rmcomps; rmcomps = cell(1,length(EEG)); rmcomps(:) = { rmtmp }; end
86
        
87
    % concatenate datasets
88
    % --------------------
89
    data = [];
90
    boundaries = [];
91
    for dat = 1:length(EEG)
92
        if iscell(EEG)
93
             [tmpdata, datboundaries] = eeg_getdatact(EEG{dat}, 'trialindices', trials{dat}, 'rmcomps', rmcomps{dat}, varargin{:} );
94
        else [tmpdata, datboundaries] = eeg_getdatact(EEG(dat), 'trialindices', trials{dat}, 'rmcomps', rmcomps{dat}, varargin{:} );
95
        end
96
        if isempty(data)
97
            data       = tmpdata;
98
            boundaries = datboundaries;
99
        else
100
            if (isstruct(EEG) && all([EEG.trials] == 1)) || size(tmpdata,3) == 1 || size(data,2) ~= size(tmpdata,2) % continuous data (if same number of data points, consider 1 trial dataset)
101
                if size(tmpdata,3) ~= 1 || size(data,3) ~= 1, error('Trying to concatenate continuous and epoched datasets'); end
102
                if size(data,1) ~= size(tmpdata,1), error('Datasets to be concatenated do not have the same number of channels'); end
103
104
                % adding boundaries
105
                if ~isempty(datboundaries)
106
                    boundaries = [boundaries datboundaries size(data,2)];
107
                else
108
                    boundaries = [boundaries size(data,2)];
109
                end
110
                data(:,end+1:end+size(tmpdata,2)) = tmpdata; % concatenating trials
111
            else
112
                if size(data,1) ~= size(tmpdata,1), error('Datasets to be concatenated do not have the same number of channels'); end
113
                if size(data,2) ~= size(tmpdata,2), error('Datasets to be concatenated do not have the same number of time points'); end
114
                data(:,:,end+1:end+size(tmpdata,3)) = tmpdata; % concatenating trials
115
            end
116
        end
117
    end
118
    return;
119
end
120
121
% if string load dataset
122
% ----------------------
123
if ischar(EEG)
124
    EEG = pop_loadset('filename', EEG, 'loadmode', 'info');
125
end
126
127
opt = finputcheck(varargin, { ...
128
    'channel'   'integer' {} [];
129
    'verbose'   'string'  { 'on','off' } 'on';
130
    'reshape'   'string'  { '2d','3d' }  '3d';
131
    'projchan'  {'integer','cell' } { {} {} } [];
132
    'component' 'integer' {} [];
133
    'samples'   'integer' {} [];
134
    'interp'    'struct'  { }        struct([]);
135
    'trialindices' {'integer','cell'} { {} {} } [];
136
    'rmcomps'      {'integer','cell'} { {} {} } [] }, 'eeg_getdatact');
137
138
if ischar(opt), error(opt); end
139
channelNotDefined = 0;
140
if isempty(opt.channel)
141
    opt.channel = [1:EEG.nbchan]; 
142
    channelNotDefined = 1;
143
elseif isequal(opt.channel, [1:EEG.nbchan]) && ~isempty(opt.interp)
144
    channelNotDefined = 1;
145
end
146
if iscell( opt.trialindices), opt.trialindices = opt.trialindices{1}; end
147
if isempty(opt.trialindices), opt.trialindices = [1:EEG.trials]; end
148
if iscell(opt.rmcomps     ), opt.rmcomps      = opt.rmcomps{1};      end
149
if (~isempty(opt.rmcomps) || ~isempty(opt.component)) && isempty(EEG.icaweights)
150
    error('No ICA weight in dataset');
151
end
152
153
if strcmpi(EEG.data, 'in set file')
154
    EEGTMP = pop_loadset('filename', EEG.filename, 'filepath', EEG.filepath, 'verbose', 'off');
155
    EEG.data = EEGTMP.data;
156
end
157
158
% get data boundaries if continuous data
159
% --------------------------------------
160
boundaries = [];
161
if nargout > 1 && EEG.trials == 1 && ~isempty(EEG.event) && isfield(EEG.event, 'type') && ischar(EEG.event(1).type)
162
    if ~isempty(opt.samples)
163
        disp('WARNING: eeg_getdatact.m, boundaries are not accurate when selecting data samples');
164
    end
165
    tmpevent = EEG.event;
166
    tmpbound = strmatch('boundary', lower({ tmpevent.type }));
167
    if ~isempty(tmpbound)
168
        boundaries = [tmpevent(tmpbound).latency ]-0.5;
169
    end
170
end
171
172
% getting channel or component activation
173
% ---------------------------------------
174
filename = fullfile(EEG.filepath, [ EEG.filename(1:end-4) '.icaact' ] );
175
if ~isempty(opt.component) && ~isempty(EEG.icaact)
176
    
177
    data = EEG.icaact(opt.component,:,:);
178
    
179
elseif ~isempty(opt.component) && exist(filename)
180
    
181
    % reading ICA file
182
    % ----------------
183
    data = repmat(single(0), [ length(opt.component) EEG.pnts EEG.trials ]);
184
    fid = fopen( filename, 'r', 'ieee-le'); %little endian (see also pop_saveset)
185
    if fid == -1, error( ['file ' filename ' could not be open' ]); end
186
    for ind = 1:length(opt.component)
187
        fseek(fid, (opt.component(ind)-1)*EEG.pnts*EEG.trials*4, -1);
188
        data(ind,:) = fread(fid, [EEG.trials*EEG.pnts 1], 'float32')';
189
    end
190
    fclose(fid);
191
    
192
elseif ~isempty(opt.component)
193
    
194
    if isempty(EEG.icaact)
195
        data = eeg_getdatact( EEG );
196
        data = (EEG.icaweights(opt.component,:)*EEG.icasphere)*data(EEG.icachansind,:);
197
    else
198
        data = EEG.icaact(opt.component,:,:);
199
    end
200
    
201
else
202
    if isnumeric(EEG.data) % channel
203
    
204
        data = EEG.data;
205
    
206
    else % channel but no data loaded string
207
        
208
        [~,EEG.data,ext] = fileparts(EEG.data); % remove path if present
209
        EEG.data = [ EEG.data ext];
210
        filename = fullfile(EEG.filepath, EEG.data);
211
        fid = fopen( filename, 'r', 'ieee-le'); %little endian (see also pop_saveset)
212
        if fid == -1
213
            filename = fullfile(EEG.data);
214
            fid = fopen( filename, 'r', 'ieee-le'); %little endian (see also pop_saveset)
215
            if fid == -1
216
                filename = fullfile(EEG.filepath, [EEG.filename(1:end-3) 'fdt' ]);
217
                fid = fopen( filename, 'r', 'ieee-le'); %little endian (see also pop_saveset)
218
                if fid == -1
219
                    error( ['file ' filename ' not found. If you have renamed/moved' 10 ...
220
                        'the .set file, you must also rename/move the associated data file.' ]);
221
                end
222
            end
223
        end
224
        if strcmpi(opt.verbose, 'on')
225
            fprintf('Reading float file ''%s''...\n', filename);
226
        end
227
228
        % old format = .fdt; new format = .dat (transposed)
229
        % -------------------------------------------------
230
        datformat = 0;
231
        if length(filename) > 3
232
            if strcmpi(filename(end-2:end), 'dat')
233
                datformat = 1;
234
            end
235
        end
236
        EEG.datfile = EEG.data;
237
238
        % reading data file
239
        % -----------------
240
        eeglab_options;
241
        if length(opt.channel) == EEG.nbchan && option_memmapdata
242
            fclose(fid);
243
            data = mmo(filename, [EEG.nbchan EEG.pnts EEG.trials], false);
244
            %data = memmapdata(filename, [EEG.nbchan EEG.pnts EEG.trials]);
245
        else
246
            if datformat
247
                if length(opt.channel) == EEG.nbchan || ~isempty(opt.interp)
248
                    data = fread(fid, [EEG.trials*EEG.pnts EEG.nbchan], 'float32')';
249
                else
250
                    data = repmat(single(0), [ length(opt.channel) EEG.pnts EEG.trials ]);
251
                    for ind = 1:length(opt.channel)
252
                        fseek(fid, (opt.channel(ind)-1)*EEG.pnts*EEG.trials*4, -1);
253
                        data(ind,:) = fread(fid, [EEG.trials*EEG.pnts 1], 'float32')';
254
                    end
255
                    opt.channel = [1:size(data,1)];
256
                end
257
            else
258
                data = fread(fid, [EEG.nbchan Inf], 'float32');
259
            end
260
            fclose(fid);
261
        end
262
        
263
    end
264
    
265
    % subtracting components from data
266
    % --------------------------------
267
    if ~isempty(opt.rmcomps)
268
        if strcmpi(opt.verbose, 'on')
269
            fprintf('Removing %d artifactual components\n', length(opt.rmcomps));
270
        end
271
        rmcomps = eeg_getdatact( EEG, 'component', opt.rmcomps); % loaded from file
272
        rmchan    = [];
273
        rmchanica = [];
274
        for index = 1:length(opt.channel)
275
            tmpicaind = find(opt.channel(index) == EEG.icachansind);
276
            if ~isempty(tmpicaind)
277
                rmchan    = [ rmchan    index ];
278
                rmchanica = [ rmchanica tmpicaind ];
279
            end
280
        end
281
        data(rmchan,:) = data(rmchan,:) - EEG.icawinv(rmchanica,opt.rmcomps)*rmcomps(:,:);
282
        
283
        %EEG = eeg_checkset(EEG, 'loaddata');
284
        %EEG = pop_subcomp(EEG, opt.rmcomps);
285
        %data = EEG.data(opt.channel,:,:);
286
        
287
        %if strcmpi(EEG.subject, 'julien') & strcmpi(EEG.condition, 'oddball') & strcmpi(EEG.group, 'after')
288
        %    jjjjf
289
        %end
290
    end
291
    
292
    if ~isempty(opt.interp)
293
        EEG.data   = data;
294
        EEG.event  = [];
295
        EEG.epoch  = [];
296
        EEG = eeg_interp(EEG, opt.interp, 'spherical');
297
        data = EEG.data;
298
        if channelNotDefined, opt.channel = [1:EEG.nbchan]; end
299
    end
300
301
    if ~isequal(opt.channel, [1:EEG.nbchan])
302
        data = data(intersect(opt.channel,[1:EEG.nbchan]),:,:);
303
    end
304
end
305
306
307
% projecting components on data channels
308
% --------------------------------------
309
if ~isempty(opt.projchan)
310
    if iscell(opt.projchan)
311
        opt.projchan = std_chaninds(EEG, opt.projchan);
312
    end
313
    
314
    finalChanInds = [];
315
    for iChan = 1:length(opt.projchan)
316
        tmpInd = find(EEG.icachansind == opt.projchan(iChan));
317
        if isempty(tmpInd)
318
            error(sprintf('Warning: can not backproject component on channel %d (not used for ICA)\n', opt.projchan(iChan)));
319
        end
320
        finalChanInds = [ finalChanInds tmpInd ];
321
    end
322
    
323
    data = EEG.icawinv(finalChanInds, opt.component)*data(:,:);
324
end
325
326
if size(data,2)*size(data,3) ~= EEG.pnts*EEG.trials
327
    disp('WARNING: The file size on disk does not correspond to the dataset, file has been truncated');
328
end
329
try
330
    if EEG.trials == 1, EEG.pnts = size(data,2); end
331
    if  strcmpi(opt.reshape, '3d')
332
         data = reshape(data, size(data,1), EEG.pnts, EEG.trials);
333
    else data = reshape(data, size(data,1), EEG.pnts*EEG.trials);
334
    end
335
catch
336
    error('The file size on disk does not correspond to the dataset information.');
337
end
338
339
% select trials
340
% -------------
341
if length(opt.trialindices) ~= EEG.trials
342
    data = data(:,:,opt.trialindices);
343
end
344
if ~isempty(opt.samples)
345
    data = data(:,opt.samples,:);
346
end