-
Notifications
You must be signed in to change notification settings - Fork 245
/
eeg_context.m
678 lines (649 loc) · 28.4 KB
/
eeg_context.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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
% EEG_CONTEXT - returns (in output 'delays') a matrix giving, for each event of specified
% ("target") type(s), the latency (in ms) to the Nth preceding and/or following
% urevents (if any) of specified ("neighbor") type(s). Return the target event
% and urevent numbers, the neighbor urevent numbers, and the values of specified
% urevent field(s) for each of the neighbor urevents. Uses the EEG.urevent
% structure, plus EEG.EVENT.urevent pointers to it. If epoched data, also
% uses the EEG.epoch structure. For use in event-handling scripts and functions.
% Usage:
% >> [targs,urnbrs,urnbrtypes,delays,tfields,urnfields] = ...
% eeg_context(EEG,{targets},{neighbors},[positions],{fields},alltargs);
% Required input:
% EEG - EEGLAB dataset structure containing EEG.event and EEG.urevent sub-structures
%
% Optional inputs:
% targets - string or cell array of strings naming event type(s) of the specified target
% events {default | []: all events}
% neighbors - string or cell array of strings naming event type(s) of the specified
% neighboring urevents {default | []: any neighboring events}.
% [positions] - int vector giving the relative positions of 'neighbor' type urevents to return.
% Ex: [-3 -2 -1 0 1 2 3] -> return the previous 3, current, and succeeding 3
% urevents of the specified {neighbor} types. [positions] values are arranged
% in ascending order before processing. {default | []: 1 = first succeeding}
% fields - string or cell array of strings naming one or more (ur)event field(s) to return
% values for neighbor urevents. {default: no field info returned}
% alltargs - string ('all'|[]) if 'all', return information about all target urevents,
% even those on which no epoch in the current dataset is centered.
% {default: [] -> only return information on epoch-centered target events}
% Outputs:
% targs - size(ntargets,4) matrix giving the indices of target events in the event
% structure in column 1 and in the urevent structure in column 2. Column 3 gives
% the epoch number in which the target has latency 0 (else NaN if no such epoch).
% The fourth column gives the index of the target type in the {targets} cell array.
% urnbrs - matrix of indices of "neighbor" events in the URevent structure (NaN if none).
% urnbrtypes - int array giving the urnbrs event type indices in the {neighbor} cell array,
% else NaN if no such neighbor. Ex: If nbr = {'square','rt'} (see below),
% then urnbrtypes outputs are [1|2]; if nbr = {'rt'}, returns [1]s.
% delays - matrix giving, for each {targets} type event, the latency of the delay (in ms)
% from each target event to its neighbor urevents. Else, returns NaN when no
% neighbor event. Output matrix size: (ntargets,length(positions)).
% tfields - real or cell array of values of the requested (ur)event field(s) for the target
% events. Values are the same type as the field values, else NaN if no such event.
% urnfields - real or cell array of values of the requested (ur)event field(s) for the neighbor
% urevents. Values are the same type as the field values, else NaN if no such event.
% If > 1 field specified, a 3-D array or cell array (nevents,nnbrpos,nfields).
% Example:
%
% >> target = 'square'; % target events are type 'square'
% >> nbr = {'square','rt'}; % neighbor events are either 'square' or 'rt'
%
% >> [trgs,urnbrs,urnbrtypes,delays,tflds,urnflds] = ...
% eeg_context(EEG,target,nbr,[-4 1],'position');
% %
% % Output 'delays' now contains latencies (in ms) from each 'square' target event to the
% % 4th preceding and 1st succeeding 'rt' OR 'square' urevent (else NaN when none such).
% % Outputs 'tfields' and 'urnflds' give the 'position' field values of target events and
% % neighbor urevents. Output 'urnbrtypes', the index of the type (1='square' or 2='rt')
% % of the ('urnbrs') neighbor urevents.
% %
% >> trts = find(trgs(:,4)==2); % targets followed by an 'rt' (before any 'square')
% >> pos3 = find(trgfld = 3); % targets with 'position'=3 (numeric field value).
% >> selevents = intersect_bc(trts,pos3); % target events by both criteria
% >> selepochs = trgs(selevents,3); % epoch numbers centered on the selected target events
%
% Author: Scott Makeig, SCCN, Institute for Neural Computation, UCSD, March 27, 2004
% Copyright (C) Scott Makeig, SCCN, Institute for Neural Computation, UCSD, March 27, 2004
%
% 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.
% Edit History:
% 1/10/05 added 4th (type) field to output trgs; added to Example;
% 5/25/04 test for isnan(urevent.duration) to detect real break events -sm
% 3/27/04 made no-such-event return NaNs; added {target} and {neighbor} defaults -sm
% 3/28/04 added test for boundary urevents; renamed relidx as positions, lats as delays -sm
% 3/29/04 reorganized output order, adding urnbrtypes -sm
% 3/29/04 changed urnbrtypes to int array -sm
% 3/31/04 ruled out searching 'boundary' events -sm
% 5/06/04 completed the function -sm
%
function [targs,ur_nbrs,ur_nbrtypes,delays,tfields,nfields] = eeg_context(EEG,targets,neighbors,positions,field,alltargs)
verbose = 0; % flag useful info printout (1=on|0=off)
debug_print = 0; % flag overly verbose printout
breakwarning = 0; % flag no pre-4.4 warning given
if nargin < 1
help eeg_context
return
end
if nargin< 6 || isempty(alltargs)
alltargs = 0;
elseif strcmpi(alltargs,'all')
alltargs = 1;
else
error('alltargs argument must be ''all'' or [].')
end
if ~isstruct(EEG)
error('first argument must be an EEG dataset structure');
end
if ~isfield(EEG,'event')
error('No EEG.event structure found');
end
if ~isfield(EEG,'urevent')
error('No EEG.urevent structure found');
end
if ~isfield(EEG.event,'urevent')
error('No EEG.event().urevent field found');
end
if EEG.trials == 1 || ~isfield(EEG.event(1),'epoch')
fprintf('Data are continuous: Returning info on all targets; no epoch info returned.\n')
alltargs = 1;
epochinfo = 0;
else
epochinfo = 1;
end
if epochinfo && ~isfield(EEG,'epoch')
error('No EEG.epoch information in this epoched dataset - run eeg_checkset()');
end
if epochinfo && ~isfield(EEG.epoch,'eventlatency')
error('No EEG.epoch.eventlatency information in this epoched dataset');
end
if epochinfo && ~isfield(EEG.epoch,'event')
error('No EEG.epoch.event information in this epoched dataset');
end
nevents = length(EEG.event);
nurevents = length(EEG.urevent);
if length(EEG.urevent) < nevents
fprintf('In this dataset there are more events than urevents. Check consistency.\n');
end
%
%%%%%%%%%%%%%%%%%% Substitute input defaults %%%%%%%%%%%%%%%%%%%%
%
if nargin < 5 || isempty(field)
NO_FIELD = 1; % flag no field variable output
end
if nargin < 4 || isempty(positions)
positions = 1; % default: find next
end
if nargin < 3 || isempty(neighbors)
neighbors = {'_ALL'}; % flag neighbors are all neighboring events
end
if nargin < 2 || isempty(targets)
targets = {'_ALL'}; % flag targets are all events
end
%
%%%%%%%%%%%%% Test and adjust input arguments %%%%%%%%%%%%%%%%%%%%
%
if ischar(targets)
targets = {targets};
end
if ~iscell(targets)
error('2nd argument "targets" must be a {cell array} of event types.');
end
if ischar(neighbors)
neighbors = {neighbors};
end
if ~iscell(neighbors)
error('3rd argument "neighbors" must be a {cell array} of event types.');
end
for k=1:length(targets) % make all target types strings
if ~ischar(targets{k})
targets{k} = num2str(targets{k});
end
end
for k=1:length(neighbors) % make all neighbor types strings
if ~ischar(neighbors{k})
neighbors{k} = num2str(neighbors{k});
end
end
tmp = sort(positions); % reorder positions in ascending order
if sum(tmp==positions) ~= length(positions)
fprintf('eeg_context(): returning neighbors in ascending order: ');
for k=1:length(tmp)
fprintf('%d ',tmp(k));
end
fprintf('\n');
end
positions = tmp;
%
%%%%%%%%%%%%%% Prepare to find "neighbor" events %%%%%%%%%%%%%%%%%%
%
zeroidx = find(positions == 0); % find 0's in positions vector
negidx = find(positions < 0);
negpos = positions(negidx);
if ~isempty(negpos)
negpos = abs(negpos(end:-1:1)); % work backwards, make negpos positive
negidx = negidx(end:-1:1); % index into output ur_nbrs
end
nnegpos = length(negpos); % number of negative positions to search for
posidx = find(positions>0); % work forwards
pospos = positions(posidx);
npospos = length(pospos); % number of positive positions to search for
%
%%%%%%%%%%%%%%%%%%%% Initialize output arrays %%%%%%%%%%%%%%%%%%%%%%
%
npos = length(positions);
delays = NaN*zeros(nevents,npos); % holds inter-event intervals in ms
% else NaN when no neighboring event
targs = NaN*zeros(nevents,1); % holds indices of targets
targepochs= NaN*zeros(nevents,1); % holds numbers of the epoch centered
% on each target (or NaN if none such)
ur_trgs = NaN*zeros(nevents,1); % holds indices of targets
ur_nbrs = NaN*zeros(nevents,npos); % holds indices of neighbors
ur_nbrtypes = NaN*zeros(nevents,npos); % holds {neighbors} type indices
cellfld = -1; % flag no field output specified
if ~exist('NO_FIELD','var') % if field values asked for
if ischar(field)
if ~isfield(EEG.urevent,field)
error('Specified field not found in urevent struct');
end
if ischar(EEG.urevent(1).(field)) ...
| iscell(EEG.urevent(1).(field)) ...
| isstruct(EEG.urevent(1).(field)),
tfields = cell(nevents,1);
nfields = cell(nevents,npos);
cellfld = 1; % flag that field outputs are cell arrays
else % is number
tfields = NaN*zeros(nevents,1);
nfields = NaN*zeros(nevents,npos);
cellfld = 0; % flag that field outputs are numeric arrays
end
field = {field}; % make string field a cell array for uniformity
nfieldnames = 1;
elseif iscell(field)
nfieldnames = length(field);
for f = 1:nfieldnames
if ~isfield(EEG.urevent,field{f})
error('Specified field not found in urevent struct');
end
if ischar(EEG.urevent(1).(field{f})) ...
| iscell(EEG.urevent(1).(field{f})) ...
| isstruct(EEG.urevent(1).(field{f})),
if f==1,
tfields = cell(nevents,nfieldnames);
nfields = cell(nevents,npos,nfieldnames);
end
cellfld = 1; % flag that field outputs are cell arrays
else % is number
if f==1
tfields = NaN*zeros(nevents,nfieldnames);
nfields = NaN*zeros(nevents,npos,nfieldnames);
end
end
end
if cellfld == -1,
cellfld = 0; % field value(s) must be numeric
end
else
error('''field'' value must be string or cell array');
end
end
targetcount = 0; % index of current target
% Below:
% evidx = current event index
% uridx = current urevent index
% uidx = neighbor urevent index
% tidx = target type index
% nidx = neighbor type index
% pidx = position index
%
%%%%%%%%%%%for each event in the dataset %%%%%%%%%%%%%%%%%%%%
%
wb=waitbar(0,'Computing event contexts...','createcancelbtn','delete(gcf)');
noepochs = 0; % counter of targets that are not epoch-centered
targidx = zeros(nevents,1);
for evidx = 1:nevents %%%%%% for each event in the dataset %%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
waitbar(evidx/nevents); % update the waitbar fraction
if ~strcmp(EEG.event(evidx).type,'boundary') % ignore boundary events (no urevents!)
%
%%%%%%%%%%%%%%%%%%%%%%%% find target events %%%%%%%%%%%%%%%%%
%
uridx = EEG.event(evidx).urevent; % find its urevent index
if isempty(uridx)
fprintf('eeg_context(): Data event %d does not point to an urevent.\n',evidx);
delete(wb);
return
end
istarget = 0; % initialize target flag
tidx = 1; % initialize target type index
%
%%%%%%%%%%%%%%% cycle through target types %%%%%%%%%%%%%%%%%%
%
while ~istarget & tidx<=length(targets) % for each potential target type
uridxtype = EEG.urevent(uridx).type;
if ~ischar(uridxtype), uridxtype = num2str(uridxtype); end
if strcmpi(uridxtype,targets(tidx)) || strcmp(targets{1},'_ALL')
% if is a target type
istarget=1; % flag event as target
targetcount = targetcount+1; % increment target count
%
%%%%%%%%%%%%% find 0th neighbors (=targets themselves)
%
if ~isempty(zeroidx) % if the target event is asked for in the nbrs array
delays(targetcount,zeroidx) = 0;
if ~exist('NO_FIELD','var')
for f=1:nfieldnames
if cellfld == 0
nfields(targetcount,zeroidx,f) = EEG.urevent(uridx).(field{f});
else % cellfld == 1
nfields{targetcount,zeroidx,f} = EEG.urevent(uridx).(field{f});
end
end
end
end
if epochinfo % if the data are epoched
is0epoch = 0;
for z = 1:length(EEG.event(evidx).epoch) % for each epoch the event is in
ep = EEG.event(evidx).epoch(z);
for e = 1:length(EEG.epoch(ep).event) % for each event in the epoch
if EEG.epoch(ep).event(e) == evidx % if current event
% js : added the if ~iscell loop
if ~iscell(EEG.epoch(ep).eventlatency) % i.e. not more than 1 eventtype in the epoch
if length(EEG.epoch(ep).eventlatency(e)) == 1
trglt = EEG.epoch(ep).eventlatency(e); % get its epoch latency
else
trglt = EEG.epoch(ep).eventlatency(1); % this shouldn't happen
fprintf('EEG.epoch(%d).eventlatency(%d) length > 1 ??\n',ep,e);
end
else
if length(EEG.epoch(ep).eventlatency{e}) == 1
trglt = EEG.epoch(ep).eventlatency{e}; % get its epoch latency
else
trglt = EEG.epoch(ep).eventlatency{e}(1); % this shouldn't happen
fprintf('EEG.epoch(%d).eventlatency{%d} length > 1 ??\n',ep,e);
end
end
if trglt == 0
targepochs(targetcount) = ep;
is0epoch = 1;
break;
end
end
end
if is0epoch
break;
end
end % for
if ~is0epoch, noepochs = noepochs+1; end
end
targs(targetcount) = evidx; % save event index
ur_trgs(targetcount) = uridx; % save urevent index
if ~exist('NO_FIELD','var')
for f=1:nfieldnames
if cellfld ==0
tfields(targetcount,f) = EEG.urevent(uridx).(field{f});
elseif cellfld == 1
tfields{targetcount,f} = EEG.urevent(uridx).(field{f});
end
end
break % stop target type checking
end
else % next target type
tidx = tidx+1; % else try next target type
end % if is target
end % while ~istarget
if istarget % if current event is a target type
targidx(targetcount) = tidx; % save index of its type within targets
if ~isempty(negpos)
%
%%%%%%%%%%%%%%%%%% find previous neighbor urevents %%%%%%%%%%%%
%
uidx = uridx-1; % begin with the previous urevent
npidx = 1; % index into negpos
curpos = 1; % current (negative) position
seekpos = negpos(npidx); % begin with first negpos position
while uidx > 0 & npidx <= nnegpos % search through previous urevents
uidxtype = EEG.urevent(uidx).type;
if ~ischar(uidxtype), uidxtype = num2str(uidxtype); end
if strcmpi(uidxtype,'boundary') % flag boundary urevents
if ~isfield(EEG.urevent,'duration') ...
| ( isnan(EEG.urevent(uidx).duration) ...
| isempty(EEG.urevent(uidx).duration)) % pre-v4.4 or real break urevent
% (NaN duration)
if ~isfield(EEG.urevent,'duration') ... % pre version-4.4 dataset
& breakwarning == 0
fprintf('Pre-v4.4 boundary urevent found - duration field not defined.');
breakwarning = 1;
end
end
break % don't search for neighbors across a boundary urevent
end
isneighbor = 0; % initialize neighbor flag
nidx = 1; % initialize neighbor type index
%
%%%%%%%%%% cycle through neighbor types %%%%%%%%%%%%%
%
while ~isneighbor & nidx<=length(neighbors) % for each neighbor event type
if strcmpi(uidxtype,neighbors(nidx)) || any(strcmp(neighbors,'_ALL'))
isneighbor=1; % flag 'neighbors' event
curpos = curpos+1;
%
%%%%%%%%%%%%%%% if an event in one of the specified positions %%%%%
%
if curpos-1 == seekpos
delays(targetcount,negidx(npidx)) = 1000/EEG.srate * ...
(EEG.urevent(uidx).latency - EEG.urevent(uridx).latency);
% return negative latencies for negpos events
ur_nbrs(targetcount,negidx(npidx))=uidx; % mark urevent as neighbor
ur_nbrtypes(targetcount,negidx(npidx)) = nidx;
if ~exist('NO_FIELD','var')
for f=1:nfieldnames
if cellfld ==0
if nfieldnames > 1
if ~isempty(EEG.urevent(uidx).(field{f}))
nfields(targetcount,negidx(npidx),f) = EEG.urevent(uidx).(field{f});
else
nfields(targetcount,negidx(npidx),f) = NaN;
end
elseif ~isempty(EEG.urevent(uidx).(field{f}))
nfields(targetcount,negidx(npidx)) = EEG.urevent(uidx).(field{f});
else
nfields(targetcount,negidx(npidx)) = NaN;
end
elseif cellfld == 1
if nfieldnames > 1
nfields{targetcount,negidx(npidx),f} = EEG.urevent(uidx).(field{f});
else
nfields{targetcount,negidx(npidx)} = EEG.urevent(uidx).(field{f});
end
end
end
end
npidx = npidx+1; % look for next negpos position
if npidx<=nnegpos
seekpos = negpos(npidx); % new seek position
end
end % if seekpos
break % stop neighbors type checking
else
nidx = nidx+1; % try next 'neighbors' event type
end
end % nidx - neighbor-type testing loop
%
%%%%%%%%%%%%%%% find preceding neighbor event %%%%%%%%%%%%%%
%
uidx = uidx-1; % keep checking for a 'neighbors' type event
end % while uidx - urevent type checking
end % if negpos
if ~isempty(pospos)
%
%%%%%%%%%%%%%%% find succeeding position urevents %%%%%%%%%%%%
%
uidx = uridx+1; % begin with the succeeding urevent
ppidx = 1; % index into pospos
curpos = 1; % current (positive) position
seekpos = pospos(ppidx); % begin with first pospos position
while uidx <= nurevents & ppidx <= npospos % search through succeeding urevents
isneighbor = 0; % initialize neighbor flag
uidxtype = EEG.urevent(uidx).type;
if ~ischar(uidxtype), uidxtype = num2str(uidxtype); end
if strcmpi(uidxtype,'boundary') % flag boundary events
if ~isfield(EEG.urevent,'duration') ...
| ( isnan(EEG.urevent(uidx).duration) ...
| isempty(EEG.urevent(uidx).duration)) % pre-v4.4 or real break urevent
% (NaN duration)
if ~isfield(EEG.urevent,'duration') ... % pre version-4.4 dataset
& breakwarning == 0
fprintf('Pre-v4.4 boundary urevent found - duration field not defined.');
breakwarning = 1;
end
end
break % don't search for neighbors across a boundary urevent
end
pidx = 1; % initialize neighbor type index
%
%%%%%%%%%% cycle through neighbor types %%%%%%%%%%%%%
%
while ~isneighbor & pidx<=length(neighbors) % for each neighbor event type
if strcmpi(uidxtype,neighbors(pidx)) ...
| strcmp(neighbors,'_ALL')
isneighbor=1; % flag 'neighbors' event
curpos = curpos+1;
%
%%%% if an event in one of the specified positions %%%%%
%
if curpos-1 == seekpos
ur_nbrs(targetcount,posidx(ppidx))=uidx; % mark urevent as neighbor
% ur_nbrtypes{targetcount,posidx(ppidx)} = EEG.urevent(uidx).type; % note its type
ur_nbrtypes(targetcount,posidx(ppidx)) = pidx; % note its type
delays(targetcount,posidx(ppidx)) = 1000/EEG.srate * ...
(EEG.urevent(uidx).latency - EEG.urevent(uridx).latency);
% return positive latencies for pospos events
if ~exist('NO_FIELD','var')
for f=1:nfieldnames
if cellfld ==0
if nfieldnames > 1
if ~isempty(EEG.urevent(uidx).(field{f}))
nfields(targetcount,posidx(ppidx),f) = EEG.urevent(uidx).(field{f});
else
nfields(targetcount,posidx(ppidx),f) = NaN;
end
elseif ~isempty(EEG.urevent(uidx).(field{f}))
nfields(targetcount,posidx(ppidx)) = EEG.urevent(uidx).(field{f});
else
nfields(targetcount,posidx(ppidx)) = NaN;
end
else % if cellfld == 1
if nfieldnames > 1
nfields{targetcount,posidx(ppidx),f} = EEG.urevent(uidx).(field{f});
else
nfields{targetcount,posidx(ppidx)} = EEG.urevent(uidx).(field{f});
end
end
end
end
ppidx = ppidx+1;
if ppidx<=npospos
seekpos = pospos(ppidx); % new seek position
end
break % stop neighbors type checking
end % if seekpos
break
else
%
%%%%%%%%%%%% find succeeding neighbor event %%%%%%%%%%%%
%
pidx = pidx+1; % try next 'neighbors' event-type
end
end % pidx - neighbor-type testing loop
uidx = uidx+1; % keep checking for 'neighbors' type urevents
end % uidx - urevent type checking
end % if pospos
%
%%%%%%%%%%%%%%% debug mode info printout %%%%%%%%%%%%%%%%%%%%%%
%
if debug_print
fprintf('%d. ',targetcount)
if targetcount<1000, fprintf(' '); end
if targetcount<100, fprintf(' '); end
if targetcount<10, fprintf(' '); end
if uidx > 1
%fprintf('event %-4d ttype %s - delays: ',evidx,num2str(EEG.urevent(evidx).type));
for k=1:npos
fprintf('(%d) ',ur_nbrs(targetcount,k));
if ur_nbrs(targetcount,k)<1000, fprintf(' '); end
if ur_nbrs(targetcount,k)<100, fprintf(' '); end
if ur_nbrs(targetcount,k)<10, fprintf(' '); end
fprintf('%2.0f ',delays(targetcount,k));
end
if ~exist('NO_FIELD','var')
if cellfld == 0 % numeric field values
fprintf('fields: ')
for f=1:nfieldnames
fprintf('%-5g - ',tfields(targetcount,f))
for k=1:npos
fprintf('%-5g ',nfields(targetcount,k,f));
end
end
elseif cellfld == 1 % cell array field values
fprintf('fields: ')
for f=1:nfieldnames
if ischar(EEG.urevent(1).(field{f}))
fprintf('%-5g -',tfields{targetcount,f})
for k=1:npos
fprintf('%-5g ',nfields{targetcount,k,f});
end % k
end % ischar
end % f
end % cellfield
end % ~NO_FIELD
end % uidx > 1
fprintf('\n');
end % debug_print
end % istarget
%
%%%%%%%%%%%%%%%%% find next target event %%%%%%%%%%%%%%%%%%%%%%
%
end % if not 'boundary' event
evidx = evidx+1; % continue event checking
end % event loop
%
%%%%%%%%% delete watibar %%%%%%%%
%
if ishandle(wb), delete(wb); end
if ~alltargs
fprintf('Returning info on the %d of %d target events that have epochs centered on them.\n',...
targetcount-noepochs,targetcount);
else
fprintf('Returning info on all %d target events (%d have epochs centered on them).\n',...
targetcount,targetcount-noepochs);
end
if debug_print
fprintf('---------------------------------------------------\n');
fprintf('ur# event # ttype targtype - delays (urnbr) ms\n');
end
%
%%%%%%%%%%%%%% Truncate the output arrays %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
if targetcount > 0
targs = [targs(1:targetcount) ur_trgs(1:targetcount) ...
targepochs(1:targetcount) targidx(1:targetcount)]; % 4-column output
ur_nbrs = ur_nbrs(1:targetcount,:);
delays = delays(1:targetcount,:);
epcenttargs = find(~isnan(targs(:,3))); % find targets that have an epoch centered on them
if ~alltargs
targs = targs(epcenttargs,:);
ur_nbrs = ur_nbrs(epcenttargs,:);
delays = delays(epcenttargs,:);
end
if ~exist('NO_FIELD','var')
if cellfld == 0
tfields = tfields(1:targetcount,:);
nfields = nfields(1:targetcount,:,:);
elseif cellfld == 1
tfields = tfields(1:targetcount,:);
nfields = nfields(1:targetcount,:,:);
end
if ~alltargs
tfields = tfields(epcenttargs,:);
nfields = nfields(epcenttargs,:,:);
end
else % NO_FIELD
tfields = [];
nfields = [];
end
ur_nbrtypes = ur_nbrtypes(1:targetcount,:);
if ~alltargs
ur_nbrtypes = ur_nbrtypes(epcenttargs,:);
end
else % return nulls if no targets found
if verbose
fprintf('eeg_context(): No target type events found.\n')
end
delays = [];
targs = [];
ur_nbrs = [];
tfields = [];
nfields = [];
end