1+ function stats = fmrwhy_qc_calculate_tSNR(bids_dir , sub , functional_fn , options )
2+ % function stats = fmrwhy_qc_calculate_tSNR(bids_dir, sub, ses, task, run)
3+ % Function to calculate temporal SNR from single run of (masked) fMRI timeseries data
4+
5+ % First access and reshape the functional data: 4D to 2D
6+ nii = nii_tool(' load' , functional_fn );
7+ data_4D = double(nii .img );
8+ [Ni , Nj , Nk , Nt ] = size(data_4D );
9+ data_2D = reshape(data_4D , Ni * Nj * Nk , Nt ); % [voxels, time]
10+ data_2D = data_2D ' ; % [time, voxels]
11+
12+ % Get masks
13+ masks = fmrwhy_util_loadMasks(bids_dir , sub , options );
14+
15+ % Remove linear and quadratic trend per voxel
16+ data_2D_detrended = fmrwhy_util_detrend(data_2D , 2 ); % [time, voxels]
17+
18+ % Calculate mean
19+ data_2D_mean = nanmean(data_2D_detrended ); % [1, voxels]
20+
21+ % Remove mean
22+ data_2D_demeaned = data_2D_detrended - data_2D_mean ; % [time, voxels]
23+
24+ % Calculate standard deviation
25+ data_2D_stddev = std(data_2D_detrended ); % [1, voxels]
26+
27+ % Calculate Z-statistic
28+ data_2D_zstat = data_2D_demeaned ./ data_2D_stddev ;
29+ data_2D_zstat(isnan(data_2D_zstat )) = 0 ;
30+ data_2D_zstat_ts = nanmean(abs(data_2D_zstat ), 2 ); % perhaps this should only be done within brain mask?
31+ Zstat_mean = nanmean(data_2D_zstat_ts ); % perhaps this should only be done within brain mask?
32+
33+ % Calculate variance
34+ % data_2D_var = var(data_2D_detrended);
35+
36+ % Calculate percentage signal change: [I(t) - mean(I)]/mean(I)*100
37+ data_2D_psc = 100 * (data_2D_detrended ./ data_2D_mean ) - 100 ;
38+ data_2D_psc(isnan(data_2D_psc )) = 0 ;
39+
40+ % Calculate tSNR
41+ tSNR_2D = data_2D_mean ./ data_2D_stddev ;
42+ tSNR_mean_brain = nanmean(tSNR_2D(masks .brain_mask_I ));
43+ tSNR_mean_GM = nanmean(tSNR_2D(masks .GM_mask_I ));
44+ tSNR_mean_WM = nanmean(tSNR_2D(masks .WM_mask_I ));
45+ tSNR_mean_CSF = nanmean(tSNR_2D(masks .CSF_mask_I ));
46+
47+ % Prepare 3D and 4D images
48+ % data_3D_mean = reshape(data_2D_mean, Ni, Nj, Nk);
49+ % data_3D_var = reshape(data_2D_var, Ni, Nj, Nk);
50+ % data_3D_stddev = reshape(data_2D_stddev, Ni, Nj, Nk);
51+ % tSNR_3D = reshape(tSNR_2D, Ni, Nj, Nk);
52+
53+ data_4D_psc = reshape(data_2D_psc ' , Ni , Nj , Nk , Nt );
54+ data_4D_detrended = reshape(data_2D_detrended ' , Ni , Nj , Nk , Nt );
55+ data_4D_demeaned = reshape(data_2D_demeaned ' , Ni , Nj , Nk , Nt );
56+
57+ stats = struct ;
58+ % Single values
59+ stats.tSNR_mean_brain = tSNR_mean_brain ;
60+ stats.tSNR_mean_GM = tSNR_mean_GM ;
61+ stats.tSNR_mean_WM = tSNR_mean_WM ;
62+ stats.tSNR_mean_CSF = tSNR_mean_CSF ;
63+ stats.Zstat_mean = Zstat_mean ;
64+ % Single parameter timeseries
65+ stats.data_2D_zstat_ts = data_2D_zstat_ts ;
66+ % % 3D images
67+ % stats.data_3D_mean = data_3D_mean;
68+ % stats.data_3D_var = data_3D_var;
69+ % stats.data_3D_stddev = data_3D_stddev;
70+ % stats.data_3D_tsnr = tSNR_3D;
71+ % 4D image timeseries
72+ stats.data_4D_psc = data_4D_psc ;
73+ stats.data_4D_detrended = data_4D_detrended ;
74+ stats.data_4D_demeaned = data_4D_demeaned ;
75+
76+ %% Display metrics in command window
77+ % disp(['Mean Zscore: ' num2str(Zstat_mean)])
78+ % disp(['tSNR (brain): ' num2str(tSNR_brain)])
79+ % disp(['tSNR (GM): ' num2str(tSNR_GM)])
80+ % disp(['tSNR (WM): ' num2str(tSNR_WM)])
81+ % disp(['tSNR (CSF): ' num2str(tSNR_CSF)])
0 commit comments