-
Notifications
You must be signed in to change notification settings - Fork 0
/
erplab_deleteTimeSegments.m
204 lines (163 loc) · 7.48 KB
/
erplab_deleteTimeSegments.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
% erplab_deleteTimeSegments.m
%
% Deletes data segments between 2 event codes (string or number) if the size of the segment
% is greater than a user-specified threshold (in msec)
%
% USAGE
%
% EEG = erplab_deleteTimeSegments(EEG, inputMaxDistanceMS, inputStartPeriodBufferMS, inputEndPeriodBufferMS, ignoreEventCodes);
%
%
% Input:
%
% EEG - continuous EEG dataset (EEGLAB's EEG struct)
% maxDistanceMS - user-specified time threshold
% startEventCodeBufferMS - time buffer around first event code
% endEventCodeBufferMS - time buffer around last event code
%
% Optional
% ignoreEventCodes - array of event code numbers to ignore
% displayEEGPLOTGUI - (true|false)
%
% Output:
%
% EEG - continuous EEG dataset (EEGLAB's EEG struct)
%
%
% Example: Delete segment of data between any two event codes when it is
% longer than 3000 ms (3 secs).
%
% EEG = erplab_deleteTimeSegments(EEG, 3000, 100, 200, []);
%
%
%
%
% *** This function is part of ERPLAB Toolbox ***
% Author: Jason Arita
% Center for Mind and Brain
% University of California, Davis,
% Davis, CA
% 2009
%b8d3721ed219e65100184c6b95db209bb8d3721ed219e65100184c6b95db209b
%
% ERPLAB Toolbox
% Copyright © 2007 The Regents of the University of California
% Created by Javier Lopez-Calderon and Steven Luck
% Center for Mind and Brain, University of California, Davis,
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
function [EEG, rejectionWindows] = erplab_deleteTimeSegments(EEG, inputMaxDistanceMS, inputStartPeriodBufferMS, inputEndPeriodBufferMS, varargin)
% Error check the input variables
if nargin<1
help erplab_deleteTimeSegments
return
elseif nargin<4
error('ERPLAB:erplab_deleteTimeSegments: needs 4 inputs.')
elseif length(varargin) > 2 % only want 3 optional inputs at most
error('ERPLAB:erplab_deleteTimeSegments:TooManyInputs', ...
'requires at most 2 optional inputs');
else
disp('Working...')
end
if length(EEG.event)<1
fprintf('\ndelshortseg.m did not find remaining event codes.\n')
return
end
%% Handle optional variables
optargs = {[] false}; % Default optional inputs
% Put defaults into the valuesToUse cell array,
% and overwrite the ones specified in varargin.
optargs(1:length(varargin)) = varargin; % if vargin is empty, optargs keep their default values. If vargin is specified then it overwrites
% Place optional args into variable names
[ignoreEventCodes, eegplotGUIFeedback] = optargs{:};
%% Convert all timing info to samples
maxDistanceSample = round(inputMaxDistanceMS *(EEG.srate/1000)); % ms to samples
startPeriodBufferSample = round(inputStartPeriodBufferMS *(EEG.srate/1000)); % ms to samples
endPeriodBufferSample = round(inputEndPeriodBufferMS *(EEG.srate/1000)); % ms to samples
%% Set up WORKING event codes + IGNORED event codes
if ischar(EEG.event(1).type)
analyzedEventCodes = setdiff({EEG.event.type}, ignoreEventCodes); % Filter out the ignored event code
analyzedEventIndices = ismember({EEG.event.type}, analyzedEventCodes); %
analyzedSamples = round([EEG.event(analyzedEventIndices).latency]); % Convert event codes to samples
else
analyzedEventCodes = setdiff([EEG.event.type], ignoreEventCodes); % Filter out the ignored event code
analyzedEventIndices = ismember([EEG.event.type], analyzedEventCodes); %
analyzedSamples = round([EEG.event(analyzedEventIndices).latency]); % Convert event codes to samples
end
if analyzedSamples(1) ~= 1
analyzedSamples = [1 analyzedSamples]; % add first time point index
end
if analyzedSamples(end) ~= EEG.pnts
analyzedSamples = [analyzedSamples EEG.pnts]; % add first time point index
end
lastSample = 1;
rejectionWindows = zeros(length(analyzedSamples), 2); % [];
%% Find large segments between time samples
for ii=1:length(analyzedSamples)
if abs(analyzedSamples(ii)-lastSample)>=maxDistanceSample
t1 = lastSample;
t2 = analyzedSamples(ii);
% If at the beginning of the data array, don't add initial buffer
if t1 == 1
rejWin = [t1 ...
t2 - endPeriodBufferSample];
% If at the end of the data array, don't add end buffer
elseif t2 == EEG.pnts
rejWin = [t1 + startPeriodBufferSample ...
t2 ];
% else add time buffer to inital and end data points
else
rejWindowMin = t1 + startPeriodBufferSample;
rejWindowMax = t2 - endPeriodBufferSample;
% Test to ensure overlapping buffer windows do not delete
% the overlapping time segment
if rejWindowMin < rejWindowMax
rejWin = [rejWindowMin rejWindowMax];
else
rejWin = [];
end
end
rejectionWindows = vertcat(rejectionWindows, rejWin); %#ok<AGROW>
end
lastSample = analyzedSamples(ii);
end
rejectionWindows(any(rejectionWindows==0,2),:) = []; % trim empty rows
%% Via EEGLAB.EEG_EEGREJ, delete the rejected windows
rejectionWindowCount = size(rejectionWindows, 2);
if rejectionWindowCount < 1
fprintf('\nNote: No large segment was found.\n')
else
if(rejectionWindowCount > 1)
rejectionWindows = joinclosesegments(rejectionWindows, [], 5);
end
if eegplotGUIFeedback
% Plot EEG data with to-be-rejected time windows
rejectionWindowChannelMatrix = zeros(size(rejectionWindows,1),EEG.nbchan, 1); % do not mark any channel in EEGPLOT
rejectionWindowColorMatrix = repmat([1 0 0], size(rejectionWindows,1),1); % color matrix for EEGPLOT highlighting
rejectionWindowMatrix = [rejectionWindows rejectionWindowColorMatrix rejectionWindowChannelMatrix]; % combined rejection window highlighting for EEGPLOT
rejectionCommand = sprintf('%s = eeg_eegrej( %s, rejectionWindows);', 'EEG', 'EEG'); % inputname(1), inputname(1));
assignin('base', 'rejectionWindows', rejectionWindows); % not sure why this is needed
eegplot(EEG.data, 'winrej', rejectionWindowMatrix, 'srate', EEG.srate,'butlabel','REJECT','command', rejectionCommand,'events', EEG.event,'winlength', 20);
fprintf('\n %g rejection segments marked.\n\n', size(rejectionWindows,1));
else
EEG = eeg_eegrej( EEG, rejectionWindows);
end
end
%% Delete first boundary event code when it is the first sample.
if ischar(EEG.event(1).type)
if strcmpi(EEG.event(1).type,'boundary') && EEG.event(1).latency<=1 % in sample
EEG = pop_editeventvals(EEG,'delete',1);
end
end