Tckgen with both direction between two ROIs (both being seed and target)

Hi MRtrix team,

I was trying to create streamlines between two ROIs, with no assumptions of direction, so I used both ROIs as seed_image and both ROIs as include images, like below:

Blockquote
tckgen -algorithm iFoD2 -select 5000
-seed_image $sub/fs/ROIs/Left-LGN_dil-1.nii.gz
-include $sub/fs/ROIs/Left-V1_dil-1.nii.gz
-seed_image $sub/fs/ROIs/Left-V1_dil-1.nii.gz
-include $sub/fs/ROIs/Left-LGN_dil-1.nii.gz
-angle 45 -cutoff 0.05 -minlength 20 -maxlength 200
-stop $sub/mrtrix/dwi_wmCsd_autolmax.mif
$sub/mrtrix/LOR2_2.tck -force

but I got very little streamlines,

then I tried with one direction:

Blockquote
tckgen -algorithm iFoD2 -select 5000
-seed_image $sub/fs/ROIs/Left-LGN_dil-1.nii.gz
-include $sub/fs/ROIs/Left-V1_dil-1.nii.gz
-angle 45 -cutoff 0.05 -minlength 20 -maxlength 200
-stop $sub/mrtrix/dwi_wmCsd_autolmax.mif
$sub/mrtrix/LOR2_2.tck -force


with this I got way more streamlines than the first (bidirectional streamlines).

Here I quote what Rob said in another thread(Tractography of optic chiasma):

Blockquote
The green -include ROI is therefore effectively performing an “or” operation: a streamline only needs to traverse one of the two green blobs in order to satisfy all criteria.

  1. with this logic, the first test has two seed ROIs and two include ROIs, shouldn’t it get more streamlines than the latter test, with only one seed and one inclusion?

  2. regarding to my second test, LGN as seed and V1 as -include, why there will be tracts going anterior from LGN? they didn’t reach/include V1.

Thanks!

Mengxing

Hi Mengxing,

… with no assumptions of direction, so I used both ROIs as seed_image and both ROIs as include images, like below:

Generally the way people approach this problem is to do your second example twice; that is, call tckgen once with LGN as seed and V1 as include, and once with V1 as seed and LGN as include. This will give you an equivalent number of streamlines generated traversing in either direction. By doing both within a single execution, the proportion of streamlines in the output file that will have been generated traversing in one direction rather than the other will be … more complex.

Regardless, while the outcome of your first experiment is definitely wrong, I don’t see any reason why it should not behave as you intended, nor can I reproduce the problematic behaviour. So I would probably start with a request to be doubly sure that you can reproduce the behaviour and that what’s being shown is definitely what was generated using the quoted commands. I would also ask that you run tckgen with the -info flag and post here what is produced (tckgen in particular produces additional statistics on the streamlines generation process if -info or -debug are specified).

Here I quote what Rob said in another thread:

That quote is specific to the case where both “blobs” are present within a single binary mask image, as tckgen is agnostic to the fact that there are multiple disconnected components within a mask image; it just wants to know whether a streamline intersects a voxel within the mask or not. Given your first usage explicitly uses the -include option twice, that misunderstanding is not relevant to your case.

with this logic, the first test has two seed ROIs and two include ROIs, shouldn’t it get more streamlines than the latter test, with only one seed and one inclusion?

Ideally in this scenario both examples should produce exactly the same number of streamlines. Both examples request 5000 streamlines. The fact that the first example provides two separate seed images does not change this: the command will continue until the output track file contains 5000 streamlines, and then it stops.

regarding to my second test, LGN as seed and V1 as -include, why there will be tracts going anterior from LGN? they didn’t reach/include V1.

Those streamlines are guaranteed to reach V1. From the streamline seed location, the streamline traverses in one direction, and let’s say that tracking in that direction results in reaching V1. The same streamline will then traverse a second time from the seed location in the opposite direction, and could end up anywhere. If you wish for each streamline to project in a unidirectional fashion from its seed location (which is typically the case if the -stop option is being used), use the -seed_unidirectional option.

Cheers
Rob

Hi Rob,
Thanks for your response!

I re-ran the code, this time without any mask, less confounding. But still there is huge difference between using two seeds/include and one seed/include. Here I posted the stdout, from two methods, as you can see, using two seeds and two include, resulted 48 streamlines, but using one seed and one include, resulted 1066 streamlines.

