Wednesday, November 7, 2012

Slice Timing Correction in SPM

I have posted a couple new videos about slice-timing correction in SPM: One from the GUI, and the other from the command line. The command line usage is more interesting and informative, especially if you aim to batch your preprocessing without using the graphical user interface; and this will be the goal of this series of tutorials.

And just imagine - no more mindless pointing and clicking. No more sore wrists and carpal tunnel syndrome from those long nights of copying and pasting onset times, one after the other, subject after subject, until your mind becomes so warped that you accidentally end up copying and pasting a particularly spicy, shockingly personal, yet oddly poetic missive sent to an ex-girlfriend after quaffing one too many Smirnoff Ices, which then ends up estimating a general linear model of your pathetic and utter wretchedness. Obviously, this analysis will go into the supplementary materials.

To avoid this, slice timing can instead be called by the program spm_slice_timing, which requires the following arguments:

P - A list of files to slice time correct (can select these using spm_select)
sliceOrder - Slice acquisition order
refslice - Reference slice for time zero
timing - requires two arguments: 1) time between slices; and 2) time between last slice and next volume

sliceOrder can be assigned with a Matlab concatenation command. For example, if the slices were acquired in an interleaved order starting with slice 1, and there were 35 slice total, the slice order could be written like this:

sliceOrder = [1:2:35 2:2:35];

Which would return a list of numbers going from 1 to 35 by steps of 2, and then going back and concatenating this with a list of numbers from 2 to 35 by steps of 2.

The timing variable is easy to fill in once you have both the TR and the TA variables. TR is your repetition time - for example, 2 seconds between volumes. TA is defined as TR-(TR/(num. of slices)), which in this case would be 2-(2/35) ~ 1.94. This is the time at which the last slice was acquired; and, since the first slice was acquired at time 0, the time between each slice can be calculated as TA/nSlices, e.g. 1.94/(nSlices-1) = 1.94/34 ~ 0.057 (not significant, but trending towards it). Likewise, the value for the second field can be calculated as TR-TA, which also equals about 0.057. If the variables TR and TA have already been assigned values, then the fields of the timing variable can be filled up:

timing(1) = TA/nslices;
timing(2) = TR-TA;

With this in hand, spm_slice_timing can be filled in as follows:

spm_slice_timing(spm_select('List', pwd, '^r01.nii'), [1:2:35 2:2:35], 0, timing)

Both versions of slice timing correction can be found in the following tutorials:

The GUI version of slice timing correction. This is for little kids and grandmas.

Now we're talking; this is the real sh*t. Henceforth shall you be set on the path towards nerd glory, and your exploits shall be recorded in the blank verse epic, Childe Roland to the Nerd Tower Came.


  1. Dear Andrew,

    thanks a lot for this great blog! It helps beginner's like me a lot.
    Now, when I try to adapt your script I get the following error:

    Reference slice should contain a slice index.

    Do you know how to fix this? In this context I was wondering, why did you put a zero for the reference slice?

    as I have an even number of slices, my slice_order looks like this:
    [2:2:36 1:2:35]

    1. Hey there,

      That's because the refslice can either be your actual slice for time zero, or it can be the time in milliseconds for the first slice. In your case, you could just put your TR in milliseconds, since it seems as though you are starting from the second slice that was acquired.


  2. Hi, first of all thanks a lot for your useful tutorials. I was just wondering if slice timing is also needed for block designs. I read that it is good for event-related designs. I actually do have blocks of an active condition (5 x 60 sec) with a rest conditions of 45 sec inbetween. What would you recommend?

    1. Hey, no problem! I'm always glad to help. For slice timing, it's not that important for block designs, since you're usually not that interested in what's going on at a TR by TR basis (which is more important in event-related designs). However, if you still wanted to account for delay effects in the HRF but without any of the interpolation introduced by slice timing, you could try including time derivates by selecting "Time Derivatives" under the "Model Derivatives" menu in the Specify 1st-level module in SPM.