Friday, April 26, 2013

working with NIfTI files in R: background

As I've written about before, I generally work with NIfTI-formatted fMRI images, often in R, using the oro.nifti package.

Recently I've had some difficulty with my written nifti-format images: they were not being read properly in some software packages (particularly caret and afni). After much frustration, I think I tracked the problem down to setting some of the nifti header fields incorrectly. In the hopes of reducing others' frustration, and perhaps eliciting some suggestions, in this set of posts I will demonstrate what I believe is proper way to read and write nifti images in R. As always, please share your experiences, particularly if you think a different strategy is more robust.

thinking about brain image data

First, some framing. We're all used to seeing brain image data shown like this (in MRIcroN): a three-dimensional picture. Most neuroimaging software uses this type of visualization; we open a nifti (or whatever format) image, and see a brain-shaped picture. But what is in a nifti file? It is sometimes surprising to people that the nifti file for a single brain image just stores a 3d array of numbers, plus a "header" file that contains information about how the numbers should be turned into a picture; how the numbers in the array relate to the real world.

This picture is made by assigning a color to every value in the 3d array; the picture turns out brain-shaped because the numbers in the array are brain-shaped. If this isn't obvious, consider this picture:

This is my sketch of a 3d array. Each array entry (voxel) has a number, giving the amount of "activation" (or whatever) in that particular voxel. Programs like MRIcroN assign a color to the number in each box when they make the brain image plots like the top picture, using the header information to translate the 3d array into actual space. (If 3d arrays still are not clear, do a bit of google searching before reading on; it's critical for understanding how to work with nifti images in R.)

at least two sets of coordinates

We always need to consider at least two sets of coordinates with neuroimaging data, and be able to move between them when needed. One set gives the location of the voxel in the 3d array, while the other gives the location of the voxel in an aligned space (e.g. MNI, or the distance from an anatomic landmark). (This is sometimes referred to as i,j,k vs. x,y,z coordinates, particularly in afni.)

The two sets of coordinates are shown in my MRIcroN screen image above: the yellow bar highlights the X=10, Y=17, Z=21 boxes, while the red bar indicates the -42,-48,30 coordinates. This means that the crosshairs are showing the voxel at location 10,17,21 in the 3d array, but location 42,-48,30 in the anatomical space specified in the nifti header. This voxel has a value of 496 (green bar).

All this means that the same 3d array of numbers could be plotted in many ways just by changing the header information. For example, in the next post I'll include R code to write nifti files. Here I wrote a 3d array twice, once setting the voxel size in the header to the true value, 4x4x4mm (blue). But then I wrote the same 3d array again, but setting the voxel size in the header to 3x3x3 mm (red). I then opened up the ch2bet template in MRIcroN and overlaid both images.

As you can see, MRIcroN plotted both images without complaint, but the 'blob' locations and sizes do not match: the red clusters are smaller and shifted towards the posterior left.


Before describing reading and writing NIfTI files in R I wanted to introduce some of the underlying concepts: image data is stored as a 3d array*, with real-world orientating information in the header fields.

*I keep referring to 3d arrays for simplicity. But fMRI data is often stored as 4d arrays, or even higher. In this case the 4th dimension is time (usually TR). But the concepts are the same - we have the large array holding the voxel values, then the header with the orientating information.

No comments:

Post a Comment