def test_rb_disable_slr(): rb = RecoBundles(f, greater_than=0, clust_thr=10) rec_trans, rec_labels = rb.recognize(model_bundle=f2, model_clust_thr=5., reduction_thr=10, slr=False) D = bundles_distances_mam(f2, f[rec_labels]) # check if the bundle is recognized correctly if len(f2) == len(rec_labels): for row in D: assert_equal(row.min(), 0) refine_trans, refine_labels = rb.refine(model_bundle=f2, pruned_streamlines=rec_trans, model_clust_thr=5., reduction_thr=10) D = bundles_distances_mam(f2, f[refine_labels]) # check if the bundle is recognized correctly for row in D: assert_equal(row.min(), 0)
def test_rb_no_neighb(): # what if no neighbors are found? No recognition b = Streamlines(fornix) b1 = b.copy() b2 = b1[:20].copy() b2._data += np.array([100, 0, 0]) b3 = b1[:20].copy() b3._data += np.array([300, 0, 0]) b.extend(b3) rb = RecoBundles(b, greater_than=0, clust_thr=10) rec_trans, rec_labels = rb.recognize(model_bundle=b2, model_clust_thr=5., reduction_thr=10) if len(rec_trans) > 0: refine_trans, refine_labels = rb.refine(model_bundle=b2, pruned_streamlines=rec_trans, model_clust_thr=5., reduction_thr=10) assert_equal(len(refine_labels), 0) assert_equal(len(refine_trans), 0) else: assert_equal(len(rec_labels), 0) assert_equal(len(rec_trans), 0)
def test_rb_reduction_mam(): rb = RecoBundles(f, greater_than=0, clust_thr=10, verbose=True) rec_trans, rec_labels = rb.recognize(model_bundle=f2, model_clust_thr=5., reduction_thr=10, reduction_distance='mam', slr=True, slr_metric='asymmetric', pruning_distance='mam') D = bundles_distances_mam(f2, f[rec_labels]) # check if the bundle is recognized correctly if len(f2) == len(rec_labels): for row in D: assert_equal(row.min(), 0) refine_trans, refine_labels = rb.refine(model_bundle=f2, pruned_streamlines=rec_trans, model_clust_thr=5., reduction_thr=10) D = bundles_distances_mam(f2, f[refine_labels]) # check if the bundle is recognized correctly for row in D: assert_equal(row.min(), 0)
def test_rb_clustermap(): cluster_map = qbx_and_merge(f, thresholds=[40, 25, 20, 10]) rb = RecoBundles(f, greater_than=0, less_than=1000000, cluster_map=cluster_map, clust_thr=10) rec_trans, rec_labels = rb.recognize(model_bundle=f2, model_clust_thr=5., reduction_thr=10) D = bundles_distances_mam(f2, f[rec_labels]) # check if the bundle is recognized correctly if len(f2) == len(rec_labels): for row in D: assert_equal(row.min(), 0) refine_trans, refine_labels = rb.refine(model_bundle=f2, pruned_streamlines=rec_trans, model_clust_thr=5., reduction_thr=10) D = bundles_distances_mam(f2, f[refine_labels]) # check if the bundle is recognized correctly for row in D: assert_equal(row.min(), 0)
def segment_reco(self, tg=None): """ Segment streamlines using the RecoBundles algorithm [Garyfallidis2017] Parameters ---------- tg : StatefulTractogram class instance A whole-brain tractogram to be segmented. Returns ------- fiber_groups : dict Keys are names of the bundles, values are Streamline objects. The streamlines in each object have all been oriented to have the same orientation (using `dts.orient_by_streamline`). """ tg = self._read_tg(tg=tg) fiber_groups = {} self.move_streamlines(tg, self.reg_algo) # We generate our instance of RB with the moved streamlines: self.logger.info("Extracting Bundles") rb = RecoBundles(self.moved_sl, verbose=False, rng=self.rng) # Next we'll iterate over bundles, registering each one: bundle_list = list(self.bundle_dict.keys()) bundle_list.remove('whole_brain') self.logger.info("Assigning Streamlines to Bundles") for bundle in bundle_list: model_sl = self.bundle_dict[bundle]['sl'] _, rec_labels = rb.recognize(model_bundle=model_sl, model_clust_thr=self.model_clust_thr, reduction_thr=self.reduction_thr, reduction_distance='mdf', slr=True, slr_metric='asymmetric', pruning_distance='mdf') # Use the streamlines in the original space: recognized_sl = tg.streamlines[rec_labels] if self.refine and len(recognized_sl) > 0: _, rec_labels = rb.refine(model_sl, recognized_sl, self.model_clust_thr, reduction_thr=self.reduction_thr, pruning_thr=self.pruning_thr) recognized_sl = tg.streamlines[rec_labels] standard_sl = self.bundle_dict[bundle]['centroid'] oriented_sl = dts.orient_by_streamline(recognized_sl, standard_sl) if self.return_idx: fiber_groups[bundle] = {} fiber_groups[bundle]['idx'] = rec_labels fiber_groups[bundle]['sl'] = StatefulTractogram( oriented_sl, self.img, Space.RASMM) else: fiber_groups[bundle] = StatefulTractogram( oriented_sl, self.img, Space.RASMM) self.fiber_groups = fiber_groups return fiber_groups
def run(self, streamline_files, model_bundle_files, greater_than=50, less_than=1000000, no_slr=False, clust_thr=15., reduction_thr=15., reduction_distance='mdf', model_clust_thr=2.5, pruning_thr=8., pruning_distance='mdf', slr_metric='symmetric', slr_transform='similarity', slr_matrix='small', refine=False, r_reduction_thr=12., r_pruning_thr=6., no_r_slr=False, out_dir='', out_recognized_transf='recognized.trk', out_recognized_labels='labels.npy'): """ Recognize bundles Parameters ---------- streamline_files : string The path of streamline files where you want to recognize bundles. model_bundle_files : string The path of model bundle files. greater_than : int, optional Keep streamlines that have length greater than this value in mm. less_than : int, optional Keep streamlines have length less than this value in mm. no_slr : bool, optional Don't enable local Streamline-based Linear Registration. clust_thr : float, optional MDF distance threshold for all streamlines. reduction_thr : float, optional Reduce search space by (mm). reduction_distance : string, optional Reduction distance type can be mdf or mam. model_clust_thr : float, optional MDF distance threshold for the model bundles. pruning_thr : float, optional Pruning after matching. pruning_distance : string, optional Pruning distance type can be mdf or mam. slr_metric : string, optional Options are None, symmetric, asymmetric or diagonal. slr_transform : string, optional Transformation allowed. translation, rigid, similarity or scaling. slr_matrix : string, optional Options are 'nano', 'tiny', 'small', 'medium', 'large', 'huge'. refine : bool, optional Enable refine recognized bundle. r_reduction_thr : float, optional Refine reduce search space by (mm). r_pruning_thr : float, optional Refine pruning after matching. no_r_slr : bool, optional Don't enable Refine local Streamline-based Linear Registration. out_dir : string, optional Output directory. (default current directory) out_recognized_transf : string, optional Recognized bundle in the space of the model bundle. out_recognized_labels : string, optional Indices of recognized bundle in the original tractogram. 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) """ slr = not no_slr r_slr = not no_r_slr bounds = [(-30, 30), (-30, 30), (-30, 30), (-45, 45), (-45, 45), (-45, 45), (0.8, 1.2), (0.8, 1.2), (0.8, 1.2)] slr_matrix = slr_matrix.lower() if slr_matrix == 'nano': slr_select = (100, 100) if slr_matrix == 'tiny': slr_select = (250, 250) if slr_matrix == 'small': slr_select = (400, 400) if slr_matrix == 'medium': slr_select = (600, 600) if slr_matrix == 'large': slr_select = (800, 800) if slr_matrix == 'huge': slr_select = (1200, 1200) slr_transform = slr_transform.lower() if slr_transform == 'translation': bounds = bounds[:3] if slr_transform == 'rigid': bounds = bounds[:6] if slr_transform == 'similarity': bounds = bounds[:7] if slr_transform == 'scaling': bounds = bounds[:9] logging.info('### RecoBundles ###') io_it = self.get_io_iterator() t = time() logging.info(streamline_files) input_obj = load_tractogram(streamline_files, 'same', bbox_valid_check=False) streamlines = input_obj.streamlines logging.info(' Loading time %0.3f sec' % (time() - t, )) rb = RecoBundles(streamlines, greater_than=greater_than, less_than=less_than) for _, mb, out_rec, out_labels in io_it: t = time() logging.info(mb) model_bundle = load_tractogram(mb, 'same', bbox_valid_check=False).streamlines logging.info(' Loading time %0.3f sec' % (time() - t, )) logging.info("model file = ") logging.info(mb) recognized_bundle, labels = \ rb.recognize( model_bundle, model_clust_thr=model_clust_thr, reduction_thr=reduction_thr, reduction_distance=reduction_distance, pruning_thr=pruning_thr, pruning_distance=pruning_distance, slr=slr, slr_metric=slr_metric, slr_x0=slr_transform, slr_bounds=bounds, slr_select=slr_select, slr_method='L-BFGS-B') if refine: if len(recognized_bundle) > 1: # affine x0 = np.array([0, 0, 0, 0, 0, 0, 1., 1., 1, 0, 0, 0]) affine_bounds = [(-30, 30), (-30, 30), (-30, 30), (-45, 45), (-45, 45), (-45, 45), (0.8, 1.2), (0.8, 1.2), (0.8, 1.2), (-10, 10), (-10, 10), (-10, 10)] recognized_bundle, labels = \ rb.refine( model_bundle, recognized_bundle, model_clust_thr=model_clust_thr, reduction_thr=r_reduction_thr, reduction_distance=reduction_distance, pruning_thr=r_pruning_thr, pruning_distance=pruning_distance, slr=r_slr, slr_metric=slr_metric, slr_x0=x0, slr_bounds=affine_bounds, slr_select=slr_select, slr_method='L-BFGS-B') if len(labels) > 0: ba, bmd = rb.evaluate_results(model_bundle, recognized_bundle, slr_select) logging.info("Bundle adjacency Metric {0}".format(ba)) logging.info("Bundle Min Distance Metric {0}".format(bmd)) new_tractogram = StatefulTractogram(recognized_bundle, streamline_files, Space.RASMM) save_tractogram(new_tractogram, out_rec, bbox_valid_check=False) logging.info('Saving output files ...') np.save(out_labels, np.array(labels)) logging.info(out_rec) logging.info(out_labels)
def run(self, streamline_files, model_bundle_files, greater_than=50, less_than=1000000, no_slr=False, clust_thr=15., reduction_thr=15., reduction_distance='mdf', model_clust_thr=2.5, pruning_thr=8., pruning_distance='mdf', slr_metric='symmetric', slr_transform='similarity', slr_matrix='small', refine=False, r_reduction_thr=12., r_pruning_thr=6., no_r_slr=False, out_dir='', out_recognized_transf='recognized.trk', out_recognized_labels='labels.npy'): """ Recognize bundles Parameters ---------- streamline_files : string The path of streamline files where you want to recognize bundles model_bundle_files : string The path of model bundle files greater_than : int, optional Keep streamlines that have length greater than this value (default 50) in mm. less_than : int, optional Keep streamlines have length less than this value (default 1000000) in mm. no_slr : bool, optional Don't enable local Streamline-based Linear Registration (default False). clust_thr : float, optional MDF distance threshold for all streamlines (default 15) reduction_thr : float, optional Reduce search space by (mm) (default 15) reduction_distance : string, optional Reduction distance type can be mdf or mam (default mdf) model_clust_thr : float, optional MDF distance threshold for the model bundles (default 2.5) pruning_thr : float, optional Pruning after matching (default 8). pruning_distance : string, optional Pruning distance type can be mdf or mam (default mdf) slr_metric : string, optional Options are None, symmetric, asymmetric or diagonal (default symmetric). slr_transform : string, optional Transformation allowed. translation, rigid, similarity or scaling (Default 'similarity'). slr_matrix : string, optional Options are 'nano', 'tiny', 'small', 'medium', 'large', 'huge' (default 'small') refine : bool, optional Enable refine recognized bunle (default False) r_reduction_thr : float, optional Refine reduce search space by (mm) (default 12) r_pruning_thr : float, optional Refine pruning after matching (default 6). no_r_slr : bool, optional Don't enable Refine local Streamline-based Linear Registration (default False). out_dir : string, optional Output directory (default input file directory) out_recognized_transf : string, optional Recognized bundle in the space of the model bundle (default 'recognized.trk') out_recognized_labels : string, optional Indices of recognized bundle in the original tractogram (default 'labels.npy') References ---------- .. [Garyfallidis17] Garyfallidis et al. Recognition of white matter bundles using local and global streamline-based registration and clustering, Neuroimage, 2017. """ slr = not no_slr r_slr = not no_r_slr bounds = [(-30, 30), (-30, 30), (-30, 30), (-45, 45), (-45, 45), (-45, 45), (0.8, 1.2), (0.8, 1.2), (0.8, 1.2)] slr_matrix = slr_matrix.lower() if slr_matrix == 'nano': slr_select = (100, 100) if slr_matrix == 'tiny': slr_select = (250, 250) if slr_matrix == 'small': slr_select = (400, 400) if slr_matrix == 'medium': slr_select = (600, 600) if slr_matrix == 'large': slr_select = (800, 800) if slr_matrix == 'huge': slr_select = (1200, 1200) slr_transform = slr_transform.lower() if slr_transform == 'translation': bounds = bounds[:3] if slr_transform == 'rigid': bounds = bounds[:6] if slr_transform == 'similarity': bounds = bounds[:7] if slr_transform == 'scaling': bounds = bounds[:9] logging.info('### RecoBundles ###') io_it = self.get_io_iterator() t = time() logging.info(streamline_files) input_obj = nib.streamlines.load(streamline_files) streamlines = input_obj.streamlines logging.info(' Loading time %0.3f sec' % (time() - t, )) rb = RecoBundles(streamlines, greater_than=greater_than, less_than=less_than) for _, mb, out_rec, out_labels in io_it: t = time() logging.info(mb) model_bundle = nib.streamlines.load(mb).streamlines logging.info(' Loading time %0.3f sec' % (time() - t, )) logging.info("model file = ") logging.info(mb) recognized_bundle, labels = \ rb.recognize( model_bundle, model_clust_thr=model_clust_thr, reduction_thr=reduction_thr, reduction_distance=reduction_distance, pruning_thr=pruning_thr, pruning_distance=pruning_distance, slr=slr, slr_metric=slr_metric, slr_x0=slr_transform, slr_bounds=bounds, slr_select=slr_select, slr_method='L-BFGS-B') if refine: if len(recognized_bundle) > 1: # affine x0 = np.array([0, 0, 0, 0, 0, 0, 1., 1., 1, 0, 0, 0]) affine_bounds = [(-30, 30), (-30, 30), (-30, 30), (-45, 45), (-45, 45), (-45, 45), (0.8, 1.2), (0.8, 1.2), (0.8, 1.2), (-10, 10), (-10, 10), (-10, 10)] recognized_bundle, labels = \ rb.refine( model_bundle, recognized_bundle, model_clust_thr=model_clust_thr, reduction_thr=r_reduction_thr, reduction_distance=reduction_distance, pruning_thr=r_pruning_thr, pruning_distance=pruning_distance, slr=r_slr, slr_metric=slr_metric, slr_x0=x0, slr_bounds=affine_bounds, slr_select=slr_select, slr_method='L-BFGS-B') if len(labels) > 0: ba, bmd = rb.evaluate_results(model_bundle, recognized_bundle, slr_select) logging.info("Bundle adjacency Metric {0}".format(ba)) logging.info("Bundle Min Distance Metric {0}".format(bmd)) new_tractogram = nib.streamlines.Tractogram( recognized_bundle, affine_to_rasmm=np.eye(4)) nib.streamlines.save(new_tractogram, out_rec, header=input_obj.header) logging.info('Saving output files ...') np.save(out_labels, np.array(labels)) logging.info(out_rec) logging.info(out_labels)
def run(self, streamline_files, model_bundle_files, greater_than=50, less_than=1000000, no_slr=False, clust_thr=15., reduction_thr=15., reduction_distance='mdf', model_clust_thr=2.5, pruning_thr=8., pruning_distance='mdf', slr_metric='symmetric', slr_transform='similarity', slr_matrix='small', refine=False, r_reduction_thr=12., r_pruning_thr=6., no_r_slr=False, out_dir='', out_recognized_transf='recognized.trk', out_recognized_labels='labels.npy'): """ Recognize bundles Parameters ---------- streamline_files : string The path of streamline files where you want to recognize bundles model_bundle_files : string The path of model bundle files greater_than : int, optional Keep streamlines that have length greater than this value (default 50) in mm. less_than : int, optional Keep streamlines have length less than this value (default 1000000) in mm. no_slr : bool, optional Don't enable local Streamline-based Linear Registration (default False). clust_thr : float, optional MDF distance threshold for all streamlines (default 15) reduction_thr : float, optional Reduce search space by (mm) (default 15) reduction_distance : string, optional Reduction distance type can be mdf or mam (default mdf) model_clust_thr : float, optional MDF distance threshold for the model bundles (default 2.5) pruning_thr : float, optional Pruning after matching (default 8). pruning_distance : string, optional Pruning distance type can be mdf or mam (default mdf) slr_metric : string, optional Options are None, symmetric, asymmetric or diagonal (default symmetric). slr_transform : string, optional Transformation allowed. translation, rigid, similarity or scaling (Default 'similarity'). slr_matrix : string, optional Options are 'nano', 'tiny', 'small', 'medium', 'large', 'huge' (default 'small') refine : bool, optional Enable refine recognized bunle (default False) r_reduction_thr : float, optional Refine reduce search space by (mm) (default 12) r_pruning_thr : float, optional Refine pruning after matching (default 6). no_r_slr : bool, optional Don't enable Refine local Streamline-based Linear Registration (default False). out_dir : string, optional Output directory (default input file directory) out_recognized_transf : string, optional Recognized bundle in the space of the model bundle (default 'recognized.trk') out_recognized_labels : string, optional Indices of recognized bundle in the original tractogram (default 'labels.npy') References ---------- .. [Garyfallidis17] Garyfallidis et al. Recognition of white matter bundles using local and global streamline-based registration and clustering, Neuroimage, 2017. """ slr = not no_slr r_slr = not no_r_slr bounds = [(-30, 30), (-30, 30), (-30, 30), (-45, 45), (-45, 45), (-45, 45), (0.8, 1.2), (0.8, 1.2), (0.8, 1.2)] slr_matrix = slr_matrix.lower() if slr_matrix == 'nano': slr_select = (100, 100) if slr_matrix == 'tiny': slr_select = (250, 250) if slr_matrix == 'small': slr_select = (400, 400) if slr_matrix == 'medium': slr_select = (600, 600) if slr_matrix == 'large': slr_select = (800, 800) if slr_matrix == 'huge': slr_select = (1200, 1200) slr_transform = slr_transform.lower() if slr_transform == 'translation': bounds = bounds[:3] if slr_transform == 'rigid': bounds = bounds[:6] if slr_transform == 'similarity': bounds = bounds[:7] if slr_transform == 'scaling': bounds = bounds[:9] logging.info('### RecoBundles ###') io_it = self.get_io_iterator() t = time() logging.info(streamline_files) streamlines, header = load_trk(streamline_files) logging.info(' Loading time %0.3f sec' % (time() - t,)) rb = RecoBundles(streamlines, greater_than=greater_than, less_than=less_than) for _, mb, out_rec, out_labels in io_it: t = time() logging.info(mb) model_bundle, _ = load_trk(mb) logging.info(' Loading time %0.3f sec' % (time() - t,)) logging.info("model file = ") logging.info(mb) recognized_bundle, labels = \ rb.recognize( model_bundle, model_clust_thr=model_clust_thr, reduction_thr=reduction_thr, reduction_distance=reduction_distance, pruning_thr=pruning_thr, pruning_distance=pruning_distance, slr=slr, slr_metric=slr_metric, slr_x0=slr_transform, slr_bounds=bounds, slr_select=slr_select, slr_method='L-BFGS-B') if refine: if len(recognized_bundle) > 1: # affine x0 = np.array([0, 0, 0, 0, 0, 0, 1., 1., 1, 0, 0, 0]) affine_bounds = [(-30, 30), (-30, 30), (-30, 30), (-45, 45), (-45, 45), (-45, 45), (0.8, 1.2), (0.8, 1.2), (0.8, 1.2), (-10, 10), (-10, 10), (-10, 10)] recognized_bundle, labels = \ rb.refine( model_bundle, recognized_bundle, model_clust_thr=model_clust_thr, reduction_thr=r_reduction_thr, reduction_distance=reduction_distance, pruning_thr=r_pruning_thr, pruning_distance=pruning_distance, slr=r_slr, slr_metric=slr_metric, slr_x0=x0, slr_bounds=affine_bounds, slr_select=slr_select, slr_method='L-BFGS-B') if len(labels) > 0: ba, bmd = rb.evaluate_results( model_bundle, recognized_bundle, slr_select) logging.info("Bundle adjacency Metric {0}".format(ba)) logging.info("Bundle Min Distance Metric {0}".format(bmd)) save_trk(out_rec, recognized_bundle, np.eye(4)) logging.info('Saving output files ...') np.save(out_labels, np.array(labels)) logging.info(out_rec) logging.info(out_labels)
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),