Rest2GNI.m 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. function GNI=Rest2GNI(RestData,WBMaskName,nVoxelPerSectionMax)
  2. % function GNI=Rest2GNI(RestData,WBMaskName)
  3. %
  4. % Purpose:
  5. % Calculate GNI from preprocessed resting state data and a whole brain mask
  6. % if GNI>3, global signal regression may not be necessary
  7. %
  8. % reference:
  9. % Chen G, Chen GY, Xie C, Ward BD, Li W, Antuono P and Li SJ.
  10. % A Method to Determine the Necessity for Global Signal Regression in Resting-State fMRI Studies
  11. % Magn Reson Med; doi: 10.1002/mrm.24201(2012)
  12. % Please cite the reference if you found the method useful.
  13. %
  14. % Author: Gang Chen
  15. % Date: 25 May 2012
  16. % Version: 1, initial release, limited function, limited testing has been performed. use at your own risk.
  17. %
  18. % Requirement:
  19. % You have to make sure "load_nii.m" and/or "BrikLoad.m" work in your matlab.
  20. % Google them, you may find the address where you can download them. You can
  21. % also send an email (gachen@mcw.edu) to me if you have questions.
  22. %
  23. % Input:
  24. % RestData:
  25. % full path and name of the 4-D preprocessed resting state data,
  26. % the program will accept .nii and .BRIK + .HEAD format
  27. % WBMaskName:
  28. % full path and name of the 3-D whole brain mask, must align to the
  29. % RestData and have the same matrix size in the first three dimention
  30. % the program will accept .nii and .BRIK + .HEAD format
  31. % nVoxelPerSectionMax:
  32. % This is determined by the memory size of your computer
  33. % at 100 this program will take less than 1GB memory
  34. % at 1000 this program will take more memory but runs faster, adjust as
  35. % needed
  36. %
  37. % example usage:
  38. % clear;
  39. % clc
  40. % ResultFolder=['D:\Work\ADNI\LFTC\'];
  41. % % dir([ResultFolder '*LFTC_NGR*.nii']);
  42. % RestFiles=dir([ResultFolder '*LFTC_NGR*.nii']);
  43. % WBMaskName='wWBMask4mm.nii';
  44. % for i=1:numel(RestFiles)
  45. % disp(num2str(i))
  46. % RestData=[ResultFolder RestFiles(i).name];
  47. % GNI(i)=Rest2GNI(RestData,WBMaskName,100);
  48. % if GNI(i)<3
  49. % disp([RestFiles(i).name ' needs global signal regression'])
  50. % end
  51. % end
  52. if strcmpi(RestData(end-3:end),'.nii')
  53. nii=load_nii(RestData);
  54. WBTC=nii.img;
  55. nii=load_nii(WBMaskName);
  56. WBMask=nii.img;
  57. elseif strcmpi(RestData(end-3:end),'orig')
  58. [err, WBTC , BrikInfo, ErrMessage] = BrikLoad(RestData);
  59. [err, WBMask , BrikInfo, ErrMessage] = BrikLoad(WBMaskName);
  60. else
  61. error('unknown data format')
  62. end
  63. nTP=size(WBTC,4);
  64. if nTP<=1
  65. error('RestData is not a 4-D file')
  66. end
  67. nvoxel=size(WBTC,1)*size(WBTC,2)*size(WBTC,3);
  68. WBTC=reshape(WBTC,[nvoxel nTP]);
  69. GSTC=WBTC(WBMask==1,:);
  70. GSTC=DeNaNInf(GSTC); % remove NaN value, sometimes the mask is outside of brain
  71. GSTC=mean(GSTC,1);
  72. % % GSTC=mean(WBTC(WBMask==1,:),1);
  73. [R,P]=MyCorrcoefSmallLarge(GSTC.',WBTC.',nVoxelPerSectionMax);
  74. P(P>=0.05)=1;
  75. Z=p2z(P).*sign(R);
  76. WBMask=double(WBMask);
  77. Z3D=WBMask;
  78. Z3D(:)=Z;
  79. GSConMask=double(Z3D<-1.96).*double(WBMask);
  80. nGSConVoxel=sum(GSConMask(:));
  81. GNI=100*nGSConVoxel./sum(WBMask(:));
  82. function [R,P]=MyCorrcoefSmallLarge(TC_Small,TC_Large,nTC_SectionMax)
  83. % by default one colume of TC represent one time course.
  84. % % For testing
  85. % TC_Small = rand(141,10);
  86. % TC_Large = rand(141,1079);
  87. % nTC_SectionMax=500;
  88. % tic;[R,P]=MyCorrcoefSmallLarge(TC_Small,TC_Large,nTC_SectionMax);toc
  89. % size(R)
  90. % [R2,P2]=mycorrcoef(TC_Small,TC_Large);
  91. % sum(abs(R(:)-R2(:)))
  92. % sum(abs(P(:)-P2(:)))
  93. if nargin==2
  94. nTC_SectionMax=1000;
  95. end
  96. nTC=size(TC_Large,2);
  97. nSection=ceil(nTC/nTC_SectionMax);
  98. nTC_OneSection=ceil(nTC/nSection);
  99. R=zeros(size(TC_Small,2),size(TC_Large,2));
  100. P=R;
  101. for iSection=1:nSection-1
  102. [r,p]=mycorrcoef(TC_Small,TC_Large(:,1+(iSection-1)*nTC_OneSection:iSection*nTC_OneSection));
  103. R(:,1+(iSection-1)*nTC_OneSection:iSection*nTC_OneSection)=r;
  104. P(:,1+(iSection-1)*nTC_OneSection:iSection*nTC_OneSection)=p;
  105. end
  106. [r,p]=mycorrcoef(TC_Small,TC_Large(:,1+(nSection-1)*nTC_OneSection:end));
  107. R(:,1+(nSection-1)*nTC_OneSection:end)=r;
  108. P(:,1+(nSection-1)*nTC_OneSection:end)=p;
  109. return
  110. function [r,p]=mycorrcoef(TC1,TC2)
  111. if nargout<=1 % Quickly dispose of most common case.
  112. %by default one colume of TC represent one time course.
  113. if size(TC1,1)==size(TC2,1) && size(TC1,1)~=1
  114. TC=[TC1 TC2];
  115. [CC]=corrcoef(TC);
  116. r=CC(1:size(TC1,2),size(TC1,2)+1:size(TC1,2)+size(TC2,2));
  117. elseif size(TC1,2)==size(TC2,2)
  118. TC=[TC1;TC2];
  119. [CC]=corrcoef(TC.');
  120. r=CC(1:size(TC1,1),size(TC1,1)+1:size(TC1,1)+size(TC2,1));
  121. end
  122. p=[];
  123. else
  124. %by default one colume of TC represent one time course.
  125. if size(TC1,1)==size(TC2,1) && size(TC1,1)~=1
  126. TC=[TC1 TC2];
  127. [CC,P]=corrcoef(TC);
  128. r=CC(1:size(TC1,2),size(TC1,2)+1:size(TC1,2)+size(TC2,2));
  129. p=P(1:size(TC1,2),size(TC1,2)+1:size(TC1,2)+size(TC2,2));
  130. elseif size(TC1,2)==size(TC2,2)
  131. TC=[TC1;TC2];
  132. [CC,P]=corrcoef(TC.');
  133. r=CC(1:size(TC1,1),size(TC1,1)+1:size(TC1,1)+size(TC2,1));
  134. p=P(1:size(TC1,1),size(TC1,1)+1:size(TC1,1)+size(TC2,1));
  135. end
  136. end
  137. function m=DeNaNInf(m,Opt)
  138. if nargin==1
  139. Opt.Display=0;
  140. Opt.Fast=0;
  141. end
  142. if ~isfield(Opt,'Fast')
  143. Opt.Fast=0;
  144. end
  145. if ~isfield(Opt,'Display')
  146. Opt.Display=0;
  147. end
  148. if Opt.Fast
  149. if Opt.Display
  150. nNotFinite=sum(~isfinite(m(:)));
  151. end
  152. m(~isfinite(m))=mean(m(isfinite(m)));
  153. if Opt.Display
  154. disp([num2str(nNotFinite) ' Non-finite elements (' num2str(100*nNotFinite/numel(m)) '%) replaced by the mean'])
  155. end
  156. return
  157. end
  158. nNaN=sum(isnan(m(:)));
  159. m(isnan(m))=mean(m(~isnan(m)));
  160. if Opt.Display
  161. disp([num2str(nNaN) ' NaN elements (' num2str(100*nNaN/numel(m)) '%) replaced by the mean'])
  162. end
  163. nInf=sum(isinf(m(:)));
  164. m(isinf(m))=mean(m(~isinf(m)));
  165. if Opt.Display
  166. disp([num2str(nInf) ' Inf elements (' num2str(100*nInf/numel(m)) '%) replaced by the mean'])
  167. end
  168. function z=p2z(p)
  169. % See also z2p, normcdf, norminv, ranksum
  170. z=-norminv(p/2);