c1_taskPLS_novelty_frontal_erp_LV1.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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, 'c1_taskpls_erp.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. %% explore temporal loadings
  32. % h = figure('units','centimeter','position',[0 0 15 10]);
  33. % set(gcf,'renderer','Painters')
  34. % statsPlot = [];
  35. % statsPlot = cat(1, statsPlot,squeeze(nanmax(abs(stat.prob(1:64,:,:)),[],1)));
  36. % plot(stat.time,statsPlot, 'k')
  37. % xlabel('Time [s from stim onset]'); ylabel('max abs BSR');
  38. % title({'ERP changes'; ['p = ', num2str(round(result.perm_result.sprob(indLV),4))]})
  39. % set(findall(gcf,'-property','FontSize'),'FontSize',18)
  40. %
  41. % h = figure('units','centimeter','position',[0 0 15 10]);
  42. % set(gcf,'renderer','Painters')
  43. % statsPlot = [];
  44. % statsPlot = cat(1, statsPlot,squeeze(mean(stat.prob(1:64,:,:),1)));
  45. % plot(stat.time,statsPlot, 'k')
  46. % xlabel('Time [s from stim onset]'); ylabel('mean BSR');
  47. % title({'ERP changes'; ['p = ', num2str(round(result.perm_result.sprob(indLV),4))]})
  48. % set(findall(gcf,'-property','FontSize'),'FontSize',18)
  49. %% plot multivariate topographies
  50. h = figure('units','centimeters','position',[0 0 10 10]);
  51. set(gcf,'renderer','Painters')
  52. cfg = [];
  53. cfg.layout = 'biosemi64.lay';
  54. cfg.parameter = 'powspctrm';
  55. cfg.comment = 'no';
  56. cfg.colormap = cBrew;
  57. cfg.colorbar = 'EastOutside';
  58. plotData = [];
  59. plotData.label = elec.label; % {1 x N}
  60. plotData.dimord = 'chan';
  61. cfg.zlim = [-4 4];
  62. cfg.figure = h;
  63. plotData.powspctrm = squeeze(nanmean(stat.mask(:,:,:).*...
  64. stat.prob(:,:,:),3));
  65. [~, sortind] = sort(plotData.powspctrm, 'descend');
  66. cfg.marker = 'off';
  67. cfg.highlight = 'yes';
  68. cfg.highlightchannel = plotData.label(sortind([1:4])); % 38 (frontal) 32, 19, 56 (central)
  69. cfg.highlightcolor = [0 0 0];
  70. cfg.highlightsymbol = '.';
  71. cfg.highlightsize = 15;
  72. ft_topoplotER(cfg,plotData);
  73. cb = colorbar('location', 'EastOutside'); set(get(cb,'ylabel'),'string','Mean BSR');
  74. figureName = ['c1_frontal_erp_topo'];
  75. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  76. saveas(h, fullfile(pn.figures, figureName), 'png');
  77. %% plot using raincloud plot
  78. groupsizes=result.num_subj_lst;
  79. conditions=lv_evt_list;
  80. conds = {'old'; 'new'};
  81. condData = []; uData = [];
  82. for indGroup = 1
  83. if indGroup == 1
  84. relevantEntries = 1:groupsizes(1)*numel(conds);
  85. elseif indGroup == 2
  86. relevantEntries = groupsizes(1)*numel(conds)+1:...
  87. groupsizes(1)*numel(conds)+groupsizes(2)*numel(conds);
  88. end
  89. for indCond = 1:numel(conds)
  90. targetEntries = relevantEntries(conditions(relevantEntries)==indCond);
  91. condData{indGroup}(indCond,:) = result.vsc(targetEntries,indLV);
  92. uData{indGroup}(indCond,:) = result.usc(targetEntries,indLV);
  93. end
  94. end
  95. cBrew(1,:) = 2.*[.3 .1 .1];
  96. idx_outlier = cell(1); idx_standard = cell(1);
  97. for indGroup = 1
  98. dataToPlot = uData{indGroup}';
  99. % define outlier as lin. modulation that is more than three scaled median absolute deviations (MAD) away from the median
  100. X = [1 1; 1 2]; b=X\dataToPlot'; IndividualSlopes = b(2,:);
  101. outliers = isoutlier(IndividualSlopes, 'median');
  102. idx_outlier{indGroup} = find(outliers);
  103. idx_standard{indGroup} = find(outliers==0);
  104. end
  105. h = figure('units','centimeter','position',[0 0 12 10]);
  106. ax = subplot(1,1,1);
  107. for indGroup = 1
  108. dataToPlot = uData{indGroup}';
  109. % read into cell array of the appropriate dimensions
  110. data = []; data_ws = [];
  111. for i = 1:2
  112. for j = 1:1
  113. data{i, j} = dataToPlot(:,i);
  114. % individually demean for within-subject visualization
  115. data_ws{i, j} = dataToPlot(:,i)-...
  116. nanmean(dataToPlot(:,:),2)+...
  117. repmat(nanmean(nanmean(dataToPlot(:,:),2),1),size(dataToPlot(:,:),1),1);
  118. data_nooutlier{i, j} = data{i, j};
  119. data_nooutlier{i, j}(idx_outlier{indGroup}) = [];
  120. data_ws_nooutlier{i, j} = data_ws{i, j};
  121. data_ws_nooutlier{i, j}(idx_outlier{indGroup}) = [];
  122. % sort outliers to back in original data for improved plot overlap
  123. data_ws{i, j} = [data_ws{i, j}(idx_standard{indGroup}); data_ws{i, j}(idx_outlier{indGroup})];
  124. end
  125. end
  126. % IMPORTANT: plot individually centered estimates, stats on uncentered estimates!
  127. set(gcf,'renderer','Painters')
  128. cla;
  129. cl = cBrew(indGroup,:);
  130. [~, dist] = rm_raincloud_fixedSpacing(data_ws, [.8 .8 .8],1);
  131. h_rc = rm_raincloud_fixedSpacing(data_ws_nooutlier, cl,1,[],[],[],dist);
  132. view([90 -90]);
  133. axis ij
  134. box(gca,'off')
  135. set(gca, 'YTickLabels', {conds{2}; conds{1}});
  136. yticks = get(gca, 'ytick'); ylim([yticks(1)-(yticks(2)-yticks(1))./2, yticks(2)+(yticks(2)-yticks(1))./1.5]);
  137. minmax = [min(min(cat(2,data_ws{:}))), max(max(cat(2,data_ws{:})))];
  138. xlim(minmax+[-0.2*diff(minmax), 0.2*diff(minmax)])
  139. ylabel('novelty'); xlabel({'Brainscore'; '[Individually centered]'})
  140. % test linear effect
  141. curData = [data_nooutlier{1, 1}, data_nooutlier{2, 1}];
  142. X = [1 1; 1 2]; b=X\curData'; IndividualSlopes = b(2,:);
  143. [~, p, ci, stats] = ttest(IndividualSlopes);
  144. title(['M:', num2str(round(mean(IndividualSlopes),3)), '; p=', num2str(round(p,3))])
  145. end
  146. % change tick order
  147. ax.XDir = 'reverse';
  148. set(ax, 'YTickLabels', {conds{1}; conds{2}});
  149. set(findall(gcf,'-property','FontSize'),'FontSize',12)
  150. figureName = ['c1_frontalerp_rcp'];
  151. saveas(h, fullfile(pn.figures, figureName), 'epsc');
  152. saveas(h, fullfile(pn.figures, figureName), 'png');