ck_xmod_stats.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. %% stats for linear models comparison
  2. %% DATA ===================================================================
  3. clear stats
  4. ecc=[]; sz=[]; % eccentricity and size
  5. signal = []; % categorical 1=MRI, 2=MUA, 3-7=LFP bands
  6. area=[]; % categorical 1=V1,4=V4
  7. model=[]; % categorical 1=lin, 2=lin_ng, 3=css, 4=dog
  8. % v1
  9. ecc = [ecc; ...
  10. mri1(m).ECC; ...
  11. mua1(m).ECC; ...
  12. ];
  13. sz = [ sz; ...
  14. mri1(m).S; ...
  15. mua1(m).S; ...
  16. ];
  17. signal = [signal;...
  18. 1*ones(size(mri1(m).S)); ...
  19. 2*ones(size(mua1(m).S)); ...
  20. ];
  21. area = [area; ...
  22. 1*ones(size(mri1(m).S)); ...
  23. 1*ones(size(mua1(m).S)); ...
  24. ];
  25. for i=1:5
  26. ecc = [ecc; lfp1(i,m).ECC];
  27. sz = [ sz; lfp1(i,m).S];
  28. signal = [signal; (2+i)*ones(size(lfp1(i,m).S))];
  29. area = [area; 1*ones(size(lfp1(i,m).S))];
  30. end
  31. % v4
  32. ecc = [ecc; ...
  33. mri4(m).ECC; ...
  34. mua4(m).ECC; ...
  35. ];
  36. sz = [ sz; ...
  37. mri4(m).S; ...
  38. mua4(m).S; ...
  39. ];
  40. signal = [signal;...
  41. 1*ones(size(mri4(m).S)); ...
  42. 2*ones(size(mua4(m).S)); ...
  43. ];
  44. area = [area; ...
  45. 4*ones(size(mri4(m).S)); ...
  46. 4*ones(size(mua4(m).S)); ...
  47. ];
  48. for i=1:5
  49. ecc = [ecc; lfp4(i,m).ECC];
  50. sz = [ sz; lfp4(i,m).S];
  51. signal = [signal; (2+i)*ones(size(lfp4(i,m).S))];
  52. area = [area; 4*ones(size(lfp4(i,m).S))];
  53. end
  54. %
  55. sigtype = {1,2,3,4,5,6,7;'mri' ,'mua','alpha','beta','theta','hgam','lgam'};
  56. signal_num=signal;
  57. for i=1:length(signal_num)
  58. sn{i,1}=sigtype{2,signal_num(i)};
  59. end
  60. signal=categorical(signal);
  61. area=categorical(area);
  62. areaname = {' V1', 'V4'};
  63. DT=table(signal,area, ecc, sz);
  64. %% PLOT SCATTER AND FITS ==================================================
  65. f_xmod = figure;
  66. set(f_xmod,'Position',[100 100 2000 800]);
  67. CLR=[...
  68. 0 0 0;...
  69. 0.85,0.33,0.10;...
  70. 0.93,0.69,0.13;...
  71. 0.47,0.67,0.19;...
  72. 0.49,0.18,0.56;...
  73. 0.30,0.75,0.93;...
  74. 0.00,0.45,0.74;...
  75. ];
  76. % do the modelfits and plot scatter and fitlines
  77. % v1 -----
  78. DT1=DT(DT.area==categorical(1) & DT.ecc<=MaxECC(1),:);
  79. mdl_v1 = fitlm(DT1,'sz ~ 1 + signal*ecc');
  80. slidx = 1+ length(mdl_v1.Coefficients.Estimate)/2;
  81. v1idx=[];
  82. for j=1:length(mdl_v1.CoefficientNames)
  83. if mdl_v1.CoefficientNames{j}(1:3) == 'sig' & ...
  84. mdl_v1.CoefficientNames{j}(end-2:end) ~= 'ecc'
  85. v1idx = [v1idx str2double(mdl_v1.CoefficientNames{j}(8:end))];
  86. end
  87. end
  88. msz = 40;
  89. subplot(2,2,1);
  90. ll={}; US=[sigtype{1,:}]; hold on; ii=1;
  91. for i=1:length(US)
  92. sel=DT1.signal==categorical(i);
  93. if sum(sel)>0
  94. scatter(DT1.ecc(sel),DT1.sz(sel),msz,...
  95. 'Marker','o',...
  96. 'MarkerEdgeColor',CLR(i,:),'MarkerFaceColor',CLR(i,:),...
  97. 'MarkerEdgeAlpha',0,'MarkerFaceAlpha',0.2);
  98. ll{ii}=sigtype{2,i};
  99. ii=ii+1;
  100. end
  101. end
  102. legend(ll,'Location','NorthEastOutside');
  103. title('V1');xlabel('Ecc');ylabel('Sz');
  104. set(gca,'xlim',[0 12.5],'ylim',[0 7],'TickDir','out');
  105. subplot(2,2,2);
  106. ll={}; US=[sigtype{1,:}]; hold on; ii=1;
  107. for i=1:length(US)
  108. sel=DT1.signal==categorical(i);
  109. if sum(sel)>0
  110. x=[0 1.5*MaxECC(1)];
  111. if i==1
  112. y=[...
  113. mdl_v1.Coefficients.Estimate(1) + ...
  114. mdl_v1.Coefficients.Estimate(slidx).*x ...
  115. ];
  116. plot(x,y, 'LineWidth',5, 'Color',CLR(i,:));
  117. else
  118. j = find(v1idx==i,1,'first');
  119. y=[...
  120. mdl_v1.Coefficients.Estimate(1) + ...
  121. mdl_v1.Coefficients.Estimate(1+j) + ...
  122. (mdl_v1.Coefficients.Estimate(slidx) + ...
  123. mdl_v1.Coefficients.Estimate(slidx+j)).*x ...
  124. ];
  125. plot(x,y, 'LineWidth',3, 'Color',CLR(i,:));
  126. end
  127. ll{ii}=sigtype{2,i};
  128. ii=ii+1;
  129. end
  130. end
  131. legend(ll,'Location','NorthEastOutside');
  132. title('V1 FIT');xlabel('Ecc');ylabel('Sz');
  133. set(gca,'xlim',[0 12.5],'ylim',[0 7],'TickDir','out');
  134. % v4
  135. DT4=DT(DT.area==categorical(4) & DT.ecc<=MaxECC(2),:);
  136. mdl_v4 = fitlm(DT4,'sz ~ 1 + signal*ecc');
  137. v4idx=[];
  138. for j=1:length(mdl_v4.CoefficientNames)
  139. if mdl_v4.CoefficientNames{j}(1:3) == 'sig' & ...
  140. mdl_v4.CoefficientNames{j}(end-2:end) ~= 'ecc'
  141. v4idx = [v4idx str2double(mdl_v4.CoefficientNames{j}(8:end))];
  142. end
  143. end
  144. subplot(2,2,3);
  145. ll={}; US=[sigtype{1,:}]; hold on; ii=1;
  146. for i=1:length(US)
  147. sel=DT4.signal==categorical(i);
  148. if sum(sel)>0
  149. %scatter(DT4.ecc(sel),DT4.sz(sel),'filled','CData',CLR(i,:));
  150. scatter(DT4.ecc(sel),DT4.sz(sel),msz,...
  151. 'Marker','o',...
  152. 'MarkerEdgeColor',CLR(i,:),'MarkerFaceColor',CLR(i,:),...
  153. 'MarkerEdgeAlpha',0,'MarkerFaceAlpha',0.25);
  154. ll{ii}=sigtype{2,i};
  155. ii=ii+1;
  156. end
  157. end
  158. legend(ll,'Location','NorthEastOutside');
  159. title('V4');xlabel('Ecc');ylabel('Sz');
  160. set(gca,'xlim',[0 12.5],'ylim',[0 7],'TickDir','out');
  161. subplot(2,2,4);
  162. ll={}; US=[sigtype{1,:}]; hold on; ii=1;
  163. for i=1:length(US)
  164. sel=DT4.signal==categorical(i);
  165. if sum(sel)>0
  166. x=[0 1.5*MaxECC(2)];
  167. if i==1
  168. y=[...
  169. mdl_v4.Coefficients.Estimate(1) + ...
  170. mdl_v4.Coefficients.Estimate(slidx).*x ...
  171. ];
  172. plot(x,y, 'LineWidth',5, 'Color',CLR(i,:));
  173. else
  174. j = find(v4idx==i,1,'first');
  175. y=[...
  176. mdl_v4.Coefficients.Estimate(1) + ...
  177. mdl_v4.Coefficients.Estimate(1+j) + ...
  178. (mdl_v4.Coefficients.Estimate(slidx) + ...
  179. mdl_v4.Coefficients.Estimate(slidx+j)).*x ...
  180. ];
  181. plot(x,y, 'LineWidth',3, 'Color',CLR(i,:));
  182. end
  183. ll{ii}=sigtype{2,i};
  184. ii=ii+1;
  185. end
  186. end
  187. legend(ll,'Location','NorthEastOutside');
  188. title('V4 FIT');xlabel('Ecc');ylabel('Sz');
  189. set(gca,'xlim',[0 12.5],'ylim',[0 7],'TickDir','out');
  190. sgtitle(['MODEL: ' MMS{m} ', Rth_mri: ' num2str(Rth_mri) ...
  191. ', Rth_ephys:' num2str(Rth_ephys)],'interpreter','none')
  192. if SaveFigs
  193. saveas(f_xmod,fullfile(pngfld, ['XMOD_REGR_' MMS{m} '.png']));
  194. saveas(f_xmod,fullfile(svgfld, ['XMOD_REGR_' MMS{m} '.svg']));
  195. end
  196. if CloseFigs; close(f_xmod); end
  197. %% WHICH SIGNAL TYPES HAVE SIGNIFICANT ECC-SZ RELATION ====================
  198. areas = [1 4];
  199. st=[sigtype{1,:}];sn=sigtype(2,:);
  200. for a = 1:length(areas) % loop over areas
  201. stats.area(a).signalswithslope = [];
  202. for s = st % loop over signals
  203. sel = ...
  204. DT.area==categorical(areas(a)) & ...
  205. DT.signal==categorical(s) & ...
  206. DT.ecc<=MaxECC(a);
  207. if sum(sel)>1
  208. tbl = DT(sel,:);
  209. mdl = fitlm(tbl,'sz ~ 1 + ecc');
  210. stats.area(a).signal(s).name = sn{s};
  211. stats.area(a).signal(s).mdl = mdl;
  212. stats.area(a).signal(s).anova = anova(mdl);
  213. stats.area(a).signal(s).ic = mdl.Coefficients(1,:);
  214. stats.area(a).signal(s).sl = mdl.Coefficients(2,:);
  215. CI = coefCI(mdl);
  216. stats.area(a).signal(s).icCI = CI(1,:);
  217. stats.area(a).signal(s).slCI = CI(2,:);
  218. if stats.area(a).signal(s).sl.pValue < 0.05
  219. stats.area(a).signalswithslope = [...
  220. stats.area(a).signalswithslope s];
  221. end
  222. fprintf(['Area ' num2str(areas(a)) ', Signal: ' num2str(sn{s}) ...
  223. ', slope: ' num2str(stats.area(a).signal(s).sl.Estimate) ...
  224. ', n = ' num2str(stats.area(a).signal(s).anova.DF(2)+1) ...
  225. ', t = ' num2str(stats.area(a).signal(s).sl.tStat) ...
  226. ', p = ' num2str(stats.area(a).signal(s).sl.pValue) '\n']);
  227. end
  228. end
  229. end
  230. %% TEST SIGNALS WITH SIGNIFICANT SLOPE TOGETHER IN ONE LINEAR MODEL =======
  231. for a = 1:length(areas) % loop over areas
  232. sel = ...
  233. DT.area==categorical(areas(a)) & ...
  234. ismember(DT.signal,categorical(stats.area(a).signalswithslope)) & ...
  235. DT.ecc<=MaxECC(a);
  236. % recreate a table to avoid empty signal categories
  237. signal2 = zeros(size(signal_num));
  238. for i=1:length(stats.area(a).signalswithslope)
  239. signal2(signal_num==stats.area(a).signalswithslope(i))=i;
  240. end
  241. signal2 = signal2(sel);
  242. area2 = area(sel);
  243. ecc2=ecc(sel);
  244. sz2=sz(sel);
  245. signal2=categorical(signal2);
  246. tbl2=table(signal2,area2, ecc2, sz2);
  247. mdl2 = fitlm(tbl2,'sz2 ~ signal2*ecc2');
  248. stats.area(a).full.mdl = mdl2;
  249. stats.area(a).full.anova = anova(mdl2);
  250. stats.area(a).full.signals = sn(stats.area(a).signalswithslope);
  251. fprintf('========================================\n')
  252. fprintf(['All significant signal types in one model V' num2str(areas(a)) '\n']);
  253. fprintf('========================================\n')
  254. fprintf('Eccentricity\n')
  255. fprintf(['F = ' num2str(stats.area(a).full.anova.F(2)) ...
  256. ', df = ' num2str(stats.area(a).full.anova.DF(2)) ...
  257. ', p = ' num2str(stats.area(a).full.anova.pValue(2)) '\n']);
  258. fprintf('Signal\n')
  259. fprintf(['F = ' num2str(stats.area(a).full.anova.F(1)) ...
  260. ', df = ' num2str(stats.area(a).full.anova.DF(1)) ...
  261. ', p = ' num2str(stats.area(a).full.anova.pValue(1)) '\n']);
  262. fprintf('Ecc*Signal\n')
  263. fprintf(['F = ' num2str(stats.area(a).full.anova.F(3)) ...
  264. ', df = ' num2str(stats.area(a).full.anova.DF(3)) ...
  265. ', p = ' num2str(stats.area(a).full.anova.pValue(3)) '\n']);
  266. end
  267. clear signal2;
  268. %% TEST SIGNALS WITH SIGNIFICANT SLOPE AGAINST MRI ========================
  269. for a = 1:length(areas) % loop over areas
  270. ss = stats.area(a).signalswithslope; ss(ss==1)=[];
  271. sidx=1;
  272. fprintf('========================================\n')
  273. fprintf(['MRI vs EPHYS V' num2str(areas(a)) '\n']);
  274. fprintf('========================================\n')
  275. for s = ss
  276. sel = ...
  277. DT.area == categorical(areas(a)) & ...
  278. ismember(DT.signal,categorical([1 s])) & ...
  279. DT.ecc <= MaxECC(a) ;
  280. % recreate a table to avoid empty signal categories
  281. signal2 = zeros(size(signal_num));
  282. for i=1:length(stats.area(a).signalswithslope)
  283. signal2(signal_num==stats.area(a).signalswithslope(i))=i;
  284. end
  285. signal2 = signal2(sel);
  286. area2 = area(sel);
  287. ecc2=ecc(sel);
  288. sz2=sz(sel);
  289. signal2=categorical(signal2);
  290. tbl2=table(signal2,area2, ecc2, sz2);
  291. mdl2 = fitlm(tbl2,'sz2 ~ signal2*ecc2');
  292. stats.area(a).sig_vsMRI(sidx).name = sn{s};
  293. stats.area(a).sig_vsMRI(sidx).mdl = mdl2;
  294. stats.area(a).sig_vsMRI(sidx).anova = anova(mdl2);
  295. fprintf(['MRI vs ' stats.area(a).sig_vsMRI(sidx).name '\n']);
  296. fprintf('Eccentricity\n')
  297. fprintf(['F = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.F(2)) ...
  298. ', df = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.DF(2)) ...
  299. ', p = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.pValue(2)) '\n']);
  300. fprintf('Signal\n')
  301. fprintf(['F = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.F(1)) ...
  302. ', df = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.DF(1)) ...
  303. ', p = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.pValue(1)) '\n']);
  304. fprintf('Ecc*Signal\n')
  305. fprintf(['F = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.F(3)) ...
  306. ', df = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.DF(3)) ...
  307. ', p = ' num2str(stats.area(a).sig_vsMRI(sidx).anova.pValue(3)) '\n']);
  308. sidx=sidx+1;
  309. end
  310. end
  311. %% PLOT SLOPES WITH CI AND INDICATE SIGN DIFF FROM MRI ====================
  312. f_slopes = figure;
  313. set(f_slopes,'Position',[100 100 1200 400]);
  314. % V1 -----
  315. subplot(1,2,1); hold on;
  316. mri_sl = stats.area(1).signal(1).sl.Estimate;
  317. mri_sl_bot = stats.area(1).signal(1).slCI(1);
  318. mri_sl_top = stats.area(1).signal(1).slCI(2);
  319. x=[0 10]; xarea=[x fliplr(x)];
  320. yarea=[mri_sl_bot mri_sl_bot mri_sl_top mri_sl_top];
  321. fill(xarea,yarea,'r','EdgeColor','none','FaceAlpha',0.25)
  322. plot(x,[mri_sl mri_sl],'r','Linewidth',3);
  323. for s=2:7
  324. NoData=false;
  325. if isempty(stats.area(1).signal(s).sl)
  326. NoData=true;
  327. end
  328. if~NoData
  329. Y=[stats.area(1).signal(s).sl.Estimate ...
  330. stats.area(1).signal(s).slCI(1) ...
  331. stats.area(1).signal(s).slCI(2)];
  332. % check if this is significantly different from MRI
  333. isSim=false;
  334. for ss = 1:length(stats.area(1).sig_vsMRI)
  335. if strcmp(stats.area(1).signal(s).name,...
  336. stats.area(1).sig_vsMRI(ss).name) & ...
  337. stats.area(1).sig_vsMRI(ss).anova.pValue(3) > 0.05
  338. isSim=true;
  339. end
  340. end
  341. if isSim
  342. bar(s,Y(1),'FaceColor',[0.4660, 0.6740, 0.1880]);
  343. errorbar(s,Y(1),Y(1)-Y(2),Y(3)-Y(1),'k','Linestyle','none');
  344. elseif NoData
  345. % nothing to plot
  346. else
  347. bar(s,Y(1),'FaceColor',[.25 .25 .25]);
  348. errorbar(s,Y(1),Y(1)-Y(2),Y(3)-Y(1),'k','Linestyle','none');
  349. end
  350. end
  351. end
  352. set(gca,'xlim',[1.5 7.5],'ylim',[-0.1 0.5])
  353. set(gca,'xtick',1:7,'xticklabels',sigtype(2,:))
  354. ylabel('Ecc-Sz SLOPE');
  355. title('V1','interpreter','none');
  356. % V4 -----
  357. subplot(1,2,2); hold on;
  358. mri_sl = stats.area(2).signal(1).sl.Estimate;
  359. mri_sl_bot = stats.area(2).signal(1).slCI(1);
  360. mri_sl_top = stats.area(2).signal(1).slCI(2);
  361. x=[0 10]; xarea=[x fliplr(x)];
  362. yarea=[mri_sl_bot mri_sl_bot mri_sl_top mri_sl_top];
  363. fill(xarea,yarea,'r','EdgeColor','none','FaceAlpha',0.25)
  364. plot(x,[mri_sl mri_sl],'r','Linewidth',3);
  365. for s=2:7
  366. NoData=false;
  367. if isempty(stats.area(2).signal(s).sl)
  368. NoData=true;
  369. end
  370. if~NoData
  371. Y=[stats.area(2).signal(s).sl.Estimate ...
  372. stats.area(2).signal(s).slCI(1) ...
  373. stats.area(2).signal(s).slCI(2)];
  374. % check if this is significantly different from MRI
  375. isSim=false;
  376. for ss = 1:length(stats.area(2).sig_vsMRI)
  377. if strcmp(stats.area(2).signal(s).name,...
  378. stats.area(2).sig_vsMRI(ss).name) & ...
  379. stats.area(2).sig_vsMRI(ss).anova.pValue(3) > 0.05
  380. isSim=true;
  381. end
  382. end
  383. if isSim
  384. bar(s,Y(1),'FaceColor',[0.4660, 0.6740, 0.1880]);
  385. errorbar(s,Y(1),Y(1)-Y(2),Y(3)-Y(1),'k','Linestyle','none');
  386. elseif NoData
  387. % nothing to plot
  388. else
  389. bar(s,Y(1),'FaceColor',[.25 .25 .25]);
  390. errorbar(s,Y(1),Y(1)-Y(2),Y(3)-Y(1),'k','Linestyle','none');
  391. end
  392. end
  393. end
  394. set(gca,'xlim',[1.5 7.5],'ylim',[-0.10 0.5])
  395. set(gca,'xtick',1:7,'xticklabels',sigtype(2,:))
  396. ylabel('Ecc-Sz SLOPE');
  397. title('V4','interpreter','none');
  398. sgtitle(['MODEL: ' MMS{m} ', Rth_mri: ' num2str(Rth_mri) ...
  399. ', Rth_ephys:' num2str(Rth_ephys)],'interpreter','none')
  400. if SaveFigs
  401. saveas(f_slopes,fullfile(pngfld, ['XMOD_SlopeComparison_' MMS{m} '.png']));
  402. saveas(f_slopes,fullfile(svgfld, ['XMOD_SlopeComparison_' MMS{m} '.svg']));
  403. end
  404. if CloseFigs; close(f_slopes); end