“What went wrong?” data processing edition#

So, we got through our data acquisition. The raw images look good. What do we do with that?

It’s recommended to follow a standardised processing protocol, like fMRIPrep, but many times there are hidden parameters which are not applicable for rodents. Here are some of the most common obstacles that were unearthed during the development of fMRIPrep-rodents.

Example 1#

First, we will correct for non-uniformity that is inherent across the intensity values of many types of “weighted” images. This example used the default call to N4BiasFieldCorrection from ANTs. Let’s look at the original first:

import nanslice.jupyter as ns
%matplotlib widget

ns.three_plane('assets/example-1_desc-orig_proc.nii.gz', interactive=True, clim=(0,150))

Now let’s look at the corrected image. The results are not as good as they could be.

ns.three_plane('assets/example-1_desc-n4default_proc.nii.gz', interactive=True, clim=(0,150))
ns.three_plane('assets/example-1_desc-n4final_proc.nii.gz', interactive=True, clim=(0,150))

Example 2#

Our next step is “brain masking”. We will use the popular FSL tool bet to remove non-brain tissue (aka skull-strip) an image. This step helps downstream preprocessing such as registration.

ns.three_plane('assets/example-2_desc-orig_proc.nii.gz', interactive=True, cmap='gray')

After applying the mask supplied by bet, the image looks like this:

ns.three_plane('assets/example-2_desc-bet_proc.nii.gz', interactive=True, cmap='gray')

Let’s try another tool, instead this one is made for rats: AFNI’s 3dSkullStrip with the -rat flag.

ns.three_plane('assets/example-2_desc-3dss_proc.nii.gz', interactive=True, cmap='gray')
ns.three_plane('assets/example-2_desc-arts_proc.nii.gz', interactive=True, cmap='gray')

Example 3#

This example involves normalisation of the anatomical image of a mouse to a standard space template. First, let’s load the target image (disclaimer: this image isn’t completely raw; it has been clipped and normalised in preparation for the normalisation):

ns.three_plane('assets/example-3_desc-orig_proc.nii.gz', interactive=True, cmap='gray')

and the template:

ns.three_plane('assets/example-3_desc-tpl_proc.nii.gz', interactive=True, cmap='gray')

Now, let’s look at the processed image:

ns.three_plane('assets/example-3_desc-warped_proc.nii.gz', interactive=True, cmap='gray')

Example 4#

This example uses EPI data normalised in SPM. The warp calculated the mean across time to a template image, and then applied it to each frame individually.

Below is the output warped EPI volume:

ns.three_plane('assets/example-4_proc.nii.gz', interactive=True, clim=(0,50))

Example 5#

Our final example uses FSL’s topup tool to correct for susceptibility distortion in EPI images. We have two spin-echo images, one with the phase-encoding direction that is superior to inferior, and the other with a phase-encoding direction going from inferior to superior.

Below are the mean images of the volumes acquired for each phase-encoding direction:

ns.three_plane('assets/example-5_dir-IS_desc-tmean_proc.nii.gz', interactive=True, clim=(0,50))
ns.three_plane('assets/example-5_dir-SI_desc-tmean_proc.nii.gz', interactive=True, clim=(0,50))

The topup output is less than desirable:

ns.three_plane('assets/example-5_desc-orig_proc.nii.gz', interactive=True, clim=(0,50))

What do you think the problem was?

import nibabel as nb

img = nb.load('assets/example-5_dir-IS_desc-tmean_proc.nii.gz')
hdr = img.header
print(hdr)
<class 'nibabel.nifti1.Nifti1Header'> object, endian='<'
sizeof_hdr      : 348
data_type       : b''
db_name         : b''
extents         : 16384
session_error   : 0
regular         : b'r'
dim_info        : 0
dim             : [ 3 60 48 36  1  1  1  1]
intent_p1       : 0.0
intent_p2       : 0.0
intent_p3       : 0.0
intent_code     : none
datatype        : float32
bitpix          : 32
slice_start     : 0
pixdim          : [1.  0.4 0.4 0.6 1.5 1.  1.  1. ]
vox_offset      : 0.0
scl_slope       : nan
scl_inter       : nan
slice_end       : 0
slice_code      : unknown
xyzt_units      : 10
cal_max         : 0.0
cal_min         : 0.0
slice_duration  : 0.0
toffset         : 0.0
glmax           : 0
glmin           : 0
descrip         : b'6.0.5:9e026117'
aux_file        : b''
qform_code      : unknown
sform_code      : aligned
quatern_b       : 0.0
quatern_c       : 0.70710677
quatern_d       : 0.70710677
qoffset_x       : 12.0
qoffset_y       : -9.731
qoffset_z       : -11.266
srow_x          : [-0.4  0.   0.  12. ]
srow_y          : [ 0.     0.     0.6   -9.731]
srow_z          : [  0.      0.4     0.    -11.266]
intent_name     : b''
magic           : b'n+1'
ns.three_plane(
  'assets/example-5_desc-micron_proc.nii.gz',
  interactive=True,
  cmap='gray',
  clim=(0,50),
  title='unit adjusted header'
)
ns.three_plane(
  'assets/example-5_desc-scaled_proc.nii.gz',
  interactive=True,
  cmap='gray',
  clim=(0,50),
  title='scale adjusted header'
)