I uploaded the data I used to Drive(tractsDebug - Google Drive), just in case you want to replicate from your end. BTW, I’m using Ubuntu 20.04 and mrtrix (== mrinfo 3.0_RC3-1085-g4f819e7c ==)

two seeds and two include

Blockquote
mengxing@XPS:~/TESTDATA/local$ tckgen -algorithm iFoD2 -select 5000 -seed_image $sub/fs/ROIs/Left-LGN_dil-1.nii.gz -include $sub/fs/ROIs/Left-V1_dil-1.nii.gz -seed_image $sub/fs/ROIs/Left-V1_dil-1.nii.gz -include $sub/fs/ROIs/Left-LGN_dil-1.nii.gz -angle 45 -cutoff 0.05 -minlength 20 -maxlength 200 -stop $sub/mrtrix/dwi_wmCsd_autolmax_nomask.mif $sub/mrtrix/LOR2_6.tck -force -info -debug
tckgen: [WARNING] existing output files will be overwritten
tckgen: [DEBUG] No config file found at “/etc/mrtrix.conf”
tckgen: [DEBUG] No config file found at “/home/mengxing/.mrtrix.conf”
tckgen: [DEBUG] could not parse spherical ROI specification “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” - assuming mask image
tckgen: [INFO] opening image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] transforms_match: FOV difference in scanner coordinates: 3.9180703910543173e-06
tckgen: [DEBUG] sanitising image information…
tckgen: [INFO] Axes and transform of image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” altered to approximate RAS coordinate system
tckgen: [DEBUG] searching for suitable phase encoding data…
tckgen: [INFO] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” opened with dimensions 256x256x256, voxel spacing 1x1x1, datatype UInt8
tckgen: [DEBUG] loading image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [100%] uncompressing image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” initialised with strides = [ -1 65536 -256 ], start = 65535, using indirect IO
tckgen: [DEBUG] sanitising image information…
tckgen: [DEBUG] allocating scratch buffer for image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” initialised with strides = [ -1 1421 -29 ], start = 1420, using direct IO
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” unloaded
tckgen: [DEBUG] could not parse spherical ROI specification “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” - assuming mask image
tckgen: [INFO] opening image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] transforms_match: FOV difference in scanner coordinates: 3.9180703910543173e-06
tckgen: [DEBUG] sanitising image information…
tckgen: [INFO] Axes and transform of image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” altered to approximate RAS coordinate system
tckgen: [DEBUG] searching for suitable phase encoding data…
tckgen: [INFO] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” opened with dimensions 256x256x256, voxel spacing 1x1x1, datatype UInt8
tckgen: [DEBUG] loading image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [100%] uncompressing image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” initialised with strides = [ -1 65536 -256 ], start = 65535, using indirect IO
tckgen: [DEBUG] sanitising image information…
tckgen: [DEBUG] allocating scratch buffer for image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” initialised with strides = [ -1 156 -12 ], start = 155, using direct IO
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” unloaded
tckgen: [INFO] opening image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] transforms_match: FOV difference in scanner coordinates: 3.9180703910543173e-06
tckgen: [DEBUG] sanitising image information…
tckgen: [INFO] Axes and transform of image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” altered to approximate RAS coordinate system
tckgen: [DEBUG] searching for suitable phase encoding data…
tckgen: [INFO] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” opened with dimensions 256x256x256, voxel spacing 1x1x1, datatype UInt8
tckgen: [DEBUG] loading image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [100%] uncompressing image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” initialised with strides = [ -1 65536 -256 ], start = 65535, using indirect IO
tckgen: [DEBUG] sanitising image information…
tckgen: [DEBUG] allocating scratch buffer for image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” initialised with strides = [ -1 156 -12 ], start = 155, using direct IO
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” unloaded
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [INFO] opening image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] transforms_match: FOV difference in scanner coordinates: 3.9180703910543173e-06
tckgen: [DEBUG] sanitising image information…
tckgen: [INFO] Axes and transform of image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” altered to approximate RAS coordinate system
tckgen: [DEBUG] searching for suitable phase encoding data…
tckgen: [INFO] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” opened with dimensions 256x256x256, voxel spacing 1x1x1, datatype UInt8
tckgen: [DEBUG] loading image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [100%] uncompressing image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” initialised with strides = [ -1 65536 -256 ], start = 65535, using indirect IO
tckgen: [DEBUG] sanitising image information…
tckgen: [DEBUG] allocating scratch buffer for image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” initialised with strides = [ -1 1421 -29 ], start = 1420, using direct IO
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” unloaded
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [INFO] opening image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif”…
tckgen: [DEBUG] reading key/value file “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif”…
tckgen: [DEBUG] sanitising image information…
tckgen: [INFO] image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” opened with dimensions 104x104x72x45, voxel spacing 2.0192299999999999x2.0192299999999999x2x1, datatype Float32LE
tckgen: [DEBUG] memory-mapping file “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif”…
tckgen: [DEBUG] file “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” mapped at 0x7effdba4f000, size 140175360 (read-only)
tckgen: [DEBUG] image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” loaded
tckgen: [DEBUG] image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” initialised with strides = [ 45 4680 486720 1 ], start = 0, using direct IO
tckgen: [INFO] step size = 1.00639975 mm
tckgen: [INFO] maximum angular change in fibre orientation per step = 45 deg
tckgen: [INFO] Minimum radius of curvature = 1.3149246mm
tckgen: [INFO] iFOD2 using 3 vertices per 1.00639975mm step
tckgen: [DEBUG] For tracking step size 1.00639975mm, max change in fibre orientation angle per step 45 deg (using RK4), minimum radius of curvature 1.31492mm, downsampling ratio 3: minimum length of 20mm requires at least 21 vertices pre-DS, is tested explicitly for 23 vertices or less post-DS; maximum length of 200mm will stop tracking after 600 vertices pre-DS, is tested explicitly for 199 or more vertices post-DS
tckgen: [DEBUG] creating empty file “sub18/mrtrix/LOR2_6.tck”
tckgen: [INFO] file “sub18/mrtrix/LOR2_6.tck” already exists - removing
tckgen: [INFO] rejection sampling will use 7 directions with a ratio of 2.15373945 (predicted number of samples per step = 12.9595909)
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “source”…
tckgen: [DEBUG] launching thread “sink”…
tckgen: [DEBUG] waiting for completion of threads “source”…
tckgen: [ 0%] 206451 seeds, 186301 streamlines, 1 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.254864097, max_val = 0.248964176)
tckgen: [ 0%] 505111 seeds, 455417 streamlines, 6 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.333255559, max_val = 0.30005464)
tckgen: [ 0%] 552601 seeds, 498258 streamlines, 7 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.308890939, max_val = 0.302813679)
tckgen: [ 0%] 673091 seeds, 606888 streamlines, 8 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.270945519, max_val = 0.270853788)
tckgen: [ 0%] 739021 seeds, 666269 streamlines, 9 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.262706727, max_val = 0.257611394)
tckgen: [ 0%] 830971 seeds, 749100 streamlines, 9 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.25940609, max_val = 0.255449086)
tckgen: [ 0%] 870341 seeds, 784524 streamlines, 9 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.258471906, max_val = 0.253768772)
tckgen: [ 0%] 927401 seeds, 835919 streamlines, 9 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.276347458, max_val = 0.271248609)
tckgen: [ 0%] 1113501 seeds, 1003852 streamlines, 12 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.256636232, max_val = 0.249747723)
tckgen: [ 0%] 1157301 seeds, 1043293 streamlines, 12 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.269458801, max_val = 0.262298465)
tckgen: [ 0%] 1716851 seeds, 1547681 streamlines, 23 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.297974795, max_val = 0.255817831)
tckgen: [ 0%] 1784351 seeds, 1608599 streamlines, 23 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.254709512, max_val = 0.252438724)
tckgen: [ 0%] 1837321 seeds, 1656291 streamlines, 23 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.296893001, max_val = 0.268821955)
tckgen: [ 0%] 1925661 seeds, 1735834 streamlines, 23 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.259857923, max_val = 0.258106768)
tckgen: [ 0%] 2264341 seeds, 2041196 streamlines, 27 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.321649313, max_val = 0.269435883)
tckgen: [ 0%] 2326491 seeds, 2097355 streamlines, 28 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.25367263, max_val = 0.25314182)
tckgen: [ 0%] 2472071 seeds, 2228619 streamlines, 30 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.245968476, max_val = 0.236088097)
tckgen: [ 0%] 2568901 seeds, 2315777 streamlines, 31 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.384820193, max_val = 0.345347673)
tckgen: [ 0%] 2661521 seeds, 2399278 streamlines, 31 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.354164332, max_val = 0.329433918)
tckgen: [ 0%] 2689541 seeds, 2424574 streamlines, 32 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.271914095, max_val = 0.258854926)
tckgen: [ 0%] 3088931 seeds, 2784826 streamlines, 34 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.295394003, max_val = 0.282667488)
tckgen: [ 0%] 3101441 seeds, 2796117 streamlines, 34 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.300877005, max_val = 0.29560855)
tckgen: [ 0%] 3769911 seeds, 3398829 streamlines, 39 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.236867711, max_val = 0.234286204)
tckgen: [ 0%] 4097771 seeds, 3694617 streamlines, 42 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.274844617, max_val = 0.261607111)
tckgen: [ 0%] 4392251 seeds, 3960088 streamlines, 43 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.262892336, max_val = 0.240138605)
tckgen: [ 0%] 4482191 seeds, 4041208 streamlines, 45 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.307391167, max_val = 0.267150313)
tckgen: [ 0%] 4495311 seeds, 4053016 streamlines, 45 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.252346843, max_val = 0.247654289)
tckgen: [ 0%] 4809341 seeds, 4335861 streamlines, 47 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.256309599, max_val = 0.244871408)
tckgen: [ 0%] 4993941 seeds, 4502074 streamlines, 48 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.276931375, max_val = 0.274493754)
tckgen: [ 0%] 4999871 seeds, 4507435 streamlines, 48 selected
tckgen: [DEBUG] no readers left on queue “source->sink”
tckgen: [DEBUG] no writers left on queue “source->sink”
tckgen: [DEBUG] threads “source” completed OK
tckgen: [DEBUG] waiting for completion of thread “sink”…
tckgen: [DEBUG] thread “sink” completed OK
tckgen: [100%] 5000000 seeds, 4507546 streamlines, 48 selected
tckgen: [INFO] mean number of samples per step = -nan
tckgen: [INFO] mean number of steps between rejection sampling truncations = -nan
tckgen: [INFO] maximum truncation error = 1.1937879323959351
tckgen: [INFO] Total number of track terminations: 9015260
tckgen: [INFO] Termination reason probabilities:
tckgen: [INFO] Calibrator sub-threshold: 100%
tckgen: [INFO] Exited image: 0%
tckgen: [INFO] Diffusion model sub-threshold: 0.0131%
tckgen: [INFO] Excessive curvature: 0%
tckgen: [INFO] Max length exceeded: 0.00205%
tckgen: [INFO] Traversed all include regions: 0.000821%
tckgen: [INFO] Track rejection counts:
tckgen: [INFO] Invalid seed point: 492460
tckgen: [INFO] No propagation from seed: 140135
tckgen: [INFO] Shorter than minimum length: 1227257
tckgen: [INFO] Missed inclusion region: 3140190
tckgen: [DEBUG] unmapping file “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif”
tckgen: [DEBUG] image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” unloaded
tckgen: [DEBUG] deleting scratch buffer for image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” unloaded
tckgen: [DEBUG] deleting scratch buffer for image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” unloaded
tckgen: [DEBUG] deleting scratch buffer for image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” unloaded
tckgen: [DEBUG] deleting scratch buffer for image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” unloaded

