示例#1
0
def test_ivim_errors():
    """
    Test if errors raised in the module are working correctly.

    Scipy introduced bounded least squares fitting in the version 0.17
    and is not supported by the older versions. Initializing an IvimModel
    with bounds for older Scipy versions should raise an error.
    """
    # Run the test for Scipy versions less than 0.17
    if SCIPY_VERSION < LooseVersion('0.17'):
        assert_raises(ValueError,
                      IvimModel,
                      gtab,
                      bounds=([0., 0., 0., 0.], [np.inf, 1., 1., 1.]),
                      fit_method='LM')
    else:
        ivim_model_LM = IvimModel(gtab,
                                  bounds=([0., 0., 0.,
                                           0.], [np.inf, 1., 1., 1.]),
                                  fit_method='LM')
        ivim_fit = ivim_model_LM.fit(data_multi)
        est_signal = ivim_fit.predict(gtab, S0=1.)
        assert_array_equal(est_signal.shape, data_multi.shape)
        assert_array_almost_equal(ivim_fit.model_params, ivim_params_LM)
        assert_array_almost_equal(est_signal, data_multi)
示例#2
0
def test_noisy_fit():
    """
    Test fitting for noisy signals. This tests whether the threshold condition
    applies correctly and returns the linear fitting parameters.

    For older scipy versions, the returned value of `f` from a linear fit is around 135
    and D and D_star values are equal. Hence doing a test based on Scipy version.
    """
    model_one_stage = IvimModel(gtab)
    fit_one_stage = model_one_stage.fit(noisy_single)
    assert_array_less(fit_one_stage.model_params, [10000., 0.3, .01, 0.001])
示例#3
0
def test_noisy_fit():
    """
    Test fitting for noisy signals. This tests whether the threshold condition
    applies correctly and returns the linear fitting parameters.

    For older scipy versions, the returned value of `f` from a linear fit is around 135
    and D and D_star values are equal. Hence doing a test based on Scipy version.
    """
    model_one_stage = IvimModel(gtab)
    fit_one_stage = model_one_stage.fit(noisy_single)
    assert_array_less(fit_one_stage.model_params, [10000., 0.3, .01, 0.001])
示例#4
0
文件: test_ivim.py 项目: bgsuper/dipy
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, fit_method='LM')

    ivim_model_multiple_b0.fit(data_single)
示例#5
0
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)
示例#6
0
    def get_fitted_ivim(self, data, mask, bval, bvec, b0_threshold=50):
        logging.info('Intra-Voxel Incoherent Motion Estimation...')
        bvals, bvecs = read_bvals_bvecs(bval, bvec)
        if b0_threshold < bvals.min():
            warn("b0_threshold (value: {0}) is too low, increase your "
                 "b0_threshold. It should be higher than the first b0 value "
                 "({1}).".format(b0_threshold, bvals.min()))

        gtab = gradient_table(bvals, bvecs, b0_threshold=b0_threshold)
        ivimmodel = IvimModel(gtab)
        ivimfit = ivimmodel.fit(data, mask)

        return ivimfit, gtab
示例#7
0
文件: reconst.py 项目: arokem/dipy
    def get_fitted_ivim(self, data, mask, bval, bvec, b0_threshold=50):
        logging.info('Intra-Voxel Incoherent Motion Estimation...')
        bvals, bvecs = read_bvals_bvecs(bval, bvec)
        if b0_threshold < bvals.min():
            warn("b0_threshold (value: {0}) is too low, increase your "
                 "b0_threshold. It should higher than the first b0 value "
                 "({1}).".format(b0_threshold, bvals.min()))

        gtab = gradient_table(bvals, bvecs, b0_threshold=b0_threshold)
        ivimmodel = IvimModel(gtab)
        ivimfit = ivimmodel.fit(data, mask)

        return ivimfit, gtab
