b3b_taskPLS_recognition_erf_LV1.m 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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, 'b3b_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. h = figure('units','centimeter','position',[0 0 15 10]);
  37. set(gcf,'renderer','Painters')
  38. statsPlot = [];
  39. %statsPlot = cat(1, statsPlot,squeeze(nanmean(stat.prob(1:64,:,:),1)));
  40. statsPlot = cat(1, statsPlot,squeeze(nanmean(stat.mask(1:64,:,:).*stat.prob(1:64,:,:),1)));
  41. range_plot = [-4 1.5];
  42. imagesc(stat.time,[],statsPlot, range_plot);
  43. set(gca,'Ydir','Normal');
  44. % set custom colormap
  45. ncol = 2000; cBrew = brewermap(ncol,'RdBu'); cBrew = flipud(cBrew);
  46. % adjust for unequal range
  47. reldev = min(abs(range_plot))./max(abs(range_plot));
  48. if abs(range_plot(2))<max(abs(range_plot))
  49. nadjust = [1:ncol/2, ncol/2+round(linspace(1, ncol/2, reldev*(ncol/2)))];
  50. elseif abs(range_plot(1))<max(abs(range_plot))
  51. nadjust = [round(linspace(1, ncol/2, reldev*(ncol/2))),ncol/2:ncol];
  52. else
  53. nadjust = 1:ncol;
  54. end
  55. cBrew = cBrew(nadjust,:);
  56. colormap(cBrew); colorbar;
  57. xlabel('Time [s from stim onset]'); ylabel('Frequency (Hz)');
  58. title({'ERF changes'; ['p = ', num2str(round(result.perm_result.sprob(indLV),4))]})
  59. set(findall(gcf,'-property','FontSize'),'FontSize',18)
  60. set(gca, 'YTickLabels', round(stat.freq(get(gca, 'YTick')),0));
  61. %https://de.mathworks.com/matlabcentral/answers/476715-superimposing-two-imagesc-graphs-over-each-other
  62. % h = figure('units','centimeter','position',[0 0 15 10]);
  63. % set(gcf,'renderer','Painters')
  64. % hold all; axis square;
  65. % ax1 = axes;
  66. % statsPlot = [];
  67. % statsPlot = cat(1, statsPlot,squeeze(nanmean(stat.prob(1:64,:,:),1)));
  68. % im1 = imagesc(stat.time,[],statsPlot, [-4 4]);
  69. % im1.AlphaData = .5;
  70. % axis square;
  71. % ax2 = axes;
  72. % statsPlot = [];
  73. % statsPlot = cat(1, statsPlot,squeeze(nanmean(stat.mask(1:64,:,:).*stat.prob(1:64,:,:),1)));
  74. % im2 = imagesc(stat.time,[],statsPlot, [-4 4]);
  75. % im2.AlphaData = .8;
  76. % axis square;
  77. % linkaxes([ax1,ax2])
  78. % %%Hide the top axes
  79. % ax2.Visible = 'off';
  80. % ax2.XTick = [];
  81. % ax2.YTick = [];
  82. % colormap(ax1,gray)
  83. % colormap(ax2,cBrew)
  84. % set(gca,'Ydir','Normal');
  85. % xlabel('Time [s from stim onset]'); ylabel('Frequency (Hz)');
  86. % title({'ERF changes'; ['p = ', num2str(round(result.perm_result.sprob(indLV),4))]})
  87. % set(findall(gcf,'-property','FontSize'),'FontSize',18)
  88. % set(gca, 'YTickLabels', round(stat.freq(get(gca, 'YTick')),0));
  89. % colorbar;
  90. % figureName = ['b01_pls_traces'];
  91. % saveas(h, fullfile(pn.figures, figureName), 'epsc');
  92. % saveas(h, fullfile(pn.figures, figureName), 'png');
  93. %% plot multivariate topographies
  94. % set custom colormap
  95. cBrew = brewermap(500,'RdBu');
  96. cBrew = flipud(cBrew);
  97. h = figure('units','centimeters','position',[0 0 10 10]);
  98. set(gcf,'renderer','Painters')
  99. cfg = [];
  100. cfg.layout = 'biosemi64.lay';
  101. cfg.parameter = 'powspctrm';
  102. cfg.comment = 'no';
  103. cfg.colormap = cBrew;
  104. cfg.colorbar = 'EastOutside';
  105. plotData = [];
  106. plotData.label = elec.label; % {1 x N}
  107. plotData.dimord = 'chan';
  108. cfg.zlim = [-4 4];
  109. cfg.figure = h;
  110. plotData.powspctrm = squeeze(nanmean(nanmean(stat.mask(:,stat.freq>8 & stat.freq<20,stat.time>1 & stat.time<2).*...
  111. stat.prob(:,stat.freq>8 & stat.freq<20,stat.time>1 & stat.time<2),3),2));
  112. [~, sortind] = sort(plotData.powspctrm, 'ascend');
  113. cfg.marker = 'off';
  114. cfg.highlight = 'yes';
  115. cfg.highlightchannel = plotData.label(sortind(1:6));
  116. cfg.highlightcolor = [1 1 1];
  117. cfg.highlightsymbol = '.';
  118. cfg.highlightsize = 30;
  119. ft_topoplotER(cfg,plotData);
  120. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Mean BSR');
  121. title('AlphaBeta 1-2s')
  122. %% 'Theta 1-2s'
  123. h = figure('units','centimeters','position',[0 0 10 10]);
  124. set(gcf,'renderer','Painters')
  125. cfg = [];
  126. cfg.layout = 'biosemi64.lay';
  127. cfg.parameter = 'powspctrm';
  128. cfg.comment = 'no';
  129. cfg.colormap = cBrew;
  130. cfg.colorbar = 'EastOutside';
  131. plotData = [];
  132. plotData.label = elec.label; % {1 x N}
  133. plotData.dimord = 'chan';
  134. cfg.zlim = [-2 2];
  135. cfg.figure = h;
  136. plotData.powspctrm = squeeze(nanmean(nanmean(stat.mask(:,stat.freq>2 &stat.freq<7,stat.time>1 & stat.time<2).*...
  137. stat.prob(:,stat.freq>2 & stat.freq<7,stat.time>1 & stat.time<2),3),2));
  138. [~, sortind] = sort(plotData.powspctrm, 'descend');
  139. cfg.marker = 'off';
  140. cfg.highlight = 'yes';
  141. cfg.highlightchannel = plotData.label(sortind(1:3));
  142. cfg.highlightcolor = [1 1 1];
  143. cfg.highlightsymbol = '.';
  144. cfg.highlightsize = 30;
  145. ft_topoplotER(cfg,plotData);
  146. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Mean BSR');
  147. title('Theta 1-2s')
  148. %% title('AlphaBeta 0.5-1s')
  149. h = figure('units','centimeters','position',[0 0 10 10]);
  150. set(gcf,'renderer','Painters')
  151. cfg = [];
  152. cfg.layout = 'biosemi64.lay';
  153. cfg.parameter = 'powspctrm';
  154. cfg.comment = 'no';
  155. cfg.colormap = cBrew;
  156. cfg.colorbar = 'EastOutside';
  157. plotData = [];
  158. plotData.label = elec.label; % {1 x N}
  159. plotData.dimord = 'chan';
  160. cfg.zlim = [-2 2];
  161. cfg.figure = h;
  162. plotData.powspctrm = squeeze(nanmean(nanmean(stat.mask(:,stat.freq>8 & stat.freq<20,stat.time>0.5 & stat.time<1).*...
  163. stat.prob(:,stat.freq>8 & stat.freq<20,stat.time>0.5 & stat.time<1),3),2));
  164. [~, sortind] = sort(plotData.powspctrm, 'descend');
  165. cfg.marker = 'off';
  166. cfg.highlight = 'yes';
  167. cfg.highlightchannel = plotData.label(sortind(1:3));
  168. cfg.highlightcolor = [1 1 1];
  169. cfg.highlightsymbol = '.';
  170. cfg.highlightsize = 30;
  171. ft_topoplotER(cfg,plotData);
  172. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Mean BSR');
  173. title('AlphaBeta 0.5-1s')
  174. %% plot using raincloud plot
  175. groupsizes=result.num_subj_lst;
  176. conditions=lv_evt_list;
  177. conds = {'hit'; 'miss'};
  178. condData = []; uData = [];
  179. for indGroup = 1
  180. if indGroup == 1
  181. relevantEntries = 1:groupsizes(1)*numel(conds);
  182. elseif indGroup == 2
  183. relevantEntries = groupsizes(1)*numel(conds)+1:...
  184. groupsizes(1)*numel(conds)+groupsizes(2)*numel(conds);
  185. end
  186. for indCond = 1:numel(conds)
  187. targetEntries = relevantEntries(conditions(relevantEntries)==indCond);
  188. condData{indGroup}(indCond,:) = result.vsc(targetEntries,indLV);
  189. uData{indGroup}(indCond,:) = result.usc(targetEntries,indLV);
  190. end
  191. end
  192. cBrew(1,:) = 2.*[.3 .1 .1];
  193. cBrew(2,:) = [.6 .6 .6];
  194. idx_outlier = cell(1); idx_standard = cell(1);
  195. for indGroup = 1
  196. dataToPlot = uData{indGroup}';
  197. % define outlier as lin. modulation that is more than three scaled median absolute deviations (MAD) away from the median
  198. X = [1 1; 1 2]; b=X\dataToPlot'; IndividualSlopes = b(2,:);
  199. outliers = isoutlier(IndividualSlopes, 'median');
  200. idx_outlier{indGroup} = find(outliers);
  201. idx_standard{indGroup} = find(outliers==0);
  202. end
  203. h = figure('units','centimeter','position',[0 0 8 10]);
  204. for indGroup = 1
  205. dataToPlot = uData{indGroup}';
  206. % read into cell array of the appropriate dimensions
  207. data = []; data_ws = [];
  208. for i = 1:2
  209. for j = 1:1
  210. data{i, j} = dataToPlot(:,i);
  211. % individually demean for within-subject visualization
  212. data_ws{i, j} = dataToPlot(:,i)-...
  213. nanmean(dataToPlot(:,:),2)+...
  214. repmat(nanmean(nanmean(dataToPlot(:,:),2),1),size(dataToPlot(:,:),1),1);
  215. data_nooutlier{i, j} = data{i, j};
  216. data_nooutlier{i, j}(idx_outlier{indGroup}) = [];
  217. data_ws_nooutlier{i, j} = data_ws{i, j};
  218. data_ws_nooutlier{i, j}(idx_outlier{indGroup}) = [];
  219. % sort outliers to back in original data for improved plot overlap
  220. data_ws{i, j} = [data_ws{i, j}(idx_standard{indGroup}); data_ws{i, j}(idx_outlier{indGroup})];
  221. end
  222. end
  223. % IMPORTANT: plot individually centered estimates, stats on uncentered estimates!
  224. %subplot(1,2,indGroup);
  225. set(gcf,'renderer','Painters')
  226. cla;
  227. cl = cBrew(indGroup,:);
  228. [~, dist] = rm_raincloud_fixedSpacing(data_ws, [.8 .8 .8],1);
  229. h_rc = rm_raincloud_fixedSpacing(data_ws_nooutlier, cl,1,[],[],[],dist);
  230. view([90 -90]);
  231. axis ij
  232. box(gca,'off')
  233. set(gca, 'YTickLabels', {conds{2}; conds{1}});
  234. yticks = get(gca, 'ytick'); ylim([yticks(1)-(yticks(2)-yticks(1))./2, yticks(2)+(yticks(2)-yticks(1))./1.5]);
  235. minmax = [min(min(cat(2,data_ws{:}))), max(max(cat(2,data_ws{:})))];
  236. xlim(minmax+[-0.2*diff(minmax), 0.2*diff(minmax)])
  237. ylabel('scene category'); xlabel({'Brainscore'; '[Individually centered]'})
  238. % test linear effect
  239. curData = [data_nooutlier{1, 1}, data_nooutlier{2, 1}];
  240. X = [1 1; 1 2]; b=X\curData'; IndividualSlopes = b(2,:);
  241. [~, p, ci, stats] = ttest(IndividualSlopes);
  242. title(['M:', num2str(round(mean(IndividualSlopes),3)), '; p=', num2str(round(p,3))])
  243. end