one seed and one include

Blockquote
mengxing@XPS:~/TESTDATA/local$ tckgen -algorithm iFoD2 -select 5000 -seed_image $sub/fs/ROIs/Left-LGN_dil-1.nii.gz -include $sub/fs/ROIs/Left-V1_dil-1.nii.gz -angle 45 -cutoff 0.05 -minlength 20 -maxlength 200 -stop $sub/mrtrix/dwi_wmCsd_autolmax_nomask.mif $sub/mrtrix/LOR2_7.tck -force -debug
tckgen: [WARNING] existing output files will be overwritten
tckgen: [DEBUG] No config file found at “/etc/mrtrix.conf”
tckgen: [DEBUG] No config file found at “/home/mengxing/.mrtrix.conf”
tckgen: [DEBUG] could not parse spherical ROI specification “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” - assuming mask image
tckgen: [INFO] opening image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] transforms_match: FOV difference in scanner coordinates: 3.9180703910543173e-06
tckgen: [DEBUG] sanitising image information…
tckgen: [INFO] Axes and transform of image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” altered to approximate RAS coordinate system
tckgen: [DEBUG] searching for suitable phase encoding data…
tckgen: [INFO] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” opened with dimensions 256x256x256, voxel spacing 1x1x1, datatype UInt8
tckgen: [DEBUG] loading image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [100%] uncompressing image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” initialised with strides = [ -1 65536 -256 ], start = 65535, using indirect IO
tckgen: [DEBUG] sanitising image information…
tckgen: [DEBUG] allocating scratch buffer for image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” initialised with strides = [ -1 1421 -29 ], start = 1420, using direct IO
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” unloaded
tckgen: [INFO] opening image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] transforms_match: FOV difference in scanner coordinates: 3.9180703910543173e-06
tckgen: [DEBUG] sanitising image information…
tckgen: [INFO] Axes and transform of image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” altered to approximate RAS coordinate system
tckgen: [DEBUG] searching for suitable phase encoding data…
tckgen: [INFO] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” opened with dimensions 256x256x256, voxel spacing 1x1x1, datatype UInt8
tckgen: [DEBUG] loading image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [100%] uncompressing image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” initialised with strides = [ -1 65536 -256 ], start = 65535, using indirect IO
tckgen: [DEBUG] sanitising image information…
tckgen: [DEBUG] allocating scratch buffer for image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” loaded
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” initialised with strides = [ -1 156 -12 ], start = 155, using direct IO
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” unloaded
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “loop threads”…
tckgen: [DEBUG] waiting for completion of threads “loop threads”…
tckgen: [DEBUG] threads “loop threads” completed OK
tckgen: [INFO] opening image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif”…
tckgen: [DEBUG] reading key/value file “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif”…
tckgen: [DEBUG] sanitising image information…
tckgen: [INFO] image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” opened with dimensions 104x104x72x45, voxel spacing 2.0192299999999999x2.0192299999999999x2x1, datatype Float32LE
tckgen: [DEBUG] memory-mapping file “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif”…
tckgen: [DEBUG] file “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” mapped at 0x7fa3e3a4f000, size 140175360 (read-only)
tckgen: [DEBUG] image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” loaded
tckgen: [DEBUG] image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” initialised with strides = [ 45 4680 486720 1 ], start = 0, using direct IO
tckgen: [INFO] step size = 1.00639975 mm
tckgen: [INFO] maximum angular change in fibre orientation per step = 45 deg
tckgen: [INFO] Minimum radius of curvature = 1.3149246mm
tckgen: [INFO] iFOD2 using 3 vertices per 1.00639975mm step
tckgen: [DEBUG] For tracking step size 1.00639975mm, max change in fibre orientation angle per step 45 deg (using RK4), minimum radius of curvature 1.31492mm, downsampling ratio 3: minimum length of 20mm requires at least 21 vertices pre-DS, is tested explicitly for 23 vertices or less post-DS; maximum length of 200mm will stop tracking after 600 vertices pre-DS, is tested explicitly for 199 or more vertices post-DS
tckgen: [DEBUG] creating empty file “sub18/mrtrix/LOR2_7.tck”
tckgen: [INFO] file “sub18/mrtrix/LOR2_7.tck” already exists - removing
tckgen: [INFO] rejection sampling will use 7 directions with a ratio of 2.15373945 (predicted number of samples per step = 12.9595909)
tckgen: [DEBUG] initialising threads…
tckgen: [DEBUG] launching 8 threads “source”…
tckgen: [DEBUG] launching thread “sink”…
tckgen: [DEBUG] waiting for completion of threads “source”…
tckgen: [ 1%] 396841 seeds, 396841 streamlines, 82 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.236962944, max_val = 0.233543977)
tckgen: [ 2%] 593511 seeds, 593511 streamlines, 115 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.312178135, max_val = 0.293956578)
tckgen: [ 3%] 1017881 seeds, 1017881 streamlines, 193 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.287869751, max_val = 0.233815059)
tckgen: [ 5%] 1481771 seeds, 1481771 streamlines, 291 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.258409858, max_val = 0.244873852)
tckgen: [ 16%] 3784061 seeds, 3784061 streamlines, 802 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.264128089, max_val = 0.255487531)
tckgen: [ 16%] 3803251 seeds, 3803251 streamlines, 804 selected
tckgen: [DEBUG] max_val exceeded!!! (val = 0.275974691, max_val = 0.262473255)
tckgen: [ 21%] 4999981 seeds, 4999981 streamlines, 1066 selected
tckgen: [DEBUG] no readers left on queue “source->sink”
tckgen: [DEBUG] no writers left on queue “source->sink”
tckgen: [DEBUG] threads “source” completed OK
tckgen: [DEBUG] waiting for completion of thread “sink”…
tckgen: [DEBUG] thread “sink” completed OK
tckgen: [WARNING] less than desired streamline number due to implicit maximum number of seeds; set -seeds 0 to override
tckgen: [100%] 5000000 seeds, 5000000 streamlines, 1066 selected
tckgen: [INFO] mean number of samples per step = -nan
tckgen: [INFO] mean number of steps between rejection sampling truncations = -nan
tckgen: [INFO] maximum truncation error = 1.2311856746673584
tckgen: [INFO] Total number of track terminations: 10000180
tckgen: [INFO] Termination reason probabilities:
tckgen: [INFO] Calibrator sub-threshold: 99.9%
tckgen: [INFO] Exited image: 0%
tckgen: [INFO] Diffusion model sub-threshold: 0.0116%
tckgen: [INFO] Excessive curvature: 0%
tckgen: [INFO] Max length exceeded: 0.0465%
tckgen: [INFO] Traversed all include regions: 0.016%
tckgen: [INFO] Track rejection counts:
tckgen: [INFO] Invalid seed point: 0
tckgen: [INFO] No propagation from seed: 13139
tckgen: [INFO] Shorter than minimum length: 85785
tckgen: [INFO] Missed inclusion region: 4900100
tckgen: [DEBUG] unmapping file “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif”
tckgen: [DEBUG] image “sub18/mrtrix/dwi_wmCsd_autolmax_nomask.mif” unloaded
tckgen: [DEBUG] deleting scratch buffer for image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-LGN_dil-1.nii.gz” unloaded
tckgen: [DEBUG] deleting scratch buffer for image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz”…
tckgen: [DEBUG] image “sub18/fs/ROIs/Left-V1_dil-1.nii.gz” unloaded

