14
14
%
15
15
% A montage is specified as a structure with the fields
16
16
% montage.tra = MxN matrix
17
- % montage.labelorg = Nx1 cell-array
17
+ % montage.labelold = Nx1 cell-array
18
18
% montage.labelnew = Mx1 cell-array
19
19
%
20
20
% As an example, a bipolar montage could look like this
21
- % bipolar.labelorg = {'1', '2', '3', '4'}
21
+ % bipolar.labelold = {'1', '2', '3', '4'}
22
22
% bipolar.labelnew = {'1-2', '2-3', '3-4'}
23
23
% bipolar.tra = [
24
24
% +1 -1 0 0
28
28
%
29
29
% The montage can optionally also specify the channel type and unit of the input
30
30
% and output data with
31
- % montage.chantypeorg = Nx1 cell-array
31
+ % montage.chantypeold = Nx1 cell-array
32
32
% montage.chantypenew = Mx1 cell-array
33
- % montage.chanunitorg = Nx1 cell-array
33
+ % montage.chanunitold = Nx1 cell-array
34
34
% montage.chanunitnew = Mx1 cell-array
35
35
%
36
36
% Additional options should be specified in key-value pairs and can be
74
74
return
75
75
end
76
76
77
+ % use "old/new" instead of "org/new"
78
+ montage = fixmontage(montage );
79
+
77
80
% get optional input arguments
78
81
keepunused = ft_getopt(varargin , ' keepunused' , ' no' );
79
82
inverse = ft_getopt(varargin , ' inverse' , ' no' );
88
91
end
89
92
90
93
% these are optional, at the end we will clean up the output in case they did not exist
91
- haschantype = (isfield(input , ' chantype' ) || isfield(input , ' chantypenew' )) && all(isfield(montage , {' chantypeorg ' , ' chantypenew' }));
92
- haschanunit = (isfield(input , ' chanunit' ) || isfield(input , ' chanunitnew' )) && all(isfield(montage , {' chanunitorg ' , ' chanunitnew' }));
94
+ haschantype = (isfield(input , ' chantype' ) || isfield(input , ' chantypenew' )) && all(isfield(montage , {' chantypeold ' , ' chantypenew' }));
95
+ haschanunit = (isfield(input , ' chanunit' ) || isfield(input , ' chanunitnew' )) && all(isfield(montage , {' chanunitold ' , ' chanunitnew' }));
93
96
94
97
% make sure they always exist to facilitate the remainder of the code
95
- if ~isfield(montage , ' chantypeorg ' )
96
- montage.chantypeorg = repmat({' unknown' }, size(montage .labelorg ));
98
+ if ~isfield(montage , ' chantypeold ' )
99
+ montage.chantypeold = repmat({' unknown' }, size(montage .labelold ));
97
100
if isfield(input , ' chantype' ) && ~istrue(inverse )
98
101
warning(' copying input chantype to montage' );
99
- [sel1 , sel2 ] = match_str(montage .labelorg , input .label );
100
- montage .chantypeorg (sel1 ) = input .chantype(sel2 );
102
+ [sel1 , sel2 ] = match_str(montage .labelold , input .label );
103
+ montage .chantypeold (sel1 ) = input .chantype(sel2 );
101
104
end
102
105
end
103
106
110
113
end
111
114
end
112
115
113
- if ~isfield(montage , ' chanunitorg ' )
114
- montage.chanunitorg = repmat({' unknown' }, size(montage .labelorg ));
116
+ if ~isfield(montage , ' chanunitold ' )
117
+ montage.chanunitold = repmat({' unknown' }, size(montage .labelold ));
115
118
if isfield(input , ' chanunit' ) && ~istrue(inverse )
116
119
warning(' copying input chanunit to montage' );
117
- [sel1 , sel2 ] = match_str(montage .labelorg , input .label );
118
- montage .chanunitorg (sel1 ) = input .chanunit(sel2 );
120
+ [sel1 , sel2 ] = match_str(montage .labelold , input .label );
121
+ montage .chanunitold (sel1 ) = input .chanunit(sel2 );
119
122
end
120
123
end
121
124
157
160
end
158
161
159
162
% check the consistency of the montage
160
- if ~iscell(montage .labelorg ) || ~iscell(montage .labelnew )
163
+ if ~iscell(montage .labelold ) || ~iscell(montage .labelnew )
161
164
error(' montage labels need to be specified in cell-arrays' );
162
165
end
163
166
164
167
% check the consistency of the montage
165
- if ~all(isfield(montage , {' tra' , ' labelorg ' , ' labelnew' }))
168
+ if ~all(isfield(montage , {' tra' , ' labelold ' , ' labelnew' }))
166
169
error(' the second input argument does not correspond to a montage' );
167
170
end
168
171
169
172
% check the consistency of the montage
170
173
if size(montage .tra ,1 )~=length(montage .labelnew )
171
174
error(' the number of channels in the montage is inconsistent' );
172
- elseif size(montage .tra ,2 )~=length(montage .labelorg )
175
+ elseif size(montage .tra ,2 )~=length(montage .labelold )
173
176
error(' the number of channels in the montage is inconsistent' );
174
177
end
175
178
189
192
190
193
if istrue(inverse )
191
194
% swap the role of the original and new channels
192
- tmp.labelnew = montage .labelorg ;
193
- tmp.labelorg = montage .labelnew ;
194
- tmp.chantypenew = montage .chantypeorg ;
195
- tmp.chantypeorg = montage .chantypenew ;
196
- tmp.chanunitnew = montage .chanunitorg ;
197
- tmp.chanunitorg = montage .chanunitnew ;
195
+ tmp.labelnew = montage .labelold ;
196
+ tmp.labelold = montage .labelnew ;
197
+ tmp.chantypenew = montage .chantypeold ;
198
+ tmp.chantypeold = montage .chantypenew ;
199
+ tmp.chanunitnew = montage .chanunitold ;
200
+ tmp.chanunitold = montage .chanunitnew ;
198
201
% apply the inverse montage, this can be used to undo a previously
199
202
% applied montage
200
203
tmp.tra = full(montage .tra );
210
213
% select and keep the columns that are non-empty, i.e. remove the empty columns
211
214
selcol = find(~all(montage .tra == 0 , 1 ));
212
215
montage.tra = montage .tra(: ,selcol );
213
- montage.labelorg = montage .labelorg (selcol );
214
- montage.chantypeorg = montage .chantypeorg (selcol );
215
- montage.chanunitorg = montage .chanunitorg (selcol );
216
+ montage.labelold = montage .labelold (selcol );
217
+ montage.chantypeold = montage .chantypeold (selcol );
218
+ montage.chanunitold = montage .chanunitold (selcol );
216
219
clear selcol
217
220
218
221
% select and remove the columns corresponding to channels that are not present in the
219
222
% original data
220
- remove = setdiff(montage .labelorg , intersect(montage .labelorg , inputlabel ));
221
- selcol = match_str(montage .labelorg , remove );
223
+ remove = setdiff(montage .labelold , intersect(montage .labelold , inputlabel ));
224
+ selcol = match_str(montage .labelold , remove );
222
225
% we cannot just remove the colums, all rows that depend on it should also be removed
223
226
selrow = false(length(montage .labelnew ),1 );
224
227
for i= 1 : length(selcol )
225
228
selrow = selrow & (montage .tra(: ,selcol(i ))~=0 );
226
229
end
227
230
% convert from indices to logical vector
228
- selcol = indx2logical(selcol , length(montage .labelorg ));
231
+ selcol = indx2logical(selcol , length(montage .labelold ));
229
232
% remove rows and columns
230
- montage.labelorg = montage .labelorg (~selcol );
233
+ montage.labelold = montage .labelold (~selcol );
231
234
montage.labelnew = montage .labelnew(~selrow );
232
- montage.chantypeorg = montage .chantypeorg (~selcol );
235
+ montage.chantypeold = montage .chantypeold (~selcol );
233
236
montage.chantypenew = montage .chantypenew(~selrow );
234
- montage.chanunitorg = montage .chanunitorg (~selcol );
237
+ montage.chanunitold = montage .chanunitold (~selcol );
235
238
montage.chanunitnew = montage .chanunitnew(~selrow );
236
239
montage.tra = montage .tra(~selrow , ~selcol );
237
240
clear remove selcol selrow i
238
241
239
242
% add columns for channels that are present in the input data but not specified in
240
243
% the montage, stick to the original order in the data
241
- [dum , ix ] = setdiff(inputlabel , montage .labelorg );
244
+ [dum , ix ] = setdiff(inputlabel , montage .labelold );
242
245
addlabel = inputlabel(sort(ix ));
243
246
addchantype = inputchantype(sort(ix ));
244
247
addchanunit = inputchanunit(sort(ix ));
264
267
% add the channels that are not rereferenced to the input and output of the
265
268
% montage
266
269
montage .tra((m +(1 : k )),(n +(1 : k ))) = eye(k );
267
- montage.labelorg = cat(1 , montage .labelorg (: ), addlabel(: ));
270
+ montage.labelold = cat(1 , montage .labelold (: ), addlabel(: ));
268
271
montage.labelnew = cat(1 , montage .labelnew(: ), addlabel(: ));
269
- montage.chantypeorg = cat(1 , montage .chantypeorg (: ), addchantype(: ));
272
+ montage.chantypeold = cat(1 , montage .chantypeold (: ), addchantype(: ));
270
273
montage.chantypenew = cat(1 , montage .chantypenew(: ), addchantype(: ));
271
- montage.chanunitorg = cat(1 , montage .chanunitorg (: ), addchanunit(: ));
274
+ montage.chanunitold = cat(1 , montage .chanunitold (: ), addchanunit(: ));
272
275
montage.chanunitnew = cat(1 , montage .chanunitnew(: ), addchanunit(: ));
273
276
else
274
277
% add the channels that are not rereferenced to the input of the montage only
275
278
montage .tra(: ,(n +(1 : k ))) = zeros(m ,k );
276
- montage.labelorg = cat(1 , montage .labelorg (: ), addlabel(: ));
277
- montage.chantypeorg = cat(1 , montage .chantypeorg (: ), addchantype(: ));
278
- montage.chanunitorg = cat(1 , montage .chanunitorg (: ), addchanunit(: ));
279
+ montage.labelold = cat(1 , montage .labelold (: ), addlabel(: ));
280
+ montage.chantypeold = cat(1 , montage .chantypeold (: ), addchantype(: ));
281
+ montage.chanunitold = cat(1 , montage .chanunitold (: ), addchanunit(: ));
279
282
end
280
283
clear addlabel addchantype addchanunit m n k
281
284
285
288
if length(unique(montage .labelnew ))~=m
286
289
error(' not all output channels of the montage are unique' );
287
290
end
288
- if length(unique(montage .labelorg ))~=n
291
+ if length(unique(montage .labelold ))~=n
289
292
error(' not all input channels of the montage are unique' );
290
293
end
291
294
292
295
% determine whether all channels that have to be rereferenced are available
293
- if length(intersect(inputlabel , montage .labelorg ))~=length(montage .labelorg )
296
+ if length(intersect(inputlabel , montage .labelold ))~=length(montage .labelold )
294
297
error(' not all channels that are required in the montage are available in the data' );
295
298
end
296
299
297
300
% reorder the columns of the montage matrix
298
- [selinput , selmontage ] = match_str(inputlabel , montage .labelorg );
301
+ [selinput , selmontage ] = match_str(inputlabel , montage .labelold );
299
302
montage.tra = montage .tra(: ,selmontage );
300
- montage.labelorg = montage .labelorg (selmontage );
301
- montage.chantypeorg = montage .chantypeorg (selmontage );
302
- montage.chanunitorg = montage .chanunitorg (selmontage );
303
+ montage.labelold = montage .labelold (selmontage );
304
+ montage.chantypeold = montage .chantypeold (selmontage );
305
+ montage.chanunitold = montage .chanunitold (selmontage );
303
306
304
307
% ensure that the montage is double precision
305
308
montage.tra = double(montage .tra );
315
318
end
316
319
317
320
% update the channel scaling if the input has different units than the montage expects
318
- if isfield(input , ' chanunit' ) && ~isequal(input .chanunit , montage .chanunitorg )
319
- scale = ft_scalingfactor(input .chanunit , montage .chanunitorg );
321
+ if isfield(input , ' chanunit' ) && ~isequal(input .chanunit , montage .chanunitold )
322
+ scale = ft_scalingfactor(input .chanunit , montage .chanunitold );
320
323
montage.tra = montage .tra * diag(scale );
321
- montage.chanunitorg = input .chanunit ;
322
- elseif isfield(input , ' chanunitnew' ) && ~isequal(input .chanunitnew , montage .chanunitorg )
323
- scale = ft_scalingfactor(input .chanunitnew , montage .chanunitorg );
324
+ montage.chanunitold = input .chanunit ;
325
+ elseif isfield(input , ' chanunitnew' ) && ~isequal(input .chanunitnew , montage .chanunitold )
326
+ scale = ft_scalingfactor(input .chanunitnew , montage .chanunitold );
324
327
montage.tra = montage .tra * diag(scale );
325
- montage.chanunitorg = input .chanunitnew ;
328
+ montage.chanunitold = input .chanunitnew ;
326
329
end
327
330
328
- if isfield(input , ' chantype' ) && ~isequal(input .chantype , montage .chantypeorg )
331
+ if isfield(input , ' chantype' ) && ~isequal(input .chantype , montage .chantypeold )
329
332
error(' inconsistent chantype in data and montage' );
330
- elseif isfield(input , ' chantypenew' ) && ~isequal(input .chantypenew , montage .chantypeorg )
333
+ elseif isfield(input , ' chantypenew' ) && ~isequal(input .chantypenew , montage .chantypeold )
331
334
error(' inconsistent chantype in data and montage' );
332
335
end
333
336
334
- if isfield(input , ' labelorg ' ) && isfield(input , ' labelnew' )
337
+ if isfield(input , ' labelold ' ) && isfield(input , ' labelnew' )
335
338
inputtype = ' montage' ;
336
339
elseif isfield(input , ' tra' )
337
340
inputtype = ' sens' ;
379
382
if keepchans
380
383
sens.chanpos = sens .chanpos(sel2 ,: );
381
384
else
382
- if ~isfield(sens , ' chanposorg ' )
383
- % add a chanposorg only if it is not there yet
384
- sens.chanposorg = sens .chanpos ;
385
+ if ~isfield(sens , ' chanposold ' )
386
+ % add a chanposold only if it is not there yet
387
+ sens.chanposold = sens .chanpos ;
385
388
end
386
389
sens.chanpos = nan(numel(montage .labelnew ),3 );
387
390
end
391
394
if keepchans
392
395
sens.chanori = sens .chanori(sel2 ,: );
393
396
else
394
- if ~isfield(sens , ' chanoriorg ' )
395
- sens.chanoriorg = sens .chanori ;
397
+ if ~isfield(sens , ' chanoriold ' )
398
+ sens.chanoriold = sens .chanori ;
396
399
end
397
400
sens.chanori = nan(numel(montage .labelnew ),3 );
398
401
end
406
409
% original label,
407
410
% type and unit
408
411
% for reference
409
- if ~isfield(sens , ' labelorg ' )
410
- sens.labelorg = inputlabel ;
412
+ if ~isfield(sens , ' labelold ' )
413
+ sens.labelold = inputlabel ;
411
414
end
412
- if ~isfield(sens , ' chantypeorg ' )
413
- sens.chantypeorg = inputchantype ;
415
+ if ~isfield(sens , ' chantypeold ' )
416
+ sens.chantypeold = inputchantype ;
414
417
end
415
- if ~isfield(sens , ' chanunitorg ' )
416
- sens.chanunitorg = inputchanunit ;
418
+ if ~isfield(sens , ' chanunitold ' )
419
+ sens.chanunitold = inputchanunit ;
417
420
end
418
421
419
422
% keep track of the order of the balancing and which one is the current one
545
548
546
549
% only retain the chantype and/or chanunit if they were present in the input
547
550
if ~haschantype
548
- input = removefields(input , {' chantype' , ' chantypeorg ' , ' chantypenew' });
551
+ input = removefields(input , {' chantype' , ' chantypeold ' , ' chantypenew' });
549
552
end
550
553
if ~haschanunit
551
- input = removefields(input , {' chanunit' , ' chanunitorg ' , ' chanunitnew' });
554
+ input = removefields(input , {' chanunit' , ' chanunitold ' , ' chanunitnew' });
552
555
end
553
556
554
557
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -568,3 +571,20 @@ function nowarning(varargin)
568
571
end
569
572
end
570
573
574
+ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575
+ % HELPER FUNCTION use "old/new" instead of "org/new"
576
+ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
577
+ function montage = fixmontage(montage )
578
+ if isfield(montage , ' labelorg' )
579
+ montage.labelold = montage .labelorg ;
580
+ montage = rmfield(montage , ' labelorg' );
581
+ end
582
+ if isfield(montage , ' chantypeorg' )
583
+ montage.chantypeold = montage .chantypeorg ;
584
+ montage = rmfield(montage , ' chantypeorg' );
585
+ end
586
+ if isfield(montage , ' chanuniteorg' )
587
+ montage.chanunitold = montage .chanunitorg ;
588
+ montage = rmfield(montage , ' chanunitorg' );
589
+ end
590
+
0 commit comments