示例#8
0
def test_ivim_errors():
    """
    Test if errors raised in the module are working correctly.

    Scipy introduced bounded least squares fitting in the version 0.17
    and is not supported by the older versions. Initializing an IvimModel
    with bounds for older Scipy versions should raise an error.
    """
    ivim_model_trr = IvimModel(gtab,
                               bounds=([0., 0., 0., 0.], [np.inf, 1., 1., 1.]),
                               fit_method='trr')
    ivim_fit = ivim_model_trr.fit(data_multi)
    est_signal = ivim_fit.predict(gtab, S0=1.)
    assert_array_equal(est_signal.shape, data_multi.shape)
    assert_array_almost_equal(ivim_fit.model_params, ivim_params_trr)
    assert_array_almost_equal(est_signal, data_multi)
示例#9
0
文件: test_ivim.py 项目: bgsuper/dipy
def test_fit_one_stage():
    """
    Test to check the results for the one_stage linear fit.
    """
    model = IvimModel(gtab, two_stage=False)
    fit = model.fit(data_single)
    linear_fit_params = [9.88834140e+02, 1.19707191e-01, 7.91176970e-03,
                         9.30095210e-04]

    linear_fit_signal = [988.83414044, 971.77122546, 955.46786293,
                         939.87125905, 924.93258982, 896.85182201,
                         870.90346447, 846.81187693, 824.34108781,
                         803.28900104, 783.48245048, 764.77297789,
                         747.03322866, 669.54798887, 605.03328304,
                         549.00852235, 499.21077611, 454.40299244,
                         413.83192296, 376.98072773, 343.45531017]

    assert_array_almost_equal(fit.model_params, linear_fit_params)
    assert_array_almost_equal(fit.predict(gtab), linear_fit_signal)
示例#10
0
def test_fit_one_stage():
    """
    Test to check the results for the one_stage linear fit.
    """
    model = IvimModel(gtab, two_stage=False)
    fit = model.fit(data_single)
    linear_fit_params = [9.88834140e+02, 1.19707191e-01, 7.91176970e-03,
                         9.30095210e-04]

    linear_fit_signal = [988.83414044, 971.77122546, 955.46786293,
                         939.87125905, 924.93258982, 896.85182201,
                         870.90346447, 846.81187693, 824.34108781,
                         803.28900104, 783.48245048, 764.77297789,
                         747.03322866, 669.54798887, 605.03328304,
                         549.00852235, 499.21077611, 454.40299244,
                         413.83192296, 376.98072773, 343.45531017]

    assert_array_almost_equal(fit.model_params, linear_fit_params)
    assert_array_almost_equal(fit.predict(gtab), linear_fit_signal)
示例#11
0
def test_ivim_errors():
    """
    Test if errors raised in the module are working correctly.

    Scipy introduced bounded least squares fitting in the version 0.17
    and is not supported by the older versions. Initializing an IvimModel
    with bounds for older Scipy versions should raise an error.
    """
    # Run the test for Scipy versions less than 0.17
    if SCIPY_VERSION < LooseVersion('0.17'):
        assert_raises(ValueError, IvimModel, gtab,
                      bounds=([0., 0., 0., 0.], [np.inf, 1., 1., 1.]))
    else:
        ivim_model = IvimModel(gtab,
                               bounds=([0., 0., 0., 0.], [np.inf, 1., 1., 1.]))
        ivim_fit = ivim_model.fit(data_multi)
        est_signal = ivim_fit.predict(gtab, S0=1.)
        assert_array_equal(est_signal.shape, data_multi.shape)
        assert_array_almost_equal(ivim_fit.model_params, ivim_params)
        assert_array_almost_equal(est_signal, data_multi)
