Tract lengths

Hi all,

I’ve run into trouble with tract length again. You recently added an -explicit flag to tckstats in order to ensure the correct evaluation of length from a transformed tck file (since the step size information in the header is not useful any more)

My issue is now regarding using tckedit to extract specific lengths from these (transformed) files. I assume that this feature still uses the step size information.

What I thought was to resample the transformed tck file to the step size in the header and then do the extraction of tracts. Problem is that if I run tckstats on the transformed .tck files (before resampling the step size) using the explicit flag, I get a different result, to when I run tckstats after the step size resampling. Incidentally, I get an identical result with or without the -explicit flag on the resampled file.

I suspect that this issue may be due to the interpolation in the resampling but thought I’d check with you guys…

Claude

Hi Claude,

Thanks for raising. I do believe that tckedit will make use of the step size information to calculate the length of the streamline (excluding the first and last segments), and so may misbehave with nonlinearly-transformed data.

You can track the relevant developers discussion on GitHub here.

Rob

Thanks @rsmith that’s what I thought. Would my fix make sense? I.e. resampling the step size before doing the editing?

Problem is that if I run tckstats on the transformed .tck files (before resampling the step size) using the explicit flag, I get a different result, to when I run tckstats after the step size resampling.

On reading your post more closely, this is indeed unexpected. I’d expect them to be slightly different, since quantifying streamline length via inter-vertex distances is never perfectly accurate, and the latter involves explicitly determining new streamline vertex locations whereas the former just calculates distances between the transformed vertices, but I wouldn’t expect the differences to be very large in magnitude.

Incidentally, I get an identical result with or without the -explicit flag on the resampled file.

Basically that means that tckresample -step_size is operating as it should: the inter-vertex distances (for all but the first and last streamline segments) are all fixed, and hence it is safe to assume this when calculating total streamline length without the -explicit flag.

Would my fix make sense? I.e. resampling the step size before doing the editing?

Yes, assuming everything is operating as it should, i.e. the magnitude of the difference between tckstats -explicit and tckresample -step_size | tckstats is small.

Hi @rsmith

I’ve re-tested this and this is the output that I get. Unless I am missing something obvious, there may be some bug in the resampling.

The resampling command that I used was:

tckresample example-1-standard.tck -step_size 0.125 example-1-standard-resampled.tck

My output is:

Note that the visualisations for example-1-standard.tck and for example-1-standard-resampled.tck are identicle.

Claude

  • tckstats example-1-standard.tck: We expect this to be erroneously close to example-1.tck, since the non-linear transformations of all but the start and endpoints of each streamline are not being properly taken into account.

  • tckstats example-1-standard.tck -explicit: This is actually the result that looks erroneous to me, not the resampling. The mean / min / max are all decreased, and the standard deviation is very much decreased. So I think this is where the main error is (see below)

  • tckstats example-1-standard-resampled.tck: I expect these to be close-but-not-identical to tckstats example-1.tck, since the streamlines have in fact been non-linearly transformed, but no humongous differences are expected. This is I think what we see in the raw numbers.

  • tckstats example-1-standard-resampled.tck -explicit: This is expected to be almost identical to tckstats example-1-standard-resampled.tck, within floating-point precision. The difference is a little greater than that, which I think I now know why (see below).

So, the issue with both points 2 and 4 is that when I introduced the -explicit option in tckstats, I achieved it by calling a pre-existing function for calculating the length of a streamline when the step size is not known. However back when that function was written it was based on the premise that the step size of the streamline is unknown, but is nevertheless constant (for all but the first and last segment of each streamline). This means that if the distance between streamline vertices is not consistent along its entire length, the streamline length calculation using this function is going to be erroneous (specifically, it gets the distance between the two most central points on the streamline, and then assumes that that distance is accurate for all other non-endpoint segments; for a nonlinearly-warped streamline this will not be the case).

Unfortunately this is a major stuff-up on my part, and is definitely going to require re-checking your results (the lengths following resampling should be trustworthy). With trying to keep up with demand I don’t get to test everything as thoroughly as would be ideal; heck I only get to answer forum questions on Sundays. I’ll also push a fix to the master branch so hopefully nobody else will get caught out.

Pleading for forgiveness :pray:
Rob

Thanks for the reply @rsmith, I will recheck all my results where I’ve used tckstats with the -explicit flag.

Also, I was reading your got change log and you had mentioned that there are potential issues with tckstats with downsampled tracts but this should not affect iFOD2 default downsampled. Did I understand correctly?

Finally, a thought / feature request for future releases. Would it be powerful to either:

  1. resampled step size automatically after using tcktranform (this will avoid most issues with editing transformation tracts using a length rule)
    Or
  2. remove the step size from the header after tcktranform to ensure that users cannot use this information when calculating length.

… you had mentioned that there are potential issues with tckstats with downsampled tracts …

If you’re referring to the comment here, my point there was more about the downsampling that occurs within tckgen, but it does apply to downsampling in general.

I’m not yet totally solved on how best to handle this, so I’ll describe what’s going on as best I can here in case anyone has input / writing it out in full makes my mind up.

