Thanks for providing some data. It didn’t take too long for me to twig as to what’s going on, and in retrospect I probably should have figured it out without requiring any data…
What’s happening here is a combination of two effects, which are themselves due to different design decisions, so you’ll have to bear with me…
When streamlines are tested against a set of ROIs, both in
tckedit, it is simply the set of streamline vertices that are used to sample values from the underlying binary images (without interpolation). So it is possible for a streamline to “cross” the corner of a voxel that is within the ROI, but for none of the discrete vertex samples to lie within that voxel, such that the streamline is not considered to “intersect” that ROI.
Some behaviours that are specific to iFOD2, and some that are most relevant to iFOD2:
While the reported “step size” is by default half a voxel, the default “number of samples” is 4. What this actually represents is that each “step” is in fact an arc through space, with vertices at the start, end, and 2 in the middle of that arced trajectory. The FOD amplitudes at the tangents to this arc at those four points are what is used to calculate the probability of following each generated candidate trajectory.
When I incorporated ACT into MRtrix3, I decided to keep the intermediate points along each arc, rather than using only the two endpoints that are separated by the “step size”. This provides a more dense sampling of the underlying 5TT image: The default step size would commonly be larger than the voxel size of this image, so taking values from that image only at the “step size” of the tracking algorithm could lead to jumping over tissue contrast.
This however led to larger track files, which some people did not like. Accordingly, I implemented downsampling within
tckgen: Once a streamline has been fully generated using some step size, the command may then reduce the number of vertices it writes to the output file.
This downsampling algorithm always preserves the seed point and both endpoints, regardless of the extent to which you downsample; which also means that the distance from a streamline endpoint to the next vertex is not guaranteed to be the step size, which needs to be accounted for in streamline length calculations.
You may notice in the output of
tckinfo that track files contain both the “
step_size” and “
output_step_size” fields. The former is the step size utilised by the tracking algorithm; the latter is the product of the step size and the downsampling factor, as an approximation of the distance between vertices as the data are stored within the file. Any calculations in MRtrix3 involving streamline length use the latter when available, as it’s more reflective of the data within the file.
By default, the downsampling factor for iFOD2 is set to
(nsamples - 1); that is, for the default of 4 samples per step (1 start, 1 end, and 2 in between for each arc),
tckgen will downsample the streamline by a factor of 3; by doing so, the output track file will contain only the streamline vertices at the start and end of each “step”, and not the two in the middle of each “step”.
The reason that
tckedit is not selecting all of the streamlines that you produced with
tckgen, despite using exactly the same ROIs, is that
tckedit is using a less densely sampled representation of the streamline than what was used during
I can prove this in two ways:
If I first run
tckresample on the streamlines, up-sampling the representation by a factor of 3, then run
tckedit, it selects 493 out of the 500 streamlines, rather than 443/500 when not using
If I disable down-sampling during
tckgen by using
-downsample 1 (unfortunately this won’t work for you currently, I need to fix some code there), then run
tckedit, it selects all 500 streamlines.
I suppose this then raises the question: How should streamlines be assigned to ROIs?
In the past we’ve debated about whether linear or nearest-neighbour interpolation should be used, which affects the shape of the outer boundary defining the region in which streamlines vertices should or should not be assigned to the ROI. But what you’ve drawn attention to here is a slightly different issue, as it involves not only the shape of that “inclusion region”, but also how densely each streamline is sampled.
In other contexts (e.g.
tcksample -precise), MRtrix3 uses the method shown in Appendix 3 of this paper, which detects the voxel edges traversed by each streamline based on a continuous spline representation of such. So this attempts to catch any voxels where the streamline just intersects it for a very short segment length, and is therefore (or at least it’s intended to be) less dependent on the density of vertex samples along each streamline when assigning them to a voxel grid. It however requires greater computation than simply sampling an image underneath each streamline vertex.
tckedit benefit from having this more “precise” mapping of streamlines to voxel ROIs? Open to thoughts on the issue.