spm_VOI.m 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. function [TabDat,xSVC] = spm_VOI(SPM,xSPM,hReg,xY)
  2. % List of local maxima and adjusted p-values for a small Volume of Interest
  3. % FORMAT [TabDat,xSVC] = spm_VOI(SPM,xSPM,hReg,[xY])
  4. %
  5. % SPM - Structure containing analysis details (see spm_spm)
  6. %
  7. % xSPM - Structure containing SPM, distribution & filtering details
  8. % Required fields are:
  9. % .swd - SPM working directory - directory containing current SPM.mat
  10. % .Z - minimum of n Statistics {filtered on u and k}
  11. % .n - number of conjoint tests
  12. % .STAT - distribution {Z, T, X or F}
  13. % .df - degrees of freedom [df{interest}, df{residual}]
  14. % .u - height threshold
  15. % .k - extent threshold {resels}
  16. % .XYZ - location of voxels {voxel coords}
  17. % .XYZmm - location of voxels {mm}
  18. % .S - search Volume {voxels}
  19. % .R - search Volume {resels}
  20. % .FWHM - smoothness {voxels}
  21. % .M - voxels -> mm matrix
  22. % .VOX - voxel dimensions {mm}
  23. % .DIM - image dimensions {voxels} - column vector
  24. % .Vspm - mapped statistic image(s)
  25. % .Ps - uncorrected P values in searched volume (for voxel FDR)
  26. % .Pp - uncorrected P values of peaks (for peak FDR)
  27. % .Pc - uncorrected P values of cluster extents (for cluster FDR)
  28. % .uc - 0.05 critical thresholds for FWEp, FDRp, FWEc, FDRc
  29. %
  30. % hReg - Handle of results section XYZ registry (see spm_results_ui.m)
  31. % xY - VOI structure
  32. %
  33. % TabDat - Structure containing table data (see spm_list.m)
  34. % xSVC - Thresholded xSPM data (see spm_getSPM.m)
  35. %__________________________________________________________________________
  36. %
  37. % spm_VOI is called by the SPM results section and takes variables in
  38. % SPM to compute p-values corrected for a specified volume of interest.
  39. %
  40. % The volume of interest may be defined as a box or sphere centred on
  41. % the current voxel or by a mask image.
  42. %
  43. % If the VOI is defined by a mask this mask must have been defined
  44. % independently of the SPM (e.g. using a mask based on an orthogonal
  45. % contrast).
  46. %
  47. % External mask images should be in the same orientation as the SPM
  48. % (i.e. as the input used in stats estimation). The VOI is defined by
  49. % voxels with values greater than 0.
  50. %
  51. % See also: spm_list
  52. %__________________________________________________________________________
  53. % Copyright (C) 1999-2014 Wellcome Trust Centre for Neuroimaging
  54. % Karl Friston
  55. % $Id: spm_VOI.m 6080 2014-07-01 16:00:22Z guillaume $
  56. %-Parse arguments
  57. %--------------------------------------------------------------------------
  58. if nargin < 2, error('Not enough input arguments.'); end
  59. if nargin < 3, hReg = []; end
  60. if nargin < 4, xY = []; end
  61. Num = spm_get_defaults('stats.results.svc.nbmax'); % maxima per cluster
  62. Dis = spm_get_defaults('stats.results.svc.distmin'); % distance among maxima {mm}
  63. %-Title
  64. %--------------------------------------------------------------------------
  65. spm('FigName',['SPM{',xSPM.STAT,'}: Small Volume Correction']);
  66. %-Get current location {mm}
  67. %--------------------------------------------------------------------------
  68. try
  69. xyzmm = xY.xyz;
  70. catch
  71. xyzmm = spm_results_ui('GetCoords');
  72. end
  73. %-Specify search volume
  74. %--------------------------------------------------------------------------
  75. if isfield(xY,'def')
  76. switch xY.def
  77. case 'sphere'
  78. SPACE = 'S';
  79. case 'box'
  80. SPACE = 'B';
  81. case 'mask'
  82. SPACE = 'I';
  83. otherwise
  84. error('Unknown VOI type.');
  85. end
  86. else
  87. str = sprintf(' at [%.0f,%.0f,%.0f]',xyzmm(1),xyzmm(2),xyzmm(3));
  88. SPACE = spm_input('Search volume...',-1,'m',...
  89. {['Sphere',str],['Box',str],'Image'},['S','B','I']);
  90. end
  91. %-Voxels in entire search volume {mm}
  92. %--------------------------------------------------------------------------
  93. XYZmm = SPM.xVol.M(1:3,:)*[SPM.xVol.XYZ; ones(1, SPM.xVol.S)];
  94. Q = ones(1,size(xSPM.XYZmm,2));
  95. O = ones(1,size( XYZmm,2));
  96. FWHM = xSPM.FWHM;
  97. switch SPACE
  98. case 'S' %-Sphere
  99. %----------------------------------------------------------------------
  100. if ~isfield(xY,'spec')
  101. D = spm_input('radius of VOI {mm}',-2);
  102. else
  103. D = xY.spec;
  104. end
  105. str = sprintf('%0.1fmm sphere',D);
  106. j = find(sum((xSPM.XYZmm - xyzmm*Q).^2) <= D^2);
  107. k = find(sum(( XYZmm - xyzmm*O).^2) <= D^2);
  108. D = D./xSPM.VOX;
  109. case 'B' %-Box
  110. %----------------------------------------------------------------------
  111. if ~isfield(xY,'spec')
  112. D = spm_input('box dimensions [k l m] {mm}',-2);
  113. else
  114. D = xY.spec;
  115. end
  116. if length(D)~=3, D = ones(1,3)*D(1); end
  117. str = sprintf('%0.1f x %0.1f x %0.1f mm box',D(1),D(2),D(3));
  118. j = find(all(abs(xSPM.XYZmm - xyzmm*Q) <= D(:)*Q/2));
  119. k = find(all(abs( XYZmm - xyzmm*O) <= D(:)*O/2));
  120. D = D./xSPM.VOX;
  121. case 'I' %-Mask Image
  122. %----------------------------------------------------------------------
  123. if ~isfield(xY,'spec')
  124. [VM,sts] = spm_select([1 Inf],'image','Image defining search volume');
  125. if ~sts, TabDat = []; xSVC = []; return; end
  126. else
  127. VM = xY.spec;
  128. end
  129. D = spm_vol(VM);
  130. if numel(D) > 1
  131. fprintf('Computing union of all masks.\n');
  132. spm_check_orientations(D);
  133. D2 = struct(...
  134. 'fname', ['virtual_SVC_mask' spm_file_ext],...
  135. 'dim', D(1).dim,...
  136. 'dt', [spm_type('uint8') spm_platform('bigend')],...
  137. 'mat', D(1).mat,...
  138. 'n', 1,...
  139. 'pinfo', [1 0 0]',...
  140. 'descrip', 'SVC mask');
  141. D2.dat = false(D2.dim);
  142. for i=1:numel(D)
  143. D2.dat = D2.dat | spm_read_vols(D(i));
  144. end
  145. D2.dat = uint8(D2.dat);
  146. D = D2;
  147. end
  148. str = spm_file(D.fname,'short30');
  149. str = regexprep(str, {'\\' '\^' '_' '{' '}'}, ...
  150. {'\\\\' '\\^' '\\_' '\\{' '\\}'}); % Escape TeX special characters
  151. str = sprintf('image mask: %s',str);
  152. VOX = sqrt(sum(D.mat(1:3,1:3).^2));
  153. FWHM = FWHM.*(xSPM.VOX./VOX);
  154. XYZ = D.mat \ [xSPM.XYZmm; ones(1, size(xSPM.XYZmm, 2))];
  155. j = find(spm_sample_vol(D, XYZ(1,:), XYZ(2,:), XYZ(3,:),0) > 0);
  156. XYZ = D.mat \ [ XYZmm; ones(1, size( XYZmm, 2))];
  157. k = find(spm_sample_vol(D, XYZ(1,:), XYZ(2,:), XYZ(3,:),0) > 0);
  158. end
  159. xSPM.S = length(k);
  160. xSPM.R = spm_resels(FWHM,D,SPACE);
  161. xSPM.Z = xSPM.Z(j);
  162. xSPM.XYZ = xSPM.XYZ(:,j);
  163. xSPM.XYZmm = xSPM.XYZmm(:,j);
  164. %-Restrict FDR to the search volume
  165. %--------------------------------------------------------------------------
  166. df = xSPM.df;
  167. STAT = xSPM.STAT;
  168. DIM = xSPM.DIM;
  169. R = xSPM.R;
  170. n = xSPM.n;
  171. Vspm = xSPM.Vspm;
  172. u = xSPM.u;
  173. S = xSPM.S;
  174. try, xSPM.Ps = xSPM.Ps(k); end
  175. if STAT ~= 'P'
  176. [up, xSPM.Pp] = spm_uc_peakFDR(0.05,df,STAT,R,n,Vspm,k,u);
  177. uu = spm_uc(0.05,df,STAT,R,n,S);
  178. end
  179. try % if STAT == 'T'
  180. V2R = 1/prod(xSPM.FWHM(DIM>1));
  181. [uc, xSPM.Pc, ue] = spm_uc_clusterFDR(0.05,df,STAT,R,n,Vspm,k,V2R,u);
  182. catch
  183. uc = NaN;
  184. ue = NaN;
  185. xSPM.Pc = [];
  186. end
  187. try, xSPM.uc = [uu up ue uc]; end
  188. %-Tabulate p values
  189. %--------------------------------------------------------------------------
  190. str = sprintf('search volume: %s',str);
  191. if any(strcmp(SPACE,{'S','B'}))
  192. str = sprintf('%s at [%.0f,%.0f,%.0f]',str,xyzmm(1),xyzmm(2),xyzmm(3));
  193. end
  194. TabDat = spm_list('List',xSPM,hReg,Num,Dis,str);
  195. if nargout > 1, xSVC = xSPM; end
  196. %-Reset title
  197. %--------------------------------------------------------------------------
  198. spm('FigName',['SPM{',xSPM.STAT,'}: Results']);