Skip to content

Commit 1881242

Browse files
Use labelOLD instead of labelORG, idem for chanpos, chanori, chantype and chanunit. This is more consistent with old/new in ft_apply_montage. The previous montages (containing "org") should still work.
1 parent 5746bca commit 1881242

File tree

5 files changed

+130
-84
lines changed

5 files changed

+130
-84
lines changed

forward/ft_apply_montage.m

Lines changed: 87 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
%
1515
% A montage is specified as a structure with the fields
1616
% montage.tra = MxN matrix
17-
% montage.labelorg = Nx1 cell-array
17+
% montage.labelold = Nx1 cell-array
1818
% montage.labelnew = Mx1 cell-array
1919
%
2020
% As an example, a bipolar montage could look like this
21-
% bipolar.labelorg = {'1', '2', '3', '4'}
21+
% bipolar.labelold = {'1', '2', '3', '4'}
2222
% bipolar.labelnew = {'1-2', '2-3', '3-4'}
2323
% bipolar.tra = [
2424
% +1 -1 0 0
@@ -28,9 +28,9 @@
2828
%
2929
% The montage can optionally also specify the channel type and unit of the input
3030
% and output data with
31-
% montage.chantypeorg = Nx1 cell-array
31+
% montage.chantypeold = Nx1 cell-array
3232
% montage.chantypenew = Mx1 cell-array
33-
% montage.chanunitorg = Nx1 cell-array
33+
% montage.chanunitold = Nx1 cell-array
3434
% montage.chanunitnew = Mx1 cell-array
3535
%
3636
% Additional options should be specified in key-value pairs and can be
@@ -74,6 +74,9 @@
7474
return
7575
end
7676

77+
% use "old/new" instead of "org/new"
78+
montage = fixmontage(montage);
79+
7780
% get optional input arguments
7881
keepunused = ft_getopt(varargin, 'keepunused', 'no');
7982
inverse = ft_getopt(varargin, 'inverse', 'no');
@@ -88,16 +91,16 @@
8891
end
8992

9093
% 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'}));
9396

9497
% 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));
97100
if isfield(input, 'chantype') && ~istrue(inverse)
98101
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);
101104
end
102105
end
103106

@@ -110,12 +113,12 @@
110113
end
111114
end
112115

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));
115118
if isfield(input, 'chanunit') && ~istrue(inverse)
116119
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);
119122
end
120123
end
121124

@@ -157,19 +160,19 @@
157160
end
158161

159162
% check the consistency of the montage
160-
if ~iscell(montage.labelorg) || ~iscell(montage.labelnew)
163+
if ~iscell(montage.labelold) || ~iscell(montage.labelnew)
161164
error('montage labels need to be specified in cell-arrays');
162165
end
163166

164167
% check the consistency of the montage
165-
if ~all(isfield(montage, {'tra', 'labelorg', 'labelnew'}))
168+
if ~all(isfield(montage, {'tra', 'labelold', 'labelnew'}))
166169
error('the second input argument does not correspond to a montage');
167170
end
168171

169172
% check the consistency of the montage
170173
if size(montage.tra,1)~=length(montage.labelnew)
171174
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)
173176
error('the number of channels in the montage is inconsistent');
174177
end
175178

@@ -189,12 +192,12 @@
189192

190193
if istrue(inverse)
191194
% 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;
198201
% apply the inverse montage, this can be used to undo a previously
199202
% applied montage
200203
tmp.tra = full(montage.tra);
@@ -210,35 +213,35 @@
210213
% select and keep the columns that are non-empty, i.e. remove the empty columns
211214
selcol = find(~all(montage.tra==0, 1));
212215
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);
216219
clear selcol
217220

