Authored by Olivier David

Merge branch 'master' of https://gin11-git.ujf-grenoble.fr/ftract_dev/ImaGIN2

# Conflicts:
#	toolbox/ImaGIN_Electrode.m
@@ -246,7 +246,6 @@ if ~exist(figDir, 'dir') @@ -246,7 +246,6 @@ if ~exist(figDir, 'dir')
246 end 246 end
247 247
248 % close all; 248 % close all;
249 -  
250 Size = 8; % Number of channels per screenshot 249 Size = 8; % Number of channels per screenshot
251 n_c = size(D,1); 250 n_c = size(D,1);
252 if n_c >= Size 251 if n_c >= Size
@@ -254,15 +253,17 @@ if n_c >= Size @@ -254,15 +253,17 @@ if n_c >= Size
254 for i2 = 1:tmp 253 for i2 = 1:tmp
255 figure(i2); 254 figure(i2);
256 set(gcf,'Position',[629 -17 702 1101]) 255 set(gcf,'Position',[629 -17 702 1101])
257 - for i3 = 1:Size  
258 - if intersect(i3+(i2-1)*Size,interIdx) == i3+(i2-1)*Size  
259 - color = 'm'; % Channel doesn't have position and is bad  
260 - elseif intersect(i3+(i2-1)*Size,NaNbIdx) == i3+(i2-1)*Size  
261 - color = 'r'; %Bad channels will be printed in red 256 + for i3 = 1:Size
  257 + if ~ismember(chanlabels(D,i3+(i2-1)*Size),D.csv_labels)
  258 + color = 'g'; % Channel was not matched with the .csv
262 elseif intersect(i3+(i2-1)*Size,ixNaN) == i3+(i2-1)*Size 259 elseif intersect(i3+(i2-1)*Size,ixNaN) == i3+(i2-1)*Size
263 - color = 'b'; %NaN channels will be printed in blue 260 + color = 'b'; % Channel was matched, is good, has NaN coordinates
  261 + elseif intersect(i3+(i2-1)*Size,interIdx) == i3+(i2-1)*Size
  262 + color = 'm'; % Channel was matched, is bad, has NaN coordinates
  263 + elseif intersect(i3+(i2-1)*Size,NaNbIdx) == i3+(i2-1)*Size
  264 + color = 'r'; % Channel was matched, is bad, has coordinates
264 else 265 else
265 - color = 'k'; %Good channels will be printed in black 266 + color = 'k'; % Channel was matched, is good, has coordinates
266 end 267 end
267 subplot(Size,1,i3) 268 subplot(Size,1,i3)
268 plot(time(D),D(i3+(i2-1)*Size,:),color); 269 plot(time(D),D(i3+(i2-1)*Size,:),color);
@@ -284,15 +285,17 @@ if n_c >= Size @@ -284,15 +285,17 @@ if n_c >= Size
284 if rmd ~= 0 285 if rmd ~= 0
285 figure(tmp + 1) 286 figure(tmp + 1)
286 set(gcf,'Position',[629 -17 702 1101]) 287 set(gcf,'Position',[629 -17 702 1101])
287 - for i4 = 1:rmd  
288 - if intersect(i3+(i2-1)*Size+i4,interIdx)== i3+(i2-1)*Size+i4  
289 - color = 'm';  
290 - elseif intersect(i3+(i2-1)*Size+i4,NaNbIdx)== i3+(i2-1)*Size+i4  
291 - color = 'r'; 288 + for i4 = 1:rmd
  289 + if ~ismember(chanlabels(D,i3+(i2-1)*Size+i4),D.csv_labels)
  290 + color = 'g'; % Channel was not matched with the .csv
292 elseif intersect(i3+(i2-1)*Size+i4,ixNaN) == i3+(i2-1)*Size+i4 291 elseif intersect(i3+(i2-1)*Size+i4,ixNaN) == i3+(i2-1)*Size+i4
293 - color = 'b'; 292 + color = 'b'; % Channel was matched, is good, has NaN coordinates
  293 + elseif intersect(i3+(i2-1)*Size+i4,interIdx) == i3+(i2-1)*Size+i4
  294 + color = 'm'; % Channel was matched, is bad, has NaN coordinates
  295 + elseif intersect(i3+(i2-1)*Size+i4,NaNbIdx) == i3+(i2-1)*Size+i4
  296 + color = 'r'; % Channel was matched, is bad, has coordinates
