-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathglm_fmri_fit.m
116 lines (80 loc) · 3.79 KB
/
glm_fmri_fit.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
function [B, seB, tB, pB, Rsq] = glm_fmri_fit(data,X,regIndx,mask)
%
% this function takes in a 4D fMRI dataset and a model as arguments, fits
% the model to the data at each voxel using least squares, and returns the
% estimated parameters. Skips voxels where the mask is set to 0 or false.
%%%%%%%%%%%%%%%%%%%%%% INPUTS:
% data - 4D dataset with time series in the 4th d
% X - design matrix of regressors
% regIndx - vector w/length = # of regressors, 0 for baseline and >=1 for
% regressors of interest
% mask - (optional) 3D dataset of 0s and 1s matching data dimensions
%%%%%%%%%%%%%%%%%%%%%% OUTPUTS:
% B coefficients fitted w/OLS for every voxel in 3d matrix that doesn't
% have a "0" in the first volume (these are considered to be masked out
% voxels). Also:
%
% 'seB' - standard error of each regression coefficient
% 'tB' - this returns the t or F-stat grouped by regIndx as appropriate
% 'pB' - corresponding p-values for each t-stat
% 'Rsq' - Rsquared for the full model not including the baseline
% kelly May 2012
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% define data dimensions and parameters to estimate
dim = size(data);
[N,p] = size(X); % number of time points & model parameters
df = N - p; % df = # of data points - parameters estimated
p0 = length(regIndx(regIndx==0)); % # of baseline params
df0 = N - p0; % df for baseline model
% make sure the data and mask dimensions agree
if exist('mask','var')
if dim(1:3) ~= size(mask)
error('fmri data and mask dimensions must agree\n\n');
end
else % if no mask is given, do all voxels
mask = ones(dim(1:3));
end
% check to make sure # of time points and # of rows in design matrix equal each other
if N ~= dim(4)
error('the number of rows in the design matrix has to equal the data.')
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%% define arrays of zeros for out stats
B = zeros(dim(1),dim(2),dim(3),p);
seB = zeros(size(B));
tB = zeros(size(B));
pB = zeros(size(B));
Rsq = zeros(dim(1:3));
%% fit model X to data
% get subscripts for all voxels of interest (within brain or roi mask)
indx = find(mask);
[i j k] = ind2sub(size(data),indx);
tenths = round(linspace(0,length(indx),11));
fprintf('\nfitting the model...\n\n');
for v = 1:length(indx)
Y = squeeze(data(i(v),j(v),k(v),:)); % get a voxel's time series
these_B = pinv(X'*X)*X'*Y; % estimate betas using OLS
zeroInd = find(these_B==0); % if a beta==0,
these_B(zeroInd) = -.0001; % change it to be a very small nonzero value
B(i(v),j(v),k(v),:) = these_B;
Yhat = X*these_B; % model's prediction for Y
residuals = Y - Yhat; % residuals
SSe = sum( (residuals).^2 ); % residual SS, aka squared error
MSe = SSe./df; % mean sq error aka error variance
s2matrix = MSe.*pinv(X'*X); % var-cov matrix for the regressors
s2B = diag(s2matrix); % each regressor's variance
these_seB = sqrt(s2B); % standard error of betas
seB(i(v),j(v),k(v),:) = these_seB;
these_tB = these_B ./ these_seB; % distributed as t w/ N-2 df
tB(i(v),j(v),k(v),:) = these_tB;
these_pB = 1 - tcdf(abs(these_tB), N-2); % p-value for t-stat
pB(i(v),j(v),k(v),:) = these_pB;
Yhat0 = X(:,regIndx==0)*these_B(regIndx==0); % baseline model's Y estimate,
SSe0 = sum( (Y - Yhat0).^2 ); % & squared error
this_Rsq = 100 * (1 - (SSe / SSe0 )); % Coefficient of Multiple Determination, Rsquared
Rsq(i(v),j(v),k(v)) = this_Rsq;
%
if ismember(v,tenths)
fprintf('\n%2.0f percent done...\n', round(v/length(indx)*100));
end %
end
fprintf('\ndone fitting model.\n\n');