spm_dcm_average.m 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. function [DCM] = spm_dcm_average(P,name,nocond,graphics)
  2. % Produce an aggregate DCM model using Bayesian FFX averaging
  3. % FORMAT [DCM] = spm_dcm_average(P,name,nocond,graphics)
  4. %
  5. % P - character/cell array of DCM filenames
  6. % name - name of DCM output file (will be prefixed by 'DCM_avg_')
  7. % nocond - optional flag for suppressing conditional dependencies
  8. % graphics - optional flag for showing outliers (based on conditional
  9. % entropy)
  10. %
  11. % This routine creates a new DCM in which the parameters are averaged
  12. % over a number of fitted DCM models. These can be over sessions or over
  13. % subjects. This average model can then be interrogated using the standard
  14. % DCM 'review' options to look at contrasts of parameters. The resulting
  15. % inferences correspond to a Bayesian Fixed Effects analysis. If called with
  16. % no output arguments the Bayesian parameter average DCM will be written to
  17. % file, otherwise the DCM structure is returned.
  18. %
  19. % Note that the Bayesian averaging is only applied to the A, B and C
  20. % matrices (and matrix D if a nonlinear model is used).
  21. % All other quantities in the average model are initially simply copied from
  22. % the first DCM in the list. Subsequently, they are deleted before saving
  23. % the average DCM in order to avoid any false impression that averaged
  24. % models could be used for model comparison or contained averaged time series.
  25. % Neither operation is valid and will be prevented by the DCM interface.
  26. % Finally, note that only models with exactly the same A,B,C,(D) structure
  27. % and the same brain regions can be averaged.
  28. %
  29. % A Bayesian random effects analysis can be implemented for a particular
  30. % contrast using the spm_dcm_sessions.m function.
  31. %__________________________________________________________________________
  32. % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
  33. % Will Penny & Klaas Enno Stephan
  34. % $Id: spm_dcm_average.m 7271 2018-03-04 13:11:54Z karl $
  35. % Preiminaries
  36. %--------------------------------------------------------------------------
  37. try
  38. P;
  39. catch
  40. [P, sts] = spm_select([1 Inf],'^DCM.*\.mat$','Select DCM*.mat files');
  41. if ~sts, return; end
  42. end
  43. if ischar(P), P = cellstr(P); end
  44. N = numel(P);
  45. % options and filename
  46. %--------------------------------------------------------------------------
  47. try, name; catch, name = spm_input('Name for DCM_avg_???.mat','+1','s'); end
  48. try, nocond; catch, nocond = 0; end
  49. try, graphics; catch, graphics = 0; end
  50. %-Loop through all selected models and get posterior means and precisions
  51. %==========================================================================
  52. for model = 1:N
  53. % get DCM structure
  54. %----------------------------------------------------------------------
  55. if ischar(P{model}), load(P{model}); else, DCM = P{model}; end
  56. % Only look at those parameters with non-zero prior variance
  57. %----------------------------------------------------------------------
  58. if isstruct(DCM.M.pC)
  59. pC = diag(spm_vec(DCM.M.pC));
  60. else
  61. pC = DCM.M.pC;
  62. end
  63. wsel = diag(pC) > 0 & diag(pC) < 128;
  64. pC = diag(wsel)*pC*diag(wsel);
  65. wsel = find(wsel);
  66. % find the space spanned by the prior covariance
  67. %----------------------------------------------------------------------
  68. if model == 1
  69. % suppress prior dependencies if necessary
  70. %----------------------------------------------------------------------
  71. if nocond, pC = diag(diag(pC)); end
  72. U = spm_svd(pC,0);
  73. wsel_first = wsel;
  74. DCM_first = DCM;
  75. else
  76. if length(wsel) ~= length(wsel_first) || any(wsel ~= wsel_first)
  77. error('DCMs must have same structure.');
  78. end
  79. end
  80. % suppress posterior dependencies if necessary
  81. %----------------------------------------------------------------------
  82. Cp = DCM.Cp;
  83. if nocond, Cp = diag(diag(Cp)); end
  84. % Get posterior precision matrix and mean
  85. %----------------------------------------------------------------------
  86. Cp = U'*Cp*U;
  87. Ep = U'*spm_vec(DCM.Ep);
  88. miCp(:,:,model) = inv(full(Cp));
  89. mEp(:,model) = Ep;
  90. % evaluate diagnostics
  91. %----------------------------------------------------------------------
  92. if graphics
  93. T(model) = trace(Cp);
  94. H(model) = spm_logdet(miCp(:,:,model));
  95. Fs(model) = DCM.F;
  96. end
  97. end
  98. %-Report free energies and conditional entropies
  99. %==========================================================================
  100. if graphics
  101. spm_figure('GetWin','BPA');
  102. subplot(3,1,1), bar(Fs)
  103. title('Free energy','FontSize',16)
  104. xlabel('Subject'), axis square
  105. subplot(3,1,2), bar(H)
  106. title('Conditional entropy','FontSize',16)
  107. xlabel('Subject'), axis square
  108. subplot(3,1,3), bar(T)
  109. title('Posterior variance','FontSize',16)
  110. xlabel('Subject'), axis square
  111. end
  112. %-Average models using Bayesian fixed-effects analysis -> average Ep,Cp
  113. %==========================================================================
  114. % averaged posterior covariance
  115. %--------------------------------------------------------------------------
  116. Cp = spm_inv(sum(miCp,3));
  117. % averaged posterior mean
  118. %--------------------------------------------------------------------------
  119. pE = spm_vec(DCM.M.pE);
  120. wEp = 0;
  121. for model = 1:N
  122. wEp = wEp + miCp(:,:,model)*mEp(:,model);
  123. end
  124. Ep = Cp*wEp;
  125. % project back through U
  126. %--------------------------------------------------------------------------
  127. Cp = U*Cp*U';
  128. Ep = U*Ep + pE - U*U'*pE;
  129. Ep = spm_unvec(Ep,DCM.M.pE);
  130. %-Copy contents of first DCM into the output DCM and add BPA
  131. %==========================================================================
  132. DCM = DCM_first;
  133. DCM.averaged = true;
  134. try
  135. DCM.models = char(P);
  136. end
  137. % compute posterior probabilities and variance
  138. %--------------------------------------------------------------------------
  139. sw = warning('off','SPM:negativeVariance');
  140. Vp = diag(Cp);
  141. Pp = 1 - spm_Ncdf(0,abs(spm_vec(Ep) - spm_vec(pE)),Vp);
  142. warning(sw);
  143. DCM.Ep = Ep;
  144. DCM.Cp = Cp;
  145. DCM.Vp = spm_unvec(Vp,DCM.M.pE);
  146. DCM.Pp = spm_unvec(Pp,DCM.M.pE);
  147. %-Save new DCM if there are no output arguments
  148. %==========================================================================
  149. if nocond
  150. DCM.name = [name ' (FFX average - no conditional dependencies)'];
  151. else
  152. DCM.name = [name ' (Bayesian FFX average)'];
  153. end
  154. if ~nargout
  155. save(['DCM_avg_' name '.mat'], 'DCM', spm_get_defaults('mat.format'));
  156. end
  157. % Warn the user how this average DCM should NOT be used
  158. %--------------------------------------------------------------------------
  159. % disp(['Results of averaging DCMs were saved in DCM_avg_' name '.mat.']);
  160. % disp('Please note that this file only contains average parameter estimates');
  161. % disp('and their posterior probabilities, but NOT averaged time series.');
  162. % disp('Also, note that this file can NOT be used for model comparisons.');