Open jdtournier opened 9 years ago
Hmm, might want to think about how this might generalize. In one of the GitLab branches I gave tckmap the capability to warp tracks to template space after having determined the TWI factor, but prior to voxel mapping.
Would it be safe to assume that there won't be a mixture of template-space and subject-space ROIs? Because the seed may not be the only thing coming from template space, and it would get clumsy trying to provide a corresponding warp for each.
Good point. I was going to assume that all seed points get transformed. As you say, too messy to support anything else. And the target application will overwhelmingly be group analyses, where really there shouldn't be any subject-specific ROIs. Let's keep this simple...
And good idea for tckmap too. Might be worth coding up a few helper functions and an OptionGroup to go with it if it's going to be used a fair bit. Would also allow us to merge the tcknormalise
functionality into tckedit
, although that might make it a bit too obscure, not sure...
I was thinking more along the lines of include / exclude / mask... e.g. if you provide a template -> subject warp for seed points, should the same transformation be applied to all ROIs? I tend to think a mask is likely to be per-subject, whereas include / exclude are more likely to also be template-space-based...
Reckon tcknormalise could disappear into tckedit no problems.
Good point about the other ROIs. I'm happy for an all or nothing approach on that one - I don't see a need for subject-specific masks assuming your registration works ok, the brain outline should register pretty well. But then if you're talking about ACT, well then yes, that might be an issue. But we could maybe make sure your 5tt image is always assumed to be in subject space?
More pertinent is the fact that this means we need both the forward and backward transforms to be supplied... Not problematic as such, just changes what I had in mind for the command-line syntax. We'll need an option to supply both forward & inverse transforms, another to specify that seeds & ROIs should be warped, and another to specify that tracks should be warped. Or something that provides similar flexibility. Maybe one option to specify the forward/backward warps to the space where the ROIs are defined, and another to specify the forward transform for the tracks - i.e. they could be different, although I have no idea what use that would be, but it is very simple to offer the option of a different warp for the ROIs and for the final tracks...
Yes, 5TT image would always be in subject space regardless.
One possibility would be: If the transform is provided from subject to template space, that makes it easy to test against ROIs and to output the tracks in template space, but doesn't deal with the seed points. But if the warp is diffeomorphic, it should be possible to non-linearly find the point in subject space that warps to the actual defined seed point in template space. And since it only has to be done for one point per streamline, it shouldn't be too expensive.
I also don't see a valid use case for warping output tracks with a different field to that used to map to ROIs, so having to provide the path to the same warp twice every time would be kinda annoying. Would be simpler to have something like:
-tempate_warp
: Provide warp from subject space to template space (either affine or field image)-warp_seeds
: Transform seed points according to the INVERSE of the field-warp_rois
: Transform streamline points before mapping them to include / exclude / mask ROIs-warp_tracks
: Transform streamline data before writing to output fileAnyone think of any important use cases that this would preclude?
Happy with the options you suggest. Only thing is I really think users should be supplying both the forward and inverse transforms. For one, there will be cases where the seed generator has to try a lot of positions before finding a suitable start point/direction combination. In these cases, we're going to get a performance hit. Second, I'd rather separate out tckgen's job as cleanly as possible from anything to do with registration. There are different ways of inverting a warp, I'd rather people had the choice as to how this was done. Third, in the event that people use substandard registration approaches and provide a non-invertible warp, there is a chance of crash or infinite loop - I'd rather leave that part out of the equation. Finally, the registration algorithm that will hopefully eventually make its way into MRtrix will spit out both forward and inverse transforms for free, by virtue of its being symmetric, so there wouldn't even need to be an explicit call to warp invert command...
@jdtournier , the scenario you initially described and the suggested implementation strategy are not equivalent. For argument's sake, let's say we mean "spatially homogeneous seeding" when we simply say "seeding". In general, "seeding" could be a specific distribution or strategy of distributing seeds.
The common workflow...
generate ROIs in template space, warp them to subject space, generate the tracks, and/or warp the tracks back to template space afterwards
...seeds in subject space, but the suggested strategy...
modifying each seed point generated by the seeder immediately prior to using it, and subsequently by transforming the streamlines to template space prior to queuing them up for the writer
...seeds in template space.
Any non-orthonormal transformation/warp between subject and template space will result in a difference in seeding distribution/strategy between both of these workflows.
Not that I'm saying that either one is the best or desired in any scenario, but boxing up the functionality in a single command means we'll need to be clear in defining to the user what's going on. (and possibly think a bit about whether/what logic actually is the best or at least most intuitive in this case; that's how the command should behave by default I guess)
I can see that could be viewed as a problem... But then to get homogeneous seeding in native space, you'd probably need to regrid the ROI from template space, which you can do right now if you want - could do with a little script to ease the workflow, but that wouldn't require any changes to the backend. If this isn't viewed as an appropriate solution, then there's probably not much point in providing the option in tckgen itself...
But then I'm not sure that uniform seeding in template space is a bad thing either. You could argue that this is the right way to go - I guess it would depend on the specifics of the question being addressed...
In any case, right now we have commands to do all of this (the explicit regridding option, that is). It would be relatively easy to script it all up for ANTS or FNIRT, maybe that would be a better way to go...?
A common workflow is to generate ROIs in template space, warp them to subject space, generate the tracks, and/or warp the tracks back to template space afterwards. It would be cleaner to be able to do this within tckgen itself. We could add one option '-seed_warp' specifying how to transform seed points from template to subject space, and another '-warp_tracks' to transform the tracks generated from subject to template space.
This should be trivial to implement by modifying each seed point generated by the seeder immediately prior to using it, and subsequently by transforming the streamlines to template space prior to queuing them up for the writer. This is a very trivial operation - simply replace each vertex by the values in the interpolated warp image at that vertex's location. Only slight potential complication that I can foresee is that the initial direction will also need to be transformed so that the same -initdirection option can be used across subjects. Again, that shouldn't be particularly difficult...