Freesurfer BOLD files

From CCN Wiki
Jump to navigation Jump to search

Freesurfer, like SPM, can perform functional analyses on fMRI data. These analyses generally employ the general linear model (GLM) to assess the degree to which the blood-oxygen dependent (BOLD) signal correlates with different predictors (e.g., group, experimental condition, task or even nuisance regressors such as motion).

For Freesurfer and SPM, these files will start off as NIfTI (.nii) files. Each file contains a header, which contains important information directing the software how to interpret the data, and one or more 3D matrices of raw data, representing the signal at each voxel at a particular point in time, as measured by the scanner during the experiment. The data for a single run (e.g., a 5-minute scan of an experimental task) can be stored as a series of individual 3D volume files, with each file representing a single scan of the brain like a single frame of a 5-minute movie. Alternately, multiple volumes can be concatenated together and stored in a single 4D file. Whereas SPM operates on either 3D or 4D data, Freesurfer seems to require 4D data.

The header information is important because it provides the context required to interpret the data matrix. For example, an experiment looking at hippocampal processing might use a 32 x 32 x 24 array of 1mm voxels and look at a relatively small subcortical volume. Another experiment looking at global cortical processing might use a 32 x 32 x 24 array of 3mm voxels to look at the entire brain volume. Without knowing the voxel size, it would be impossible for any piece of software to interpret the data matrix. The NIfTI header includes information about how big the voxels are, the orientation, and many other important bits of information, though not all software makes use of all the header information.

File Fixing

Freesurfer expects the BOLD data to be organized into individual folders for each experimental run, and that each file is called "f.nii". Moreover, Freesurfer (but not SPM) appears to make use of the TR value stored in the NIfTI header. In order to ensure that the filename requirement is met and that the TR value is correctly set, a script called set_TR.m can be found in the ubfs Scripts/Matlab folder. Another issue, specific to our scanner, is the fact that the Toshiba scanner at the CTRC does not (currently) do anything to account for the magnetic field inhomogeneity that invariably accompanies the first several seconds of a functional run. Other scanners (e.g., Siemens) automatically discard the first several seconds of data. Because the BOLD data from the CTRC will have this magnetic field inhomogeneity artifact, we must manually drop the affected volumes and also remember to adjust the onsets of the experimental events accordingly.

Golden Rule

Never directly modify the BOLD data in the raw files. Instead, copy the raw data to your working directory and work on copies of the data. This avoids the potentially catastrophic possibility of procedures being applied multiple times to the same data, resulting in data loss or mangling.

Note that certain operations are fine to apply to BOLD data because they don't change the data itself, but instead just make changes to the NII file headers that are easily detected and can easily be reversed. The only allowable change that you might consider doing to the raw data, however, is to set the TR.

Determining which volumes are important

Before you drop any volumes (the next step), you should be aware of the volumes that are associated with any events. For some of our studies, this may be constant across participants, and therefore something that a lab member familiar with the study can tell you. However, a MATLAB function called critVols can be found in the ubfs/Scripts/Matlab folder that can also provide this information. Copy it to your MATLAB path if you haven't already done so. This function requires the participant's PsychToolBox MATLAB runtime files -- the same files that are used to generate .par files. The simplest way to run the script is to call it with no parameters:

v=critVols(); %assume the default TR of 2.047

The function assumes a TR of 2.047, which is correct for the LDT and Multisensory Imagery study. If you are using it for any other study, you may need to specify the TR:

v=critVols('TR', 2.00); %overrides the default TR

As usual, there is a built-in help

help critVols

After you run this function on a set of .mat files, you will get a list of start and end volumes for each of the associated runs:

v{:}

Below is the information for the 6th run for participant 202, who participated in the LDT study:

ans = 

        run: 6
    subject: '0202'
   startvol: 5
     endvol: 242

