behavioralAnalyses.m 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. % Computes behavioral analyses on the dACC dataset.
  2. % function developed by Demetrio Ferro. (C) CC BY-NC-SA 4.0
  3. clear all; close all; clc;
  4. savefolder='./Figures/';
  5. dACC =load('../Data/dACC_all.mat');
  6. Ntrs_dACC=arrayfun(@(cc) dACC.data{cc}.numTrials, 1:length(dACC.data));
  7. Nccs_dACC=length(dACC.data);
  8. vars1_dACC=arrayfun(@(cc) dACC.data{cc}.vars(1,3), 1:length(dACC.data));
  9. %unique_idx_dACC=find(diff([-1 Ntrs_dACC])~=0); % for consecutive sets with same number of trials, takes only the first
  10. unique_idx_dACC=find(diff([-1 vars1_dACC])~=0); % for consecutive sets with same number vars1, takes only the first
  11. dACC_s1=find(diff([-1 Ntrs_dACC(1:55)])~=0);
  12. dACC_s2=find(diff([-1 Ntrs_dACC(56:129)])~=0);
  13. dACC_s12=[dACC_s1 55+dACC_s2];
  14. %% Loading main data from vars data structures
  15. Vtl_dACC=struct2varsmat(dACC,5);
  16. Vbl_dACC=struct2varsmat(dACC,6);
  17. Vtr_dACC=struct2varsmat(dACC,7);
  18. Vbr_dACC=struct2varsmat(dACC,8);
  19. Ptl_dACC=struct2varsmat(dACC,12)./100;
  20. Ptr_dACC=struct2varsmat(dACC,13)./100;
  21. Ord_dACC=struct2varsmat(dACC,15);
  22. Chlr_dACC=struct2varsmat(dACC,16);
  23. %% Computing EV and Risk
  24. EVl_dACC = Ptl_dACC.*Vtl_dACC + (1-Ptl_dACC).*Vbl_dACC;
  25. EVr_dACC = Ptr_dACC.*Vtr_dACC + (1-Ptr_dACC).*Vbr_dACC;
  26. EVf_dACC=nan(size(EVl_dACC));
  27. EVs_dACC=nan(size(EVl_dACC));
  28. EVf_dACC(Ord_dACC==1)=EVl_dACC(Ord_dACC==1);
  29. EVf_dACC(Ord_dACC==2)=EVr_dACC(Ord_dACC==2);
  30. EVs_dACC(Ord_dACC==1)=EVr_dACC(Ord_dACC==1);
  31. EVs_dACC(Ord_dACC==2)=EVl_dACC(Ord_dACC==2);
  32. Vtf_dACC=nan(size(Ord_dACC));
  33. Vbf_dACC=nan(size(Ord_dACC));
  34. Vts_dACC=nan(size(Ord_dACC));
  35. Vbs_dACC=nan(size(Ord_dACC));
  36. Vtf_dACC(Ord_dACC==1)=Vtl_dACC(Ord_dACC==1);
  37. Vbf_dACC(Ord_dACC==1)=Vbl_dACC(Ord_dACC==1);
  38. Vts_dACC(Ord_dACC==1)=Vtr_dACC(Ord_dACC==1);
  39. Vbs_dACC(Ord_dACC==1)=Vbr_dACC(Ord_dACC==1);
  40. Vts_dACC(Ord_dACC==2)=Vtl_dACC(Ord_dACC==2);
  41. Vbs_dACC(Ord_dACC==2)=Vbl_dACC(Ord_dACC==2);
  42. Vtf_dACC(Ord_dACC==2)=Vtr_dACC(Ord_dACC==2);
  43. Vbf_dACC(Ord_dACC==2)=Vbr_dACC(Ord_dACC==2);
  44. Chfs_dACC=nan(size(Ord_dACC));
  45. Chfs_dACC(Ord_dACC==1)=Chlr_dACC(Ord_dACC==1);
  46. Chfs_dACC(Ord_dACC==2)=(1-(Chlr_dACC(Ord_dACC==2)/2-1)*2);
  47. ChC_dACC=nan(size(Ord_dACC));
  48. ChC_dACC(EVf_dACC>=EVs_dACC)=double(Chfs_dACC(EVf_dACC>=EVs_dACC)==1);
  49. ChC_dACC(EVf_dACC<=EVs_dACC)=double(Chfs_dACC(EVf_dACC<=EVs_dACC)==2);
  50. Devlr_dACC=(EVl_dACC-EVr_dACC);
  51. Devfs_dACC=(EVf_dACC-EVs_dACC);
  52. Rl_dACC = Ptl_dACC.*(Vtl_dACC-EVl_dACC).^2 + (1-Ptl_dACC).*(Vbl_dACC-EVl_dACC).^2;
  53. Rr_dACC = Ptr_dACC.*(Vtr_dACC-EVr_dACC).^2 + (1-Ptr_dACC).*(Vbr_dACC-EVr_dACC).^2;
  54. Rf_dACC=nan(size(Ord_dACC));
  55. Rs_dACC=nan(size(Ord_dACC));
  56. Rf_dACC(Ord_dACC==1) = Rl_dACC(Ord_dACC==1);
  57. Rf_dACC(Ord_dACC==2) = Rr_dACC(Ord_dACC==2);
  58. Rs_dACC(Ord_dACC==1) = Rr_dACC(Ord_dACC==1);
  59. Rs_dACC(Ord_dACC==2) = Rl_dACC(Ord_dACC==2);
  60. %% Logit choice vs EV difference dACC sgACC
  61. hff=figure('Units','Normalized','Position',[0 .33 .5 .33]);
  62. subplot(1,2,1);
  63. fitplotlogitglm((EVf_dACC(:)-EVs_dACC(:)),double((Chfs_dACC(:))==1),'r');
  64. title('dACC: logit(p_{ch1}) = \beta_0+\beta_1 (EV_{1} - EV_{2})');
  65. xlabel('EV_{1}-EV_{2}'); ylabel('p_{ch1} = probability of (ch=1)');
  66. subplot(1,2,2);
  67. fitplotlogitglm((EVr_dACC(:)-EVl_dACC(:)),double((Chlr_dACC(:))==2),'b');
  68. title('dACC: logit(p_{chR}) = \beta_0+\beta_1 (EV_{R} - EV_{L})');
  69. xlabel('EV_{R}-EV_{L}'); ylabel('p_{chR} = probability of (ch=R)');
  70. saveas(hff,[savefolder 'Fig1_logit_ch_EV.png']);
  71. saveas(hff,[savefolder 'Fig1_logit_ch_EV.svg']);
  72. %% Logit choice vs Risk difference
  73. hff=figure('Units','Normalized','Position',[0 0 .5 .33]);
  74. subplot(1,2,1);
  75. fitplotlogitglm((Rf_dACC(:)-Rs_dACC(:)),double((Chfs_dACC(:))==1),'r');
  76. title('dACC: logit(p_{ch1})=\beta_0+\beta_1 (R_{1}-R_{2})');
  77. xlabel('R_{1}-R_{2}'); ylabel('p_{ch1} = probability of (ch=1)');
  78. subplot(1,2,2);
  79. fitplotlogitglm((Rr_dACC(:)-Rl_dACC(:)),double((Chlr_dACC(:))==2),'b');
  80. title('dACC: logit(p_{chR})=\beta_0+\beta_1 (R_{R}-R_{L})');
  81. xlabel('R_{R}-R_{L}'); ylabel('p_{chR} = probability of (ch=R)');
  82. saveas(hff,[savefolder '/Fig3_logit_ch_Risk.png']);
  83. saveas(hff,[savefolder '/Fig3_logit_ch_Risk.svg']);
  84. % ---------------------------------SUPPORT----FUNCTIONS----------------------------
  85. %% Compute Logistic fits
  86. function [gfit,ginfos]=fitplotlogitglm(X, Y, colorvs, alpha, linespec, linewidth, ...
  87. beta_offset, beta_color, plot_flag, Nbins, fontsize)
  88. % plotmsem plots mean +/- sem with shaded, continuous error bars
  89. % function developed by Demetrio Ferro. (C) CC BY-NC-SA 4.0
  90. if nargin<11
  91. if nargin<10
  92. if nargin<9
  93. if nargin <7
  94. if nargin < 6
  95. if nargin < 5
  96. if nargin < 4
  97. alpha=.1;
  98. end
  99. linespec='-';
  100. end
  101. linewidth=2;
  102. end
  103. beta_offset=[max(get(gca,'XLim')).*1.2, .1, .1];
  104. end
  105. plot_flag=1;
  106. end
  107. Nbins=50;
  108. end
  109. fontsize=6;
  110. end
  111. if nargin>=3 && ischar(colorvs) && contains('kbgcrmyw',colorvs(1))
  112. color=rem(floor((strfind('kbgcrmyw',colorvs(1))-1)*[.25 .5 1]),2);
  113. if length(colorvs)>1
  114. linespec=colorvs(2:end);
  115. end
  116. elseif nargin>=3 && isa(colorvs,'double')
  117. color=colorvs(1:3);
  118. else
  119. color=[0 0 0];
  120. end
  121. if nargin<8
  122. beta_color=color;
  123. end
  124. warning('off','all');
  125. if length(Y)<=1
  126. szx=size(X);
  127. gfit.Coefficients.Estimate(1:(szx(szx>1)+1))=nan;
  128. ginfos.warn=1;
  129. ginfos.nobs=1;
  130. ginfos.warnmsg='One single observation is not enough for glm fit';
  131. elseif length(Y)>1
  132. if size(X,2)>1 && size(X,1)>1 && plot_flag
  133. error('Plot function only works with one single regressor');
  134. elseif size(X,2)>1 && size(X,1)~=length(Y)
  135. X=X';
  136. end
  137. lastwarn('');
  138. gfit=fitglm(X,Y,'Distribution','binomial','link','logit');
  139. ginfos.nobs=sum(~isnan(Y));
  140. ginfos.warnmsg=lastwarn();
  141. if ~isempty(ginfos.warnmsg)
  142. ginfos.warn=1;
  143. else
  144. ginfos.warn=0;
  145. end
  146. if plot_flag
  147. gcci=gfit.coefCI;
  148. bp=gfit.Coefficients.pValue;
  149. bv=gfit.Coefficients.Estimate;
  150. bx = bv(1) + (X*bv(2));
  151. hx = 1 ./ (1 + exp(-sort(bx)));
  152. if Nbins>0
  153. nluqEV=linspace(floor(min(X)),ceil(max(X)),Nbins);
  154. [zq,xq]=nanmeanquantized(nluqEV,X,Y);
  155. plot(xq,zq,'.','color',color); hold on;
  156. plot(sort(X),hx,linespec,'color',color,'Linewidth',linewidth);
  157. plot([0 0],[0 1],'k-','LineWidth',1);
  158. end
  159. plot([nluqEV(1) 0],[1 1]./(1+exp(-bv(1))),'--','color',color);
  160. fill([xq flip(xq)],...
  161. [glmval(gcci(:,1),xq,'logit')' flip(glmval(gcci(:,2),xq,'logit')')],...
  162. color,'edgecolor','none','facealpha',alpha);
  163. %if length(nluqEV)>1; xlim(nluqEV([1 end])); daspect([nluqEV(end)-nluqEV(1) 1 1]); end
  164. text(beta_offset(1),beta_offset(2)+beta_offset(3)*2,...
  165. sprintf(['\\beta_0 = %1.3f^{' getpstars(bp(1)) '};'],bv(1)),'color',beta_color,'FontSize',fontsize);
  166. text(beta_offset(1),beta_offset(2)+beta_offset(3)*1,...
  167. sprintf(['\\beta_1 = %1.3f^{' getpstars(bp(2)) '};'],bv(2)),'color',beta_color,'FontSize',fontsize);
  168. text(beta_offset(1),beta_offset(2)+beta_offset(3)*0,...
  169. sprintf('n= %d;',length(X)),'color',beta_color,'FontSize',fontsize);
  170. box off
  171. end
  172. end
  173. end
  174. function [ zq, xq ] = nanmeanquantized( x, y, z )
  175. % find avg z at index y with value x
  176. xq=nan(1,length(x)-1);
  177. zq=nan(1,length(x)-1);
  178. for ix=1:(length(x)-1)
  179. xq(ix)=x(ix)/2+x(ix+1)/2;
  180. if ix==(length(x)-1)
  181. zq(ix)=nanmean(z(y>=x(ix) & y<=x(ix+1)));
  182. else
  183. zq(ix)=nanmean(z(y>=x(ix) & y<x(ix+1)));
  184. end
  185. end
  186. end
  187. function [ pstars ] = getpstars( pvalue )
  188. if pvalue <0.001
  189. pstars=' ***';
  190. elseif pvalue<0.01
  191. pstars=' ** ';
  192. elseif pvalue<0.05
  193. pstars=' * ';
  194. else
  195. pstars=' - ';
  196. end
  197. end
  198. %% Get task variables
  199. function ACCmat=struct2varsmat(ACCstruct, vars_index, start_offset,end_offset)
  200. % The function takes as first input ACCstruct loaded from "../Data/dACC_all.mat" and provides task variables,
  201. % respectively indicized by the second input vars_index, in trial range start_offset:end_offset
  202. % function developed by Demetrio Ferro. (C) CC BY-NC-SA 4.0
  203. if nargin<4
  204. if nargin<3
  205. start_offset=0;
  206. end
  207. end_offset=0;
  208. end
  209. Nccs=length(ACCstruct.data);
  210. Ntrs=arrayfun(@(cc) ACCstruct.data{cc}.numTrials, 1:Nccs);
  211. ACCmat=nan(Nccs,max(Ntrs));
  212. for cc=1:Nccs
  213. Ntrcc=size(ACCstruct.data{cc}.vars,1);
  214. ACCmat(cc,:)=cat(1,ACCstruct.data{cc}.vars(:,vars_index),nan(max(Ntrs)-Ntrcc,1));
  215. ACCmat(cc,1:start_offset)=nan;
  216. ACCmat(cc,Ntrcc-end_offset+1:Ntrcc)=nan;
  217. end
  218. end