Obtain connectivity fingerprint from a voxel

Hello Mrtrix experts,

I am trying to replicate an analysis that uses connectivity fingerprints to predict functional responses. I have a tractogram with structural connectomes generated by QSIRecon based on several atlases, and associated SIFT2 weights. For a given region, I have to look at each voxel that makes up the region, and make connectivity fingerprint vectors describing that voxels connectivity to each region in the parcellation. So, for example, if I have 150 regions in the parcellation, and the region I am focusing on has 400 voxels, then I would be making 400 fingerprint vectors with a length of 150. Here’s a figure from the paper that describes what the outcome looks like when done across subjects.

I know tck2connectome can be used to make fingerprints, and I think several of the QSIRecon derivatives will come in handy, such as the parcellation image which I can make function as a nodes.mif image. However, I suppose I am unsure how to get streamlines that originate in a given voxel (fixed_seed_tracks.tck), given that the parcellations include cortical gray matter. The original paper used an FSL-based pipeline that explicitly made 5000 streamlines per voxel and wasn’t too explicit about what they defined as a seeding mask. Can you think of some way I could extract this information, or am I thinking about this the wrong way?

Thanks,
Steven

1 Like

I’ve since rethought my strategy, since I am not sure what I was describing first would be feasible or be the best route given the goal of the analysis. That is, using the full premade tractogram would both render it hard to associate streamlines with origin voxels and leave no way to ensure that each voxel was seeded the same number of times. Both of these confounds would work against the planned analysis.

Essentially, I am trying to do this, but with QSIRecon/MRtrix tractography. I already have the DWI-registered parcels for a different atlas:

Automated cortical parcellation was performed in each participant’s T1 scan, using the Destrieux atlas (Destrieux et al. 2010) from Freesurfer 5.1 (Fischl et al. 2002, 2004) to define 148 cortical regions. … We used the DWI-registered parcels as seed and target regions for fiber tracking…The principal diffusion directions were calculated per voxel, and probabilistic diffusion tractography was carried out using FSL-FDT (Behrens et al. 2007) with 5000 streamline samples in each seed voxel to create a connectivity distribution to each of the target regions, while avoiding a mask consisting of the ventricles. Each of the 148 regions was used as a seed region and tractography was carried out to all 147 remaining regions, or targets. Thus, every voxel within each parcel is described by a vector of connection probabilities to each other brain region.

I might redo the tractography, but this time seed particularly from a given parcellation region (in my case, right fusiform gyrus) using the following parameters:
tckgen -act ACT.nii.gz -backtrack -crop_at_gmwmi -seed_random_per_voxel fusiform_R.nii.gz 5000 -include everything_besides_fusiform_R.nii.gz -output_seeds seeds.txt

If I do this, will there be a way to associate streamlines to the voxel they were seeded from? Is that what the -output_seeds argument would specify?

I would hope that FOD power would be low enough in ventricles that I wouldn’t have to worry about streamlines crossing them.

Thanks,
Steven


Post attempt edit: Perhaps I’ve misunderstood how -seed_random_per_voxel, because the number of streamlines I was getting seemed to far exceed the number of voxels in the mask*5000. I also had a chance to look at the seeds output file, and am having trouble figuring out how to use the seed_index field. Would it be best to use the X Y and Z position of the seed to assign voxels?

Hi Steven,

I think that what you’re looking for is something like this script. You could either run it in a loop, where on each iteration you generate a binary image corresponding to just one of the parcels and use that as the seed image, or you could produce a modified version of that script that simply uses every voxel present in the input parcellation as a seed voxel.

However, I suppose I am unsure how to get streamlines that originate in a given voxel (fixed_seed_tracks.tck ), given that the parcellations include cortical gray matter.

Well, yes; for this sort of fine-detailed approach, using surface vertices for the cortex rather than voxels would be preferable. The aforementioned script at least exploits a trick whereby if it looks increasingly unlikely that the requested number of streamlines can be generated from a given seed, it will abort execution for that particular voxel. Using GMWMI-based seeding for such parcels would also potentially be preferable; but again, if you wanted to do this for cortical parcels but not for sub-cortical parcels, you’d need to modify the code.

Technically you could also take the cortical GM partial volume image, add it to the sub-cortical volume, and zero out the cortical GM volume, which would permit streamlines to be seeded in, and track into, the cortex. Though I don’t personally expect the resulting trajectories to be trustworthy in the absence of information over and above the low-spatial-resolution FODs.

I am of course assuming that you are using ACT based on your description, though you didn’t state so explicitly. (Edit; it’s in the second post)

That is, using the full premade tractogram would both render it hard to associate streamlines with origin voxels and leave no way to ensure that each voxel was seeded the same number of times.

Yes and no for both:

  • You can get tckgen to output the seed location for each streamline; see -output_seeds. It’s a bit of a hack though, and you’d need your own code to utilise such.

  • Generally for this sort of “endpoint-seeded tracking”, you would be performing unidirectional tracking, in which case the seed point is the first vertex of the streamline. The -vector option in tck2connectome, which is used in the maskconnectivity script linked above, exploits this knowledge to only consider the last vertex of each streamline when assigning to parcels.

  • There is a difference between “ensuring that each voxel was seeded the same number of times”, and “ensuring that the same number of streamlines generated from each voxel were written”. Both the proportion of streamline seeds resulting in streamline propagation, and the number of generated streamlines satisfying all criteria and being written to file, can differ between voxels. -seed_*_per_voxel only guarantees an equal number of seeds per voxel. So while you could use one of these options and provide all non-zero voxels within the parcellation as the seed image in order to do whole-brain tractography, the guarantee provided by such may not be precisely what you’re looking for. maskconnectivity on the other hand, because it explicitly runs tckgen multiple times with a single voxel seed each time, guarantees an equal number of exported streamlines per seed voxel.

If I do this, will there be a way to associate streamlines to the voxel they were seeded from? Is that what the -output_seeds argument would specify?

-output_seeds will give, for each streamline, the vertex index that corresponds to the seed, as well as the real-space position of the seed vertex. This would need to be transformed to determine the voxel in which that seed resides. But as previously, it’s unclear how to interpret such. If you are interested in how one voxel connects to everything else, but the streamlines seeded there are propagated in both directions, does that streamline contribute two connections to that voxel or just one?

Perhaps I’ve misunderstood how -seed_random_per_voxel, because the number of streamlines I was getting seemed to far exceed the number of voxels in the mask*5000.

Assuming you requested 5000 seeds per voxel, the total number of streamlines should never exceed that product. If this is definitely the case and not a misunderstanding, that would need to be looked into.

Cheers
Rob

As always, thanks for the insightful and thoughtful answer Rob!

Looks interesting, will take a look.

After some discussion with others who have done similar work, I decided not to look at endpoint terminations, but rather tract inclusion. That is, does a streamline pass through a given target parcel at any point? If so, that streamline’s SIFT weight is contributed to the connectivity fingerprint.

I looked into it on my end and it was a misunderstanding; I thought my seed region was smaller than it actually was, so the number of streamlines far exceeded my estimates, but my estimate was wrong.

Best,
Steven

After some discussion with others who have done similar work, I decided not to look at endpoint terminations, but rather tract inclusion. That is, does a streamline pass through a given target parcel at any point? If so, that streamline’s SIFT weight is contributed to the connectivity fingerprint.

While you can do that, I’ve personally always found it counter-intuitive permitting an individual streamline to contribute to multiple targets in that way (see e.g. this work). Nevertheless you could modify that script to behave in that way. It’d require adding your seed mask into the parcellation image, generating a full connectivity matrix, and then extracting just the column of interest.