Hi @rsmith Rob, sorry to spam. I’d really appreciate it if you could take a look at my last post. Many thanks!

best,
Mengxing

Just editing your debugging printouts to remove the unrelated information:

two seeds and two include

mengxing@XPS:~/TESTDATA/local$ tckgen -algorithm iFoD2 -select 5000 -seed_image $sub/fs/ROIs/Left-LGN_dil-1.nii.gz -include $sub/fs/ROIs/Left-V1_dil-1.nii.gz -seed_image $sub/fs/ROIs/Left-V1_dil-1.nii.gz -include $sub/fs/ROIs/Left-LGN_dil-1.nii.gz -angle 45 -cutoff 0.05 -minlength 20 -maxlength 200 -stop $sub/mrtrix/dwi_wmCsd_autolmax_nomask.mif $sub/mrtrix/LOR2_6.tck -force -info -debug
tckgen: [100%]  5000000 seeds,  4507546 streamlines,       48 selected
tckgen: [INFO] mean number of samples per step = -nan
tckgen: [INFO] mean number of steps between rejection sampling truncations = -nan
tckgen: [INFO] maximum truncation error = 1.1937879323959351
tckgen: [INFO] Total number of track terminations: 9015260
tckgen: [INFO] Termination reason probabilities:
tckgen: [INFO]   Calibrator sub-threshold: 100%
tckgen: [INFO]   Exited image: 0%
tckgen: [INFO]   Diffusion model sub-threshold: 0.0131%
tckgen: [INFO]   Excessive curvature: 0%
tckgen: [INFO]   Max length exceeded: 0.00205%
tckgen: [INFO]   Traversed all include regions: 0.000821%
tckgen: [INFO] Track rejection counts:
tckgen: [INFO]   Invalid seed point: 492460
tckgen: [INFO]   No propagation from seed: 140135
tckgen: [INFO]   Shorter than minimum length: 1227257
tckgen: [INFO]   Missed inclusion region: 3140190

