spm_contrasts.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. function SPM = spm_contrasts(SPM,Ic)
  2. % Compute and store contrast parameters and inference SPM{.}
  3. % FORMAT SPM = spm_contrasts(SPM,Ic)
  4. %
  5. % SPM - SPM data structure
  6. % Ic - indices of xCon to compute
  7. %
  8. % This function fills in SPM.xCon and writes con_????, ess_???? and
  9. % spm?_???? images.
  10. %__________________________________________________________________________
  11. % Copyright (C) 2002-2017 Wellcome Trust Centre for Neuroimaging
  12. % Karl Friston, Will Penny & Guillaume Flandin
  13. % $Id: spm_contrasts.m 7029 2017-02-24 15:39:07Z guillaume $
  14. % Temporary copy of the SPM variable, to avoid saving it in SPM.mat unless
  15. % it has changed (faster, read-only access)
  16. %--------------------------------------------------------------------------
  17. tmpSPM = SPM;
  18. %-Change to results directory
  19. %--------------------------------------------------------------------------
  20. try, cd(SPM.swd); end
  21. %-Get contrast definitions (if available)
  22. %--------------------------------------------------------------------------
  23. try
  24. xCon = SPM.xCon;
  25. catch
  26. xCon = [];
  27. end
  28. %-Set all contrasts by default
  29. %--------------------------------------------------------------------------
  30. if nargin < 2
  31. Ic = 1:length(xCon);
  32. end
  33. Ic(Ic == 0) = [];
  34. %-Map parameter and hyperarameter files
  35. %--------------------------------------------------------------------------
  36. if ~isempty(xCon) && xCon(Ic(1)).STAT == 'P'
  37. %-Conditional estimators
  38. %----------------------------------------------------------------------
  39. Vbeta = SPM.VCbeta;
  40. else
  41. %-OLS estimators and error variance estimate
  42. %----------------------------------------------------------------------
  43. Vbeta = SPM.Vbeta;
  44. VHp = SPM.VResMS;
  45. end
  46. if spm_mesh_detect(Vbeta)
  47. file_ext = '.gii';
  48. g = SPM.xY.VY(1).private;
  49. metadata = g.private.metadata;
  50. name = {metadata.name};
  51. if any(ismember(name,'SurfaceID'))
  52. metadata = metadata(ismember(name,'SurfaceID'));
  53. metadata = {metadata.name, metadata.value};
  54. elseif isfield(g,'faces') && ~isempty(g.faces)
  55. metadata = {'SurfaceID', SPM.xY.VY(1).fname};
  56. else
  57. metadata = {};
  58. end
  59. else
  60. file_ext = spm_file_ext;
  61. metadata = {};
  62. end
  63. %-Compute & store contrast parameters, contrast/ESS images, & SPM images
  64. %==========================================================================
  65. spm('Pointer','Watch')
  66. XYZ = SPM.xVol.XYZ;
  67. iXYZ = cumprod([1,SPM.xVol.DIM(1:2)'])*XYZ - sum(cumprod(SPM.xVol.DIM(1:2)'));
  68. for i = 1:length(Ic)
  69. %-Canonicalise contrast structure with required fields
  70. %----------------------------------------------------------------------
  71. ic = Ic(i);
  72. if isempty(xCon(ic).eidf)
  73. X1o = spm_FcUtil('X1o',xCon(ic),SPM.xX.xKXs);
  74. [trMV,trMVMV] = spm_SpUtil('trMV',X1o,SPM.xX.V);
  75. xCon(ic).eidf = trMV^2/trMVMV;
  76. end
  77. %-Write contrast/ESS images?
  78. %======================================================================
  79. if isempty(xCon(ic).Vcon)
  80. switch xCon(ic).STAT
  81. case {'T','P'}
  82. if strcmp(xCon(ic).STAT,'P') && strcmp(SPM.PPM.xCon(ic).PSTAT,'F')
  83. % Bayes Factor for compound contrast
  84. %------------------------------------------------------
  85. disp('Bayes factor for compound contrast');
  86. fprintf('\t%-32s: %30s',sprintf('LogBF image %2d',ic),...
  87. '...computing'); %-#
  88. if isfield(SPM.PPM,'VB')
  89. % First level Bayes
  90. xCon = spm_vb_logbf(SPM,XYZ,xCon,ic);
  91. else
  92. % Second level Bayes
  93. xCon = spm_bayes2_logbf(SPM,XYZ,xCon,ic);
  94. end
  95. else
  96. %-Implement contrast as linear combination of beta images
  97. %------------------------------------------------------
  98. fprintf('\t%-32s: %30s',sprintf('contrast image %2d',ic),...
  99. '...computing'); %-#
  100. %-Prepare handle for contrast image
  101. %------------------------------------------------------
  102. xCon(ic).Vcon = struct(...
  103. 'fname', [sprintf('con_%04d',ic) file_ext],...
  104. 'dim', SPM.xVol.DIM',...
  105. 'dt', [spm_type('float32'), spm_platform('bigend')],...
  106. 'mat', SPM.xVol.M,...
  107. 'pinfo', [1,0,0]',...
  108. 'descrip',sprintf('Contrast %d: %s',ic,xCon(ic).name),...
  109. metadata{:});
  110. xCon(ic).Vcon = spm_data_hdr_write(xCon(ic).Vcon);
  111. %-Compute contrast
  112. %------------------------------------------------------
  113. Q = find(abs(xCon(ic).c) > 0);
  114. V = Vbeta(Q);
  115. cB = zeros(1,size(XYZ,2));
  116. for j=1:numel(V)
  117. cB = cB + xCon(ic).c(Q(j)) * spm_data_read(V(j),'xyz',XYZ);
  118. end
  119. %-Write contrast image
  120. %------------------------------------------------------
  121. tmp = NaN(SPM.xVol.DIM');
  122. tmp(iXYZ) = cB;
  123. xCon(ic).Vcon = spm_data_write(xCon(ic).Vcon,tmp);
  124. clear tmp cB
  125. fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),sprintf(...
  126. '...written %s',spm_file(xCon(ic).Vcon.fname,'filename')))%-#
  127. end
  128. case 'F' %-Implement ESS as sum of squared weighted beta images
  129. %----------------------------------------------------------
  130. fprintf('\t%-32s: %30s',sprintf('ESS image %2d',ic),...
  131. '...computing'); %-#
  132. %-Prepare handle for ESS image
  133. %----------------------------------------------------------
  134. xCon(ic).Vcon = struct(...
  135. 'fname', [sprintf('ess_%04d',ic) file_ext],...
  136. 'dim', SPM.xVol.DIM',...
  137. 'dt', [spm_type('float32'), spm_platform('bigend')],...
  138. 'mat', SPM.xVol.M,...
  139. 'pinfo', [1,0,0]',...
  140. 'descrip',sprintf('ESS contrast %d: %s',ic,xCon(ic).name),...
  141. metadata{:});
  142. xCon(ic).Vcon = spm_data_hdr_write(xCon(ic).Vcon);
  143. %-Compute ESS
  144. %----------------------------------------------------------
  145. % Residual (in parameter space) forming matrix
  146. h = spm_FcUtil('Hsqr',xCon(ic),SPM.xX.xKXs);
  147. ss = zeros(numel(Vbeta),size(XYZ,2));
  148. for j=1:numel(Vbeta)
  149. ss(j,:) = spm_data_read(Vbeta(j),'xyz',XYZ);
  150. end
  151. ss = sum((h*ss).^2,1);
  152. %-Write ESS image
  153. %----------------------------------------------------------
  154. tmp = NaN(SPM.xVol.DIM');
  155. tmp(iXYZ) = ss;
  156. xCon(ic).Vcon = spm_data_write(xCon(ic).Vcon,tmp);
  157. clear tmp ss
  158. fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),sprintf(...
  159. '...written %s',spm_file(xCon(ic).Vcon.fname,'filename')))%-#
  160. otherwise
  161. %----------------------------------------------------------
  162. error(['unknown STAT "',xCon(ic).STAT,'"'])
  163. end % (switch(xCon...)
  164. end % (if isempty(xCon(ic)...)
  165. %-Write inference SPM/PPM
  166. %======================================================================
  167. if isempty(xCon(ic).Vspm) || xCon(ic).STAT == 'P'
  168. % (always update PPM as size threshold, gamma, may have changed)
  169. fprintf('\t%-32s: %30s',sprintf('spm{%s} image %2d',xCon(ic).STAT,ic),...
  170. '...computing'); %-#
  171. switch(xCon(ic).STAT)
  172. case 'T' %-Compute SPM{t} image
  173. %----------------------------------------------------------
  174. cB = spm_data_read(xCon(ic).Vcon,'xyz',XYZ);
  175. l = spm_data_read(VHp,'xyz',XYZ); % get hyperparamters
  176. Vc = xCon(ic).c'*SPM.xX.Bcov*xCon(ic).c;
  177. SE = sqrt(l*Vc); % and standard error
  178. Z = cB./SE;
  179. str = sprintf('[%.1f]',SPM.xX.erdf);
  180. case 'P' %-Compute PPM{P} image
  181. %----------------------------------------------------------
  182. if all(strcmp({SPM.PPM.xCon(ic).PSTAT},'T'))
  183. % Simple contrast - Gaussian distributed
  184. c = xCon(ic).c;
  185. cB = spm_data_read(xCon(ic).Vcon,'xyz',XYZ);
  186. if isfield(SPM.PPM,'VB');
  187. % If posterior sd image for that contrast does
  188. % not already exist, then compute it
  189. try
  190. SPM.PPM.Vcon_sd(ic);
  191. catch
  192. SPM = spm_vb_contrasts(SPM,XYZ,xCon,ic);
  193. end
  194. % Read in posterior sd image for contrast
  195. Vsd = spm_data_read(SPM.PPM.Vcon_sd(ic),'xyz',XYZ);
  196. VcB = Vsd.^2;
  197. else
  198. VcB = c'*SPM.PPM.Cby*c;
  199. for j = 1:length(SPM.PPM.l)
  200. % hyperparameter and Taylor approximation
  201. %----------------------------------------------
  202. l = spm_data_read(SPM.VHp(j),'xyz',XYZ);
  203. VcB = VcB + (c'*SPM.PPM.dC{j}*c)*(l - SPM.PPM.l(j));
  204. end
  205. end
  206. % posterior probability cB > g
  207. %------------------------------------------------------
  208. Gamma = xCon(ic).eidf;
  209. Z = 1 - spm_Ncdf(Gamma,cB,VcB);
  210. % Convert probability to Log Odds Ratio
  211. Z = log( Z ./ (1 - Z+eps) );
  212. str = sprintf('[%.2f]',Gamma);
  213. %xCon(ic).name = [xCon(ic).name ' ' str];
  214. else
  215. % Compound contrast - Log Bayes Factor
  216. fprintf('\t\t%-75s\n','Log Bayes Factor for compound contrast');
  217. fprintf('\t%-32s: %29s\n',' ',' ');
  218. Z = spm_data_read(xCon(ic).Vcon,'xyz',XYZ);
  219. str = sprintf('[%1.2f]',xCon(ic).eidf);
  220. end
  221. case 'F' %-Compute SPM{F} image
  222. %----------------------------------------------------------
  223. MVM = spm_data_read(xCon(ic).Vcon,'xyz',XYZ)/trMV;
  224. RVR = spm_data_read(VHp,'xyz',XYZ);
  225. Z = MVM./RVR;
  226. str = sprintf('[%.1f,%.1f]',xCon(ic).eidf,SPM.xX.erdf);
  227. otherwise
  228. %----------------------------------------------------------
  229. error(['unknown STAT "',xCon(ic).STAT,'"']);
  230. end % (switch(xCon(ic)...)
  231. %-Write SPM - statistic image
  232. %------------------------------------------------------------------
  233. xCon(ic).Vspm = struct(...
  234. 'fname', [sprintf('spm%s_%04d',xCon(ic).STAT,ic) file_ext],...
  235. 'dim', SPM.xVol.DIM',...
  236. 'dt', [spm_type('float32'), spm_platform('bigend')],...
  237. 'mat', SPM.xVol.M,...
  238. 'pinfo', [1,0,0]',...
  239. 'descrip',sprintf('SPM{%s_%s} - contrast %d: %s',...
  240. xCon(ic).STAT,str,ic,xCon(ic).name),...
  241. metadata{:});
  242. xCon(ic).Vspm = spm_data_hdr_write(xCon(ic).Vspm);
  243. tmp = zeros(SPM.xVol.DIM');
  244. tmp(iXYZ) = Z;
  245. xCon(ic).Vspm = spm_data_write(xCon(ic).Vspm,tmp);
  246. clear tmp Z
  247. cmd = sprintf(['[hReg,xSPM,SPM] = spm_results_ui(''Setup'',',...
  248. 'struct(''swd'',''%s'',''Ic'',%d));',...
  249. 'TabDat = spm_list(''List'',xSPM,hReg);'],pwd,ic);
  250. img = spm_file(spm_file(xCon(ic).Vspm.fname,'filename'),'link',cmd);
  251. n = 30; if length(img)>n, n = length(img)+n-13; end
  252. fprintf('%s%*s\n',repmat(sprintf('\b'),1,30),n,sprintf(...
  253. '...written %s',img)); %-#
  254. end % (if isempty(xCon(ic)...)
  255. end % (for i = 1:length(Ic))
  256. spm('Pointer','Arrow')
  257. % place xCon back in SPM
  258. %--------------------------------------------------------------------------
  259. SPM.xCon = xCon;
  260. % Check if SPM has changed. Save only if it has.
  261. %--------------------------------------------------------------------------
  262. if spm_check_version('matlab','8.0') >= 0, my_isequaln = @isequaln;
  263. else my_isequaln = @isequalwithequalnans; end
  264. if ~my_isequaln(tmpSPM,SPM)
  265. fprintf('\t%-32s: %30s','Saving SPM.mat','...writing'); %-#
  266. save('SPM.mat', 'SPM', spm_get_defaults('mat.format'));
  267. fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...SPM.mat saved') %-#
  268. end