示例#12
0
文件: test_ivim.py 项目: bgsuper/dipy
def test_noisy_fit():
    """
    Test fitting for noisy signals. This tests whether the threshold condition
    applies correctly and returns the linear fitting parameters.

    For older scipy versions, the returned value of `f` from a linear fit is
    around 135 and D and D_star values are equal. Hence doing a test based on
    Scipy version.
    """
    model_one_stage = IvimModel(gtab, fit_method='LM')
    with warnings.catch_warnings(record=True) as w:
        fit_one_stage = model_one_stage.fit(noisy_single)
        assert_equal(len(w), 3)
        for l_w in w:
            assert_(issubclass(l_w.category, UserWarning))
        assert_("" in str(w[0].message))
        assert_("x0 obtained from linear fitting is not feasibile" in
                str(w[0].message))
        assert_("x0 is unfeasible" in str(w[1].message))
        assert_("Bounds are violated for leastsq fitting" in str(w[2].message))

    assert_array_less(fit_one_stage.model_params, [10000., 0.3, .01, 0.001])
示例#13
0
    def __init__(self, gtab, split_b_D=200.0, n_threads=1):
        """
        Model to reconstruct an IVIM tensor

        Parameters
        ----------
        gtab : GradientTable class instance

        split_b_D : float
            The value of b that separates perfusion from diffusion
        """
        ReconstModel.__init__(self, gtab)
        self.split_b_D = split_b_D
        # Use two separate tensors for initial estimation:
        self.diffusion_idx = np.hstack(
            [np.where(gtab.bvals > self.split_b_D),
             np.where(gtab.b0s_mask)]).squeeze()

        # The first tensor represents diffusion
        self.diffusion_gtab = gradient_table(
            self.gtab.bvals[self.diffusion_idx],
            self.gtab.bvecs[self.diffusion_idx])

        self.diffusion_model = TensorModel(self.diffusion_gtab)

        # The second tensor represents perfusion:
        self.perfusion_idx = np.array(
            np.where(gtab.bvals <= self.split_b_D)).squeeze()
        self.perfusion_gtab = gradient_table(
            self.gtab.bvals[self.perfusion_idx],
            self.gtab.bvecs[self.perfusion_idx])

        self.perfusion_model = TensorModel(self.perfusion_gtab)

        # We'll need a "vanilla" IVIM model:
        self.ivim_model = IvimModel(self.gtab)
        # How many threads in parallel execution:
        self.n_threads = n_threads
示例#14
0
文件: test_ivim.py 项目: bgsuper/dipy
def test_b0_threshold_greater_than0():
    """
    Added test case for default b0_threshold set to 50.
    Checks if error is thrown correctly.
    """
    bvals_b0t = np.array([50., 10., 20., 30., 40., 60., 80., 100.,
                          120., 140., 160., 180., 200., 300., 400.,
                          500., 600., 700., 800., 900., 1000.])
    N = len(bvals_b0t)
    bvecs = generate_bvecs(N)
    gtab = gradient_table(bvals_b0t, bvecs.T)
    with assert_raises(ValueError) as vae:
        _ = IvimModel(gtab, fit_method='LM')
        b0_s = "The IVIM model requires a measurement at b==0. As of "
        assert b0_s in vae.exception
示例#15
0
approximated as a mono exponential decay and by taking the logarithm of the signal
values a linear fit can be obtained. Another linear fit for ``S0`` (bvals <
``split_b_S0`` (default: 200)) follows and ``f`` is estimated using $1 -
S0_{prime}/S0$. Then a non-linear least-squares fitting is performed to fit
``D_star`` and ``f``. If the ``two_stage`` flag is set to ``True`` while
initializing the model, a final non-linear least squares fitting is performed
for all the parameters. All initializations for the model such as ``split_b_D``
are passed while creating the ``IvimModel``. If you are using Scipy 0.17, you
can also set bounds by setting ``bounds=([0., 0., 0.,0.], [np.inf, 1., 1., 1.]))``
while initializing the ``IvimModel``.

