def filter(self, lines): # lines that go though seed region testmask = copy.deepcopy(self.mask) #these are the raw lines from the seed testmask[:] = 0 testmask[(self.radtang == 2) & (self.angles == 1)] = 1 lines.seedlines = Streamlines( target(lines.lines, self.mask_nii.affine, testmask)) # seeds testmask[:] = 0 testmask[(self.radtang == 2) & (self.angles == 1)] = 1 lines.seedlines = Streamlines( target(lines.lines, self.mask_nii.affine, testmask)) # lines that cross over successfully testmask[:] = 0 testmask[(self.radtang == 2) & (self.updown == 1)] = 1 lines.lines_crsovr = Streamlines( target(lines.seedlines, self.mask_nii.affine, testmask)) lines.lines_crsovr = Streamlines( target(lines.lines_crsovr, self.mask_nii.affine, (self.radtang == 1), include=False)) #lines that fail to cross over lines.lines_crsovr_fail = Streamlines( target(lines.seedlines, self.mask_nii.affine, testmask, include=False))
def rad_tang_native(streamlines, drt, U, affine): eps = drt * 0.3 tang = Streamlines( target(streamlines, affine, U > (drt + eps), include=False)) tang = Streamlines(target(tang, affine, U < (drt + eps))) rad = Streamlines(target(streamlines, affine, U > (drt + eps))) return rad, tang
def targetme(sls, include, exclude, aff): for i in range(include.shape[-1]): sls = list(utils.target(sls, include[:, :, :, i], affine=aff)) for i in range(exclude.shape[-1]): sls = list( utils.target(sls, exclude[:, :, :, i], affine=aff, include=False)) return sls
def test_target(): streamlines = [np.array([[0., 0., 0.], [1., 0., 0.], [2., 0., 0.]]), np.array([[0., 0., 0], [0, 1., 1.], [0, 2., 2.]]) ] affine = np.eye(4) mask = np.zeros((4, 4, 4), dtype=bool) mask[0, 0, 0] = True # Both pass though new = list(target(streamlines, mask, affine=affine)) assert_equal(len(new), 2) new = list(target(streamlines, mask, affine=affine, include=False)) assert_equal(len(new), 0) # only first mask[:] = False mask[1, 0, 0] = True new = list(target(streamlines, mask, affine=affine)) assert_equal(len(new), 1) assert_true(new[0] is streamlines[0]) new = list(target(streamlines, mask, affine=affine, include=False)) assert_equal(len(new), 1) assert_true(new[0] is streamlines[1]) # Test that bad points raise a value error bad_sl = [ np.array([[10., 10., 10.]])] new = target(bad_sl, mask, affine=affine) assert_raises(ValueError, list, new) bad_sl = [-np.array([[10., 10., 10.]])] new = target(bad_sl, mask, affine=affine) assert_raises(ValueError, list, new) # Test smaller voxels affine = np.random.random((4, 4)) - .5 affine[3] = [0, 0, 0, 1] streamlines = list(move_streamlines(streamlines, affine)) new = list(target(streamlines, mask, affine=affine)) assert_equal(len(new), 1) assert_true(new[0] is streamlines[0]) new = list(target(streamlines, mask, affine=affine, include=False)) assert_equal(len(new), 1) assert_true(new[0] is streamlines[1]) # Test that changing mask and affine do not break target include = target(streamlines, mask, affine=affine) exclude = target(streamlines, mask, affine=affine, include=False) affine[:] = np.eye(4) mask[:] = False include = list(include) exclude = list(exclude) assert_equal(len(include), 1) assert_true(include[0] is streamlines[0]) assert_equal(len(exclude), 1) assert_true(exclude[0] is streamlines[1])
def label_streamlines(streamlines, labels, labels_Value, affine, hdr, f_name, data_path): cc_slice = labels == labels_Value cc_streamlines = utils.target(streamlines, labels, affine=affine) cc_streamlines = list(cc_streamlines) other_streamlines = utils.target(streamlines, cc_slice, affine=affine, include=False) other_streamlines = list(other_streamlines) assert len(other_streamlines) + len(cc_streamlines) == len(streamlines) print("num of roi steamlines is %d", len(cc_streamlines)) # Make display objects color = line_colors(cc_streamlines) cc_streamlines_actor = fvtk.line(cc_streamlines, line_colors(cc_streamlines)) cc_ROI_actor = fvtk.contour(cc_slice, levels=[1], colors=[(1., 1., 0.)], opacities=[1.]) # Add display objects to canvas r = fvtk.ren() fvtk.add(r, cc_streamlines_actor) fvtk.add(r, cc_ROI_actor) # Save figures fvtk.record(r, n_frames=1, out_path=f_name + '_roi.png', size=(800, 800)) fvtk.camera(r, [-1, 0, 0], [0, 0, 0], viewup=[0, 0, 1]) fvtk.record(r, n_frames=1, out_path=f_name + '_roi.png', size=(800, 800)) """""" csd_streamlines_trk = ((sl, None, None) for sl in cc_streamlines) csd_sl_fname = f_name + '_roi_streamline.trk' nib.trackvis.write(csd_sl_fname, csd_streamlines_trk, hdr, points_space='voxel') #nib.save(nib.Nifti1Image(FA, img.get_affine()), 'FA_map2.nii.gz') print('Saving "_roi_streamline.trk" sucessful.') import tractconverter as tc input_format = tc.detect_format(csd_sl_fname) input = input_format(csd_sl_fname) output = tc.FORMATS['vtk'].create(csd_sl_fname + ".vtk", input.hdr) tc.convert(input, output) return cc_streamlines
def _filter_from_roi_trackvis_style(tracts_fname, roi_fname, out_tracts_fname, include, mode, tol): tracts, hdr = nb.trackvis.read(tracts_fname, as_generator=True, points_space='voxel') img = nb.load(roi_fname) aff = np.eye(4) filtered_strl = [] mask = img.get_data() for chunk in ichunk(tracts, 100000): logging.debug("Starting new loop") # Need to "unshift" because Dipy shifts them back to fit in voxel grid. # However, to mimic the way TrackVis filters, we need to "unshift" it. # TODO check no negative coordinates strls = [s[0] - 0.5 for s in chunk] # Interpretation from @mdesco code: # target is used for this case because we want to support # include=False. if mode == 'any_part' and tol == 0: target_strl_gen = target(strls, mask, aff, include=include) target_strl = list(target_strl_gen) if len(target_strl) > 0: filtered_strl.extend(target_strl) else: corner_dist = dist_to_corner(aff) # Tolerance is considered to be in mm. Rescale wrt voxel size. tol = tol / min(img.get_header().get_zooms()) # Check this to avoid Dipy's warning and scare users. if tol < corner_dist: logging.debug( "Setting tolerance to minimal distance to corner") tol = corner_dist if mode == 'any_part': strls_ind = near_roi(strls, mask, aff, tol=tol, mode='any') else: strls_ind = near_roi(strls, mask, aff, tol=tol, mode=mode) for i in np.where(strls_ind)[0]: filtered_strl.append(strls[i]) logging.info("Original nb: {0}, kept: {1}".format(hdr['n_count'], len(filtered_strl))) # Remove the unshift final_strls = [(s + 0.5, None, None) for s in filtered_strl] new_hdr = np.copy(hdr) new_hdr['n_count'] = len(filtered_strl) nb.trackvis.write(out_tracts_fname, final_strls, new_hdr, points_space="voxel")
def sl_filter_target(streamlines, target_mask, affine, seed_label, target_label): from dipy.tracking.utils import target from nilearn.image import resample_img import numpy as np import os import nibabel as nib trk_file = nib.streamlines.load(streamlines) streams = trk_file.streamlines hdr = trk_file.header # resample mask to resolution of input data & get data target_resamp = resample_img(target_mask, affine) target_mask_bool = np.zeros(target_resamp.shape) target_mask_bool[ target_resamp.get_data().round() > 0] = 1 # rounding is key! target_sl_generator = target(streams, target_mask_bool, affine, include=True) target_streams = list(target_sl_generator) # create new filtered streamlines .trk file tractogram = nib.streamlines.Tractogram(target_streams) tractogram.affine_to_rasmm = np.eye(4) trk_file = nib.streamlines.TrkFile(tractogram, header=hdr) target_streamlines = os.path.abspath( 'target_streamlines_seed-%d_target-%d.trk' % (seed_label, target_label)) nib.streamlines.save(trk_file, target_streamlines) return target_streamlines, seed_label, target_label
def label_streamlines(streamlines,labels,labels_Value,affine,hdr,f_name,data_path): cc_slice=labels==labels_Value cc_streamlines = utils.target(streamlines, labels, affine=affine) cc_streamlines = list(cc_streamlines) other_streamlines = utils.target(streamlines, cc_slice, affine=affine, include=False) other_streamlines = list(other_streamlines) assert len(other_streamlines) + len(cc_streamlines) == len(streamlines) print ("num of roi steamlines is %d",len(cc_streamlines)) # Make display objects color = line_colors(cc_streamlines) cc_streamlines_actor = fvtk.line(cc_streamlines, line_colors(cc_streamlines)) cc_ROI_actor = fvtk.contour(cc_slice, levels=[1], colors=[(1., 1., 0.)], opacities=[1.]) # Add display objects to canvas r = fvtk.ren() fvtk.add(r, cc_streamlines_actor) fvtk.add(r, cc_ROI_actor) # Save figures fvtk.record(r, n_frames=1, out_path=f_name+'_roi.png', size=(800, 800)) fvtk.camera(r, [-1, 0, 0], [0, 0, 0], viewup=[0, 0, 1]) fvtk.record(r, n_frames=1, out_path=f_name+'_roi.png', size=(800, 800)) """""" csd_streamlines_trk = ((sl, None, None) for sl in cc_streamlines) csd_sl_fname = f_name+'_roi_streamline.trk' nib.trackvis.write(csd_sl_fname, csd_streamlines_trk, hdr, points_space='voxel') #nib.save(nib.Nifti1Image(FA, img.get_affine()), 'FA_map2.nii.gz') print('Saving "_roi_streamline.trk" sucessful.') import tractconverter as tc input_format=tc.detect_format(csd_sl_fname) input=input_format(csd_sl_fname) output=tc.FORMATS['vtk'].create(csd_sl_fname+".vtk",input.hdr) tc.convert(input,output) return cc_streamlines
def main(): """Track example dataset""" data, fa, bvec, bval, voxel_size = sample_hardi_data() seed_mask, target_mask = sample_tracking_seedNtarget() density = [1, 1, 2] start_step = [-0.3, -0.7, -0.7] tracks = simple_tracking_function(data, fa, bval, bvec, seed_mask, start_step, voxel_size, density) tracks = list(tracks) targeted_tracks = target(tracks, target_mask, voxel_size) """
def ROI_atlas_dipy(atlasobj, track_path): trk = load_trk(track_path, 'same') streamlines = trk.streamlines streamlines = reduct(streamlines) atlas = atlasobj.get_data(2) roi_feature = np.zeros(atlasobj.count) for i in range(1, atlasobj.count + 1): ROI_mask = atlas == i cc_streamlines = utils.target(streamlines, trk.affine, ROI_mask) cc_streamlines = Streamlines(cc_streamlines) roi_feature[i - 1] = len(cc_streamlines) print('roi ', i, ' finished!', atlasobj.count, 'total') return roi_feature
def nonbuggytarget(lines, mask, affine): lines_out = [] for ii in range(0, len(lines)): line = lines[ii] try: temp = Streamlines(target(line, affine, mask)) except ValueError: pass print('Buggy ValueError at line number ', ii) else: if (len(temp) > 0): lines_out.append(temp) return lines_out
def get_trks(subject, maindir,dtk_path,vol_ids): if subject.split('-')[0]=='sub': print(subject) sub = os.path.join(maindir,subject) trkdir = os.path.join(sub,'dwi','tracks') fsdir = os.path.join(sub,'anat','freesurfer') if os.path.exists(trkdir): for run in os.listdir(trkdir): trkrun = os.path.join(trkdir,run) if not os.path.exists(os.path.join(trkrun, "algo_vol-trk_map.json")) and os.path.isdir(trkrun): #if os.path.isdir(trkrun): # and run in os.listdir(fsdir): print(run) maskdir,mgz = gen_masks(fsdir,run,vol_ids,subject,maindir) nii = mgz.split('.')[0]+'.nii' bash_command(f'mri_convert --in_type mgz --out_type nii {mgz} {nii}') bash_command(f'flirt -in {os.path.join(sub,"dwi","dtk",run)}_dwi.nii -ref {nii} -omat {os.path.join(sub,"dwi",run)}_reg.mtx -out {os.path.join(sub,"dwi",run)}_reg') #if not os.path.exists(os.path.join(trkrun,"algo_vol-trk_map.json")): algo_vxl_sl={} for algo in os.listdir(trkrun): if algo.endswith('.trk') and 'fltr' in algo and 'reg' not in algo: print(algo) bash_command(f'{dtk_path}track_transform {os.path.join(trkrun,algo)} {os.path.join(trkrun,algo.split(".")[0])}_reg.trk -src {os.path.join(sub,"dwi","dtk",run)}_dwi.nii -ref {nii} -reg {os.path.join(sub,"dwi",run)}_reg.mtx -reg_type flirt') algo_trks,algo_aff,hshtbl = read_trkfile(f'{os.path.join(trkrun,algo.split(".")[0])}_reg.trk') np.savetxt(f'{os.path.join(trkrun,algo.split(".")[0])}_sl.txt',np.array(hshtbl)) vxl_sl={} if os.path.exists(maskdir): for maskf in os.listdir(maskdir): if maskf.endswith('npz'): try: mask = np.load(os.path.join(maskdir, maskf))['arr_0'] vxl_sl[maskf.split("_")[0]] = gen_hshtbl(list(utils.target( algo_trks,mask,algo_aff))) except: print(f'Could not load mask {maskf} for {run} {algo}') sl_vxl={} ks = sorted([int(k) for k in vxl_sl.keys()]) print(len(ks)) for kE in ks: sl_vxl[str(kE)]=vxl_sl[str(kE)] algo_vxl_sl[algo.split('.')[0]]=sl_vxl if os.path.exists(maskdir): shutil.rmtree(maskdir) with open(os.path.join(trkrun,"algo_vol-trk_map.json"),'w') as t: json.dump(algo_vxl_sl,t)
def choose_cc_bundle(streamlines,affine,folder_name,part): from dipy.tracking import utils from dipy.tracking.streamline import Streamlines file_list = os.listdir(folder_name) for file in file_list: if part in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) cc_mask_mat = mask_img.get_data() mask_include = cc_mask_mat == 1 masked_streamlines = utils.target(streamlines, affine, mask_include) masked_streamlines = Streamlines(masked_streamlines) return masked_streamlines
def select_by_vol_roi(streamlines, target_mask, affine, include=True): """ Include or exclude the streamlines according to a ROI Parameters ---------- streamlines: streamline data target_mask: volume roi affine: project streamline to roi space include: True or False (include or exclude) Return ------ roi_streamlines: extracted streamlines """ roi_selection = utils.target(streamlines=streamlines, target_mask=target_mask, affine=affine, include=include) roi_streamlines = list(roi_selection) return roi_streamlines
def sl_filter(streamlines, target_mask): from dipy.tracking.utils import target #from nilearn.image import resample_img import numpy as np import os import nibabel as nib trk_file = nib.streamlines.load(streamlines) streams = trk_file.streamlines hdr = trk_file.header # resample mask to resolution of input data & get data #target_resamp = resample_img(target_mask, affine) target_mask_img = nib.load(target_mask) affine = target_mask_img.affine target_mask_bool = np.zeros(target_mask_img.get_data().shape) target_mask_bool[ target_mask_img.get_data().round() > 0] = 1 # rounding is key! target_sl_generator = target(streams, target_mask_bool, affine, include=True) target_streams = list(target_sl_generator) # create new filtered streamlines .trk file tractogram = nib.streamlines.Tractogram(target_streams) tractogram.affine_to_rasmm = np.eye(4) trk_file = nib.streamlines.TrkFile(tractogram, header=hdr) # get the filename import re label = re.search(r'(?<=Fix_)\w+', target_mask).group(0)[:-6] # save streamlines to filename target_streamlines = os.path.abspath('target_streamlines_region_%s.trk' % label) nib.streamlines.save(trk_file, target_streamlines) return target_streamlines, target_mask, affine, label
def calc_cc_part_val(streamlines, mask, affine, calc_type='mean'): from dipy.tracking import utils from dipy.tracking.streamline import Streamlines from weighted_tracts import weighting_streamlines masked_streamlines = utils.target(streamlines, affine, mask) masked_streamlines = Streamlines(masked_streamlines) weights = weighting_streamlines(dir_name, masked_streamlines, affine, show=False, weight_by='3_2_AxPasi7') if 'mean' in calc_type: val = np.nanmean(weights) elif 'median' in calc_type: val = np.nanmedian(weights) return val
def run_tracking(step_curv_combinations, recon_shelved, n_seeds_per_iter, traversal, maxcrossing, max_length, pft_back_tracking_dist, pft_front_tracking_dist, particle_count, roi_neighborhood_tol, min_length, track_type, min_separation_angle, sphere, tiss_class, tissue_shelved, verbose=False): """ Create a density map of the list of streamlines. Parameters ---------- step_curv_combinations : list List of tuples representing all pair combinations of step sizes and curvature thresholds from which to sample streamlines. recon_path : str File path to diffusion reconstruction model. n_seeds_per_iter : int Number of seeds from which to initiate tracking for each unique ensemble combination. By default this is set to 250. directget : str The statistical approach to tracking. Options are: det (deterministic), closest (clos), boot (bootstrapped), and prob (probabilistic). maxcrossing : int Maximum number if diffusion directions that can be assumed per voxel while tracking. max_length : int Maximum number of steps to restrict tracking. pft_back_tracking_dist : float Distance in mm to back track before starting the particle filtering tractography. The total particle filtering tractography distance is equal to back_tracking_dist + front_tracking_dist. By default this is set to 2 mm. pft_front_tracking_dist : float Distance in mm to run the particle filtering tractography after the the back track distance. The total particle filtering tractography distance is equal to back_tracking_dist + front_tracking_dist. By default this is set to 1 mm. particle_count : int Number of particles to use in the particle filter. roi_neighborhood_tol : float Distance (in the units of the streamlines, usually mm). If any coordinate in the streamline is within this distance from the center of any voxel in the ROI, the filtering criterion is set to True for this streamline, otherwise False. Defaults to the distance between the center of each voxel and the corner of the voxel. waymask_data : ndarray Tractography constraint mask array in native diffusion space. min_length : int Minimum fiber length threshold in mm to restrict tracking. track_type : str Tracking algorithm used (e.g. 'local' or 'particle'). min_separation_angle : float The minimum angle between directions [0, 90]. sphere : obj DiPy object for modeling diffusion directions on a sphere. tiss_class : str Tissue classification method. tissue_shelved : str File path to joblib-shelved 4D T1w tissue segmentations in native diffusion space. Returns ------- streamlines : ArraySequence DiPy list/array-like object of streamline points from tractography. """ import gc import time import numpy as np from dipy.tracking import utils from dipy.tracking.streamline import select_by_rois from dipy.tracking.local_tracking import LocalTracking, \ ParticleFilteringTracking from dipy.direction import (ProbabilisticDirectionGetter, ClosestPeakDirectionGetter, DeterministicMaximumDirectionGetter) from nilearn.image import index_img, math_img from pynets.dmri.utils import generate_seeds, random_seeds_from_mask from nibabel.streamlines.array_sequence import ArraySequence start_time = time.time() if verbose is True: print("%s%s%s" % ('Preparing tissue constraints:', np.round(time.time() - start_time, 1), 's')) start_time = time.time() tissue_img = tissue_shelved.get() # Order: B0_mask = index_img(tissue_img, 0) atlas_img = index_img(tissue_img, 1) t1w2dwi = index_img(tissue_img, 3) gm_in_dwi = index_img(tissue_img, 4) vent_csf_in_dwi = index_img(tissue_img, 5) wm_in_dwi = index_img(tissue_img, 6) tissue_img.uncache() tiss_classifier = prep_tissues(t1w2dwi, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, B0_mask) # if verbose is True: # print("%s%s%s" % ( # 'Fitting tissue classifier:', # np.round(time.time() - start_time, 1), 's')) # start_time = time.time() if verbose is True: print("%s%s%s" % ('Loading reconstruction:', np.round(time.time() - start_time, 1), 's')) start_time = time.time() print("%s%s" % ("Curvature: ", step_curv_combinations[1])) # Instantiate DirectionGetter if traversal.lower() in ["probabilistic", "prob"]: dg = ProbabilisticDirectionGetter.from_shcoeff( recon_shelved.get(), max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) elif traversal.lower() in ["closestpeaks", "cp"]: dg = ClosestPeakDirectionGetter.from_shcoeff( recon_shelved.get(), max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) elif traversal.lower() in ["deterministic", "det"]: maxcrossing = 1 dg = DeterministicMaximumDirectionGetter.from_shcoeff( recon_shelved.get(), max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) else: raise ValueError("ERROR: No valid direction getter(s) specified.") if verbose is True: print("%s%s%s" % ('Extracting directions:', np.round(time.time() - start_time, 1), 's')) start_time = time.time() print("%s%s" % ("Step: ", step_curv_combinations[0])) # Perform wm-gm interface seeding, using n_seeds at a time seeds = generate_seeds( random_seeds_from_mask(np.asarray( math_img("img > 0.01", img=index_img( tissue_img, 2)).dataobj).astype("bool").astype("int16") > 0, seeds_count=n_seeds_per_iter, random_seed=42)) if verbose is True: print("%s%s%s" % ('Drawing random seeds:', np.round(time.time() - start_time, 1), 's')) start_time = time.time() # print(seeds) # Perform tracking if track_type == "local": streamline_generator = LocalTracking(dg, tiss_classifier, np.stack([i for i in seeds]), np.eye(4), max_cross=int(maxcrossing), maxlen=int(max_length), step_size=float( step_curv_combinations[0]), fixedstep=False, return_all=True, random_seed=42) elif track_type == "particle": streamline_generator = ParticleFilteringTracking( dg, tiss_classifier, np.stack([i for i in seeds]), np.eye(4), max_cross=int(maxcrossing), step_size=float(step_curv_combinations[0]), maxlen=int(max_length), pft_back_tracking_dist=pft_back_tracking_dist, pft_front_tracking_dist=pft_front_tracking_dist, pft_max_trial=20, particle_count=particle_count, return_all=True, random_seed=42) else: raise ValueError("ERROR: No valid tracking method(s) specified.") if verbose is True: print("%s%s%s" % ('Instantiating tracking:', np.round(time.time() - start_time, 1), 's')) start_time = time.time() # print(seeds) del dg # Filter resulting streamlines by those that stay entirely # inside the brain try: roi_proximal_streamlines = utils.target( streamline_generator, np.eye(4), np.asarray(B0_mask.dataobj).astype('bool'), include=True) except BaseException: print('No streamlines found inside the brain! ' 'Check registrations.') #return None if verbose is True: print("%s%s%s" % ('Drawing streamlines:', np.round(time.time() - start_time, 1), 's')) start_time = time.time() del seeds, tiss_classifier, streamline_generator B0_mask.uncache() atlas_img.uncache() t1w2dwi.uncache() gm_in_dwi.uncache() vent_csf_in_dwi.uncache() wm_in_dwi.uncache() gc.collect() # Filter resulting streamlines by roi-intersection # characteristics atlas_data = np.array(atlas_img.dataobj).astype("uint16") # Build mask vector from atlas for later roi filtering parcels = [ atlas_data == roi_val for roi_val in [i for i in np.unique(atlas_data) if i != 0] ] try: roi_proximal_streamlines = \ select_by_rois( roi_proximal_streamlines, affine=np.eye(4), rois=parcels, include=list(np.ones(len(parcels)).astype("bool")), mode="any", tol=roi_neighborhood_tol, ) except BaseException: print('No streamlines found to connect any parcels! ' 'Check registrations.') #return None del atlas_data if verbose is True: print("%s%s%s" % ('Selecting by parcellation:', np.round(time.time() - start_time, 1), 's')) start_time = time.time() del parcels gc.collect() if verbose is True: print("%s%s%s" % ('Selecting by minimum length criterion:', np.round(time.time() - start_time, 1), 's')) gc.collect() return ArraySequence([ s.astype("float32") for s in roi_proximal_streamlines if len(s) > float(min_length) ])
def filter_freesurf(sls, apac_data, aff, code): return list(utils.target(sls, apac_data == code, affine=aff))
def metrics_run_loop_per_roi(self, streamlines, affine, grouping): """ https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3931231/ streamlines found to intersect with the yellow mask in the corpus callosum (CC) using target. Then we used these streamlines to investigate which areas of the cortex are connected using a modified aparc+aseg.mgz label map created by FreeSurfer (Fischl, 2012) of 89 regions. https://dipy.org/documentation/1.0.0./examples_built/segment_clustering_metrics/ roi_slice = self.labels == 2 # cc_slice est le target mask pour corpus callosum """ df = pd.DataFrame() ls_all_roi = self.labels_all.values() ls_dimensions_index = list() for roi in self.labels_all.keys(): # saving metrics per ROI roi_slice = (self.labels == roi) target_streamlines = utils.target(streamlines, affine, roi_slice) roi_streamlines = Streamlines(target_streamlines) metrics_dic = self.metrics_compute(roi_streamlines) ls_rois = list() for metric in metrics_dic.keys(): ls_rois.append(self.labels_all[roi]) df = self.dataframe_populate(df, metrics_dic, ls_rois) ls_dimensions_index.append(len(roi_streamlines)) # make density map? # dm = utils.density_map(target_streamlines, np.eye(4), self.labels.shape) # Saving metrics per combination of ROIs for comb_rois in self.combinations_rois(): if roi in comb_rois: roi1 = comb_rois[0] roi2 = comb_rois[1] roi_12 = f"{self.labels_all[roi1]}_{self.labels_all[roi2]}" target_streamlines = grouping[roi1, roi2] rois_streamlines = Streamlines(target_streamlines) if len(rois_streamlines) > 0: metrics_dic = self.metrics_compute(rois_streamlines) ls_rois = list() for metric in metrics_dic.keys(): ls_rois.append(roi_12) df = self.dataframe_populate(df, metrics_dic, ls_rois) ls_dimensions_index.append(len(rois_streamlines)) ls_index = list() for i in range(1, max(ls_dimensions_index) + 1): ls_index.append((self.subj_id, i)) index = pd.MultiIndex.from_tuples(ls_index, names=[self.id_col, "Streamlines"]) df = df.set_index(index) df.to_csv( os.path.join(self.output_loc, f"{self.subj_id}_all_streamlines_metrics.csv")) print("saved to csv for subject:", self.subj_id)
def run_tracking(step_curv_combinations, recon_path, n_seeds_per_iter, directget, maxcrossing, max_length, pft_back_tracking_dist, pft_front_tracking_dist, particle_count, roi_neighborhood_tol, waymask, min_length, track_type, min_separation_angle, sphere, tiss_class, tissues4d, cache_dir): import gc import os import h5py from dipy.tracking import utils from dipy.tracking.streamline import select_by_rois from dipy.tracking.local_tracking import LocalTracking, \ ParticleFilteringTracking from dipy.direction import (ProbabilisticDirectionGetter, ClosestPeakDirectionGetter, DeterministicMaximumDirectionGetter) from nilearn.image import index_img from pynets.dmri.track import prep_tissues from nibabel.streamlines.array_sequence import ArraySequence from nipype.utils.filemanip import copyfile, fname_presuffix recon_path_tmp_path = fname_presuffix(recon_path, suffix=f"_{step_curv_combinations}", newpath=cache_dir) copyfile(recon_path, recon_path_tmp_path, copy=True, use_hardlink=False) if waymask is not None: waymask_tmp_path = fname_presuffix(waymask, suffix=f"_{step_curv_combinations}", newpath=cache_dir) copyfile(waymask, waymask_tmp_path, copy=True, use_hardlink=False) else: waymask_tmp_path = None tissue_img = nib.load(tissues4d) # Order: B0_mask = index_img(tissue_img, 0) atlas_img = index_img(tissue_img, 1) atlas_data_wm_gm_int = index_img(tissue_img, 2) t1w2dwi = index_img(tissue_img, 3) gm_in_dwi = index_img(tissue_img, 4) vent_csf_in_dwi = index_img(tissue_img, 5) wm_in_dwi = index_img(tissue_img, 6) tiss_classifier = prep_tissues(t1w2dwi, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, B0_mask) B0_mask_data = np.asarray(B0_mask.dataobj).astype("bool") atlas_data = np.array(atlas_img.dataobj).astype("uint16") atlas_data_wm_gm_int_data = np.asarray( atlas_data_wm_gm_int.dataobj).astype("bool").astype("int16") # Build mask vector from atlas for later roi filtering parcels = [] i = 0 intensities = [i for i in np.unique(atlas_data) if i != 0] for roi_val in intensities: parcels.append(atlas_data == roi_val) i += 1 del atlas_data parcel_vec = list(np.ones(len(parcels)).astype("bool")) with h5py.File(recon_path_tmp_path, 'r+') as hf: mod_fit = hf['reconstruction'][:].astype('float32') hf.close() print("%s%s" % ("Curvature: ", step_curv_combinations[1])) # Instantiate DirectionGetter if directget == "prob" or directget == "probabilistic": dg = ProbabilisticDirectionGetter.from_shcoeff( mod_fit, max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) elif directget == "clos" or directget == "closest": dg = ClosestPeakDirectionGetter.from_shcoeff( mod_fit, max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) elif directget == "det" or directget == "deterministic": maxcrossing = 1 dg = DeterministicMaximumDirectionGetter.from_shcoeff( mod_fit, max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) else: raise ValueError("ERROR: No valid direction getter(s) specified.") print("%s%s" % ("Step: ", step_curv_combinations[0])) # Perform wm-gm interface seeding, using n_seeds at a time seeds = utils.random_seeds_from_mask( atlas_data_wm_gm_int_data > 0, seeds_count=n_seeds_per_iter, seed_count_per_voxel=False, affine=np.eye(4), ) if len(seeds) == 0: print( UserWarning("No valid seed points found in wm-gm " "interface...")) return None # print(seeds) # Perform tracking if track_type == "local": streamline_generator = LocalTracking( dg, tiss_classifier, seeds, np.eye(4), max_cross=int(maxcrossing), maxlen=int(max_length), step_size=float(step_curv_combinations[0]), fixedstep=False, return_all=True, ) elif track_type == "particle": streamline_generator = ParticleFilteringTracking( dg, tiss_classifier, seeds, np.eye(4), max_cross=int(maxcrossing), step_size=float(step_curv_combinations[0]), maxlen=int(max_length), pft_back_tracking_dist=pft_back_tracking_dist, pft_front_tracking_dist=pft_front_tracking_dist, particle_count=particle_count, return_all=True, ) else: try: raise ValueError("ERROR: No valid tracking method(s) specified.") except ValueError: import sys sys.exit(0) # Filter resulting streamlines by those that stay entirely # inside the brain try: roi_proximal_streamlines = utils.target(streamline_generator, np.eye(4), B0_mask_data, include=True) except BaseException: print('No streamlines found inside the brain! ' 'Check registrations.') return None # Filter resulting streamlines by roi-intersection # characteristics try: roi_proximal_streamlines = \ nib.streamlines.array_sequence.ArraySequence( select_by_rois( roi_proximal_streamlines, affine=np.eye(4), rois=parcels, include=parcel_vec, mode="%s" % ("any" if waymask is not None else "both_end"), tol=roi_neighborhood_tol, ) ) print("%s%s" % ("Filtering by: \nNode intersection: ", len(roi_proximal_streamlines))) except BaseException: print('No streamlines found to connect any parcels! ' 'Check registrations.') return None try: roi_proximal_streamlines = nib.streamlines. \ array_sequence.ArraySequence( [ s for s in roi_proximal_streamlines if len(s) >= float(min_length) ] ) print(f"Minimum fiber length >{min_length}mm: " f"{len(roi_proximal_streamlines)}") except BaseException: print('No streamlines remaining after minimal length criterion.') return None if waymask is not None and os.path.isfile(waymask_tmp_path): from nilearn.image import math_img mask = math_img("img > 0.0075", img=nib.load(waymask_tmp_path)) waymask_data = np.asarray(mask.dataobj).astype("bool") try: roi_proximal_streamlines = roi_proximal_streamlines[utils.near_roi( roi_proximal_streamlines, np.eye(4), waymask_data, tol=roi_neighborhood_tol, mode="all")] print("%s%s" % ("Waymask proximity: ", len(roi_proximal_streamlines))) except BaseException: print('No streamlines remaining in waymask\'s vacinity.') return None out_streams = [s.astype("float32") for s in roi_proximal_streamlines] del dg, seeds, roi_proximal_streamlines, streamline_generator, \ atlas_data_wm_gm_int_data, mod_fit, B0_mask_data os.remove(recon_path_tmp_path) gc.collect() try: return ArraySequence(out_streams) except BaseException: return None
def run_tracking(step_curv_combinations, recon_path, n_seeds_per_iter, directget, maxcrossing, max_length, pft_back_tracking_dist, pft_front_tracking_dist, particle_count, roi_neighborhood_tol, waymask, min_length, track_type, min_separation_angle, sphere, tiss_class, tissues4d, cache_dir, min_seeds=100): import gc import os import h5py from dipy.tracking import utils from dipy.tracking.streamline import select_by_rois from dipy.tracking.local_tracking import LocalTracking, \ ParticleFilteringTracking from dipy.direction import (ProbabilisticDirectionGetter, ClosestPeakDirectionGetter, DeterministicMaximumDirectionGetter) from nilearn.image import index_img from pynets.dmri.track import prep_tissues from nibabel.streamlines.array_sequence import ArraySequence from nipype.utils.filemanip import copyfile, fname_presuffix import uuid from time import strftime run_uuid = f"{strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4()}" recon_path_tmp_path = fname_presuffix( recon_path, suffix=f"_{'_'.join([str(i) for i in step_curv_combinations])}_" f"{run_uuid}", newpath=cache_dir) copyfile(recon_path, recon_path_tmp_path, copy=True, use_hardlink=False) tissues4d_tmp_path = fname_presuffix( tissues4d, suffix=f"_{'_'.join([str(i) for i in step_curv_combinations])}_" f"{run_uuid}", newpath=cache_dir) copyfile(tissues4d, tissues4d_tmp_path, copy=True, use_hardlink=False) if waymask is not None: waymask_tmp_path = fname_presuffix( waymask, suffix=f"_{'_'.join([str(i) for i in step_curv_combinations])}_" f"{run_uuid}", newpath=cache_dir) copyfile(waymask, waymask_tmp_path, copy=True, use_hardlink=False) else: waymask_tmp_path = None tissue_img = nib.load(tissues4d_tmp_path) # Order: B0_mask = index_img(tissue_img, 0) atlas_img = index_img(tissue_img, 1) seeding_mask = index_img(tissue_img, 2) t1w2dwi = index_img(tissue_img, 3) gm_in_dwi = index_img(tissue_img, 4) vent_csf_in_dwi = index_img(tissue_img, 5) wm_in_dwi = index_img(tissue_img, 6) tiss_classifier = prep_tissues(t1w2dwi, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, B0_mask) B0_mask_data = np.asarray(B0_mask.dataobj).astype("bool") seeding_mask = np.asarray( seeding_mask.dataobj).astype("bool").astype("int16") with h5py.File(recon_path_tmp_path, 'r+') as hf: mod_fit = hf['reconstruction'][:].astype('float32') print("%s%s" % ("Curvature: ", step_curv_combinations[1])) # Instantiate DirectionGetter if directget.lower() in ["probabilistic", "prob"]: dg = ProbabilisticDirectionGetter.from_shcoeff( mod_fit, max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) elif directget.lower() in ["closestpeaks", "cp"]: dg = ClosestPeakDirectionGetter.from_shcoeff( mod_fit, max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) elif directget.lower() in ["deterministic", "det"]: maxcrossing = 1 dg = DeterministicMaximumDirectionGetter.from_shcoeff( mod_fit, max_angle=float(step_curv_combinations[1]), sphere=sphere, min_separation_angle=min_separation_angle, ) else: raise ValueError("ERROR: No valid direction getter(s) specified.") print("%s%s" % ("Step: ", step_curv_combinations[0])) # Perform wm-gm interface seeding, using n_seeds at a time seeds = utils.random_seeds_from_mask( seeding_mask > 0, seeds_count=n_seeds_per_iter, seed_count_per_voxel=False, affine=np.eye(4), ) if len(seeds) < min_seeds: print( UserWarning( f"<{min_seeds} valid seed points found in wm-gm interface...")) return None # print(seeds) # Perform tracking if track_type == "local": streamline_generator = LocalTracking(dg, tiss_classifier, seeds, np.eye(4), max_cross=int(maxcrossing), maxlen=int(max_length), step_size=float( step_curv_combinations[0]), fixedstep=False, return_all=True, random_seed=42) elif track_type == "particle": streamline_generator = ParticleFilteringTracking( dg, tiss_classifier, seeds, np.eye(4), max_cross=int(maxcrossing), step_size=float(step_curv_combinations[0]), maxlen=int(max_length), pft_back_tracking_dist=pft_back_tracking_dist, pft_front_tracking_dist=pft_front_tracking_dist, pft_max_trial=20, particle_count=particle_count, return_all=True, random_seed=42) else: raise ValueError("ERROR: No valid tracking method(s) specified.") # Filter resulting streamlines by those that stay entirely # inside the brain try: roi_proximal_streamlines = utils.target(streamline_generator, np.eye(4), B0_mask_data.astype('bool'), include=True) except BaseException: print('No streamlines found inside the brain! ' 'Check registrations.') return None del mod_fit, seeds, tiss_classifier, streamline_generator, \ B0_mask_data, seeding_mask, dg B0_mask.uncache() atlas_img.uncache() t1w2dwi.uncache() gm_in_dwi.uncache() vent_csf_in_dwi.uncache() wm_in_dwi.uncache() atlas_img.uncache() tissue_img.uncache() gc.collect() # Filter resulting streamlines by roi-intersection # characteristics atlas_data = np.array(atlas_img.dataobj).astype("uint16") # Build mask vector from atlas for later roi filtering parcels = [] i = 0 intensities = [i for i in np.unique(atlas_data) if i != 0] for roi_val in intensities: parcels.append(atlas_data == roi_val) i += 1 parcel_vec = list(np.ones(len(parcels)).astype("bool")) try: roi_proximal_streamlines = \ nib.streamlines.array_sequence.ArraySequence( select_by_rois( roi_proximal_streamlines, affine=np.eye(4), rois=parcels, include=parcel_vec, mode="any", tol=roi_neighborhood_tol, ) ) print("%s%s" % ("Filtering by: \nNode intersection: ", len(roi_proximal_streamlines))) except BaseException: print('No streamlines found to connect any parcels! ' 'Check registrations.') return None try: roi_proximal_streamlines = nib.streamlines. \ array_sequence.ArraySequence( [ s for s in roi_proximal_streamlines if len(s) >= float(min_length) ] ) print(f"Minimum fiber length >{min_length}mm: " f"{len(roi_proximal_streamlines)}") except BaseException: print('No streamlines remaining after minimal length criterion.') return None if waymask is not None and os.path.isfile(waymask_tmp_path): waymask_data = np.asarray( nib.load(waymask_tmp_path).dataobj).astype("bool") try: roi_proximal_streamlines = roi_proximal_streamlines[utils.near_roi( roi_proximal_streamlines, np.eye(4), waymask_data, tol=int(round(roi_neighborhood_tol * 0.50, 1)), mode="all")] print("%s%s" % ("Waymask proximity: ", len(roi_proximal_streamlines))) del waymask_data except BaseException: print('No streamlines remaining in waymask\'s vacinity.') return None hf.close() del parcels, atlas_data tmp_files = [tissues4d_tmp_path, waymask_tmp_path, recon_path_tmp_path] for j in tmp_files: if j is not None: if os.path.isfile(j): os.system(f"rm -f {j} &") if len(roi_proximal_streamlines) > 0: return ArraySequence( [s.astype("float32") for s in roi_proximal_streamlines]) else: return None
def choose_specific_bundle(streamlines, affine, folder_name, mask_type, n, nii_file): from dipy.tracking import utils from dipy.tracking.streamline import Streamlines #masks_dict = {'cc':[1,2,3,4,5],'cr':[6],'cing':[7],'mcp':[8],'fx':[9]} file_list = os.listdir(folder_name) for file in file_list: if 'ratlas' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) all_mask_mat = mask_img.get_data() if 'CR_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) cr_mask_mat = mask_img.get_fdata() if 'IFOF_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) ifof_mask_mat = mask_img.get_data() if 'ILF_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) ilf_mask_mat = mask_img.get_data() if 'slf_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) slf_mask_mat = mask_img.get_data() if 'cc1_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) cc_mask_mat = mask_img.get_fdata() if 'fx_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) fx_mask_mat = mask_img.get_data() if 'midsag_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) midsag_mask_mat = mask_img.get_data() if 'no_left_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) left_out_mask_mat = mask_img.get_data() if 'no_right_mask' in file and file.endswith('.nii'): mask_file = os.path.join(folder_name, file) mask_img = nib.load(mask_file) right_out_mask_mat = mask_img.get_data() if mask_type == 'w': masked_streamlines = streamlines return masked_streamlines elif mask_type == 'cc': mask_include = cc_mask_mat == 1 mask_exclude = (ifof_mask_mat == 1) | (cc_mask_mat == 2) | ( ilf_mask_mat == 1) | (slf_mask_mat == 1) | (cr_mask_mat == 1) | ( fx_mask_mat == 1) #mask_include = (all_mask_mat > 0) & (all_mask_mat < 6) #mask_exclude = (all_mask_mat > 5) elif mask_type == 'cr': mask_include = (cr_mask_mat == 1) | (cr_mask_mat == 3) mask_exclude = (cr_mask_mat == 2) | (right_out_mask_mat == 1) elif mask_type == 'cing': mask_include = (all_mask_mat == 7) mask_exclude = (midsag_mask_mat == 1) | (left_out_mask_mat == 1) elif mask_type == 'mcp': mask_include = (all_mask_mat == 8) mask_exclude = (all_mask_mat < 6) elif mask_type == 'fx': mask_include = (fx_mask_mat == 1 ) #(left_out_mask_mat ==1)|(right_out_mask_mat ==1) mask_exclude = (cr_mask_mat == 1) | (ifof_mask_mat == 1) | ( ilf_mask_mat == 1) | (all_mask_mat == 7) | (slf_mask_mat == 1 ) #(cc_mask_mat == 1)| elif mask_type == 'ifof': mask_include = (ifof_mask_mat == 1) mask_exclude = (midsag_mask_mat == 1) | (cr_mask_mat == 1) | ( ilf_mask_mat == 1) | (slf_mask_mat == 1) | ( ifof_mask_mat == 2) #| (left_out_mask_mat ==1) elif mask_type == 'ilf': mask_include = (ilf_mask_mat == 1) mask_exclude = (midsag_mask_mat == 1) | (cr_mask_mat == 1) | ( ifof_mask_mat == 1) | (ilf_mask_mat == 2) | (right_out_mask_mat == 1) elif mask_type == 'slf': mask_include = (slf_mask_mat == 1) mask_exclude = (midsag_mask_mat == 1) | (cr_mask_mat == 1) | ( slf_mask_mat == 2) | (right_out_mask_mat == 1) masked_streamlines = utils.target(streamlines, affine, mask_include) masked_streamlines = utils.target(masked_streamlines, affine, mask_exclude, include=False) masked_streamlines = Streamlines(masked_streamlines) save_ft(folder_name, n, masked_streamlines, nii_file, file_name='_' + mask_type + '.trk') return masked_streamlines
path = base + str(int(res[i] * 10000)) + "mm_drt-" + str( int(drt[j] * 100)) + "+w-" + str(int(w[k] * 100)) + "/" nstreamlines = streamline.load_vtk_streamlines( path + 'native_streamlines.vtk') fustreamlines = streamline.load_vtk_streamlines( path + 'from_unfold_streamlines.vtk') ustreamlines = streamline.load_vtk_streamlines( path + 'Unfolded/unfold_streamlines.vtk') U, affine = load_nifti(path + 'U.nii.gz') V, affine = load_nifti(path + 'V.nii.gz') mask, affine = load_nifti(path + 'nodif_brain_mask.nii.gz') one_slice = copy.deepcopy(mask) one_slice[:, :, 1:] = 0 one_slice[np.isnan(one_slice) == 1] = 0 nstreamlines = Streamlines(target(nstreamlines, affine, one_slice)) nrad, ntang = rad_tang_native(nstreamlines, drt[j], U, affine) furad, futang = rad_tang_native(fustreamlines, drt[j], U, affine) #Asymmetry plot import matplotlib nmax_x_y, nmax_x_y_streamlines = max_x_y(ntang, 1.1, -0.5, 5) fumax_x_y, fumax_x_y_streamlines = max_x_y(futang, 1.1, -0.5, 5) font = {'family': 'sans-serif', 'weight': 1, 'size': 22} matplotlib.rc('font', **font) fig, axs = plt.subplots(2) axs[0].set_xlim(-0.5, 1.25)
def run_LiFE(subject): print 'Process subject ' + subject if os.path.isfile( os.path.join(path_saveing, subject, 'Lamyg2LpMFG_LIFE_started.txt')) == False: print "LiFE Files do not exist for this subject, start calculation." if os.path.isfile( os.path.join( path_saveing, subject, 'Lamyg2LpMFG_clustered.trk')) == True and os.path.isfile( os.path.join(path_saveing, subject, '2M_SIFT.trk')) == True: print "All neccessary files there, continue ..." print "Show other processes that this subject is processed" done = np.array([1]) np.savetxt(os.path.join(path_saveing, subject, 'Lamyg2LpMFG_LIFE_started.txt'), done, delimiter=',') try: directory_output = os.path.join(path_saveing, subject) print "Start calculation for subject %s" % subject f_streamlines = os.path.join(path_saveing, subject, 'Lamyg2LpMFG_clustered.trk') f_in_nifti = os.path.join(path, subject, 'T1w/Diffusion/data.nii.gz') streams, hdr = tv.read(f_streamlines, points_space='voxel') streamlines = [i[0] for i in streams] data, affine, gtab, header, shell_mask = load_hcp_data( path, subject) dim = header['dim'][1:4] # Otherwise all weights are NaN data[data <= 0.0] = 1.0 print "Calculating neighborhood with LiFE" fiber_model_neighborhood = life.FiberModel(gtab) fiber_fit_neighborhood = fiber_model_neighborhood.fit( data, streamlines, affine=np.eye(4)) indices_neighborhood = fiber_fit_neighborhood.vox_coords neighborhood = np.zeros(dim, dtype=bool) for i in range(indices_neighborhood.shape[0]): neighborhood[indices_neighborhood[i][0], indices_neighborhood[i][1], indices_neighborhood[i][2]] = 1 save_as_nifti( path_saveing + subject + "/Lamyg2LpMFG_neighborhood", neighborhood.astype(np.int), affine) print 'Find fiber that pass through neighborhood' f_streamlines_whole_brain = path_saveing + subject + "/2M_SIFT.trk" streams_whole_brain, hdr_whole_brain = tv.read( f_streamlines_whole_brain, points_space='voxel') streamlines_whole_brain = [i[0] for i in streams_whole_brain] neighborhood_streamlines = utils.target( streamlines_whole_brain, neighborhood, affine=np.eye(4)) neighborhood_streamlines = list(neighborhood_streamlines) strm = ((sl, None, None) for sl in neighborhood_streamlines) tv.write(path_saveing + subject + "/Lamyg2LpMFG_2M_SIFT_without_path.trk", strm, hdr_mapping=hdr_whole_brain, points_space='voxel') print "Combine streamlines" streamlines_together = neighborhood_streamlines + streamlines strm_together = ((sl, None, None) for sl in streamlines_together) tv.write(path_saveing + subject + "/Lamyg2LpMFG_2M_SIFT_with_path.trk", strm_together, hdr_mapping=hdr_whole_brain, points_space='voxel') print "Start LiFE optimization with new path" fiber_model_together = life.FiberModel(gtab) fiber_fit_together = fiber_model_together.fit( data, streamlines_together, affine=np.eye(4)) model_predict_together = fiber_fit_together.predict() indices_together = fiber_fit_together.vox_coords mask_with = np.zeros(dim, dtype=bool) whole_brain_together = np.zeros(header['dim'][1:5]) for i in range(indices_together.shape[0]): whole_brain_together[ indices_together[i][0], indices_together[i][1], indices_together[i][2]] = model_predict_together[i] mask_with[indices_together[i][0], indices_together[i][1], indices_together[i][2]] = 1 save_as_nifti( path_saveing + subject + "/Lamyg2LpMFG_LiFE_prediction_with_path", whole_brain_together, affine) save_as_matlab_file(path_saveing + subject + "/Lamyg2LpMFG_LiFE_betas_with_path", beta=fiber_fit_together.beta) save_as_nifti( path_saveing + subject + "/Lamyg2LpMFG_LiFE_mask_with_path", mask_with.astype(np.int), affine) print "Calculate RMSE with" model_error_together = model_predict_together - fiber_fit_together.data model_rmse_together = np.sqrt( np.mean(model_error_together[..., ~gtab.b0s_mask]**2, -1)) whole_brain_rmse_together = np.zeros(dim) for i in range(indices_together.shape[0]): whole_brain_rmse_together[ indices_together[i][0], indices_together[i][1], indices_together[i][2]] = model_rmse_together[i] save_as_nifti( path_saveing + subject + "/Lamyg2LpMFG_LiFE_rmse_with_path", whole_brain_rmse_together, affine) print "Start LiFE optimization without new path" fiber_fit = copy.deepcopy(fiber_fit_together) fiber_fit.beta[-len(streamlines):] = 0 model_predict = fiber_fit.predict() indices = fiber_fit.vox_coords whole_brain = np.zeros(header['dim'][1:5]) mask_without = np.zeros(dim, dtype=bool) for i in range(indices.shape[0]): whole_brain[indices[i][0], indices[i][1], indices[i][2]] = model_predict[i] mask_without[indices[i][0], indices[i][1], indices[i][2]] = 1 save_as_nifti( path_saveing + subject + "/Lamyg2LpMFG_LiFE_prediction_without_path", whole_brain, affine) save_as_matlab_file(path_saveing + subject + "/Lamyg2LpMFG_LiFE_betas_without_path", beta=fiber_fit.beta) save_as_nifti( path_saveing + subject + "/Lamyg2LpMFG_LiFE_mask_without_path", mask_without.astype(np.int), affine) print "Calculate RMSE without" model_error = model_predict - fiber_fit.data model_rmse = np.sqrt( np.mean(model_error[..., ~gtab.b0s_mask]**2, -1)) whole_brain_rmse = np.zeros(dim) for i in range(indices.shape[0]): whole_brain_rmse[indices[i][0], indices[i][1], indices[i][2]] = model_rmse[i] save_as_nifti( path_saveing + subject + "/Lamyg2LpMFG_LiFE_rmse_without_path", whole_brain_rmse, affine) print "All done" except: print "An error occured while computing LiFE. Skip this subject." else: print "Some input files are missing, skip this subject." else: print "LiFE Files exist already for this subject, skip calculation." return 0
""" 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 of the corpus callosum identified by the label value 2. We'll create an ROI mask from that label and create two sets of streamlines, those that intersect with the ROI and those that don't. """ cc_slice = labels == 2 cc_streamlines = utils.target(streamlines, cc_slice, affine=affine) cc_streamlines = list(cc_streamlines) other_streamlines = utils.target(streamlines, cc_slice, affine=affine, include=False) other_streamlines = list(other_streamlines) assert len(other_streamlines) + len(cc_streamlines) == len(streamlines) """ We can use some of dipy's visualization tools to display the ROI we targeted above and all the streamlines that pass though that ROI. The ROI is the yellow region near the center of the axial image. """ from dipy.viz import fvtk from dipy.viz.colormap import line_colors
def evaluate_streamline_plausibility(dwi_data, gtab, mask_data, streamlines, affine=np.eye(4), sphere='repulsion724'): """ Linear Fascicle Evaluation (LiFE) takes any connectome and uses a forward modelling approach to predict diffusion measurements in the same brain. Parameters ---------- dwi_data : array 4D array of dwi data. gtab : Obj DiPy object storing diffusion gradient information. mask_data : array 3D Brain mask. streamlines : ArraySequence DiPy list/array-like object of streamline points from tractography. Returns ------- streamlines : ArraySequence DiPy list/array-like object of streamline points from tractography. References ---------- .. [1] Pestilli, F., Yeatman, J, Rokem, A. Kay, K. and Wandell B.A. (2014). Validation and statistical inference in living connectomes. Nature Methods 11: 1058-1063. doi:10.1038/nmeth.3098 """ import dipy.tracking.life as life import dipy.core.optimize as opt from dipy.tracking._utils import _mapping_to_voxel # from dipy.data import get_sphere from dipy.tracking import utils from dipy.tracking.streamline import Streamlines original_count = len(streamlines) streamlines_long = nib.streamlines. \ array_sequence.ArraySequence( [ s for s in streamlines if len(s) >= float(10) ] ) print('Removing streamlines with negative voxel indices...') # Remove any streamlines with negative voxel indices lin_T, offset = _mapping_to_voxel(np.eye(4)) streamlines_positive = [] for sl in streamlines_long: inds = np.dot(sl, lin_T) inds += offset if not inds.min().round(decimals=6) < 0: streamlines_positive.append(sl) del streamlines_long # Filter resulting streamlines by those that stay entirely # inside the ROI of interest mask_data = np.array(mask_data, dtype=bool, copy=False) streamlines_in_brain = Streamlines( utils.target(streamlines_positive, np.eye(4), mask_data, include=True)) streamlines_in_brain = [i for i in streamlines_in_brain] del streamlines_positive print('Fitting fiber model...') # ! Remember this 4d masking function ! data_in_mask = np.nan_to_num( np.broadcast_to(mask_data[..., None], dwi_data.shape).astype('bool') * dwi_data) # ! Remember this 4d masking function ! fiber_model = life.FiberModel(gtab) fiber_fit = fiber_model.fit(data_in_mask, streamlines_in_brain, affine=affine, sphere=False) # sphere = get_sphere(sphere) # fiber_fit = fiber_model.fit(data_in_mask, streamlines_in_brain, # affine=affine, # sphere=sphere) streamlines = list( np.array(streamlines_in_brain)[np.where(fiber_fit.beta > 0)[0]]) pruned_count = len(streamlines) if pruned_count == 0: print( UserWarning('\nWarning LiFE skipped due to implausible values ' 'detected in model betas. This does not ' 'necessarily invalidate the ' 'tractography. Rather it could indicate that ' 'you\'ve sampled too few streamlines, or that the ' 'sampling scheme is simply incompatible with the ' 'LiFE model. Is your acquisition hemispheric? ' 'Also check the gradient table for errors. \n')) return streamlines_in_brain else: del streamlines_in_brain model_predict = fiber_fit.predict() model_error = model_predict - fiber_fit.data model_rmse = np.sqrt(np.mean(model_error[:, 10:]**2, -1)) beta_baseline = np.zeros(fiber_fit.beta.shape[0]) pred_weighted = np.reshape( opt.spdot(fiber_fit.life_matrix, beta_baseline), (fiber_fit.vox_coords.shape[0], np.sum(~gtab.b0s_mask))) mean_pred = np.empty((fiber_fit.vox_coords.shape[0], gtab.bvals.shape[0])) S0 = fiber_fit.b0_signal mean_pred[..., gtab.b0s_mask] = S0[:, None] mean_pred[..., ~gtab.b0s_mask] = (pred_weighted + fiber_fit.mean_signal[:, None]) * S0[:, None] mean_error = mean_pred - fiber_fit.data mean_rmse = np.sqrt(np.mean(mean_error**2, -1)) print(f"Original # Streamlines: {original_count}") print(f"Final # Streamlines: {pruned_count}") print(f"Streamlines removed: {pruned_count - original_count}") print(f"Mean RMSE: {np.mean(mean_rmse)}") print(f"Mean Model RMSE: {np.mean(model_rmse)}") print(f"Mean Reduction RMSE: {np.mean(mean_rmse - model_rmse)}") return streamlines
def save_results(table, area_pairs, medium, subject_name): with open('saved/{}_track_result'.format(subject_name), 'wb') as f: pickle.dump(table, f) streamlines = table['streamlines'] sft = table['sft'] sub_affine = table['affine'] data = table['data'] labels = table["labels"] affine = np.eye(4) # extract streamlines only pass through ROIs cc_slice = (labels == medium[0]) # ROIs if len(medium) > 1: for m in medium: cc_slice = cc_slice | (labels == m) cc_streamlines = utils.target(streamlines, affine, cc_slice) cc_streamlines = Streamlines(cc_streamlines) other_streamlines = utils.target(streamlines, affine, cc_slice, include=False) other_streamlines = Streamlines(other_streamlines) assert len(other_streamlines) + len(cc_streamlines) == len(streamlines) M, grouping = utils.connectivity_matrix(streamlines, affine, labels, return_mapping=True, mapping_as_streamlines=True) M[:3, :] = 0 M[:, :3] = 0 for pair in area_pairs: track = grouping[pair[0], pair[1]] shape = labels.shape dm = utils.density_map(track, affine, shape) import nibabel as nib # Save density map dm_img = nib.Nifti1Image(dm.astype("int16"), sub_affine) dm_img.to_filename("saved/{}_{}.nii.gz".format(subject_name, pair)) # save_trk(sft, "tractogram_probabilistic_dg.trk") # # visualzie # # Enables/disables interactive visualization # interactive = False # if has_fury: # # Prepare the display objects. # color = colormap.line_colors(streamlines) # streamlines_actor = actor.line(streamlines, color) # # Create the 3D display. # r = window.Scene() # r.add(streamlines_actor) # # Save still images for this static example. Or for interactivity use # window.record(r, out_path='fiber_tracking_Caudate_l_r_result.png', size=(800, 800)) # if interactive: # window.show(r)
def inflection(streamlines, drt, U, affine): eps = drt * 0.3 #tang = Streamlines(target(streamlines,affine,U>(drt+eps),include=False)) tang = Streamlines(target(streamlines, affine, U < (drt + eps))) tang = Streamlines(target(tang, affine, U > (drt + eps))) return tang
def run_LiFE(subject): print 'Process subject ' + subject if os.path.isfile(os.path.join(path_saveing, subject, 'RVLPFC2FIRSTamyg_bigRight_LIFE_started2.txt')) == False: print "LiFE Files do not exist for this subject, start calculation." if os.path.isfile(os.path.join(path_saveing, subject, 'RVLPFC2FIRSTamyg_bigRight_clustered.trk')) == True and os.path.isfile(os.path.join(path_saveing, subject, '2M_SIFT.trk')) == True: print "All neccessary files there, continue ..." print "Show other processes that this subject is processed" done = np.array([1]) np.savetxt(os.path.join(path_saveing, subject, 'RVLPFC2FIRSTamyg_bigRight_LIFE_started2.txt'), done, delimiter=',') try: directory_output = os.path.join(path_saveing, subject) print "Start calculation for subject %s" % subject f_streamlines = os.path.join(path_saveing, subject, 'RVLPFC2FIRSTamyg_bigRight_clustered.trk') f_in_nifti = os.path.join(path, subject, 'T1w/Diffusion/data.nii.gz') streams, hdr = tv.read(f_streamlines, points_space='voxel') streamlines = [i[0] for i in streams] data, affine, gtab, header, shell_mask = load_hcp_data(path, subject) dim = header['dim'][1:4] # Otherwise all weights are NaN data[data <= 0.0] = 1.0 print "Calculating neighborhood with LiFE" fiber_model_neighborhood = life.FiberModel(gtab) fiber_fit_neighborhood = fiber_model_neighborhood.fit(data, streamlines, affine=np.eye(4)) indices_neighborhood = fiber_fit_neighborhood.vox_coords neighborhood = np.zeros(dim, dtype=bool) for i in range(indices_neighborhood.shape[0]): neighborhood[indices_neighborhood[i][0], indices_neighborhood[i][1], indices_neighborhood[i][2]] = 1 save_as_nifti(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_neighborhood", neighborhood.astype(np.int), affine) print 'Find fiber that pass through neighborhood' f_streamlines_whole_brain = path_saveing + subject + "/2M_SIFT.trk" streams_whole_brain, hdr_whole_brain = tv.read(f_streamlines_whole_brain, points_space='voxel') streamlines_whole_brain = [i[0] for i in streams_whole_brain] neighborhood_streamlines = utils.target(streamlines_whole_brain, neighborhood, affine=np.eye(4)) neighborhood_streamlines = list(neighborhood_streamlines) strm = ((sl, None, None) for sl in neighborhood_streamlines) tv.write(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_2M_SIFT_without_path.trk", strm, hdr_mapping=hdr_whole_brain, points_space='voxel') print "Combine streamlines" streamlines_together = neighborhood_streamlines + streamlines strm_together = ((sl, None, None) for sl in streamlines_together) tv.write(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_2M_SIFT_with_path.trk", strm_together, hdr_mapping=hdr_whole_brain, points_space='voxel') print "Start LiFE optimization with new path" fiber_model_together = life.FiberModel(gtab) fiber_fit_together = fiber_model_together.fit(data, streamlines_together, affine=np.eye(4)) model_predict_together = fiber_fit_together.predict() indices_together = fiber_fit_together.vox_coords mask_with = np.zeros(dim, dtype=bool) whole_brain_together = np.zeros(header['dim'][1:5]) for i in range(indices_together.shape[0]): whole_brain_together[indices_together[i][0], indices_together[i][1], indices_together[i][2]] = model_predict_together[i] mask_with[indices_together[i][0], indices_together[i][1], indices_together[i][2]] = 1 save_as_nifti(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_LiFE_prediction_with_path", whole_brain_together, affine) save_as_matlab_file(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_LiFE_betas_with_path", beta = fiber_fit_together.beta) save_as_nifti(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_LiFE_mask_with_path", mask_with.astype(np.int), affine) print "Calculate RMSE with" model_error_together = model_predict_together - fiber_fit_together.data model_rmse_together = np.sqrt(np.mean(model_error_together[..., ~gtab.b0s_mask] ** 2, -1)) whole_brain_rmse_together = np.zeros(dim) for i in range(indices_together.shape[0]): whole_brain_rmse_together[indices_together[i][0], indices_together[i][1], indices_together[i][2]] = model_rmse_together[i] save_as_nifti(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_LiFE_rmse_with_path", whole_brain_rmse_together, affine) print "Start LiFE optimization without new path" fiber_fit = copy.deepcopy(fiber_fit_together) fiber_fit.beta[-len(streamlines):] = 0 model_predict = fiber_fit.predict() indices = fiber_fit.vox_coords whole_brain = np.zeros(header['dim'][1:5]) mask_without = np.zeros(dim, dtype=bool) for i in range(indices.shape[0]): whole_brain[indices[i][0], indices[i][1], indices[i][2]] = model_predict[i] mask_without[indices[i][0], indices[i][1], indices[i][2]] = 1 save_as_nifti(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_LiFE_prediction_without_path", whole_brain, affine) save_as_matlab_file(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_LiFE_betas_without_path", beta = fiber_fit.beta) save_as_nifti(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_LiFE_mask_without_path", mask_without.astype(np.int), affine) print "Calculate RMSE without" model_error = model_predict - fiber_fit.data model_rmse = np.sqrt(np.mean(model_error[..., ~gtab.b0s_mask] ** 2, -1)) whole_brain_rmse = np.zeros(dim) for i in range(indices.shape[0]): whole_brain_rmse[indices[i][0], indices[i][1], indices[i][2]] = model_rmse[i] save_as_nifti(path_saveing + subject + "/RVLPFC2FIRSTamyg_bigRight_LiFE_rmse_without_path", whole_brain_rmse, affine) print "All done" except: print "An error occured while computing LiFE. Skip this subject." else: print "Some input files are missing, skip this subject." else: print "LiFE Files exist already for this subject, skip calculation." return 0
streamlines = Streamlines(streamline_generator) et4 = time.time() - st4 #lengths = [length(sl).astype(np.int) for sl in streamlines] #print 'generating streamlines finished, the length is {}~{}, running time is {}'.format(np.min(lengths), np.max(lengths), et4) del bm, mask, fod_coeff, prob_dg, classifier #, lengths gc.collect() print 'bm, mask, fod_coeff, prob_dg, classifier, lengths delete to save memory' #Cut streamlines #streamlines = [sl for sl in streamlines if length(sl).astype(np.int)>3] #print 'cutting short streamlines finished' logic_t = np.logical_or(labels_==roi_l, labels_==roi_r) cc_slice = np.where(logic_t, True, False) cc_streamlines = utils.target(streamlines, cc_slice, affine=affine) cc_streamlines = Streamlines(cc_streamlines) # Prepare the display objects. color = line_colors(cc_streamlines) if window.have_vtk: streamlines_actor = actor.line(cc_streamlines, line_colors(cc_streamlines)) # Create the 3D display. r = window.Renderer() r.add(streamlines_actor) # Save still images for this static example. Or for interactivity use window.record(r, n_frames=1, out_path=outpath+'roi_streamlines/'+runno+'_tract'+str(myindex)+'.png', size=(800, 800))
def cal_ROI_num(mask_path, track_path, normdata_path, name, method_index, atlas, index, output): if normdata_path == None: norm_file = os.path.join('./data/DWI', name, 'norm.nii.gz') else: norm_file = normdata_path data, affine = load_nifti(norm_file) if method_index == 1: method = 'EuDX' elif method_index == 2: method = 'probabilistic' elif method_index == 3: method = 'deterministic' elif method_index == 4: method = 'sfm' elif method_index == 5: method = 'pft' else: method = None if track_path == None: trackfile = os.path.join('./Result/Track', 'tractogram_' + method + '_' + name + '.trk') else: trackfile = os.path.join(track_path, 'tractogram_' + method + '_' + name + '.trk') tracks = dwi.load_streamlines_from_trk(trackfile) tracks = reduct(tracks) index = str(index) if mask_path == None: ROI_file = os.path.join('./data/atlas', atlas, 'ROI_' + index + '_2.nii.gz') else: ROI_file = mask_path ROI_mask = load_nifti_data(ROI_file) cc_slice = np.zeros(data.shape[:3]) cc_slice[:ROI_mask.shape[0], :ROI_mask.shape[1], :ROI_mask. shape[2]] = ROI_mask cc_streamlines = utils.target(tracks, affine, cc_slice.astype(np.float)) cc_streamlines = Streamlines(cc_streamlines) if not os.path.isfile(output): mode = 'w+' else: mode = 'r+' with open(output, mode) as fileR: # 打开文本读取状态 strF = fileR.read() #print(len(strF)) if len(strF) == 0: R = {} else: R = json.loads(strF) # 解析读到的文本内容 转为python数据 以一个变量接收 #print(args.name in R.keys()) if name in R.keys(): a = R[name] a[index] = len(cc_streamlines) R[name] = a else: a = {index: len(cc_streamlines)} R[name] = a with open(output, 'w') as fileR: jsObj = json.dumps(R, indent=4) fileR.write(jsObj)
""" 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 of the corpus callosum identified by the label value 2. We'll create an ROI mask from that label and create two sets of streamlines, those that intersect with the ROI and those that don't. """ cc_slice = labels == 2 cc_streamlines = utils.target(streamlines, cc_slice, affine=affine) cc_streamlines = list(cc_streamlines) other_streamlines = utils.target(streamlines, cc_slice, affine=affine, include=False) other_streamlines = list(other_streamlines) assert len(other_streamlines) + len(cc_streamlines) == len(streamlines) """ We can use some of dipy's visualization tools to display the ROI we targeted above and all the streamlines that pass though that ROI. The ROI is the yellow region near the center of the axial image. """ from dipy.viz import fvtk
def track_ensemble(target_samples, atlas_data_wm_gm_int, parcels, mod_fit, tiss_classifier, sphere, directget, curv_thr_list, step_list, track_type, maxcrossing, roi_neighborhood_tol, min_length, waymask, B0_mask, max_length=1000, n_seeds_per_iter=500, pft_back_tracking_dist=2, pft_front_tracking_dist=1, particle_count=15, min_separation_angle=20): """ Perform native-space ensemble tractography, restricted to a vector of ROI masks. target_samples : int Total number of streamline samples specified to generate streams. atlas_data_wm_gm_int : array 3D int32 numpy array of atlas parcellation intensities from Nifti1Image in T1w-warped native diffusion space, restricted to wm-gm interface. parcels : list List of 3D boolean numpy arrays of atlas parcellation ROI masks from a Nifti1Image in T1w-warped native diffusion space. mod : obj Connectivity reconstruction model. tiss_classifier : str Tissue classification method. sphere : obj DiPy object for modeling diffusion directions on a sphere. directget : str The statistical approach to tracking. Options are: det (deterministic), closest (clos), boot (bootstrapped), and prob (probabilistic). curv_thr_list : list List of integer curvature thresholds used to perform ensemble tracking. step_list : list List of float step-sizes used to perform ensemble tracking. track_type : str Tracking algorithm used (e.g. 'local' or 'particle'). maxcrossing : int Maximum number if diffusion directions that can be assumed per voxel while tracking. roi_neighborhood_tol : float Distance (in the units of the streamlines, usually mm). If any coordinate in the streamline is within this distance from the center of any voxel in the ROI, the filtering criterion is set to True for this streamline, otherwise False. Defaults to the distance between the center of each voxel and the corner of the voxel. min_length : int Minimum fiber length threshold in mm. waymask : str Path to a Nifti1Image in native diffusion space to constrain tractography. B0_mask : str File path to B0 brain mask. max_length : int Maximum number of steps to restrict tracking. n_seeds_per_iter : int Number of seeds from which to initiate tracking for each unique ensemble combination. By default this is set to 200. particle_count pft_back_tracking_dist : float Distance in mm to back track before starting the particle filtering tractography. The total particle filtering tractography distance is equal to back_tracking_dist + front_tracking_dist. By default this is set to 2 mm. pft_front_tracking_dist : float Distance in mm to run the particle filtering tractography after the the back track distance. The total particle filtering tractography distance is equal to back_tracking_dist + front_tracking_dist. By default this is set to 1 mm. particle_count : int Number of particles to use in the particle filter. min_separation_angle : float The minimum angle between directions [0, 90]. Returns ------- streamlines : ArraySequence DiPy list/array-like object of streamline points from tractography. References ---------- .. [1] Takemura, H., Caiafa, C. F., Wandell, B. A., & Pestilli, F. (2016). Ensemble Tractography. PLoS Computational Biology. https://doi.org/10.1371/journal.pcbi.1004692 """ import gc import time from colorama import Fore, Style from dipy.tracking import utils from dipy.tracking.streamline import Streamlines, select_by_rois from dipy.tracking.local_tracking import LocalTracking, ParticleFilteringTracking from dipy.direction import (ProbabilisticDirectionGetter, ClosestPeakDirectionGetter, DeterministicMaximumDirectionGetter) start = time.time() B0_mask_data = nib.load(B0_mask).get_fdata() if waymask: waymask_data = np.asarray(nib.load(waymask).dataobj).astype('bool') # Commence Ensemble Tractography parcel_vec = list(np.ones(len(parcels)).astype('bool')) streamlines = nib.streamlines.array_sequence.ArraySequence() circuit_ix = 0 stream_counter = 0 while int(stream_counter) < int(target_samples): for curv_thr in curv_thr_list: print("%s%s" % ('Curvature: ', curv_thr)) # Instantiate DirectionGetter if directget == 'prob': dg = ProbabilisticDirectionGetter.from_shcoeff(mod_fit, max_angle=float(curv_thr), sphere=sphere, min_separation_angle=min_separation_angle) elif directget == 'clos': dg = ClosestPeakDirectionGetter.from_shcoeff(mod_fit, max_angle=float(curv_thr), sphere=sphere, min_separation_angle=min_separation_angle) elif directget == 'det': dg = DeterministicMaximumDirectionGetter.from_shcoeff(mod_fit, max_angle=float(curv_thr), sphere=sphere, min_separation_angle=min_separation_angle) else: raise ValueError('ERROR: No valid direction getter(s) specified.') for step in step_list: print("%s%s" % ('Step: ', step)) # Perform wm-gm interface seeding, using n_seeds at a time seeds = utils.random_seeds_from_mask(atlas_data_wm_gm_int > 0, seeds_count=n_seeds_per_iter, seed_count_per_voxel=False, affine=np.eye(4)) if len(seeds) == 0: raise RuntimeWarning('Warning: No valid seed points found in wm-gm interface...') # print(seeds) # Perform tracking if track_type == 'local': streamline_generator = LocalTracking(dg, tiss_classifier, seeds, np.eye(4), max_cross=int(maxcrossing), maxlen=int(max_length), step_size=float(step), fixedstep=False, return_all=True) elif track_type == 'particle': streamline_generator = ParticleFilteringTracking(dg, tiss_classifier, seeds, np.eye(4), max_cross=int(maxcrossing), step_size=float(step), maxlen=int(max_length), pft_back_tracking_dist=pft_back_tracking_dist, pft_front_tracking_dist=pft_front_tracking_dist, particle_count=particle_count, return_all=True) else: raise ValueError('ERROR: No valid tracking method(s) specified.') # Filter resulting streamlines by those that stay entirely inside the brain roi_proximal_streamlines = utils.target(streamline_generator, np.eye(4), B0_mask_data, include=True) # Filter resulting streamlines by roi-intersection characteristics roi_proximal_streamlines = Streamlines(select_by_rois(roi_proximal_streamlines, affine=np.eye(4), rois=parcels, include=parcel_vec, mode='both_end', tol=roi_neighborhood_tol)) print("%s%s" % ('Filtering by: \nnode intersection: ', len(roi_proximal_streamlines))) if str(min_length) != '0': roi_proximal_streamlines = nib.streamlines.array_sequence.ArraySequence([s for s in roi_proximal_streamlines if len(s) >= float(min_length)]) print("%s%s" % ('Minimum length criterion: ', len(roi_proximal_streamlines))) if waymask: roi_proximal_streamlines = roi_proximal_streamlines[utils.near_roi(roi_proximal_streamlines, np.eye(4), waymask_data, tol=roi_neighborhood_tol, mode='any')] print("%s%s" % ('Waymask proximity: ', len(roi_proximal_streamlines))) out_streams = [s.astype('float32') for s in roi_proximal_streamlines] streamlines.extend(out_streams) stream_counter = stream_counter + len(out_streams) # Cleanup memory del seeds, roi_proximal_streamlines, streamline_generator, out_streams gc.collect() del dg circuit_ix = circuit_ix + 1 print("%s%s%s%s%s%s" % ('Completed Hyperparameter Circuit: ', circuit_ix, '\nCumulative Streamline Count: ', Fore.CYAN, stream_counter, "\n")) print(Style.RESET_ALL) print('Tracking Complete:\n', str(time.time() - start)) return streamlines