def test_unique_bvals_magnitude(): bvals = np.array([1000, 1000, 1000, 1000, 2000, 2000, 2000, 2000, 0]) ubvals_gt = np.array([0, 1000, 2000]) b = unique_bvals_magnitude(bvals) npt.assert_array_almost_equal(ubvals_gt, b) bvals = np.array([995, 995, 995, 995, 2005, 2005, 2005, 2005, 0]) # Case that b-values are rounded: b = unique_bvals_magnitude(bvals) npt.assert_array_almost_equal(ubvals_gt, b) # b-values are not rounded if you specific the magnitude of the values # precision: b = unique_bvals_magnitude(bvals, bmag=0) npt.assert_array_almost_equal(b, np.array([0, 995, 2005])) # Case that b-values are in ms/um2 bvals = np.array( [0.995, 0.995, 0.995, 0.995, 2.005, 2.005, 2.005, 2.005, 0]) b = unique_bvals_magnitude(bvals) ubvals_gt = np.array([0, 1, 2]) npt.assert_array_almost_equal(ubvals_gt, b) # Test case that optional parameter round_bvals is set to true bvals = np.array([995, 1000, 1004, 1000, 2001, 2000, 1988, 2017, 0]) ubvals_gt = np.array([0, 1000, 2000]) rbvals_gt = np.array([1000, 1000, 1000, 1000, 2000, 2000, 2000, 2000, 0]) ub, rb = unique_bvals_magnitude(bvals, rbvals=True) npt.assert_array_almost_equal(ubvals_gt, ub) npt.assert_array_almost_equal(rbvals_gt, rb)
def test_design_matrix(): ub = unique_bvals_magnitude(bvals_3s) D = msdki.design_matrix(ub) Dgt = np.ones((4, 3)) Dgt[:, 0] = -ub Dgt[:, 1] = 1.0 / 6 * ub**2 assert_array_almost_equal(D, Dgt)
def __init__(self, gtab, bmag=None, return_S0_hat=False, *args, **kwargs): """ Mean Signal Diffusion Kurtosis Model [1]_. Parameters ---------- gtab : GradientTable class instance bmag : int The order of magnitude that the bvalues have to differ to be considered an unique b-value. Default: derive this value from the maximal b-value provided: $bmag=log_{10}(max(bvals)) - 1$. return_S0_hat : bool If True, also return S0 values for the fit. args, kwargs : arguments and keyword arguments passed to the fit_method. See msdki.wls_fit_msdki for details References ---------- .. [1] Henriques, R.N., 2018. Advanced Methods for Diffusion MRI Data Analysis and their Application to the Healthy Ageing Brain (Doctoral thesis). Downing College, University of Cambridge. https://doi.org/10.17863/CAM.29356 """ ReconstModel.__init__(self, gtab) self.return_S0_hat = return_S0_hat self.ubvals = unique_bvals_magnitude(gtab.bvals, bmag=bmag) self.design_matrix = design_matrix(self.ubvals) self.bmag = bmag self.args = args self.kwargs = kwargs self.min_signal = self.kwargs.pop('min_signal', MIN_POSITIVE_SIGNAL) if self.min_signal is not None and self.min_signal <= 0: e_s = "The `min_signal` key-word argument needs to be strictly" e_s += " positive." raise ValueError(e_s) # Check if at least three b-values are given enough_b = check_multi_b(self.gtab, 3, non_zero=False, bmag=bmag) if not enough_b: mes = "MSDKI requires at least 3 b-values (which can include b=0)" raise ValueError(mes)
def test_msdki_statistics(): # tests if MD and MK are equal to expected values of a spherical # tensors # Multi-tensors ub = unique_bvals_magnitude(bvals_3s) design_matrix = msdki.design_matrix(ub) msignal, ng = msdki.mean_signal_bvalue(DWI, gtab_3s, bmag=None) params = msdki.wls_fit_msdki(design_matrix, msignal, ng) assert_array_almost_equal(params[..., 1], MKgt_multi) assert_array_almost_equal(params[..., 0], MDgt_multi) mdkiM = msdki.MeanDiffusionKurtosisModel(gtab_3s) mdkiF = mdkiM.fit(DWI) mk = mdkiF.msk md = mdkiF.msd assert_array_almost_equal(MKgt_multi, mk) assert_array_almost_equal(MDgt_multi, md) # Single-tensors mdkiF = mdkiM.fit(signal_sph) mk = mdkiF.msk md = mdkiF.msd assert_array_almost_equal(MKgt, mk) assert_array_almost_equal(MDgt, md) # Test with given mask mask = np.ones(DWI.shape[:-1]) v = (0, 0, 0) mask[1, 1, 1] = 0 mdkiF = mdkiM.fit(DWI, mask=mask) mk = mdkiF.msk md = mdkiF.msd assert_array_almost_equal(MKgt_multi, mk) assert_array_almost_equal(MDgt_multi, md) assert_array_almost_equal(MKgt_multi[v], mdkiF[v].msk) # tuple case assert_array_almost_equal(MDgt_multi[v], mdkiF[v].msd) # tuple case assert_array_almost_equal(MKgt_multi[0], mdkiF[0].msk) # not tuple case assert_array_almost_equal(MDgt_multi[0], mdkiF[0].msd) # not tuple case # Test returned S0 mdkiM = msdki.MeanDiffusionKurtosisModel(gtab_3s, return_S0_hat=True) mdkiF = mdkiM.fit(DWI) assert_array_almost_equal(S0gt_multi, mdkiF.S0_hat) assert_array_almost_equal(MKgt_multi[v], mdkiF[v].msk)
def mean_signal_bvalue(data, gtab, bmag=None): """ Computes the average signal across different diffusion directions for each unique b-value Parameters ---------- data : ndarray ([X, Y, Z, ...], g) ndarray containing the data signals in its last dimension. gtab : a GradientTable class instance The gradient table containing diffusion acquisition parameters. bmag : The order of magnitude that the bvalues have to differ to be considered an unique b-value. Default: derive this value from the maximal b-value provided: $bmag=log_{10}(max(bvals)) - 1$. Returns ------- msignal : ndarray ([X, Y, Z, ..., nub]) Mean signal along all gradient directions for each unique b-value Note that the last dimension contains the signal means and nub is the number of unique b-values. ng : ndarray(nub) Number of gradient directions used to compute the mean signal for all unique b-values Notes ----- This function assumes that directions are evenly sampled on the sphere or on the hemisphere """ bvals = gtab.bvals.copy() # Compute unique and rounded bvals ub, rb = unique_bvals_magnitude(bvals, bmag=bmag, rbvals=True) # Initialize msignal and ng nub = ub.size ng = np.zeros(nub) msignal = np.zeros(data.shape[:-1] + (nub,)) for bi in range(ub.size): msignal[..., bi] = np.mean(data[..., rb == ub[bi]], axis=-1) ng[bi] = np.sum(rb == ub[bi]) return msignal, ng