For brevity, we focus on a small section of the slice as selected aboove,
to fit the IVIM model. First, we instantiate the IvimModel object.
"""

ivimmodel = IvimModel(gtab, fit_method='LM')
"""
To fit the model, call the `fit` method and pass the data for fitting.
"""

ivimfit = ivimmodel.fit(data_slice)
"""
The fit method creates a IvimFit object which contains the
parameters of the model obtained after fitting. These are accessible
through the `model_params` attribute of the IvimFit object.
The parameters are arranged as a 4D array, corresponding to the spatial
dimensions of the data, and the last dimension (of length 4)
corresponding to the model parameters according to the following
order : $\mathbf{S_{0}, f, D^*, D}$.
"""
示例#16
0
                      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_LM = np.zeros((2, 2, 1, 4))
ivim_params_LM[0, 0, 0] = ivim_params_LM[0, 1, 0] = params_LM
ivim_params_LM[1, 0, 0] = ivim_params_LM[1, 1, 0] = params_LM

ivim_model_LM = IvimModel(gtab, fit_method='LM')
ivim_model_one_stage = IvimModel(gtab, fit_method='LM')
ivim_fit_single = ivim_model_LM.fit(data_single)
ivim_fit_multi = ivim_model_LM.fit(data_multi)

ivim_fit_single_one_stage = ivim_model_one_stage.fit(data_single)
ivim_fit_multi_one_stage = 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.
])

bvecs_no_b0 = generate_bvecs(N)
gtab_no_b0 = gradient_table(bvals_no_b0, bvecs.T, b0_threshold=0)
示例#17
0
文件: test_ivim.py 项目: bgsuper/dipy
def setup_module():
    global gtab, ivim_fit_single, ivim_model_LM, data_single, params_LM, \
        data_multi, ivim_params_LM, 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_LM = 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_LM = np.zeros((2, 2, 1, 4))
    ivim_params_LM[0, 0, 0] = ivim_params_LM[0, 1, 0] = params_LM
    ivim_params_LM[1, 0, 0] = ivim_params_LM[1, 1, 0] = params_LM

    ivim_model_LM = IvimModel(gtab, fit_method='LM')
    ivim_model_one_stage = IvimModel(gtab, fit_method='LM')
    ivim_fit_single = ivim_model_LM.fit(data_single)
    ivim_fit_multi = ivim_model_LM.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
示例#18
0
a linear fit can be obtained. Another linear fit for ``S0`` (bvals <
``split_b_S0`` (default: 200)) follows and ``f`` is estimated using $1 -
S0_{prime}/S0$. Then a non-linear least squares fitting is performed to fit
``D_star`` and ``f``. If the ``two_stage`` flag is set to ``True`` while
initializing the model, a final non-linear least squares fitting is performed
for all the parameters using Scipy's ``leastsq`` or ``least_square`` function
depending on which Scipy version you are using. All initializations for the
model such as ``split_b_D`` are passed while creating the ``IvimModel``. If you
are using Scipy 0.17, you can also set bounds by setting ``bounds=([0., 0., 0.,
0.], [np.inf, 1., 1., 1.]))`` while initializing the ``IvimModel``. It is
recommeded that you upgrade to Scipy 0.17 since the fitting results might at
times return values which do not make sense physically (for example, a negative
$\mathbf{f}$).
"""

ivimmodel = IvimModel(gtab)
"""
To fit the model, call the `fit` method and pass the data for fitting.
"""

ivimfit = ivimmodel.fit(data_slice)
"""
The fit method creates a IvimFit object which contains the
parameters of the model obtained after fitting. These are accessible
through the `model_params` attribute of the IvimFit object.
The parameters are arranged as a 4D array, corresponding to the spatial
dimensions of the data, and the last dimension (of length 4)
corresponding to the model parameters according to the following
order : $\mathbf{S_{0}, f, D^*, D}$.
"""
示例#19
0
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)

ivim_fit_single_one_stage = ivim_model_one_stage.fit(data_single)
ivim_fit_multi_one_stage = 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.])

