def streamlines_whole_brain_get(self, csapeaks, white_matter): '''Create seeds for fiber tracking from a binary mask, evenly distributed in all voxels of mask which are True seeds : points qui couvrent les coordonnées où il y a white matter Streamlines : set de streamlines. Chaque streamline est un array de 3xM. Chaque ligne correspond aux coordonnées xyz d'un point de la streamline. Et M (nbr de lignes) est le nbr de points qui composent la streamline. ''' print("extracting streamlines ...") affine = np.eye(4) seeds = utils.seeds_from_mask( white_matter, affine, density=1) # Create seeds for fiber tracking from a binary mask, # evenly distributed in all voxels of mask which are True # seeds : points qui couvrent les coordonnées où il y a white matter stopping_criterion = BinaryStoppingCriterion(white_matter) # stopping_criterion = ThresholdStoppingCriterion(csapeaks.gfa, .25) streamline_generator = LocalTracking(csapeaks, stopping_criterion, seeds, affine=affine, step_size=0.5) streamlines = Streamlines(streamline_generator) # # compress streamlines # from dipy.tracking.streamlinespeed import compress_streamlines # streamlines = compress_streamlines(streamlines, tol_error=0.2) return streamlines, affine
def test_binary_stopping_criterion(): """This tests that the binary stopping criterion returns expected streamline statuses. """ mask = np.random.random((4, 4, 4)) mask[mask < 0.4] = 0.0 btc_boolean = BinaryStoppingCriterion(mask > 0) btc_float64 = BinaryStoppingCriterion(mask) # Test voxel center for ind in ndindex(mask.shape): pts = np.array(ind, dtype='float64') state_boolean = btc_boolean.check_point(pts) state_float64 = btc_float64.check_point(pts) if mask[ind] > 0: npt.assert_equal(state_boolean, int(StreamlineStatus.TRACKPOINT)) npt.assert_equal(state_float64, int(StreamlineStatus.TRACKPOINT)) else: npt.assert_equal(state_boolean, int(StreamlineStatus.ENDPOINT)) npt.assert_equal(state_float64, int(StreamlineStatus.ENDPOINT)) # Test random points in voxel for ind in ndindex(mask.shape): for _ in range(50): pts = np.array(ind, dtype='float64') + np.random.random(3) - 0.5 state_boolean = btc_boolean.check_point(pts) state_float64 = btc_float64.check_point(pts) if mask[ind] > 0: npt.assert_equal(state_boolean, int(StreamlineStatus.TRACKPOINT)) npt.assert_equal(state_float64, int(StreamlineStatus.TRACKPOINT)) else: npt.assert_equal(state_boolean, int(StreamlineStatus.ENDPOINT)) npt.assert_equal(state_float64, int(StreamlineStatus.ENDPOINT)) # Test outside points outside_pts = [[100, 100, 100], [0, -1, 1], [0, 10, 2], [0, 0.5, -0.51], [0, -0.51, 0.1], [4, 0, 0]] for pts in outside_pts: pts = np.array(pts, dtype='float64') state_boolean = btc_boolean.check_point(pts) state_float64 = btc_float64.check_point(pts) npt.assert_equal(state_boolean, int(StreamlineStatus.OUTSIDEIMAGE)) npt.assert_equal(state_float64, int(StreamlineStatus.OUTSIDEIMAGE))
def loc_track(path, default_sphere, coords=None, npath=None, UParams=None, ang_thr=None): data, affine = load_nifti(path + 'data.nii.gz') data[np.isnan(data) == 1] = 0 mask, affine = load_nifti(path + 'nodif_brain_mask.nii.gz') mask[np.isnan(mask) == 1] = 0 mask[:, :, 1:] = 0 stopper = copy.deepcopy(mask) #stopper[:, :, :] = 1 gtab = gradient_table(path + 'bvals', path + 'bvecs') csa_model = CsaOdfModel(gtab, smooth=1, sh_order=12) peaks = peaks_from_model(csa_model, data, default_sphere, relative_peak_threshold=0.99, min_separation_angle=25, mask=mask) if ang_thr is not None: peaks.ang_thr = ang_thr if os.path.exists(path + 'grad_dev.nii.gz'): gd, affine_g = load_nifti(path + 'grad_dev.nii.gz') nmask, naffine = load_nifti(npath + 'nodif_brain_mask.nii.gz') nmask[np.isnan(nmask) == 1] = 0 nmask[:, :, 1:] = 0 seedss = copy.deepcopy(nmask) seedss = utils.seeds_from_mask(seedss, naffine, [2, 2, 2]) useed = [] UParams = coords.Uparams for seed in seedss: us = coords.rFUa_xyz(seed[0], seed[1], seed[2]) vs = coords.rFVa_xyz(seed[0], seed[1], seed[2]) ws = coords.rFWa_xyz(seed[0], seed[1], seed[2]) condition = us >= UParams.min_a and us <= UParams.max_a and vs >= UParams.min_b and vs <= UParams.max_b \ and ws >= UParams.min_c and ws <= UParams.max_c if condition == True: useed.append([float(us), float(vs), float(ws)]) seeds = np.asarray(useed) else: gd = None seedss = copy.deepcopy(mask) seeds = utils.seeds_from_mask(seedss, affine, [2, 2, 2]) stopping_criterion = BinaryStoppingCriterion(stopper) tracked = tracking(peaks, stopping_criterion, seeds, affine, graddev=gd, sphere=default_sphere) tracked.localTracking() return tracked
def prep_tracking(self): """Uses nibabel and dipy functions in order to load the grey matter, white matter, and csf masks and use a tissue classifier (act, cmc, or binary) on the include/exclude maps to make a tissueclassifier object Returns ------- ActStoppingCriterion, CmcStoppingCriterion, or BinaryStoppingCriterion The resulting tissue classifier object, depending on which method you use (currently only does act) """ if self.track_type == "local": tiss_class = "bin" elif self.track_type == "particle": tiss_class = "cmc" self.dwi_img = nib.load(self.dwi) self.data = self.dwi_img.get_data() # Loads mask and ensures it's a true binary mask self.mask_img = nib.load(self.nodif_B0_mask) self.mask = self.mask_img.get_data() > 0 # Load tissue maps and prepare tissue classifier self.gm_mask = nib.load(self.gm_in_dwi) self.gm_mask_data = self.gm_mask.get_data() self.wm_mask = nib.load(self.wm_in_dwi) self.wm_mask_data = self.wm_mask.get_data() self.wm_in_dwi_data = nib.load( self.wm_in_dwi).get_data().astype("bool") if tiss_class == "act": self.vent_csf_in_dwi = nib.load(self.vent_csf_in_dwi) self.vent_csf_in_dwi_data = self.vent_csf_in_dwi.get_data() self.background = np.ones(self.gm_mask.shape) self.background[(self.gm_mask_data + self.wm_mask_data + self.vent_csf_in_dwi_data) > 0] = 0 self.include_map = self.wm_mask_data self.include_map[self.background > 0] = 0 self.exclude_map = self.vent_csf_in_dwi_data self.tiss_classifier = ActStoppingCriterion( self.include_map, self.exclude_map) elif tiss_class == "bin": self.tiss_classifier = BinaryStoppingCriterion(self.wm_in_dwi_data) # self.tiss_classifier = BinaryStoppingCriterion(self.mask) elif tiss_class == "cmc": self.vent_csf_in_dwi = nib.load(self.vent_csf_in_dwi) self.vent_csf_in_dwi_data = self.vent_csf_in_dwi.get_data() voxel_size = np.average(self.wm_mask.get_header()["pixdim"][1:4]) step_size = 0.2 self.tiss_classifier = CmcStoppingCriterion.from_pve( self.wm_mask_data, self.gm_mask_data, self.vent_csf_in_dwi_data, step_size=step_size, average_voxel_size=voxel_size, ) else: pass return self.tiss_classifier
def test_closest_peak_tracker(): """This tests that the Closest Peak Direction Getter plays nice LocalTracking and produces reasonable streamlines in a simple example. """ sphere = HemiSphere.from_sphere(unit_octahedron) # A simple image with three possible configurations, a vertical tract, # a horizontal tract and a crossing pmf_lookup = np.array([[0., 0., 1.], [1., 0., 0.], [0., 1., 0.], [.5, .5, 0.]]) simple_image = np.array([[0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [2, 3, 2, 2, 2, 0], [0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], ]) simple_image = simple_image[..., None] pmf = pmf_lookup[simple_image] seeds = [np.array([1., 1., 0.]), np.array([2., 4., 0.])] mask = (simple_image > 0).astype(float) sc = BinaryStoppingCriterion(mask) dg = ClosestPeakDirectionGetter.from_pmf(pmf, 90, sphere, pmf_threshold=0.1) streamlines = Streamlines(LocalTracking(dg, sc, seeds, np.eye(4), 1.)) expected = [np.array([[0., 1., 0.], [1., 1., 0.], [2., 1., 0.], [3., 1., 0.], [4., 1., 0.]]), np.array([[2., 0., 0.], [2., 1., 0.], [2., 2., 0.], [2., 3., 0.], [2., 4., 0.]])] def allclose(x, y): return x.shape == y.shape and np.allclose(x, y) if not allclose(streamlines[0], expected[0]): raise AssertionError() if not allclose(streamlines[1], expected[1]): raise AssertionError()
def _core_run(self, stopping_path, use_binary_mask, stopping_thr, seeding_path, seed_density, step_size, direction_getter, out_tract, save_seeds): stop, affine = load_nifti(stopping_path) if use_binary_mask: stopping_criterion = BinaryStoppingCriterion(stop > stopping_thr) else: stopping_criterion = ThresholdStoppingCriterion(stop, stopping_thr) logging.info('stopping criterion done') seed_mask, _ = load_nifti(seeding_path) seeds = \ utils.seeds_from_mask( seed_mask, density=[seed_density, seed_density, seed_density], affine=affine) logging.info('seeds done') tracking_result = LocalTracking(direction_getter, stopping_criterion, seeds, affine, step_size=step_size, save_seeds=save_seeds) logging.info('LocalTracking initiated') if save_seeds: streamlines, seeds = zip(*tracking_result) seeds = {'seeds': seeds} else: streamlines = list(tracking_result) seeds = {} sft = StatefulTractogram(streamlines, seeding_path, Space.RASMM, data_per_streamline=seeds) save_tractogram(sft, out_tract, bbox_valid_check=False) logging.info('Saved {0}'.format(out_tract))
def fiber_tracking(subject): # declare the type of algorithm, \in [deterministic, probabilitic] algo = 'deterministic' # algo = 'probabilitic' ''' @param subject: string represents the subject name @param algo: the name for the algorithms, \in ['deterministic', 'probabilitic'] @return streamlines: for saving the final results and visualization ''' print('processing for', subject) fname, bval_fname, bvec_fname, label_fname = get_file_names(subject) data, sub_affine, img = load_nifti(fname, return_img=True) bvals, bvecs = read_bvals_bvecs(bval_fname, bvec_fname) gtab = gradient_table(bvals, bvecs) labels = load_nifti_data(label_fname) print('data loading complete.\n') ################################################################## # set mask(s) and seed(s) # global_mask = binary_dilation((data[:, :, :, 0] != 0)) global_mask = binary_dilation((labels == 1) | (labels == 2)) # global_mask = binary_dilation((labels == 2) | (labels == 32) | (labels == 76)) affine = np.eye(4) seeds = utils.seeds_from_mask(global_mask, affine, density=1) print('mask(s) and seed(s) set complete.\n') ################################################################## print('getting directions from diffusion dataset...') # define tracking mask with Constant Solid Angle (CSA) csamodel = CsaOdfModel(gtab, 6) stopping_criterion = BinaryStoppingCriterion(global_mask) # define direction criterion direction_criterion = None print('Compute directions...') if algo == "deterministic": # EuDX direction_criterion = peaks.peaks_from_model( model=csamodel, data=data, sphere=peaks.default_sphere, relative_peak_threshold=.8, min_separation_angle=45, mask=global_mask) # # Deterministic Algorithm (select direction with max probability) # direction_criterion = DeterministicMaximumDirectionGetter.from_shcoeff( # csd_fit.shm_coeff, # max_angle=30., # sphere=default_sphere) else: response, ratio = auto_response(gtab, data, roi_radius=10, fa_thr=0.7) # fit the reconstruction model with Constrained Spherical Deconvolusion (CSD) csd_model = ConstrainedSphericalDeconvModel(gtab, response, sh_order=6) csd_fit = csd_model.fit(data, mask=global_mask) # gfa = csamodel.fit(data, mask=global_mask).gfa # stopping_criterion = ThresholdStoppingCriterion(gfa, .25) # Probabilitic Algorithm direction_criterion = ProbabilisticDirectionGetter.from_shcoeff( csd_fit.shm_coeff, max_angle=30., sphere=default_sphere) print('direction computation complete.\n') ################################################################## print('start tracking process...') # start tracking streamline_generator = LocalTracking(direction_criterion, stopping_criterion, seeds, affine=affine, step_size=0.5) # Generate streamlines object streamlines = Streamlines(streamline_generator) sft = StatefulTractogram(streamlines, img, Space.RASMM) print('traking complete.\n') ################################################################## return { "subject": subject, "streamlines": streamlines, "sft": sft, "affine": sub_affine, "data": data, "img": img, "labels": labels }
def prep_tissues(t1_mask, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, B0_mask, cmc_step_size=0.2): """ Estimate a tissue classifier for tractography. Parameters ---------- t1_mask : Nifti1Image T1w mask img. gm_in_dwi : Nifti1Image Grey-matter tissue segmentation Nifti1Image. vent_csf_in_dwi : Nifti1Image Ventricular CSF tissue segmentation Nifti1Image. wm_in_dwi : Nifti1Image White-matter tissue segmentation Nifti1Image. tiss_class : str Tissue classification method. cmc_step_size : float Step size from CMC tissue classification method. Returns ------- tiss_classifier : obj Tissue classifier object. References ---------- .. [1] Zhang, Y., Brady, M. and Smith, S. Segmentation of Brain MR Images Through a Hidden Markov Random Field Model and the Expectation-Maximization Algorithm IEEE Transactions on Medical Imaging, 20(1): 45-56, 2001 .. [2] Avants, B. B., Tustison, N. J., Wu, J., Cook, P. A. and Gee, J. C. An open source multivariate framework for n-tissue segmentation with evaluation on public data. Neuroinformatics, 9(4): 381-400, 2011. """ import gc from dipy.tracking.stopping_criterion import ( ActStoppingCriterion, CmcStoppingCriterion, BinaryStoppingCriterion, ) from nilearn.masking import intersect_masks from nilearn.image import math_img # Load B0 mask B0_mask_img = math_img("img > 0.01", img=B0_mask) # Load t1 mask mask_img = math_img("img > 0.01", img=t1_mask) # Load tissue maps and prepare tissue classifier wm_mask_img = math_img("img > 0.01", img=wm_in_dwi) gm_mask_img = math_img("img > 0.01", img=gm_in_dwi) vent_csf_in_dwi_img = math_img("img > 0.01", img=vent_csf_in_dwi) gm_data = np.asarray(gm_mask_img.dataobj, dtype=np.float32) wm_data = np.asarray(wm_mask_img.dataobj, dtype=np.float32) vent_csf_in_dwi_data = np.asarray(vent_csf_in_dwi_img.dataobj, dtype=np.float32) if tiss_class == "act": background = np.ones(mask_img.shape) background[(gm_data + wm_data + vent_csf_in_dwi_data) > 0] = 0 gm_data[background > 0] = 1 tiss_classifier = ActStoppingCriterion(gm_data, vent_csf_in_dwi_data) del background elif tiss_class == "wm": tiss_classifier = BinaryStoppingCriterion( np.asarray( intersect_masks( [ mask_img, wm_mask_img, B0_mask_img, nib.Nifti1Image(np.invert( vent_csf_in_dwi_data.astype('bool')).astype('int'), affine=mask_img.affine) ], threshold=1, connected=False, ).dataobj)) elif tiss_class == "cmc": tiss_classifier = CmcStoppingCriterion.from_pve( wm_data, gm_data, vent_csf_in_dwi_data, step_size=cmc_step_size, average_voxel_size=np.average(mask_img.header["pixdim"][1:4]), ) elif tiss_class == "wb": tiss_classifier = BinaryStoppingCriterion( np.asarray( intersect_masks( [ mask_img, B0_mask_img, nib.Nifti1Image(np.invert( vent_csf_in_dwi_data.astype('bool')).astype('int'), affine=mask_img.affine), ], threshold=1, connected=False, ).dataobj)) else: raise ValueError("Tissue classifier cannot be none.") B0_mask_img.uncache() mask_img.uncache() wm_mask_img.uncache() gm_mask_img.uncache() del gm_data, wm_data, vent_csf_in_dwi_data gc.collect() return tiss_classifier
csapeaks = peaks.peaks_from_model(model=csamodel, data=data, sphere=peaks.default_sphere, relative_peak_threshold=.8, min_separation_angle=45, mask=white_matter) """ Now we can use EuDX to track all of the white matter. To keep things reasonably fast we use ``density=1`` which will result in 1 seeds per voxel. The stopping criterion, determining when the tracking stops, is set to stop when the tracking exit the white matter. """ seeds = utils.seeds_from_mask(white_matter, density=1) stopping_criterion = BinaryStoppingCriterion(white_matter) affine = np.eye(4) streamline_generator = LocalTracking(csapeaks, stopping_criterion, seeds, affine=affine, step_size=0.5) streamlines = Streamlines(streamline_generator) """ The first of the tracking utilities we'll cover here is ``target``. This function takes a set of streamlines and a region of interest (ROI) and returns only those streamlines that pass though the ROI. The ROI should be an array such that the voxels that belong to the ROI are ``True`` and all other voxels are ``False`` (this type of binary array is sometimes called a mask). This function can also exclude all the streamlines that pass though an ROI by setting the ``include`` flag to ``False``. In this example we'll target the streamlines of the corpus callosum. Our ``labels`` array has a sagittal slice
def tractography_estimation_data(dmri_estimation_data): path_tmp = tempfile.NamedTemporaryFile(mode='w+', suffix='.trk', delete=False) trk_path_tmp = str(path_tmp.name) dir_path = os.path.dirname(trk_path_tmp) gtab = dmri_estimation_data['gtab'] wm_img = nib.load(dmri_estimation_data['f_pve_wm']) dwi_img = nib.load(dmri_estimation_data['dwi_file']) dwi_data = dwi_img.get_fdata() B0_mask_img = nib.load(dmri_estimation_data['B0_mask']) mask_img = intersect_masks( [ nib.Nifti1Image(np.asarray( wm_img.dataobj).astype('bool').astype('int'), affine=wm_img.affine), nib.Nifti1Image(np.asarray( B0_mask_img.dataobj).astype('bool').astype('int'), affine=B0_mask_img.affine) ], threshold=1, connected=False, ) mask_data = mask_img.get_fdata() mask_file = fname_presuffix(dmri_estimation_data['B0_mask'], suffix="tracking_mask", use_ext=True) mask_img.to_filename(mask_file) csa_model = CsaOdfModel(gtab, sh_order=6) csa_peaks = peaks_from_model(csa_model, dwi_data, default_sphere, relative_peak_threshold=.8, min_separation_angle=45, mask=mask_data) stopping_criterion = BinaryStoppingCriterion(mask_data) seed_mask = (mask_data == 1) seeds = seeds_from_mask(seed_mask, dwi_img.affine, density=[1, 1, 1]) streamlines_generator = LocalTracking(csa_peaks, stopping_criterion, seeds, affine=dwi_img.affine, step_size=.5) streamlines = Streamlines(streamlines_generator) sft = StatefulTractogram(streamlines, B0_mask_img, origin=Origin.NIFTI, space=Space.VOXMM) sft.remove_invalid_streamlines() trk = f"{dir_path}/tractogram.trk" os.rename(trk_path_tmp, trk) save_tractogram(sft, trk, bbox_valid_check=False) del streamlines, sft, streamlines_generator, seeds, seed_mask, csa_peaks, \ csa_model, dwi_data, mask_data dwi_img.uncache() mask_img.uncache() gc.collect() yield {'trk': trk, 'mask': mask_file}
def prep_tissues(B0_mask, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, cmc_step_size=0.2): """ Estimate a tissue classifier for tractography. Parameters ---------- B0_mask : str File path to B0 brain mask. gm_in_dwi : str File path to grey-matter tissue segmentation Nifti1Image. vent_csf_in_dwi : str File path to ventricular CSF tissue segmentation Nifti1Image. wm_in_dwi : str File path to white-matter tissue segmentation Nifti1Image. tiss_class : str Tissue classification method. cmc_step_size : float Step size from CMC tissue classification method. Returns ------- tiss_classifier : obj Tissue classifier object. """ try: import cPickle as pickle except ImportError: import _pickle as pickle from dipy.tracking.stopping_criterion import ActStoppingCriterion, CmcStoppingCriterion, BinaryStoppingCriterion # Loads mask and ensures it's a true binary mask mask_img = nib.load(B0_mask) # Load tissue maps and prepare tissue classifier gm_mask_data = nib.load(gm_in_dwi).get_fdata() wm_mask_data = nib.load(wm_in_dwi).get_fdata() vent_csf_in_dwi_data = nib.load(vent_csf_in_dwi).get_fdata() if tiss_class == 'act': background = np.ones(mask_img.shape) background[(gm_mask_data + wm_mask_data + vent_csf_in_dwi_data) > 0] = 0 include_map = gm_mask_data include_map[background > 0] = 1 tiss_classifier = ActStoppingCriterion(include_map, vent_csf_in_dwi_data) del background del include_map elif tiss_class == 'bin': tiss_classifier = BinaryStoppingCriterion(wm_mask_data.astype('bool')) elif tiss_class == 'cmc': voxel_size = np.average(mask_img.header['pixdim'][1:4]) tiss_classifier = CmcStoppingCriterion.from_pve( wm_mask_data, gm_mask_data, vent_csf_in_dwi_data, step_size=cmc_step_size, average_voxel_size=voxel_size) elif tiss_class == 'wb': tiss_classifier = BinaryStoppingCriterion( mask_img.get_fdata().astype('bool')) else: raise ValueError('Tissue Classifier cannot be none.') del gm_mask_data, wm_mask_data, vent_csf_in_dwi_data mask_img.uncache() return tiss_classifier
def run_tractography(fdwi, fbval, fbvec, fwmparc, mod_func, mod_type, seed_density=20): """ mod_func : 'str' 'csd' or 'csa' mod_type : 'str' 'det' or 'prob' seed_density : int, default=20 Seeding density for tractography """ # Getting default params sphere = get_sphere("repulsion724") stream_affine = np.eye(4) # Loading data print("Loading Data...") dwi, gtab, wm_mask = load_data(fdwi, fbval, fbvec, fwmparc) # Make tissue classifier tiss_classifier = BinaryStoppingCriterion(wm_mask) if mod_func == "csd": mod = csd_mod_est(gtab, dwi, wm_mask) elif mod_func == "csa": mod = odf_mod_est(gtab) # Build seed list seeds = utils.random_seeds_from_mask( wm_mask, affine=stream_affine, seeds_count=int(seed_density), seed_count_per_voxel=True, ) # Make streamlines if mod_type == "det": print("Obtaining peaks from model...") direction_getter = peaks_from_model( mod, dwi, sphere, relative_peak_threshold=0.5, min_separation_angle=25, mask=wm_mask, npeaks=5, normalize_peaks=True, ) elif mod_type == "prob": print("Preparing probabilistic tracking...") print("Fitting model to data...") mod_fit = mod.fit(dwi, wm_mask) print("Building direction-getter...") try: print( "Proceeding using spherical harmonic coefficient from model estimation..." ) direction_getter = ProbabilisticDirectionGetter.from_shcoeff( mod_fit.shm_coeff, max_angle=60.0, sphere=sphere) except: print("Proceeding using FOD PMF from model estimation...") fod = mod_fit.odf(sphere) pmf = fod.clip(min=0) direction_getter = ProbabilisticDirectionGetter.from_pmf( pmf, max_angle=60.0, sphere=sphere) print("Running Local Tracking") streamline_generator = LocalTracking( direction_getter, tiss_classifier, seeds, stream_affine, step_size=0.5, return_all=True, ) print("Reconstructing tractogram streamlines...") streamlines = Streamlines(streamline_generator) tracks = Streamlines([track for track in streamlines if len(track) > 60]) return tracks
def QCSA_tractmake(data, affine, vox_size, gtab, mask, masktype, header, step_size, peak_processes, outpathtrk, subject='NA', ratio=1, overwrite=False, get_params=False, doprune=False, figspath=None, verbose=None): # Compute odfs in Brain Mask t2 = time() if os.path.isfile(outpathtrk) and not overwrite: txt = "Subject already saved at "+outpathtrk print(txt) streamlines_generator = None params = None return outpathtrk, streamlines_generator, params csa_model = CsaOdfModel(gtab, 6) if peak_processes == 1: parallel = False else: parallel = True if verbose: send_mail("Starting calculation of Constant solid angle model for subject " + subject,subject="CSA model start") wholemask = np.where(mask == 0, False, True) print(f"There are {peak_processes} and {parallel} here") csa_peaks = peaks_from_model(model=csa_model, data=data, sphere=peaks.default_sphere, # issue with complete sphere mask=wholemask, relative_peak_threshold=.5, min_separation_angle=25, parallel=parallel, nbr_processes=peak_processes) duration = time() - t2 if verbose: print(subject + ' CSA duration %.3f' % (duration,)) t3 = time() if verbose: send_mail('Computing classifier for local tracking for subject ' + subject + ',it has been ' + str(round(duration)) + 'seconds since the start of tractmaker',subject="Seed computation" ) print('Computing classifier for local tracking for subject ' + subject) if masktype == "FA": #tensor_model = dti.TensorModel(gtab) #tenfit = tensor_model.fit(data, mask=labels > 0) #FA = fractional_anisotropy(tenfit.evals) FA_threshold = 0.05 classifier = ThresholdStoppingCriterion(mask, FA_threshold) if figspath is not None: fig = plt.figure() mask_fa = mask.copy() mask_fa[mask_fa < FA_threshold] = 0 plt.xticks([]) plt.yticks([]) plt.imshow(mask_fa[:, :, data.shape[2] // 2].T, cmap='gray', origin='lower', interpolation='nearest') fig.tight_layout() fig.savefig(figspath + 'threshold_fa.png') else: classifier = BinaryStoppingCriterion(wholemask) # generates about 2 seeds per voxel # seeds = utils.random_seeds_from_mask(fa > .2, seeds_count=2, # affine=np.eye(4)) # generates about 2 million streamlines # seeds = utils.seeds_from_mask(fa > .2, density=1, # affine=np.eye(4)) if verbose: print('Computing seeds') seeds = utils.seeds_from_mask(wholemask, density=1, affine=np.eye(4)) #streamlines_generator = local_tracking.local_tracker(csa_peaks,classifier,seeds,affine=np.eye(4),step_size=step_size) if verbose: print('Computing the local tracking') duration = time() - t2 send_mail('Start of the local tracking ' + ',it has been ' + str(round(duration)) + 'seconds since the start of tractmaker', subject="Seed computation") #stepsize = 2 #(by default) stringstep = str(step_size) stringstep = stringstep.replace(".", "_") if verbose: print("stringstep is "+stringstep) streamlines_generator = LocalTracking(csa_peaks, classifier, seeds, affine=np.eye(4), step_size=step_size) if verbose: duration = time() - t2 txt = 'About to save streamlines at ' + outpathtrk + ',it has been ' + str(round(duration)) + \ 'seconds since the start of tractmaker', send_mail(txt,subject="Tract saving" ) cutoff = 2 if doprune: streamlines_generator = prune_streamlines(list(streamlines_generator), data[:, :, :, 0], cutoff=cutoff, verbose=verbose) myheader = create_tractogram_header(outpathtrk, *header) sg = lambda: (s for i, s in enumerate(streamlines_generator) if i % ratio == 0) save_trk_heavy_duty(outpathtrk, streamlines=sg, affine=affine, header=myheader, shape=mask.shape, vox_size=vox_size) else: sg = lambda: (s for i, s in enumerate(streamlines_generator) if i % ratio == 0) myheader = create_tractogram_header(outpathtrk, *header) save_trk_heavy_duty(outpathtrk, streamlines=sg, affine=affine, header=myheader, shape=mask.shape, vox_size=vox_size) if verbose: duration = time() - t2 txt = "Tract files were saved at "+outpathtrk + ',it has been ' + str(round(duration)) + \ 'seconds since the start of tractmaker' print(txt) send_mail(txt,subject="Tract saving" ) # save everything - will generate a 20+ GBytes of data - hard to manipulate # possibly add parameter in csv file or other to decide whether to save large tractogram file # outpathfile=outpath+subject+"bmCSA_detr"+stringstep+".trk" # myheader=create_tractogram_header(outpathfile,*get_reference_info(fdwi)) duration3 = time() - t2 if verbose: print(duration3) print(subject + ' Tracking duration %.3f' % (duration3,)) send_mail("Finished file save at "+outpathtrk+" with tracking duration of " + str(duration3) + "seconds", subject="file save update" ) if get_params: numtracts, minlength, maxlength, meanlength, stdlength = get_trk_params(streamlines_generator, verbose) params = [numtracts, minlength, maxlength, meanlength, stdlength] if verbose: print("For subject " + str(subject) + " the number of tracts is " + str(numtracts) + ", the minimum length is " + str(minlength) + ", the maximum length is " + str(maxlength) + ", the mean length is " + str(meanlength) + ", the std is " + str(stdlength)) else: params = None return outpathtrk, streamlines_generator, params
def test_affine_transformations(): """This tests that the input affine is properly handled by LocalTracking and produces reasonable streamlines in a simple example. """ sphere = HemiSphere.from_sphere(unit_octahedron) # A simple image with three possible configurations, a vertical tract, # a horizontal tract and a crossing pmf_lookup = np.array([[0., 0., 1.], [1., 0., 0.], [0., 1., 0.], [.4, .6, 0.]]) simple_image = np.array([ [0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 3, 2, 2, 2, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], ]) simple_image = simple_image[..., None] pmf = pmf_lookup[simple_image] seeds = [np.array([1., 1., 0.]), np.array([2., 4., 0.])] expected = [ np.array([[1., 1., 0.], [2., 1., 0.], [3., 1., 0.]]), np.array([[2., 1., 0.], [2., 2., 0.], [2., 3., 0.], [2., 4., 0.]]) ] mask = (simple_image > 0).astype(float) sc = BinaryStoppingCriterion(mask) dg = DeterministicMaximumDirectionGetter.from_pmf(pmf, 60, sphere, pmf_threshold=0.1) # TST- bad affine wrong shape bad_affine = np.eye(3) npt.assert_raises(ValueError, LocalTracking, dg, sc, seeds, bad_affine, 1.) # TST - bad affine with shearing bad_affine = np.eye(4) bad_affine[0, 1] = 1. npt.assert_raises(ValueError, LocalTracking, dg, sc, seeds, bad_affine, 1.) # TST - bad seeds bad_seeds = 1000 npt.assert_raises(ValueError, LocalTracking, dg, sc, bad_seeds, np.eye(4), 1.) # TST - identity a0 = np.eye(4) # TST - affines with positive/negative offsets a1 = np.eye(4) a1[:3, 3] = [1, 2, 3] a2 = np.eye(4) a2[:3, 3] = [-2, 0, -1] # TST - affine with scaling a3 = np.eye(4) a3[0, 0] = a3[1, 1] = a3[2, 2] = 8 # TST - affine with axes inverting (negative value) a4 = np.eye(4) a4[1, 1] = a4[2, 2] = -1 # TST - combined affines a5 = a1 + a2 + a3 a5[3, 3] = 1 # TST - in vivo affine example # Sometimes data have affines with tiny shear components. # For example, the small_101D data-set has some of that: fdata, _, _ = get_fnames('small_101D') a6 = nib.load(fdata).affine for affine in [a0, a1, a2, a3, a4, a5, a6]: lin = affine[:3, :3] offset = affine[:3, 3] seeds_trans = [np.dot(lin, s) + offset for s in seeds] # We compute the voxel size to adjust the step size to one voxel voxel_size = np.mean(np.sqrt(np.dot(lin, lin).diagonal())) streamlines = LocalTracking(direction_getter=dg, stopping_criterion=sc, seeds=seeds_trans, affine=affine, step_size=voxel_size, return_all=True) # We apply the inverse affine transformation to the generated # streamlines. It should be equals to the expected streamlines # (generated with the identity affine matrix). affine_inv = np.linalg.inv(affine) lin = affine_inv[:3, :3] offset = affine_inv[:3, 3] streamlines_inv = [] for line in streamlines: streamlines_inv.append([np.dot(pts, lin) + offset for pts in line]) npt.assert_equal(len(streamlines_inv[0]), len(expected[0])) npt.assert_(np.allclose(streamlines_inv[0], expected[0], atol=0.3)) npt.assert_equal(len(streamlines_inv[1]), len(expected[1])) npt.assert_(np.allclose(streamlines_inv[1], expected[1], atol=0.3))
def test_particle_filtering_tractography(): """This tests that the ParticleFilteringTracking produces more streamlines connecting the gray matter than LocalTracking. """ sphere = get_sphere('repulsion100') step_size = 0.2 # Simple tissue masks simple_wm = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0]]) simple_wm = np.dstack([ np.zeros(simple_wm.shape), simple_wm, simple_wm, simple_wm, np.zeros(simple_wm.shape) ]) simple_gm = np.array([[1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0], [0, 1, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0]]) simple_gm = np.dstack([ np.zeros(simple_gm.shape), simple_gm, simple_gm, simple_gm, np.zeros(simple_gm.shape) ]) simple_csf = np.ones(simple_wm.shape) - simple_wm - simple_gm sc = ActStoppingCriterion.from_pve(simple_wm, simple_gm, simple_csf) seeds = seeds_from_mask(simple_wm, np.eye(4), density=2) # Random pmf in every voxel shape_img = list(simple_wm.shape) shape_img.extend([sphere.vertices.shape[0]]) np.random.seed(0) # Random number generator initialization pmf = np.random.random(shape_img) # Test that PFT recover equal or more streamlines than localTracking dg = ProbabilisticDirectionGetter.from_pmf(pmf, 60, sphere) local_streamlines_generator = LocalTracking(dg, sc, seeds, np.eye(4), step_size, max_cross=1, return_all=False) local_streamlines = Streamlines(local_streamlines_generator) pft_streamlines_generator = ParticleFilteringTracking( dg, sc, seeds, np.eye(4), step_size, max_cross=1, return_all=False, pft_back_tracking_dist=1, pft_front_tracking_dist=0.5) pft_streamlines = Streamlines(pft_streamlines_generator) npt.assert_(np.array([len(pft_streamlines) > 0])) npt.assert_(np.array([len(pft_streamlines) >= len(local_streamlines)])) # Test that all points are equally spaced for l in [1, 2, 5, 10, 100]: pft_streamlines = ParticleFilteringTracking(dg, sc, seeds, np.eye(4), step_size, max_cross=1, return_all=True, maxlen=l) for s in pft_streamlines: for i in range(len(s) - 1): npt.assert_almost_equal(np.linalg.norm(s[i] - s[i + 1]), step_size) # Test that all points are within the image volume seeds = seeds_from_mask(np.ones(simple_wm.shape), np.eye(4), density=1) pft_streamlines_generator = ParticleFilteringTracking(dg, sc, seeds, np.eye(4), step_size, max_cross=1, return_all=True) pft_streamlines = Streamlines(pft_streamlines_generator) for s in pft_streamlines: npt.assert_(np.all((s + 0.5).astype(int) >= 0)) npt.assert_(np.all((s + 0.5).astype(int) < simple_wm.shape)) # Test that the number of streamline return with return_all=True equal the # number of seeds places npt.assert_(np.array([len(pft_streamlines) == len(seeds)])) # Test non WM seed position seeds = [[0, 5, 4], [0, 0, 1], [50, 50, 50]] pft_streamlines_generator = ParticleFilteringTracking(dg, sc, seeds, np.eye(4), step_size, max_cross=1, return_all=True) pft_streamlines = Streamlines(pft_streamlines_generator) npt.assert_equal(len(pft_streamlines[0]), 3) # INVALIDPOINT npt.assert_equal(len(pft_streamlines[1]), 3) # ENDPOINT npt.assert_equal(len(pft_streamlines[2]), 1) # OUTSIDEIMAGE # Test with wrong StoppingCriterion type sc_bin = BinaryStoppingCriterion(simple_wm) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, sc_bin, seeds, np.eye(4), step_size)) # Test with invalid back/front tracking distances npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, sc, seeds, np.eye(4), step_size, pft_back_tracking_dist=0, pft_front_tracking_dist=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, sc, seeds, np.eye(4), step_size, pft_back_tracking_dist=-1)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, sc, seeds, np.eye(4), step_size, pft_back_tracking_dist=0, pft_front_tracking_dist=-2)) # Test with invalid affine shape npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, sc, seeds, np.eye(3), step_size)) # Test with invalid maxlen npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, sc, seeds, np.eye(4), step_size, maxlen=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, sc, seeds, np.eye(4), step_size, maxlen=-1)) # Test with invalid particle count npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, sc, seeds, np.eye(4), step_size, particle_count=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, sc, seeds, np.eye(4), step_size, particle_count=-1)) # Test reproducibility tracking1 = Streamlines( ParticleFilteringTracking(dg, sc, seeds, np.eye(4), step_size, random_seed=0))._data tracking2 = Streamlines( ParticleFilteringTracking(dg, sc, seeds, np.eye(4), step_size, random_seed=0))._data npt.assert_equal(tracking1, tracking2)
def prep_tissues(t1_mask, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, cmc_step_size=0.2): """ Estimate a tissue classifier for tractography. Parameters ---------- t1_mask : str File path to a T1w mask. gm_in_dwi : str File path to grey-matter tissue segmentation Nifti1Image. vent_csf_in_dwi : str File path to ventricular CSF tissue segmentation Nifti1Image. wm_in_dwi : str File path to white-matter tissue segmentation Nifti1Image. tiss_class : str Tissue classification method. cmc_step_size : float Step size from CMC tissue classification method. Returns ------- tiss_classifier : obj Tissue classifier object. References ---------- .. [1] Zhang, Y., Brady, M. and Smith, S. Segmentation of Brain MR Images Through a Hidden Markov Random Field Model and the Expectation-Maximization Algorithm IEEE Transactions on Medical Imaging, 20(1): 45-56, 2001 .. [2] Avants, B. B., Tustison, N. J., Wu, J., Cook, P. A. and Gee, J. C. An open source multivariate framework for n-tissue segmentation with evaluation on public data. Neuroinformatics, 9(4): 381-400, 2011. """ try: import cPickle as pickle except ImportError: import _pickle as pickle from dipy.tracking.stopping_criterion import ActStoppingCriterion, CmcStoppingCriterion, BinaryStoppingCriterion from nilearn.masking import intersect_masks from nilearn.image import math_img # Loads mask mask_img = nib.load(t1_mask) # Load tissue maps and prepare tissue classifier wm_img = nib.load(wm_in_dwi) gm_img = nib.load(gm_in_dwi) gm_mask_data = np.asarray(gm_img.dataobj) wm_mask_data = np.asarray(wm_img.dataobj) vent_csf_in_dwi_data = np.asarray(nib.load(vent_csf_in_dwi).dataobj) if tiss_class == 'act': background = np.ones(mask_img.shape) background[(gm_mask_data + wm_mask_data + vent_csf_in_dwi_data) > 0] = 0 gm_mask_data[background > 0] = 1 tiss_classifier = ActStoppingCriterion(gm_mask_data, vent_csf_in_dwi_data) del background elif tiss_class == 'bin': tiss_classifier = BinaryStoppingCriterion(np.asarray(intersect_masks([math_img('img > 0.0', img=mask_img), math_img('img > 0.0', img=wm_img)], threshold=1, connected=False).dataobj)) elif tiss_class == 'cmc': voxel_size = np.average(mask_img.header['pixdim'][1:4]) tiss_classifier = CmcStoppingCriterion.from_pve(wm_mask_data, gm_mask_data, vent_csf_in_dwi_data, step_size=cmc_step_size, average_voxel_size=voxel_size) elif tiss_class == 'wb': tiss_classifier = BinaryStoppingCriterion(np.asarray(mask_img.dataobj).astype('bool')) else: raise ValueError('Tissue classifier cannot be none.') del gm_mask_data, wm_mask_data, vent_csf_in_dwi_data mask_img.uncache() gm_img.uncache() wm_img.uncache() return tiss_classifier
def main(): parser = _build_arg_parser() args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.DEBUG) assert_inputs_exist(parser, [args.sh_file, args.seed_file, args.mask_file]) assert_outputs_exist(parser, args, args.output_file) if not nib.streamlines.is_supported(args.output_file): parser.error('Invalid output streamline file format (must be trk or ' + 'tck): {0}'.format(args.output_file)) if not args.min_length > 0: parser.error('minL must be > 0, {}mm was provided.'.format( args.min_length)) if args.max_length < args.min_length: parser.error( 'maxL must be > than minL, (minL={}mm, maxL={}mm).'.format( args.min_length, args.max_length)) if args.compress: if args.compress < 0.001 or args.compress > 1: logging.warning( 'You are using an error rate of {}.\nWe recommend setting it ' 'between 0.001 and 1.\n0.001 will do almost nothing to the ' 'tracts while 1 will higly compress/linearize the tracts'. format(args.compress)) if args.npv and args.npv <= 0: parser.error('Number of seeds per voxel must be > 0.') if args.nt and args.nt <= 0: parser.error('Total number of seeds must be > 0.') mask_img = nib.load(args.mask_file) mask_data = mask_img.get_fdata() # Make sure the mask is isotropic. Else, the strategy used # when providing information to dipy (i.e. working as if in voxel space) # will not yield correct results. fodf_sh_img = nib.load(args.sh_file) if not np.allclose(np.mean(fodf_sh_img.header.get_zooms()[:3]), fodf_sh_img.header.get_zooms()[0], atol=1.e-3): parser.error( 'SH file is not isotropic. Tracking cannot be ran robustly.') if args.npv: nb_seeds = args.npv seed_per_vox = True elif args.nt: nb_seeds = args.nt seed_per_vox = False else: nb_seeds = 1 seed_per_vox = True voxel_size = fodf_sh_img.header.get_zooms()[0] vox_step_size = args.step_size / voxel_size seed_img = nib.load(args.seed_file) seeds = track_utils.random_seeds_from_mask( seed_img.get_fdata(), np.eye(4), seeds_count=nb_seeds, seed_count_per_voxel=seed_per_vox, random_seed=args.seed) # Tracking is performed in voxel space max_steps = int(args.max_length / args.step_size) + 1 streamlines = LocalTracking(_get_direction_getter(args, mask_data), BinaryStoppingCriterion(mask_data), seeds, np.eye(4), step_size=vox_step_size, max_cross=1, maxlen=max_steps, fixedstep=True, return_all=True, random_seed=args.seed, save_seeds=args.save_seeds) scaled_min_length = args.min_length / voxel_size scaled_max_length = args.max_length / voxel_size if args.save_seeds: filtered_streamlines, seeds = \ zip(*((s, p) for s, p in streamlines if scaled_min_length <= length(s) <= scaled_max_length)) data_per_streamlines = {'seeds': lambda: seeds} else: filtered_streamlines = \ (s for s in streamlines if scaled_min_length <= length(s) <= scaled_max_length) data_per_streamlines = {} if args.compress: filtered_streamlines = (compress_streamlines(s, args.compress) for s in filtered_streamlines) tractogram = LazyTractogram(lambda: filtered_streamlines, data_per_streamlines, affine_to_rasmm=seed_img.affine) filetype = nib.streamlines.detect_format(args.output_file) header = create_header_from_anat(seed_img, base_filetype=filetype) # Use generator to save the streamlines on-the-fly nib.streamlines.save(tractogram, args.output_file, header=header)
def main(): parser = _build_arg_parser() args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.DEBUG) assert_inputs_exist(parser, [args.in_odf, args.in_seed, args.in_mask]) assert_outputs_exist(parser, args, args.out_tractogram) if not nib.streamlines.is_supported(args.out_tractogram): parser.error('Invalid output streamline file format (must be trk or ' + 'tck): {0}'.format(args.out_tractogram)) verify_streamline_length_options(parser, args) verify_compression_th(args.compress) verify_seed_options(parser, args) mask_img = nib.load(args.in_mask) mask_data = get_data_as_mask(mask_img, dtype=bool) # Make sure the data is isotropic. Else, the strategy used # when providing information to dipy (i.e. working as if in voxel space) # will not yield correct results. odf_sh_img = nib.load(args.in_odf) if not np.allclose(np.mean(odf_sh_img.header.get_zooms()[:3]), odf_sh_img.header.get_zooms()[0], atol=1e-03): parser.error( 'ODF SH file is not isotropic. Tracking cannot be ran robustly.') if args.npv: nb_seeds = args.npv seed_per_vox = True elif args.nt: nb_seeds = args.nt seed_per_vox = False else: nb_seeds = 1 seed_per_vox = True voxel_size = odf_sh_img.header.get_zooms()[0] vox_step_size = args.step_size / voxel_size seed_img = nib.load(args.in_seed) seeds = track_utils.random_seeds_from_mask( seed_img.get_fdata(dtype=np.float32), np.eye(4), seeds_count=nb_seeds, seed_count_per_voxel=seed_per_vox, random_seed=args.seed) # Tracking is performed in voxel space max_steps = int(args.max_length / args.step_size) + 1 streamlines_generator = LocalTracking( _get_direction_getter(args), BinaryStoppingCriterion(mask_data), seeds, np.eye(4), step_size=vox_step_size, max_cross=1, maxlen=max_steps, fixedstep=True, return_all=True, random_seed=args.seed, save_seeds=args.save_seeds) scaled_min_length = args.min_length / voxel_size scaled_max_length = args.max_length / voxel_size if args.save_seeds: filtered_streamlines, seeds = \ zip(*((s, p) for s, p in streamlines_generator if scaled_min_length <= length(s) <= scaled_max_length)) data_per_streamlines = {'seeds': lambda: seeds} else: filtered_streamlines = \ (s for s in streamlines_generator if scaled_min_length <= length(s) <= scaled_max_length) data_per_streamlines = {} if args.compress: filtered_streamlines = ( compress_streamlines(s, args.compress) for s in filtered_streamlines) tractogram = LazyTractogram(lambda: filtered_streamlines, data_per_streamlines, affine_to_rasmm=seed_img.affine) filetype = nib.streamlines.detect_format(args.out_tractogram) reference = get_reference_info(seed_img) header = create_tractogram_header(filetype, *reference) # Use generator to save the streamlines on-the-fly nib.streamlines.save(tractogram, args.out_tractogram, header=header)
def test_bootstap_peak_tracker(): """This tests that the Bootstrat Peak Direction Getter plays nice LocalTracking and produces reasonable streamlines in a simple example. """ sphere = get_sphere('repulsion100') # A simple image with three possible configurations, a vertical tract, # a horizontal tract and a crossing simple_image = np.array([ [0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [2, 3, 2, 2, 2, 0], [0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], ]) simple_image = simple_image[..., None] bvecs = sphere.vertices bvals = np.ones(len(bvecs)) * 1000 bvecs = np.insert(bvecs, 0, np.array([0, 0, 0]), axis=0) bvals = np.insert(bvals, 0, 0) gtab = gradient_table(bvals, bvecs) angles = [(90, 90), (90, 0)] fracs = [50, 50] mevals = np.array([[1.5, 0.4, 0.4], [1.5, 0.4, 0.4]]) * 1e-3 mevecs = [ np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]), np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) ] voxel1 = single_tensor(gtab, 1, mevals[0], mevecs[0], snr=None) voxel2 = single_tensor(gtab, 1, mevals[0], mevecs[1], snr=None) voxel3, _ = multi_tensor(gtab, mevals, fractions=fracs, angles=angles, snr=None) data = np.tile(voxel3, [5, 6, 1, 1]) data[simple_image == 1] = voxel1 data[simple_image == 2] = voxel2 response = (np.array(mevals[1]), 1) csd_model = ConstrainedSphericalDeconvModel(gtab, response, sh_order=6) seeds = [np.array([0., 1., 0.]), np.array([2., 4., 0.])] sc = BinaryStoppingCriterion((simple_image > 0).astype(float)) sphere = HemiSphere.from_sphere(get_sphere('symmetric724')) boot_dg = BootDirectionGetter.from_data(data, csd_model, 60, sphere=sphere) streamlines_generator = LocalTracking(boot_dg, sc, seeds, np.eye(4), 1.) streamlines = Streamlines(streamlines_generator) expected = [ np.array([[0., 1., 0.], [1., 1., 0.], [2., 1., 0.], [3., 1., 0.], [4., 1., 0.]]), np.array([ [2., 4., 0.], [2., 3., 0.], [2., 2., 0.], [2., 1., 0.], [2., 0., 0.], ]) ] def allclose(x, y): return x.shape == y.shape and np.allclose(x, y, atol=0.5) if not allclose(streamlines[0], expected[0]): raise AssertionError() if not allclose(streamlines[1], expected[1]): raise AssertionError()
def tracking(shm_file, mask_file, outdir, force_overwrite, particles, step_size, max_lenght, max_angle, algorithm, wpid_seeds_info): ''' Tracking function that will run in parallel Params: shm_file: SHM file computed from the dwi file mask_file: mask were to perform tractography outdir: Directory were to save streamlines force_overwrite: if True, existing files will be overwriten step_size: size in mm of each step in the tracking max_lenght: maximum lenght of each streamline max_angle: maximum angle at each step of tracking algoright: either 'probabilistic' or 'deterministic' wpid_seeds_info: tuple which contains: - wpid: The id of this worker - seeds: One list for each seed with points to track from - info: CIFTI information for each seed: -mtype: A valid CIFTI MODELTYPE -name: A valid CIFTI BRAINSTRUCTURE -coord: Voxel or vertex to which the seed makes reference -size: size of the CIFTI SURFACE (if applies) Returns: list of streamlines ''' import citrix import streamlines as sl from dipy.data import default_sphere from dipy.tracking.local_tracking import LocalTracking from dipy.tracking.stopping_criterion import BinaryStoppingCriterion wpid, (seeds, cifti_info) = wpid_seeds_info logging.debug("Worker {} started".format(wpid)) # Check if file exists outfile = os.path.join(outdir, "stream_{}.trk".format(wpid)) if os.path.isfile(outfile) and not force_overwrite: print("File already exists, use the -f flag to overwrite it") return shm = citrix.load(shm_file) shm_data = shm.get_data() mask_nib = citrix.load(mask_file) mask = mask_nib.get_data() if algorithm == 'deterministic': directions = deterministic.from_shcoeff(shm_data, max_angle, default_sphere) else: directions = probabilistic.from_shcoeff(shm_data, max_angle, default_sphere) stop_criterion = BinaryStoppingCriterion(mask) percent = max(1, len(seeds) / 5) streamlines = [] used_seeds = [] for i, s in enumerate(seeds): if i % percent == 0: logging.debug("{}, {}/{} seeds".format(wpid, i, len(seeds))) # Repeat the seeds as long as needed if len(s) == 3: # It's one point s = [s] repeated_seeds = [ss for ss in s for _ in range(2 * particles)] res = LocalTracking(directions, stop_criterion, repeated_seeds, shm.affine, step_size=step_size, maxlen=max_lenght, return_all=False) for streamline in itertools.islice(res, particles * len(s)): if streamline is not None and len(streamline) > 1: streamlines.append(streamline) if cifti_info[i][0] == 'CIFTI_MODEL_TYPE_SURFACE': used_seeds.append(cifti_info[i][2]) else: used_seeds.append([int(cf) for cf in cifti_info[i][2]]) streamlines = sl.Streamlines(streamlines, shm.affine, shm.shape[:3], shm.header.get_zooms()[:3]) numpy.savetxt(os.path.join(outdir, "info_{}.txt".format(wpid)), used_seeds) sl.io.save(streamlines, outfile) logging.debug("Worker {} finished".format(wpid)) return
- mask: numpy array [:, :, :] **Stopping States** - 'ENDPOINT': stops at a position where mask = 0; the streamline reached the target stopping area. - 'OUTSIDEIMAGE': stops at a position outside of metric_map; the streamline reached an area outside the image where no direction data is available. - 'TRACKPOINT': stops at a position because no direction is available; the streamline is stopping where mask > 0, but there is no valid direction to follow. - 'INVALIDPOINT': N/A. """ binary_criterion = BinaryStoppingCriterion(white_matter == 1) fig = plt.figure() plt.xticks([]) plt.yticks([]) fig.tight_layout() plt.imshow(white_matter[:, :, data.shape[2] // 2].T, cmap='gray', origin='lower', interpolation='nearest') fig.savefig('white_matter_mask.png') """ .. figure:: white_matter_mask.png :align: center
def prep_tissues(t1_mask, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, cmc_step_size=0.2): """ Estimate a tissue classifier for tractography. Parameters ---------- t1_mask : str File path to a T1w mask. gm_in_dwi : str File path to grey-matter tissue segmentation Nifti1Image. vent_csf_in_dwi : str File path to ventricular CSF tissue segmentation Nifti1Image. wm_in_dwi : str File path to white-matter tissue segmentation Nifti1Image. tiss_class : str Tissue classification method. cmc_step_size : float Step size from CMC tissue classification method. Returns ------- tiss_classifier : obj Tissue classifier object. """ try: import cPickle as pickle except ImportError: import _pickle as pickle from dipy.tracking.stopping_criterion import ActStoppingCriterion, CmcStoppingCriterion, BinaryStoppingCriterion from nilearn.masking import intersect_masks from nilearn.image import math_img # Loads mask mask_img = nib.load(t1_mask) # Load tissue maps and prepare tissue classifier wm_img = nib.load(wm_in_dwi) gm_img = nib.load(gm_in_dwi) gm_mask_data = np.asarray(gm_img.dataobj) wm_mask_data = np.asarray(wm_img.dataobj) vent_csf_in_dwi_data = np.asarray(nib.load(vent_csf_in_dwi).dataobj) if tiss_class == 'act': background = np.ones(mask_img.shape) background[(gm_mask_data + wm_mask_data + vent_csf_in_dwi_data) > 0] = 0 gm_mask_data[background > 0] = 1 tiss_classifier = ActStoppingCriterion(gm_mask_data, vent_csf_in_dwi_data) del background elif tiss_class == 'bin': tiss_classifier = BinaryStoppingCriterion( np.asarray( intersect_masks([ math_img('img > 0.0', img=mask_img), math_img('img > 0.0', img=wm_img) ], threshold=1, connected=False).dataobj)) elif tiss_class == 'cmc': voxel_size = np.average(mask_img.header['pixdim'][1:4]) tiss_classifier = CmcStoppingCriterion.from_pve( wm_mask_data, gm_mask_data, vent_csf_in_dwi_data, step_size=cmc_step_size, average_voxel_size=voxel_size) elif tiss_class == 'wb': tiss_classifier = BinaryStoppingCriterion( np.asarray(mask_img.dataobj).astype('bool')) else: raise ValueError('Tissue Classifier cannot be none.') del gm_mask_data, wm_mask_data, vent_csf_in_dwi_data mask_img.uncache() gm_img.uncache() wm_img.uncache() return tiss_classifier