This would tell us that nothing happened during volumes 1:4 and during the volumes from 242:end. You will almost certainly want to drop the first 4 volumes. Depending on your requirements, you may wish to drop the volumes at the end as well, but consult with a knowledgeable lab member first, if you have any question (it is essential that all data sets are treated the same way within a single study).

DENT Data: Fixing Files Using Drag and Drop with MRICron

NIfTI (.nii) files collected from DENT may have the incorrect number of volumes listed in the file header. Though the run often terminates before the 256 volume maximum has been reached, their system nonetheless indicates that the 4D volumes have 256 frames. If you open up the headers using fsledithd, you will receive a warning, and fsl will automatically pad the end of the 4D volumes with empty data frames (volumes containing only zeroes) until they reach the requisite file size. It turns out that the files with partial data frames are problematic for the motion correction for reasons that you will appreciate when you follow these directions.

Copy the RAW BOLD Files

The first step will be to copy the 4D BOLD data from the master file archive into separate directories. The original files will not be uniformly named, with names like 334_BOLD_run_1_4_1.nii. Copy each file into its own 3-digit subdirectory to indicate the run number, and rename each file to f.nii, e.g.:

  • 001
    • f.nii
  • 002
    • f.nii
  • etc.

Expand the BOLD Files

You will need to use the terminal for this part. In each of the run directories, use fslsplit to convert the single 4D f.nii files into a series of 3D files that will be named vol####.nii.gz.

fslsplit f.nii

At this point, if there is a mismatch between the number of time points in the file header and the amount of data stored in the file, a number of empty volumes will be generated, up to the number of volumes indicated in the file header. For example, if the file header indicates that there are 256 volumes but the MRI stopped recording after 210 volumes, the files named vol0210.nii.gz onwards will be dummy volumes. Note that the file numbers start at 0000. This is important to bear in mind: The file number will be one less than the volume index. For example, volume 1 is numbered vol0000.nii.gz. Likewise, the 256th volume is numbered vol0255.nii.gz.

After you've expanded the files, delete the original f.nii file:

rm f.nii

View Data Frames in MRICron

Installed on your workstation is a handy MRI file viewer called MRICron. Launch it (it may try to reload the last file you viewed -- just let it do whatever it wants). Now that you have the MRICron viewer window open, you can drag and drop .nii files directly into the viewer. If you have the Linux File Manager window open to a directory containing your expanded 4D volumes, you can drag any of these files into MRICron to find where the dummy data starts. Participants in the imagery study usually finish somewhere around volume 200-215, so you can test random files somewhere in that range. You're looking for the volume with the highest number where you can see an entire volume of BOLD data. If you want to see what I'm talking about, try loading in vol0255.nii.gz and you will probably see that the entire MRI volume just appears as a solid gray. If the MRI was stopped part-way through acquisition, you may also find the brain is partly cut-off. That volume is no good either, but that means you have probably found the first volume that you want to delete (load the volume immediately previous in the sequence and you should find that it contains a complete brain volume).

Now that you have figured out which volumes are the dummy volumes, you can select them in the file manager window and delete them. For example, if you determine that vol0209.nii.gz is good, but vol0210.nii.gz is a dummy volume, go ahead and delete all volumes from vol0210.nii.gz up to the end of the series (i.e., all the way to vol0255.nii.gz)

Finally, while we're here we can also drop the first for volumes, just to remain consistent with how we processed data from the CTRC. Go ahead and delete vol0000.nii.gz to vol0003.nii.gz (remember, the fourth volume is numbered 0003).

Merge Volumes

Back to the terminal window, we are going to use fslmerge to recombine the remaining volumes back into a single f.nii.gz file:

fslmerge -t f.nii vol*
rm vol* #deletes the individual volume files
#OPTIONAL: Also set the TR for the corrected file. Check with an expert before doing the next two steps
TR_DURATION=2.047  # the duration of the TR 
3drefit -TR ${TR_DURATION} f.nii.gz # While we're here, we can make sure the TR is precisely correct

Now we're good to go: we have a series of files named f.nii.gz that all have the first 4 volumes dropped, have the correct number of time points in the header, and have the correct TR.

