def test_eudx_further(): """ Cause we love testin.. ;-) """ fimg,fbvals,fbvecs=get_data('small_101D') img=ni.load(fimg) affine=img.get_affine() data=img.get_data() gtab = gradient_table(fbvals, fbvecs) tensor_model = TensorModel(gtab) ten = tensor_model.fit(data) x,y,z=data.shape[:3] seeds=np.zeros((10**4,3)) for i in range(10**4): rx=(x-1)*np.random.rand() ry=(y-1)*np.random.rand() rz=(z-1)*np.random.rand() seeds[i]=np.ascontiguousarray(np.array([rx,ry,rz]),dtype=np.float64) #print seeds #""" ind = quantize_evecs(ten.evecs) eu=EuDX(a=ten.fa, ind=ind, seeds=seeds, a_low=.2) T=[e for e in eu] #check that there are no negative elements for t in T: assert_equal(np.sum(t.ravel()<0),0)
def tens_mod_fa_est(gtab, dwi_file, B0_mask): """Estimate a tensor FA image to use for registrations using dipy functions Parameters ---------- gtab : GradientTable gradient table created from bval and bvec file dwi_file : str Path to eddy-corrected and RAS reoriented dwi image B0_mask : str Path to nodif B0 mask (averaged b0 mask) Returns ------- str Path to tensor_fa image file """ data = nib.load(dwi_file).get_fdata() print("Generating simple tensor FA image to use for registrations...") nodif_B0_img = nib.load(B0_mask) B0_mask_data = nodif_B0_img.get_fdata().astype("bool") nodif_B0_affine = nodif_B0_img.affine model = TensorModel(gtab) mod = model.fit(data, B0_mask_data) FA = fractional_anisotropy(mod.evals) FA[np.isnan(FA)] = 0 fa_img = nib.Nifti1Image(FA.astype(np.float32), nodif_B0_affine) fa_path = f"{os.path.dirname(B0_mask)}/tensor_fa.nii.gz" nib.save(fa_img, fa_path) return fa_path
def test_response_from_mask(): fdata, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) data = nib.load(fdata).get_data() gtab = gradient_table(bvals, bvecs) ten = TensorModel(gtab) tenfit = ten.fit(data) FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 radius = 3 for fa_thr in np.arange(0, 1, 0.1): response_auto, ratio_auto, nvoxels = auto_response( gtab, data, roi_center=None, roi_radius=radius, fa_thr=fa_thr, return_number_of_voxels=True) ci, cj, ck = np.array(data.shape[:3]) // 2 mask = np.zeros(data.shape[:3]) mask[ci - radius:ci + radius, cj - radius:cj + radius, ck - radius:ck + radius] = 1 mask[FA <= fa_thr] = 0 response_mask, ratio_mask = response_from_mask(gtab, data, mask) assert_equal(int(np.sum(mask)), nvoxels) assert_array_almost_equal(response_mask[0], response_auto[0]) assert_almost_equal(response_mask[1], response_auto[1]) assert_almost_equal(ratio_mask, ratio_auto)
def tens_mod_est(gtab, data, wm_in_dwi): ''' Estimate a tensor model from dwi data. Parameters ---------- gtab : Obj DiPy object storing diffusion gradient information data : array 4D numpy array of diffusion image data. wm_in_dwi : str File path to white-matter tissue segmentation Nifti1Image. Returns ------- tensor_odf : obj Tensor-estimated orientation distribution function. ''' from dipy.reconst.dti import TensorModel from dipy.data import get_sphere print('Fitting tensor model...') sphere = get_sphere('repulsion724') wm_in_dwi_mask = nib.load(wm_in_dwi).get_fdata().astype('bool') model = TensorModel(gtab) mod = model.fit(data, wm_in_dwi_mask) tensor_odf = mod.odf(sphere) return tensor_odf
def load_fibercup_tractography_derivatives_2D(): niftipath = 'data\\fibercup\\R3.nii.gz' bvalspath = 'data\\fibercup\\R3.bvals' bvecspath = 'data\\fibercup\\R3.bvecs' print("Fetching data") data, affine = load_nifti(niftipath) bvals, bvecs = read_bvals_bvecs(bvalspath, bvecspath) gtab = gradient_table(bvals, bvecs) print("Fitting tensor model...") tenmodel = TensorModel(gtab) tenfit = tenmodel.fit(data) quadratic_form = tenfit.quadratic_form evals, evecs = np.linalg.eig(quadratic_form) max_directions = np.argmax(evals, axis=2) directions = np.array([[[ evals[i, j, k][max_directions[i, j, k]] * evecs[i, j, k][max_directions[i, j, k]] for k in range(len(max_directions[0, 0])) ] for j in range(len(max_directions[0]))] for i in range(len(max_directions))]) return np.real(directions[:, :, 1, :2])
def compute_tensor_model(dir_src, dir_out, verbose=False): fbval = pjoin(dir_src, 'bvals_' + par_b_tag) fbvec = pjoin(dir_src, 'bvecs_' + par_b_tag) fdwi = pjoin(dir_src, 'data_' + par_b_tag + '_' + par_dim_tag + '.nii.gz') fmask = pjoin(dir_src, 'nodif_brain_mask_' + par_dim_tag + '.nii.gz') bvals, bvecs = read_bvals_bvecs(fbval, fbvec) gtab = gradient_table(bvals, bvecs, b0_threshold=par_b0_threshold) data, affine = load_nifti(fdwi, verbose) mask, _ = load_nifti(fmask, verbose) ten_model = TensorModel(gtab) ten_fit = ten_model.fit(data, mask) FA = ten_fit.fa MD = ten_fit.md EV = ten_fit.evecs.astype(np.float32) fa_name = 'data_' + par_b_tag + '_' + par_dim_tag + '_FA.nii.gz' save_nifti(pjoin(dir_out, fa_name), FA, affine) md_name = 'data_' + par_b_tag + '_' + par_dim_tag + '_MD.nii.gz' save_nifti(pjoin(dir_out, md_name), MD, affine) ev_name = 'data_' + par_b_tag + '_' + par_dim_tag + '_EV.nii.gz' save_nifti(pjoin(dir_out, ev_name), EV, affine)
def test_masked_array_with_tensor(): data = np.ones((2, 4, 56)) mask = np.array([[True, False, False, True], [True, False, True, False]]) bvec, bval = read_bvec_file(get_data('55dir_grad.bvec')) gtab = grad.gradient_table_from_bvals_bvecs(bval, bvec.T) tensor_model = TensorModel(gtab) tensor = tensor_model.fit(data, mask=mask) assert_equal(tensor.shape, (2, 4)) assert_equal(tensor.fa.shape, (2, 4)) assert_equal(tensor.evals.shape, (2, 4, 3)) assert_equal(tensor.evecs.shape, (2, 4, 3, 3)) tensor = tensor[0] assert_equal(tensor.shape, (4,)) assert_equal(tensor.fa.shape, (4,)) assert_equal(tensor.evals.shape, (4, 3)) assert_equal(tensor.evecs.shape, (4, 3, 3)) tensor = tensor[0] assert_equal(tensor.shape, tuple()) assert_equal(tensor.fa.shape, tuple()) assert_equal(tensor.evals.shape, (3,)) assert_equal(tensor.evecs.shape, (3, 3)) assert_equal(type(tensor.model_params), np.ndarray)
def tens_mod_fa_est(gtab_file, dwi_file, B0_mask): """ Estimate a tensor FA image to use for registrations. Parameters ---------- gtab_file : str File path to pickled DiPy gradient table object. dwi_file : str File path to diffusion weighted image. B0_mask : str File path to B0 brain mask. Returns ------- fa_path : str File path to FA Nifti1Image. B0_mask : str File path to B0 brain mask Nifti1Image. gtab_file : str File path to pickled DiPy gradient table object. dwi_file : str File path to diffusion weighted Nifti1Image. fa_md_path : str File path to FA/MD mask Nifti1Image. """ import os from dipy.io import load_pickle from dipy.reconst.dti import TensorModel from dipy.reconst.dti import fractional_anisotropy, mean_diffusivity gtab = load_pickle(gtab_file) data = nib.load(dwi_file).get_fdata() print("Generating tensor FA image to use for registrations...") nodif_B0_img = nib.load(B0_mask) nodif_B0_mask_data = np.nan_to_num(np.asarray( nodif_B0_img.dataobj)).astype("bool") model = TensorModel(gtab) mod = model.fit(data, nodif_B0_mask_data) FA = fractional_anisotropy(mod.evals) MD = mean_diffusivity(mod.evals) FA_MD = np.logical_or(FA >= 0.2, (np.logical_and(FA >= 0.08, MD >= 0.0011))) FA[np.isnan(FA)] = 0 FA_MD[np.isnan(FA_MD)] = 0 fa_path = f"{os.path.dirname(B0_mask)}{'/tensor_fa.nii.gz'}" nib.save(nib.Nifti1Image(FA.astype(np.float32), nodif_B0_img.affine), fa_path) fa_md_path = f"{os.path.dirname(B0_mask)}{'/tensor_fa_md.nii.gz'}" nib.save(nib.Nifti1Image(FA_MD.astype(np.float32), nodif_B0_img.affine), fa_md_path) nodif_B0_img.uncache() del FA, FA_MD return fa_path, B0_mask, gtab_file, dwi_file
def test_eudx_bad_seed(): """Test passing a bad seed to eudx""" fimg, fbvals, fbvecs = get_data('small_101D') img = ni.load(fimg) affine = img.get_affine() data = img.get_data() gtab = gradient_table(fbvals, fbvecs) tensor_model = TensorModel(gtab) ten = tensor_model.fit(data) ind = quantize_evecs(ten.evecs) sphere = get_sphere('symmetric724') seed = [1000000., 1000000., 1000000.] eu = EuDX(a=ten.fa, ind=ind, seeds=[seed], odf_vertices=sphere.vertices, a_low=.2) assert_raises(ValueError, list, eu) print(data.shape) seed = [1., 5., 8.] eu = EuDX(a=ten.fa, ind=ind, seeds=[seed], odf_vertices=sphere.vertices, a_low=.2) track = list(eu) seed = [-1., 1000000., 1000000.] eu = EuDX(a=ten.fa, ind=ind, seeds=[seed], odf_vertices=sphere.vertices, a_low=.2) assert_raises(ValueError, list, eu)
def test_phantom(): N = 50 vol = orbital_phantom(gtab, func=f, t=np.linspace(0, 2 * np.pi, N), datashape=(10, 10, 10, len(bvals)), origin=(5, 5, 5), scale=(3, 3, 3), angles=np.linspace(0, 2 * np.pi, 16), radii=np.linspace(0.2, 2, 6), S0=100) m = TensorModel(gtab) t = m.fit(vol) FA = t.fa # print vol FA[np.isnan(FA)] = 0 # 686 -> expected FA given diffusivities of [1500, 400, 400] l1, l2, l3 = 1500e-6, 400e-6, 400e-6 expected_fa = (np.sqrt(0.5) * np.sqrt((l1 - l2)**2 + (l2 - l3)**2 + (l3 - l1)**2) / np.sqrt(l1**2 + l2**2 + l3**2)) assert_array_almost_equal(FA.max(), expected_fa, decimal=2)
def response_from_mask_ssst(gtab, data, mask): """ Computation of single-shell single-tissue (ssst) response function from a given mask. Parameters ---------- gtab : GradientTable data : ndarray diffusion data mask : ndarray mask from where to compute the response function Returns ------- response : tuple, (2,) (`evals`, `S0`) ratio : float The ratio between smallest versus largest eigenvalue of the response. Notes ----- In CSD there is an important pre-processing step: the estimation of the fiber response function. In order to do this, we look for voxels with very anisotropic configurations. This information can be obtained by using csdeconv.mask_for_response_ssst() through a mask of selected voxels (see[1]_). The present function uses such a mask to compute the ssst response function. For the response we also need to find the average S0 in the ROI. This is possible using `gtab.b0s_mask()` we can find all the S0 volumes (which correspond to b-values equal 0) in the dataset. The `response` consists always of a prolate tensor created by averaging the highest and second highest eigenvalues in the ROI with FA higher than threshold. We also include the average S0s. We also return the `ratio` which is used for the SDT models. References ---------- .. [1] Tournier, J.D., et al. NeuroImage 2004. Direct estimation of the fiber orientation density function from diffusion-weighted MRI data using spherical deconvolution """ ten = TensorModel(gtab) indices = np.where(mask > 0) if indices[0].size == 0: msg = "No voxel in mask with value > 0 were found." warnings.warn(msg, UserWarning) return (np.nan, np.nan), np.nan tenfit = ten.fit(data[indices]) lambdas = tenfit.evals[:, :2] S0s = data[indices][:, np.nonzero(gtab.b0s_mask)[0]] return _get_response(S0s, lambdas)
def execution(self, context): gtab = load(self.gradient_table.fullPath()) tensor = TensorModel(gtab, fit_method=self.method) dump(tensor, self.model.fullPath(), compress=9) #handling metadata: self.model.setMinf('gradient_table', self.gradient_table.uuid()) self.model.setMinf('fitting_method', self.method) self.model.setMinf('model_type', 'dti') context.write("Process finish successfully")
def test_fit_method_error(): bvec, bval = read_bvec_file(get_data('55dir_grad.bvec')) gtab = grad.gradient_table_from_bvals_bvecs(bval, bvec.T) # This should work (smoke-testing!): TensorModel(gtab, fit_method='WLS') # This should raise an error because there is no such fit_method assert_raises(ValueError, TensorModel, gtab, min_signal=1e-9, fit_method='s')
def make_tensor(self, b0_mask): """Create the tensor """ from dipy.reconst.dti import TensorModel tensor_model = TensorModel(self.gtab) tensor_fit = tensor_model.fit(b0_mask) fa = tensor_fit.fa self.save_plot(fa2[:, :, 35].T, f"{self.subj_id}tensor")
def tens_mod_est(self): print("Fitting tensor model...") self.model = TensorModel(self.gtab) self.ten = self.model.fit(self.data, self.wm_in_dwi_data) self.fa = self.ten.fa self.fa[np.isnan(self.fa)] = 0 self.sphere = get_sphere("repulsion724") self.ind = quantize_evecs(self.ten.evecs, self.sphere.vertices) return self.ten
def tens_mod_est(gtab, data, wm_in_dwi): from dipy.reconst.dti import TensorModel from dipy.data import get_sphere print('Fitting tensor model...') sphere = get_sphere('repulsion724') wm_in_dwi_mask = nib.load(wm_in_dwi).get_fdata().astype('bool') model = TensorModel(gtab) mod = model.fit(data, wm_in_dwi_mask) tensor_odf = mod.odf(sphere) return tensor_odf
def test_eudx_further(): """ Cause we love testin.. ;-) """ fimg,fbvals,fbvecs=get_data('small_101D') img=ni.load(fimg) affine=img.get_affine() data=img.get_data() gtab = gradient_table(fbvals, fbvecs) tensor_model = TensorModel(gtab) ten = tensor_model.fit(data) x,y,z=data.shape[:3] seeds=np.zeros((10**4,3)) for i in range(10**4): rx=(x-1)*np.random.rand() ry=(y-1)*np.random.rand() rz=(z-1)*np.random.rand() seeds[i]=np.ascontiguousarray(np.array([rx,ry,rz]),dtype=np.float64) sphere = get_sphere('symmetric724') ind = quantize_evecs(ten.evecs) eu=EuDX(a=ten.fa, ind=ind, seeds=seeds, odf_vertices=sphere.vertices, a_low=.2) T=[e for e in eu] #check that there are no negative elements for t in T: assert_equal(np.sum(t.ravel()<0),0) # Test eudx with affine def random_affine(seeds): affine = np.eye(4) affine[:3, :] = np.random.random((3, 4)) seeds = np.dot(seeds, affine[:3, :3].T) seeds += affine[:3, 3] return affine, seeds # Make two random affines and move seeds affine1, seeds1 = random_affine(seeds) affine2, seeds2 = random_affine(seeds) # Make tracks using different affines eu1 = EuDX(a=ten.fa, ind=ind, odf_vertices=sphere.vertices, seeds=seeds1, a_low=.2, affine=affine1) eu2 = EuDX(a=ten.fa, ind=ind, odf_vertices=sphere.vertices, seeds=seeds2, a_low=.2, affine=affine2) # Move from eu2 affine2 to affine1 eu2_to_eu1 = utils.move_streamlines(eu2, output_space=affine1, input_space=affine2) # Check that the tracks are the same for sl1, sl2 in zip(eu1, eu2_to_eu1): assert_array_almost_equal(sl1, sl2)
def test_single_tensor(): evals = np.array([1.4, .35, .35]) * 10**(-3) evecs = np.eye(3) S = single_tensor(gtab, 100, evals, evecs, snr=None) assert_array_almost_equal(S[gtab.b0s_mask], 100) assert_(np.mean(S[~gtab.b0s_mask]) < 100) from dipy.reconst.dti import TensorModel m = TensorModel(gtab) t = m.fit(S) assert_array_almost_equal(t.fa, 0.707, decimal=3)
def tractography(img, gtab, mask, dwi_dir, do_viz=True): data = img.get_data() # dirty imputation data[np.isnan(data)] = 0 # Diffusion model csd_model = ConstrainedSphericalDeconvModel(gtab, response=None) sphere = get_sphere('symmetric724') csd_peaks = peaks_from_model(model=csd_model, data=data, sphere=sphere, mask=mask, relative_peak_threshold=.5, min_separation_angle=25, parallel=False) # FA values to stop the tractography tensor_model = TensorModel(gtab, fit_method='WLS') tensor_fit = tensor_model.fit(data, mask) fa = fractional_anisotropy(tensor_fit.evals) stopping_values = np.zeros(csd_peaks.peak_values.shape) stopping_values[:] = fa[..., None] # tractography streamline_generator = EuDX(stopping_values, csd_peaks.peak_indices, seeds=10**6, odf_vertices=sphere.vertices, a_low=0.1) streamlines = [streamline for streamline in streamline_generator] streamlines = filter_according_to_length(streamlines) np.savez(os.path.join(dwi_dir, 'streamlines.npz'), streamlines) # write the result as images hdr = nib.trackvis.empty_header() hdr['voxel_size'] = img.header.get_zooms()[:3] hdr['voxel_order'] = 'LAS' hdr['dim'] = fa.shape[:3] csd_streamlines_trk = ((sl, None, None) for sl in streamlines) csd_sl_fname = os.path.join(dwi_dir, 'csd_streamline.trk') nib.trackvis.write(csd_sl_fname, csd_streamlines_trk, hdr, points_space='voxel') fa_image = os.path.join(dwi_dir, 'fa_map.nii.gz') nib.save(nib.Nifti1Image(fa, img.affine), fa_image) if 1: visualization(os.path.join(dwi_dir, 'streamlines.npz')) return streamlines
def __init__(self, gtab, split_b_D=200.0, n_threads=1): """ Model to reconstruct an IVIM tensor Parameters ---------- gtab : GradientTable class instance split_b_D : float The value of b that separates perfusion from diffusion """ ReconstModel.__init__(self, gtab) self.split_b_D = split_b_D # Use two separate tensors for initial estimation: self.diffusion_idx = np.hstack( [np.where(gtab.bvals > self.split_b_D), np.where(gtab.b0s_mask)]).squeeze() # The first tensor represents diffusion self.diffusion_gtab = gradient_table( self.gtab.bvals[self.diffusion_idx], self.gtab.bvecs[self.diffusion_idx]) self.diffusion_model = TensorModel(self.diffusion_gtab) # The second tensor represents perfusion: self.perfusion_idx = np.array( np.where(gtab.bvals <= self.split_b_D)).squeeze() self.perfusion_gtab = gradient_table( self.gtab.bvals[self.perfusion_idx], self.gtab.bvecs[self.perfusion_idx]) self.perfusion_model = TensorModel(self.perfusion_gtab) # We'll need a "vanilla" IVIM model: self.ivim_model = IvimModel(self.gtab) # How many threads in parallel execution: self.n_threads = n_threads
def track(self): SeedBasedTracker.track(self) if self.streamlines is not None: return dti_model = TensorModel(self.data.gtab) dti_fit = dti_model.fit(self.data.dwi, mask=self.data.binarymask) dti_fit_odf = dti_fit.odf(sphere=default_sphere) max_angle = Config.get_config().getfloat("DTITracking", "maxAngle", fallback="30.0") direction_getter = DeterministicMaximumDirectionGetter.from_pmf(dti_fit_odf, max_angle=max_angle, sphere=default_sphere) self._track(ThresholdStoppingCriterion(dti_fit.fa, self.options.fa_threshold), direction_getter) Cache.get_cache().set(self.id, self.streamlines)
def get_dti_streamlines(data_container, random_seeds=False, seeds_count=30000, seeds_per_voxel=False, step_width=1.0, max_angle=30.0, fa_threshold=0.15): """ Tracks and returns CSD Streamlines for the given DataContainer. Parameters ---------- data_container The DataContainer we would like to track streamlines on random_seeds A boolean indicating whether we would like to use random seeds seeds_count If we use random seeds, this specifies the seed count seeds_per_voxel If True, the seed count is specified per voxel step_width The step width used while tracking fa_threshold The FA threshold to use to stop tracking max_angle The maximum allowed angle between incoming and outgoing angle, float between 0.0 and 90.0 deg Returns ------- Streamlines A list of Streamlines """ seeds = _get_seeds(data_container, random_seeds, seeds_count, seeds_per_voxel) dti_fit = TensorModel(data_container.gtab).fit( data_container.dwi, mask=data_container.binary_mask) dti_fit_odf = dti_fit.odf(sphere=default_sphere) direction_getter = DeterministicMaximumDirectionGetter.from_pmf( dti_fit_odf, max_angle=max_angle, sphere=default_sphere) classifier = ThresholdStoppingCriterion(dti_fit.fa, fa_threshold) streamlines_generator = LocalTracking(direction_getter, classifier, seeds, data_container.aff, step_size=step_width) streamlines = Streamlines(streamlines_generator) return streamlines
def test_boot_pmf(): # This tests the local model used for the bootstrapping. hsph_updated = HemiSphere.from_sphere(unit_octahedron) vertices = hsph_updated.vertices bvecs = vertices bvals = np.ones(len(vertices)) * 1000 bvecs = np.insert(bvecs, 0, np.array([0, 0, 0]), axis=0) bvals = np.insert(bvals, 0, 0) gtab = gradient_table(bvals, bvecs) voxel = single_tensor(gtab) data = np.tile(voxel, (3, 3, 3, 1)) point = np.array([1., 1., 1.]) tensor_model = TensorModel(gtab) boot_pmf_gen = BootPmfGen(data, model=tensor_model, sphere=hsph_updated) no_boot_pmf = boot_pmf_gen.get_pmf_no_boot(point) model_pmf = tensor_model.fit(voxel).odf(hsph_updated) npt.assert_equal(len(hsph_updated.vertices), no_boot_pmf.shape[0]) npt.assert_array_almost_equal(no_boot_pmf, model_pmf) # test model spherical harmonic order different than bootstrap order with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", category=UserWarning) csd_model = ConstrainedSphericalDeconvModel(gtab, response, sh_order=6) # Tests that the first catched warning comes from # the CSD model constructor npt.assert_(issubclass(w[0].category, UserWarning)) npt.assert_("Number of parameters required " in str(w[0].message)) # Tests that additionnal warnings are raised for outdated SH basis npt.assert_(len(w) > 1) boot_pmf_gen_sh4 = BootPmfGen(data, model=csd_model, sphere=hsph_updated, sh_order=4) pmf_sh4 = boot_pmf_gen_sh4.get_pmf(point) npt.assert_equal(len(hsph_updated.vertices), pmf_sh4.shape[0]) npt.assert_(np.sum(pmf_sh4.shape) > 0) boot_pmf_gen_sh8 = BootPmfGen(data, model=csd_model, sphere=hsph_updated, sh_order=8) pmf_sh8 = boot_pmf_gen_sh8.get_pmf(point) npt.assert_equal(len(hsph_updated.vertices), pmf_sh8.shape[0]) npt.assert_(np.sum(pmf_sh8.shape) > 0)
def response_from_mask(gtab, data, mask): """ Estimate the response function from a given mask. Parameters ---------- gtab : GradientTable data : ndarray Diffusion data mask : ndarray Mask to use for the estimation of the response function. For example a mask of the white matter voxels with FA values higher than 0.7 (see [1]_). Returns ------- response : tuple, (2,) (`evals`, `S0`) ratio : float The ratio between smallest versus largest eigenvalue of the response. Notes ----- See csdeconv.auto_response() or csdeconv.recursive_response() if you don't have a computed mask for the response function estimation. References ---------- .. [1] Tournier, J.D., et al. NeuroImage 2004. Direct estimation of the fiber orientation density function from diffusion-weighted MRI data using spherical deconvolution """ ten = TensorModel(gtab) indices = np.where(mask > 0) if indices[0].size == 0: msg = "No voxel in mask with value > 0 were found." warnings.warn(msg, UserWarning) return (np.nan, np.nan), np.nan tenfit = ten.fit(data[indices]) lambdas = tenfit.evals[:, :2] S0s = data[indices][:, np.nonzero(gtab.b0s_mask)[0]] return _get_response(S0s, lambdas)
def test_boot_pmf(): """This tests the local model used for the bootstrapping. """ hsph_updated = HemiSphere.from_sphere(unit_octahedron) vertices = hsph_updated.vertices bvecs = vertices bvals = np.ones(len(vertices)) * 1000 bvecs = np.insert(bvecs, 0, np.array([0, 0, 0]), axis=0) bvals = np.insert(bvals, 0, 0) gtab = gradient_table(bvals, bvecs) voxel = single_tensor(gtab) data = np.tile(voxel, (3, 3, 3, 1)) point = np.array([1., 1., 1.]) tensor_model = TensorModel(gtab) boot_pmf_gen = BootPmfGen(data, model=tensor_model, sphere=hsph_updated) no_boot_pmf = boot_pmf_gen.get_pmf_no_boot(point) model_pmf = tensor_model.fit(voxel).odf(hsph_updated) npt.assert_equal(len(hsph_updated.vertices), no_boot_pmf.shape[0]) npt.assert_array_almost_equal(no_boot_pmf, model_pmf) # test model spherical harmonic order different than bootstrap order with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", category=UserWarning) csd_model = ConstrainedSphericalDeconvModel(gtab, None, sh_order=6) assert_greater( len([lw for lw in w if issubclass(lw.category, UserWarning)]), 0) boot_pmf_gen_sh4 = BootPmfGen(data, model=csd_model, sphere=hsph_updated, sh_order=4) pmf_sh4 = boot_pmf_gen_sh4.get_pmf(point) npt.assert_equal(len(hsph_updated.vertices), pmf_sh4.shape[0]) npt.assert_(np.sum(pmf_sh4.shape) > 0) boot_pmf_gen_sh8 = BootPmfGen(data, model=csd_model, sphere=hsph_updated, sh_order=8) pmf_sh8 = boot_pmf_gen_sh8.get_pmf(point) npt.assert_equal(len(hsph_updated.vertices), pmf_sh8.shape[0]) npt.assert_(np.sum(pmf_sh8.shape) > 0)
def tens_mod_fa_est(gtab_file, dwi_file, B0_mask): ''' Estimate a tensor FA image to use for registrations. Parameters ---------- gtab_file : str File path to pickled DiPy gradient table object. dwi_file : str File path to diffusion weighted image. B0_mask : str File path to B0 brain mask. Returns ------- fa_path : str File path to FA Nifti1Image. B0_mask : str File path to B0 brain mask Nifti1Image. gtab_file : str File path to pickled DiPy gradient table object. dwi_file : str File path to diffusion weighted Nifti1Image. ''' import os from dipy.io import load_pickle from dipy.reconst.dti import TensorModel from dipy.reconst.dti import fractional_anisotropy data = nib.load(dwi_file).get_fdata() gtab = load_pickle(gtab_file) print('Generating simple tensor FA image to use for registrations...') nodif_B0_img = nib.load(B0_mask) B0_mask_data = nodif_B0_img.get_fdata().astype('bool') nodif_B0_affine = nodif_B0_img.affine model = TensorModel(gtab) mod = model.fit(data, B0_mask_data) FA = fractional_anisotropy(mod.evals) FA[np.isnan(FA)] = 0 fa_img = nib.Nifti1Image(FA.astype(np.float32), nodif_B0_affine) fa_path = "%s%s" % (os.path.dirname(B0_mask), '/tensor_fa.nii.gz') nib.save(fa_img, fa_path) return fa_path, B0_mask, gtab_file, dwi_file
def track_gen_model(brain_mask_file, dwi_data_file, dwi_bval_file, dwi_bvec_file): img_mask = nib.load(brain_mask_file) img, gtab = dwi.get_dwi_img_gtab(dwi_data_file, dwi_bval_file, dwi_bvec_file) data_mask = img_mask.get_data() affine = img.get_affine() data = img.get_data() model = TensorModel(gtab) ten = model.fit(data, mask=data_mask) sphere = get_sphere('symmetric724') ind = quantize_evecs(ten.evecs, sphere.vertices) p = Struct() p.affine = affine p.sphere = sphere p.ten = ten p.ind = ind return p
def eudx_basic(self, dti_file, mask_file, gtab, stop_val=0.1): """ Tracking with basic tensors and basic eudx - experimental We now force seeding at every voxel in the provided mask for simplicity. Future functionality will extend these options. **Positional Arguments:** dti_file: - File (registered) to use for tensor/fiber tracking mask_file: - Brain mask to keep tensors inside the brain gtab: - dipy formatted bval/bvec Structure **Optional Arguments:** stop_val: - Value to cutoff fiber track """ img = nb.load(dti_file) data = img.get_data() img = nb.load(mask_file) mask = img.get_data() # use all points in mask seedIdx = np.where(mask > 0) # seed everywhere not equal to zero seedIdx = np.transpose(seedIdx) model = TensorModel(gtab) ten = model.fit(data, mask) sphere = get_sphere('symmetric724') ind = quantize_evecs(ten.evecs, sphere.vertices) eu = EuDX(a=ten.fa, ind=ind, seeds=seedIdx, odf_vertices=sphere.vertices, a_low=stop_val) tracks = [e for e in eu] return (ten, tracks)
def tens_mod_est(gtab, data, B0_mask): """ Estimate a tensor ODF model from dwi data. Parameters ---------- gtab : Obj DiPy object storing diffusion gradient information data : array 4D numpy array of diffusion image data. B0_mask : str File path to B0 brain mask. Returns ------- mod_odf : ndarray Coefficients of the tensor reconstruction. model : obj Fitted tensor model. References ---------- .. [1] Basser PJ, Mattielo J, LeBihan (1994). MR diffusion tensor spectroscopy and imaging. .. [2] Pajevic S, Pierpaoli (1999). Color schemes to represent the orientation of anisotropic tissues from diffusion tensor data: application to white matter fiber tract mapping in the human brain. """ from dipy.reconst.dti import TensorModel from dipy.data import get_sphere sphere = get_sphere("repulsion724") B0_mask_data = np.nan_to_num(np.asarray( nib.load(B0_mask).dataobj)).astype("bool") print("Generating tensor model...") model = TensorModel(gtab) mod = model.fit(data, B0_mask_data) mod_odf = mod.odf(sphere) del B0_mask_data return mod_odf, model
def make_tensorfit(data, mask, gtab, affine, subject, outpath, overwrite=False, forcestart=False, verbose=None): #Given dwi data, a mask, and other relevant information, creates the fa and saves it to outpath, unless #if it already exists, in which case it simply returns the fa from dipy.reconst.dti import TensorModel outpathbmfa, exists, _ = check_for_fa(outpath, subject, getdata=False) if exists and not forcestart: fa = load_nifti(outpathbmfa) fa_array = fa[0] if verbose: txt = "FA already computed at " + outpathbmfa print(txt) return outpathbmfa, fa_array else: if verbose: print('Calculating the tensor model from bval/bvec values of ', subject) tensor_model = TensorModel(gtab) t1 = time() if len(mask.shape) == 4: mask = mask[..., 0] tensor_fit = tensor_model.fit(data, mask) duration1 = time() - t1 if verbose: print(subject + ' DTI duration %.3f' % (duration1, )) save_nifti(outpathbmfa, tensor_fit.fa, affine) if verbose: print('Saving subject' + subject + ' at ' + outpathbmfa) return outpathbmfa, tensor_fit.fa