Introduction - FSLUTILS

To work with FSL, it is essential to become comfortable in working at the UNIX command line. This practical introduces some of the more useful FSL command line utilities, which allow you to query and manipulate your image files.

Contents:

FSLUTILS
An introduction to working with images on the command line (typing in the terminal), for doing things like making image measurements and carrying out basic maths on images.
More FSLUTILS (optional)
Learn how to use fslsplit, fslmerge and fslroi (for breaking apart images, putting them back together and extracting ROIs).

FSLUTILS

cd ~/fsl_course_data/intro

fslinfo and fslhd

These tools enable various properties of an image to be viewed.

Type fslinfo sub-002_T1w_brain and fslinfo thresh_zstat1 and note their different image matrix dimensions (dim1-3) and voxel sizes, in mm (pixdim1-3).

Note that some images (sub-002_T1w_brain) are of integer datatype, while others (thresh_zstat1) are of floating point datatype. Integer means that the intensity values can only take on whole numbers - no fractions - raw image data is normally of this type. Floating point means that intensity values can be fractional - the result of applying most statistical processing algorithms to image data results in images of floating point type.

Also try running fslhd on these files. This provides much more detailed information about the images. Don't worry if you don't know what every field means.


fslstats

fslstats is a general tool for calculating various values/statistics from the image intensities. It is quite flexible but we will just illustrate some basic uses here. Type fslstats to see the full list of possible options and brief description of the output. Any combination and order of options is possible.

Run

fslstats sub-002_T1w_brain -R -r

The first pair of numbers (specified by -R) is the absolute range of the data - i.e., the min and max intensities. The second pair (-r) is the "robust range" - i.e. the min and max if the outer tails of the intensity distribution are ignored (this is useful if the data contains outliers). View the image histogram in FSLeyes to see how all these numbers relate to the histogram.

Slightly confusingly, the robust range doesn't seem to be doing the same thing for the left and right tails. This is because there are lots of empty voxels in the image (because the data has been brain-extracted) that are affecting the calculation. Click on the spanner button () on the histogram toolbar, expand the Histogram settings for selected overlay section, un-check the Ignore zeros setting, and enter -1 for the minimum Data range bound. See how the histogram is affected.

Run:

fslstats sub-002_T1w_brain -m -M

The first number is the mean intensity of all voxels in image, whilst the second is the mean of only the non-zero voxels. The first is much lower because of all the zero background voxels dragging down the mean. The second number is a more meaningful mean of the actual within-brain intensities - view the image and click around inside the brain to see this.


fslmaths

fslmaths is a very general image calculator and can be used to perform a great variety of manipulations of images. See the (long) usage by just typing fslmaths. Don't worry about understanding it all at this point, we will illustrate some basic uses here, but be aware that it is a very general and powerful tool that is worth getting to know.

As a very simple example, we will find the difference between two consecutive timepoint images (the images are extracted from a functional dataset, and this difference calculation might be used as part of a quality assessment). Do this by running:

fslmaths image0 -sub image1 imdiff

and view the output (the final argument in that command) in FSLeyes. Now calculate this as a percent difference image by running:

fslmaths imdiff -div image0 -mul 100 imdiffpercent

This means: "take the difference image, divide by the first of the original images (voxelwise), multiply by 100, and output". View the output in FSLeyes, and then use fslstats to calculate its absolute and robust range - see that the robust range is quite small, with most change showing up as motion effects round the edge of the brain.

Make sure that you understand the fslmaths commands above; and note that in general an "input" can be a number instead of an image (the "100" could have been an image name instead). This does not apply to the first input in the command!


Combining fslmaths and fslstats

Now let's consider another example where we need both fslmaths and fslstats. In this example we will take a probabilistic ROI of the left Thalamus (already transformed from a standard-space atlas) and quantify some characteristics of the thresholded fMRI activations that we viewed earlier. This will involve making an appropriate binary mask and then using this with fslstats.