Fixing Files in the Terminal

It turns out there are several useful utilities associated with AFNI and FSL that can let us do everything we need to do in the terminal, without running MATLAB. This is helpful if you want to automate the process with a script, but note also that the method described below doesn't handle 4D volumes where early stopping affects motion correction. Automation would require computing when the last TR of real data was acquired so that padded volumes could automatically be dropped.

Do I need to drop any volumes?

Run the following command to examine the .nii header for one of your BOLD files:

fslhd <filename.nii>

The first few lines of the output will look like this:

filename       f.nii.gz

sizeof_hdr     348
data_type      FLOAT32
dim0           4
dim1           64
dim2           64
dim3           29
dim4           220
dim5           1
dim6           1
dim7           1
vox_units      mm
time_units     s

The key line here is the number of elements in the time dimension (nt). Here we see there are 220 volumes in this file. Now let's compare to the original data, as it came off the scanner. Go to the raw data on ubfs and run the same command. In this case, we get the following output:

filename       1500-fMRI_BOLD.nii.gz

sizeof_hdr     348
data_type      FLOAT32
dim0           4
dim1           64
dim2           64
dim3           29
dim4           220
dim5           1
dim6           1
dim7           1
vox_units      mm
time_units     s

Egads! The new file and the original data both have 220 volumes, meaning that the new file has not yet had the first 4 volumes dropped, and so you're going to need to check out the procedures below.

Dropping Volumes Using dropvols.sh

Upon learning that fslroi can be used to easily drop volumes in a single step, I wrote a shell script found in /ubfs/Scripts/Shell/dropvols.sh. You should also find that it's on your path (/opt/scripts). If not, let someone know. You can find out whether it's in your path by running the following command in the shell terminal:

which dropvols.sh

If the command is in your path, it will tell you the location of the script.

The script will drop the first n volumes from the named file.

dropvols.sh
Usage: dropvols.sh <filename> <vols>

Example usage:

dropvols.sh f.nii 5 #will drop the first 5 volumes from f.nii