Imagine that one possessed a method to accurately quantify the length of each streamline based on a continuous spline representation. In this case, as long as the number of discrete sampled vertices along the spline is “sufficient” (e.g. Nyquist criterion), the quantification of length should be relatively stable regardless of the actual number of vertices.

However when one calculates length based on a discrete vertex representation, whether summing the distances between vertices or taking the product of the number of vertices and the known fixed step size, the quantified length will always be shorter than the length of the continuous spline, due to using chordal lengths of curved trajectories. The fewer vertices there are, the greater the magnitude of the under-estimate.

… but this should not affect iFOD2 default downsampled. Did I understand correctly?

The reason this is not an issue for iFOD2 (specifically under default usage) is due to the internal mathematics and mechanisms of iFOD2 and the default parameters.

With default parameters, for each “step”, iFOD2 generates one new vertex at precisely (0.5 x voxel_size) distance from the current point, as well as 2 “intermediate” vertices between the current and target vertices along an arc of fixed radius of curvature. The probabilities of candidate trajectories during probabilistic streamlines tractography are calculated based on the amplitudes of the FODs at the positions and tangents defined by these four points (current point, target vertex, and two “intermediate” points). As the streamline is propagated, streamline vertices are generated at all points (including the intermediate ones), principally to ensure that any underlying ACT 5TT image or ROIs are sampled adequately densely (don’t want streamlines to “jump over” features). However by default a downsampling factor of 3 is used, which then results in all of the “intermediate” points being discarded before writing the streamline to disk.

Because the distance between the vertices at the start & end of each arc is exactly (0.5 x voxel_size), the distance between each vertex taking into account the intermediate points is in fact going to be a bit more than (1/6 x voxel_size) for anything other than a perfectly straight trajectory. However following the default downsampling, the distance between vertices will be exactly (0.5 x voxel_size).

Compare this to an alternative example: iFOD1, where the default step size is (0.1 x voxel_size), and let’s say that we use a downsampling factor of 5. Following downsampling, the distances between vertices will be less than or equal to (0.5 x voxel_size), with the magnitude of the error dependent on the radius of curvature.

For this reason, in the next tag update I’m removing all reference to calculation of streamlines lengths based on knowledge of step size.

As a slight aside: one could approximate this spline length by upsampling to a very high density of vertices along the spline before calculating the lengths. This is in fact essentially already done with tckmap -precise, tcksift, tcksift2. An issue I have is that tckgen needs to be able to apply criteria to streamlines lengths, and ideally its behaviour should be identical to applying such length criteria in e.g. tckedit, but it may be undesirable to introduce such computational demand to tckgen. I suppose I may be able to instead perform the more expensive calculation of length only if the streamline appears to be close to one of the length thresholds?

resampled step size automatically after using tcktranform (this will avoid most issues with editing transformation tracts using a length rule)

While that could be done, resampling to a fixed step size would likely be considerably slower than tcktransform itself. I would personally prefer to support piping of streamlines data so that one could run tcktransform in.tck - | tckresample - out.tck if desired. The code update linked above will prevent MRtrix3 from calculating lengths based on step size knowledge, so this will no longer be necessary in order for MRtrix3’s calculations to be accurate; the question is whether adding documentation regarding the calculation of streamlines lengths is sufficient to prevent users from making the same mistake if they choose to perform such calculations themselves manually.

remove the step size from the header after tcktranform to ensure that users cannot use this information when calculating length.

It would certainly make sense to remove (or better, invalidate) the “output_step_size” field, which, following introduction of the downsampling capability in tckgen, has been used to indicate the expected distance between vertices in the output file, as opposed to the “step size” used by the tractography algorithm. However it would be preferable to retain the latter, as it would make sense to retain this information along with all other tractography parameters.

An issue here is that when I first implemented this, there were a lot of .tck files floating around that simply didn’t contain the “output_step_size” field; in which case I would revert to using “step_size”. This in its current form would therefore perform calculations based on the “tracking” step size if the “output” step size were omitted / invalid, conflicting with the previous paragraph.

So I agree that invalidating “output_step_size” in tcktransform would be preferable, but don’t think that “step_size” should also be removed. “output_step_size” should additionally be used as a rough guide only, rather than for calculations that require precision (I think that after the update the only place that MRtrix3 code will use it will be in the determination of bin widths in a streamline length histogram).

Hi @rsmith,

I have finally had some time to test the new code for tckstats just to ensure that it is working correctly for the test on my actual data!

I thought I’d post the results for anyone who’s interested.

These recrated (with different data) the problem using tckstats version 3.0_RC3-51-g52a (pre-fix):

These recrated (with different data) the problem using tckstats version 3.0_RC3-135-g2b (post-fix):

Note that when I resampled the .tck file (as described in my earlier post). I get almost the same result as with the post-fix -explicit flag (these results were generated using version 3.0_RC3-135-g2b)

So it looks good! :slight_smile:

Hi all,

I wonder how exactly the “tckstats” calculates the track lengths, I haven’t seen this in tutorial document.

Wang