\(\newcommand{L}[1]{\| #1 \|}\newcommand{VL}[1]{\L{ \vec{#1} }}\newcommand{R}[1]{\operatorname{Re}\,(#1)}\newcommand{I}[1]{\operatorname{Im}\, (#1)}\)

Scripting of SPM analysis with nipype

Requirements:

Can you write a Nipype script to do all the pre-processing in SPM?

You are doing an analysis for the following scans:

In the following, remember you can explore the individual Nipype objects like this:

>>> from nipype.interfaces import spm
>>> slice_timer = spm.SliceTiming()
>>> slice_timer.help()
Use spm to perform slice timing correction.
...

The script should do the following, using nibabel and Nipype:

  • copy the structural image with a prefix of c because SPM will modify the image during registration (it modifies the image affine);
  • drop the first 4 volumes from the functional run. Save the new functional image with a filename prefix of f.
  • run slice timing, assuming an ascending interleaved slice acqusition order (first, third, …, second, fourth, …). See SPM slice timing exercise for details. The resulting funcitonal image will have a filename prefix of af;
  • run motion correction estimation, and write out the mean image across volumes. You will need nipype.interfaces.spm.Realign. The mean image will have filename prefix meanaf. Hint: to write only the mean image, you need a inputs.write_which value of [0, 1]. See the script fragment below;
  • estimate the registration of the structural image to the mean functional image: nipype.interfaces.spm.Coregister;
  • register the (registered) structural image to the template and write the slice-time corrected functional image with these estimated parameters: nipype.interfaces.spm.Normalize12. SPM calls this “spatial normalization”. The resulting functional image will have a prefix of waf. Hint: I’ve put suggested values for the bounding_box input parameter in the script fragment below;
  • smooth the spatially normalized 4D functional image by 8mm FWHM: nipype.interfaces.spm.Smooth. The resulting functional image will have the prefix swaf.

Your script will likely start something like this:

""" Script to run SPM processing in nipype
"""
import shutil

import nibabel as nib

# Import our own configuration for nipype
import nipype_settings

import nipype.interfaces.spm as spm

# Start at the original image
base_fname = 'ds114_sub009_t2r1.nii'
structural_orig = 'ds114_sub009_highres.nii'
structural_fname = 'cds114_sub009_highres.nii'

# Copy the structural, because SPM will modify it
shutil.copyfile(structural_orig, structural_fname)

# Analysis parameters
TR = 2.5
slice_time_ref_slice = 1  # 1-based indexing
n_dummies = 4
# Realign "write_which" input. The 0 means 'do not write resampled versions of
# any of the individual volumes`.  The 1 means 'write mean across volumes after
# motion correction'.  See config/spm_cfg_realign.m in the SPM12 distribution.
write_which = [0, 1]
# Normalize write parameters.  Bounding box gives extreme [[left, posterior,
# inferior], [right, anterior, superior]] millimeter coordinates of the voxel
# grid that SPM will use to write out the new images in template space.  See
# spm_preproc_write8.m for use of the bounding box values.
bounding_box = [[-78., -112., -46.], [78., 76., 86.]]

When you have finished, have a look at the solution script at nipype_ds114_sub009_t2r1.py.