""" ================================================== Automatic Fiber Bundle Extraction with RecoBundles ================================================== This example explains how we can use RecoBundles [Garyfallidis17]_ to extract bundles from tractograms. First import the necessary modules. """ import numpy as np from dipy.align.streamlinear import whole_brain_slr from dipy.data import get_two_hcp842_bundles from dipy.data import (fetch_target_tractogram_hcp, fetch_bundle_atlas_hcp842, get_bundle_atlas_hcp842, get_target_tractogram_hcp) from dipy.io.stateful_tractogram import Space, StatefulTractogram from dipy.io.streamline import load_trk, save_trk from dipy.io.utils import create_tractogram_header from dipy.segment.bundles import RecoBundles from dipy.viz import actor, window """ Download and read data for this tutorial """ target_file, target_folder = fetch_target_tractogram_hcp() atlas_file, atlas_folder = fetch_bundle_atlas_hcp842() atlas_file, all_bundles_files = get_bundle_atlas_hcp842() target_file = get_target_tractogram_hcp() sft_atlas = load_trk(atlas_file, "same", bbox_valid_check=False) atlas = sft_atlas.streamlines atlas_header = create_tractogram_header(atlas_file, *sft_atlas.space_attributes) sft_target = load_trk(target_file, "same", bbox_valid_check=False) target = sft_target.streamlines target_header = create_tractogram_header(target_file, *sft_target.space_attributes) """ let's visualize atlas tractogram and target tractogram before registration """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(atlas, colors=(1, 0, 1))) scene.add(actor.line(target, colors=(1, 1, 0))) window.record(scene, out_path='tractograms_initial.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: tractograms_initial.png :align: center Atlas and target before registration. """ """ We will register target tractogram to model atlas' space using streamlinear registeration (SLR) [Garyfallidis15]_ """ moved, transform, qb_centroids1, qb_centroids2 = whole_brain_slr( atlas, target, x0='affine', verbose=True, progressive=True, rng=np.random.RandomState(1984)) """ We save the transform generated in this registration, so that we can use it in the bundle profiles example """ np.save("slr_transform.npy", transform) """ let's visualize atlas tractogram and target tractogram after registration """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(atlas, colors=(1, 0, 1))) scene.add(actor.line(moved, colors=(1, 1, 0))) window.record(scene, out_path='tractograms_after_registration.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: tractograms_after_registration.png :align: center Atlas and target after registration. """ """ Extracting bundles using RecoBundles [Garyfallidis17]_ RecoBundles requires a model (reference) bundle and tries to extract similar looking bundle from the input tractogram. There are some key parameters that users can set as per requirements. Here are the key threshold parameters measured in millimeters and their function in Recobundles: - model_clust_thr : It will use QuickBundles to get the centroids of the model bundle and work with centroids instead of all streamlines. This helps to make RecoBundles faster. The larger the value of the threshold, the fewer centroids will be, the and smaller the threshold value, the more centroids will be. If you prefer to use all the streamlines of the model bundle, you can set this threshold to 0.01 mm. Recommended range of the model_clust_thr is 0.01 - 3.0 mm. - reduction_thr : This threshold will be used to reduce the search space for finding the streamlines that match model bundle streamlines in shape. Instead of looking at the entire tractogram, now we will be looking at neighboring region of a model bundle in the tractogram. Increase the threshold to increase the search space. Recommended range of the reduction_thr is 15 - 30 mm. - pruning_thr : This threshold will filter the streamlines for which the distance to the model bundle is greater than the pruning_thr. This serves to filter the neighborhood area (search space) to get streamlines that are like the model bundle. Recommended range of the pruning_thr is 8 - 12 mm. - reduction_distance and pruning_distance : Distance method used internally. Minimum Diferect Flip distance (mdf) or Mean Average Minimum (mam). Default is set to mdf. - slr : If slr flag is set to True, local registration of model bundle with neighbouring area will be performed. Default and recommended is True. """ """ Read Arcuate Fasciculus Left and Corticospinal Tract Left bundles from already fetched atlas data to use them as model bundle. Let's visualize the Arcuate Fasciculus Left model bundle. """ model_af_l_file, model_cst_l_file = get_two_hcp842_bundles() sft_af_l = load_trk(model_af_l_file, "same", bbox_valid_check=False) model_af_l = sft_af_l.streamlines interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(model_af_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='AF_L_model_bundle.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: AF_L_model_bundle.png :align: center Model Arcuate Fasciculus Left bundle """ rb = RecoBundles(moved, verbose=True, rng=np.random.RandomState(2001)) recognized_af_l, af_l_labels = rb.recognize(model_bundle=model_af_l, model_clust_thr=0.1, reduction_thr=15, pruning_thr=7, reduction_distance='mdf', pruning_distance='mdf', slr=True) """ let's visualize extracted Arcuate Fasciculus Left bundle """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(recognized_af_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='AF_L_recognized_bundle.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: AF_L_recognized_bundle.png :align: center Extracted Arcuate Fasciculus Left bundle """ """ Save the bundle as a trk file. Let's save the recognized bundle in the common space (atlas space), in this case, MNI space. """ reco_af_l = StatefulTractogram(recognized_af_l, atlas_header, Space.RASMM) save_trk(reco_af_l, "AF_L_rec_1.trk", bbox_valid_check=False) """ Let's save the recognized bundle in the original space of the subject anatomy. """ reco_af_l = StatefulTractogram(target[af_l_labels], target_header, Space.RASMM) save_trk(reco_af_l, "AF_L_org_1.trk", bbox_valid_check=False) """ Now, let's increase the reduction_thr and pruning_thr values. """ recognized_af_l, af_l_labels = rb.recognize(model_bundle=model_af_l, model_clust_thr=0.1, reduction_thr=20, pruning_thr=10, reduction_distance='mdf', pruning_distance='mdf', slr=True) """ let's visualize extracted Arcuate Fasciculus Left bundle. """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(recognized_af_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='AF_L_recognized_bundle2.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: AF_L_recognized_bundle2.png :align: center Extracted Arcuate Fasciculus Left bundle """ """ Save the bundle as a trk file. Let's save the recognized bundle in the common space (atlas space), in this case, MNI space. """ reco_af_l = StatefulTractogram(recognized_af_l, atlas_header, Space.RASMM) save_trk(reco_af_l, "AF_L_rec_2.trk", bbox_valid_check=False) """ Let's save the recognized bundle in the original space of the subject anatomy. """ reco_af_l = StatefulTractogram(target[af_l_labels], target_header, Space.RASMM) save_trk(reco_af_l, "AF_L_org_2.trk", bbox_valid_check=False) """ Now, let's increase the reduction_thr and pruning_thr values further. """ recognized_af_l, af_l_labels = rb.recognize(model_bundle=model_af_l, model_clust_thr=0.1, reduction_thr=25, pruning_thr=12, reduction_distance='mdf', pruning_distance='mdf', slr=True) """ let's visualize extracted Arcuate Fasciculus Left bundle. """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(recognized_af_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='AF_L_recognized_bundle3.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: AF_L_recognized_bundle3.png :align: center Extracted Arcuate Fasciculus Left bundle """ """ Save the bundle as a trk file. Let's save the recognized bundle in the common space (atlas space), in this case, MNI space. """ reco_af_l = StatefulTractogram(recognized_af_l, atlas_header, Space.RASMM) save_trk(reco_af_l, "AF_L_rec_3.trk", bbox_valid_check=False) """ Let's save the recognized bundle in the original space of the subject anatomy. """ reco_af_l = StatefulTractogram(target[af_l_labels], target_header, Space.RASMM) save_trk(reco_af_l, "AF_L_org_3.trk", bbox_valid_check=False) """ Let's apply auto-calibrated RecoBundles on the output of standard RecoBundles. This step will filter out the outlier streamlines. This time, the RecoBundles' extracted bundle will serve as a model bundle. As a rule of thumb, provide larger threshold values in standard RecoBundles function and smaller values in the auto-calibrated RecoBundles (refinement) step. """ r_recognized_af_l, r_af_l_labels = rb.refine(model_bundle=model_af_l, pruned_streamlines=recognized_af_l, model_clust_thr=0.1, reduction_thr=15, pruning_thr=6, reduction_distance='mdf', pruning_distance='mdf', slr=True) """ let's visualize extracted refined Arcuate Fasciculus Left bundle. """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(r_recognized_af_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='AF_L_refine_recognized_bundle.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: AF_L_refine_recognized_bundle.png :align: center Extracted Arcuate Fasciculus Left bundle """ """ Save the bundle as a trk file. Let's save the recognized bundle in the common space (atlas space), in this case, MNI space. """ reco_af_l = StatefulTractogram(r_recognized_af_l, atlas_header, Space.RASMM) save_trk(reco_af_l, "AF_L_rec_refine.trk", bbox_valid_check=False) """ Let's save the recognized bundle in the original space of the subject anatomy. """ reco_af_l = StatefulTractogram(target[r_af_l_labels], target_header, Space.RASMM) save_trk(reco_af_l, "AF_L_org_refine.trk", bbox_valid_check=False) """ Let's load Corticospinal Tract Left model bundle and visualize it. """ sft_cst_l = load_trk(model_cst_l_file, "same", bbox_valid_check=False) model_cst_l = sft_cst_l.streamlines interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(model_cst_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='CST_L_model_bundle.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: CST_L_model_bundle.png :align: center The Corticospinal tract model bundle """ recognized_cst_l, cst_l_labels = rb.recognize(model_bundle=model_cst_l, model_clust_thr=0.1, reduction_thr=15, pruning_thr=7, reduction_distance='mdf', pruning_distance='mdf', slr=True) """ let's visualize extracted Corticospinal tract Left bundle """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(recognized_cst_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='CST_L_recognized_bundle.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: CST_L_recognized_bundle.png :align: center Extracted Corticospinal tract Left bundle """ """ Save the bundle as a trk file. Let's save the recognized bundle in the common space (atlas space), in this case, MNI space. """ reco_cst_l = StatefulTractogram(recognized_cst_l, atlas_header, Space.RASMM) save_trk(reco_cst_l, "CST_L_rec_1.trk", bbox_valid_check=False) """ Let's save the recognized bundle in the original space of the subject anatomy. """ reco_cst_l = StatefulTractogram(target[cst_l_labels], target_header, Space.RASMM) save_trk(reco_cst_l, "CST_L_org_1.trk", bbox_valid_check=False) """ Now, let's increase the reduction_thr and pruning_thr values. """ recognized_cst_l, cst_l_labels = rb.recognize(model_bundle=model_cst_l, model_clust_thr=0.1, reduction_thr=20, pruning_thr=10, reduction_distance='mdf', pruning_distance='mdf', slr=True) """ let's visualize extracted Corticospinal tract Left bundle. """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(recognized_cst_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='CST_L_recognized_bundle2.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: CST_L_recognized_bundle2.png :align: center Extracted Corticospinal tract Left bundle """ """ Save the bundle as a trk file. Let's save the recognized bundle in the common space (atlas space), in this case, MNI space. """ reco_cst_l = StatefulTractogram(recognized_cst_l, atlas_header, Space.RASMM) save_trk(reco_cst_l, "CST_L_rec_2.trk", bbox_valid_check=False) """ Let's save the recognized bundle in the original space of the subject anatomy. """ reco_cst_l = StatefulTractogram(target[cst_l_labels], target_header, Space.RASMM) save_trk(reco_cst_l, "CST_L_org_2.trk", bbox_valid_check=False) """ Now, let's increase the reduction_thr and pruning_thr values further. """ recognized_cst_l, cst_l_labels = rb.recognize(model_bundle=model_cst_l, model_clust_thr=0.1, reduction_thr=25, pruning_thr=12, reduction_distance='mdf', pruning_distance='mdf', slr=True) """ let's visualize extracted Corticospinal tract Left bundle. """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(recognized_cst_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='CST_L_recognized_bundle3.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: CST_L_recognized_bundle3.png :align: center Extracted Corticospinal tract Left bundle """ """ Save the bundle as a trk file. Let's save the recognized bundle in the common space (atlas space), in this case, MNI space. """ reco_cst_l = StatefulTractogram(recognized_cst_l, atlas_header, Space.RASMM) save_trk(reco_cst_l, "CST_L_rec_3.trk", bbox_valid_check=False) """ Let's save the recognized bundle in the original space of the subject anatomy. """ reco_cst_l = StatefulTractogram(target[cst_l_labels], target_header, Space.RASMM) save_trk(reco_cst_l, "CST_L_org_3.trk", bbox_valid_check=False) """ Let's apply auto-calibrated RecoBundles on the output of standard RecoBundles. This step will filter out the outlier streamlines. This time, the RecoBundles' extracted bundle will serve as a model bundle. As a rule of thumb, provide larger threshold values in standard RecoBundles function and smaller values in the auto-calibrated RecoBundles (refinement) step. """ r_recognized_cst_l, r_cst_l_labels = rb.refine( model_bundle=model_cst_l, pruned_streamlines=recognized_cst_l, model_clust_thr=0.1, reduction_thr=15, pruning_thr=6, reduction_distance='mdf', pruning_distance='mdf', slr=True) """ let's visualize extracted refined Corticospinal tract Left bundle. """ interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) scene.add(actor.line(r_recognized_cst_l)) scene.set_camera(focal_point=(-18.17281532, -19.55606842, 6.92485857), position=(-360.11, -30.46, -40.44), view_up=(-0.03, 0.028, 0.89)) window.record(scene, out_path='CST_L_refine_recognized_bundle.png', size=(600, 600)) if interactive: window.show(scene) """ .. figure:: CST_L_refine_recognized_bundle.png :align: center Extracted refined Corticospinal tract Left bundle """ """ Save the bundle as a trk file. Let's save the recognized bundle in the common space (atlas space), in this case, MNI space. """ reco_cst_l = StatefulTractogram(r_recognized_cst_l, atlas_header, Space.RASMM) save_trk(reco_cst_l, "CST_L_rec_refine.trk", bbox_valid_check=False) """ Let's save the recognized bundle in the original space of the subject anatomy. """ reco_cst_l = StatefulTractogram(target[r_cst_l_labels], target_header, Space.RASMM) save_trk(reco_cst_l, "CST_L_org_refine.trk", bbox_valid_check=False) """ This example shows how changing different threshold parameters can change the output. It is up to the user to decide what is the desired output and select parameters accordingly. """ """ References ---------- .. [Garyfallidis17] Garyfallidis et al. Recognition of white matter bundles using local and global streamline-based registration and clustering, Neuroimage, 2017. .. [Chandio2020] Chandio, B.Q., Risacher, S.L., Pestilli, F., Bullock, D., Yeh, FC., Koudoro, S., Rokem, A., Harezlak, J., and Garyfallidis, E. Bundle analytics, a computational framework for investigating the shapes and profiles of brain pathways across populations. Sci Rep 10, 17149 (2020) """