bvecs_no_b0 = generate_bvecs(N)
gtab_no_b0 = gradient_table(bvals_no_b0, bvecs.T)

bvals_with_multiple_b0 = np.array([0., 0., 0., 0., 40., 60., 80., 100.,
示例#20
0
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)

ivim_fit_single_one_stage = ivim_model_one_stage.fit(data_single)
ivim_fit_multi_one_stage = 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.])

bvecs_no_b0 = generate_bvecs(N)
gtab_no_b0 = gradient_table(bvals_no_b0, bvecs.T)

bvals_with_multiple_b0 = np.array([0., 0., 0., 0., 40., 60., 80., 100.,
示例#21
0
a linear fit can be obtained. Another linear fit for ``S0`` (bvals <
``split_b_S0`` (default: 200)) follows and ``f`` is estimated using $1 -
S0_{prime}/S0$. Then a non-linear least squares fitting is performed to fit
``D_star`` and ``f``. If the ``two_stage`` flag is set to ``True`` while
initializing the model, a final non-linear least squares fitting is performed
for all the parameters using Scipy's ``leastsq`` or ``least_square`` function
depending on which Scipy version you are using. All initializations for the
model such as ``split_b_D`` are passed while creating the ``IvimModel``. If you
are using Scipy 0.17, you can also set bounds by setting ``bounds=([0., 0., 0.,
0.], [np.inf, 1., 1., 1.]))`` while initializing the ``IvimModel``. It is
recommeded that you upgrade to Scipy 0.17 since the fitting results might at
times return values which do not make sense physically (for example, a negative
$\mathbf{f}$).
"""

ivimmodel = IvimModel(gtab)

"""
To fit the model, call the `fit` method and pass the data for fitting.
"""

ivimfit = ivimmodel.fit(data_slice)

"""
The fit method creates a IvimFit object which contains the
parameters of the model obtained after fitting. These are accessible
through the `model_params` attribute of the IvimFit object.
The parameters are arranged as a 4D array, corresponding to the spatial
dimensions of the data, and the last dimension (of length 4)
corresponding to the model parameters according to the following
order : $\mathbf{S_{0}, f, D^*, D}$.
示例#22
0
approximated as a mono exponential decay and by taking the logarithm of the signal
values a linear fit can be obtained. Another linear fit for ``S0`` (bvals <
``split_b_S0`` (default: 200)) follows and ``f`` is estimated using $1 -
S0_{prime}/S0$. Then a non-linear least-squares fitting is performed to fit
``D_star`` and ``f``. If the ``two_stage`` flag is set to ``True`` while
initializing the model, a final non-linear least squares fitting is performed
for all the parameters. All initializations for the model such as ``split_b_D``
are passed while creating the ``IvimModel``. If you are using Scipy 0.17, you
can also set bounds by setting ``bounds=([0., 0., 0.,0.], [np.inf, 1., 1., 1.]))``
while initializing the ``IvimModel``.

