Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
eeglab/functions/popfunc/pop_select.m
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
738 lines (678 sloc)
31.6 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% POP_SELECT - given an input EEG dataset structure, output a new EEG data structure | |
% retaining and/or excluding specified time/latency, data point, channel, | |
% and/or epoch range(s). | |
% Usage: | |
% >> OUTEEG = pop_select(INEEG, 'key1', value1, 'key2', value2 ...); | |
% | |
% Graphic interface: | |
% "Time range" - [edit box] RETAIN only the indicated epoch latency or continuous data | |
% time range: [low high] in ms, inclusive. For continuous data, several | |
% time ranges may be specified, separated by semicolons. | |
% Example: "5 10; 12 EEG.xmax" will retain the indicated | |
% stretches of continuous data, and remove data portions outside | |
% the indicated ranges, e.g. from 0 s to 5 s and from 10 s to 12 s. | |
% Command line equivalent: 'time' (or 'notime' - see below) | |
% "Time range" - [checkbox] EXCLUDE the indicated latency range(s) from the data. | |
% For epoched data, it is not possible to remove a range of latencies | |
% from the middle of the epoch, so either the low and/or the high values | |
% in the specified latency range (see above) must be at an epoch boundary | |
% (EEG.xmin, EEGxmax). Command line equivalent: [if checked] 'notime' | |
% "Point range" - [edit box] RETAIN the indicated data point range(s). | |
% Same options as for the "Time range" features (above). | |
% Command line equivalent: 'point' (or 'nopoint' - see below). | |
% "Point range" - [checkbox] EXCLUDE the indicated point range(s). | |
% Command line equivalent: [if checked] 'nopoint' | |
% "Epoch range" - [edit box] RETAIN the indicated data epoch indices in the dataset. | |
% This checkbox is only visible for epoched datasets. | |
% Command line equivalent: 'trial' (or 'notrial' - see below) | |
% "Epoch range" - [checkbox] EXCLUDE the specified data epochs. | |
% Command line equivalent: [if checked] 'notrial' | |
% "Channel range" - [edit box] RETAIN the indicated vector of data channels | |
% Command line equivalent: 'channel' (or 'nochannel' - see below) | |
% "Channel range" - [checkbox] EXCLUDE the indicated channels. | |
% Command line equivalent: [if checked] 'nochannel' | |
% "..." - [button] select channels by name. | |
% "Scroll dataset" - [button] call the EEGPLOT function to scroll the | |
% channel activities in a new window for visual inspection. | |
% Commandline equivalent: EEGPLOT - see its help for details. | |
% Inputs: | |
% INEEG - input EEG dataset structure | |
% | |
% Optional inputs | |
% 'time' - [min max] in seconds. Epoch latency or continuous data time range | |
% to retain in the new dataset, (Note: not ms, as in the GUI text entry | |
% above). For continuous data (only), several time ranges can be specified, | |
% separated by semicolons. Example: "5 10; 12 EEG.xmax" will retain | |
% the indicated times ranges, removing data outside the indicated ranges | |
% e.g. here from 0 to 5 s and from 10 s to 12 s. (See also, 'notime') | |
% 'rmtime' - [min max] in seconds. Epoch latency or continuous dataset time range | |
% to exclude from the new dataset. For continuous data, may be | |
% [min1 max1; min2 max2; ...] to exclude several time ranges. For epoched | |
% data, the latency range must include an epoch boundary, as latency | |
% ranges in the middle of epochs cannot be removed from epoched data. | |
% 'point' - [min max] epoch or continuous data point range to retain in the new | |
% dataset. For continuous datasets, this may be [min1 max1; min2 max2; ...] | |
% to retain several point ranges. (Notes: If both 'point'/'nopoint' and | |
% 'time' | 'notime' are specified, the 'point' limit values take precedence. | |
% The 'point' argument was originally a point vector, now deprecated). | |
% 'rmpoint' - [min max] epoch or continuous data point range to exclude in the new dataset. | |
% For epoched data, the point range must include either the first (0) | |
% or the last point (EEG.pnts), as a central point range cannot be removed. | |
% 'trial' - [integer array] array of trial indices to retain in the new dataset | |
% 'rmtrial' - [integer array] array of trial indices to exclude from the new dataset | |
% 'sorttrial' - ['on'|'off'] sort trial indices before extracting them (default: 'on'). | |
% 'checkchans' - ['on'|'off'] check that channels are present before | |
% rejecting them (default: 'on') | |
% 'channel' - vector of channel indices to retain in the new | |
% dataset. Can also be a cell array of channel names. | |
% 'rmchannel' - vector of channel indices to exclude from the new | |
% dataset. Can also be a cell array of channel names. | |
% 'chantype' - [string|cell] list of channel types to keep | |
% 'rmchantype' - [string|cell] list of channel types to remove | |
% | |
% Outputs: | |
% OUTEEG - new EEG dataset structure | |
% | |
% Note: This function performs a conjunction (AND) of all its optional inputs. | |
% Using negative counterparts of all options, any logical combination is | |
% possible. Legacy input 'notrial', 'notime', 'nochannel', 'nopoint' | |
% are still supported. | |
% | |
% Author: Arnaud Delorme, CNL/Salk Institute, 2001; SCCN/INC/UCSD, 2002- | |
% | |
% see also: EEGLAB | |
% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu | |
% | |
% This file is part of EEGLAB, see http://www.eeglab.org | |
% for the documentation and details. | |
% | |
% Redistribution and use in source and binary forms, with or without | |
% modification, are permitted provided that the following conditions are met: | |
% | |
% 1. Redistributions of source code must retain the above copyright notice, | |
% this list of conditions and the following disclaimer. | |
% | |
% 2. Redistributions in binary form must reproduce the above copyright notice, | |
% this list of conditions and the following disclaimer in the documentation | |
% and/or other materials provided with the distribution. | |
% | |
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
% THE POSSIBILITY OF SUCH DAMAGE. | |
% 01-25-02 reformated help & license -ad | |
% 01-26-02 changed the format for events and trial conditions -ad | |
% 02-04-02 changed display format and allow for negation of inputs -ad | |
% 02-17-02 removed the event removal -ad | |
% 03-17-02 added channel info subsets selection -ad | |
% 03-21-02 added event latency recalculation -ad | |
function [EEG, com] = pop_select( EEG, varargin) | |
com = ''; | |
if nargin < 1 | |
help pop_select; | |
return; | |
end | |
if isempty(EEG(1).data) | |
disp('Pop_select error: cannot process empty dataset'); return; | |
end | |
if nargin < 2 | |
geometry = { [1 1 1] [1 1 0.25 0.23 0.51] [1 1 0.25 0.23 0.51] [1 1 0.25 0.23 0.51] [1 1 0.25 0.23 0.51] ... | |
[1 1 0.25 0.23 0.51] [1] [1 1 1]}; | |
enabletype = ~isempty(EEG(1).chanlocs) && isfield(EEG(1).chanlocs, 'type') && ~isempty(EEG(1).chanlocs(1).type); | |
uilist = { ... | |
{ 'Style', 'text', 'string', 'Select data in:', 'fontweight', 'bold' }, ... | |
{ 'Style', 'text', 'string', 'Input desired range', 'fontweight', 'bold' }, ... | |
{ 'Style', 'text', 'string', 'on->remove these', 'fontweight', 'bold' }, ... | |
{ 'Style', 'text', 'string', 'Time range [min max] (s)', 'fontangle', fastif(length(EEG)>1, 'italic', 'normal') }, ... | |
{ 'Style', 'edit', 'string', '', 'enable', 'on' }, ... | |
{ }, { 'Style', 'checkbox', 'string', ' ', 'enable', 'on' },{ }, ... | |
... | |
{ 'Style', 'text', 'string', 'Point range (ex: [1 10])', 'fontangle', fastif(length(EEG)>1, 'italic', 'normal') }, ... | |
{ 'Style', 'edit', 'string', '', 'enable', 'on' }, ... | |
{ }, { 'Style', 'checkbox', 'string', ' ', 'enable', 'on' },{ }, ... | |
... | |
{ 'Style', 'text', 'string', 'Epoch range (ex: 3:2:10)', 'fontangle', fastif(length(EEG)>1, 'italic', 'normal') }, ... | |
{ 'Style', 'edit', 'string', '', 'enable', 'on' }, ... | |
{ }, { 'Style', 'checkbox', 'string', ' ', 'enable', 'on' },{ }, ... | |
... | |
{ 'Style', 'text', 'string', 'Channel(s)' }, ... | |
{ 'Style', 'edit', 'string', '', 'tag', 'chans' }, ... | |
{ }, { 'Style', 'checkbox', 'string', ' ' }, ... | |
{ 'style' 'pushbutton' 'string' '...', 'enable' fastif(isempty(EEG(1).chanlocs), 'off', 'on') ... | |
'callback' 'pop_chansel(get(gcbf, ''userdata''), ''field'', ''labels'', ''handle'', findobj(''parent'', gcbf, ''tag'', ''chans''));' }, ... | |
... | |
{ 'Style', 'text', 'string', 'Channel type(s)' }, ... | |
{ 'Style', 'edit', 'string', '', 'tag', 'chantype' }, ... | |
{ }, { 'Style', 'checkbox', 'string', ' ' }, ... | |
{ 'style' 'pushbutton' 'string' '...', 'enable' fastif(enabletype, 'on', 'off') ... | |
'callback' 'pop_chansel(get(gcbf, ''userdata''), ''field'', ''type'', ''handle'', findobj(''parent'', gcbf, ''tag'', ''chantype''));' }, ... | |
... | |
{ }, { }, { 'Style', 'pushbutton', 'string', 'Scroll dataset', 'enable', fastif(length(EEG)>1, 'off', 'on'), 'callback', ... | |
'eegplot(EEG.data, ''srate'', EEG.srate, ''winlength'', 5, ''limits'', [EEG.xmin EEG.xmax]*1000, ''position'', [100 300 800 500], ''xgrid'', ''off'', ''eloc_file'', EEG.chanlocs);' } {}}; | |
% 'callback' 'tmplabels = get(gcbf, ''userdata''); [~, tmpvalchan] = pop_chansel(tmplabels, ''withindex'', ''on''); set(findobj(gcbf, ''tag'', ''chans''), ''string'',tmpvalchan); clear tmplabels tmpvalchan' }, ... | |
chanlocs = eeg_mergelocs(EEG.chanlocs); | |
results = inputgui( 'geometry', geometry, 'uilist', uilist, 'helpcom', 'pophelp(''pop_select'');', 'title', 'Select data -- pop_select()', 'userdata', chanlocs ); | |
if isempty(results), return; end | |
% decode inputs | |
% ------------- | |
args = {}; | |
if ~isempty( results{1} ) | |
if ~results{2}, args = { args{:}, 'time', eval( [ '[' results{1} ']' ] ) }; | |
else args = { args{:}, 'rmtime', eval( [ '[' results{1} ']' ] ) }; end | |
end | |
if ~isempty( results{3} ) | |
if ~results{4}, args = { args{:}, 'point', eval( [ '[' results{3} ']' ] ) }; | |
else args = { args{:}, 'rmpoint', eval( [ '[' results{3} ']' ] ) }; end | |
end | |
if ~isempty( results{5} ) | |
if ~results{6}, args = { args{:}, 'trial', eval( [ '[' results{5} ']' ] ) }; | |
else args = { args{:}, 'rmtrial', eval( [ '[' results{5} ']' ] ) }; end | |
end | |
if ~isempty( results{7} ) | |
[ chaninds, chanlist ] = eeg_decodechan(chanlocs, results{7}); | |
if isempty(chanlist) | |
if length(EEG) > 1 && length(unique([EEG.nbchan])) > 1 | |
error([ 'Cannot use channel indices when processing multiple datasets' 10 ... | |
'with some channels already removed' ]) | |
end | |
chanlist = chaninds; | |
end | |
if ~results{8}, args = { args{:}, 'channel' , chanlist }; | |
else args = { args{:}, 'rmchannel', chanlist }; end | |
end | |
if ~isempty( results{9} ) | |
[ ~, chantypes ] = eeg_decodechan(chanlocs, results{9}, 'type'); | |
if ~results{10}, args = { args{:}, 'chantype' , unique(chantypes) }; | |
else args = { args{:}, 'rmchantype', unique(chantypes) }; end | |
end | |
else | |
args = varargin; | |
end | |
% process multiple datasets | |
% ------------------------- | |
if length(EEG) > 1 | |
if nargin < 2 | |
[ EEG, com ] = eeg_eval( 'pop_select', EEG, 'warning', 'on', 'params', args); | |
else | |
[ EEG, com ] = eeg_eval( 'pop_select', EEG, 'warning', 'off', 'params',args); | |
end | |
return; | |
end | |
%----------------------------AMICA--------------------------------- | |
if isfield(EEG.etc,'amica') && isfield(EEG.etc.amica,'prob_added') | |
for index = 1:2:length(args) | |
if strcmpi(args{index}, 'channel') | |
args{index+1} = [ args{index+1} EEG.nbchan-(0:2*EEG.etc.amica.num_models-1)]; | |
end | |
end | |
end | |
%-------------------------------------------------------------------- | |
g = finputcheck(args, { 'time' 'real' [] []; ... | |
'notime' 'real' [] []; ... | |
'rmtime' 'real' [] []; ... | |
'trial' 'integer' [] [1:EEG.trials]; ... | |
'notrial' 'integer' [] []; ... | |
'rmtrial' 'integer' [] []; ... | |
'point' 'integer' [] []; ... | |
'nopoint' 'integer' [] []; ... | |
'rmpoint' 'integer' [] []; ... | |
'channel' { 'integer','cell' } [] []; | |
'nochannel' { 'integer','cell' } [] []; | |
'rmchannel' { 'integer','cell' } [] []; | |
'chantype' { 'string','cell' } [] {}; | |
'rmchantype' { 'string','cell' } [] {}; | |
'trialcond' 'integer' [] []; ... | |
'notrialcond' 'integer' [] []; ... | |
'sort' 'integer' [] []; ... | |
'sorttrial' 'string' { 'on','off' } 'on' }, 'pop_select'); | |
if ischar(g), error(g); end | |
if ~isempty(g.sort) | |
if g.sort, g.sorttrial = 'on'; | |
else g.sorttrial = 'off'; | |
end | |
end | |
if strcmpi(g.sorttrial, 'on') | |
g.trial = sort(setdiff( g.trial, g.notrial )); | |
if isempty(g.trial), error('Error: dataset %s is empty',EEG.filename); end | |
else | |
g.trial(ismember(g.trial,g.notrial)) = []; | |
% still warn about & remove duplicate trials (may be removed in the future) | |
[p,q] = unique_bc(g.trial); | |
if length(p) ~= length(g.trial) | |
disp('Warning: trial selection contained duplicated elements, which were removed.'); | |
end | |
g.trial = g.trial(sort(q)); | |
end | |
% rename parameters | |
% ----------------- | |
if ~isempty(g.rmtime) g.notime = g.rmtime; end | |
if ~isempty(g.rmpoint) g.nopoint = g.rmpoint; end | |
if ~isempty(g.rmtrial) g.notrial = g.rmtrial; end | |
if ~isempty(g.rmchannel) g.nochannel = g.rmchannel; end | |
% decode channels | |
% --------------- | |
if ~isempty(g.channel) || ~isempty(g.nochannel) | |
% find channels by name | |
if ~isempty(g.channel) | |
if ~isempty(g.chantype) || ~isempty(g.rmchantype) | |
error('You can select channels by name or by type but not both'); | |
end | |
inds = eeg_decodechan(EEG, g.channel, 'labels', true); | |
chanFlag = zeros(1, EEG.nbchan); | |
chanFlag(inds) = 1; | |
else | |
chanFlag = ones(1, EEG.nbchan); | |
end | |
if ~isempty(g.nochannel) | |
if ~isempty(g.chantype) || ~isempty(g.rmchantype) | |
error('You can select channels by name or by type but not both'); | |
end | |
inds = eeg_decodechan(EEG, g.nochannel, 'labels', true); | |
chanFlag(inds) = 0; | |
end | |
else | |
% find channels by type | |
if ~isempty(g.chantype) | |
inds = eeg_decodechan(EEG, g.chantype, 'type', true); | |
chanFlag = zeros(1, EEG.nbchan); | |
chanFlag(inds) = 1; | |
else | |
chanFlag = ones(1, EEG.nbchan); | |
end | |
if ~isempty(g.rmchantype) | |
inds = eeg_decodechan(EEG, g.rmchantype, 'type', true); | |
chanFlag(inds) = 0; | |
end | |
end | |
g.channel = find(chanFlag); | |
% time selection | |
% -------------- | |
if ~isempty(g.time) && (g.time(1) < EEG.xmin*1000) && (g.time(2) > EEG.xmax*1000) | |
error('Wrong time range'); | |
end | |
if min(g.trial) < 1 || max( g.trial ) > EEG.trials | |
error('Wrong trial range'); | |
end | |
if size(g.point,2) > 2 | |
g.point = [g.point(1) g.point(end)]; | |
disp('Warning: vector format for point range is deprecated'); | |
end | |
if size(g.nopoint,2) > 2 | |
g.nopoint = [g.nopoint(1) g.nopoint(end)]; | |
disp('Warning: vector format for point range is deprecated'); | |
end | |
if ~isempty( g.point ) | |
g.time = zeros(size(g.point)); | |
for index = 1:length(g.point(:)) | |
g.time(index) = eeg_point2lat(g.point(index), 1, EEG.srate, [EEG.xmin EEG.xmax]); | |
end | |
g.notime = []; | |
end | |
if ~isempty( g.nopoint ) | |
g.notime = zeros(size(g.nopoint)); | |
for index = 1:length(g.nopoint(:)) | |
g.notime(index) = eeg_point2lat(g.nopoint(index), 1, EEG.srate, [EEG.xmin EEG.xmax]); | |
end | |
g.time = []; | |
end | |
if ~isempty( g.notime ) | |
if size(g.notime,2) ~= 2 | |
error('Time/point range must contain 2 columns exactly'); | |
end | |
if g.notime(2) == EEG.xmax | |
g.time = [EEG.xmin g.notime(1)]; | |
else | |
if g.notime(1) == EEG.xmin | |
g.time = [g.notime(2) EEG.xmax]; | |
elseif EEG.trials > 1 | |
error('Wrong notime range. Remember that it is not possible to remove a slice of time for data epochs.'); | |
end | |
end | |
if g.notime(end) > EEG.xmax, g.notime(end) = EEG.xmax; end | |
if g.notime(1) < EEG.xmin, g.notime(1) = EEG.xmin; end | |
if floor(max(g.notime(:))) > EEG.xmax | |
error('Time/point range exceed upper data limits'); | |
end | |
if min(g.notime(:)) < EEG.xmin | |
error('Time/point range exceed lower data limits'); | |
end | |
end | |
if ~isempty(g.time) | |
if size(g.time,2) ~= 2 | |
error('Time/point range must contain 2 columns exactly'); | |
end | |
for index = 1:length(g.time) | |
if g.time(index) > EEG.xmax | |
g.time(index) = EEG.xmax; | |
disp('Upper time limits exceed data, corrected'); | |
elseif g.time(index) < EEG.xmin | |
g.time(index) = EEG.xmin; | |
disp('Lower time limits exceed data, corrected'); | |
end | |
end | |
end | |
% select trial values | |
%-------------------- | |
if ~isempty(g.trialcond) | |
try | |
tt = struct( g.trialcond{:} ); catch | |
error('Trial conditions format error'); | |
end | |
ttfields = fieldnames (tt); | |
for index = 1:length(ttfields) | |
if ~isfield( EEG.epoch, ttfields{index} ) | |
error([ ttfields{index} 'is not a field of EEG.epoch' ]); | |
end | |
tmpepoch = EEG.epoch; | |
eval( [ 'Itriallow = find( [ tmpepoch(:).' ttfields{index} ' ] >= tt.' ttfields{index} '(1) );' ] ); | |
eval( [ 'Itrialhigh = find( [ tmpepoch(:).' ttfields{index} ' ] <= tt.' ttfields{index} '(end) );' ] ); | |
Itrialtmp = intersect_bc(Itriallow, Itrialhigh); | |
g.trial = intersect_bc( g.trial(:)', Itrialtmp(:)'); | |
end | |
end | |
if isempty(g.trial) | |
error('Empty dataset, no trial'); | |
end | |
if length(g.trial) ~= EEG.trials | |
fprintf('Removing %d trial(s)...\n', EEG.trials - length(g.trial)); | |
end | |
if length(g.channel) ~= EEG.nbchan | |
fprintf('Removing %d channel(s)...\n', EEG.nbchan - length(g.channel)); | |
end | |
try | |
% For AMICA probabilities... | |
%----------------------------------------------------- | |
if isfield(EEG.etc, 'amica') && ~isempty(EEG.etc.amica) && isfield(EEG.etc.amica, 'v_smooth') && ~isempty(EEG.etc.amica.v_smooth) && ~isfield(EEG.etc.amica,'prob_added') | |
if isfield(EEG.etc.amica, 'num_models') && ~isempty(EEG.etc.amica.num_models) | |
if size(EEG.data,2) == size(EEG.etc.amica.v_smooth,2) && size(EEG.data,3) == size(EEG.etc.amica.v_smooth,3) && size(EEG.etc.amica.v_smooth,1) == EEG.etc.amica.num_models | |
EEG = eeg_formatamica(EEG); | |
%------------------------------------------- | |
[EEG, com] = pop_select(EEG,args{:}); | |
%------------------------------------------- | |
EEG = eeg_reformatamica(EEG); | |
EEG = eeg_checkamica(EEG); | |
return; | |
else | |
disp('AMICA probabilities not compatible with size of data, probabilities cannot be rejected') | |
disp('Resuming rejection...') | |
end | |
end | |
end | |
% ------------------------------------------------------ | |
catch | |
warnmsg = strcat('your dataset contains amica information, but the amica plugin is not installed. Continuing and ignoring amica information.'); | |
warning(warnmsg) | |
end | |
% recompute latency and epoch number for events | |
% --------------------------------------------- | |
if length(g.trial) ~= EEG.trials && ~isempty(EEG.event) | |
if ~isfield(EEG.event, 'epoch') | |
disp('Pop_epoch warning: bad event format with epoch dataset, removing events'); | |
EEG.event = []; | |
else | |
if isfield(EEG.event, 'epoch') | |
keepevent = []; | |
for indexevent = 1:length(EEG.event) | |
newindex = find( EEG.event(indexevent).epoch == g.trial );% For AMICA probabilities... | |
%----------------------------------------------------- | |
try | |
if isfield(EEG.etc, 'amica') && ~isempty(EEG.etc.amica) && isfield(EEG.etc.amica, 'v_smooth') && ~isempty(EEG.etc.amica.v_smooth) && ~isfield(EEG.etc.amica,'prob_added') | |
if isfield(EEG.etc.amica, 'num_models') && ~isempty(EEG.etc.amica.num_models) | |
if size(EEG.data,2) == size(EEG.etc.amica.v_smooth,2) && size(EEG.data,3) == size(EEG.etc.amica.v_smooth,3) && size(EEG.etc.amica.v_smooth,1) == EEG.etc.amica.num_models | |
EEG = eeg_formatamica(EEG); | |
%------------------------------------------- | |
[EEG, com] = pop_select(EEG,args{:}); | |
%------------------------------------------- | |
EEG = eeg_reformatamica(EEG); | |
EEG = eeg_checkamica(EEG); | |
return; | |
else | |
disp('AMICA probabilities not compatible with size of data, probabilities cannot be rejected') | |
disp('Resuming rejection...') | |
end | |
end | |
end | |
catch | |
warnmsg = strcat('your dataset contains amica information, but the amica plugin is not installed. Continuing and ignoring amica information.'); | |
warning(warnmsg) | |
end; | |
% ------------------------------------------------------ | |
if ~isempty(newindex) | |
keepevent = [keepevent indexevent]; | |
if isfield(EEG.event, 'latency') | |
EEG.event(indexevent).latency = EEG.event(indexevent).latency - (EEG.event(indexevent).epoch-1)*EEG.pnts + (newindex-1)*EEG.pnts; | |
end | |
EEG.event(indexevent).epoch = newindex; | |
end | |
end | |
diffevent = setdiff_bc([1:length(EEG.event)], keepevent); | |
if ~isempty(diffevent) | |
disp(['Pop_select: removing ' int2str(length(diffevent)) ' unreferenced events']); | |
EEG.event(diffevent) = []; | |
end | |
end | |
end | |
end | |
% performing removal | |
% ------------------ | |
if ~isempty(g.time) || ~isempty(g.notime) | |
if EEG.trials > 1 | |
% select new time window | |
% ---------------------- | |
try, tmpevent = EEG.event; | |
tmpeventlatency = [ tmpevent.latency ]; | |
catch, tmpeventlatency = []; | |
end | |
alllatencies = 1-(EEG.xmin*EEG.srate); % time 0 point | |
alllatencies = linspace( alllatencies, EEG.pnts*(EEG.trials-1)+alllatencies, EEG.trials); | |
[EEG.data, tmptime, indices, epochevent]= epoch(EEG.data, alllatencies, ... | |
[g.time(1) g.time(2)]*EEG.srate, 'allevents', tmpeventlatency); | |
tmptime = tmptime/EEG.srate; | |
if g.time(1) ~= tmptime(1) && g.time(2)-1/EEG.srate ~= tmptime(2) | |
fprintf('pop_select(): time limits have been adjusted to [%3.3f %3.3f] to fit data points limits\n', tmptime(1), tmptime(2)+1/EEG.srate); | |
end | |
EEG.xmin = tmptime(1); | |
EEG.xmax = tmptime(2); | |
EEG.pnts = size(EEG.data,2); | |
alllatencies = alllatencies(indices); | |
% modify the event structure accordingly (latencies and add epoch field) | |
% ---------------------------------------------------------------------- | |
allevents = []; | |
newevent = []; | |
count = 1; | |
if ~isempty(epochevent) | |
newevent = EEG.event(1); | |
for index=1:EEG.trials | |
for indexevent = epochevent{index} | |
newevent(count) = EEG.event(indexevent); | |
newevent(count).epoch = index; | |
newevent(count).latency = newevent(count).latency - alllatencies(index) - tmptime(1)*EEG.srate + 1 + EEG.pnts*(index-1); | |
count = count + 1; | |
end | |
end | |
end | |
EEG.event = newevent; | |
% erase event-related fields from the epochs | |
% ------------------------------------------ | |
if ~isempty(EEG.epoch) | |
fn = fieldnames(EEG.epoch); | |
EEG.epoch = rmfield(EEG.epoch,{fn{strmatch('event',fn)}}); | |
end | |
else | |
if isempty(g.notime) | |
if length(g.time) == 2 && EEG.xmin < 0 | |
disp('Warning: negative minimum time; unchanged to ensure correct latency of initial boundary event'); | |
end | |
g.notime = g.time'; | |
g.notime = g.notime(:); | |
if g.notime(1) ~= 0, g.notime = [EEG.xmin g.notime(:)']; | |
else g.notime = [g.notime(2:end)']; | |
end | |
if g.time(end) == EEG.xmax, g.notime(end) = []; | |
else g.notime(end+1) = EEG.xmax; | |
end | |
for index = 1:length(g.notime) | |
if g.notime(index) ~= 0 && g.notime(index) ~= EEG.xmax | |
if mod(index,2), g.notime(index) = g.notime(index) + 1/EEG.srate; | |
else g.notime(index) = g.notime(index) - 1/EEG.srate; | |
end | |
end | |
end | |
g.notime = reshape(g.notime, 2, length(g.notime)/2)'; | |
end | |
nbtimes = length(g.notime(:)); | |
[points,flag] = eeg_lat2point(g.notime(:)', ones(1,nbtimes), EEG.srate, [EEG.xmin EEG.xmax]); | |
points = reshape(points, size(g.notime)); | |
% fixing if last region is the same | |
if flag | |
if ~isempty(find((points(end,1)-points(end,2))== 0)), points(end,:) = []; end | |
end | |
EEG = eeg_eegrej(EEG, points); | |
end | |
end | |
% performing removal | |
% ------------------ | |
if ~isequal(g.channel,1:size(EEG.data,1)) || ~isequal(g.trial,1:size(EEG.data,3)) | |
eeglab_options; | |
if option_memmapdata | |
% this code below is preferred for memory mapped files | |
diff1 = setdiff_bc([1:size(EEG.data,1)], g.channel); | |
diff2 = setdiff_bc([1:size(EEG.data,3)], g.trial); | |
if ~isempty(diff1) | |
EEG.data(diff1, :, :) = []; | |
end | |
if ~isempty(diff2) | |
EEG.data(:, :, diff2) = []; | |
end | |
else | |
EEG.data = EEG.data(g.channel, :, g.trial); | |
end | |
end | |
if ~isempty(EEG.icaact), EEG.icaact = EEG.icaact(:,:,g.trial); end | |
if ~isempty(EEG.chanlocs) | |
if ~isfield(EEG.chaninfo, 'removedchans') | |
EEG.chaninfo.removedchans = []; | |
end | |
try | |
diff1 = setdiff_bc([1:EEG.nbchan], g.channel); | |
fields = fieldnames(EEG.chanlocs); | |
for iChan = diff1(:)' | |
EEG.chaninfo.removedchans(end+1).(fields{1}) = EEG.chanlocs(iChan).(fields{1}); | |
for iField = 1:length(fields) | |
EEG.chaninfo.removedchans(end).(fields{iField}) = EEG.chanlocs(iChan).(fields{iField}); | |
end | |
end | |
catch | |
disp('There was an issue storing removed channels in pop_select'); | |
end | |
EEG.chanlocs = EEG.chanlocs(g.channel); | |
end | |
EEG.trials = length(g.trial); | |
EEG.pnts = size(EEG.data,2); | |
EEG.nbchan = length(g.channel); | |
if ~isempty(EEG.epoch) | |
EEG.epoch = EEG.epoch( g.trial ); | |
end | |
if ~isempty(EEG.specdata) | |
if length(g.point) == EEG.pnts | |
EEG.specdata = EEG.specdata(g.channel, :, g.trial); | |
else | |
EEG.specdata = []; | |
fprintf('Warning: spectral data were removed because of the change in the number of points\n'); | |
end | |
end | |
% ica specific | |
% ------------ | |
if ~isempty(EEG.icachansind) | |
rmchans = setdiff_bc( EEG.icachansind, g.channel ); % channels to remove | |
% channel sub-indices | |
% ------------------- | |
icachans = 1:length(EEG.icachansind); | |
for index = length(rmchans):-1:1 | |
chanind = find(EEG.icachansind == rmchans(index)); | |
icachans(chanind) = []; | |
end | |
% new channels indices | |
% -------------------- | |
count = 1; | |
newinds = []; | |
for index = 1:length(g.channel) | |
if any(EEG.icachansind == g.channel(index)) | |
newinds(count) = index; | |
count = count+1; | |
end | |
end | |
EEG.icachansind = newinds; | |
else | |
icachans = 1:size(EEG.icasphere,2); | |
end | |
if ~isempty(EEG.icawinv) | |
flag_rmchan = (length(icachans) ~= size(EEG.icawinv,1)); | |
if isempty(EEG.icaweights) || flag_rmchan | |
EEG.icawinv = EEG.icawinv(icachans,:); | |
EEG.icaweights = pinv(EEG.icawinv); | |
EEG.icasphere = eye(size(EEG.icaweights,2)); | |
end | |
end | |
if ~isempty(EEG.specicaact) | |
if length(g.point) == EEG.pnts | |
EEG.specicaact = EEG.specicaact(icachans, :, g.trial); | |
else | |
EEG.specicaact = []; | |
fprintf('Warning: spectral ICA data were removed because of the change in the number of points\n'); | |
end | |
end | |
% check if only one epoch | |
% ----------------------- | |
if EEG.trials == 1 | |
if isfield(EEG.event, 'epoch') | |
EEG.event = rmfield(EEG.event, 'epoch'); | |
end | |
EEG.epoch = []; | |
end | |
if isfield(EEG.reject, 'gcompreject') && isequal(g.channel,1:size(EEG.data,1)) | |
tmpgcompreject = EEG.reject.gcompreject; | |
EEG.reject = []; | |
EEG.reject.gcompreject = tmpgcompreject; | |
else | |
EEG.reject = []; | |
end | |
EEG.stats = []; | |
EEG.reject.rejmanual = []; | |
% for stats, can adapt remove the selected trials and electrodes | |
% in the future to gain time ----------------------------------- | |
EEG.stats.jp = []; | |
EEG = eeg_checkset(EEG, 'eventconsistency'); | |
% generate command | |
% ---------------- | |
if nargout > 1 | |
com = sprintf('EEG = pop_select( EEG, %s);', vararg2str(args)); | |
end | |
return; | |
% ********* OLD, do not remove any event any more | |
% ********* in the future maybe do a pack event to remove events not in the time range of any epoch | |
if ~isempty(EEG.event) | |
% go to array format if necessary | |
if isstruct(EEG.event), format = 'struct'; | |
else format = 'array'; | |
end | |
switch format, case 'struct', EEG = eventsformat(EEG, 'array'); end | |
% keep only events related to the selected trials | |
Indexes = []; | |
Ievent = []; | |
for index = 1:length( g.trial ) | |
currentevents = find( EEG.event(:,2) == g.trial(index)); | |
Indexes = [ Indexes ones(1, length(currentevents))*index ]; | |
Ievent = union_bc( Ievent, currentevents ); | |
end | |
EEG.event = EEG.event( Ievent,: ); | |
EEG.event(:,2) = Indexes(:); | |
switch format, case 'struct', EEG = eventsformat(EEG, 'struct'); end | |
end | |