fmri_rp_metrics.m 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. function RPmetrics = fmri_rp_metrics(rp,type,ReferenceImage)
  2. %FMRI_RP_METRICS computes various Realignment Parameters (RP) based metrics
  3. %
  4. %Inputs:
  5. % -RP can be the path to an RP file or the pre-loaded RP matrix.
  6. % -TYPE is a string specifying with which software was used to compute RP
  7. % {'fsl','spm','afni','hcp'}
  8. % -REFERENCEIMAGE (is optional and is used for FD Jenkinson computation.
  9. % Provide the path of the nifti volume used as base for realignment.
  10. %
  11. %Ouptut:
  12. % -RPmetrics is a structure containing:
  13. % .FDpower (L1 norm)
  14. % .tra_abs (absolute traslations)
  15. % .rot_abs (absolute rotations)
  16. % .FDafni (L2 norm)
  17. % .FDjenk (rms relative to previous volume)
  18. % .rms (rms relative to the reference volume)
  19. %
  20. %Requirements:
  21. % SPM (https://www.fil.ion.ucl.ac.uk/spm/) is required if FDjenk is
  22. % desired.
  23. %
  24. %Acknowledgements:
  25. % For FDjenk computation, this function adopts a code written by:
  26. % YAN Chao-Gan 120930 (ycg.yan@gmail.com) that is part of the toolbox: DPARSF
  27. %
  28. %References:
  29. % - Power, Jonathan D., et al. "Spurious but systematic correlations in
  30. % functional connectivity MRI networks arise from subject motion."
  31. % Neuroimage 59.3 (2012): 2142-2154.
  32. % - Yan, Chao-Gan, et al. "A comprehensive assessment of regional variation
  33. % in the impact of head micromovements on functional connectomics."
  34. % Neuroimage 76 (2013): 183-201.
  35. %__________________________________________________________________________
  36. % Daniele Mascali
  37. % Enrico Fermi Center, MARBILab, Rome
  38. % danielemascali@gmail.com
  39. if nargin == 0
  40. help(mfilename)
  41. return
  42. end
  43. switch lower(type)
  44. case {'fsl'} %ok
  45. rp_indx.rot = [1 2 3];
  46. rp_indx.tra = [4 5 6];
  47. rp_rot_unit = 'rad';
  48. case {'spm'} %ok. Indeed they are plotted by SPM in degrees but they are saved in radians
  49. rp_indx.rot = [4 5 6];
  50. rp_indx.tra = [1 2 3];
  51. rp_rot_unit = 'rad';
  52. case {'afni'} %ok
  53. rp_indx.rot = [1 2 3];
  54. rp_indx.tra = [4 5 6];
  55. rp_rot_unit = 'deg';
  56. case {'hcp'} %verified
  57. rp_indx.rot = [4 5 6];
  58. rp_indx.tra = [1 2 3];
  59. rp_rot_unit = 'deg';
  60. end
  61. rp_average_brain_radius = 50; %mm; 50 according to Power,
  62. if ischar(rp)
  63. rp = load(rp);
  64. end
  65. %FD power %L1 norm
  66. [RPmetrics.FDpower,RPmetrics.tra_abs,RPmetrics.rot_abs] = FD_Power(rp,rp_indx,rp_rot_unit,rp_average_brain_radius);
  67. %FD afni %L2 norm + different rotational weight
  68. RPmetrics.FDafni = FD_afni(rp,rp_indx,rp_rot_unit);
  69. %FD Jenkinson
  70. if nargin > 2
  71. [rel_rms, abs_rms] = FD_Jenkinson(rp,ReferenceImage,rp_indx,rp_rot_unit);
  72. RPmetrics.FDjenk = rel_rms; %rms relative to the previous volume
  73. RPmetrics.rms = abs_rms; %RMS relative to the reference volume
  74. end
  75. return
  76. end
  77. function [fd,tra_abs,rot_abs] = FD_Power(rp,rp_indx,rp_rot_unit,rp_average_brain_radius)
  78. tra = rp(:,rp_indx.tra);
  79. rot = rp(:,rp_indx.rot);
  80. fd_tra = sum( abs( diff(tra) ) ,2);
  81. %rotaions must be converted from rad to mm. (assuming a radius of 50 mm)
  82. switch lower(rp_rot_unit)
  83. case {'rad'}
  84. rot_mm = rot*rp_average_brain_radius;
  85. case {'mm'}
  86. %do nothing
  87. rot_mm = rot;
  88. case {'deg'}
  89. rot_mm = rot*rp_average_brain_radius*2*pi/360;
  90. end
  91. fd_rot = sum( abs( diff(rot_mm) ) ,2);
  92. fd = sum([fd_tra,fd_rot],2);
  93. fd = [0; fd]; % due to the differenziation I need to add a 0.
  94. %extract also abs rot and tra
  95. % let's subtract the value at time 0, so in case the ref volume is not the
  96. % first one the position still refers to the first scan.
  97. rp_mm = [tra,rot_mm];
  98. rp_mm_dm = bsxfun(@minus, rp_mm, rp_mm(1,:));
  99. tra_abs = sum(abs(rp_mm_dm(:,1:3)),2);
  100. rot_abs = sum(abs(rp_mm_dm(:,4:6)),2);
  101. return
  102. end
  103. function fd = FD_afni(rp,rp_indx,rp_rot_unit)
  104. % AFNI use L2 instead of L1 (as it used in FDpower), moreover the rotations
  105. % are scaled in a different way (rot in deg equals mm)
  106. tra = rp(:,rp_indx.tra);
  107. rot = rp(:,rp_indx.rot);
  108. %rotaions must be converted to deg
  109. switch lower(rp_rot_unit)
  110. case {'rad'}
  111. rot = 180*rot./pi;
  112. case {'deg'}
  113. %do nothing
  114. end
  115. fd = sqrt(sum(diff([tra,rot]).^2,2));
  116. fd = [0; fd]; % due to the differenziation I need to add a 0.
  117. return
  118. end
  119. function [rel_rms, abs_rms] = FD_Jenkinson(RP,ReferenceImage,rp_indx,rp_rot_unit)
  120. % function [rel_rms, abs_rms] = y_FD_Jenkinson(RealignmentParameterFile,ReferenceImage)
  121. % Calculate FD Jenkinson (relative RMS) and absolute RMS based on SPM's realignment parameters
  122. % Reference: Jenkinson, M., Bannister, P., Brady, M., Smith, S., 2002. Improved optimization for the robust and accurate linear registration and motion correction of brain images. Neuroimage 17, 825-841.
  123. % Jenkinson, M. 1999. Measuring transformation error by RMS deviation. Internal Technical Report TR99MJ1, FMRIB Centre, University of Oxford. Available at www.fmrib.ox.ac.uk/analysis/techrep for downloading.
  124. % Input:
  125. % RealignmentParameterFile - The realignment parameter file for a given participant generated by SPM. E.g., rp***.txt
  126. % ReferenceImage - The reference image for realignment (usually the first time point (one-pass) or the mean image after an initial motion correction (two-pass))
  127. % Output:
  128. % rel_rms - relative RMS (FD Jenkinson)
  129. % abs_rms - absolute RMS
  130. %-----------------------------------------------------------
  131. % Written by YAN Chao-Gan 120930.
  132. % The Nathan Kline Institute for Psychiatric Research, 140 Old Orangeburg Road, Orangeburg, NY 10962, USA
  133. % Child Mind Institute, 445 Park Avenue, New York, NY 10022, USA
  134. % The Phyllis Green and Randolph Cowen Institute for Pediatric Neuroscience, New York University Child Study Center, New York, NY 10016, USA
  135. % ycg.yan@gmail.com
  136. %RP=load(RealignmentParameterFile);
  137. % if necessary convert RP to SPM format
  138. if sum(rp_indx.tra) ~= 6
  139. RPtmp = nan(size(RP));
  140. RPtmp(:,1:3) = RP(:,4:6);
  141. RPtmp(:,4:6) = RP(:,1:3);
  142. RP = RPtmp; clear RPtmp;
  143. end
  144. switch lower(rp_rot_unit)
  145. case {'rad'}
  146. %do nothing
  147. case {'deg'}
  148. %converting to rad
  149. RP(:,4:6) = RP(:,4:6)*pi/180;
  150. end
  151. %-------------------------------------
  152. rmax = 80.0; %The default radius (as in FSL) of a sphere represents the brain
  153. nTimePoint=size(RP,1);
  154. sinq1=sin(RP(:,4));
  155. sinq2=sin(RP(:,5));
  156. sinq3=sin(RP(:,6));
  157. cosq1=cos(RP(:,4));
  158. cosq2=cos(RP(:,5));
  159. cosq3=cos(RP(:,6));
  160. %[RefData, RefHead] = rest_ReadNiftiImage(ReferenceImage,1);
  161. RefHead = spm_vol(ReferenceImage);
  162. center = RefHead.mat*([0.5*(RefHead.dim(1));0.5*(RefHead.dim(2));0.5*(RefHead.dim(3));1]);
  163. center = center(1:3); %Get the coordinate for the center
  164. abs_rms = zeros(nTimePoint,1);
  165. for t=1:nTimePoint
  166. M1=[1 0 0 0;...
  167. 0 cosq1(t) sinq1(t) 0;...
  168. 0 -sinq1(t) cosq1(t) 0;...
  169. 0 0 0 1;];
  170. M2=[cosq2(t) 0 sinq2(t) 0;...
  171. 0 1 0 0;...
  172. -sinq2(t) 0 cosq2(t) 0;...
  173. 0 0 0 1;];
  174. M3=[cosq3(t) sinq3(t) 0 0;...
  175. -sinq3(t) cosq3(t) 0 0;...
  176. 0 0 1 0;...
  177. 0 0 0 1;];
  178. MT=[1 0 0 RP(t,1);...
  179. 0 1 0 RP(t,2);...
  180. 0 0 1 RP(t,3);...
  181. 0 0 0 1;];
  182. M_RigidBodyTransform=MT*M1*M2*M3;
  183. MA1=eye(4);
  184. MA2=(M_RigidBodyTransform);
  185. M = MA1*inv(MA2) - eye(4);
  186. A = M(1:3,1:3);
  187. T = M(1:3,4);
  188. abs_rms(t) = sqrt(rmax*rmax/5*trace(A'*A) + (T+A*center)'*(T+A*center));
  189. end
  190. rel_rms = zeros(nTimePoint-1,1);
  191. for t=2:nTimePoint
  192. M1=[1 0 0 0;...
  193. 0 cosq1(t) sinq1(t) 0;...
  194. 0 -sinq1(t) cosq1(t) 0;...
  195. 0 0 0 1;];
  196. M2=[cosq2(t) 0 sinq2(t) 0;...
  197. 0 1 0 0;...
  198. -sinq2(t) 0 cosq2(t) 0;...
  199. 0 0 0 1;];
  200. M3=[cosq3(t) sinq3(t) 0 0;...
  201. -sinq3(t) cosq3(t) 0 0;...
  202. 0 0 1 0;...
  203. 0 0 0 1;];
  204. MT=[1 0 0 RP(t,1);...
  205. 0 1 0 RP(t,2);...
  206. 0 0 1 RP(t,3);...
  207. 0 0 0 1;];
  208. M_RigidBodyTransform=MT*M1*M2*M3;
  209. M1=[1 0 0 0;...
  210. 0 cosq1(t-1) sinq1(t-1) 0;...
  211. 0 -sinq1(t-1) cosq1(t-1) 0;...
  212. 0 0 0 1;];
  213. M2=[cosq2(t-1) 0 sinq2(t-1) 0;...
  214. 0 1 0 0;...
  215. -sinq2(t-1) 0 cosq2(t-1) 0;...
  216. 0 0 0 1;];
  217. M3=[cosq3(t-1) sinq3(t-1) 0 0;...
  218. -sinq3(t-1) cosq3(t-1) 0 0;...
  219. 0 0 1 0;...
  220. 0 0 0 1;];
  221. MT=[1 0 0 RP(t-1,1);...
  222. 0 1 0 RP(t-1,2);...
  223. 0 0 1 RP(t-1,3);...
  224. 0 0 0 1;];
  225. M_RigidBodyTransform_1=MT*M1*M2*M3;
  226. MA1=(M_RigidBodyTransform_1);
  227. MA2=(M_RigidBodyTransform);
  228. M = MA1*inv(MA2) - eye(4);
  229. A = M(1:3,1:3);
  230. T = M(1:3,4);
  231. rel_rms(t-1) = sqrt(rmax*rmax/5*trace(A'*A) + (T+A*center)'*(T+A*center));
  232. end
  233. rel_rms=[0;rel_rms]; %The FD_Jenkinson at time point t means the movement from time point t-1 to time point t. (Put the FD_Jenkinson for the first time point to "0".)
  234. return
  235. end