For brevity, we focus on a small section of the slice as selected aboove,
to fit the IVIM model. First, we instantiate the IvimModel object.
"""

ivimmodel = IvimModel(gtab, fit_method='LM')

"""
To fit the model, call the `fit` method and pass the data for fitting.
"""

ivimfit = ivimmodel.fit(data_slice)

"""
The fit method creates a IvimFit object which contains the
parameters of the model obtained after fitting. These are accessible
through the `model_params` attribute of the IvimFit object.
The parameters are arranged as a 4D array, corresponding to the spatial
dimensions of the data, and the last dimension (of length 4)
corresponding to the model parameters according to the following
order : $\mathbf{S_{0}, f, D^*, D}$.
示例#23
0
a linear fit can be obtained. Another linear fit for ``S0`` (bvals <
``split_b_S0`` (default: 200)) follows and ``f`` is estimated using $1 -
S0_{prime}/S0$. Then a non-linear least squares fitting is performed to fit
``D_star`` and ``f``. If the ``two_stage`` flag is set to ``True`` while
initializing the model, a final non-linear least squares fitting is performed
for all the parameters using Scipy's ``leastsq`` or ``least_square`` function
depending on which Scipy version you are using. All initializations for the
model such as ``split_b_D`` are passed while creating the ``IvimModel``. If you
are using Scipy 0.17, you can also set bounds by setting ``bounds=([0., 0., 0.,
0.], [np.inf, 1., 1., 1.]))`` while initializing the ``IvimModel``. It is
recommeded that you upgrade to Scipy 0.17 since the fitting results might at
times return values which do not make sense physically (for example, a negative
$\mathbf{f}$).
"""

ivimmodel = IvimModel(gtab, fit_method='LM')
"""
To fit the model, call the `fit` method and pass the data for fitting.
"""
t1 = time.time()
ivimfit = ivimmodel.fit(data_slice)
t2 = time.time()
total = t2 - t1
"""
The fit method creates a IvimFit object which contains the
parameters of the model obtained after fitting. These are accessible
through the `model_params` attribute of the IvimFit object.
The parameters are arranged as a 4D array, corresponding to the spatial
dimensions of the data, and the last dimension (of length 4)
corresponding to the model parameters according to the following
order : $\mathbf{S_{0}, f, D^*, D}$.
示例#24
0
class IvimTensorModel(ReconstModel):
    def __init__(self, gtab, split_b_D=200.0, n_threads=1):
        """
        Model to reconstruct an IVIM tensor

        Parameters
        ----------
        gtab : GradientTable class instance

        split_b_D : float
            The value of b that separates perfusion from diffusion
        """
        ReconstModel.__init__(self, gtab)
        self.split_b_D = split_b_D
        # Use two separate tensors for initial estimation:
        self.diffusion_idx = np.hstack(
            [np.where(gtab.bvals > self.split_b_D),
             np.where(gtab.b0s_mask)]).squeeze()

        # The first tensor represents diffusion
        self.diffusion_gtab = gradient_table(
            self.gtab.bvals[self.diffusion_idx],
            self.gtab.bvecs[self.diffusion_idx])

        self.diffusion_model = TensorModel(self.diffusion_gtab)

        # The second tensor represents perfusion:
        self.perfusion_idx = np.array(
            np.where(gtab.bvals <= self.split_b_D)).squeeze()
        self.perfusion_gtab = gradient_table(
            self.gtab.bvals[self.perfusion_idx],
            self.gtab.bvecs[self.perfusion_idx])

        self.perfusion_model = TensorModel(self.perfusion_gtab)

        # We'll need a "vanilla" IVIM model:
        self.ivim_model = IvimModel(self.gtab)
        # How many threads in parallel execution:
        self.n_threads = n_threads

    def model_eq1(self, b, *params):
        """
        The model with a fixed perfusion fraction
        """
        bvecs = self.gtab.bvecs
        beta = self._ivim_pf
        Q, Q_star = _reconstruct_tensors(params)
        return _ivim_tensor_equation(beta, b, bvecs, Q_star, Q)

    def model_eq2(self, b, *params):
        """
        The full model, including perfusion fraction as free parameter
        """
        beta = params[0]
        bvecs = self.gtab.bvecs
        Q, Q_star = _reconstruct_tensors(params[1:])
        return _ivim_tensor_equation(beta, b, bvecs, Q_star, Q)

    def _inner_loop(self, vox_chunk):
        model_params = np.zeros((vox_chunk.shape[0], 13))
        for ii, vox in enumerate(vox_chunk):
            # Extract initial guess of Euler angles for the diffusion fit:
            dt_evecs = self.diffusion_fit.evecs[vox]
            angles_dti = calc_euler(dt_evecs)
            # Extract initial guess of Euler angles for the perfusion fit:
            perfusion_evecs = self.perfusion_fit.evecs[vox]
            angles_perfusion = calc_euler(perfusion_evecs)
            # Initial guess of perfusion fraction based on "vanilla" IVIM:
            self._ivim_pf = np.clip(
                np.min([
                    self.ivim_fit.perfusion_fraction[vox],
                    1 - self.ivim_fit.perfusion_fraction[vox]
                ]), 0, 1)
            # If diffusivity is lower than this, it's not perfusion!
            min_D_star = 0.003
            # Put together initial guess for 13 parameters of full model:
            initial = [
                self._ivim_pf,
                np.min([self.diffusion_fit.evals[vox, 0], min_D_star]),
                np.min([self.diffusion_fit.evals[vox, 1], min_D_star]),
                np.min([self.diffusion_fit.evals[vox, 2], min_D_star]),
                angles_dti[0], angles_dti[1], angles_dti[2],
                np.max([self.perfusion_fit.evals[vox, 0], min_D_star]),
                np.max([self.perfusion_fit.evals[vox, 1], min_D_star]),
                np.max([self.perfusion_fit.evals[vox, 2], min_D_star]),
                angles_perfusion[0], angles_perfusion[1], angles_perfusion[2]
            ]

            # Bounds on the parameters:
            lb = (0, 0, 0, 0, -np.pi, -np.pi, -np.pi, 0.003, 0.003, 0.003,
                  -np.pi, -np.pi, -np.pi)
            ub = (0.5, 0.003, 0.003, 0.003, np.pi, np.pi, np.pi, np.inf,
                  np.inf, np.inf, np.pi, np.pi, np.pi)

            # Fit the full model to the data with initial guess and bounds
            try:
                popt, pcov = curve_fit(
                    self.model_eq2,
                    self.gtab.bvals,
                    self.mask_data[vox] /
                    np.mean(self.mask_data[vox, self.gtab.b0s_mask]),
                    p0=initial,
                    bounds=(lb, ub),
                    xtol=0.05,
                    ftol=0.05,
                    maxfev=10000)
            # Sometimes it can't fit the data:
            except RuntimeError:
                popt = np.ones(len(initial)) * np.nan
            model_params[ii] = popt

        return model_params

    def fit(self, data, mask=None):
        """
        Fit the IVIM tensor model
        """
        if mask is None:
            mask = np.ones(data.shape[:-1], dtype=bool)
        self.mask_data = data[mask]

        # Fit diffusion tensor to diffusion-weighted data:
        diffusion_data = self.mask_data[:, self.diffusion_idx]
        self.diffusion_fit = self.diffusion_model.fit(diffusion_data)
        # Fit "vanilla" IVIM to all of the data:
        self.ivim_fit = self.ivim_model.fit(self.mask_data)
        # Fit perfusion tensor to perfusion-weighted data:
        perfusion_data = self.mask_data[:, self.perfusion_idx]
        self.perfusion_fit = self.perfusion_model.fit(perfusion_data)
        # Pre-allocate parameters
        #model_params = np.zeros((self.mask_data.shape[0], 13))

        voxel_indices = np.arange(self.mask_data.shape[0])

        if self.n_threads > 1:
            # Loop over voxels:
            vox_chunks = np.array_split(voxel_indices, self.n_threads)

            with ThreadPoolExecutor(max_workers=self.n_threads) as executor:
                loop = asyncio.new_event_loop()

                tasks = [
                    loop.run_in_executor(
                        executor,
                        self._inner_loop,
                        vox_chunk,
                    ) for vox_chunk in vox_chunks
                ]

                try:
                    model_params = np.concatenate(
                        list(
                            tqdm(
                                loop.run_until_complete(
                                    asyncio.gather(*tasks)))))
                finally:
                    loop.close()
        else:
            model_params = self._inner_loop(voxel_indices)

        return IvimTensorFit(self, model_params)