b_scenecat_n1_bl.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. currentFile = mfilename('fullpath');
  2. [pathstr,~,~] = fileparts(currentFile);
  3. cd(fullfile(pathstr,'..'))
  4. rootpath = pwd;
  5. pn.data_eeg = fullfile(rootpath, '..', 'eegmp_preproc', 'data', 'outputs', 'eeg');
  6. pn.data_erp = fullfile(rootpath, 'data', 'erp');
  7. pn.data_erf = fullfile(rootpath, 'data', 'erf');
  8. pn.tools = fullfile(rootpath, 'tools');
  9. addpath(fullfile(rootpath, '..', 'eegmp_preproc', 'tools', 'fieldtrip')); ft_defaults
  10. addpath(fullfile(pn.tools, 'BrewerMap'));
  11. addpath(fullfile(pn.tools, 'shadedErrorBar'));
  12. pn.figures = fullfile(rootpath, 'figures');
  13. %% load event info
  14. load(fullfile(pn.data_eeg, ['sub-001_task-xxxx_eeg_art.mat']), 'events');
  15. parameter = {'scene_category'; 'old'; 'behavior'; 'subsequent_memory'};
  16. for ind_param = 1:numel(parameter)
  17. conds.(parameter{ind_param}) = unique(events.(parameter{ind_param}));
  18. end
  19. %% load erp_bl
  20. for ind_id = 1:33
  21. id = sprintf('sub-%03d', ind_id);
  22. load(fullfile(pn.data_erp, [id,'_erp_bl.mat']));
  23. for ind_option = 1:numel(conds.scene_category)
  24. if ind_id == 1
  25. erpgroup.scene_category.(conds.scene_category{ind_option}) = erp_bl.scene_category{ind_option};
  26. erpgroup.scene_category.(conds.scene_category{ind_option}) = ...
  27. rmfield(erpgroup.scene_category.(conds.scene_category{ind_option}), {'avg', 'var', 'dof'});
  28. erpgroup.scene_category.(conds.scene_category{ind_option}).dimord = 'sub_chan_time';
  29. end
  30. erpgroup.scene_category.(conds.scene_category{ind_option}).avg(ind_id,:,:) = erp_bl.scene_category{ind_option}.avg;
  31. end
  32. end
  33. time = erpgroup.scene_category.manmade.time;
  34. elec = erpgroup.scene_category.manmade.elec;
  35. channels = erpgroup.scene_category.manmade.label;
  36. %idx_chans = find(ismember(channels, {'O1', 'Oz', 'O2'}));
  37. %idx_chans = find(ismember(channels, {'PO7', 'PO8'}));
  38. %idx_chans = find(ismember(channels, {'Pz', 'CPz', 'P1'}));
  39. mergeddata = cat(4, erpgroup.scene_category.manmade.avg, ...
  40. erpgroup.scene_category.natural.avg);
  41. %% plot the ERPs (for initial inspection)
  42. % manmade = erpgroup.scene_category.manmade;
  43. % manmade.avg = squeeze(nanmean(manmade.avg,1));
  44. % manmade.dimord = 'chan_time';
  45. %
  46. % natural = erpgroup.scene_category.natural;
  47. % natural.avg = squeeze(nanmean(natural.avg,1));
  48. % natural.dimord = 'chan_time';
  49. %
  50. % cfg = [];
  51. % cfg.layout = 'EEG1010.lay';
  52. % cfg.interactive = 'yes';
  53. % cfg.showoutline = 'yes';
  54. % cfg.xlim = [-.2 .3];
  55. % ft_multiplotER(cfg, natural, manmade)
  56. %% plot topography of visual N1
  57. % set custom colormap
  58. cBrew = brewermap(500,'RdBu');
  59. cBrew = flipud(cBrew);
  60. colormap(cBrew)
  61. h = figure('units','centimeters','position',[0 0 10 10]);
  62. set(gcf,'renderer','Painters')
  63. cfg = [];
  64. cfg.layout = 'EEG1005.lay';
  65. cfg.parameter = 'powspctrm';
  66. cfg.comment = 'no';
  67. cfg.colormap = cBrew;
  68. cfg.colorbar = 'EastOutside';
  69. plotData = [];
  70. plotData.label = elec.label(1:64); % {1 x N}
  71. plotData.dimord = 'chan';
  72. plotData.powspctrm = squeeze(nanmean(nanmean(nanmin(mergeddata(:,:,time>0.04 & time <0.12,1:2),[],3),1),4))';
  73. [~, sortidx] = sort(plotData.powspctrm, 'ascend');
  74. idx_chans = sortidx(1);
  75. cfg.marker = 'off';
  76. cfg.highlight = 'yes';
  77. cfg.highlightchannel = plotData.label(idx_chans);
  78. cfg.highlightcolor = [1 0 0];
  79. cfg.highlightsymbol = '.';
  80. cfg.highlightsize = 18;
  81. cfg.zlim = [-10 10]*10^-4;
  82. cfg.figure = h;
  83. ft_topoplotER(cfg,plotData);
  84. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Amplitude');
  85. set(findall(gcf,'-property','FontSize'),'FontSize',12)
  86. figureName = ['b_topo_minimum'];
  87. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  88. saveas(h, fullfile(pn.figures, figureName), 'png');
  89. %% visualize N1 over negative maximum
  90. % avg across channels and conditions
  91. condAvg = squeeze(nanmean(nanmean(mergeddata(:,idx_chans,:,1:2),2),4));
  92. condAvg1 = squeeze(nanmean(nanmean(mergeddata(:,idx_chans,:,1),2),4));
  93. condAvg2 = squeeze(nanmean(nanmean(mergeddata(:,idx_chans,:,2),2),4));
  94. h = figure('units','centimeters','position',[0 0 10 8]);
  95. cla; hold on;
  96. % new value = old value ? subject average + grand average
  97. curData = squeeze(nanmean(mergeddata(:,idx_chans,:,1),2));
  98. curData = curData-condAvg+repmat(nanmean(condAvg,1),size(condAvg,1),1);
  99. standError = nanstd(curData,1)./sqrt(size(curData,1));
  100. l1 = shadedErrorBar(time,nanmean(curData,1),standError, 'lineprops', {'color', 'k','linewidth', 2}, 'patchSaturation', .1);
  101. curData = squeeze(nanmean(mergeddata(:,idx_chans,:,2),2));
  102. curData = curData-condAvg+repmat(nanmean(condAvg,1),size(condAvg,1),1);
  103. standError = nanstd(curData,1)./sqrt(size(curData,1));
  104. l2 = shadedErrorBar(time,nanmean(curData,1),standError, 'lineprops', {'color', 'r','linewidth', 2}, 'patchSaturation', .1);
  105. % ax = gca; ax.YDir = 'reverse';
  106. xlabel('Time (s) from stim onset')
  107. xlim([-.025 .16]); %ylim([-.03 .18])
  108. ylabel({'ERP';'(microVolts)'});
  109. xlabel({'Time (s)'});
  110. set(findall(gcf,'-property','FontSize'),'FontSize',12)
  111. %% ERP components for subjects 1-17 and 18-33 are shifted in time!
  112. h = figure('units','centimeters','position',[0 0 10 8]);
  113. cla; hold on;
  114. % new value = old value ? subject average + grand average
  115. curData = squeeze(nanmean(mergeddata(1:17,idx_chans,:,1),2));
  116. standError = nanstd(curData,1)./sqrt(size(curData,1));
  117. l1 = shadedErrorBar(time,nanmean(curData,1),standError, 'lineprops', {'color', 'k','linewidth', 2}, 'patchSaturation', .1);
  118. curData = squeeze(nanmean(mergeddata(18:end,idx_chans,:,1),2));
  119. standError = nanstd(curData,1)./sqrt(size(curData,1));
  120. l2 = shadedErrorBar(time,nanmean(curData,1),standError, 'lineprops', {'color', 'r','linewidth', 2}, 'patchSaturation', .1);
  121. % ax = gca; ax.YDir = 'reverse';
  122. legend({'Initial 17', 'Final 16'}, 'location', 'NorthWest'); legend('boxoff')
  123. xlabel('Time (s) from stim onset')
  124. xlim([-.025 .16]); %ylim([-.03 .18])
  125. ylabel({'ERP';'(microVolts)'});
  126. xlabel({'Time (s)'});
  127. set(findall(gcf,'-property','FontSize'),'FontSize',12)
  128. figureName = ['b_twogroups'];
  129. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  130. saveas(h, fullfile(pn.figures, figureName), 'png');
  131. %% align individual subjects N1 to first negative peak
  132. % find individual minimum (avg. across conditions) between 40 and 120 ms
  133. time2search = find(time>0.04 & time <0.12);
  134. newtime = 0-100*(time(2)-time(1)):(time(2)-time(1)):0+100*(time(2)-time(1));
  135. for indID = 1:size(condAvg,1)
  136. %[peaks, locs] = findpeaks(condAvg1(indID,:));
  137. tmp = find(islocalmin(condAvg(indID,time2search), ...
  138. 'FlatSelection', 'center', ...
  139. 'MinSeparation', 25));
  140. minVal1(indID) = condAvg1(indID,time2search(tmp(1)));
  141. curmin = time2search(tmp(1));
  142. alignedN1_1(indID,:) = condAvg1(indID,curmin-100:curmin+100);
  143. minVal2(indID) = condAvg2(indID,time2search(tmp(1)));
  144. curmin = time2search(tmp(1));
  145. alignedN1_2(indID,:) = condAvg2(indID,curmin-100:curmin+100);
  146. alignedTopo(indID,:,:) = squeeze(nanmean(mergeddata(indID,:,curmin-100:curmin+100,1:2),4));
  147. end
  148. % alternatively: consider global minimum
  149. % for indID = 1:size(condAvg,1)
  150. % [~, minLoc1(indID)] = min(condAvg(indID,time2search));
  151. % curmin = time2search(minLoc1(indID));
  152. % minVal1(indID) = condAvg1(indID,curmin);
  153. % alignedN1_1(indID,:) = condAvg1(indID,curmin-100:curmin+100);
  154. % [~, minLoc2(indID)] = min(condAvg(indID,time2search));
  155. % curmin = time2search(minLoc2(indID));
  156. % minVal1(indID) = condAvg2(indID,curmin);
  157. % alignedN1_2(indID,:) = condAvg2(indID,curmin-100:curmin+100);
  158. % end
  159. mergeddata_aligned = cat(3, alignedN1_1, alignedN1_2);
  160. [h, p, ci, stats] = ttest(minVal1, minVal2)
  161. % avg across channels and conditions
  162. condAvg_al = squeeze(nanmean(mergeddata_aligned(:,:,1:2),3));
  163. % check that troughs are aligned
  164. % figure; imagesc(zscore(condAvg_al,[],2))
  165. % figure; imagesc(condAvg_al)
  166. h = figure('units','centimeters','position',[0 0 10 8]);
  167. cla; hold on;
  168. % new value = old value ? subject average + grand average
  169. curData = squeeze(mergeddata_aligned(:,:,1));
  170. curData = curData-condAvg_al+repmat(nanmean(condAvg_al,1),size(condAvg_al,1),1);
  171. standError = nanstd(curData,1)./sqrt(size(curData,1));
  172. l1 = shadedErrorBar(newtime*1000,nanmean(curData,1),standError, 'lineprops', {'color', 'k','linewidth', 2}, 'patchSaturation', .1);
  173. curData = squeeze(mergeddata_aligned(:,:,2));
  174. curData = curData-condAvg_al+repmat(nanmean(condAvg_al,1),size(condAvg_al,1),1);
  175. standError = nanstd(curData,1)./sqrt(size(curData,1));
  176. l2 = shadedErrorBar(newtime*1000,nanmean(curData,1),standError, 'lineprops', {'color', 'r','linewidth', 2}, 'patchSaturation', .1);
  177. % ax = gca; ax.YDir = 'reverse';
  178. legend({'manmade', 'natural'}, 'location', 'NorthWest'); legend('boxoff')
  179. xlabel('Time (s) from local minimum')
  180. xlim([-100 100]); %ylim([-.03 .18])
  181. ylabel({'ERP';'(microVolts)'});
  182. xlabel({'Time (ms) from local minimum'});
  183. set(findall(gcf,'-property','FontSize'),'FontSize',12)
  184. figureName = ['b_scenecat_N1'];
  185. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  186. saveas(h, fullfile(pn.figures, figureName), 'png');
  187. %% plot topography around detected trough
  188. h = figure('units','centimeters','position',[0 0 10 10]);
  189. set(gcf,'renderer','Painters')
  190. cfg = [];
  191. cfg.layout = 'EEG1010.lay';
  192. cfg.parameter = 'powspctrm';
  193. cfg.comment = 'no';
  194. cfg.colormap = cBrew;
  195. cfg.colorbar = 'EastOutside';
  196. plotData = [];
  197. plotData.label = elec.label(1:64); % {1 x N}
  198. plotData.dimord = 'chan';
  199. plotData.powspctrm = squeeze(nanmean(nanmean(alignedTopo(:, :, newtime>-.01 & newtime < .01),3),1))';
  200. [~, sortidx] = sort(plotData.powspctrm, 'ascend');
  201. idx_chans = sortidx(1);
  202. idx_chans_visual = idx_chans;
  203. cfg.marker = 'off';
  204. cfg.highlight = 'yes';
  205. cfg.highlightchannel = plotData.label(idx_chans);
  206. cfg.highlightcolor = [1 0 0];
  207. cfg.highlightsymbol = '.';
  208. cfg.highlightsize = 18;
  209. cfg.zlim = [-5 5]*10^-4;
  210. cfg.figure = h;
  211. ft_topoplotER(cfg,plotData);
  212. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Amplitude');
  213. set(findall(gcf,'-property','FontSize'),'FontSize',12)
  214. figureName = ['b_trough_topo'];
  215. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  216. saveas(h, fullfile(pn.figures, figureName), 'png');
  217. %% plot topography for different timewindows
  218. %
  219. % timewins = [0.03 0.075; ...
  220. % 0.075, 0.1; ...
  221. % 0.1, 0.15; ...
  222. % 0.495, 0.535];
  223. %
  224. % % set custom colormap
  225. % cBrew = brewermap(500,'RdBu');
  226. % cBrew = flipud(cBrew);
  227. % colormap(cBrew)
  228. %
  229. % h = figure('units','centimeters','position',[0 0 10 10]);
  230. % set(gcf,'renderer','Painters')
  231. %
  232. % for indTime = 1:size(timewins,1)
  233. % subplot(3,2,indTime)
  234. %
  235. % cfg = [];
  236. % cfg.layout = 'EEG1010.lay';
  237. % cfg.parameter = 'powspctrm';
  238. % cfg.comment = 'no';
  239. % cfg.colormap = cBrew;
  240. % cfg.colorbar = 'EastOutside';
  241. %
  242. % plotData = [];
  243. % plotData.label = elec.label(1:64); % {1 x N}
  244. % plotData.dimord = 'chan';
  245. % plotData.powspctrm = squeeze(nanmean(nanmean(nanmean(mergeddata(:,:,time>=timewins(indTime,1) & time <=timewins(indTime,2),1),3),1),4))';
  246. % [~, sortidx] = sort(plotData.powspctrm, 'ascend');
  247. % idx_chans = sortidx(1:6);
  248. %
  249. % cfg.marker = 'off';
  250. % cfg.highlight = 'yes';
  251. % cfg.highlightchannel = plotData.label(idx_chans);
  252. % cfg.highlightcolor = [1 0 0];
  253. % cfg.highlightsymbol = '.';
  254. % cfg.highlightsize = 18;
  255. % cfg.zlim = [-10 10]*10^-4;
  256. % cfg.figure = h;
  257. % ft_topoplotER(cfg,plotData);
  258. % cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Amplitude');
  259. %
  260. % end