spm_hdm_ui.m 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. function [Ep,Cp,K1,K2] = spm_hdm_ui(xSPM,SPM,hReg)
  2. % User interface for hemodynamic model estimation
  3. % FORMAT [Ep,Cp,K1,K2] = spm_hdm_ui(xSPM,SPM,hReg
  4. %
  5. % xSPM - structure containing specific SPM details
  6. % SPM - structure containing generic SPM details
  7. % hReg - Handle of results section XYZ registry (see spm_results_ui.m)
  8. %
  9. % Ep - conditional expectations of the hemodynamic model parameters
  10. % Cp - conditional covariance of the hemodynamic model parameters
  11. % K1 - 1st order kernels
  12. % K2 - 2nd order kernels
  13. % (see main body of routine for details of model specification)
  14. %__________________________________________________________________________
  15. % Copyright (C) 2005-2013 Wellcome Trust Centre for Neuroimaging
  16. % Karl Friston
  17. % $Id: spm_hdm_ui.m 6314 2015-01-23 17:00:51Z guillaume $
  18. % get figure handles
  19. %--------------------------------------------------------------------------
  20. Finter = spm_figure('GetWin','Interactive');
  21. header = get(Finter,'Name');
  22. set(Finter,'Name','Hemodynamic modelling')
  23. % inputs
  24. %==========================================================================
  25. % which session?
  26. %--------------------------------------------------------------------------
  27. s = length(SPM.Sess);
  28. if s > 1
  29. s = spm_input('which session',1,'n1',s,s);
  30. end
  31. Sess = SPM.Sess(s);
  32. % 'causes' or imputs U
  33. %--------------------------------------------------------------------------
  34. spm_input('Input specification:... ',1,'d');
  35. U.dt = Sess.U(1).dt;
  36. u = length(Sess.U);
  37. if u == 1 && length(Sess.U(1).name) == 1
  38. U.name = Sess.U(1).name;
  39. U.u = Sess.U(1).u(33:end,1);
  40. else
  41. U.name = {};
  42. U.u = [];
  43. for i = 1:u
  44. for j = 1:length(Sess.U(i).name)
  45. str = ['include ' Sess.U(i).name{j} '?'];
  46. if spm_input(str,2,'y/n',[1 0])
  47. U.u = [U.u Sess.U(i).u(33:end,j)];
  48. U.name{end + 1} = Sess.U(i).name{j};
  49. end
  50. end
  51. end
  52. end
  53. %-Echo time (TE) of data acquisition
  54. %--------------------------------------------------------------------------
  55. TE = 0.04;
  56. TE_ok = 0;
  57. while ~TE_ok
  58. TE = spm_input('Echo time, TE [s]', '+1', 'r', TE);
  59. if ~TE || (TE < 0) || (TE > 0.1)
  60. str = { 'Extreme value for TE or TE undefined.',...
  61. 'Please re-enter TE (in seconds!)'};
  62. spm_input(str,'+1','bd','OK',[1],1);
  63. else
  64. TE_ok = 1;
  65. end
  66. end
  67. %-System outputs
  68. %==========================================================================
  69. % enforce adjustment w.r.t. all effects
  70. %--------------------------------------------------------------------------
  71. xY = struct( 'Ic' ,0,...
  72. 'name' ,'HDM',...
  73. 'Sess' ,s);
  74. % get region stucture
  75. %--------------------------------------------------------------------------
  76. xY = struct('name', 'HDM', 'Sess', s);
  77. [y,xY] = spm_regions(xSPM,SPM,hReg,xY);
  78. % place response and confounds in response structure
  79. %--------------------------------------------------------------------------
  80. y = xY.u;
  81. Y.y = y;
  82. Y.dt = SPM.xY.RT;
  83. Y.X0 = xY.X0;
  84. %-Estimate
  85. %==========================================================================
  86. spm('Pointer','Watch')
  87. spm('FigName','Estimation in progress');
  88. % Model specification: m input; 4 states; 1 outout; m + 6 parameters
  89. %--------------------------------------------------------------------------
  90. % u(m) - mth stimulus function (u)
  91. %
  92. % x(1) - vascular signal log(s)
  93. % x(2) - rCBF log(f)
  94. % x(3) - venous volume log(v)
  95. % x(4) - deoyxHb log(q)
  96. %
  97. % y(1) - BOLD (y)
  98. %
  99. % P(1) - signal decay d(ds/dt)/ds) half-life = log(2)/P(1) ~ 1sec
  100. % P(2) - autoregulation d(ds/dt)/df) 2*pi*sqrt(1/P(1)) ~ 10 sec
  101. % P(3) - transit time (t0) ~ 1 sec
  102. % P(4) - exponent for Fout(v) (alpha) c.f. Grubb's exponent (~ 0.38)
  103. % P(5) - resting oxygen extraction (E0) ~ range 20 - 50%
  104. % P(6) - ratio of intra- to extra- (epsilon) ~ range 0.5 - 2
  105. % vascular components
  106. % of the gradient echo signal
  107. % P(6 + 1:m) - input efficacies - d(ds/dt)/du) ~0.3 per event
  108. %--------------------------------------------------------------------------
  109. % priors (3 modes of hemodynamic variation)
  110. %--------------------------------------------------------------------------
  111. m = size(U.u,2);
  112. [pE,pC] = spm_hdm_priors(m,3);
  113. % model
  114. %--------------------------------------------------------------------------
  115. M.f = 'spm_fx_hdm';
  116. M.g = 'spm_gx_hdm';
  117. M.x = [0 0 0 0]';
  118. M.pE = pE;
  119. M.pC = pC;
  120. M.m = m;
  121. M.n = 4;
  122. M.l = 1;
  123. M.N = 64;
  124. M.dt = 24/M.N;
  125. M.TE = TE;
  126. % nonlinear system identification
  127. %--------------------------------------------------------------------------
  128. [Ep,Cp,Ce,K0,K1,K2,M0,M1] = spm_nlsi(M,U,Y);
  129. %-display results
  130. %==========================================================================
  131. t = [1:M.N]*M.dt;
  132. Fhdm = spm_figure;
  133. set(Fhdm,'name','Hemodynamic Modeling')
  134. % display input parameters
  135. %--------------------------------------------------------------------------
  136. subplot(2,2,1)
  137. P = Ep(7:end);
  138. C = diag(Cp(7:end,7:end));
  139. [i,j] = max(abs(P));
  140. spm_barh(P,C)
  141. axis square
  142. title({'stimulus efficacy'; 'with 90% confidence intervals'},'FontSize',10)
  143. set(gca,'Ytick',[1:m],'YTickLabel',U.name,'FontSize',8)
  144. str = {};
  145. for i = 1:m
  146. str{end + 1} = U.name{i};
  147. str{end + 1} = sprintf('mean = %0.2f',P(i));
  148. str{end + 1} = '';
  149. end
  150. set(gca,'Ytick',[1:m*3]/3 + 1/2,'YTickLabel',str)
  151. xlabel('relative efficacy per event/sec')
  152. % display hemodynamic parameters
  153. %--------------------------------------------------------------------------
  154. subplot(2,2,3)
  155. P = Ep(1:6);
  156. pE = pE(1:6);
  157. C = diag(Cp(1:6,1:6));
  158. spm_barh(P,C,pE)
  159. title({ 'hemodynamic parameters'},'FontSize',10)
  160. set(gca,'Ytick',[1:18]/3 + 1/2)
  161. set(gca,'YTickLabel',{ 'SIGNAL decay',...
  162. sprintf('%0.2f per sec',P(1)),'',...
  163. 'FEEDBACK',...
  164. sprintf('%0.2f per sec',P(2)),'',...
  165. 'TRANSIT TIME',...
  166. sprintf('%0.2f seconds',P(3)),'',...
  167. 'EXPONENT',...
  168. sprintf('%0.2f',P(4)),'',...
  169. 'EXTRACTION',...
  170. sprintf('%0.0f %s',P(5)*100,'%'),'',...
  171. 'log SIGNAL RATIO',...
  172. sprintf('%0.2f %s',P(6),'%'),''},'FontSize',8)
  173. % get display state kernels (i.e. state dynamics)
  174. %==========================================================================
  175. % Volterra kernels of states
  176. %--------------------------------------------------------------------------
  177. [H0,H1] = spm_kernels(M0,M1,M.N,M.dt);
  178. subplot(3,2,2)
  179. plot(t,exp(H1(:,:,j)))
  180. axis square
  181. title({['1st order kernels for ' U.name{j}];...
  182. 'state variables'},'FontSize',9)
  183. ylabel('normalized values')
  184. legend({'s','f','v','q'}, 'Location','Best');
  185. grid on
  186. % display output kernels (i.e. BOLD response)
  187. %--------------------------------------------------------------------------
  188. subplot(3,2,4)
  189. plot(t,K1(:,:,j))
  190. axis square
  191. title({'1st order kernel';...
  192. 'output: BOLD'},'FontSize',9)
  193. ylabel('normalized flow signal')
  194. grid on
  195. subplot(3,2,6)
  196. imagesc(t,t,K2(:,:,1,j,j))
  197. axis square
  198. title({'2nd order kernel';...
  199. 'output: BOLD'},'FontSize',9)
  200. xlabel({'time \{seconds\} for'; U.name{j}})
  201. grid on
  202. %-Reset title
  203. %--------------------------------------------------------------------------
  204. spm('FigName',header);
  205. spm('Pointer','Arrow')
  206. spm_input('Thank you',1,'d')