one seed and one include

mengxing@XPS:~/TESTDATA/local$ tckgen -algorithm iFoD2 -select 5000 -seed_image $sub/fs/ROIs/Left-LGN_dil-1.nii.gz -include $sub/fs/ROIs/Left-V1_dil-1.nii.gz -angle 45 -cutoff 0.05 -minlength 20 -maxlength 200 -stop $sub/mrtrix/dwi_wmCsd_autolmax_nomask.mif $sub/mrtrix/LOR2_7.tck -force -debug
tckgen: [WARNING] less than desired streamline number due to implicit maximum number of seeds; set -seeds 0 to override
tckgen: [100%]  5000000 seeds,  5000000 streamlines,     1066 selected
tckgen: [INFO] mean number of samples per step = -nan
tckgen: [INFO] mean number of steps between rejection sampling truncations = -nan
tckgen: [INFO] maximum truncation error = 1.2311856746673584
tckgen: [INFO] Total number of track terminations: 10000180
tckgen: [INFO] Termination reason probabilities:
tckgen: [INFO]   Calibrator sub-threshold: 99.9%
tckgen: [INFO]   Exited image: 0%
tckgen: [INFO]   Diffusion model sub-threshold: 0.0116%
tckgen: [INFO]   Excessive curvature: 0%
tckgen: [INFO]   Max length exceeded: 0.0465%
tckgen: [INFO]   Traversed all include regions: 0.016%
tckgen: [INFO] Track rejection counts:
tckgen: [INFO]   Invalid seed point: 0
tckgen: [INFO]   No propagation from seed: 13139
tckgen: [INFO]   Shorter than minimum length: 85785
tckgen: [INFO]   Missed inclusion region: 4900100