218221
% select and remove the columns corresponding to channels that are not present in the
219222
% 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);
222225
% we cannot just remove the colums, all rows that depend on it should also be removed
223226
selrow = false(length(montage.labelnew),1);
224227
for i=1:length(selcol)
225228
selrow = selrow & (montage.tra(:,selcol(i))~=0);
226229
end
227230
% convert from indices to logical vector
228-
selcol = indx2logical(selcol, length(montage.labelorg));
231+
selcol = indx2logical(selcol, length(montage.labelold));
229232
% remove rows and columns
230-
montage.labelorg = montage.labelorg(~selcol);
233+
montage.labelold = montage.labelold(~selcol);
231234
montage.labelnew = montage.labelnew(~selrow);
232-
montage.chantypeorg = montage.chantypeorg(~selcol);
235+
montage.chantypeold = montage.chantypeold(~selcol);
233236
montage.chantypenew = montage.chantypenew(~selrow);
234-
montage.chanunitorg = montage.chanunitorg(~selcol);
237+
montage.chanunitold = montage.chanunitold(~selcol);
235238
montage.chanunitnew = montage.chanunitnew(~selrow);
236239
montage.tra = montage.tra(~selrow, ~selcol);
237240
clear remove selcol selrow i
238241

239242
% add columns for channels that are present in the input data but not specified in
240243
% the montage, stick to the original order in the data
241-
[dum, ix] = setdiff(inputlabel, montage.labelorg);
244+
[dum, ix] = setdiff(inputlabel, montage.labelold);
242245
addlabel = inputlabel(sort(ix));
243246
addchantype = inputchantype(sort(ix));
244247
addchanunit = inputchanunit(sort(ix));
@@ -264,18 +267,18 @@
264267
% add the channels that are not rereferenced to the input and output of the
265268
% montage
266269
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(:));
268271
montage.labelnew = cat(1, montage.labelnew(:), addlabel(:));
269-
montage.chantypeorg = cat(1, montage.chantypeorg(:), addchantype(:));
272+
montage.chantypeold = cat(1, montage.chantypeold(:), addchantype(:));
270273
montage.chantypenew = cat(1, montage.chantypenew(:), addchantype(:));
271-
montage.chanunitorg = cat(1, montage.chanunitorg(:), addchanunit(:));
274+
montage.chanunitold = cat(1, montage.chanunitold(:), addchanunit(:));
272275
montage.chanunitnew = cat(1, montage.chanunitnew(:), addchanunit(:));
273276
else
274277
% add the channels that are not rereferenced to the input of the montage only
275278
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(:));
279282
end
280283
clear addlabel addchantype addchanunit m n k
281284

@@ -285,21 +288,21 @@
285288
if length(unique(montage.labelnew))~=m
286289
error('not all output channels of the montage are unique');
287290
end
288-
if length(unique(montage.labelorg))~=n
291+
if length(unique(montage.labelold))~=n
289292
error('not all input channels of the montage are unique');
290293
end
291294

292295
% 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)
294297
error('not all channels that are required in the montage are available in the data');
295298
end
296299

297300
% reorder the columns of the montage matrix
298-
[selinput, selmontage] = match_str(inputlabel, montage.labelorg);
301+
[selinput, selmontage] = match_str(inputlabel, montage.labelold);
299302
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);
303306

304307
% ensure that the montage is double precision
305308
montage.tra = double(montage.tra);
@@ -315,23 +318,23 @@
315318
end
316319

317320
% 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);
320323
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);
324327
montage.tra = montage.tra * diag(scale);
325-
montage.chanunitorg = input.chanunitnew;
328+
montage.chanunitold = input.chanunitnew;
326329
end
327330

328-
if isfield(input, 'chantype') && ~isequal(input.chantype, montage.chantypeorg)
331+
if isfield(input, 'chantype') && ~isequal(input.chantype, montage.chantypeold)
329332
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)
331334
error('inconsistent chantype in data and montage');
332335
end
333336