294 else 297 else
295 - color = 'k'; 298 + color = 'k'; % Channel was matched, is good, has coordinates
296 end 299 end
297 subplot(rmd,1,i4) 300 subplot(rmd,1,i4)
298 plot(time(D),D(i3+(i2-1)*Size+i4,:),color); 301 plot(time(D),D(i3+(i2-1)*Size+i4,:),color);
@@ -312,15 +315,17 @@ else @@ -312,15 +315,17 @@ else
312 figure(1) 315 figure(1)
313 set(gcf,'Position',[629 -17 702 1101]) 316 set(gcf,'Position',[629 -17 702 1101])
314 for i5 = 1:n_c 317 for i5 = 1:n_c
315 - if intersect(i5,interIdx)== i5  
316 - color = 'm';  
317 - elseif intersect(i5,NaNbIdx)== i5  
318 - color = 'r';  
319 - elseif intersect(i5,ixNaN)== i5  
320 - color = 'b'; 318 + if ~ismember(chanlabels(D,i5),D.csv_labels)
  319 + color = 'g'; % Channel was not matched with the .csv
  320 + elseif intersect(i5,ixNaN) == i5
  321 + color = 'b'; % Channel was matched, is good, has NaN coordinates
  322 + elseif intersect(i5,interIdx) == i5
  323 + color = 'm'; % Channel was matched, is bad, has NaN coordinates
  324 + elseif intersect(i5,NaNbIdx) == i5
  325 + color = 'r'; % Channel was matched, is bad, has coordinates
321 else 326 else
322 - color = 'k';  
323 - end 327 + color = 'k'; % Channel was matched, is good, has coordinates
  328 + end