Note that even though the original file was a .nii file, the modified file will be gzip compressed, and saved as f.nii.gz (it may be possible to prevent it from gzipping the output, but it's really not worth the effort).

Deprecated: Dropping Volumes in the Terminal Using fslsplit and fslmerge

These steps are deprecated as of May, 2020 when I accidentally discovered that a single FSL utility, fslroi, can do this all in one shot. dropvols.sh now uses fslroi for this task. I leave these instructions for posterity.

Dropping the volumes with fslsplit

The FSL utility fslsplit will break up a 4D BOLD volume into a series of 3D BOLD volumes. The default behavior is to produce files named vol0000.nii.gz to voln-1.nii.gz from a 4D volume with n time points. For example, if your BOLD volume was 220 time points, this command would produce vol0000.nii.gz, vol0001.nii.gz, ... , vol0219.nii.gz

Conversely, the FSL utility fslmerge does the reverse.

We can chain these two commands together, deleting any unwanted volumes in between. Suppose we wish to drop the first 4 volumes. These correspond to vol0000.nii.gz, vol0001.nii.gz, vol0002.nii.gz and vol0003.nii.gz. Fortunately, the BASH shell uses regular expressions which have a convenient shorthand for specifying wildcard characters in a range of values. In this case, we will want to delete all the files that start with "vol000" followed by the numbers 0 to 3, followed by ".nii.gz". This works out to the following pattern:

vol000[0-3].nii.gz

Now we can put this all together:

BASEFILENAME=f.nii.gz #the file we will drop volumes from
DELETE_TO=3 #we wish to drop the first 4 volumes
#However, since file numbering starts at 0, we stop at 3 (0000,0001,0002,0003) rather than 4
mkdir old #a directory to store the backup out of the way
cp ${BASEFILENAME} old/ #back up the original file just in case
fslsplit ${BASEFILENAME} #break up the original file
rm ${BASEFILENAME} #delete the original file
rm vol000[0-${DELETE_TO}].nii.gz #delete the files corresponding to first 4 volumes
#merge all the remaining vol*.nii.gz files into a single 4D volume
#it will gzip the file, producing f.nii.gz. That's ok if it's gzipped.
fslmerge -t f.nii vol* 
rm vol* #delete all the individual 3D BOLD volumes
#inspect the new f.nii.gz file using fslhd to confirm the header information is what you expect. 
If so, delete the backup
rm -rf old


Remember to account for the dropped volumes when creating your .par files

Setting the TR in the Terminal using fsledithd

Having seen the output from fslhd, the fsl utility, fsledithd, is similar. It uses the linux tool nano as a backend text editor to modify the header information:

fsledithd f.nii

The nano program will open, displaying each of the fields on a line. Pay attention to the dt field in red:

# FSLEDITHD
# This text file contains the header information for an Analyze or Nifti file
# Simply edit this file then save it and the header will be regenerated
# All lines starting with the hash (#) character, like this line, will be ignored
# Ensure that all lines intended to set values take the form: name = 'value' 
# Note that if the file is Analyze then many settings will be ignored
# Further note that the filetype cannot be changed by this program
#   i.e. changing the nifti_type has no effect

<nifti_image
 nifti_type = 'NIFTI-1+'
 image_offset = '352'
 ndim = '4'
 nx = '64'
 ny = '64'
 nz = '29'
 nt = '256'
 dx = '3.3125'
 dy = '3.3125'
 dz = '4.1'
 dt = '1'
 datatype = '16'
 nbyper = '4'
 byteorder = 'LSB_FIRST'
 scl_slope = '1'
 scl_inter = '0'
 xyz_units = '2'
 time_units = '8'
 descrip = 'FSL5.0'
 aux_file = 'none'
 qform_code = '1'
 quatern_b = '0'
 quatern_c = '0'
 quatern_d = '0'
 qoffset_x = '-112.216'
 qoffset_y = '-93.003'
 qoffset_z = '-49.844'
 qfac = '1'
 sform_code = '1'
 sto_xyz_matrix = '3.3125 0 0 -112.216 0 3.3125 0 -93.003 0 0 4.1 -49.844 0 0 0 1'
 num_ext = '0'

# Many fields require codes to be set (e.g. sform_code, qform_code, intent_code)
# Valid values are:
#   sform_code (or qform) :- 0=UNKNOWN, 1=SCANNER_ANAT, 2=ALIGNED_ANAT, 3=TALAIRACH, 4=MNI_152
#   xyz_units :- 1=METER, 2=MM, 3=MICRON 
#   t_units :- 8=SEC, 16=MSEC, 24=USEC, 32=HZ, 40=PPM, 48=RADS
#   intent_code :- 0=NONE, 2=CORRELATION, 3=TTEST, 4=FTEST, 5=ZSCORE, 6=CHISQ, ...
#                  22=PVAL, 23=LOGPVAL, 24=LOG10PVAL, 1001=ESTIMATE, 1002=LABEL (incl masks)
#                  Other codes can be found in the /usr/share/fsl/5.0/src/niftiio/nifti1.h file
/>

The dt field value tells us that the header is reporting a 1-second TR. That's incorrect. It should be 2 (2.047) seconds. Change the value from 1 to 2.047. Then hit ^O (CTRL-O) to write the change, and ^X (CTRL-X) to exit. The header is now modified with the correct TR value.

Setting the TR in the Terminal Using the AFNI tool 3drefit

The AFNI utility, 3drefit can do all sorts of things, including the trivial task of modifying the TR field in your BOLD data when you use the -TR switch:

BASEFILENAME=f.nii.gz #the name of the file to modify
TR_DURATION=2.047 #the duration of the TR
3drefit -TR ${TR_DURATION} ${BASEFILENAME}

Running the above command will produce output like the following:

++ 3drefit: AFNI version=AFNI_2011_12_21_1014 (Jan  8 2015) [64-bit]
++ Authored by: RW Cox
++ Processing AFNI dataset f.nii
 + loading and re-writing dataset f.nii (./f.nii in NIFTI storage)
++ 3drefit processed 1 datasets

File Organization

All FreeSurfer BOLD files for an individual need to have the same name, and be organized in numerically labelled directories. As the example below illustrates, it is not imperative to our usual workflow that these folders be sequentially numbered (e.g., if there is any missing data). By convention, we store the BOLD data in the bold subfolder in the participant's FreeSurfer folder:

  • $SUBJECTS_DIR
    • $SUBJECT_ID
      • bem
      • bold
        • 001
          • f.nii.gz
        • 002
          • f.nii.gz
        • 006
          • f.nii.gz
      • label
      • mri
      • scripts
      • src
      • stats
      • surf
      • tmp
      • touch
      • trash

Handling Multiple Sessions

When data are acquired over multiple sessions, it is likely that the files will be in very different space. If you plan to analyze all the data simultaneously, you will need to ensure that all your BOLD files are coregistered with each other.

Is There a Coregistration Issue?

View a template BOLD file from each of your sessions, with the surfaces overlaid. If the surfaces do not line up with the BOLD data, you will have to force the registration to a BOLD file that does line up with the surfaces:

#inspect the BOLD/SURF registration for one of the preprocessed files (alternately, could check it for the f.nii file)
SUBJID=FS_0217
freeview -v fmcpr.nii.gz -f ${SUBJECTS_DIR}/${SUBJID}/surf/lh.white:edgecolor=green \
${SUBJECTS_DIR}/${SUBJID}/surf/rh.white:edgecolor=green \
-viewport coronal

If there's a problem, it will look something like what is shown in this tutorial

Assume that your 3D surface was generated from the T1 MPRAGE from one of those sessions. Use the template BOLD file that was acquired closest in time to this MPRAGE image. For example, if a participant was in SESS1 and SESS2, and the SESS2 T1 file was used to generate the surfaces, coregister the SESS1 BOLD files to the first run of SESS2 (in the example below, this is run 007):

cd 001
#generate a template BOLD image from f.nii
mri_convert --mid-frame f.nii.gz template.nii.gz

#What is the reference (target) image to align to?
TARGET=${SUBJECTS_DIR}/${SUBJID}/bold/007/template.nii.gz
mri_robust_register --mov template.nii.gz --dst ${TARGET} --lta coregister.lta  --satit

Then apply the lta coregistration file to the BOLD data:

mri_convert -at coregister.lta f.nii.gz f.nii.gz

Repeat for the remaining runs from the session that is out-of-alignment.

IMPORTANT: After you have completed the above steps and the volumes have been roughly aligned, delete all the template.nii.gz files you just created. The preproc-sess command that you will run later on will check whether a template.nii.gz file exists. If this file already exists, the command will skip all kind of important steps that it will infer have already been done!

Highly Accurate Inverse Consistent Registration: A Robust Approach
M. Reuter, H.D. Rosas, B. Fischl.  NeuroImage 53(4):1181-1196, 2010.
http://dx.doi.org/10.1016/j.neuroimage.2010.07.020

Coregister.sh

I've written a shell script that coregisters multisession BOLD data to a reference functional file. A copy of coregister.sh can be found in the ubfs Scripts/Shell/ folder if it is not already in your path (/opt/scripts). It requires that your bold/ directory contains a file called runs that contains the BOLD subdirectories you wish to coregister. The script will coregister the f.nii.gz files in each of the directories with the f.nii.gz file it find in the first listed directory. For example:

Sample runs file
001
002
003
004
005
006

The script takes a list of subjects as a parameter and iterates through all their folders:

sample subjects file (mysubjects.txt)
FS_001
FS_003
FS_011

Then to run the script to coregister the functional runs for these three subjects:

./coregister.sh mysubjects.txt