Now that the data have been preprocessed, we are ready for statistical analysis.
We will use the General Linear Model, which is a parametric method to assess
the data at each voxel. Let us say that during an experiment we measure a
response variable Yj, with j = 1 to J, indexes of observation, and
for each observation we have a set of K( K < J ) response variables,
xjk, with k = 1 to K. The response variables may be continuous
covariates, functions of covariates, or they may be dummy variables indicating
the levels of an experimental factor. The general linear model explains the
variation in Yj in terms of a linear combination of the response
variables, plus an error term.
Yj =
xj1b1 + ... + xjkbk+...+
xjKbK + ej
where, bk are unknown parameters, corresponding to each of the K
explanatory variables and ej are the errors which are correlated. A
description of the procedure is written up as an
abstract.
After estimating the parameters, the t maps can be calculated using
fmrilm. Let us consider the
example that was discussed before,
which is a block design of a pain study. Each functional
scan will be analyzed separately.
Overview of commands used in fmristat
The 3 basic functions that you will use in fmristat are the
following:
- fmridesign: input information about your paradigm into fmristat
- fmrilm: takes information from fmridesign and looks for activation
in a single functional run
- multistat: combines the statistical output of fmrilm within or across
subjects
The analysis is done in Matlab which is run from the command line by typing in
'matlab' (without the quotes). If you are not very familiar with Matlab you can
take a look at Matlab's
Help Desk on the web, or you can just run demo, from within Matlab. The basic idea behind the Matlab commands is simply (a) specifying the variables that will be used in each of the three functions above, and (b) executing these functions with the specified variables.
We begin with fmridesign. The inputs to this function are the frametimes, slicetimes, and events. The output of this function, X_cache, is a struct, which is used in fmrilm.
Before running fmridesign, we must define the following variables:
frametimes is a row vector in which you enter the time, in
seconds, at which each frame was acquired. To define this vector, the
measurement interval, or "TR" must to be known. The repetition time is set when
you do your experiment in the scanner. The TR will normally be constant throughout the run, unless you are using physiological gating at the scanner. Let us say for this example, the TR is 3s; the frametimes variable
will look like this (Note: the first frame should be set to t=0s):
frametimes = (0:119) * 3;
or
frametimes = [ 0 3 6 9 12 15 18 21 24 27 30
33 ... 351 354 357 ];
slicetimes is a row vector of relative slice acquisition times. The slicetimes are ordered in the row vector according to their voxel coordinates. For axial slices, the z-space coordinate value of 0 would refer to slice #1 and the time for this slice would be entered into the first column of slicetimes. If your minc image dimension steps are negative, the first slice will be the topmost, superior slice - this is the case for most fmri images acquired at the BIC. Once you have determined where the first slice can be found, the slicetimes variable would follow the convention:
slicetimes = [ <time for slice #1> <time for slice #2> ... <time for slice #N> ]
The slicetimes will depend on the delay in TR that was specified for your protocol at the scanner. It will also depend on the MR sequence that was used in your scans, and the slice excitation order: ascending, descending or interleaved.
A. Slice Timings
You can determine your slice time interval with the following calculation:
slicetime = [TR - delay in TR] / [total number of slices]
NB: There may be a very small delay (12 to 14ms) from the acquisition of the first slice and the trigger delivery from the scanner. This should not impact your analysis. Overall, you can expect the total scan time of a complete run to be accurate to within +/- 10 milliseconds.
B. Slice Excitation Direction
1. Ascending
If the order is ascending, then the first axial slice that will be acquired will be the most inferior slice (toward the the subject's feet), and the last slice will be the most superior slice (toward the top of the head).
If for example, you are using the mosaic 64, ascending, your slices are acquired inferior to superior (the foot to head direction). Therefore the top slice is the last one to be imaged and the slicetimes variable will look like this for 25 slices:
slicetimes =
[ 2.40 2.30 2.20 ... 0.10 0 ];
2. Descending
If descending, axial or transverse slices will be acquired superior to inferior, or head to foot, with the first slice being near the top of the brain and the last slice being the most inferior one.
The descending mode is the default ordering, but you should confirm this for your protocol with the MR technician. If your experiment is performed with the mosaic 64 sequence descending, your slicetimes might look like the following:
slicetimes =
[ 0 0.10 0.20 ... 2.30 2.40 ];
You could make use of whatever Matlab shortcuts you may know. You could for example
create an array with a numslices variable being the number of slices in your functional images:
slicetimes = ( 0 : ( numslices - 1 ) ) * 0.100;
3. Interleaved
The order of acquisition of an interleaved scan depends whether the total number of slices is odd or even.
A. Odd numbered total amount of slices
If your fMRI images were acquired with an odd numbered total amount of slices, the default interleaved sequence begins with the most inferior slice and acquires every odd numbered slice first, ascending to the top of the brain. The acquisition then returns to the lowest even slice and ascends to the top of the brain acquiring all the even slices.
As an example, if you are using the 128 matrix fMRI sequence, and you choose to acquire in
interleaved order, the lowest axial slice is excited first, and the second slice from the
bottom of the brain will be acquired only after all the odd numbered slices are acquired. So the slicetimes vector will look like the following for an odd numbered 15 slice acquisition with 110 ms per slice:
slicetimes = [ 0.7700 1.5400 0.6600 1.4300 0.5500 1.3200 0.4400 ...
1.2100 0.3300 1.1000 0.2200 0.9900 0.1100 0.8800 0 ];
The shortcut Matlab code that generated these interleaved slicetimes is a bit tricky and there are several ways to do it. Here is one way:
slicetimes_tmp = (14:-1:0) * 0.110;
s1 = slicetimes_tmp(8:15);
s2 = slicetimes_tmp(1:7);
slicetimes(1:2:15) = s1;
slicetimes(2:2:15) = s2;
B. Even numbered total amount of slices
If your scanning protocol specifies an even numbered total amount of slices, the default interleaved sequence starts with the even slices acquired first, then the odds. In this case your order of acquisition would be first slices 2, 4, 6, ..., then slices 1, 3, 5, ...
As an example with the same slice parameters as above, except with an even numbered total slices, say 14, we have the following:
slicetimes = [ 0.6600 1.4300 0.5500 1.3200 0.4400 1.2100 0.3300 ...
1.1000 0.2200 0.9900 0.1100 0.8800 0 0.7700 ];
Note: If you require accurate timing information, you should try to configure your stimulus presentation software to record the time when each trigger signal is received, even if you do not require the trigger to advance the stimulus presentation. You may recall that each time a frame begins, the scanner emits a TTL pulse which we convert into keyboard keypresses or mouse clicks. Refer back to the fmri resources section for a review.
events is a matrix whose rows are events and whose columns are:
- eventid - an integer from 1 to number of events to identify event
type;
- eventimes - start of event, synchronized with frame and slice
times;
- durations- (optional - default is 0) - duration of event;
- heights- (optional - default is 1) - height of response for
event.
For each event type, the response is a box function starting at the event
times, with the specified durations and heights, convolved with the
hemodynamic response function, or HRF. If the duration is zero, the response is the
HRF whose integral is the specified height - this is useful for 'instantaneous'
stimuli such as visual stimuli. The response is then subsampled at the appropriate
frame and slice times to create a design matrix for each slice, whose columns correspond
to the event id number.
Let us now consider our example case, which was a block design of three frames rest,
three frames hot, three frames rest and three frames warm, all repeated 5
times. The hot event is identified by 1 and the warm event by 2 and the rest condition
is left unspecified since it is the baseline. The events start at times 30, 90, 150, ...
and each has a duration of 30 seconds, with equal height. This means we can write:
eventid = kron (ones(3,1), [1;2]);
eventimes = (0:5)' * 60 + 30;
duration = ones(6,1) * 30;
height = ones(6,1);
events = [ eventid eventimes duration height ];
or:
events = [
| 1 | 30 | 30 | 1 |
| 2 | 90 | 30 | 1 |
| 1 | 150 | 30 | 1 |
| 2 | 210 | 30 | 1 |
| 1 | 270 | 30 | 1 |
| 2 | 330 | 30 | 1 ]; |
Note: "kron" stands for Kronecker tensor product, and it is a function used in Matlab.
The use here is just to give you an example of an easy way to make your design matrices. You
are free to write the events matrix in any way that you prefer.
One thing to keep in mind is that all values for all frames must be given,
because the smoothing and lagging by the hemodynamic function is done on all frames
before fmrilm excludes the initial time points.
At this point, all of the necessary variables are defined. There are other
parameters which you can specify - type 'help fmridesign' for a complete list.
If you choose not to specify any trailing variables, you will obtain their default
values. The final design matrix can be calculated by calling the
fmridesign function in Matlab and equating its output to an X_cache
variable:
X_cache = fmridesign (frametimes, slicetimes, events)
The output of this function, the struct X_cache will be used as an input for the
next step in the analysis, the function fmrilm.
This fmristat function reads in an fMRI file and writes out a t-statistic file.
The inputs to fmrilm are: input_file,
output_file_base, X_cache,
contrast, exclude,
which_stats, fwhm_cor, and
n_ntrends.
There are several values output, including df.t, the
effective degrees of freedom of the T statistic. And if an F-statistic is performed, df.F is also
available. Again the input variables have to be defined first before we can use the function.
input_file, is the minc file we would like to analyze
and it is the dependent variable. In our case:
input_file = 'study_subj001_20031019_111740_3_mri_MC.mnc'
output_file_base, is a matrix whose rows are the base
filenames for the output statistics, one filename base for each row of
contrast is needed.
Let us consider that in our example we would like to compare hot minus warm
(hmw) and an overall combined effect of hot plus warm (hpw) stimulus versus the
baseline. So the output_file_base will look like this:
output_file_base = |
['study_subj001_20031019_111740_3_mri_MC_hmw'; |
| 'study_subj001_20031019_111740_3_mri_MC_hpw']; |
X_cache is the design matrix for all slices and it is
the output from fmridesign.
contrast is a matrix whose rows are contrasts for the
response variables, and columns are the contrasts. The column numbers will correspond to the event ids that were used in the events matrix above. Since in this example, we want to
test for hot minus warm, and also for hot plus warm, against the baseline, the contrast matrix will look like:
exclude is a list of frames that should be excluded from
the analysis. This could be used to remove the first few frames of your functional run,
which may not represent steady-state images. You can also use this variable to exclude
frames during which your subject moved more than 1mm or 1 degree.
exclude = [ 1 2 ];
which_stats is a matrix that indicates desired output
statistics with a series of strings. Rows correspond to the rows of contrast. The required
strings to use are as follows:
- _mag_t: T statistic image: the degrees of freedom is df. Note that t-stat = effect / sdeffect. The resulting output file will be
output_file_base_mag_t.mnc.
- _mag_ef: effect image, output_file_base_mag_ef.mnc
- _mag_sd: standard deviation of the effect,
output_file_base_mag_sd.mnc.
- _mag_F: F-statistic image, output_file_base_mag_F.mnc, for
testing all rows of contrast simultaneously. The degrees of freedom is available through df.F.
- _cor: the temporal autocorrelation, output_file_base_cor.mnc.
- _resid: the residuals from the model, output_file_base_resid.mnc, only for the non-excluded frames (warning: uses lots of memory).
- _wresid: the whitened residuals from the model,
output_file_base_wresid.mnc, only for the non-excluded frames
(warning: uses lots of memory).
- _AR: the AR parameter(s) a_1 ... a_p, in
output_file_base_A.mnc
- _fwhm: the estimated FWHM in the first frame of
output_file_base_fwhm.mnc
If which_stats is a row vector, then it is
used for all contrasts. The default output is _mag_t, which gives you just the t-stat output. Do not forget to include the leading underscore character:
which_stats
= '_mag_t _fwhm _mag_sd _mag_ef' ;
fwhm_cor is the fwhm in mm of a 3D Gaussian kernel used
to smooth the autocorrelation of residuals. This is NOT the fwhm
of the image data as used by stat_threshold, but should be fairly large. Setting
it to Inf smooths the autocorrelation to 0, i.e. it assumes the scans are
uncorrelated (this is appropriate when the TR>10 seconds). If this value is negative it is taken to be the desired df. The default is -100, to target a df of 100.
fwhm_cor = -100;
n_trends is the number of trends
to remove. This is a 3 column vector of the following form:
n_trends=[n_temporal n_spatial pcnt]
- n_temporal: the number of cubic spline terms to
remove per 6 minutes of scanning time. The n_temporal default value is
3. Other values for
n_temporal:
n_temporal = 0: will remove just the constant term and no temporal
trends
n_temporal = -1: will not remove anything
- n_spatial: order of the polynomial in the spatial
average weighted by first non-excluded frame, 0 will remove no spatial
trends and the default is 1.
- pcnt: if pcnt=1, then the data is converted to
percentages before the analysis by dividing each frame by its spatial average, * 100%
The default value for n_trends is
[ 3 1 1 ]. This will convert the
data to percent of whole volume and spatially and temporally detrend it.
Note: If you wish to execute the analysis according to the method
employed by previous versions of fmristat prior to 2002, you should set n_trends =
[ 3 0 0 ];
At this point all the variables for fmrilm are set, and the command can be
issued in Matlab:
[df spatial_av] = fmrilm (input_file, output_file_base, X_cache,
contrast, exclude, which_stats, fwhm_cor, n_trends);
After running fmrilm, the statistics are calculated, and the
output_file_base_mag_t.mnc file is the t-stat map file. The statistical
significance thresholds for the t-maps should be calculated. To do that,
stat_threshold is used, also on the Matlab
command line.