334-
if isfield(input, 'labelorg') && isfield(input, 'labelnew')
337+
if isfield(input, 'labelold') && isfield(input, 'labelnew')
335338
inputtype = 'montage';
336339
elseif isfield(input, 'tra')
337340
inputtype = 'sens';
@@ -379,9 +382,9 @@
379382
if keepchans
380383
sens.chanpos = sens.chanpos(sel2,:);
381384
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;
385388
end
386389
sens.chanpos = nan(numel(montage.labelnew),3);
387390
end
@@ -391,8 +394,8 @@
391394
if keepchans
392395
sens.chanori = sens.chanori(sel2,:);
393396
else
394-
if ~isfield(sens, 'chanoriorg')
395-
sens.chanoriorg = sens.chanori;
397+
if ~isfield(sens, 'chanoriold')
398+
sens.chanoriold = sens.chanori;
396399
end
397400
sens.chanori = nan(numel(montage.labelnew),3);
398401
end
@@ -406,14 +409,14 @@
406409
% original label,
407410
% type and unit
408411
% for reference
409-
if ~isfield(sens, 'labelorg')
410-
sens.labelorg = inputlabel;
412+
if ~isfield(sens, 'labelold')
413+
sens.labelold = inputlabel;
411414
end
412-
if ~isfield(sens, 'chantypeorg')
413-
sens.chantypeorg = inputchantype;
415+
if ~isfield(sens, 'chantypeold')
416+
sens.chantypeold = inputchantype;
414417
end
415-
if ~isfield(sens, 'chanunitorg')
416-
sens.chanunitorg = inputchanunit;
418+
if ~isfield(sens, 'chanunitold')
419+
sens.chanunitold = inputchanunit;
417420
end
418421

419422
% keep track of the order of the balancing and which one is the current one
@@ -545,10 +548,10 @@
545548

546549
% only retain the chantype and/or chanunit if they were present in the input
547550
if ~haschantype
548-
input = removefields(input, {'chantype', 'chantypeorg', 'chantypenew'});
551+
input = removefields(input, {'chantype', 'chantypeold', 'chantypenew'});
549552
end
550553
if ~haschanunit
551-
input = removefields(input, {'chanunit', 'chanunitorg', 'chanunitnew'});
554+
input = removefields(input, {'chanunit', 'chanunitold', 'chanunitnew'});
552555
end
553556

554557
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -568,3 +571,20 @@ function nowarning(varargin)
568571
end
569572
end
570573

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+

forward/ft_convert_units.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@
199199
if isfield(obj, 'pnt'), obj.pnt = scale * obj.pnt; end
200200
if isfield(obj, 'pos'), obj.pos = scale * obj.pos; end
201201
if isfield(obj, 'chanpos'), obj.chanpos = scale * obj.chanpos; end
202-
if isfield(obj, 'chanposorg'), obj.chanposorg = scale * obj.chanposorg; end
202+
if isfield(obj, 'chanposorg'), obj.chanposold = scale * obj.chanposorg; end % pre-2016 version
203+
if isfield(obj, 'chanposold'), obj.chanposold = scale * obj.chanposold; end % 2016 version and later
203204
if isfield(obj, 'coilpos'), obj.coilpos = scale * obj.coilpos; end
204205
if isfield(obj, 'elecpos'), obj.elecpos = scale * obj.elecpos; end
205206

test/test_bug2332.m

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
%% verify grad has been updated successfully
2828

29-
assert(isequal(comp.grad.chanposorg, data.grad.chanpos));
29+
assert(isequal(comp.grad.chanposold, data.grad.chanpos));
3030
assert(all(isnan(comp.grad.chanpos(:))));
3131

3232
%% rejectcomponent
@@ -50,18 +50,18 @@
5050
%% verify again that grad was updated successfully
5151

5252
assert(all(isnan(datplan.grad.chanpos(:))));
53-
assert(~any(isnan(datplan.grad.chanposorg(:))));
53+
assert(~any(isnan(datplan.grad.chanposold(:))));
5454

55-
% *org fields should still reflect the original physical positions
56-
assert(isequal(datplan.grad.chanposorg, data.grad.chanpos));
55+
% *old fields should still reflect the original physical positions
56+
assert(isequal(datplan.grad.chanposold, data.grad.chanpos));
5757

5858
%% simple check that combineplanar still works
5959

6060
datcmb = ft_combineplanar([], datplan);
6161

6262
% now chanpos should be nans
6363
assert(all(isnan(datcmb.grad.chanpos(:))));
64-
% FIXME do we want a chanposorg on combined planar data as well?
64+
% FIXME do we want a chanposold on combined planar data as well?
6565

6666
%% move back to original working dir
6767

0 commit comments

Comments
 (0)