def test_fwdti_predictions(): # single voxel case gtf = 0.50 # ground truth volume fraction angles = [(90, 0), (90, 0)] mevals = np.array([[0.0017, 0.0003, 0.0003], [0.003, 0.003, 0.003]]) S_conta, peaks = multi_tensor(gtab_2s, mevals, S0=100, angles=angles, fractions=[(1-gtf) * 100, gtf*100], snr=None) R = all_tensor_evecs(peaks[0]) R = R.reshape((9)) model_params = np.concatenate(([0.0017, 0.0003, 0.0003], R, [gtf]), axis=0) S_pred1 = fwdti_prediction(model_params, gtab_2s, S0=100) assert_array_almost_equal(S_pred1, S_conta) # Testing in model class fwdm = fwdti.FreeWaterTensorModel(gtab_2s) S_pred2 = fwdm.predict(model_params, S0=100) assert_array_almost_equal(S_pred2, S_conta) # Testing in fit class fwefit = fwdm.fit(S_conta) S_pred3 = fwefit.predict(gtab_2s, S0=100) assert_array_almost_equal(S_pred3, S_conta, decimal=5) # Multi voxel simulation S_pred1 = fwdti_prediction(model_params_mv, gtab_2s, S0=100) # function assert_array_almost_equal(S_pred1, DWI) S_pred2 = fwdm.predict(model_params_mv, S0=100) # Model class assert_array_almost_equal(S_pred2, DWI) fwefit = fwdm.fit(DWI) # Fit class S_pred3 = fwefit.predict(gtab_2s, S0=100) assert_array_almost_equal(S_pred3, DWI)
def test_sphere_scaling_csdmodel(): """Check that mirroring regularization sphere does not change the result of the model""" _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, sticks = multi_tensor(gtab, mevals, 100., angles=angles, fractions=[50, 50], snr=None) hemi = small_sphere sphere = hemi.mirror() response = (np.array([0.0015, 0.0003, 0.0003]), 100) model_full = ConstrainedSphericalDeconvModel(gtab, response, reg_sphere=sphere) model_hemi = ConstrainedSphericalDeconvModel(gtab, response, reg_sphere=hemi) csd_fit_full = model_full.fit(S) csd_fit_hemi = model_hemi.fit(S) assert_array_almost_equal(csd_fit_full.shm_coeff, csd_fit_hemi.shm_coeff)
def test_peaksFromModelParallel(): SNR = 100 S0 = 100 _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) data, _ = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)], fractions=[50, 50], snr=SNR) # test equality with/without multiprocessing model = SimpleOdfModel() pam_multi = peaks_from_model(model, data, _sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=True) pam_single = peaks_from_model(model, data, _sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=False) assert_array_almost_equal(pam_multi.gfa, pam_single.gfa) assert_array_almost_equal(pam_multi.qa, pam_single.qa) assert_array_almost_equal(pam_multi.peak_values, pam_single.peak_values) assert_array_equal(pam_multi.peak_indices, pam_single.peak_indices) assert_array_almost_equal(pam_multi.peak_dirs, pam_single.peak_dirs) assert_array_almost_equal(pam_multi.shm_coeff, pam_single.shm_coeff) assert_array_almost_equal(pam_multi.odf, pam_single.odf)
def test_minmax_normalize(): bvalue = 3000 S0 = 1 SNR = 100 sphere = get_sphere("symmetric362") bvecs = np.concatenate(([[0, 0, 0]], sphere.vertices)) bvals = np.zeros(len(bvecs)) + bvalue bvals[0] = 0 gtab = gradient_table(bvals, bvecs) evals = np.array(([0.0017, 0.0003, 0.0003], [0.0017, 0.0003, 0.0003])) S, sticks = multi_tensor(gtab, evals, S0, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=SNR) odf = multi_tensor_odf(sphere.vertices, evals, angles=[(0, 0), (90, 0)], fractions=[50, 50]) odf2 = minmax_normalize(odf) assert_equal(odf2.max(), 1) assert_equal(odf2.min(), 0) odf3 = np.empty(odf.shape) odf3 = minmax_normalize(odf, odf3) assert_equal(odf3.max(), 1) assert_equal(odf3.min(), 0)
def test_r2_term_odf_sharp(): SNR = None S0 = 1 angle = 75 _, fbvals, fbvecs = get_data('small_64D') #get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) sphere = get_sphere('symmetric724') gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) S, sticks = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (angle, 0)], fractions=[50, 50], snr=SNR) mevecs = [all_tensor_evecs(sticks[0]).T, all_tensor_evecs(sticks[1]).T] odf_gt = multi_tensor_odf(sphere.vertices, [0.5, 0.5], mevals, mevecs) odfs_sh = sf_to_sh(odf_gt, sphere, sh_order=8, basis_type=None) fodf_sh = odf_sh_to_sharp(odfs_sh, sphere, basis=None, ratio=3 / 15., sh_order=8, lambda_=1., tau=0.1, r2_term=True) fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None) directions_gt, _, _ = peak_directions(odf_gt, sphere) directions, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions_gt, directions) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2)
def _compute_voxel(args): """ Simulate DW signal for one voxel. Uses the multi-tensor model and three isotropic compartments. Apparent diffusivity tensors are taken from [Alexander2002]_ and [Pierpaoli1996]_. .. [Alexander2002] Alexander et al., Detection and modeling of non-Gaussian apparent diffusion coefficient profiles in human brain data, MRM 48(2):331-340, 2002, doi: `10.1002/mrm.10209 <http://dx.doi.org/10.1002/mrm.10209>`_. .. [Pierpaoli1996] Pierpaoli et al., Diffusion tensor MR imaging of the human brain, Radiology 201:637-648. 1996. """ ffs = args["fractions"] gtab = args["gradients"] signal = np.zeros_like(gtab.bvals, dtype=np.float32) # Simulate dwi signal sf_vf = np.sum(ffs) if sf_vf > 0.0: ffs = (np.array(ffs) / sf_vf) * 100 snr = args["snr"] if args["snr"] > 0 else None try: signal, _ = multi_tensor(gtab, args["mevals"], S0=args["S0"], angles=args["sticks"], fractions=ffs, snr=snr) except Exception as e: pass # iflogger.warn('Exception simulating dwi signal: %s' % e) return signal.tolist()
def test_csd_predict(): """ """ SNR = 100 S0 = 1 _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) prediction = csd_predict(csd_fit.shm_coeff, gtab, response=response, S0=S0) npt.assert_equal(prediction.shape[0], S.shape[0]) model_prediction = csd.predict(csd_fit.shm_coeff) assert_array_almost_equal(prediction, model_prediction) # Roundtrip tests (quite inaccurate, because of regularization): assert_array_almost_equal(csd_fit.predict(gtab, S0=S0),S,decimal=1) assert_array_almost_equal(csd.predict(csd_fit.shm_coeff, S0=S0),S,decimal=1)
def test_exponential_iso(): fdata, fbvals, fbvecs = dpd.get_data() data_dti = nib.load(fdata).get_data() gtab_dti = grad.gradient_table(fbvals, fbvecs) data_multi, gtab_multi = dpd.dsi_deconv_voxels() for data, gtab in zip([data_dti, data_multi], [gtab_dti, gtab_multi]): sfmodel = sfm.SparseFascicleModel( gtab, isotropic=sfm.ExponentialIsotropicModel) sffit1 = sfmodel.fit(data[0, 0, 0]) sphere = dpd.get_sphere() odf1 = sffit1.odf(sphere) pred1 = sffit1.predict(gtab) SNR = 1000 S0 = 100 mevals = np.array(([0.0015, 0.0005, 0.0005], [0.0015, 0.0005, 0.0005])) angles = [(0, 0), (60, 0)] S, sticks = sims.multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sffit = sfmodel.fit(S) pred = sffit.predict() npt.assert_(xval.coeff_of_determination(pred, S) > 96)
def test_dki_micro_predict_single_voxel(): # single fiber simulate (which is the assumption of our model) fie = 0.49 ADi = 0.00099 ADe = 0.00226 RDi = 0 RDe = 0.00087 # prepare simulation: theta = random.uniform(0, 180) phi = random.uniform(0, 320) angles = [(theta, phi), (theta, phi)] mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]]) frac = [fie*100, (1 - fie)*100] signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, angles=angles, fractions=frac, snr=None) signal_gt, da = multi_tensor(gtab_2s, mevals, angles=angles, fractions=frac, snr=None) # Defined DKI microstrutural model dkiM = dki_micro.KurtosisMicrostructureModel(gtab_2s) # Fit single voxel signal dkiF = dkiM.fit(signal) # Check predict of KurtosisMicrostruturalModel pred = dkiM.predict(dkiF.model_params) assert_array_almost_equal(pred, signal_gt, decimal=4) pred = dkiM.predict(dkiF.model_params, S0=100) assert_array_almost_equal(pred, signal_gt * 100, decimal=4) # Check predict of KurtosisMicrostruturalFit pred = dkiF.predict(gtab_2s, S0=100) assert_array_almost_equal(pred, signal_gt * 100, decimal=4)
def test_csd_superres(): """ Check the quality of csdfit with high SH order. """ _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) # img, gtab = read_stanford_hardi() evals = np.array([[1.5, .3, .3]]) * [[1.], [1.]] / 1000. S, sticks = multi_tensor(gtab, evals, snr=None, fractions=[55., 45.]) model16 = ConstrainedSphericalDeconvModel(gtab, (evals[0], 3.), sh_order=16) fit16 = model16.fit(S) # print local_maxima(fit16.odf(default_sphere), default_sphere.edges) d, v, ind = peak_directions(fit16.odf(default_sphere), default_sphere, relative_peak_threshold=.2, min_separation_angle=0) # Check that there are two peaks assert_equal(len(d), 2) # Check that peaks line up with sticks cos_sim = abs((d * sticks).sum(1)) ** .5 assert_(all(cos_sim > .99))
def test_bdg_initial_direction(): """This test the number of inital direction." """ hsph_updated = HemiSphere.from_sphere(unit_icosahedron).subdivide(2) 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) # test that we get one direction when we have a single tensor voxel = single_tensor(gtab).reshape([1, 1, 1, -1]) dti_model = dti.TensorModel(gtab) boot_dg = BootDirectionGetter.from_data(voxel, dti_model, 30, sh_order=6) initial_direction = boot_dg.initial_direction(np.zeros(3)) npt.assert_equal(len(initial_direction), 1) npt.assert_allclose(initial_direction[0], [1, 0, 0], atol=0.1) # test that we get multiple directions when we have a multi-tensor mevals = np.array([[1.5, 0.4, 0.4], [1.5, 0.4, 0.4]]) * 1e-3 fracs = [60, 40] voxel, primary_evecs = multi_tensor(gtab, mevals, fractions=fracs, snr=None) voxel = voxel.reshape([1, 1, 1, -1]) response = (np.array([0.0015, 0.0004, 0.0004]), 1) csd_model = ConstrainedSphericalDeconvModel(gtab, response=response, sh_order=4) boot_dg = BootDirectionGetter.from_data(voxel, csd_model, 30) initial_direction = boot_dg.initial_direction(np.zeros(3)) npt.assert_equal(len(initial_direction), 2) npt.assert_allclose(initial_direction, primary_evecs, atol=0.1)
def test_odfdeconv(): SNR = 100 S0 = 1 _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (90, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) e1 = 15.0 e2 = 3.0 ratio = e2 / e1 csd = ConstrainedSDTModel(gtab, ratio, None) csd_fit = csd.fit(S) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: ConstrainedSDTModel(gtab, ratio, sh_order=10) assert_equal(len(w) > 0, True) with warnings.catch_warnings(record=True) as w: ConstrainedSDTModel(gtab, ratio, sh_order=8) assert_equal(len(w) > 0, False) csd_fit = csd.fit(np.zeros_like(S)) fodf = csd_fit.odf(sphere) assert_array_equal(fodf, np.zeros_like(fodf)) odf_sh = np.zeros_like(fodf) odf_sh[1] = np.nan fodf, it = odf_deconv(odf_sh, csd.R, csd.B_reg) assert_array_equal(fodf, np.zeros_like(fodf))
def simulated_data(gtab, S0=100, SNR=100): mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) S, sticks = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=SNR) ratio = 3 / 15.0 return S, ratio
def test_reconst_ivim(): with TemporaryDirectory() as out_dir: bvals = np.array([0., 10., 20., 30., 40., 60., 80., 100., 120., 140., 160., 180., 200., 300., 400., 500., 600., 700., 800., 900., 1000.]) N = len(bvals) bvecs = generate_bvecs(N) temp_bval_path = pjoin(out_dir, "temp.bval") np.savetxt(temp_bval_path, bvals) temp_bvec_path = pjoin(out_dir, "temp.bvec") np.savetxt(temp_bvec_path, bvecs) gtab = gradient_table(bvals, bvecs) S0, f, D_star, D = 1000.0, 0.132, 0.00885, 0.000921 mevals = np.array(([D_star, D_star, D_star], [D, D, D])) # This gives an isotropic signal. data = multi_tensor(gtab, mevals, snr=None, S0=S0, fractions=[f * 100, 100 * (1 - f)]) # Single voxel data data_single = data[0] temp_affine = np.eye(4) data_multi = np.zeros((2, 2, 1, len(gtab.bvals))) data_multi[0, 0, 0] = data_multi[0, 1, 0] = data_multi[ 1, 0, 0] = data_multi[1, 1, 0] = data_single data_img = nib.Nifti1Image(data_multi.astype(int), temp_affine) data_path = pjoin(out_dir, 'tmp_data.nii.gz') nib.save(data_img, data_path) mask = np.ones_like(data_multi[..., 0]) mask_img = nib.Nifti1Image(mask.astype(np.uint8), data_img.affine) mask_path = pjoin(out_dir, 'tmp_mask.nii.gz') nib.save(mask_img, mask_path) ivim_flow = ReconstIvimFlow() args = [data_path, temp_bval_path, temp_bvec_path, mask_path] ivim_flow.run(*args, out_dir=out_dir) S0_path = ivim_flow.last_generated_outputs['out_S0_predicted'] S0_data = nib.load(S0_path).get_data() assert_equal(S0_data.shape, data_img.shape[:-1]) f_path = ivim_flow.last_generated_outputs['out_perfusion_fraction'] f_data = nib.load(f_path).get_data() assert_equal(f_data.shape, data_img.shape[:-1]) D_star_path = ivim_flow.last_generated_outputs['out_D_star'] D_star_data = nib.load(D_star_path).get_data() assert_equal(D_star_data.shape, data_img.shape[:-1]) D_path = ivim_flow.last_generated_outputs['out_D'] D_data = nib.load(D_path).get_data() assert_equal(D_data.shape, data_img.shape[:-1])
def test_multiple_b0(): # Generate a signal with multiple b0 # This gives an isotropic signal. signal = multi_tensor(gtab_with_multiple_b0, mevals, snr=None, S0=S0, fractions=[f * 100, 100 * (1 - f)]) # Single voxel data data_single = signal[0] ivim_model_multiple_b0 = IvimModel(gtab_with_multiple_b0) x0_estimated = ivim_model_multiple_b0.fit(data_single)
def test_csdeconv(): SNR = 100 S0 = 1 _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) S, sticks = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)], fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric724') mevecs = [all_tensor_evecs(sticks[0]).T, all_tensor_evecs(sticks[1]).T] odf_gt = multi_tensor_odf(sphere.vertices, [0.5, 0.5], mevals, mevecs) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) assert_equal(csd_fit.shm_coeff[0] > 0, True) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: ConstrainedSphericalDeconvModel(gtab, response, sh_order=10) assert_equal(len(w) > 0, True) with warnings.catch_warnings(record=True) as w: ConstrainedSphericalDeconvModel(gtab, response, sh_order=8) assert_equal(len(w) > 0, False)
def setup_module(): """Module-level setup""" global gtab, gtab_2s, mevals, model_params_mv global DWI, FAref, GTF, MDref, FAdti, MDdti _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs) # FW model requires multishell data bvals_2s = np.concatenate((bvals, bvals * 1.5), axis=0) bvecs_2s = np.concatenate((bvecs, bvecs), axis=0) gtab_2s = gradient_table(bvals_2s, bvecs_2s) # Simulation a typical DT and DW signal for no water contamination S0 = np.array(100) dt = np.array([0.0017, 0, 0.0003, 0, 0, 0.0003]) evals, evecs = decompose_tensor(from_lower_triangular(dt)) S_tissue = single_tensor(gtab_2s, S0=100, evals=evals, evecs=evecs, snr=None) dm = dti.TensorModel(gtab_2s, 'WLS') dtifit = dm.fit(S_tissue) FAdti = dtifit.fa MDdti = dtifit.md dtiparams = dtifit.model_params # Simulation of 8 voxels tested DWI = np.zeros((2, 2, 2, len(gtab_2s.bvals))) FAref = np.zeros((2, 2, 2)) MDref = np.zeros((2, 2, 2)) # Diffusion of tissue and water compartments are constant for all voxel mevals = np.array([[0.0017, 0.0003, 0.0003], [0.003, 0.003, 0.003]]) # volume fractions GTF = np.array([[[0.06, 0.71], [0.33, 0.91]], [[0., 0.], [0., 0.]]]) # S0 multivoxel S0m = 100 * np.ones((2, 2, 2)) # model_params ground truth (to be fill) model_params_mv = np.zeros((2, 2, 2, 13)) for i in range(2): for j in range(2): gtf = GTF[0, i, j] S, p = multi_tensor(gtab_2s, mevals, S0=100, angles=[(90, 0), (90, 0)], fractions=[(1-gtf) * 100, gtf*100], snr=None) DWI[0, i, j] = S FAref[0, i, j] = FAdti MDref[0, i, j] = MDdti R = all_tensor_evecs(p[0]) R = R.reshape((9)) model_params_mv[0, i, j] = \ np.concatenate(([0.0017, 0.0003, 0.0003], R, [gtf]), axis=0)
def test_csd_predict(): """ Test prediction API """ SNR = 100 S0 = 1 _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = small_sphere odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) # Predicting from a fit should give the same result as predicting from a # model, S0 is 1 by default prediction1 = csd_fit.predict() prediction2 = csd.predict(csd_fit.shm_coeff) npt.assert_array_equal(prediction1, prediction2) npt.assert_array_equal(prediction1[..., gtab.b0s_mask], 1.) # Same with a different S0 prediction1 = csd_fit.predict(S0=123.) prediction2 = csd.predict(csd_fit.shm_coeff, S0=123.) npt.assert_array_equal(prediction1, prediction2) npt.assert_array_equal(prediction1[..., gtab.b0s_mask], 123.) # For "well behaved" coefficients, the model should be able to find the # coefficients from the predicted signal. coeff = np.random.random(csd_fit.shm_coeff.shape) - .5 coeff[..., 0] = 10. S = csd.predict(coeff) csd_fit = csd.fit(S) npt.assert_array_almost_equal(coeff, csd_fit.shm_coeff) # Test predict on nd-data set S_nd = np.zeros((2, 3, 4, S.size)) S_nd[:] = S fit = csd.fit(S_nd) predict1 = fit.predict() predict2 = csd.predict(fit.shm_coeff) npt.assert_array_almost_equal(predict1, predict2)
def sim_tensor_2x(gtab, angle=90, sphere=None, S0=1., snr=None): mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) data, sticks = multi_tensor(gtab, mevals, S0, angles=[(90 , 0), (90, angle)], fractions=[50, 50], snr=snr) mevecs = [all_tensor_evecs(sticks[0]).T, all_tensor_evecs(sticks[1]).T] odf_gt = multi_tensor_odf(sphere.vertices, [0.5, 0.5], mevals, mevecs) return data, sticks, odf_gt
def test_predict(): SNR = 1000 S0 = 1 _, fbvals, fbvecs = dpd.get_data("small_64D") bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = grad.gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, sticks = sims.multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sfmodel = sfm.SparseFascicleModel(gtab, response=[0.0015, 0.0003, 0.0003]) sffit = sfmodel.fit(S) pred = sffit.predict() npt.assert_almost_equal(pred, S, decimal=1)
def test_fwdti_precision(): # Simulation when water contamination is added gtf = 0.63416 # ground truth volume fraction mevals = np.array([[0.0017, 0.0003, 0.0003], [0.003, 0.003, 0.003]]) S_conta, peaks = multi_tensor(gtab_2s, mevals, S0=100, angles=[(90, 0), (90, 0)], fractions=[(1-gtf) * 100, gtf*100], snr=None) fwdm = fwdti.FreeWaterTensorModel(gtab_2s, 'WLS', piterations=5) fwefit = fwdm.fit(S_conta) FAfwe = fwefit.fa Ffwe = fwefit.f MDfwe = fwefit.md assert_almost_equal(FAdti, FAfwe, decimal=5) assert_almost_equal(Ffwe, gtf, decimal=5) assert_almost_equal(MDfwe, MDdti, decimal=5)
def test_fwdti_restore(): # Restore has to work well even in nonproblematic cases # Simulate a signal corrupted by free water diffusion contamination gtf = 0.50 # ground truth volume fraction mevals = np.array([[0.0017, 0.0003, 0.0003], [0.003, 0.003, 0.003]]) S_conta, peaks = multi_tensor(gtab_2s, mevals, S0=100, angles=[(90, 0), (90, 0)], fractions=[(1-gtf) * 100, gtf*100], snr=None) fwdm = fwdti.FreeWaterTensorModel(gtab_2s, 'NLS', weighting='sigma', sigma=4) fwdtiF = fwdm.fit(S_conta) assert_array_almost_equal(fwdtiF.fa, FAdti) assert_array_almost_equal(fwdtiF.f, gtf) fwdm2 = fwdti.FreeWaterTensorModel(gtab_2s, 'NLS', weighting='gmm') fwdtiF2 = fwdm2.fit(S_conta) assert_array_almost_equal(fwdtiF2.fa, FAdti) assert_array_almost_equal(fwdtiF2.f, gtf)
def test_peaks_shm_coeff(): SNR = 100 S0 = 100 _, fbvals, fbvecs = get_data('small_64D') from dipy.data import get_sphere sphere = get_sphere('symmetric724') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) data, _ = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)], fractions=[50, 50], snr=SNR) from dipy.reconst.shm import CsaOdfModel model = CsaOdfModel(gtab, 4) pam = peaks_from_model(model, data[None,:], sphere, .5, 45, return_odf=True, return_sh=True) # Test that spherical harmonic coefficients return back correctly B = np.linalg.pinv(pam.invB) odf2 = np.dot(pam.shm_coeff, B) assert_array_almost_equal(pam.odf, odf2) assert_equal(pam.shm_coeff.shape[-1], 45) pam = peaks_from_model(model, data[None,:], sphere, .5, 45, return_odf=True, return_sh=False) assert_equal(pam.shm_coeff, None) pam = peaks_from_model(model, data[None, :], sphere, .5, 45, return_odf=True, return_sh=True, sh_basis_type='mrtrix') B = np.linalg.pinv(pam.invB) odf2 = np.dot(pam.shm_coeff, B) assert_array_almost_equal(pam.odf, odf2)
def test_r2_term_odf_sharp(): SNR = None S0 = 1 angle = 45 #45 degrees is a very tight angle to disentangle _, fbvals, fbvecs = get_data('small_64D') #get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) sphere = get_sphere('symmetric724') gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (angle, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) odfs_sh = sf_to_sh(odf_gt, sphere, sh_order=8, basis_type=None) fodf_sh = odf_sh_to_sharp(odfs_sh, sphere, basis=None, ratio=3 / 15., sh_order=8, lambda_=1., tau=0.1, r2_term=True) fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None) directions_gt, _, _ = peak_directions(odf_gt, sphere) directions, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions_gt, directions) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) # This should pass as well sdt_model = ConstrainedSDTModel(gtab, ratio=3/15., sh_order=8) sdt_fit = sdt_model.fit(S) fodf = sdt_fit.odf(sphere) directions_gt, _, _ = peak_directions(odf_gt, sphere) directions, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions_gt, directions) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2)
def test_with_higher_S0(): """ Test whether fitting works for S0 > 1. """ # params for a single voxel S0_2 = 1000. params2 = np.array([S0_2, f, D_star, D]) mevals2 = np.array(([D_star, D_star, D_star], [D, D, D])) # This gives an isotropic signal. signal2 = multi_tensor(gtab, mevals2, snr=None, S0=S0_2, fractions=[f * 100, 100 * (1 - f)]) # Single voxel data data_single2 = signal2[0] ivim_fit = ivim_model.fit(data_single2) est_signal = ivim_fit.predict(gtab) assert_array_equal(est_signal.shape, data_single2.shape) assert_array_almost_equal(est_signal, data_single2) assert_array_almost_equal(ivim_fit.model_params, params2)
def test_sfm_stick(): fdata, fbvals, fbvecs = dpd.get_data() data = nib.load(fdata).get_data() gtab = grad.gradient_table(fbvals, fbvecs) sfmodel = sfm.SparseFascicleModel(gtab, solver="NNLS", response=[0.001, 0, 0]) sffit1 = sfmodel.fit(data[0, 0, 0]) sphere = dpd.get_sphere("symmetric642") odf1 = sffit1.odf(sphere) pred1 = sffit1.predict(gtab) SNR = 1000 S0 = 1 mevals = np.array(([0.001, 0, 0], [0.001, 0, 0])) angles = [(0, 0), (60, 0)] S, sticks = sims.multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sfmodel = sfm.SparseFascicleModel(gtab, solver="NNLS", response=[0.001, 0, 0]) sffit = sfmodel.fit(S) pred = sffit.predict() npt.assert_almost_equal(pred, S, decimal=1)
def test_odf_sh_to_sharp(): SNR = None S0 = 1 _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) S, sticks = multi_tensor(gtab, mevals, S0, angles=[(10, 0), (100, 0)], fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric724') qb = QballModel(gtab, sh_order=8, assume_normed=True) qbfit = qb.fit(S) odf_gt = qbfit.odf(sphere) Z = np.linalg.norm(odf_gt) odfs_gt = np.zeros((3, 1, 1, odf_gt.shape[0])) odfs_gt[:,:,:] = odf_gt[:] odfs_sh = sf_to_sh(odfs_gt, sphere, sh_order=8, basis_type=None) odfs_sh /= Z fodf_sh = odf_sh_to_sharp(odfs_sh, sphere, basis=None, ratio=3 / 15., sh_order=8, lambda_=1., tau=0.1) fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None) directions2, _, _ = peak_directions(fodf[0, 0, 0], sphere) assert_equal(directions2.shape[0], 2)
def test_predict(): SNR = 1000 S0 = 100 _, fbvals, fbvecs = dpd.get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = grad.gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, sticks = sims.multi_tensor(gtab, mevals, S0, angles=angles, fractions=[10, 90], snr=SNR) sfmodel = sfm.SparseFascicleModel(gtab, response=[0.0015, 0.0003, 0.0003]) sffit = sfmodel.fit(S) pred = sffit.predict() npt.assert_(xval.coeff_of_determination(pred, S) > 97) # Should be possible to predict using a different gtab: new_gtab = grad.gradient_table(bvals[::2], bvecs[::2]) new_pred = sffit.predict(new_gtab) npt.assert_(xval.coeff_of_determination(new_pred, S[::2]) > 97)
def _create_mt_sim(mevals, angles, fractions, S0, SNR, half_sphere=False): _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=fractions, snr=SNR) sphere = get_sphere('symmetric724').subdivide(2) if half_sphere: sphere = HemiSphere.from_sphere(sphere) odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles=angles, fractions=fractions) return odf_gt, sticks, sphere
def test_fwdti_singlevoxel(): # Simulation when water contamination is added gtf = 0.44444 # ground truth volume fraction mevals = np.array([[0.0017, 0.0003, 0.0003], [0.003, 0.003, 0.003]]) S_conta, peaks = multi_tensor(gtab_2s, mevals, S0=100, angles=[(90, 0), (90, 0)], fractions=[(1-gtf) * 100, gtf*100], snr=None) fwdm = fwdti.FreeWaterTensorModel(gtab_2s, 'WLS') fwefit = fwdm.fit(S_conta) FAfwe = fwefit.fa Ffwe = fwefit.f MDfwe = fwefit.md assert_almost_equal(FAdti, FAfwe, decimal=3) assert_almost_equal(Ffwe, gtf, decimal=3) assert_almost_equal(MDfwe, MDdti, decimal=3) # Test non-linear fit fwdm = fwdti.FreeWaterTensorModel(gtab_2s, 'NLS', cholesky=False) fwefit = fwdm.fit(S_conta) FAfwe = fwefit.fa Ffwe = fwefit.f MDfwe = fwefit.md assert_almost_equal(FAdti, FAfwe) assert_almost_equal(Ffwe, gtf) assert_almost_equal(MDfwe, MDdti) # Test cholesky fwdm = fwdti.FreeWaterTensorModel(gtab_2s, 'NLS', cholesky=True) fwefit = fwdm.fit(S_conta) FAfwe = fwefit.fa Ffwe = fwefit.f MDfwe = fwefit.md assert_almost_equal(FAdti, FAfwe) assert_almost_equal(Ffwe, gtf) assert_almost_equal(MDfwe, MDfwe)
def test_r2_term_odf_sharp(): SNR = None S0 = 1 angle = 45 # 45 degrees is a very tight angle to disentangle _, fbvals, fbvecs = get_fnames('small_64D') # get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) sphere = default_sphere gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (angle, 0)] S, _ = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) odfs_sh = sf_to_sh(odf_gt, sphere, sh_order=8, basis_type=None) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) fodf_sh = odf_sh_to_sharp(odfs_sh, sphere, basis=None, ratio=3 / 15., sh_order=8, lambda_=1., tau=0.1, r2_term=True) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None) directions_gt, _, _ = peak_directions(odf_gt, sphere) directions, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions_gt, directions) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) # This should pass as well with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) sdt_model = ConstrainedSDTModel(gtab, ratio=3 / 15., sh_order=8) sdt_fit = sdt_model.fit(S) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) fodf = sdt_fit.odf(sphere) directions_gt, _, _ = peak_directions(odf_gt, sphere) directions, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions_gt, directions) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2)
def test_csd_predict(): """ Test prediction API """ SNR = 100 S0 = 1 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, _ = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = small_sphere multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) response = (np.array([0.0015, 0.0003, 0.0003]), S0) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) # Predicting from a fit should give the same result as predicting from a # model, S0 is 1 by default prediction1 = csd_fit.predict() with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) prediction2 = csd.predict(csd_fit.shm_coeff) npt.assert_array_equal(prediction1, prediction2) npt.assert_array_equal(prediction1[..., gtab.b0s_mask], 1.) # Same with a different S0 prediction1 = csd_fit.predict(S0=123.) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) prediction2 = csd.predict(csd_fit.shm_coeff, S0=123.) npt.assert_array_equal(prediction1, prediction2) npt.assert_array_equal(prediction1[..., gtab.b0s_mask], 123.) # For "well behaved" coefficients, the model should be able to find the # coefficients from the predicted signal. coeff = np.random.random(csd_fit.shm_coeff.shape) - .5 coeff[..., 0] = 10. with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) S = csd.predict(coeff) csd_fit = csd.fit(S) npt.assert_array_almost_equal(coeff, csd_fit.shm_coeff) # Test predict on nd-data set S_nd = np.zeros((2, 3, 4, S.size)) S_nd[:] = S fit = csd.fit(S_nd) predict1 = fit.predict() with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) predict2 = csd.predict(fit.shm_coeff) npt.assert_array_almost_equal(predict1, predict2)
def test_recursive_response_calibration(): """ Test the recursive response calibration method. """ SNR = 100 S0 = 1 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) sphere = default_sphere gtab = gradient_table(bvals, bvecs) evals = np.array([0.0015, 0.0003, 0.0003]) evecs = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]]).T mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (90, 0)] where_dwi = lazy_index(~gtab.b0s_mask) S_cross, _ = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) S_single = single_tensor(gtab, S0, evals, evecs, snr=SNR) data = np.concatenate((np.tile(S_cross, (8, 1)), np.tile(S_single, (2, 1))), axis=0) odf_gt_cross = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) odf_gt_single = single_tensor_odf(sphere.vertices, evals, evecs) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) response = recursive_response(gtab, data, mask=None, sh_order=8, peak_thr=0.01, init_fa=0.05, init_trace=0.0021, iter=8, convergence=0.001, parallel=False) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(data) assert_equal(np.all(csd_fit.shm_coeff[:, 0] >= 0), True) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) fodf = csd_fit.odf(sphere) directions_gt_single, _, _ = peak_directions(odf_gt_single, sphere) directions_gt_cross, _, _ = peak_directions(odf_gt_cross, sphere) directions_single, _, _ = peak_directions(fodf[8, :], sphere) directions_cross, _, _ = peak_directions(fodf[0, :], sphere) ang_sim = angular_similarity(directions_cross, directions_gt_cross) assert_equal(ang_sim > 1.9, True) assert_equal(directions_cross.shape[0], 2) assert_equal(directions_gt_cross.shape[0], 2) ang_sim = angular_similarity(directions_single, directions_gt_single) assert_equal(ang_sim > 0.9, True) assert_equal(directions_single.shape[0], 1) assert_equal(directions_gt_single.shape[0], 1) with warnings.catch_warnings(record=True) as w: sphere = Sphere(xyz=gtab.gradients[where_dwi]) npt.assert_equal(len(w), 1) npt.assert_(issubclass(w[0].category, UserWarning)) npt.assert_("Vertices are not on the unit sphere" in str(w[0].message)) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) sf = response.on_sphere(sphere) S = np.concatenate(([response.S0], sf)) tenmodel = TensorModel(gtab, min_signal=0.001) tenfit = tenmodel.fit(S) FA = fractional_anisotropy(tenfit.evals) FA_gt = fractional_anisotropy(evals) assert_almost_equal(FA, FA_gt, 1)
# Matrix where synthetic signals will be stored dwi = np.empty((f.size, ang.size, bvals.size)) for f_i in range(f.size): # estimating volume fractions for individual tensors fractions = np.array([100 - f[f_i], f[f_i], 100 - f[f_i], f[f_i]]) * 0.5 for a_i in range(ang.size): # defining the directions for individual tensors angles = [(ang[a_i], 0.0), (ang[a_i], 0.0), (0.0, 0.0), (0.0, 0.0)] # producing signals using Dipy's function multi_tensor signal, sticks = multi_tensor(gtab, mevals, S0=100, angles=angles, fractions=fractions, snr=None) dwi[f_i, a_i, :] = signal """ Now that all synthetic signals were produced, we can go forward with MSDKI fitting. As other Dipy's reconstruction techniques, the MSDKI model has to be first defined for the specific GradientTable object of the synthetic data. For MSDKI, this is done by instantiating the MeanDiffusionKurtosisModel object in the following way: """ msdki_model = msdki.MeanDiffusionKurtosisModel(gtab) """ MSDKI can then be fitted to the synthetic data by calling the ``fit`` function of this object:
def test_peaks_shm_coeff(): SNR = 100 S0 = 100 _, fbvals, fbvecs = get_data('small_64D') from dipy.data import get_sphere sphere = get_sphere('symmetric724') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) data, _ = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)], fractions=[50, 50], snr=SNR) from dipy.reconst.shm import CsaOdfModel model = CsaOdfModel(gtab, 4) pam = peaks_from_model(model, data[None, :], sphere, .5, 45, return_odf=True, return_sh=True) # Test that spherical harmonic coefficients return back correctly B = np.linalg.pinv(pam.invB) odf2 = np.dot(pam.shm_coeff, B) assert_array_almost_equal(pam.odf, odf2) assert_equal(pam.shm_coeff.shape[-1], 45) pam = peaks_from_model(model, data[None, :], sphere, .5, 45, return_odf=True, return_sh=False) assert_equal(pam.shm_coeff, None) pam = peaks_from_model(model, data[None, :], sphere, .5, 45, return_odf=True, return_sh=True, sh_basis_type='mrtrix') B = np.linalg.pinv(pam.invB) odf2 = np.dot(pam.shm_coeff, B) assert_array_almost_equal(pam.odf, odf2)
def setup_module(): global gtab, ivim_fit_single, ivim_model_trr, data_single, params_trr, \ data_multi, ivim_params_trr, D_star, D, f, S0, gtab_with_multiple_b0, \ noisy_single, mevals, gtab_no_b0, ivim_fit_multi, ivim_model_VP, \ f_VP, D_star_VP, D_VP, params_VP # Let us generate some data for testing. bvals = np.array([ 0., 10., 20., 30., 40., 60., 80., 100., 120., 140., 160., 180., 200., 300., 400., 500., 600., 700., 800., 900., 1000. ]) N = len(bvals) bvecs = generate_bvecs(N) gtab = gradient_table(bvals, bvecs.T, b0_threshold=0) S0, f, D_star, D = 1000.0, 0.132, 0.00885, 0.000921 # params for a single voxel params_trr = np.array([S0, f, D_star, D]) mevals = np.array(([D_star, D_star, D_star], [D, D, D])) # This gives an isotropic signal. signal = multi_tensor(gtab, mevals, snr=None, S0=S0, fractions=[f * 100, 100 * (1 - f)]) # Single voxel data data_single = signal[0] data_multi = np.zeros((2, 2, 1, len(gtab.bvals))) data_multi[0, 0, 0] = data_multi[0, 1, 0] = data_multi[1, 0, 0] = data_multi[1, 1, 0] = data_single ivim_params_trr = np.zeros((2, 2, 1, 4)) ivim_params_trr[0, 0, 0] = ivim_params_trr[0, 1, 0] = params_trr ivim_params_trr[1, 0, 0] = ivim_params_trr[1, 1, 0] = params_trr ivim_model_trr = IvimModel(gtab, fit_method='trr') ivim_model_one_stage = IvimModel(gtab, fit_method='trr') ivim_fit_single = ivim_model_trr.fit(data_single) ivim_fit_multi = ivim_model_trr.fit(data_multi) ivim_model_one_stage.fit(data_single) ivim_model_one_stage.fit(data_multi) bvals_no_b0 = np.array([ 5., 10., 20., 30., 40., 60., 80., 100., 120., 140., 160., 180., 200., 300., 400., 500., 600., 700., 800., 900., 1000. ]) _ = generate_bvecs(N) # bvecs_no_b0 gtab_no_b0 = gradient_table(bvals_no_b0, bvecs.T, b0_threshold=0) bvals_with_multiple_b0 = np.array([ 0., 0., 0., 0., 40., 60., 80., 100., 120., 140., 160., 180., 200., 300., 400., 500., 600., 700., 800., 900., 1000. ]) bvecs_with_multiple_b0 = generate_bvecs(N) gtab_with_multiple_b0 = gradient_table(bvals_with_multiple_b0, bvecs_with_multiple_b0.T, b0_threshold=0) noisy_single = np.array([ 4243.71728516, 4317.81298828, 4244.35693359, 4439.36816406, 4420.06201172, 4152.30078125, 4114.34912109, 4104.59375, 4151.61914062, 4003.58374023, 4013.68408203, 3906.39428711, 3909.06079102, 3495.27197266, 3402.57006836, 3163.10180664, 2896.04003906, 2663.7253418, 2614.87695312, 2316.55371094, 2267.7722168 ]) noisy_multi = np.zeros((2, 2, 1, len(gtab.bvals))) noisy_multi[0, 1, 0] = noisy_multi[1, 0, 0] = noisy_multi[1, 1, 0] = noisy_single noisy_multi[0, 0, 0] = data_single ivim_model_VP = IvimModel(gtab, fit_method='VarPro') f_VP, D_star_VP, D_VP = 0.13, 0.0088, 0.000921 # params for a single voxel params_VP = np.array([f, D_star, D]) ivim_params_VP = np.zeros((2, 2, 1, 3)) ivim_params_VP[0, 0, 0] = ivim_params_VP[0, 1, 0] = params_VP ivim_params_VP[1, 0, 0] = ivim_params_VP[1, 1, 0] = params_VP
def test_peaksFromModelParallel(): SNR = 100 S0 = 100 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) data, _ = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)], fractions=[50, 50], snr=SNR) for sphere in [_sphere, default_sphere]: # test equality with/without multiprocessing model = SimpleOdfModel(gtab) pam_multi = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=True) pam_single = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=False) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", category=UserWarning) pam_multi_inv1 = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=True, nbr_processes=0) pam_multi_inv2 = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=True, nbr_processes=-2) assert_(len(w) == 2) assert_(issubclass(w[0].category, UserWarning)) assert_(issubclass(w[1].category, UserWarning)) assert_("Invalid number of processes " in str(w[0].message)) assert_("Invalid number of processes " in str(w[1].message)) for pam in [pam_multi, pam_multi_inv1, pam_multi_inv2]: assert_equal(pam.gfa.dtype, pam_single.gfa.dtype) assert_equal(pam.gfa.shape, pam_single.gfa.shape) assert_array_almost_equal(pam.gfa, pam_single.gfa) assert_equal(pam.qa.dtype, pam_single.qa.dtype) assert_equal(pam.qa.shape, pam_single.qa.shape) assert_array_almost_equal(pam.qa, pam_single.qa) assert_equal(pam.peak_values.dtype, pam_single.peak_values.dtype) assert_equal(pam.peak_values.shape, pam_single.peak_values.shape) assert_array_almost_equal(pam.peak_values, pam_single.peak_values) assert_equal(pam.peak_indices.dtype, pam_single.peak_indices.dtype) assert_equal(pam.peak_indices.shape, pam_single.peak_indices.shape) assert_array_equal(pam.peak_indices, pam_single.peak_indices) assert_equal(pam.peak_dirs.dtype, pam_single.peak_dirs.dtype) assert_equal(pam.peak_dirs.shape, pam_single.peak_dirs.shape) assert_array_almost_equal(pam.peak_dirs, pam_single.peak_dirs) assert_equal(pam.shm_coeff.dtype, pam_single.shm_coeff.dtype) assert_equal(pam.shm_coeff.shape, pam_single.shm_coeff.shape) assert_array_almost_equal(pam.shm_coeff, pam_single.shm_coeff) assert_equal(pam.odf.dtype, pam_single.odf.dtype) assert_equal(pam.odf.shape, pam_single.odf.shape) assert_array_almost_equal(pam.odf, pam_single.odf)
def rfiw_phantom(gtab, snr=None): """rectangle fiber immersed in water""" # define voxel index slice_ind = np.zeros((10, 10, 8)) slice_ind[4:7, 4:7, :] = 1 slice_ind[4:7, 7, :] = 2 slice_ind[7, 7, :] = 3 slice_ind[7, 4:7, :] = 4 slice_ind[7, 3, :] = 5 slice_ind[4:7, 3, :] = 6 slice_ind[3, 3, :] = 7 slice_ind[3, 4:7, :] = 8 slice_ind[3, 7, :] = 9 # Define tissue diffusion parameters # Restricted diffusion ADr = 0.99e-3 RDr = 0.0 # Hindered diffusion ADh = 2.26e-3 RDh = 0.87e-3 # S0 value for tissue S1 = 50 # Fraction between Restricted and Hindered diffusion fia = 0.51 # Define water diffusion Dwater = 3e-3 S2 = 100 # S0 value for water # Define tissue volume fraction for each voxel type (in index order) f = np.array([0., 1., 0.6, 0.18, 0.30, 0.15, 0.50, 0.35, 0.70, 0.42]) # Define S0 for each voxel (in index order) S0 = S1 * f + S2 * (1 - f) # multi tensor simulations assume that each water pull as constant S0 # since I am assuming that tissue and water voxels have different S0, # tissue volume fractions have to be adjusted to the measured f values when # constant S0 are assumed constant. Doing this correction, simulations will # be analogous to simulates that S0 are different for each media. (For more # details on this contact the phantom designer) f1 = f * S1 / S0 mevals = np.array([[ADr, RDr, RDr], [ADh, RDh, RDh], [Dwater, Dwater, Dwater]]) angles = [(0, 0, 1), (0, 0, 1), (0, 0, 1)] dwi = np.zeros(slice_ind.shape + (gtab.bvals.size, )) for i in range(10): fractions = [f1[i] * fia * 100, f1[i] * (1 - fia) * 100, (1 - f1[i]) * 100] sig, direction = multi_tensor(gtab, mevals, S0=S0[i], angles=angles, fractions=fractions, snr=None) dwi[slice_ind == i, :] = sig if snr is None: return dwi else: sigma = S2 * 1.0 / snr n1 = np.random.normal(0, sigma, size=dwi.shape) n2 = np.random.normal(0, sigma, size=dwi.shape) return [np.sqrt((dwi / np.sqrt(2) + n1)**2 + (dwi / np.sqrt(2) + n2)**2), sigma]
def test_peaksFromModelParallel(): SNR = 100 S0 = 100 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) data, _ = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)], fractions=[50, 50], snr=SNR) for sphere in [_sphere, default_sphere]: # test equality with/without multiprocessing model = SimpleOdfModel(gtab) pam_multi = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=True) pam_single = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=False) pam_multi_inv1 = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=True, nbr_processes=-1) pam_multi_inv2 = peaks_from_model(model, data, sphere, .5, 45, normalize_peaks=True, return_odf=True, return_sh=True, parallel=True, nbr_processes=-2) for pam in [pam_multi, pam_multi_inv1, pam_multi_inv2]: assert_equal(pam.gfa.dtype, pam_single.gfa.dtype) assert_equal(pam.gfa.shape, pam_single.gfa.shape) assert_array_almost_equal(pam.gfa, pam_single.gfa) assert_equal(pam.qa.dtype, pam_single.qa.dtype) assert_equal(pam.qa.shape, pam_single.qa.shape) assert_array_almost_equal(pam.qa, pam_single.qa) assert_equal(pam.peak_values.dtype, pam_single.peak_values.dtype) assert_equal(pam.peak_values.shape, pam_single.peak_values.shape) assert_array_almost_equal(pam.peak_values, pam_single.peak_values) assert_equal(pam.peak_indices.dtype, pam_single.peak_indices.dtype) assert_equal(pam.peak_indices.shape, pam_single.peak_indices.shape) assert_array_equal(pam.peak_indices, pam_single.peak_indices) assert_equal(pam.peak_dirs.dtype, pam_single.peak_dirs.dtype) assert_equal(pam.peak_dirs.shape, pam_single.peak_dirs.shape) assert_array_almost_equal(pam.peak_dirs, pam_single.peak_dirs) assert_equal(pam.shm_coeff.dtype, pam_single.shm_coeff.dtype) assert_equal(pam.shm_coeff.shape, pam_single.shm_coeff.shape) assert_array_almost_equal(pam.shm_coeff, pam_single.shm_coeff) assert_equal(pam.odf.dtype, pam_single.odf.dtype) assert_equal(pam.odf.shape, pam_single.odf.shape) assert_array_almost_equal(pam.odf, pam_single.odf)
RDe = RDE[i, j, k] fie = FIE[i, j, k] mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]]) frac = [fie * 100, (1 - fie) * 100] theta = random.uniform(0, 180) phi = random.uniform(0, 320) angles = [(theta, phi), (theta, phi)] signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, angles=angles, fractions=frac, snr=None) DWIsim[i, j, k, :] = signal signal, sticks = multi_tensor(gtab_2s, mevals, angles=angles, fractions=frac, snr=None) DWIsim_all_taylor[i, j, k, :] = signal def test_single_fiber_model(): # single fiber simulate (which is the assumption of our model) fie = 0.49 ADi = 0.00099 ADe = 0.00226 RDi = 0 RDe = 0.00087 # prepare simulation: theta = random.uniform(0, 180)
def test_shore_metrics(): gtab = get_gtab_taiwan_dsi() mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angl = [(0, 0), (60, 0)] S, _ = multi_tensor(gtab, mevals, S0=100.0, angles=angl, fractions=[50, 50], snr=None) # test shore_indices n = 7 l = 6 m = -4 radial_order, c = shore_order(n, l, m) n2, l2, m2 = shore_indices(radial_order, c) npt.assert_equal(n, n2) npt.assert_equal(l, l2) npt.assert_equal(m, m2) radial_order = 6 c = 41 n, l, m = shore_indices(radial_order, c) radial_order2, c2 = shore_order(n, l, m) npt.assert_equal(radial_order, radial_order2) npt.assert_equal(c, c2) npt.assert_raises(ValueError, shore_indices, 6, 100) npt.assert_raises(ValueError, shore_order, m, n, l) # since we are testing without noise we can use higher order and lower # lambdas, with respect to the default. radial_order = 8 zeta = 700 lambdaN = 1e-12 lambdaL = 1e-12 asm = ShoreModel(gtab, radial_order=radial_order, zeta=zeta, lambdaN=lambdaN, lambdaL=lambdaL) asmfit = asm.fit(S) c_shore = asmfit.shore_coeff cmat = shore_matrix(radial_order, zeta, gtab) S_reconst = np.dot(cmat, c_shore) # test the signal reconstruction S = S / S[0] nmse_signal = np.sqrt(np.sum((S - S_reconst) ** 2)) / (S.sum()) npt.assert_almost_equal(nmse_signal, 0.0, 4) # test if the analytical integral of the pdf is equal to one integral = 0 for n in range(int((radial_order)/2 + 1)): integral += c_shore[n] * (np.pi**(-1.5) * zeta ** (-1.5) * genlaguerre(n, 0.5)(0)) ** 0.5 npt.assert_almost_equal(integral, 1.0, 10) # test if the integral of the pdf calculated on a discrete grid is # equal to one pdf_discrete = asmfit.pdf_grid(17, 40e-3) integral = pdf_discrete.sum() npt.assert_almost_equal(integral, 1.0, 1) # compare the shore pdf with the ground truth multi_tensor pdf sphere = get_sphere('symmetric724') v = sphere.vertices radius = 10e-3 pdf_shore = asmfit.pdf(v * radius) pdf_mt = multi_tensor_pdf(v * radius, mevals=mevals, angles=angl, fractions=[50, 50]) nmse_pdf = np.sqrt(np.sum((pdf_mt - pdf_shore) ** 2)) / (pdf_mt.sum()) npt.assert_almost_equal(nmse_pdf, 0.0, 2) # compare the shore rtop with the ground truth multi_tensor rtop rtop_shore_signal = asmfit.rtop_signal() rtop_shore_pdf = asmfit.rtop_pdf() npt.assert_almost_equal(rtop_shore_signal, rtop_shore_pdf, 9) rtop_mt = multi_tensor_rtop([.5, .5], mevals=mevals) npt.assert_equal(rtop_mt / rtop_shore_signal < 1.10 and rtop_mt / rtop_shore_signal > 0.95, True) # compare the shore msd with the ground truth multi_tensor msd msd_mt = multi_tensor_msd([.5, .5], mevals=mevals) msd_shore = asmfit.msd() npt.assert_equal(msd_mt / msd_shore < 1.05 and msd_mt / msd_shore > 0.95, True)
def test_csdeconv(): SNR = 100 S0 = 1 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs, b0_threshold=0) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) assert_equal(csd_fit.shm_coeff[0] > 0, True) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", category=UserWarning) _ = ConstrainedSphericalDeconvModel(gtab, response, sh_order=10) assert_greater(len([lw for lw in w if issubclass(lw.category, UserWarning)]), 0) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", category=UserWarning) ConstrainedSphericalDeconvModel(gtab, response, sh_order=8) assert_equal(len([lw for lw in w if issubclass(lw.category, UserWarning)]), 0) mevecs = [] for s in sticks: mevecs += [all_tensor_evecs(s).T] S2 = single_tensor(gtab, 100, mevals[0], mevecs[0], snr=None) big_S = np.zeros((10, 10, 10, len(S2))) big_S[:] = S2 aresponse, aratio = auto_response(gtab, big_S, roi_center=(5, 5, 4), roi_radius=3, fa_thr=0.5) assert_array_almost_equal(aresponse[0], response[0]) assert_almost_equal(aresponse[1], 100) assert_almost_equal(aratio, response[0][1] / response[0][0]) auto_response(gtab, big_S, roi_radius=3, fa_thr=0.5) assert_array_almost_equal(aresponse[0], response[0]) _, _, nvoxels = auto_response(gtab, big_S, roi_center=(5, 5, 4), roi_radius=30, fa_thr=0.5, return_number_of_voxels=True) assert_equal(nvoxels, 1000) _, _, nvoxels = auto_response(gtab, big_S, roi_center=(5, 5, 4), roi_radius=30, fa_thr=1, return_number_of_voxels=True) assert_equal(nvoxels, 0)
# repetitions for the given pair of minimum-maximun # b-value rep_simulates = np.zeros((nDTdirs * nrep, bvecs.shape[0])) # Repeat simulations for the 120 diffusion gradient directions for di in range(nDTdirs): d = DTdirs[di] # Repeat each direction 100 times for s_i in np.arange(di * nrep, (di + 1) * nrep): # Multi-compartmental simulations are done using # Dipy's function multi_tensor signal, sticks = multi_tensor(gtab, mevals, S0=100, angles=[d, (1, 0, 0)], fractions=fractions, snr=SNRa) rep_simulates[s_i, :] = signal # Process NLS fitting for all simulation repetitions of # a given pair of minimum-maximun b-value fw_params[bmin_i, bmax_i, :, :] = nls_fit_tensor(gtab, rep_simulates) # Process computing progress prog = (bmax_i * 1.0) / bmax.size + (bmin_i + 1.0) / (bmax.size * bmin.size) time.sleep(1) sys.stdout.write("\r%f%%" % prog * 100) sys.stdout.flush()
# Let us generate some data for testing. bvals = np.array([0., 10., 20., 30., 40., 60., 80., 100., 120., 140., 160., 180., 200., 300., 400., 500., 600., 700., 800., 900., 1000.]) N = len(bvals) bvecs = generate_bvecs(N) gtab = gradient_table(bvals, bvecs.T) S0, f, D_star, D = 1000.0, 0.132, 0.00885, 0.000921 # params for a single voxel params = np.array([S0, f, D_star, D]) mevals = np.array(([D_star, D_star, D_star], [D, D, D])) # This gives an isotropic signal. signal = multi_tensor(gtab, mevals, snr=None, S0=S0, fractions=[f * 100, 100 * (1 - f)]) # Single voxel data data_single = signal[0] data_multi = np.zeros((2, 2, 1, len(gtab.bvals))) data_multi[0, 0, 0] = data_multi[0, 1, 0] = data_multi[ 1, 0, 0] = data_multi[1, 1, 0] = data_single ivim_params = np.zeros((2, 2, 1, 4)) ivim_params[0, 0, 0] = ivim_params[0, 1, 0] = params ivim_params[1, 0, 0] = ivim_params[1, 1, 0] = params ivim_model = IvimModel(gtab) ivim_model_one_stage = IvimModel(gtab) ivim_fit_single = ivim_model.fit(data_single) ivim_fit_multi = ivim_model.fit(data_multi)
FAref = np.zeros((2, 2, 2)) MDref = np.zeros((2, 2, 2)) # Diffusion of tissue and water compartments are constant for all voxel mevals = np.array([[0.0017, 0.0003, 0.0003], [0.003, 0.003, 0.003]]) # volume fractions GTF = np.array([[[0.06, 0.71], [0.33, 0.91]], [[0., 0.], [0., 0.]]]) # S0 multivoxel S0m = 100 * np.ones((2, 2, 2)) # model_params ground truth (to be fill) model_params_mv = np.zeros((2, 2, 2, 13)) for i in range(2): for j in range(2): gtf = GTF[0, i, j] S, p = multi_tensor(gtab_2s, mevals, S0=100, angles=[(90, 0), (90, 0)], fractions=[(1 - gtf) * 100, gtf * 100], snr=None) DWI[0, i, j] = S FAref[0, i, j] = FAdti MDref[0, i, j] = MDdti R = all_tensor_evecs(p[0]) R = R.reshape((9)) model_params_mv[0, i, j] = np.concatenate( ([0.0017, 0.0003, 0.0003], R, [gtf]), axis=0) def test_fwdti_singlevoxel(): # Simulation when water contamination is added gtf = 0.44444 # ground truth volume fraction mevals = np.array([[0.0017, 0.0003, 0.0003], [0.003, 0.003, 0.003]])
def test_odfdeconv(): SNR = 100 S0 = 1 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (90, 0)] S, _ = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) e1 = 15.0 e2 = 3.0 ratio = e2 / e1 csd = ConstrainedSDTModel(gtab, ratio, None) csd_fit = csd.fit(S) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: ConstrainedSDTModel(gtab, ratio, sh_order=10) w_count = len(w) # A warning is expected from the ConstrainedSDTModel constructor # and additionnal warnings should be raised where legacy SH bases # are used assert_equal(w_count > 1, True) with warnings.catch_warnings(record=True) as w: ConstrainedSDTModel(gtab, ratio, sh_order=8) # Test that the warning from ConstrainedSDTModel # constructor is no more raised assert_equal(len(w) == w_count - 1, True) csd_fit = csd.fit(np.zeros_like(S)) fodf = csd_fit.odf(sphere) assert_array_equal(fodf, np.zeros_like(fodf)) odf_sh = np.zeros_like(fodf) odf_sh[1] = np.nan fodf, _ = odf_deconv(odf_sh, csd.R, csd.B_reg) assert_array_equal(fodf, np.zeros_like(fodf))
def test_ivim_tensor(): bvals = array([ 10., 40., 60., 80., 100., 150., 200., 300., 500., 700., 800., 900., 1000., 10., 40., 60., 80., 100., 150., 200., 300., 500., 700., 800., 900., 1000., 10., 40., 60., 80., 100., 150., 200., 300., 500., 700., 800., 900., 1000., 10., 40., 60., 80., 100., 150., 200., 300., 500., 700., 800., 900., 1000., 10., 40., 60., 80., 100., 150., 200., 300., 500., 700., 800., 900., 1000., 10., 40., 60., 80., 100., 150., 200., 300., 500., 700., 800., 900., 1000., 0. ]) bvecs = array([[-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [-1.00000e+00, -3.40515e-09, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [3.40515e-09, 1.00000e+00, 0.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [0.00000e+00, 0.00000e+00, 1.00000e+00], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [7.04358e-01, -8.80947e-02, -7.04358e-01], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-7.04358e-01, 7.04358e-01, 8.80947e-02], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [-8.80947e-02, 7.04358e-01, 7.04358e-01], [0.00000e+00, 0.00000e+00, 0.00000e+00]]) gtab = gradient_table(bvals, bvecs, b0_threshold=0) mevals = np.array([[0.001, 0.0005, 0.0005], [0.1, 0.01, 0.01]]) itm = IvimTensorModel(gtab) betas = np.arange(0.05, 0.3, 0.05) for ii in range(len(betas)): sim = multi_tensor(gtab, mevals=mevals, snr=100, fractions=[100 * (1 - betas[ii]), betas[ii] * 100])[0] itf = itm.fit(np.array([sim])) assert np.allclose(itf.perfusion_fraction, betas[ii], atol=1e-2) prediction = itf.predict(gtab) assert np.allclose(prediction, sim, atol=0.05)
def test_bootstap_peak_tracker(): """This tests that the Bootstrat Peak Direction Getter plays nice LocalTracking and produces reasonable streamlines in a simple example. """ sphere = get_sphere('repulsion100') # A simple image with three possible configurations, a vertical tract, # a horizontal tract and a crossing simple_image = np.array([ [0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [2, 3, 2, 2, 2, 0], [0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], ]) simple_image = simple_image[..., None] bvecs = sphere.vertices bvals = np.ones(len(bvecs)) * 1000 bvecs = np.insert(bvecs, 0, np.array([0, 0, 0]), axis=0) bvals = np.insert(bvals, 0, 0) gtab = gradient_table(bvals, bvecs) angles = [(90, 90), (90, 0)] fracs = [50, 50] mevals = np.array([[1.5, 0.4, 0.4], [1.5, 0.4, 0.4]]) * 1e-3 mevecs = [ np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]), np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) ] voxel1 = single_tensor(gtab, 1, mevals[0], mevecs[0], snr=None) voxel2 = single_tensor(gtab, 1, mevals[0], mevecs[1], snr=None) voxel3, _ = multi_tensor(gtab, mevals, fractions=fracs, angles=angles, snr=None) data = np.tile(voxel3, [5, 6, 1, 1]) data[simple_image == 1] = voxel1 data[simple_image == 2] = voxel2 response = (np.array(mevals[1]), 1) csd_model = ConstrainedSphericalDeconvModel(gtab, response, sh_order=6) seeds = [np.array([0., 1., 0.]), np.array([2., 4., 0.])] tc = BinaryTissueClassifier((simple_image > 0).astype(float)) boot_dg = BootDirectionGetter.from_data(data, csd_model, 60) streamlines_generator = LocalTracking(boot_dg, tc, seeds, np.eye(4), 1.) streamlines = Streamlines(streamlines_generator) expected = [ np.array([[0., 1., 0.], [1., 1., 0.], [2., 1., 0.], [3., 1., 0.], [4., 1., 0.]]), np.array([ [2., 5., 0.], [2., 4., 0.], [2., 3., 0.], [2., 2., 0.], [2., 1., 0.], [2., 0., 0.], ]) ] def allclose(x, y): return x.shape == y.shape and np.allclose(x, y, atol=0.5) if not allclose(streamlines[0], expected[0]): raise AssertionError() if not allclose(streamlines[1], expected[1]): raise AssertionError()
def test_predict(): SNR = 1000 S0 = 100 _, fbvals, fbvecs = dpd.get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = grad.gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, sticks = sims.multi_tensor(gtab, mevals, S0, angles=angles, fractions=[10, 90], snr=SNR) sfmodel = sfm.SparseFascicleModel(gtab, response=[0.0015, 0.0003, 0.0003]) sffit = sfmodel.fit(S) pred = sffit.predict() npt.assert_(xval.coeff_of_determination(pred, S) > 97) # Should be possible to predict using a different gtab: new_gtab = grad.gradient_table(bvals[::2], bvecs[::2]) new_pred = sffit.predict(new_gtab) npt.assert_(xval.coeff_of_determination(new_pred, S[::2]) > 97) # Should be possible to predict for a single direction: new_gtab = grad.gradient_table(bvals[1][None], bvecs[1][None, :]) new_pred = sffit.predict(new_gtab) # Fitting and predicting with a volume of data: fdata, fbval, fbvec = dpd.get_fnames('small_25') gtab = grad.gradient_table(fbval, fbvec) data = load_nifti_data(fdata) sfmodel = sfm.SparseFascicleModel(gtab, response=[0.0015, 0.0003, 0.0003]) sffit = sfmodel.fit(data) pred = sffit.predict() # Should be possible to predict using a different gtab: new_gtab = grad.gradient_table(bvals[::2], bvecs[::2]) new_pred = sffit.predict(new_gtab) npt.assert_equal( new_pred.shape, data.shape[:-1] + bvals[::2].shape, ) # Should be possible to predict for a single direction: new_gtab = grad.gradient_table(bvals[1][None], bvecs[1][None, :]) new_pred = sffit.predict(new_gtab) npt.assert_equal(new_pred.shape, data.shape[:-1]) # Fitting and predicting with masked data: mask = np.zeros(data.shape[:3]) mask[2:5, 2:5, :] = 1 sffit = sfmodel.fit(data, mask=mask) pred = sffit.predict() npt.assert_equal(pred.shape, data.shape) # Should be possible to predict using a different gtab: new_gtab = grad.gradient_table(bvals[::2], bvecs[::2]) new_pred = sffit.predict(new_gtab) npt.assert_equal( new_pred.shape, data.shape[:-1] + bvals[::2].shape, ) npt.assert_equal(new_pred[0, 0, 0], 0) # Should be possible to predict for a single direction: new_gtab = grad.gradient_table(bvals[1][None], bvecs[1][None, :]) new_pred = sffit.predict(new_gtab) npt.assert_equal(new_pred.shape, data.shape[:-1]) npt.assert_equal(new_pred[0, 0, 0], 0)
def test_reconst_ivim(): with TemporaryDirectory() as out_dir: bvals = np.array([ 0., 10., 20., 30., 40., 60., 80., 100., 120., 140., 160., 180., 200., 300., 400., 500., 600., 700., 800., 900., 1000. ]) N = len(bvals) bvecs = generate_bvecs(N) temp_bval_path = pjoin(out_dir, "temp.bval") np.savetxt(temp_bval_path, bvals) temp_bvec_path = pjoin(out_dir, "temp.bvec") np.savetxt(temp_bvec_path, bvecs) gtab = gradient_table(bvals, bvecs) S0, f, D_star, D = 1000.0, 0.132, 0.00885, 0.000921 mevals = np.array(([D_star, D_star, D_star], [D, D, D])) # This gives an isotropic signal. data = multi_tensor(gtab, mevals, snr=None, S0=S0, fractions=[f * 100, 100 * (1 - f)]) # Single voxel data data_single = data[0] temp_affine = np.eye(4) data_multi = np.zeros((2, 2, 1, len(gtab.bvals))) data_multi[0, 0, 0] = data_multi[0, 1, 0] = data_multi[ 1, 0, 0] = data_multi[1, 1, 0] = data_single data_img = nib.Nifti1Image(data_multi.astype(int), temp_affine) data_path = pjoin(out_dir, 'tmp_data.nii.gz') nib.save(data_img, data_path) mask = np.ones_like(data_multi[..., 0]) mask_img = nib.Nifti1Image(mask.astype(np.uint8), data_img.affine) mask_path = pjoin(out_dir, 'tmp_mask.nii.gz') nib.save(mask_img, mask_path) ivim_flow = ReconstIvimFlow() args = [data_path, temp_bval_path, temp_bvec_path, mask_path] ivim_flow.run(*args, out_dir=out_dir) S0_path = ivim_flow.last_generated_outputs['out_S0_predicted'] S0_data = nib.load(S0_path).get_data() assert_equal(S0_data.shape, data_img.shape[:-1]) f_path = ivim_flow.last_generated_outputs['out_perfusion_fraction'] f_data = nib.load(f_path).get_data() assert_equal(f_data.shape, data_img.shape[:-1]) D_star_path = ivim_flow.last_generated_outputs['out_D_star'] D_star_data = nib.load(D_star_path).get_data() assert_equal(D_star_data.shape, data_img.shape[:-1]) D_path = ivim_flow.last_generated_outputs['out_D'] D_data = nib.load(D_path).get_data() assert_equal(D_data.shape, data_img.shape[:-1])
def test_recursive_response_calibration(): """ Test the recursive response calibration method. """ SNR = 100 S0 = 1 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) sphere = get_sphere('symmetric724') gtab = gradient_table(bvals, bvecs) evals = np.array([0.0015, 0.0003, 0.0003]) evecs = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]]).T mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (90, 0)] where_dwi = lazy_index(~gtab.b0s_mask) S_cross, _ = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) S_single = single_tensor(gtab, S0, evals, evecs, snr=SNR) data = np.concatenate((np.tile(S_cross, (8, 1)), np.tile(S_single, (2, 1))), axis=0) odf_gt_cross = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) odf_gt_single = single_tensor_odf(sphere.vertices, evals, evecs) response = recursive_response(gtab, data, mask=None, sh_order=8, peak_thr=0.01, init_fa=0.05, init_trace=0.0021, iter=8, convergence=0.001, parallel=False) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(data) assert_equal(np.all(csd_fit.shm_coeff[:, 0] >= 0), True) fodf = csd_fit.odf(sphere) directions_gt_single, _, _ = peak_directions(odf_gt_single, sphere) directions_gt_cross, _, _ = peak_directions(odf_gt_cross, sphere) directions_single, _, _ = peak_directions(fodf[8, :], sphere) directions_cross, _, _ = peak_directions(fodf[0, :], sphere) ang_sim = angular_similarity(directions_cross, directions_gt_cross) assert_equal(ang_sim > 1.9, True) assert_equal(directions_cross.shape[0], 2) assert_equal(directions_gt_cross.shape[0], 2) ang_sim = angular_similarity(directions_single, directions_gt_single) assert_equal(ang_sim > 0.9, True) assert_equal(directions_single.shape[0], 1) assert_equal(directions_gt_single.shape[0], 1) sphere = Sphere(xyz=gtab.gradients[where_dwi]) sf = response.on_sphere(sphere) S = np.concatenate(([response.S0], sf)) tenmodel = dti.TensorModel(gtab, min_signal=0.001) tenfit = tenmodel.fit(S) FA = fractional_anisotropy(tenfit.evals) FA_gt = fractional_anisotropy(evals) assert_almost_equal(FA, FA_gt, 1)
btable = np.loadtxt(get_data('dsi515btable')) gtab = gradient_table(btable[:, 0], btable[:, 1:]) """ Let's create a multi tensor with 2 fiber directions at 60 degrees. """ evals = np.array([[0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]]) directions = [(-30, 0), (30, 0)] fractions = [50, 50] signal, _ = multi_tensor(gtab, evals, 100, angles=directions, fractions=fractions, snr=None) sphere = get_sphere('symmetric724').subdivide(1) odf_gt = multi_tensor_odf(sphere.vertices, evals, angles=directions, fractions=fractions) """ Perform the reconstructions with standard DSI and DSI with deconvolution. """ dsi_model = DiffusionSpectrumModel(gtab)