There’s definitely differences between the two; but I’ll need to go in and experiment with the data itself to try to figure out what’s going on.

Rob

Mengxing,

Thanks for sharing the data. I think the following should probably explain the effect (and admittedly I probably should have realised what was going on here straight away), but let me know if there are still outstanding concerns.

For any particular tracking experiment, we can quantify from the results of the experiment the percentage of streamlines generated that satisfy all applicable criteria and are therefore written to the output track file. For whole-brain fibre-tracking this percentage is typically reasonably high, whereas if you have multiple tiny inclusion regions a long way away from one another and lots of exclusion regions the percentage would be very small.

Using your data I’ve quantified this for three different experiments:

  1. Seeding in V1, tracking to LGN: 0.00004%
  2. Seeding in LGN, tracking to V1: 0.02%
  3. Seeding in both V1 and LGN, must intersect both V1 and LGN: 0.001%

Let’s first deal with 1 and 2.

Ideally, streamlines tractography should behave relatively independently of direction, i.e. tracking from A to B should result in comparable streamlines to tracking from B to A. But what’s missing from that narrative is the relative volumes of the two ROIs. In the case of your data, V1 contains about 25 times more voxels than LGN. As such, even if the streamlines algorithm is direction-agnostic, a streamline seeded in the LGN is much more likely to reach V1 than is a streamline seeded in V1 to reach LGN. To take this idea to the extreme, imaging seeding in one WM voxel and seeing how many streamlines reach the cortex, versus seeding over the whole cortex and seeing how many streamlines intersect that one WM voxel.

