Rotating bvecs for DTI fitting

Update: While these methods continue to be useful, I now recommend using TORTOISE for preprocessing DTI.  The TORTOISE pipeline includes methods for (among other things) reducing distortions from EPI artifacts, eddy current correction, correcting for motion, rotating b-vecs, and co-registration to an anatomical image.  There are instructions for using the newest version here.  

Most people agree that it’s important to perform some type of motion correction or eddy correction before fitting tensors for DTI data.  However, it’s not always clear that you need to rotate the bvecs in response to the motion correction.  In fact, rotating the bvecs is highly recommended (link).  I’ve searched the internet and found a few different opinions on how to rotate the gradient vectors.  Some posts suggest that you don’t really need to rotate because the difference is usually small.  One post on the FSL mailing (link) list suggest that you should perform a 6 degrees of freedom (dof) transform to the b0 image and rotate your bvecs in relation to that transform before doing a 12 dof transform to deal with the other distortions.  I found a an older post on the AFNI message board (link) that details one method of rotating the bvecs.  In my tests, this method works fairly well with DWI data will relatively little motion.

I decided to rewrite the script from the AFNI Message Board in Bash (instead of tcsh).  So if you’re looking to do this rotation inside of the AFNI pipeline that I’ve detailed in the past posts (one, two), you can use the following script to rotate your bvec files after running the alignment via align_epi_anat.py.  I assume that your bvec.1D file is organized as three columns; if this is not the case, you should use 1dtranspose to rotate your bvec file (this is usually the case if you used dcm2nii to convert your DICOMs).

#!/bin/bash

#Usage: sh rotate_bvecs.sh bvec.1D dwi_al_reg_mat.aff12.1D

echo "bvec: $1"
echo "matrix: $2" 

nRows=`cat $2 | wc -l`
nRows=$(expr $nRows - 1)
echo "Number of Gradient Vectors: $nRows"

for aRow in `count -digits 3 0 $nRows`
do
 echo $aRow
 #separate bvecs
 1dcat $1{$aRow} > tmp.bvecs.${aRow} 
 #separate matrix
 1dcat $2{$aRow} > tmp.transform.${aRow} 
 #change to matrix from ONELINE
 cat_matvec tmp.transform.${aRow} > tmp.transform.mat.${aRow} 
 #get rid of translational shifts
 1dcat tmp.transform.mat.${aRow}[0..2] > tmp.transform.mat.s.${aRow}
 echo "0 0 0" > tmp.zero_fill.1D
 1dcat tmp.transform.mat.s.${aRow} tmp.zero_fill.1D\' > tmp.transform.final.${aRow}
 Vecwarp -matvec tmp.transform.final.${aRow} -input tmp.bvecs.${aRow} -forward >> bvec_rotated.1D
done

rm tmp.*

This script takes two arguments, the bvec and the “reg” matrix from align_epi_anat.py (DTI –> Anat transform).  It will separate the bvec and registration matrices into “line” per sub-brik, convert the one-line transform to a matrix, trim out the translational part of the matrix (by filling in 0’s), and then use Vecwarp to apply the matrix to the bvec and output a bvec_rotated.1D that can be used in 3dDWItoDT.

Comments are closed.