If you view the image LThal_mask_func in FSLeyes (best if loaded on top of the example_func image) you will see that it contains values between 0 and 1, representing the probability that each voxel is part of the thalamus. To use this as a mask it is necessary to turn it into a binary image (where each voxel contains either 0 or 1 but no numbers in between). This requires choosing a threshold value and then applying this in fslmaths to make a binary image. Let us choose 0.5 (i.e. 50% probability) as the threshold, and apply it with this command:

fslmaths LThal_mask_func -thr 0.5 -bin LThal_mask_func_bin

After running this load the output image in FSLeyes and see what it has done to the mask, particularly at the edges.

We can now use this mask with fslstats to extract the size of the ROI, the size of the overlap with the thresholded statistic map and the average value of the statistics within this ROI. These can be calculated with the following commands:

fslstats LThal_mask_func_bin -V
fslstats thresh_zstat1 -k LThal_mask_func_bin -V
fslstats thresh_zstat1 -k LThal_mask_func_bin -M

See if you understand what each command does and what the output means. If not, look at the usage for fslstats, by typing it on its own at the command line and pressing return. If it still isn't clear then ask one of the tutors.

Note that in the last command the -M option was used (as opposed to -m) to ensure that the average is only within the area where the thresholded stats are non-zero inside the ROI.

