def __init__(self, gtab, sphere=None, response=[0.0015, 0.0005, 0.0005], solver='ElasticNet', l1_ratio=0.5, alpha=0.001): """ Initialize a Sparse Fascicle Model Parameters ---------- gtab : GradientTable class instance sphere : Sphere class instance, optional A sphere on which coefficients will be estimated. Default: symmetric sphere with 362 points (from :mod:`dipy.data`). response : (3,) array-like, optional The eigenvalues of a canonical tensor to be used as the response function of single-fascicle signals. Default:[0.0015, 0.0005, 0.0005] solver : string or SKLearnLinearSolver object, optional This will determine the algorithm used to solve the set of linear equations underlying this model. If it is a string it needs to be one of the following: {'ElasticNet', 'NNLS'}. Otherwise, it can be an object that inherits from `dipy.optimize.SKLearnLinearSolver`. Default: 'ElasticNet'. l1_ratio : float, optional Sets the balance betwee L1 and L2 regularization in ElasticNet [Zou2005]_. Default: 0.5 alpha : float, optional Sets the balance between least-squares error and L1/L2 regularization in ElasticNet [Zou2005]_. Default: 0.001 Notes ----- This is an implementation of the SFM, described in [Rokem2014]_. .. [Rokem2014] Ariel Rokem, Jason D. Yeatman, Franco Pestilli, Kendrick N. Kay, Aviv Mezer, Stefan van der Walt, Brian A. Wandell (2014). Evaluating the accuracy of diffusion MRI models in white matter. http://arxiv.org/abs/1411.0721 .. [Zou2005] Zou H, Hastie T (2005). Regularization and variable selection via the elastic net. J R Stat Soc B:301-320 """ ReconstModel.__init__(self, gtab) if sphere is None: sphere = dpd.get_sphere() self.sphere = sphere self.response = np.asarray(response) if solver == 'ElasticNet': self.solver = lm.ElasticNet(l1_ratio=l1_ratio, alpha=alpha, positive=True, warm_start=True) elif solver == 'NNLS' or solver == 'nnls': self.solver = opt.NonNegativeLeastSquares() elif isinstance(solver, opt.SKLearnLinearSolver): self.solver = solver else: e_s = "The `solver` key-word argument needs to be: " e_s += "'ElasticNet', 'NNLS', or a " e_s += "`dipy.optimize.SKLearnLinearSolver` object" raise ValueError(e_s)
def __init__(self, gtab): """ Initialize an IsotropicModel Parameters ---------- gtab : a GradientTable class instance """ ReconstModel.__init__(self, gtab)
def __init__(self, gtab): """ Parameters ---------- gtab : a GradientTable class instance """ # Initialize the super-class: ReconstModel.__init__(self, gtab)
def __init__(self, gtab): """ Initialize an IsotropicModel. Parameters ---------- gtab : a GradientTable class instance """ ReconstModel.__init__(self, gtab)
def __init__(self, gtab, fit_method="NLS", *args, **kwargs): """ Free Water Diffusion Tensor Model [1]_. Parameters ---------- gtab : GradientTable class instance fit_method : str or callable str can be one of the following: 'WLS' for weighted linear least square fit according to [1]_ :func:`fwdti.wls_iter` 'NLS' for non-linear least square fit according to [1]_ :func:`fwdti.nls_iter` callable has to have the signature: fit_method(design_matrix, data, *args, **kwargs) args, kwargs : arguments and key-word arguments passed to the fit_method. See fwdti.wls_iter, fwdti.nls_iter for details References ---------- .. [1] Hoy, A.R., Koay, C.G., Kecskemeti, S.R., Alexander, A.L., 2014. Optimization of a free water elimination two-compartmental model for diffusion tensor imaging. NeuroImage 103, 323-333. doi: 10.1016/j.neuroimage.2014.09.053 """ ReconstModel.__init__(self, gtab) if not callable(fit_method): try: fit_method = common_fit_methods[fit_method] except KeyError: e_s = '"' + str(fit_method) + '" is not a known fit ' e_s += 'method, the fit method should either be a ' e_s += 'function or one of the common fit methods' raise ValueError(e_s) self.fit_method = fit_method self.design_matrix = design_matrix(self.gtab) self.args = args self.kwargs = kwargs # Check if at least three b-values are given bmag = int(np.log10(self.gtab.bvals.max())) b = self.gtab.bvals.copy() / (10 ** (bmag-1)) # normalize b units b = b.round() uniqueb = np.unique(b) if len(uniqueb) < 3: mes = "fwdti fit requires data for at least 2 non zero b-values" raise ValueError(mes)
def __init__(self, gtab, fit_method="NLS", *args, **kwargs): """ Free Water Diffusion Tensor Model [1]_. Parameters ---------- gtab : GradientTable class instance fit_method : str or callable str can be one of the following: 'WLS' for weighted linear least square fit according to [1]_ :func:`fwdti.wls_iter` 'NLS' for non-linear least square fit according to [1]_ :func:`fwdti.nls_iter` callable has to have the signature: fit_method(design_matrix, data, *args, **kwargs) args, kwargs : arguments and key-word arguments passed to the fit_method. See fwdti.wls_iter, fwdti.nls_iter for details References ---------- .. [1] Hoy, A.R., Koay, C.G., Kecskemeti, S.R., Alexander, A.L., 2014. Optimization of a free water elimination two-compartmental model for diffusion tensor imaging. NeuroImage 103, 323-333. doi: 10.1016/j.neuroimage.2014.09.053 """ ReconstModel.__init__(self, gtab) if not callable(fit_method): try: fit_method = common_fit_methods[fit_method] except KeyError: e_s = '"' + str(fit_method) + '" is not a known fit ' e_s += 'method, the fit method should either be a ' e_s += 'function or one of the common fit methods' raise ValueError(e_s) self.fit_method = fit_method self.design_matrix = design_matrix(self.gtab) self.args = args self.kwargs = kwargs # Check if at least three b-values are given bmag = int(np.log10(self.gtab.bvals.max())) b = self.gtab.bvals.copy() / (10**(bmag - 1)) # normalize b units b = b.round() uniqueb = np.unique(b) if len(uniqueb) < 3: mes = "fwdti fit requires data for at least 2 non zero b-values" raise ValueError(mes)
def __init__(self, gtab, fit_method="NLS", *args, **kwargs): """ Free Water Diffusion Tensor Model [1]_. Parameters ---------- gtab : GradientTable class instance fit_method : str or callable str can be one of the following: 'WLS' for weighted linear least square fit according to [1]_ :func:`fwdti.wls_iter` 'NLS' for non-linear least square fit according to [1]_ :func:`fwdti.nls_iter` callable has to have the signature: fit_method(design_matrix, data, *args, **kwargs) args, kwargs : arguments and key-word arguments passed to the fit_method. See fwdti.wls_iter, fwdti.nls_iter for details References ---------- .. [1] Henriques, R.N., Rokem, A., Garyfallidis, E., St-Jean, S., Peterson E.T., Correia, M.M., 2017. [Re] Optimization of a free water elimination two-compartment model for diffusion tensor imaging. ReScience volume 3, issue 1, article number 2 """ ReconstModel.__init__(self, gtab) if not callable(fit_method): try: fit_method = common_fit_methods[fit_method] except KeyError: e_s = '"' + str(fit_method) + '" is not a known fit ' e_s += 'method, the fit method should either be a ' e_s += 'function or one of the common fit methods' raise ValueError(e_s) self.fit_method = fit_method self.design_matrix = design_matrix(self.gtab) self.args = args self.kwargs = kwargs # Check if at least three b-values are given enough_b = check_multi_b(self.gtab, 3, non_zero=False) if not enough_b: mes = "fwDTI requires at least 3 b-values (which can include b=0)" raise ValueError(mes)
def __init__(self, gtab, fit_method="NLS", *args, **kwargs): """ Free Water Diffusion Tensor Model [1]_. Parameters ---------- gtab : GradientTable class instance fit_method : str or callable str can be one of the following: 'WLS' for weighted linear least square fit according to [1]_ :func:`fwdti.wls_iter` 'NLS' for non-linear least square fit according to [1]_ :func:`fwdti.nls_iter` callable has to have the signature: fit_method(design_matrix, data, *args, **kwargs) args, kwargs : arguments and key-word arguments passed to the fit_method. See fwdti.wls_iter, fwdti.nls_iter for details References ---------- .. [1] Hoy, A.R., Koay, C.G., Kecskemeti, S.R., Alexander, A.L., 2014. Optimization of a free water elimination two-compartmental model for diffusion tensor imaging. NeuroImage 103, 323-333. doi: 10.1016/j.neuroimage.2014.09.053 """ ReconstModel.__init__(self, gtab) if not callable(fit_method): try: fit_method = common_fit_methods[fit_method] except KeyError: e_s = '"' + str(fit_method) + '" is not a known fit ' e_s += 'method, the fit method should either be a ' e_s += 'function or one of the common fit methods' raise ValueError(e_s) self.fit_method = fit_method self.design_matrix = design_matrix(self.gtab) self.args = args self.kwargs = kwargs # Check if at least three b-values are given enough_b = check_multi_b(self.gtab, 3, non_zero=False) if not enough_b: mes = "fwDTI requires at least 3 b-values (which can include b=0)" raise ValueError(mes)
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 __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(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 __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 __init__(self, gtab, fit_method='WLS'): """Covariance tensor model of q-space trajectory imaging [1]_. Parameters ---------- gtab : dipy.core.gradients.GradientTable Gradient table with b-tensors. fit_method : str, optional Must be one of the followng: 'OLS' for ordinary least squares :func:`qti._ols_fit` 'WLS' for weighted least squares :func:`qti._wls_fit` References ---------- .. [1] Westin, Carl-Fredrik, et al. "Q-space trajectory imaging for multidimensional diffusion MRI of the human brain." Neuroimage 135 (2016): 345-362. https://doi.org/10.1016/j.neuroimage.2016.02.039. """ ReconstModel.__init__(self, gtab) if self.gtab.btens is None: raise ValueError( 'QTI requires b-tensors to be defined in the gradient table.') self.X = design_matrix(self.gtab.btens) rank = np.linalg.matrix_rank(self.X.T @ self.X) if rank < 28: warn('The combination of the b-tensor shapes, sizes, and ' + 'orientations does not enable all elements of the covariance ' + 'tensor to be estimated (rank(X.T @ X) = %s < 28).' % rank) try: self.fit_method = common_fit_methods[fit_method] except KeyError: raise ValueError('Invalid value (%s) for \'fit_method\'.' % fit_method + ' Options: \'OLS\', \'WLS\'.')
def __init__(self, gtab, sphere=None, response=[0.0015, 0.0005, 0.0005], solver='ElasticNet', l1_ratio=0.5, alpha=0.001, isotropic=None): """ Initialize a Sparse Fascicle Model Parameters ---------- gtab : GradientTable class instance sphere : Sphere class instance, optional A sphere on which coefficients will be estimated. Default: symmetric sphere with 362 points (from :mod:`dipy.data`). response : (3,) array-like, optional The eigenvalues of a canonical tensor to be used as the response function of single-fascicle signals. Default:[0.0015, 0.0005, 0.0005] solver : string, dipy.core.optimize.SKLearnLinearSolver object, or sklearn.linear_model.base.LinearModel object, optional. This will determine the algorithm used to solve the set of linear equations underlying this model. If it is a string it needs to be one of the following: {'ElasticNet', 'NNLS'}. Otherwise, it can be an object that inherits from `dipy.optimize.SKLearnLinearSolver`. Default: 'ElasticNet'. l1_ratio : float, optional Sets the balance betwee L1 and L2 regularization in ElasticNet [Zou2005]_. Default: 0.5 alpha : float, optional Sets the balance between least-squares error and L1/L2 regularization in ElasticNet [Zou2005]_. Default: 0.001 isotropic : IsotropicModel class instance This is a class that implements the function that calculates the value of the isotropic signal. This is a value of the signal that is independent of direction, and therefore removed from both sides of the SFM equation. The default is an instance of IsotropicModel, but other functions can be inherited from IsotropicModel to implement other fits to the aspects of the data that depend on b-value, but not on direction. Notes ----- This is an implementation of the SFM, described in [Rokem2015]_. .. [Rokem2014] Ariel Rokem, Jason D. Yeatman, Franco Pestilli, Kendrick N. Kay, Aviv Mezer, Stefan van der Walt, Brian A. Wandell (2014). Evaluating the accuracy of diffusion MRI models in white matter. PLoS ONE 10(4): e0123272. doi:10.1371/journal.pone.0123272 .. [Zou2005] Zou H, Hastie T (2005). Regularization and variable selection via the elastic net. J R Stat Soc B:301-320 """ ReconstModel.__init__(self, gtab) if sphere is None: sphere = dpd.get_sphere() self.sphere = sphere self.response = np.asarray(response) if isotropic is None: isotropic = IsotropicModel self.isotropic = isotropic if solver == 'ElasticNet': self.solver = lm.ElasticNet(l1_ratio=l1_ratio, alpha=alpha, positive=True, warm_start=True) elif solver == 'NNLS' or solver == 'nnls': self.solver = opt.NonNegativeLeastSquares() elif (isinstance(solver, opt.SKLearnLinearSolver) or has_sklearn and isinstance(solver, lm.base.LinearModel)): self.solver = solver else: e_s = "The `solver` key-word argument needs to be: " e_s += "'ElasticNet', 'NNLS', or a " e_s += "`dipy.optimize.SKLearnLinearSolver` object" raise ValueError(e_s)
def __init__(self, gtab): ReconstModel.__init__(self, gtab)
def __init__(self, gtab, split_b_D=400.0, split_b_S0=200., bounds=None, two_stage=True, tol=1e-15, x_scale=[1000., 0.1, 0.001, 0.0001], gtol=1e-15, ftol=1e-15, eps=1e-15, maxiter=1000): r""" Initialize an IVIM model. The IVIM model assumes that biological tissue includes a volume fraction 'f' of water flowing with a pseudo-diffusion coefficient D* and a fraction (1-f) of static (diffusion only), intra and extracellular water, with a diffusion coefficient D. In this model the echo attenuation of a signal in a single voxel can be written as .. math:: S(b) = S_0[f*e^{(-b*D\*)} + (1-f)e^{(-b*D)}] Where: .. math:: S_0, f, D\* and D are the IVIM parameters. Parameters ---------- gtab : GradientTable class instance Gradient directions and bvalues split_b_D : float, optional The b-value to split the data on for two-stage fit. This will be used while estimating the value of D. The assumption is that at higher b values the effects of perfusion is less and hence the signal can be approximated as a mono-exponential decay. default : 400. split_b_S0 : float, optional The b-value to split the data on for two-stage fit for estimation of S0 and initial guess for D_star. The assumption here is that at low bvalues the effects of perfusion are more. default : 200. bounds : tuple of arrays with 4 elements, optional Bounds to constrain the fitted model parameters. This is only supported for Scipy version > 0.17. When using a older Scipy version, this function will raise an error if bounds are different from None. This parameter is also used to fill nan values for out of bounds parameters in the `IvimFit` class using the method fill_na. default : ([0., 0., 0., 0.], [np.inf, .3, 1., 1.]) two_stage : bool Argument to specify whether to perform a non-linear fitting of all parameters after the linear fitting by splitting the data based on bvalues. This gives more accurate parameters but takes more time. The linear fit can be used to get a quick estimation of the parameters. default : False tol : float, optional Tolerance for convergence of minimization. default : 1e-15 x_scale : array, optional Scaling for the parameters. This is passed to `least_squares` which is only available for Scipy version > 0.17. default: [1000, 0.01, 0.001, 0.0001] gtol : float, optional Tolerance for termination by the norm of the gradient. default : 1e-15 ftol : float, optional Tolerance for termination by the change of the cost function. default : 1e-15 eps : float, optional Step size used for numerical approximation of the jacobian. default : 1e-15 maxiter : int, optional Maximum number of iterations to perform. default : 1000 References ---------- .. [1] Le Bihan, Denis, et al. "Separation of diffusion and perfusion in intravoxel incoherent motion MR imaging." Radiology 168.2 (1988): 497-505. .. [2] Federau, Christian, et al. "Quantitative measurement of brain perfusion with intravoxel incoherent motion MR imaging." Radiology 265.3 (2012): 874-881. """ if not np.any(gtab.b0s_mask): e_s = "No measured signal at bvalue == 0." e_s += "The IVIM model requires signal measured at 0 bvalue" raise ValueError(e_s) if gtab.b0_threshold > 0: b0_s = "The IVIM model requires a measurement at b==0. As of " b0_s += "version 0.15, the default b0_threshold for the " b0_s += "GradientTable object is set to 50, so if you used the " b0_s += "default settings to initialize the gtab input to the " b0_s += "IVIM model, you may have provided a gtab with " b0_s += "b0_threshold larger than 0. Please initialize the gtab " b0_s += "input with b0_threshold=0" raise ValueError(b0_s) ReconstModel.__init__(self, gtab) self.split_b_D = split_b_D self.split_b_S0 = split_b_S0 self.bounds = bounds self.two_stage = two_stage self.tol = tol self.options = {'gtol': gtol, 'ftol': ftol, 'eps': eps, 'maxiter': maxiter} self.x_scale = x_scale if SCIPY_LESS_0_17 and self.bounds is not None: e_s = "Scipy versions less than 0.17 do not support " e_s += "bounds. Please update to Scipy 0.17 to use bounds" raise ValueError(e_s) elif self.bounds is None: self.bounds = ((0., 0., 0., 0.), (np.inf, .3, 1., 1.)) else: self.bounds = bounds
def __init__(self, gtab, sphere=None, response=[0.0015, 0.0005, 0.0005], solver='ElasticNet', l1_ratio=0.5, alpha=0.001, isotropic=None): """ Initialize a Sparse Fascicle Model Parameters ---------- gtab : GradientTable class instance sphere : Sphere class instance, optional A sphere on which coefficients will be estimated. Default: symmetric sphere with 362 points (from :mod:`dipy.data`). response : (3,) array-like, optional The eigenvalues of a canonical tensor to be used as the response function of single-fascicle signals. Default:[0.0015, 0.0005, 0.0005] solver : string, or initialized linear model object. This will determine the algorithm used to solve the set of linear equations underlying this model. If it is a string it needs to be one of the following: {'ElasticNet', 'NNLS'}. Otherwise, it can be an object that inherits from `dipy.optimize.SKLearnLinearSolver` or an object with a similar interface from Scikit Learn: `sklearn.linear_model.ElasticNet`, `sklearn.linear_model.Lasso` or `sklearn.linear_model.Ridge` and other objects that inherit from `sklearn.base.RegressorMixin`. Default: 'ElasticNet'. l1_ratio : float, optional Sets the balance betwee L1 and L2 regularization in ElasticNet [Zou2005]_. Default: 0.5 alpha : float, optional Sets the balance between least-squares error and L1/L2 regularization in ElasticNet [Zou2005]_. Default: 0.001 isotropic : IsotropicModel class instance This is a class that implements the function that calculates the value of the isotropic signal. This is a value of the signal that is independent of direction, and therefore removed from both sides of the SFM equation. The default is an instance of IsotropicModel, but other functions can be inherited from IsotropicModel to implement other fits to the aspects of the data that depend on b-value, but not on direction. Notes ----- This is an implementation of the SFM, described in [Rokem2015]_. .. [Rokem2014] Ariel Rokem, Jason D. Yeatman, Franco Pestilli, Kendrick N. Kay, Aviv Mezer, Stefan van der Walt, Brian A. Wandell (2014). Evaluating the accuracy of diffusion MRI models in white matter. PLoS ONE 10(4): e0123272. doi:10.1371/journal.pone.0123272 .. [Zou2005] Zou H, Hastie T (2005). Regularization and variable selection via the elastic net. J R Stat Soc B:301-320 """ ReconstModel.__init__(self, gtab) if sphere is None: sphere = dpd.get_sphere() self.sphere = sphere self.response = np.asarray(response) if isotropic is None: isotropic = IsotropicModel self.isotropic = isotropic if solver == 'ElasticNet': self.solver = lm.ElasticNet(l1_ratio=l1_ratio, alpha=alpha, positive=True, warm_start=True) elif solver == 'NNLS' or solver == 'nnls': self.solver = opt.NonNegativeLeastSquares() elif (isinstance(solver, opt.SKLearnLinearSolver) or has_sklearn and isinstance(solver, sklearn.base.RegressorMixin)): self.solver = solver else: e_s = "The `solver` key-word argument needs to be: " e_s += "'ElasticNet', 'NNLS', or a " e_s += "`dipy.optimize.SKLearnLinearSolver` object" raise ValueError(e_s)
def __init__(self, gtab, split_b_D=400.0, split_b_S0=200., bounds=None, two_stage=True, tol=1e-15, x_scale=[1000., 0.1, 0.001, 0.0001], options={'gtol': 1e-15, 'ftol': 1e-15, 'eps': 1e-15, 'maxiter': 1000}): """ Initialize an IVIM model. The IVIM model assumes that biological tissue includes a volume fraction 'f' of water flowing with a pseudo-perfusion coefficient D* and a fraction (1-f) of static (diffusion only), intra and extracellular water, with a diffusion coefficient D. In this model the echo attenuation of a signal in a single voxel can be written as .. math:: S(b) = S_0[f*e^{(-b*D\*)} + (1-f)e^{(-b*D)}] Where: .. math:: S_0, f, D\* and D are the IVIM parameters. Parameters ---------- gtab : GradientTable class instance Gradient directions and bvalues split_b_D : float, optional The b-value to split the data on for two-stage fit. This will be used while estimating the value of D. The assumption is that at higher b values the effects of perfusion is less and hence the signal can be approximated as a mono-exponential decay. default : 400. split_b_S0 : float, optional The b-value to split the data on for two-stage fit for estimation of S0 and initial guess for D_star. The assumption here is that at low bvalues the effects of perfusion are more. default : 200. bounds : tuple of arrays with 4 elements, optional Bounds to constrain the fitted model parameters. This is only supported for Scipy version > 0.17. When using a older Scipy version, this function will raise an error if bounds are different from None. This parameter is also used to fill nan values for out of bounds parameters in the `IvimFit` class using the method fill_na. default : ([0., 0., 0., 0.], [np.inf, .3, 1., 1.]) two_stage : bool Argument to specify whether to perform a non-linear fitting of all parameters after the linear fitting by splitting the data based on bvalues. This gives more accurate parameters but takes more time. The linear fit can be used to get a quick estimation of the parameters. default : False tol : float, optional Tolerance for convergence of minimization. default : 1e-15 x_scale : array, optional Scaling for the parameters. This is passed to `least_squares` which is only available for Scipy version > 0.17. default: [1000, 0.01, 0.001, 0.0001] options : dict, optional Dictionary containing gtol, ftol, eps and maxiter. This is passed to leastsq. default : options={'gtol': 1e-15, 'ftol': 1e-15, 'eps': 1e-15, 'maxiter': 1000} References ---------- .. [1] Le Bihan, Denis, et al. "Separation of diffusion and perfusion in intravoxel incoherent motion MR imaging." Radiology 168.2 (1988): 497-505. .. [2] Federau, Christian, et al. "Quantitative measurement of brain perfusion with intravoxel incoherent motion MR imaging." Radiology 265.3 (2012): 874-881. """ if not np.any(gtab.b0s_mask): e_s = "No measured signal at bvalue == 0." e_s += "The IVIM model requires signal measured at 0 bvalue" raise ValueError(e_s) ReconstModel.__init__(self, gtab) self.split_b_D = split_b_D self.split_b_S0 = split_b_S0 self.bounds = bounds self.two_stage = two_stage self.tol = tol self.options = options self.x_scale = x_scale if SCIPY_LESS_0_17 and self.bounds is not None: e_s = "Scipy versions less than 0.17 do not support " e_s += "bounds. Please update to Scipy 0.17 to use bounds" raise ValueError(e_s) elif self.bounds is None: self.bounds = ((0., 0., 0., 0.), (np.inf, .3, 1., 1.)) else: self.bounds = bounds
def __init__(self, gtab, split_b_D=400.0, split_b_S0=200., bounds=None, two_stage=True, tol=1e-15, x_scale=[1000., 0.1, 0.001, 0.0001], gtol=1e-15, ftol=1e-15, eps=1e-15, maxiter=1000): r""" Initialize an IVIM model. The IVIM model assumes that biological tissue includes a volume fraction 'f' of water flowing with a pseudo-diffusion coefficient D* and a fraction (1-f) of static (diffusion only), intra and extracellular water, with a diffusion coefficient D. In this model the echo attenuation of a signal in a single voxel can be written as .. math:: S(b) = S_0[f*e^{(-b*D\*)} + (1-f)e^{(-b*D)}] Where: .. math:: S_0, f, D\* and D are the IVIM parameters. Parameters ---------- gtab : GradientTable class instance Gradient directions and bvalues split_b_D : float, optional The b-value to split the data on for two-stage fit. This will be used while estimating the value of D. The assumption is that at higher b values the effects of perfusion is less and hence the signal can be approximated as a mono-exponential decay. default : 400. split_b_S0 : float, optional The b-value to split the data on for two-stage fit for estimation of S0 and initial guess for D_star. The assumption here is that at low bvalues the effects of perfusion are more. default : 200. bounds : tuple of arrays with 4 elements, optional Bounds to constrain the fitted model parameters. This is only supported for Scipy version > 0.17. When using a older Scipy version, this function will raise an error if bounds are different from None. This parameter is also used to fill nan values for out of bounds parameters in the `IvimFit` class using the method fill_na. default : ([0., 0., 0., 0.], [np.inf, .3, 1., 1.]) two_stage : bool Argument to specify whether to perform a non-linear fitting of all parameters after the linear fitting by splitting the data based on bvalues. This gives more accurate parameters but takes more time. The linear fit can be used to get a quick estimation of the parameters. default : False tol : float, optional Tolerance for convergence of minimization. default : 1e-15 x_scale : array, optional Scaling for the parameters. This is passed to `least_squares` which is only available for Scipy version > 0.17. default: [1000, 0.01, 0.001, 0.0001] gtol : float, optional Tolerance for termination by the norm of the gradient. default : 1e-15 ftol : float, optional Tolerance for termination by the change of the cost function. default : 1e-15 eps : float, optional Step size used for numerical approximation of the jacobian. default : 1e-15 maxiter : int, optional Maximum number of iterations to perform. default : 1000 References ---------- .. [1] Le Bihan, Denis, et al. "Separation of diffusion and perfusion in intravoxel incoherent motion MR imaging." Radiology 168.2 (1988): 497-505. .. [2] Federau, Christian, et al. "Quantitative measurement of brain perfusion with intravoxel incoherent motion MR imaging." Radiology 265.3 (2012): 874-881. """ if not np.any(gtab.b0s_mask): e_s = "No measured signal at bvalue == 0." e_s += "The IVIM model requires signal measured at 0 bvalue" raise ValueError(e_s) if gtab.b0_threshold > 0: b0_s = "The IVIM model requires a measurement at b==0. As of " b0_s += "version 0.15, the default b0_threshold for the " b0_s += "GradientTable object is set to 50, so if you used the " b0_s += "default settings to initialize the gtab input to the " b0_s += "IVIM model, you may have provided a gtab with " b0_s += "b0_threshold larger than 0. Please initialize the gtab " b0_s += "input with b0_threshold=0" raise ValueError(b0_s) ReconstModel.__init__(self, gtab) self.split_b_D = split_b_D self.split_b_S0 = split_b_S0 self.bounds = bounds self.two_stage = two_stage self.tol = tol self.options = { 'gtol': gtol, 'ftol': ftol, 'eps': eps, 'maxiter': maxiter } self.x_scale = x_scale self.bounds = bounds or BOUNDS