Tractogram manipulations: logical operations, resampling, filtering

Scilpy scripts allow users to modify tractograms in various ways based on their needs, such as shown on Figure 2 in our upcoming paper:

The range of possibilities is wide!

Overall, figure 2 in our upcoming paper represents well the range of possibilities.

Figure 2 in upcoming paper.
** For the coloring of tractograms, see Adding data_per_point to tractograms for visualization.
** For an example of streamlines cutting, see Streamlines manipulation.

Preparing data for this tutorial

Examples of data for this tutorial can be downloaded using instructions here: Getting ready for tutorials. Let’s use two tractograms available in the tutorial data:

tractogram1=$in_folder/sub-01/sub-01__cst_L_part1.trk
tractogram2=$in_folder/sub-01/sub-01__cst_L_part2.trk

To look at your data in a viewer, you may use the subject’s T1 volume:

t1=$in_folder/sub-01/sub-01__t1.nii.gz

We used MI-Brain to visualize both tractograms, which each contain one part of the CST:

Initial tutorial data

Tip

You may download the complete bash script to run the whole tutorial in one step ⭳ here.

A. Logical operations

1. Merging two tractograms (using all streamlines from both).

If a streamline is exactly the same in both tractograms, it will be kept once.

scil_tractogram_count_streamlines $tractogram1
scil_tractogram_count_streamlines $tractogram2
scil_tractogram_math union $tractogram1 $tractogram2 union.trk
scil_tractogram_count_streamlines union.trk

2. Finding streamlines belonging in two tractograms (intersection)

scil_tractogram_math intersection $tractogram1 $tractogram2 intersection.trk

3. Finding streamlines that are in $tractogram1 but not in $tractogram2

scil_tractogram_math difference $tractogram1 $tractogram2 difference1-2.trk
Intersection result

Result of the intersection operation. The streamlines in orange belonged to both tractograms and form the new file intersection.trk.

B. Tractogram resampling

Resampling means changing the number of streamlines in your tractogram.

1. Downsampling: keeping only 20 streamlines: the most basic option for downsampling is to pick a given number of streamlines randomly. Our initial tractogram1 contains 2598 streamlines. Let’s pick 200 of them.

scil_tractogram_resample $tractogram1 200 tractogram_downsampled.trk

It is also possible to downsample per Quickbundles cluster. To understand Quickbundles, refer to page Tractogram Segmentation into bundles. Here, the script will divide your tractogram into sub-sections and will pick the appropriate number in each. This will ensure that the selected streamlines are not too random and cover more or less the whole tractogram range. (With this option, the final number of streamlines may not be exactly what you asked for, but will be close).

Most of the time, you can use the default value for –qbx_thresholds, particularly if you are working on whole-brain tractograms. Here, our tutorial data tractogram1 is already a small bundle, so we will be more severe and use 3.

scil_tractogram_resample $tractogram1 200 tractogram_downsampled2.trk \
    --downsample_per_cluster -v --qbx_thresholds 3

You may open and compare tractogram_downsampled.trk and tractogram_downsampled2.trk. Here, data is small and in both cases, the downsampling should cover a good portion of the spatial extend of the bundle, even though the first call is random. On whole-brain data, the difference can be more impressive.

2. Upsampling:

To add more streamlines to our tractogram, the script uses randomly picked streamlines to create new similar ones by moving a little bit each point. We will also give a –tube_radius option to make sure final streamlines do not deviate too much from original trajectory.

scil_tractogram_resample $tractogram1 4000 tractogram_upsampled.trk \
    --point_wise_std 5 -v --tube_radius 4
Intersection result

Zoomed view on the results. In green: the original bundle. In blue: the new streamlines.

3. Splitting a tractogram

We will split our tractogram into subsections. This line of code below will create 3 files: out_split_part_0.trk, out_split_part_1.trk, out_split_part_2.trk.

scil_tractogram_split --nb_chunks 3 $tractogram1 out_split_3_part

It is also possible, instead, to split into files of a given number of streamlines. For instance, this will create N files of 100 streamlines:

scil_tractogram_split --chunk_size 100 $tractogram1 out_split_100_part -v

Finally, it is again possible to split per Quickbundles cluster.

scil_tractogram_split --nb_chunk 3 --split_per_cluster \
      $tractogram1 out_split_3QB_part -v --qbx_thresholds 6

C. Tractogram flipping

To flip a tractogram on an axis (x, y, z; here we chose the x-axis), you can use:

scil_tractogram_flip $tractogram1 flipped_x.trk x -v