Becoming familiar with fslmaths and fslstats can save you a huge amount of time when you want to carry out simple image manipulations quickly. Also, if you want to carry out simple things many times, you can easily put these commands into small scripts (text files that contain the same commands that you might type in the terminal). We cannot emphasise strongly enough how useful it can be to learn these basic command-line programs, and also basic scripting. (Unfortunately you will probably not have time during the course to go through the scripting practical - there's just too much stuff to fit in! - but we do recommend that you have a look at it after the course, at least the first few basic sections).


More FSLUTILS (optional)

fslsplit and fslmerge

The following exercises are intending to teach you how to use the tools fslsplit, fslmerge and fslroi. The examples represent some situations that can be encountered in practice, but the scope of these tools goes way beyond these specific examples. Familiarity with these basic tools can help in getting data into the right format for analysis, in case it is not that way to begin with (which is more common than you might think) or give you ways of looking at original or processed data in different ways.

In this example we will look at a way of separating a diffusion sequence into diffusion-weighted and non-diffusion-weighted parts. To start with, check how many timepoints there are in the diffusion-weighted acquisition sub-003_dwi using fslinfo and then run:

fslsplit sub-003_dwi

to split up the 4D input image into its individual 3D images, or volumes, (vol0000, vol0001, vol0002, etc.). To list these new files do:

ls vol*

(note that the * is expanded by the terminal to fit any characters in all possible filenames present, and so can be used in any commands, not just ls, as we will see below). You'll see that the counting of the images starts with 0, and that the number of images should match the number of timepoints in the original 4D image.

In this diffusion sequence, as in most, there are several non-diffusion-weighted scans (the "b=0" scans) which show up as very bright in the diffusion sequence (try viewing diffdata in the movie mode of FSLeyes). So we will separate this data into two 4D images: one containing just non-diffusion-weighted scans and one containing the diffusion-weighted scans. This is not always necessary for analysis of diffusion data, but can be helpful for visualisation of input and processed data.

In this sequence there are 4 non-diffusion scans: numbers 0, 16, 32 and 48, with the counting starting at zero, just like in FSLeyes and consistent with how fslsplit numbers things. These numbers could be found from the bvals file, or by looking at the data in FSLeyes, but here we are giving them to you.

The easiest way to separate the two sets is just to rename the non-diffusion volumes, using the UNIX mv command like this:

mv vol0000.nii.gz b0vol0000.nii.gz

and doing the equivalent for vol0016.nii.gz, vol0032.nii.gz and vol0048.nii.gz. Note that because mv is not a specific FSL command it is absolutely essential to include the .nii.gz part of the filenames (whereas for FSL commands it doesn't matter if these are included or left out).

Check that these files have been renamed correctly by looking at the directory contents using ls. Now remerge the remaining diffusion-weighted 3D images into a new 4D image with:

fslmerge -t sub-003_dwi_diff vol*

The -t tells fslmerge to merge the images in time (fslmerge is also capable of doing other merges, such as stacking them on top of each other in space). After "sub-003_dwi_diff" (the name of the output image), fslmerge expects a list of images to be merged. As mentioned above, for all FSL commands the image names can be used with or without including the filetype extension (extensions are .nii.gz .hdr .img etc.).

View the resulting image in FSLeyes using the movie loop and check that the non-diffusion-weighted scans not part of this new 4D image. See how much easier it is to visualise the data this way.

The non-diffusion scans can also be merged into a single 4D image using:

fslmerge -t sub-003_dwi_b0 b0vol*

fslroi

We will now fix an image that is "wrapped", with the nose sitting behind the back of the head, as you sometimes see in poorly planned acquisitions ...

fsleyes sub-004_T1w_wrapped &

You will use fslroi to split this image into two (front and back parts) and fslmerge to remerge them back together in the right order. In FSLeyes, look at an inferior (bottom) axial slice so that you can work out the y coordinate (in the anterior-posterior direction) where you want to make the split. Record the y-coordinate (in voxels, not mm).

Now use fslinfo to find out what the image matrix dimensions are (dim1,dim2,dim3). You're now ready to extract the back part of the head into a temporary file. If your y-coordinate was 76 you would do:

fslroi sub-004_T1w_wrapped sub-004_T1w_back 0 256 76 180 0 128

Now just type fslroi to see the usage. There are several ways to run fslroi: you can specify just a 3D ROI, as we have done here - this is the first of the usage possibilities. The second option is to extract a temporal ROI from a 4D dataset (one or more full 3D volumes). The final option extracts a 4D ROI from a 4D dataset, controlling the region to be extracted in space and time. The program knows which option you want from the number of "arguments" that you type. Note that if you use the first option (3D ROI) on a 4D input file, the output will still be 4D, with the number of timepoints unchanged, and each volume cut down in 3D in the same way, as specified by the arguments.

Make sure that you understand the exact numbers used in the above command, that created the sub-004_T1w_back image; note in particular that the second number in each pair is the length of the ROI in the relevant dimension, not the end point - the <ysize> was 180 (256-76) not 256.

Now work out how to run a similar command to create "sub-004_T1w_front", from the back part of sub-004_T1w_wrapped.

Use fslmerge to merge front and back together correctly, and verify with FSLeyes. You could also do a similar thing with the slight wraparound at the top of the image.

As a last example, we will use fslstats to determine an ROI to use with fslroi. To do this run:

fslstats sub-002_T1w_brain -w

which will generate a set of numbers suitable for fslroi. This ROI is the smallest ROI possible that fully contains all non-zero voxels. We could now run fslroi using these numbers, but instead we'll combine the two commands into one, using the unix trick of putting a command within ` quote marks (this is the backquote, not the usual forward quote!). When you put a command within these quote marks then this part of a larger command will get replaced by the text output of the command within quotes. We will cut down sub-002_T1w_brain so that the image just about contains the brain, and the end slices that only contain zeros are thrown away. Run the following, and then try to understand how it works:.

fslroi sub-002_T1w_brain sub-002_T1w_brain_roi `fslstats sub-002_T1w_brain -w`

Another UNIX trick - the back-slash character ("\") in the fsleyes command here allows you to split a long command across multiple lines to make it easier to read.

You can see what fslroi has done by overlaying the two images in FSLeyes:

fsleyes sub-002_T1w_brain -cm red-yellow -dr -1 16000 \
sub-002_T1w_brain_roi -cm blue-lightblue -dr -1 16000

The End.