def test_gfa(self): signal, gtab, expected = make_fake_signal() signal = np.ones((2, 3, 4, 1)) * signal sphere = hemi_icosahedron.subdivide(3) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) model = self.model(gtab, 6, min_signal=1e-5) fit = model.fit(signal) gfa_shm = fit.gfa with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) gfa_odf = odf.gfa(fit.odf(sphere)) assert_array_almost_equal(gfa_shm, gfa_odf, 3) # gfa should be 0 if all coefficients are 0 (masked areas) mask = np.zeros(signal.shape[:-1]) fit = model.fit(signal, mask) assert_array_equal(fit.gfa, 0)
def test_gfa(): g = gfa(np.ones(100)) assert_equal(g, 0) g = gfa(np.ones((2, 100))) assert_equal(g, np.array([0, 0])) # The following series follows the rule (sqrt(n-1)/((n-1)^2)) g = gfa(np.hstack([np.ones((9)), [0]])) assert_almost_equal(g, np.sqrt(9./81)) g = gfa(np.hstack([np.ones((99)), [0]])) assert_almost_equal(g, np.sqrt(99./(99.**2))) # All-zeros returns a nan with no warning: g = gfa(np.zeros(10)) assert_(np.isnan(g))
def odf(self, sphere): r""" Calculates the real discrete odf for a given discrete sphere ..math:: :nowrap: \begin{equation} \psi_{DSI}(\hat{\mathbf{u}})=\int_{0}^{\infty}P(r\hat{\mathbf{u}})r^{2}dr \end{equation} where $\hat{\mathbf{u}}$ is the unit vector which corresponds to a sphere point. """ interp_coords = self.model.cache_get('interp_coords', key=sphere) if interp_coords is None: interp_coords = pdf_interp_coords(sphere, self.model.qradius, self.model.origin) self.model.cache_set('interp_coords', sphere, interp_coords) Pr = self.pdf() #calculate the orientation distribution function odf = pdf_odf(Pr, sphere, self.model.qradius, interp_coords) # We compute the gfa here, since we have the ODF available and # the storage requirements are minimal. Otherwise, we'd need to # recompute the ODF at significant computational expense. self._gfa = gfa(odf) pk, ind = local_maxima(odf, sphere.edges) relative_peak_threshold = self.model.direction_finder._config["relative_peak_threshold"] min_separation_angle = self.model.direction_finder._config["min_separation_angle"] # Remove small peaks. gt_threshold = pk >= (relative_peak_threshold * pk[0]) pk = pk[gt_threshold] ind = ind[gt_threshold] # Keep peaks which are unique, which means remove peaks that are too # close to a larger peak. _, where_uniq = remove_similar_vertices(sphere.vertices[ind], min_separation_angle, return_index=True) pk = pk[where_uniq] ind = ind[where_uniq] # Calculate peak metrics #global_max = max(global_max, pk[0]) n = min(self.npeaks, len(pk)) #qa_array[i, :n] = pk[:n] - odf.min() self._peak_values = np.zeros(self.npeaks) self._peak_indices = np.zeros(self.npeaks) if self.model.normalize_peaks: self._peak_values[:n] = pk[:n] / pk[0] else: self._peak_values[:n] = pk[:n] self._peak_indices[:n] = ind[:n] return odf
def test_peaksFromModel(): data = np.zeros((10, 2)) # Test basic case model = SimpleOdfModel(_gtab) odf_argmax = _odf.argmax() pam = peaks_from_model(model, data, _sphere, .5, 45, normalize_peaks=True) assert_array_equal(pam.gfa, gfa(_odf)) assert_array_equal(pam.peak_values[:, 0], 1.) assert_array_equal(pam.peak_values[:, 1:], 0.) mn, mx = _odf.min(), _odf.max() assert_array_equal(pam.qa[:, 0], (mx - mn) / mx) assert_array_equal(pam.qa[:, 1:], 0.) assert_array_equal(pam.peak_indices[:, 0], odf_argmax) assert_array_equal(pam.peak_indices[:, 1:], -1) # Test that odf array matches and is right shape pam = peaks_from_model(model, data, _sphere, .5, 45, return_odf=True) expected_shape = (len(data), len(_odf)) assert_equal(pam.odf.shape, expected_shape) assert_((_odf == pam.odf).all()) assert_array_equal(pam.peak_values[:, 0], _odf.max()) # Test mask mask = (np.arange(10) % 2) == 1 pam = peaks_from_model(model, data, _sphere, .5, 45, mask=mask, normalize_peaks=True) assert_array_equal(pam.gfa[~mask], 0) assert_array_equal(pam.qa[~mask], 0) assert_array_equal(pam.peak_values[~mask], 0) assert_array_equal(pam.peak_indices[~mask], -1) assert_array_equal(pam.gfa[mask], gfa(_odf)) assert_array_equal(pam.peak_values[mask, 0], 1.) assert_array_equal(pam.peak_values[mask, 1:], 0.) mn, mx = _odf.min(), _odf.max() assert_array_equal(pam.qa[mask, 0], (mx - mn) / mx) assert_array_equal(pam.qa[mask, 1:], 0.) assert_array_equal(pam.peak_indices[mask, 0], odf_argmax) assert_array_equal(pam.peak_indices[mask, 1:], -1)
def test_TensorModel(): data, gtab = dsi_voxels() dm = dti.TensorModel(gtab, 'LS') dtifit = dm.fit(data[0, 0, 0]) assert_equal(dtifit.fa < 0.5, True) dm = dti.TensorModel(gtab, 'WLS') dtifit = dm.fit(data[0, 0, 0]) assert_equal(dtifit.fa < 0.5, True) sphere = create_unit_sphere(4) assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices)) assert_almost_equal(dtifit.fa, gfa(dtifit.odf(sphere)), 1) # Check that the multivoxel case works: dtifit = dm.fit(data) assert_equal(dtifit.fa.shape, data.shape[:3]) # Make some synthetic data b0 = 1000. bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec')) gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T) # The first b value is 0., so we take the second one: B = bvals[1] #Scale the eigenvalues and tensor by the B value so the units match D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B evals = np.array([2., 1., 0.]) / B md = evals.mean() tensor = from_lower_triangular(D) evecs = np.linalg.eigh(tensor)[1] #Design Matrix X = dti.design_matrix(bvecs, bvals) #Signals Y = np.exp(np.dot(X,D)) assert_almost_equal(Y[0], b0) Y.shape = (-1,) + Y.shape # Test fitting with different methods: #XXX Add NNLS methods! for fit_method in ['OLS', 'WLS']: tensor_model = dti.TensorModel(gtab, fit_method=fit_method) tensor_fit = tensor_model.fit(Y) assert_true(tensor_fit.model is tensor_model) assert_equal(tensor_fit.shape, Y.shape[:-1]) assert_array_almost_equal(tensor_fit.evals[0], evals) assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor, err_msg =\ "Calculation of tensor from Y does not compare to analytical solution") assert_almost_equal(tensor_fit.md[0], md) assert_equal(tensor_fit.directions.shape[-2], 1) assert_equal(tensor_fit.directions.shape[-1], 3) # Test error-handling: assert_raises(ValueError, dti.TensorModel, gtab, fit_method='crazy_method')
def test_gfa(self): signal, gtab, expected = make_fake_signal() signal = np.ones((2, 3, 4, 1)) * signal sphere = hemi_icosahedron.subdivide(3) model = self.model(gtab, 6, min_signal=1e-5) fit = model.fit(signal) gfa_shm = fit.gfa gfa_odf = odf.gfa(fit.odf(sphere)) assert_array_almost_equal(gfa_shm, gfa_odf, 3)
def test_mapmri_odf(radial_order=6): gtab = get_gtab_taiwan_dsi() # load repulsion 724 sphere sphere = default_sphere # load icosahedron sphere l1, l2, l3 = [0.0015, 0.0003, 0.0003] data, golden_directions = generate_signal_crossing(gtab, l1, l2, l3, angle2=90) mapmod = MapmriModel(gtab, radial_order=radial_order, laplacian_regularization=True, laplacian_weighting=0.01) # repulsion724 sphere2 = create_unit_sphere(5) mapfit = mapmod.fit(data) odf = mapfit.odf(sphere) directions, _, _ = peak_directions(odf, sphere, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) # 5 subdivisions odf = mapfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] asmfit = mapmod.fit(data) odf = asmfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) if len(directions) <= 3: assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(odf) < 0.1, True) # for the isotropic implementation check if the odf spherical harmonics # actually represent the discrete sphere function. mapmod = MapmriModel(gtab, radial_order=radial_order, laplacian_regularization=True, laplacian_weighting=0.01, anisotropic_scaling=False) mapfit = mapmod.fit(data) odf = mapfit.odf(sphere) odf_sh = mapfit.odf_sh() odf_from_sh = sh_to_sf(odf_sh, sphere, radial_order, basis_type=None) assert_almost_equal(odf, odf_from_sh, 10)
def peaks_from_odfs(odf4d, sphere, relative_peak_threshold, min_separation_angle, mask=None, gfa_thr=0, normalize_peaks=False, npeaks=5): shape = odf4d.shape[:-1] if mask is None: mask = np.ones(shape, dtype='bool') else: if mask.shape != shape: raise ValueError("Mask is not the same shape as data.") gfa_array = np.zeros(shape) qa_array = np.zeros((shape + (npeaks, ))) peak_dirs = np.zeros((shape + (npeaks, 3))) peak_values = np.zeros((shape + (npeaks, ))) peak_indices = np.zeros((shape + (npeaks, )), dtype='int') peak_indices.fill(-1) global_max = -np.inf for idx in ndindex(shape): if not mask[idx]: continue odf = odf4d[idx] gfa_array[idx] = gfa(odf) if gfa_array[idx] < gfa_thr: global_max = max(global_max, odf.max()) continue # Get peaks of odf direction, pk, ind = peak_directions(odf, sphere, relative_peak_threshold, min_separation_angle) # Calculate peak metrics if pk.shape[0] != 0: global_max = max(global_max, pk[0]) n = min(npeaks, pk.shape[0]) qa_array[idx][:n] = pk[:n] - odf.min() peak_dirs[idx][:n] = direction[:n] peak_indices[idx][:n] = ind[:n] peak_values[idx][:n] = pk[:n] if normalize_peaks: peak_values[idx][:n] /= pk[0] peak_dirs[idx] *= peak_values[idx][:, None] qa_array /= global_max return peak_dirs, peak_values
def test_shore_odf(): gtab = get_isbi2013_2shell_gtab() # load repulsion 724 sphere sphere = default_sphere # load icosahedron sphere sphere2 = create_unit_sphere(5) data, golden_directions = sticks_and_ball(gtab, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) asm = ShoreModel(gtab, radial_order=6, zeta=700, lambdaN=1e-8, lambdaL=1e-8) # repulsion724 asmfit = asm.fit(data) odf = asmfit.odf(sphere) odf_sh = asmfit.odf_sh() odf_from_sh = sh_to_sf(odf_sh, sphere, 6, basis_type=None, legacy=True) npt.assert_almost_equal(odf, odf_from_sh, 10) expected_phi = shore_matrix(radial_order=6, zeta=700, gtab=gtab) npt.assert_array_almost_equal(np.dot(expected_phi, asmfit.shore_coeff), asmfit.fitted_signal()) directions, _, _ = peak_directions(odf, sphere, .35, 25) npt.assert_equal(len(directions), 2) npt.assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) # 5 subdivisions odf = asmfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) npt.assert_equal(len(directions), 2) npt.assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] asmfit = asm.fit(data) odf = asmfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) if len(directions) <= 3: npt.assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: npt.assert_equal(gfa(odf) < 0.1, True)
def test_mapmri_odf(radial_order=6): gtab = get_gtab_taiwan_dsi() # load symmetric 724 sphere sphere = get_sphere('symmetric724') # load icosahedron sphere l1, l2, l3 = [0.0015, 0.0003, 0.0003] data, golden_directions = generate_signal_crossing(gtab, l1, l2, l3, angle2=90) mapmod = MapmriModel(gtab, radial_order=radial_order, laplacian_regularization=True, laplacian_weighting=0.01) # symmetric724 sphere2 = create_unit_sphere(5) mapfit = mapmod.fit(data) odf = mapfit.odf(sphere) directions, _, _ = peak_directions(odf, sphere, .35, 25) assert_equal(len(directions), 2) assert_almost_equal( angular_similarity(directions, golden_directions), 2, 1) # 5 subdivisions odf = mapfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) assert_equal(len(directions), 2) assert_almost_equal( angular_similarity(directions, golden_directions), 2, 1) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] asmfit = mapmod.fit(data) odf = asmfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) if len(directions) <= 3: assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(odf) < 0.1, True) # for the isotropic implementation check if the odf spherical harmonics # actually represent the discrete sphere function. mapmod = MapmriModel(gtab, radial_order=radial_order, laplacian_regularization=True, laplacian_weighting=0.01, anisotropic_scaling=False) mapfit = mapmod.fit(data) odf = mapfit.odf(sphere) odf_sh = mapfit.odf_sh() odf_from_sh = sh_to_sf(odf_sh, sphere, radial_order, basis_type=None) assert_almost_equal(odf, odf_from_sh, 10)
def test_gfa(self): signal, gtab, expected = make_fake_signal() signal = np.ones((2, 3, 4, 1)) * signal sphere = hemi_icosahedron.subdivide(3) model = self.model(gtab, 6, min_signal=1e-5) fit = model.fit(signal) gfa_shm = fit.gfa gfa_odf = odf.gfa(fit.odf(sphere)) assert_array_almost_equal(gfa_shm, gfa_odf, 3) # gfa should be 0 if all coefficients are 0 (masked areas) mask = np.zeros(signal.shape[:-1]) fit = model.fit(signal, mask) assert_array_equal(fit.gfa, 0)
def test_shore_odf(): gtab = get_isbi2013_2shell_gtab() # load symmetric 724 sphere sphere = get_sphere('symmetric724') # load icosahedron sphere sphere2 = create_unit_sphere(5) data, golden_directions = SticksAndBall(gtab, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) asm = ShoreModel(gtab, radial_order=6, zeta=700, lambdaN=1e-8, lambdaL=1e-8) # symmetric724 asmfit = asm.fit(data) odf = asmfit.odf(sphere) odf_sh = asmfit.odf_sh() odf_from_sh = sh_to_sf(odf_sh, sphere, 6, basis_type=None) assert_almost_equal(odf, odf_from_sh, 10) directions, _, _ = peak_directions(odf, sphere, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) # 5 subdivisions odf = asmfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] asmfit = asm.fit(data) odf = asmfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) if len(directions) <= 3: assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(odf) < 0.1, True)
def test_dsi(): # load repulsion 724 sphere sphere = default_sphere # load icosahedron sphere sphere2 = create_unit_sphere(5) btable = np.loadtxt(get_fnames('dsi515btable')) gtab = gradient_table(btable[:, 0], btable[:, 1:]) data, golden_directions = sticks_and_ball(gtab, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) ds = DiffusionSpectrumDeconvModel(gtab) # repulsion724 dsfit = ds.fit(data) odf = dsfit.odf(sphere) directions, _, _ = peak_directions(odf, sphere, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) # 5 subdivisions dsfit = ds.fit(data) odf2 = dsfit.odf(sphere2) directions, _, _ = peak_directions(odf2, sphere2, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) assert_equal(dsfit.pdf().shape, 3 * (ds.qgrid_size, )) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] odf = ds.fit(data).odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) if len(directions) <= 3: assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(odf) < 0.1, True) assert_raises(ValueError, DiffusionSpectrumDeconvModel, gtab, qgrid_size=16)
def test_dsi(): #load symmetric 724 sphere sphere = get_sphere('symmetric724') #load icosahedron sphere sphere2 = create_unit_sphere(5) btable = np.loadtxt(get_data('dsi515btable')) bvals = btable[:,0] bvecs = btable[:,1:] data, golden_directions = SticksAndBall(bvals, bvecs, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) gtab = gradient_table(bvals, bvecs) ds = DiffusionSpectrumModel(gtab) #symmetric724 ds.direction_finder.config(sphere=sphere, min_separation_angle=25, relative_peak_threshold=.35) dsfit = ds.fit(data) odf = dsfit.odf(sphere) directions = dsfit.directions assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) #5 subdivisions ds.direction_finder.config(sphere=sphere2, min_separation_angle=25, relative_peak_threshold=.35) dsfit = ds.fit(data) odf2 = dsfit.odf(sphere2) directions = dsfit.directions assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) #from dipy.viz._show_odfs import show_odfs #show_odfs(odf[None,None,None,:], (sphere.vertices, sphere.faces)) #show_odfs(odf2[None,None,None,:], (sphere2.vertices, sphere2.faces)) assert_equal(dsfit.pdf.shape, 3 * (ds.qgrid_size, )) sb_dummies=sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] odf = ds.fit(data).odf(sphere2) directions = ds.fit(data).directions #show_odfs(odf[None, None, None, :], (sphere2.vertices, sphere2.faces)) if len(directions) <= 3: assert_equal(len(ds.fit(data).directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(ds.fit(data).odf(sphere2)) < 0.1, True)
def maps_from_sh_parallel(args): shm_coeff = args[0] peak_dirs = args[1] peak_values = args[2] peak_indices = args[3] B = args[4] sphere = args[5] gfa_thr = args[6] chunk_id = args[7] data_shape = shm_coeff.shape[0] nufo_map = np.zeros(data_shape) afd_max = np.zeros(data_shape) afd_sum = np.zeros(data_shape) rgb_map = np.zeros((data_shape, 3)) gfa_map = np.zeros(data_shape) qa_map = np.zeros((data_shape, peak_values.shape[1])) max_odf = 0 global_max = -np.inf for idx in range(len(shm_coeff)): if shm_coeff[idx].any(): odf = np.dot(shm_coeff[idx], B) odf = odf.clip(min=0) sum_odf = np.sum(odf) max_odf = np.maximum(max_odf, sum_odf) if sum_odf > 0: rgb_map[idx] = np.dot(np.abs(sphere.vertices).T, odf) rgb_map[idx] /= np.linalg.norm(rgb_map[idx]) rgb_map[idx] *= sum_odf gfa_map[idx] = gfa(odf) if gfa_map[idx] < gfa_thr: global_max = max(global_max, odf.max()) elif np.sum(peak_indices[idx] > -1): nufo_map[idx] = np.sum(peak_indices[idx] > -1) afd_max[idx] = peak_values[idx].max() afd_sum[idx] = np.sqrt(np.dot(shm_coeff[idx], shm_coeff[idx])) qa_map = peak_values[idx] - odf.min() global_max = max(global_max, peak_values[idx][0]) rgb_map /= max_odf rgb_map *= 255 qa_map /= global_max return chunk_id, nufo_map, afd_max, afd_sum, rgb_map, gfa_map, qa_map
def test_dsi(): # load symmetric 724 sphere sphere = get_sphere('symmetric724') # load icosahedron sphere sphere2 = create_unit_sphere(5) btable = np.loadtxt(get_data('dsi515btable')) gtab = gradient_table(btable[:, 0], btable[:, 1:]) data, golden_directions = SticksAndBall(gtab, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) ds = DiffusionSpectrumModel(gtab) # symmetric724 dsfit = ds.fit(data) odf = dsfit.odf(sphere) directions, _, _ = peak_directions(odf, sphere) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) # 5 subdivisions dsfit = ds.fit(data) odf2 = dsfit.odf(sphere2) directions, _, _ = peak_directions(odf2, sphere2) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) assert_equal(dsfit.pdf().shape, 3 * (ds.qgrid_size, )) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] odf = ds.fit(data).odf(sphere2) directions, _, _ = peak_directions(odf, sphere2) if len(directions) <= 3: assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(odf) < 0.1, True) assert_raises(ValueError, DiffusionSpectrumModel, gtab, qgrid_size=16)
def test_shore_odf(): gtab = get_isbi2013_2shell_gtab() # load symmetric 724 sphere sphere = get_sphere('symmetric724') # load icosahedron sphere sphere2 = create_unit_sphere(5) data, golden_directions = SticksAndBall(gtab, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) asm = ShoreModel(gtab, radial_order=6, zeta=700, lambdaN=1e-8, lambdaL=1e-8) # symmetric724 asmfit = asm.fit(data) odf = asmfit.odf(sphere) odf_sh = asmfit.odf_sh() odf_from_sh = sh_to_sf(odf_sh, sphere, 6, basis_type=None) assert_almost_equal(odf, odf_from_sh, 10) directions, _, _ = peak_directions(odf, sphere, .35, 25) assert_equal(len(directions), 2) assert_almost_equal( angular_similarity(directions, golden_directions), 2, 1) # 5 subdivisions odf = asmfit.odf(sphere2) directions, _, _ = peak_directions(odf, sphere2, .35, 25) assert_equal(len(directions), 2) assert_almost_equal( angular_similarity(directions, golden_directions), 2, 1) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] asmfit = asm.fit(data) odf = asmfit.odf(sphere2) directions, _ , _ = peak_directions(odf, sphere2, .35, 25) if len(directions) <= 3: assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(odf) < 0.1, True)
def test_gqi(): #load symmetric 724 sphere sphere = get_sphere('symmetric724') #load icosahedron sphere sphere2 = create_unit_sphere(5) btable = np.loadtxt(get_data('dsi515btable')) bvals = btable[:, 0] bvecs = btable[:, 1:] gtab = gradient_table(bvals, bvecs) data, golden_directions = SticksAndBall(gtab, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) gq = GeneralizedQSamplingModel(gtab, method='gqi2', sampling_length=1.4) #symmetric724 gqfit = gq.fit(data) odf = gqfit.odf(sphere) directions, values, indices = peak_directions(odf, sphere, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) #5 subdivisions gqfit = gq.fit(data) odf2 = gqfit.odf(sphere2) directions, values, indices = peak_directions(odf2, sphere2, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] odf = gq.fit(data).odf(sphere2) directions, values, indices = peak_directions(odf, sphere2, .35, 25) if len(directions) <= 3: assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(odf) < 0.1, True)
def test_gqi(): #load symmetric 724 sphere sphere = get_sphere('symmetric724') #load icosahedron sphere sphere2 = create_unit_sphere(5) btable = np.loadtxt(get_data('dsi515btable')) bvals = btable[:,0] bvecs = btable[:,1:] data, golden_directions = SticksAndBall(bvals, bvecs, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) gtab = gradient_table(bvals, bvecs) gq = GeneralizedQSamplingModel(gtab, method='gqi2', sampling_length=1.4) #symmetric724 gq.direction_finder.config(sphere=sphere, min_separation_angle=25, relative_peak_threshold=.35) gqfit = gq.fit(data) odf = gqfit.odf(sphere) #from dipy.viz._show_odfs import show_odfs #show_odfs(odf[None,None,None,:], (sphere.vertices, sphere.faces)) directions = gqfit.directions assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) #5 subdivisions gq.direction_finder.config(sphere=sphere2, min_separation_angle=25, relative_peak_threshold=.35) gqfit = gq.fit(data) odf2 = gqfit.odf(sphere2) directions = gqfit.directions assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) #show_odfs(odf[None,None,None,:], (sphere.vertices, sphere.faces)) sb_dummies=sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] odf = gq.fit(data).odf(sphere2) directions = gq.fit(data).directions #show_odfs(odf[None, None, None, :], (sphere2.vertices, sphere2.faces)) if len(directions) <= 3: assert_equal(len(gq.fit(data).directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(gq.fit(data).odf(sphere2)) < 0.1, True)
def test_gqi(): # load symmetric 724 sphere sphere = get_sphere('symmetric724') # load icosahedron sphere sphere2 = create_unit_sphere(5) btable = np.loadtxt(get_fnames('dsi515btable')) bvals = btable[:, 0] bvecs = btable[:, 1:] gtab = gradient_table(bvals, bvecs) data, golden_directions = SticksAndBall(gtab, d=0.0015, S0=100, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None) gq = GeneralizedQSamplingModel(gtab, method='gqi2', sampling_length=1.4) # symmetric724 gqfit = gq.fit(data) odf = gqfit.odf(sphere) directions, values, indices = peak_directions(odf, sphere, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) # 5 subdivisions gqfit = gq.fit(data) odf2 = gqfit.odf(sphere2) directions, values, indices = peak_directions(odf2, sphere2, .35, 25) assert_equal(len(directions), 2) assert_almost_equal(angular_similarity(directions, golden_directions), 2, 1) sb_dummies = sticks_and_ball_dummies(gtab) for sbd in sb_dummies: data, golden_directions = sb_dummies[sbd] odf = gq.fit(data).odf(sphere2) directions, values, indices = peak_directions(odf, sphere2, .35, 25) if len(directions) <= 3: assert_equal(len(directions), len(golden_directions)) if len(directions) > 3: assert_equal(gfa(odf) < 0.1, True)
nib.save(fa_img, os.getcwd() + '/zhibiao/' + f_name + '_FA.nii.gz') print('Saving "DTI_tensor_fa.nii.gz" sucessful.') evecs_img = nib.Nifti1Image(tenfit.evecs.astype(np.float32), affine) nib.save( evecs_img, os.getcwd() + '/zhibiao/' + f_name + '_DTI_tensor_evecs.nii.gz') print('Saving "DTI_tensor_evecs.nii.gz" sucessful.') MD = mean_diffusivity(tenfit.evals) print MD.shape print('Saving "MD.nii.gz" sucessful.') nib.save(nib.Nifti1Image(MD.astype(np.float32), img.get_affine()), os.getcwd() + '/zhibiao/' + f_name + '_MD.nii.gz') tensor_odfs = tenmodel.fit(data[20:50, 55:85, 38:39]).odf(sphere) from dipy.reconst.odf import gfa dti_gfa = gfa(tensor_odfs) """ wm_mask = (np.logical_or(FA >= 0.4, (np.logical_and(FA >= 0.15, MD >= 0.0011)))) response = recursive_response(gtab, data, mask=wm_mask, sh_order=8, peak_thr=0.01, init_fa=0.08, init_trace=0.0021, iter=8, convergence=0.001, parallel=False) from dipy.reconst.csdeconv import ConstrainedSphericalDeconvModel csd_model = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd_model.fit(data) csd_odf = csd_fit.odf(sphere) csd_peaks = peaks_from_model(model=csd_model,
def peaks_from_model(model, data, sphere, relative_peak_threshold, min_separation_angle, mask=None, return_odf=False, return_sh=True, gfa_thr=0, normalize_peaks=False, sh_order=8, sh_basis_type=None, npeaks=5, B=None, invB=None, parallel=False, nbr_processes=None): """Fit the model to data and computes peaks and metrics Parameters ---------- model : a model instance `model` will be used to fit the data. sphere : Sphere The Sphere providing discrete directions for evaluation. relative_peak_threshold : float Only return peaks greater than ``relative_peak_threshold * m`` where m is the largest peak. min_separation_angle : float in [0, 90] The minimum distance between directions. If two peaks are too close only the larger of the two is returned. mask : array, optional If `mask` is provided, voxels that are False in `mask` are skipped and no peaks are returned. return_odf : bool If True, the odfs are returned. return_sh : bool If True, the odf as spherical harmonics coefficients is returned gfa_thr : float Voxels with gfa less than `gfa_thr` are skipped, no peaks are returned. normalize_peaks : bool If true, all peak values are calculated relative to `max(odf)`. sh_order : int, optional Maximum SH order in the SH fit. For `sh_order`, there will be ``(sh_order + 1) * (sh_order + 2) / 2`` SH coefficients (default 8). sh_basis_type : {None, 'mrtrix', 'fibernav'} ``None`` for the default dipy basis which is the fibernav basis, ``mrtrix`` for the MRtrix basis, and ``fibernav`` for the FiberNavigator basis sh_smooth : float, optional Lambda-regularization in the SH fit (default 0.0). npeaks : int Maximum number of peaks found (default 5 peaks). B : ndarray, optional Matrix that transforms spherical harmonics to spherical function ``sf = np.dot(sh, B)``. invB : ndarray, optional Inverse of B. parallel: bool If True, use multiprocessing to compute peaks and metric (default False). Temporary files are saved in the default temporary directory of the system. It can be changed using ``import tempfile`` and ``tempfile.tempdir = '/path/to/tempdir'``. nbr_processes: int If `parallel` is True, the number of subprocesses to use (default multiprocessing.cpu_count()). Returns ------- pam : PeaksAndMetrics An object with ``gfa``, ``peak_directions``, ``peak_values``, ``peak_indices``, ``odf``, ``shm_coeffs`` as attributes """ if return_sh and (B is None or invB is None): B, invB = sh_to_sf_matrix( sphere, sh_order, sh_basis_type, return_inv=True) if parallel: # It is mandatory to provide B and invB to the parallel function. # Otherwise, a call to np.linalg.pinv is made in a subprocess and # makes it timeout on some system. # see https://github.com/nipy/dipy/issues/253 for details return _peaks_from_model_parallel(model, data, sphere, relative_peak_threshold, min_separation_angle, mask, return_odf, return_sh, gfa_thr, normalize_peaks, sh_order, sh_basis_type, npeaks, B, invB, nbr_processes) shape = data.shape[:-1] if mask is None: mask = np.ones(shape, dtype='bool') else: if mask.shape != shape: raise ValueError("Mask is not the same shape as data.") gfa_array = np.zeros(shape) qa_array = np.zeros((shape + (npeaks,))) peak_dirs = np.zeros((shape + (npeaks, 3))) peak_values = np.zeros((shape + (npeaks,))) peak_indices = np.zeros((shape + (npeaks,)), dtype='int') peak_indices.fill(-1) if return_sh: n_shm_coeff = (sh_order + 2) * (sh_order + 1) // 2 shm_coeff = np.zeros((shape + (n_shm_coeff,))) if return_odf: odf_array = np.zeros((shape + (len(sphere.vertices),))) global_max = -np.inf for idx in ndindex(shape): if not mask[idx]: continue odf = model.fit(data[idx]).odf(sphere) if return_sh: shm_coeff[idx] = np.dot(odf, invB) if return_odf: odf_array[idx] = odf gfa_array[idx] = gfa(odf) if gfa_array[idx] < gfa_thr: global_max = max(global_max, odf.max()) continue # Get peaks of odf direction, pk, ind = peak_directions(odf, sphere, relative_peak_threshold, min_separation_angle) # Calculate peak metrics if pk.shape[0] != 0: global_max = max(global_max, pk[0]) n = min(npeaks, pk.shape[0]) qa_array[idx][:n] = pk[:n] - odf.min() peak_dirs[idx][:n] = direction[:n] peak_indices[idx][:n] = ind[:n] peak_values[idx][:n] = pk[:n] if normalize_peaks: peak_values[idx][:n] /= pk[0] peak_dirs[idx] *= peak_values[idx][:, None] qa_array /= global_max return _pam_from_attrs(PeaksAndMetrics, sphere, peak_indices, peak_values, peak_dirs, gfa_array, qa_array, shm_coeff if return_sh else None, B if return_sh else None, odf_array if return_odf else None)
fvtk.add(r, fvtk.sphere_funcs(odfs, sphere, colormap='jet')) fvtk.show(r) fvtk.clear(r) # min-max normalization csa_mm = minmax_normalize(odfs) r = fvtk.ren() fvtk.add(r, fvtk.sphere_funcs(csa_mm, sphere, colormap='jet', norm=False)) fvtk.show(r) fvtk.clear(r) # Three ways to get the GFA GFA = csapeaks.gfa GFA_sh = csa_fit.gfa GFA_odf = gfa(odfs) coeff = csa_fit._shm_coef nib.save(nib.Nifti1Image(GFA.astype('float32'), affine), 'gfa_small.nii.gz') nib.save(nib.Nifti1Image(GFA_sh.astype('float32'), affine), 'gfa_sh_small.nii.gz') nib.save(nib.Nifti1Image(GFA_sh.astype('float32'), affine), 'gfa_odf_small.nii.gz') nib.save(nib.Nifti1Image(coeff.astype('float32'), affine), 'csa_sh_small.nii.gz') # If you want the full brain SH coefs or GFA csa_fit = csamodel.fit(data) GFA_sh = csa_fit.gfa csa_sh_coeffs = csa_fit._shm_coef nib.save(nib.Nifti1Image(GFA_sh.astype('float32'), affine), 'gfa_fullbrain.nii.gz') nib.save(nib.Nifti1Image(csa_sh_coeffs.astype('float32'), affine), 'csa_sh_fullbrain.nii.gz')
for index in ndindex(dataslice.shape[:2]): pdf = dsmodel.fit(dataslice[index]).pdf() """ If you really want to save the PDFs of a full dataset on the disc we recommend using memory maps (``numpy.memmap``) but still have in mind that even if you do that for example for a dataset of volume size ``(96, 96, 60)`` you will need about 2.5 GBytes which can take less space when reasonable spheres (with < 1000 vertices) are used. Let's now calculate a map of Generalized Fractional Anisotropy (GFA) [Tuch04]_ using the DSI ODFs. """ from dipy.reconst.odf import gfa GFA = gfa(ODF) import matplotlib.pyplot as plt fig_hist, ax = plt.subplots(1) ax.set_axis_off() plt.imshow(GFA.T) plt.savefig('dsi_gfa.png', bbox_inches='tight', origin='lower', cmap='gray') """ .. figure:: dsi_gfa.png :align: center See also :ref:`example_reconst_dsi_metrics` for calculating different types of DSI maps.
fodf_spheres = fvtk.sphere_funcs(csd_odf, sphere, scale=1.3, norm=False) fodf_spheres.SetPosition(15, 15, 1) fodf_spheres.SetScale(0.78) fvtk.add(ren, fodf_spheres) """ Additionally, we can visualize the ODFs together with a GFA slice """ from dipy.reconst.odf import gfa GFA = gfa(csd_odf) fvtk.add(ren, fvtk.slicer(GFA, plane_k=[0])) print('Saving illustration as csd_odfs.png') fvtk.record(ren, out_path='csd_odfs.png', size=(600, 600)) """ .. figure:: csd_odfs.png :align: center **CSD ODFs**. .. [Tournier2007] J-D. Tournier, F. Calamante and A. Connelly, "Robust determination of the fibre orientation distribution in diffusion MRI: Non-negativity constrained super-resolved spherical deconvolution", Neuroimage, vol. 35, no. 4, pp. 1459-1472, 2007. .. include:: ../links_names.inc
data = img.get_data() affine = img.get_affine() print('data.shape (%d, %d, %d, %d)' % data.shape) mask = data[..., 0] > 50 mask_small = mask[20:50,55:85, 38:40] data_small = data[20:50,55:85, 38:40] csamodel = CsaOdfModel(gtab, 4, smooth=0.006) csa_fit = csamodel.fit(data_small) sphere = get_sphere('symmetric724') csa_odf = csa_fit.odf(sphere) gfa_csa = gfa(csa_odf) odfs = csa_odf.clip(0) gfa_csa_wo_zeros = gfa(odfs) csa_mm = minmax_normalize(odfs) gfa_csa_mm = gfa(csa_mm) qballmodel = QballModel(gtab, 6, smooth=0.006) qball_fit = qballmodel.fit(data_small) qball_odf = qball_fit.odf(sphere) gfa_qball = gfa(qball_odf) gfa_qball_mm = gfa(minmax_normalize(qball_odf)) print 'Saving GFAs...'
from dipy.data import get_sphere from dipy.viz.mayavi.spheres import show_odfs from load_data import get_train_dsi data, affine, gtab = get_train_dsi(30) gqi_model = GeneralizedQSamplingModel(gtab, method='gqi2', sampling_length=3, normalize_peaks=True) crop = 20 gqi_fit = gqi_model.fit(data[crop:29,crop:29,crop:29]) sphere = get_sphere('symmetric724') gqi_odf = gqi_fit.odf(sphere) gqi_gfa = gfa(gqi_odf) import nibabel as nib affine[:3,3] += crop print affine nib.save(nib.Nifti1Image(gqi_odf, affine), 'gqi_odf_norm.nii.gz') nib.save(nib.Nifti1Image(gqi_gfa, affine), 'gfa_norm.nii.gz') import numpy as np np.savetxt('sphere724.txt', sphere.vertices)
def peaks_from_model(model, data, sphere, relative_peak_threshold, min_separation_angle, mask=None, return_odf=False, return_sh=True, gfa_thr=0, normalize_peaks=False, sh_order=8, sh_basis_type=None, npeaks=5, B=None, invB=None, parallel=False, num_processes=None): """Fit the model to data and computes peaks and metrics Parameters ---------- model : a model instance `model` will be used to fit the data. data : ndarray Diffusion data. sphere : Sphere The Sphere providing discrete directions for evaluation. relative_peak_threshold : float Only return peaks greater than ``relative_peak_threshold * m`` where m is the largest peak. min_separation_angle : float in [0, 90] The minimum distance between directions. If two peaks are too close only the larger of the two is returned. mask : array, optional If `mask` is provided, voxels that are False in `mask` are skipped and no peaks are returned. return_odf : bool If True, the odfs are returned. return_sh : bool If True, the odf as spherical harmonics coefficients is returned gfa_thr : float Voxels with gfa less than `gfa_thr` are skipped, no peaks are returned. normalize_peaks : bool If true, all peak values are calculated relative to `max(odf)`. sh_order : int, optional Maximum SH order in the SH fit. For `sh_order`, there will be ``(sh_order + 1) * (sh_order + 2) / 2`` SH coefficients (default 8). sh_basis_type : {None, 'tournier07', 'descoteaux07'} ``None`` for the default DIPY basis, ``tournier07`` for the Tournier 2007 [2]_ basis, and ``descoteaux07`` for the Descoteaux 2007 [1]_ basis (``None`` defaults to ``descoteaux07``). npeaks : int Maximum number of peaks found (default 5 peaks). B : ndarray, optional Matrix that transforms spherical harmonics to spherical function ``sf = np.dot(sh, B)``. invB : ndarray, optional Inverse of B. parallel: bool If True, use multiprocessing to compute peaks and metric (default False). Temporary files are saved in the default temporary directory of the system. It can be changed using ``import tempfile`` and ``tempfile.tempdir = '/path/to/tempdir'``. num_processes: int, optional If `parallel` is True, the number of subprocesses to use (default multiprocessing.cpu_count()). If < 0 the maximal number of cores minus ``num_processes + 1`` is used (enter -1 to use as many cores as possible). 0 raises an error. Returns ------- pam : PeaksAndMetrics An object with ``gfa``, ``peak_directions``, ``peak_values``, ``peak_indices``, ``odf``, ``shm_coeffs`` as attributes References ---------- .. [1] Descoteaux, M., Angelino, E., Fitzgibbons, S. and Deriche, R. Regularized, Fast, and Robust Analytical Q-ball Imaging. Magn. Reson. Med. 2007;58:497-510. .. [2] Tournier J.D., Calamante F. and Connelly A. Robust determination of the fibre orientation distribution in diffusion MRI: Non-negativity constrained super-resolved spherical deconvolution. NeuroImage. 2007;35(4):1459-1472. """ if return_sh and (B is None or invB is None): B, invB = sh_to_sf_matrix( sphere, sh_order, sh_basis_type, return_inv=True) num_processes = determine_num_processes(num_processes) if parallel and num_processes > 1: # It is mandatory to provide B and invB to the parallel function. # Otherwise, a call to np.linalg.pinv is made in a subprocess and # makes it timeout on some system. # see https://github.com/dipy/dipy/issues/253 for details return _peaks_from_model_parallel(model, data, sphere, relative_peak_threshold, min_separation_angle, mask, return_odf, return_sh, gfa_thr, normalize_peaks, sh_order, sh_basis_type, npeaks, B, invB, num_processes) shape = data.shape[:-1] if mask is None: mask = np.ones(shape, dtype='bool') else: if mask.shape != shape: raise ValueError("Mask is not the same shape as data.") gfa_array = np.zeros(shape) qa_array = np.zeros((shape + (npeaks,))) peak_dirs = np.zeros((shape + (npeaks, 3))) peak_values = np.zeros((shape + (npeaks,))) peak_indices = np.zeros((shape + (npeaks,)), dtype='int') peak_indices.fill(-1) if return_sh: n_shm_coeff = (sh_order + 2) * (sh_order + 1) // 2 shm_coeff = np.zeros((shape + (n_shm_coeff,))) if return_odf: odf_array = np.zeros((shape + (len(sphere.vertices),))) global_max = -np.inf for idx in ndindex(shape): if not mask[idx]: continue odf = model.fit(data[idx]).odf(sphere) if return_sh: shm_coeff[idx] = np.dot(odf, invB) if return_odf: odf_array[idx] = odf gfa_array[idx] = gfa(odf) if gfa_array[idx] < gfa_thr: global_max = max(global_max, odf.max()) continue # Get peaks of odf direction, pk, ind = peak_directions(odf, sphere, relative_peak_threshold, min_separation_angle) # Calculate peak metrics if pk.shape[0] != 0: global_max = max(global_max, pk[0]) n = min(npeaks, pk.shape[0]) qa_array[idx][:n] = pk[:n] - odf.min() peak_dirs[idx][:n] = direction[:n] peak_indices[idx][:n] = ind[:n] peak_values[idx][:n] = pk[:n] if normalize_peaks: peak_values[idx][:n] /= pk[0] peak_dirs[idx] *= peak_values[idx][:, None] qa_array /= global_max return _pam_from_attrs(PeaksAndMetrics, sphere, peak_indices, peak_values, peak_dirs, gfa_array, qa_array, shm_coeff if return_sh else None, B if return_sh else None, odf_array if return_odf else None)
fa_img = nib.Nifti1Image(FA.astype(np.float32), affine) print FA.shape nib.save(fa_img,os.getcwd()+'/zhibiao/'+f_name+'_FA.nii.gz') print('Saving "DTI_tensor_fa.nii.gz" sucessful.') evecs_img = nib.Nifti1Image(tenfit.evecs.astype(np.float32), affine) nib.save(evecs_img, os.getcwd()+'/zhibiao/'+f_name+'_DTI_tensor_evecs.nii.gz') print('Saving "DTI_tensor_evecs.nii.gz" sucessful.') MD = mean_diffusivity(tenfit.evals) print MD.shape print('Saving "MD.nii.gz" sucessful.') nib.save(nib.Nifti1Image(MD.astype(np.float32), img.get_affine()), os.getcwd()+'/zhibiao/'+f_name+'_MD.nii.gz') tensor_odfs = tenmodel.fit(data[20:50, 55:85, 38:39]).odf(sphere) from dipy.reconst.odf import gfa dti_gfa=gfa(tensor_odfs) """ wm_mask = (np.logical_or(FA >= 0.4, (np.logical_and(FA >= 0.15, MD >= 0.0011)))) response = recursive_response(gtab, data, mask=wm_mask, sh_order=8, peak_thr=0.01, init_fa=0.08, init_trace=0.0021, iter=8, convergence=0.001, parallel=False) from dipy.reconst.csdeconv import ConstrainedSphericalDeconvModel csd_model = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd_model.fit(data) csd_odf = csd_fit.odf(sphere) csd_peaks = peaks_from_model(model=csd_model,
def test_TensorModel(): data, gtab = dsi_voxels() dm = dti.TensorModel(gtab, 'LS') dtifit = dm.fit(data[0, 0, 0]) assert_equal(dtifit.fa < 0.5, True) dm = dti.TensorModel(gtab, 'WLS') dtifit = dm.fit(data[0, 0, 0]) assert_equal(dtifit.fa < 0.5, True) sphere = create_unit_sphere(4) assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices)) assert_almost_equal(dtifit.fa, gfa(dtifit.odf(sphere)), 1) # Check that the multivoxel case works: dtifit = dm.fit(data) # And smoke-test that all these operations return sensibly-shaped arrays: assert_equal(dtifit.fa.shape, data.shape[:3]) assert_equal(dtifit.ad.shape, data.shape[:3]) assert_equal(dtifit.md.shape, data.shape[:3]) assert_equal(dtifit.rd.shape, data.shape[:3]) assert_equal(dtifit.trace.shape, data.shape[:3]) assert_equal(dtifit.mode.shape, data.shape[:3]) assert_equal(dtifit.linearity.shape, data.shape[:3]) assert_equal(dtifit.planarity.shape, data.shape[:3]) assert_equal(dtifit.sphericity.shape, data.shape[:3]) # Test for the shape of the mask assert_raises(ValueError, dm.fit, np.ones((10, 10, 3)), np.ones((3, 3))) # Make some synthetic data b0 = 1000. bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec')) gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T) # The first b value is 0., so we take the second one: B = bvals[1] # Scale the eigenvalues and tensor by the B value so the units match D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B evals = np.array([2., 1., 0.]) / B md = evals.mean() tensor = from_lower_triangular(D) A_squiggle = tensor - (1 / 3.0) * np.trace(tensor) * np.eye(3) mode = 3 * np.sqrt(6) * np.linalg.det( A_squiggle / np.linalg.norm(A_squiggle)) evecs = np.linalg.eigh(tensor)[1] # Design Matrix X = dti.design_matrix(gtab) # Signals Y = np.exp(np.dot(X, D)) assert_almost_equal(Y[0], b0) Y.shape = (-1, ) + Y.shape # Test fitting with different methods: for fit_method in ['OLS', 'WLS', 'NLLS']: tensor_model = dti.TensorModel(gtab, fit_method=fit_method) tensor_fit = tensor_model.fit(Y) assert_true(tensor_fit.model is tensor_model) assert_equal(tensor_fit.shape, Y.shape[:-1]) assert_array_almost_equal(tensor_fit.evals[0], evals) assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor, err_msg=\ "Calculation of tensor from Y does not compare to analytical solution") assert_almost_equal(tensor_fit.md[0], md) assert_array_almost_equal(tensor_fit.mode, mode, decimal=5) assert_equal(tensor_fit.directions.shape[-2], 1) assert_equal(tensor_fit.directions.shape[-1], 3) # Test error-handling: assert_raises(ValueError, dti.TensorModel, gtab, fit_method='crazy_method')
# Convert result to dir format t = time.time() print('... convert peaks to dir format') dsidir = prepare_dir(dsipeaks, sphere, 0, 0, 1) name = os.path.join(main_dir,tp,'CMP','scalars','dsideconv_dir.nii.gz') nib.save(nib.Nifti1Image(dsidir, affine), name) elapsed = time.time() - t print(' time %d' %elapsed) # Classic DSI reconstruction t = time.time() print('... perform classic DSI reconstruction') dsmodel_dsi = DiffusionSpectrumModel(gtab) dsifit = dsmodel_dsi.fit(data) odfs = dsifit.odf(sphere) GFA = gfa(odfs) name = os.path.join(main_dir,tp,'CMP','scalars','dsidipy_gfa.nii.gz') nib.save(nib.Nifti1Image(GFA, affine), name) name = os.path.join(main_dir,tp,'CMP','scalars','dsidipy_odf.nii.gz') nib.save(nib.Nifti1Image(odfs, affine), name) elapsed = time.time() - t print(' time %d' %elapsed)
def test_TensorModel(): data, gtab = dsi_voxels() dm = dti.TensorModel(gtab, 'LS') dtifit = dm.fit(data[0, 0, 0]) assert_equal(dtifit.fa < 0.5, True) dm = dti.TensorModel(gtab, 'WLS') dtifit = dm.fit(data[0, 0, 0]) assert_equal(dtifit.fa < 0.5, True) sphere = create_unit_sphere(4) assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices)) assert_almost_equal(dtifit.fa, gfa(dtifit.odf(sphere)), 1) # Check that the multivoxel case works: dtifit = dm.fit(data) # And smoke-test that all these operations return sensibly-shaped arrays: assert_equal(dtifit.fa.shape, data.shape[:3]) assert_equal(dtifit.ad.shape, data.shape[:3]) assert_equal(dtifit.md.shape, data.shape[:3]) assert_equal(dtifit.rd.shape, data.shape[:3]) assert_equal(dtifit.trace.shape, data.shape[:3]) assert_equal(dtifit.mode.shape, data.shape[:3]) assert_equal(dtifit.linearity.shape, data.shape[:3]) assert_equal(dtifit.planarity.shape, data.shape[:3]) assert_equal(dtifit.sphericity.shape, data.shape[:3]) # Test for the shape of the mask assert_raises(ValueError, dm.fit, np.ones((10, 10, 3)), np.ones((3,3))) # Make some synthetic data b0 = 1000. bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec')) gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T) # The first b value is 0., so we take the second one: B = bvals[1] # Scale the eigenvalues and tensor by the B value so the units match D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B evals = np.array([2., 1., 0.]) / B md = evals.mean() tensor = from_lower_triangular(D) A_squiggle = tensor - (1 / 3.0) * np.trace(tensor) * np.eye(3) mode = 3 * np.sqrt(6) * np.linalg.det(A_squiggle / np.linalg.norm(A_squiggle)) evecs = np.linalg.eigh(tensor)[1] # Design Matrix X = dti.design_matrix(gtab) # Signals Y = np.exp(np.dot(X, D)) assert_almost_equal(Y[0], b0) Y.shape = (-1,) + Y.shape # Test fitting with different methods: for fit_method in ['OLS', 'WLS', 'NLLS']: tensor_model = dti.TensorModel(gtab, fit_method=fit_method) tensor_fit = tensor_model.fit(Y) assert_true(tensor_fit.model is tensor_model) assert_equal(tensor_fit.shape, Y.shape[:-1]) assert_array_almost_equal(tensor_fit.evals[0], evals) assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor, err_msg=\ "Calculation of tensor from Y does not compare to analytical solution") assert_almost_equal(tensor_fit.md[0], md) assert_array_almost_equal(tensor_fit.mode, mode, decimal=5) assert_equal(tensor_fit.directions.shape[-2], 1) assert_equal(tensor_fit.directions.shape[-1], 3) # Test error-handling: assert_raises(ValueError, dti.TensorModel, gtab, fit_method='crazy_method')
pdf = dsmodel.fit(dataslice[index]).pdf() """ If you really want to save the PDFs of a full dataset on the disc we recommend using memory maps (``numpy.memmap``) but still have in mind that even if you do that for example for a dataset of volume size ``(96, 96, 60)`` you will need about 2.5 GBytes which can take less space when reasonable spheres (with < 1000 vertices) are used. Let's now calculate a map of Generalized Fractional Anisotropy (GFA) [Tuch04]_ using the DSI ODFs. """ from dipy.reconst.odf import gfa GFA = gfa(ODF) import matplotlib.pyplot as plt fig_hist, ax = plt.subplots(1) ax.set_axis_off() plt.imshow(GFA.T) plt.savefig('dsi_gfa.png', bbox_inches='tight', origin='lower', cmap='gray') """ .. figure:: dsi_gfa.png :align: center See also :ref:`example_reconst_dsi_metrics` for calculating different types of DSI maps.
def test_peaksFromModel(): data = np.zeros((10, 2)) for sphere in [_sphere, get_sphere('symmetric642')]: # Test basic case model = SimpleOdfModel(_gtab) _odf = (sphere.vertices * [1, 2, 3]).sum(-1) odf_argmax = _odf.argmax() pam = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True) assert_array_equal(pam.gfa, gfa(_odf)) assert_array_equal(pam.peak_values[:, 0], 1.) assert_array_equal(pam.peak_values[:, 1:], 0.) mn, mx = _odf.min(), _odf.max() assert_array_equal(pam.qa[:, 0], (mx - mn) / mx) assert_array_equal(pam.qa[:, 1:], 0.) assert_array_equal(pam.peak_indices[:, 0], odf_argmax) assert_array_equal(pam.peak_indices[:, 1:], -1) # Test that odf array matches and is right shape pam = peaks_from_model(model, data, sphere, .5, 45, return_odf=True) expected_shape = (len(data), len(_odf)) assert_equal(pam.odf.shape, expected_shape) assert_((_odf == pam.odf).all()) assert_array_equal(pam.peak_values[:, 0], _odf.max()) # Test mask mask = (np.arange(10) % 2) == 1 pam = peaks_from_model(model, data, sphere, .5, 45, mask=mask, normalize_peaks=True) assert_array_equal(pam.gfa[~mask], 0) assert_array_equal(pam.qa[~mask], 0) assert_array_equal(pam.peak_values[~mask], 0) assert_array_equal(pam.peak_indices[~mask], -1) assert_array_equal(pam.gfa[mask], gfa(_odf)) assert_array_equal(pam.peak_values[mask, 0], 1.) assert_array_equal(pam.peak_values[mask, 1:], 0.) mn, mx = _odf.min(), _odf.max() assert_array_equal(pam.qa[mask, 0], (mx - mn) / mx) assert_array_equal(pam.qa[mask, 1:], 0.) assert_array_equal(pam.peak_indices[mask, 0], odf_argmax) assert_array_equal(pam.peak_indices[mask, 1:], -1) # Test serialization and deserialization: for normalize_peaks in [True, False]: for return_odf in [True, False]: for return_sh in [True, False]: pam = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=normalize_peaks, return_odf=return_odf, return_sh=return_sh) b = BytesIO() pickle.dump(pam, b) b.seek(0) new_pam = pickle.load(b) b.close() for attr in [ 'peak_dirs', 'peak_values', 'peak_indices', 'gfa', 'qa', 'shm_coeff', 'B', 'odf' ]: assert_array_equal(getattr(pam, attr), getattr(new_pam, attr)) assert_array_equal(pam.sphere.vertices, new_pam.sphere.vertices)
def test_peaksFromModel(): data = np.zeros((10, 2)) for sphere in [_sphere, get_sphere('symmetric642')]: # Test basic case model = SimpleOdfModel(_gtab) _odf = (sphere.vertices * [1, 2, 3]).sum(-1) odf_argmax = _odf.argmax() pam = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True) assert_array_equal(pam.gfa, gfa(_odf)) assert_array_equal(pam.peak_values[:, 0], 1.) assert_array_equal(pam.peak_values[:, 1:], 0.) mn, mx = _odf.min(), _odf.max() assert_array_equal(pam.qa[:, 0], (mx - mn) / mx) assert_array_equal(pam.qa[:, 1:], 0.) assert_array_equal(pam.peak_indices[:, 0], odf_argmax) assert_array_equal(pam.peak_indices[:, 1:], -1) # Test that odf array matches and is right shape pam = peaks_from_model(model, data, sphere, .5, 45, return_odf=True) expected_shape = (len(data), len(_odf)) assert_equal(pam.odf.shape, expected_shape) assert_((_odf == pam.odf).all()) assert_array_equal(pam.peak_values[:, 0], _odf.max()) # Test mask mask = (np.arange(10) % 2) == 1 pam = peaks_from_model(model, data, sphere, .5, 45, mask=mask, normalize_peaks=True) assert_array_equal(pam.gfa[~mask], 0) assert_array_equal(pam.qa[~mask], 0) assert_array_equal(pam.peak_values[~mask], 0) assert_array_equal(pam.peak_indices[~mask], -1) assert_array_equal(pam.gfa[mask], gfa(_odf)) assert_array_equal(pam.peak_values[mask, 0], 1.) assert_array_equal(pam.peak_values[mask, 1:], 0.) mn, mx = _odf.min(), _odf.max() assert_array_equal(pam.qa[mask, 0], (mx - mn) / mx) assert_array_equal(pam.qa[mask, 1:], 0.) assert_array_equal(pam.peak_indices[mask, 0], odf_argmax) assert_array_equal(pam.peak_indices[mask, 1:], -1) # Test serialization and deserialization: for normalize_peaks in [True, False]: for return_odf in [True, False]: for return_sh in [True, False]: pam = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=normalize_peaks, return_odf=return_odf, return_sh=return_sh) b = BytesIO() pickle.dump(pam, b) b.seek(0) new_pam = pickle.load(b) b.close() for attr in ['peak_dirs', 'peak_values', 'peak_indices', 'gfa', 'qa', 'shm_coeff', 'B', 'odf']: assert_array_equal(getattr(pam, attr), getattr(new_pam, attr)) assert_array_equal(pam.sphere.vertices, new_pam.sphere.vertices)