Also bear in mind here that the reason why this is the result you get is because of the effect described by this warning that should have been issued:

tckgen: [WARNING] less than desired streamline number due to implicit maximum number of seeds; set -seeds 0 to override

While you have explicitly requested for a fixed number of streamlines in your output track file via the -select option, from this there is implicitly set a maximum number of permissible attempts at generating streamlines, at which point the command will terminate prematurely (in order to mitigate the scenario where the command runs indefinitely). If you were to additionally set -seeds 0 (disabling this implicit limit), then you would end up with the same number of streamlines in the two output files; the difference would be that case 1 would take a lot longer to produce that number of accepted streamlines than would case 2, since a smaller proportion of generated streamlines would satisfy the criteria you put in place.

Now let’s deal with case 3. On first inspection, you might predict that when seeding from both ROIs simultaneously, the percentage of successful streamlines will be around the average of experiments 1 and 2; but you can see from the results of my experiment that this is not the case. The reason for this is again the difference in volume of the two ROIs. When you provide multiple seeds to tckgen in a single invocation, the location of each streamline seed point is not drawn from those seed sources with equal probability. Instead, the effective volume of each seed is calculated, with more seeds being drawn in larger seeding sources in direct proportion to the relative volumes; so the behaviour is akin to all sources of streamline seeds being agglomerated together into a single source of streamline seeds. So when you do bidirectional tracking, nevertheless in this case the vast majority of streamline seeds will be placed in V1.

(It is actually possible to fudge the numbers so that an approximately equal number of streamline seeds are drawn from each input seed image; but I’ll refrain from adding yet another layer of complexity unless required)

Hope that makes sense
Rob