324 subplot(n_c,1,i5) 329 subplot(n_c,1,i5)
325 plot(time(D),D(i5,:),color); 330 plot(time(D),D(i5,:),color);
326 ylabel([num2str(i5) ' : ' D.chanlabels{i5}]) 331 ylabel([num2str(i5) ' : ' D.chanlabels{i5}])
@@ -38,7 +38,7 @@ elec= sensors(D,'eeg'); % add channels without positions into bad channels @@ -38,7 +38,7 @@ elec= sensors(D,'eeg'); % add channels without positions into bad channels
38 pos = elec.elecpos; 38 pos = elec.elecpos;
39 Sens = elec.label; 39 Sens = elec.label;
40 chanLbs = D.chanlabels; 40 chanLbs = D.chanlabels;
41 -idxNaN = find(isnan(pos(:,1))); 41 +idxNaN = [] % find(isnan(pos(:,1))); We now assume channels without coordinates are not bad (CRFs older than 2009 do not have T1pre coordinates)
42 if ~isempty(idxNaN) 42 if ~isempty(idxNaN)
43 bIdx = [bIdx(:);idxNaN(:)]; 43 bIdx = [bIdx(:);idxNaN(:)];
44 bIdx = sort(unique(bIdx)); 44 bIdx = sort(unique(bIdx));
@@ -56,7 +56,7 @@ for i0=1:size(Filename,1) @@ -56,7 +56,7 @@ for i0=1:size(Filename,1)
56 Name=Sensors.label; 56 Name=Sensors.label;
57 Position=Sensors.elecpos; 57 Position=Sensors.elecpos;
58 BadChannelsMono=badchannels(D); 58 BadChannelsMono=badchannels(D);
59 - idxNaN = find(isnan(Position(:,1))); 59 + idxNaN = [] % find(isnan(Position(:,1))); We now assume channels without coordinates are not bad (CRFs older than 2009 do not have T1pre coordinates)
60 if ~isempty(idxNaN) 60 if ~isempty(idxNaN)
61 BadChannelsMono = [BadChannelsMono(:);idxNaN(:)]; 61 BadChannelsMono = [BadChannelsMono(:);idxNaN(:)];
62 end 62 end
@@ -80,7 +80,7 @@ for i0=1:size(Filename,1) @@ -80,7 +80,7 @@ for i0=1:size(Filename,1)
80 end 80 end
81 label_name_2 = matched_2.label; 81 label_name_2 = matched_2.label;
82 label_number_2 = matched_2.index; 82 label_number_2 = matched_2.index;
83 - if strcmp(label_name_1,label_name_2) & str2num(label_number_1)+1 == str2num(label_number_2) & ~(sum(isnan(Position(i1,:))) > 0) & ~(sum(isnan(Position(i2,:))) > 0) 83 + if strcmp(label_name_1,label_name_2) & str2num(label_number_1)+1 == str2num(label_number_2)
84 matched_channels = matched_channels+1; 84 matched_channels = matched_channels+1;
85 Cpos2full(:,end+1)= mean(Position([i1 i2],:))'; 85 Cpos2full(:,end+1)= mean(Position([i1 i2],:))';
86 Cnamesfull{1,end+1}=[Name{i1} '-' Name{i2}]; 86 Cnamesfull{1,end+1}=[Name{i1} '-' Name{i2}];
@@ -48,12 +48,14 @@ if KeepEvent == 1 % Navigate all stim events @@ -48,12 +48,14 @@ if KeepEvent == 1 % Navigate all stim events
48 noteName(~ismember(double(noteName),['A':'Z' 'a':'z' '_' '.' '''' 'µ' '-' '0':'9'])) ='_'; 48 noteName(~ismember(double(noteName),['A':'Z' 'a':'z' '_' '.' '''' 'µ' '-' '0':'9'])) ='_';
49 noteName = regexprep(noteName,'_+','_'); noteName = regexprep(noteName,'µ','u'); 49 noteName = regexprep(noteName,'_+','_'); noteName = regexprep(noteName,'µ','u');
50 noteName = strrep(noteName,'usec','us'); 50 noteName = strrep(noteName,'usec','us');
  51 + noteName = strrep(noteName,'sec','us'); % HUH notes
51 noteName = regexprep(noteName,'MA','mA'); %OD 52 noteName = regexprep(noteName,'MA','mA'); %OD
52 noteName = regexprep(noteName,'Stim_Start_',''); %YUQ notes 53 noteName = regexprep(noteName,'Stim_Start_',''); %YUQ notes
53 noteName = regexprep(noteName,'Stim_Stop_',''); %YUQ notes 54 noteName = regexprep(noteName,'Stim_Stop_',''); %YUQ notes
54 noteName = strrep(noteName,'-','_'); noteName = strrep(noteName,'__','_'); 55 noteName = strrep(noteName,'-','_'); noteName = strrep(noteName,'__','_');
55 noteName = strrep(noteName,',','');noteName = strrep(noteName,'_mA_','_'); 56 noteName = strrep(noteName,',','');noteName = strrep(noteName,'_mA_','_');
56 - noteName = strrep(noteName,'sec','us'); noteName = strrep(noteName,'_us','us'); 57 + noteName = strrep(noteName,'sec','us');
  58 + noteName = strrep(noteName,'_us','us');
57 noteName = strrep(noteName,'AA','A'); noteName = strrep(noteName,'_MA_','_'); %some MIL notes 59 noteName = strrep(noteName,'AA','A'); noteName = strrep(noteName,'_MA_','_'); %some MIL notes
58 keepN = ''; noteName = strrep(noteName,'stim',''); noteName = strrep(noteName,'Stim',''); 60 keepN = ''; noteName = strrep(noteName,'stim',''); noteName = strrep(noteName,'Stim','');
59 noteName = strrep(noteName,'TextNote:',''); % for BRN datasets 61 noteName = strrep(noteName,'TextNote:',''); % for BRN datasets
@@ -93,7 +95,7 @@ if KeepEvent == 1 % Navigate all stim events @@ -93,7 +95,7 @@ if KeepEvent == 1 % Navigate all stim events
93 elseif numel(numbr{2}) == 3 95 elseif numel(numbr{2}) == 3
94 if str2double(numbr{2}(1:2)) == str2double(numbr(1)) + 1 || str2double(numbr{2}(1:2)) + 1 == str2double(numbr(1)) 96 if str2double(numbr{2}(1:2)) == str2double(numbr(1)) + 1 || str2double(numbr{2}(1:2)) + 1 == str2double(numbr(1))
95 elecno = strcat(numbr{2}(1:2),'_',numbr{2}(3)); 97 elecno = strcat(numbr{2}(1:2),'_',numbr{2}(3));
96 - noteName = strrep(noteName,numbr{2},elecno); 98 + noteName = regexprep(noteName,numbr{2},elecno,'once'); % We should replace the first match only
97 elseif str2double(numbr{2}(1)) == str2double(numbr(1)) + 1 || str2double(numbr{2}(1)) + 1 == str2double(numbr(1)) 99 elseif str2double(numbr{2}(1)) == str2double(numbr(1)) + 1 || str2double(numbr{2}(1)) + 1 == str2double(numbr(1))
98 elecno = strcat(numbr{2}(1),'_',numbr{2}(2:3)); 100 elecno = strcat(numbr{2}(1),'_',numbr{2}(2:3));
99 noteName = strrep(noteName,numbr{2},elecno); 101 noteName = strrep(noteName,numbr{2},elecno);
@@ -80,7 +80,7 @@ catch @@ -80,7 +80,7 @@ catch
80 case '.csv' 80 case '.csv'
81 [Name, Position] = readCsv(filename); 81 [Name, Position] = readCsv(filename);
82 if all(isnan(Position)) 82 if all(isnan(Position))
83 - error('Anatomy not found: possibly patient implanted before 2009. Check implantation scheme!'); 83 + warning('T1pre coordinates not found: possibly patient implanted before 2009.');
84 end 84 end
85 otherwise 85 otherwise
86 disp('ImaGIN> ERROR: Invalid input file type.'); 86 disp('ImaGIN> ERROR: Invalid input file type.');
@@ -109,9 +109,9 @@ end @@ -109,9 +109,9 @@ end
109 109
110 110
111 % Set positions 111 % Set positions
  112 +chNotFound = {};
  113 +chMatchLog = {};
112 for i0 = 1:size(t,1) 114 for i0 = 1:size(t,1)
113 - chNotFound = {};  
114 - chMatchLog = {};  
115 T = deblank(t(i0,:)); 115 T = deblank(t(i0,:));
116 % Clone file if requested in input 116 % Clone file if requested in input
117 if (nargin >= 1) && isfield(S, 'FileOut') && ~isempty(S.FileOut) 117 if (nargin >= 1) && isfield(S, 'FileOut') && ~isempty(S.FileOut)
@@ -133,10 +133,9 @@ for i0 = 1:size(t,1) @@ -133,10 +133,9 @@ for i0 = 1:size(t,1)
133 % Loop on all channels available in the file 133 % Loop on all channels available in the file
134 for i1 = 1:length(Sensors.label) 134 for i1 = 1:length(Sensors.label)
135 sensLtmp = Sensors.label{i1}; 135 sensLtmp = Sensors.label{i1};
136 - sensLtmp(ismember(double(sensLtmp),[',' ';' '-'])) =''; 136 + sensLtmp(ismember(double(sensLtmp),[',' ';' '-' '_'])) ='';
137 Sensors.label{i1} = sensLtmp; 137 Sensors.label{i1} = sensLtmp;
138 iChanPos = findChannel(Sensors.label{i1}, Name, 'all_upper'); 138 iChanPos = findChannel(Sensors.label{i1}, Name, 'all_upper');
139 - iChanPos = findChannel(upper(Sensors.label{i1}), upper(Name), 'all_upper');  
140 % If the channel was already found in the list before: check the best option based on the case 139 % If the channel was already found in the list before: check the best option based on the case
141 if ~isempty(iChanPos) && ~isempty(chMatchLog) 140 if ~isempty(iChanPos) && ~isempty(chMatchLog)
142 iPrevious = find(strcmp(Name{iChanPos}, chMatchLog(:,2))); 141 iPrevious = find(strcmp(Name{iChanPos}, chMatchLog(:,2)));
@@ -163,9 +162,11 @@ for i0 = 1:size(t,1) @@ -163,9 +162,11 @@ for i0 = 1:size(t,1)
163 % Copy channel name from input name file (ADDED BY FT 5-Oct-2018) 162 % Copy channel name from input name file (ADDED BY FT 5-Oct-2018)
164 chMatchLog{end+1,1} = Sensors.label{i1}; 163 chMatchLog{end+1,1} = Sensors.label{i1};
165 chMatchLog{end,2} = Name{iChanPos}; 164 chMatchLog{end,2} = Name{iChanPos};
166 - Sensors.label{i1} = strrep(Name{iChanPos},'-',''); 165 + Sensors.label{i1} = Name{iChanPos};
167 else 166 else
168 - disp(['ImaGIN> WARNING: ' Sensors.label{i1} ' not assigned']); 167 + disp(['ImaGIN> WARNING: ' Sensors.label{i1} ' not assigned']);
  168 + Sensors.elecpos(i1,:) = NaN;
  169 + Sensors.chanpos(i1,:) = NaN;
169 chNotFound{end+1} = Sensors.label{i1}; 170 chNotFound{end+1} = Sensors.label{i1};
170 end 171 end
171 end 172 end
@@ -205,18 +206,16 @@ for i0 = 1:size(t,1) @@ -205,18 +206,16 @@ for i0 = 1:size(t,1)
205 end 206 end
206 207
207 % Match file: Correspondance between SEEG-CSV-LENA conventions 208 % Match file: Correspondance between SEEG-CSV-LENA conventions
208 - try  
209 - if isfield(S, 'FileTxtOut') && ~isempty(S.FileTxtOut)  
210 - try  
211 - fid = fopen(S.FileTxtOut,'w');  
212 - fprintf(fid,'SEEG,CSV\n');  
213 - for i = 1:size(chMatchLog,1)  
214 - fprintf(fid,'%s,%s\n', chMatchLog{i,1}, chMatchLog{i,2});  
215 - end  
216 - fclose(fid);  
217 - catch  
218 - disp('Log with matched channels names SEEG-CSV not saved.') 209 + if isfield(S, 'FileTxtOut') && ~isempty(S.FileTxtOut)
  210 + try
  211 + fid = fopen(S.FileTxtOut,'w');
  212 + fprintf(fid,'SEEG,CSV\n');
  213 + for i = 1:size(chMatchLog,1)
  214 + fprintf(fid,'%s,%s\n', chMatchLog{i,1}, chMatchLog{i,2});
219 end 215 end
  216 + fclose(fid);
  217 + catch
  218 + disp('Log with matched channels names SEEG-CSV not saved.')
220 end 219 end
221 end 220 end
222 221
@@ -226,7 +225,7 @@ for i0 = 1:size(t,1) @@ -226,7 +225,7 @@ for i0 = 1:size(t,1)
226 % Replace labels in D.channels 225 % Replace labels in D.channels
227 for iChan = 1:length(SpmMat.D.channels) 226 for iChan = 1:length(SpmMat.D.channels)
228 spmLtmp = SpmMat.D.channels(iChan).label; 227 spmLtmp = SpmMat.D.channels(iChan).label;
229 - spmLtmp(ismember(double(spmLtmp),[',' ';' '-'])) =''; 228 + spmLtmp(ismember(double(spmLtmp),[',' ';' '-' '_'])) ='';
230 SpmMat.D.channels(iChan).label = spmLtmp; 229 SpmMat.D.channels(iChan).label = spmLtmp;
231 230
232 iChanMatch = find(strcmpi(SpmMat.D.channels(iChan).label, chMatchLog(:,1))); 231 iChanMatch = find(strcmpi(SpmMat.D.channels(iChan).label, chMatchLog(:,1)));
@@ -311,20 +310,15 @@ for i0 = 1:size(t,1) @@ -311,20 +310,15 @@ for i0 = 1:size(t,1)
311 if (length(iChanMatch1) == 1) && (length(iChanMatch2) == 1) 310 if (length(iChanMatch1) == 1) && (length(iChanMatch2) == 1)
312 SpmMat.D.trials.events(iEvt).type = noteNameNew; 311 SpmMat.D.trials.events(iEvt).type = noteNameNew;
313 end 312 end
314 - end  
315 - try  
316 - csv_struct.csv_labels = csv_all_electrodes(:,1);  
317 - catch  
318 - elec_labels = Name';  
319 - elec_labels_no_primes = strrep(elec_labels,'p','''');  
320 - csv_all_electrodes = [elec_labels elec_labels_no_primes];  
321 - csv_struct.csv_labels = csv_all_electrodes(:,1);  
322 end 313 end
  314 + if ~(exist('csv_all_electrodes','var') == 1)
  315 + error('Could not match notes with channels found in the implantation file.')
  316 + end
  317 + csv_struct.csv_labels = csv_all_electrodes(:,1);
323 SpmMat.D.other = csv_struct; % Add an extra field to the .mat so we have a listing of all channel labels in the csv. 318 SpmMat.D.other = csv_struct; % Add an extra field to the .mat so we have a listing of all channel labels in the csv.
324 % Update existing .mat file 319 % Update existing .mat file
325 save(SpmFile, '-struct', 'SpmMat'); 320 save(SpmFile, '-struct', 'SpmMat');
326 save(spm_eeg_load(SpmFile)); % SPM's save to create a valid SPM object 321 save(spm_eeg_load(SpmFile)); % SPM's save to create a valid SPM object
327 - clear csv_all_electrode csv_struct  
328 end 322 end
329 323
330 end 324 end
@@ -403,8 +397,6 @@ function iChanPos = findChannel(Label, List, caseType) @@ -403,8 +397,6 @@ function iChanPos = findChannel(Label, List, caseType)
403 397
404 % Remove spaces 398 % Remove spaces
405 Label(Label == ' ') = []; 399 Label(Label == ' ') = [];
406 - % Remove spaces  
407 - List = strrep(List,'-','');  
408 % Switch case type 400 % Switch case type
409 switch (caseType) 401 switch (caseType)
410 case 'no_change' 402 case 'no_change'
@@ -113,10 +113,12 @@ for j=1:length(KeepEvent) % Navigate all stim events @@ -113,10 +113,12 @@ for j=1:length(KeepEvent) % Navigate all stim events
113 noteName(~ismember(double(noteName),['A':'Z' 'a':'z' '_' '.' '''' 'µ' '-' '0':'9'])) =''; 113 noteName(~ismember(double(noteName),['A':'Z' 'a':'z' '_' '.' '''' 'µ' '-' '0':'9'])) ='';
114 noteName = regexprep(noteName,'_+','_'); noteName = regexprep(noteName,'µ','u'); 114 noteName = regexprep(noteName,'_+','_'); noteName = regexprep(noteName,'µ','u');
115 if strcmpi(patientCode(5:end),'MIL');noteName = strrep(noteName,'.0',''); noteName = strrep(noteName,'_MA_','_');end%some MIL notes 115 if strcmpi(patientCode(5:end),'MIL');noteName = strrep(noteName,'.0',''); noteName = strrep(noteName,'_MA_','_');end%some MIL notes
116 - if strcmpi(patientCode(5:end),'REN');noteName = strrep(noteName,'.0','');end%some REN notes  
117 - if strcmpi(patientCode(5:end),'HUH');noteName = strrep(noteName,'.0','');end%some HUH notes 116 + if strcmpi(patientCode(5:end),'REN');noteName = strrep(noteName,'.0','');end%some REN notes
  117 + if strcmpi(patientCode(5:end),'BIC');noteName = strrep(noteName,'.0','');end%some BIC notes
  118 + if strcmpi(patientCode(5:end),'HUH');noteName = strrep(noteName,'.0',''); noteName = strrep(noteName,'','u'); end%some HUH notes
118 if strcmpi(patientCode(5:end),'TOU');noteName = strrep(noteName,'.0','');end%some TOU notes 119 if strcmpi(patientCode(5:end),'TOU');noteName = strrep(noteName,'.0','');end%some TOU notes
119 if strcmpi(patientCode(5:end),'GRE');noteName = strrep(noteName,'.0','');end%some GRE notes 120 if strcmpi(patientCode(5:end),'GRE');noteName = strrep(noteName,'.0','');end%some GRE notes
  121 + if strcmpi(patientCode(5:end),'FLO');noteName = strrep(noteName,'.0','');end%some FLO notes
120 noteName = strrep(noteName,'.',''); noteName = strrep(noteName,',',''); % /!\ float value becomes integer /!\ 122 noteName = strrep(noteName,'.',''); noteName = strrep(noteName,',',''); % /!\ float value becomes integer /!\
121 noteName = strrep(noteName,'sec','s'); noteName = strrep(noteName,'AA','A'); 123 noteName = strrep(noteName,'sec','s'); noteName = strrep(noteName,'AA','A');
122 noteName = strrep(noteName,'Stim_Start_',''); noteName = strrep(noteName,'Stim_Stop_',''); 124 noteName = strrep(noteName,'Stim_Start_',''); noteName = strrep(noteName,'Stim_Stop_','');