d2_taskPLS_recognition_erf_LV1.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. % Create an overview plot featuring the results of the multivariate PLS
  2. % comparing spectral changes during the stimulus period under load
  3. clear all; cla; clc;
  4. currentFile = mfilename('fullpath');
  5. [pathstr,~,~] = fileparts(currentFile);
  6. cd(fullfile(pathstr,'..'))
  7. rootpath = pwd;
  8. pn.data = fullfile(rootpath, 'data', 'stats');
  9. pn.figures = fullfile(rootpath, 'figures');
  10. pn.tools = fullfile(rootpath, 'tools');
  11. addpath(genpath(fullfile(pn.tools, '[MEG]PLS', 'MEGPLS_PIPELINE_v2.02b')))
  12. addpath(fullfile(pn.tools, 'fieldtrip')); ft_defaults;
  13. addpath(genpath(fullfile(pn.tools, 'RainCloudPlots')));
  14. addpath(fullfile(pn.tools, 'BrewerMap'));
  15. addpath(fullfile(pn.tools, 'winsor'));
  16. % set custom colormap
  17. cBrew = brewermap(500,'RdBu');
  18. cBrew = flipud(cBrew);
  19. colormap(cBrew)
  20. load(fullfile(pn.data, 'd2_taskpls_erf.mat'),...
  21. 'stat', 'result', 'lvdat', 'lv_evt_list', 'num_chans', 'num_freqs', 'num_time')
  22. load(fullfile(rootpath, 'data','erp', ['sub-001_erp.mat']));
  23. elec = erp.scene_category{1}.elec;
  24. result.perm_result.sprob
  25. indLV = 1;
  26. lvdat = reshape(result.boot_result.compare_u(:,indLV), num_chans, num_freqs, num_time);
  27. stat.prob = lvdat;
  28. stat.mask = lvdat > 3 | lvdat < -3;
  29. % maskNaN = double(stat.mask);
  30. % maskNaN(maskNaN==0) = NaN;
  31. %% invert solution
  32. stat.mask = stat.mask;
  33. stat.prob = stat.prob.*-1;
  34. result.vsc = result.vsc.*-1;
  35. result.usc = result.usc.*-1;
  36. %% plot BSR loadings
  37. h = figure('units','centimeter','position',[0 0 15 10]);
  38. set(gcf,'renderer','Painters')
  39. statsPlot = [];
  40. %statsPlot = cat(1, statsPlot,squeeze(nanmean(stat.prob(1:64,:,:),1)));
  41. statsPlot = cat(1, statsPlot,squeeze(nanmean(stat.mask(1:64,:,:).*stat.prob(1:64,:,:),1)));
  42. range_plot = [-1 3.5];
  43. imagesc(stat.time,[],statsPlot, range_plot);
  44. set(gca,'Ydir','Normal');
  45. % set custom colormap
  46. ncol = 2000; cBrew = brewermap(ncol,'RdBu'); cBrew = flipud(cBrew);
  47. % adjust for unequal range
  48. reldev = min(abs(range_plot))./max(abs(range_plot));
  49. if abs(range_plot(2))<max(abs(range_plot))
  50. nadjust = [1:ncol/2, ncol/2+round(linspace(1, ncol/2, reldev*(ncol/2)))];
  51. elseif abs(range_plot(1))<max(abs(range_plot))
  52. nadjust = [round(linspace(1, ncol/2, reldev*(ncol/2))),ncol/2:ncol];
  53. else
  54. nadjust = 1:ncol;
  55. end
  56. cBrew = cBrew(nadjust,:);
  57. colormap(cBrew); colorbar;
  58. xlabel('Time [s from stim onset]'); ylabel('Frequency (Hz)');
  59. title({'ERF changes'; ['p = ', num2str(round(result.perm_result.sprob(indLV),4))]})
  60. set(findall(gcf,'-property','FontSize'),'FontSize',18)
  61. set(gca, 'YTickLabels', round(stat.freq(get(gca, 'YTick')),0));
  62. figureName = ['d2_erf_bsr'];
  63. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  64. saveas(h, fullfile(pn.figures, figureName), 'png');
  65. %% plot multivariate topographies
  66. % set custom colormap
  67. cBrew = brewermap(500,'RdBu');
  68. cBrew = flipud(cBrew);
  69. h = figure('units','centimeters','position',[0 0 10 10]);
  70. set(gcf,'renderer','Painters')
  71. cfg = [];
  72. cfg.layout = 'biosemi64.lay';
  73. cfg.parameter = 'powspctrm';
  74. cfg.comment = 'no';
  75. cfg.colormap = cBrew;
  76. cfg.colorbar = 'EastOutside';
  77. plotData = [];
  78. plotData.label = elec.label; % {1 x N}
  79. plotData.dimord = 'chan';
  80. cfg.zlim = [-4 4];
  81. cfg.figure = h;
  82. plotData.powspctrm = squeeze(nanmean(nanmean(stat.mask(:,stat.freq>8 & stat.freq<20,stat.time>1 & stat.time<2).*...
  83. stat.prob(:,stat.freq>8 & stat.freq<20,stat.time>1 & stat.time<2),3),2));
  84. [~, sortind] = sort(plotData.powspctrm, 'descend');
  85. cfg.marker = 'off';
  86. cfg.highlight = 'yes';
  87. cfg.highlightchannel = plotData.label(sortind(1:6)); %26, 20, 30, 31, 21, 63
  88. cfg.highlightcolor = [0 0 0];
  89. cfg.highlightsymbol = '.';
  90. cfg.highlightsize = 30;
  91. ft_topoplotER(cfg,plotData);
  92. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Mean BSR');
  93. title('AlphaBeta 1-2s')
  94. figureName = ['d2_erf_topo1'];
  95. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  96. saveas(h, fullfile(pn.figures, figureName), 'png');
  97. %% 'Theta 200 - 500 ms'
  98. h = figure('units','centimeters','position',[0 0 10 10]);
  99. set(gcf,'renderer','Painters')
  100. cfg = [];
  101. cfg.layout = 'biosemi64.lay';
  102. cfg.parameter = 'powspctrm';
  103. cfg.comment = 'no';
  104. cfg.colormap = cBrew;
  105. cfg.colorbar = 'EastOutside';
  106. plotData = [];
  107. plotData.label = elec.label; % {1 x N}
  108. plotData.dimord = 'chan';
  109. cfg.zlim = [-1.5 1.5];
  110. cfg.figure = h;
  111. plotData.powspctrm = squeeze(nanmean(nanmean(stat.mask(:,stat.freq>2 &stat.freq<7,stat.time>.3 & stat.time<.5).*...
  112. stat.prob(:,stat.freq>2 & stat.freq<7,stat.time>.3 & stat.time<.5),3),2));
  113. [~, sortind] = sort(plotData.powspctrm, 'descend');
  114. cfg.marker = 'off';
  115. cfg.highlight = 'yes';
  116. cfg.highlightchannel = plotData.label(sortind(1:2)); % 38, 47
  117. cfg.highlightcolor = [0 0 0];
  118. cfg.highlightsymbol = '.';
  119. cfg.highlightsize = 30;
  120. ft_topoplotER(cfg,plotData);
  121. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Mean BSR');
  122. title('Theta 200 - 500 ms')
  123. figureName = ['d2_erf_topo4'];
  124. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  125. saveas(h, fullfile(pn.figures, figureName), 'png');
  126. %% 'Theta 1-2s'
  127. h = figure('units','centimeters','position',[0 0 10 10]);
  128. set(gcf,'renderer','Painters')
  129. cfg = [];
  130. cfg.layout = 'biosemi64.lay';
  131. cfg.parameter = 'powspctrm';
  132. cfg.comment = 'no';
  133. cfg.colormap = cBrew;
  134. cfg.colorbar = 'EastOutside';
  135. plotData = [];
  136. plotData.label = elec.label; % {1 x N}
  137. plotData.dimord = 'chan';
  138. cfg.zlim = [-4 4];
  139. cfg.figure = h;
  140. plotData.powspctrm = squeeze(nanmean(nanmean(stat.mask(:,stat.freq>2 &stat.freq<7,stat.time>1 & stat.time<1.5).*...
  141. stat.prob(:,stat.freq>2 & stat.freq<7,stat.time>1 & stat.time<1.5),3),2));
  142. [~, sortind] = sort(plotData.powspctrm, 'ascend');
  143. cfg.marker = 'off';
  144. cfg.highlight = 'yes';
  145. cfg.highlightchannel = plotData.label([38, 47]); % 46, 47, 38
  146. cfg.highlightcolor = [1 1 1];
  147. cfg.highlightsymbol = '.';
  148. cfg.highlightsize = 30;
  149. ft_topoplotER(cfg,plotData);
  150. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Mean BSR');
  151. title('Theta 1-1.5s')
  152. figureName = ['d2_erf_topo2'];
  153. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  154. saveas(h, fullfile(pn.figures, figureName), 'png');
  155. %% title('AlphaBeta 0.5-1s')
  156. h = figure('units','centimeters','position',[0 0 10 10]);
  157. set(gcf,'renderer','Painters')
  158. cfg = [];
  159. cfg.layout = 'biosemi64.lay';
  160. cfg.parameter = 'powspctrm';
  161. cfg.comment = 'no';
  162. cfg.colormap = cBrew;
  163. cfg.colorbar = 'EastOutside';
  164. plotData = [];
  165. plotData.label = elec.label; % {1 x N}
  166. plotData.dimord = 'chan';
  167. cfg.zlim = [-1.5 1.5];
  168. cfg.figure = h;
  169. plotData.powspctrm = squeeze(nanmean(nanmean(stat.mask(:,stat.freq>8 & stat.freq<25,stat.time>0.6 & stat.time<1).*...
  170. stat.prob(:,stat.freq>8 & stat.freq<25,stat.time>0.6 & stat.time<1),3),2));
  171. [~, sortind] = sort(plotData.powspctrm, 'ascend');
  172. cfg.marker = 'off';
  173. cfg.highlight = 'yes';
  174. cfg.highlightchannel = plotData.label(sortind(1:3)); % 20, 21, 12
  175. cfg.highlightcolor = [0 0 0];
  176. cfg.highlightsymbol = '.';
  177. cfg.highlightsize = 30;
  178. ft_topoplotER(cfg,plotData);
  179. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Mean BSR');
  180. title('AlphaBeta 0.6-1s')
  181. figureName = ['d2_erf_topo3'];
  182. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  183. saveas(h, fullfile(pn.figures, figureName), 'png');
  184. %% plot using raincloud plot
  185. groupsizes=result.num_subj_lst;
  186. conditions=lv_evt_list;
  187. conds = {'hit'; 'miss'};
  188. condData = []; uData = [];
  189. for indGroup = 1
  190. if indGroup == 1
  191. relevantEntries = 1:groupsizes(1)*numel(conds);
  192. elseif indGroup == 2
  193. relevantEntries = groupsizes(1)*numel(conds)+1:...
  194. groupsizes(1)*numel(conds)+groupsizes(2)*numel(conds);
  195. end
  196. for indCond = 1:numel(conds)
  197. targetEntries = relevantEntries(conditions(relevantEntries)==indCond);
  198. condData{indGroup}(indCond,:) = result.vsc(targetEntries,indLV);
  199. uData{indGroup}(indCond,:) = result.usc(targetEntries,indLV);
  200. end
  201. end
  202. cBrew(1,:) = 2.*[.3 .1 .1];
  203. cBrew(2,:) = [.6 .6 .6];
  204. idx_outlier = cell(1); idx_standard = cell(1);
  205. for indGroup = 1
  206. dataToPlot = uData{indGroup}';
  207. % define outlier as lin. modulation that is more than three scaled median absolute deviations (MAD) away from the median
  208. X = [1 1; 1 2]; b=X\dataToPlot'; IndividualSlopes = b(2,:);
  209. outliers = isoutlier(IndividualSlopes, 'median');
  210. idx_outlier{indGroup} = find(outliers);
  211. idx_standard{indGroup} = find(outliers==0);
  212. end
  213. h = figure('units','centimeter','position',[0 0 8 10]);
  214. ax = subplot(1,1,1);
  215. for indGroup = 1
  216. dataToPlot = uData{indGroup}';
  217. % read into cell array of the appropriate dimensions
  218. data = []; data_ws = [];
  219. for i = 1:2
  220. for j = 1:1
  221. data{i, j} = dataToPlot(:,i);
  222. % individually demean for within-subject visualization
  223. data_ws{i, j} = dataToPlot(:,i)-...
  224. nanmean(dataToPlot(:,:),2)+...
  225. repmat(nanmean(nanmean(dataToPlot(:,:),2),1),size(dataToPlot(:,:),1),1);
  226. data_nooutlier{i, j} = data{i, j};
  227. data_nooutlier{i, j}(idx_outlier{indGroup}) = [];
  228. data_ws_nooutlier{i, j} = data_ws{i, j};
  229. data_ws_nooutlier{i, j}(idx_outlier{indGroup}) = [];
  230. % sort outliers to back in original data for improved plot overlap
  231. data_ws{i, j} = [data_ws{i, j}(idx_standard{indGroup}); data_ws{i, j}(idx_outlier{indGroup})];
  232. end
  233. end
  234. % IMPORTANT: plot individually centered estimates, stats on uncentered estimates!
  235. %subplot(1,2,indGroup);
  236. set(gcf,'renderer','Painters')
  237. cla;
  238. cl = cBrew(indGroup,:);
  239. [~, dist] = rm_raincloud_fixedSpacing(data_ws, [.8 .8 .8],1);
  240. h_rc = rm_raincloud_fixedSpacing(data_ws_nooutlier, cl,1,[],[],[],dist);
  241. view([90 -90]);
  242. axis ij
  243. box(gca,'off')
  244. set(gca, 'YTickLabels', {conds{2}; conds{1}});
  245. yticks = get(gca, 'ytick'); ylim([yticks(1)-(yticks(2)-yticks(1))./2, yticks(2)+(yticks(2)-yticks(1))./1.5]);
  246. minmax = [min(min(cat(2,data_ws{:}))), max(max(cat(2,data_ws{:})))];
  247. xlim(minmax+[-0.2*diff(minmax), 0.2*diff(minmax)])
  248. ylabel('recognition'); xlabel({'Brainscore'; '[Individually centered]'})
  249. % test linear effect
  250. curData = [data_nooutlier{1, 1}, data_nooutlier{2, 1}];
  251. X = [1 1; 1 2]; b=X\curData'; IndividualSlopes = b(2,:);
  252. [~, p, ci, stats] = ttest(IndividualSlopes);
  253. title(['M:', num2str(round(mean(IndividualSlopes),3)), '; p=', num2str(round(p,6))])
  254. end
  255. % make misses initial tick
  256. ax.XDir = 'reverse';
  257. set(ax, 'YTickLabels', {conds{1}; conds{2}});
  258. figureName = ['d2_erf_rcp'];
  259. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  260. saveas(h, fullfile(pn.figures, figureName), 'png');