The process mainly works, but I get bad streamlines here and there. I did use warpcorrect… Is it possible that the origin of the affine transformation is breaking things?
If I read the ANTs command correctly, you are trying to linearly register a b0 to the flair image.
I am not sure why some of your streamlines go haywire but I’d look at the warp first.
Here is what I get for the original warp?.nii.gz:
I guess that WarpImageMultiTransform writes the location of the centre of rotation for locations that are outside the FOV of the translated moving image. Not sure why they do that… This leads to large displacements outside the FOV:
Try this:
for i in {0..2}; do
antsApplyTransforms -d 3 -i identity_warp${i}.nii.gz -o warp_2_${i}.nii.gz -r "$FIXED" -t transforms0GenericAffine.mat;
done
This produces more sensible warps (0 padded):
I am not sure if ANTs has changed but we might need to change the docs for the case that people only apply a linear transformation.
Also, since you are linearly registering the images, you shouldn’t need a warp. I’d try to convert the .mat file to an ITK plain text transformation (ConvertTransformFile) and use transformconvert (ITK) on that.
I think @maxpietsch is probably right, this is most likely related to some of the streamline vertices at the edge of the FOV, where there is no transformation information in the warp. ANTs tends to write zeros in these places, but not always (use the -f option to antsApplyTransforms to force it to use zero). tcknormalise should work OK if these voxels contain NaNs, but doesn’t treat zero any different from any other value (it’s the origin of the coordinate system, after all). The warpcorrect command is a really simple app that simply replaces a triplet of (0,0,0) with (NaN,NaN,NaN) - relying on the fact that the chances of an exact zero position in the warp is very small (not a perfect assumption by any stretch).
In your case however, given that you have used warpcorrect, and yet some vertices are being misplaced, that suggests that those voxels outside the warp field have been assigned non-zero values. It would also explain why these vertices don’t end up at the origin, but somewhere else altogether (although I can’t really tell from your image, they do seem to converge somewhere near the middle of the brain?).
So what I suggest is to use the -f option to antsApplyTransforms, using @maxpietsch’s suggested script modification, but assign very large values to those voxels, e.g. -f 10000 - values that are clearly a long way outside the FOV (unfortunately, it’s not possible to use -f nan, that would solve the problem straight away…). Then, instead of using warpcorrect, just use mrcalc to clean up the transforms:
Rather than mapping to an atlas as most users of tcknormalise do, my streamlines are mapped using an affine to the FLAIR image, but I couldn’t find the equivalent of mrtransform for .tck files. Suppose it wouldn’t be all that hard to write…
I tried the -f 10000 flag, and using mrcalc to transform my warp, and constructed a test set of 3 streamlines using this code:
idx = 0
with open('test_streamline{}.txt'.format(idx), 'w') as fid:
for z in range(-200,200,1):
fid.write('0 0 {}\n'.format(z))
idx += 1
with open('test_streamline{}.txt'.format(idx), 'w') as fid:
for z in range(-200,200,1):
fid.write('0 {} 0\n'.format(z))
idx += 1
with open('test_streamline{}.txt'.format(idx), 'w') as fid:
for z in range(-200,200,1):
fid.write('{} 0 0\n'.format(z))
"""
tckconvert -force test_streamline[].txt test.tck
tckconvert -force test_streamline0.txt test_si.tck
tckconvert -force test_streamline1.txt test_ap.tck
tckconvert -force test_streamline2.txt test_lr.tck
tcknormalise test.tck warp.mif test_flair.tck
tcknormalise test_si.tck warp.mif test_si_flair.tck
tcknormalise test_ap.tck warp.mif test_ap_flair.tck
tcknormalise test_lr.tck warp.mif test_lr_flair.tck
<img src="/uploads/default/original/1X/6b50846943dfff0d88cc31a54736a9b53bbf5797.png" width="605" height="500">
mrview flair.mif -tractography.load test.tck \
-tractography.load test_flair.tck \
-tractography.load test_si_flair.tck \
-tractography.load test_ap_flair.tck \
-tractography.load test_lr_flair.tck
"""
When I load them, the nan regions don’t seem to be mapped correctly as the arrows show. The slanted streamlines go across the entire volume.
Thank you for the nice advice. It is very helpful!
Just one quick question: does the warping method change the fiber tracts number?
I followed @maxpietsch’s instruction, and it seems work nicely. However, I find it does not preserve the original fiber tracts number. The original tracts number is 100000 and the output tracts number is 101134. I use TBSS method to register FA image to MNI152 space. Then I runtcksample: [WARNING] Track file reports 100000 tracks, but contains 101134
for i in {0…2};
do
antsApplyTransforms -d 3 -i WarpMNI152FSL/WarpMNI152FSL-{i}.nii -o MNI152FSL2tck/MNI152FSL2tck-{i}.nii -r "FIXED" -t transforms0GenericAffine.mat -f 123456789
mrcalc MNI152FSL2tck/MNI152FSL2tck-{i}.nii 123456789 -eq nan MNI152FSL2tck/MNI152FSL2tck-${i}.nii
done;
This will be the same issue discussed in this thread.
While we’re working on a more comprehensive solution, the best fix for right now is to ensure that the FoV of your warp field is sufficiently large such that no streamline vertices are outside the warp.