def __init__(self, gtab, sh_order, smooth=0.006, min_signal=1., assume_normed=False): """Creates a model that can be used to fit or sample diffusion data Arguments --------- gtab : GradientTable Diffusion gradients used to acquire data sh_order : even int >= 0 the spherical harmonic order of the model smooth : float between 0 and 1, optional The regularization parameter of the model min_signal : float, > 0, optional During fitting, all signal values less than `min_signal` are clipped to `min_signal`. This is done primarily to avoid values less than or equal to zero when taking logs. assume_normed : bool, optional If True, clipping and normalization of the data with respect to the mean B0 signal are skipped during mode fitting. This is an advanced feature and should be used with care. See Also -------- normalize_data """ OdfModel.__init__(self, gtab) self._where_b0s = lazy_index(gtab.b0s_mask) self._where_dwi = lazy_index(~gtab.b0s_mask) self.assume_normed = assume_normed self.min_signal = min_signal x, y, z = gtab.gradients[self._where_dwi].T r, theta, phi = cart2sphere(x, y, z) B, m, n = real_sym_sh_basis(sh_order, theta[:, None], phi[:, None]) L = -n * (n + 1) legendre0 = lpn(sh_order, 0)[0] F = legendre0[n] self.sh_order = sh_order self.B = B self.m = m self.n = n self._set_fit_matrix(B, L, F, smooth)
def __init__(self, gtab, sh_order=8, lambda_lb=1e-3, dec_alg='CSD', sphere=None, lambda_csd=1.0): r""" Analytical and continuous modeling of the diffusion signal with respect to the FORECAST basis [1,2,3]_. This implementation is a modification of the original FORECAST model presented in [1]_ adapted for multi-shell data as in [2,3]_ . The main idea is to model the diffusion signal as the combination of a single fiber response function $F(\mathbf{b})$ times the fODF $\rho(\mathbf{v})$ ..math:: :nowrap: \begin{equation} E(\mathbf{b}) = \int_{\mathbf{v} \in \mathcal{S}^2} \rho(\mathbf{v}) F({\mathbf{b}} | \mathbf{v}) d \mathbf{v} \end{equation} where $\mathbf{b}$ is the b-vector (b-value times gradient direction) and $\mathbf{v}$ is an unit vector representing a fiber direction. In FORECAST $\rho$ is modeled using real symmetric Spherical Harmonics (SH) and $F(\mathbf(b))$ is an axially symmetric tensor. Parameters ---------- gtab : GradientTable, gradient directions and bvalues container class. sh_order : unsigned int, an even integer that represent the SH order of the basis (max 12) lambda_lb: float, Laplace-Beltrami regularization weight. dec_alg : str, Spherical deconvolution algorithm. The possible values are Weighted Least Squares ('WLS'), Positivity Constraints using CVXPY ('POS') and the Constraint Spherical Deconvolution algorithm ('CSD'). Default is 'CSD'. sphere : array, shape (N,3), sphere points where to enforce positivity when 'POS' or 'CSD' dec_alg are selected. lambda_csd : float, CSD regularization weight. References ---------- .. [1] Anderson A. W., "Measurement of Fiber Orientation Distributions Using High Angular Resolution Diffusion Imaging", Magnetic Resonance in Medicine, 2005. .. [2] Kaden E. et al., "Quantitative Mapping of the Per-Axon Diffusion Coefficients in Brain White Matter", Magnetic Resonance in Medicine, 2016. .. [3] Zucchelli M. et al., "A generalized SMT-based framework for Diffusion MRI microstructural model estimation", MICCAI Workshop on Computational DIFFUSION MRI (CDMRI), 2017. Examples -------- In this example, where the data, gradient table and sphere tessellation used for reconstruction are provided, we model the diffusion signal with respect to the FORECAST and compute the fODF, parallel and perpendicular diffusivity. >>> import warnings >>> from dipy.data import default_sphere, get_3shell_gtab >>> gtab = get_3shell_gtab() >>> from dipy.sims.voxel import multi_tensor >>> mevals = np.array(([0.0017, 0.0003, 0.0003], ... [0.0017, 0.0003, 0.0003])) >>> angl = [(0, 0), (60, 0)] >>> data, sticks = multi_tensor(gtab, ... mevals, ... S0=100.0, ... angles=angl, ... fractions=[50, 50], ... snr=None) >>> from dipy.reconst.forecast import ForecastModel >>> from dipy.reconst.shm import descoteaux07_legacy_msg >>> with warnings.catch_warnings(): ... warnings.filterwarnings( ... "ignore", message=descoteaux07_legacy_msg, ... category=PendingDeprecationWarning) ... fm = ForecastModel(gtab, sh_order=6) >>> f_fit = fm.fit(data) >>> d_par = f_fit.dpar >>> d_perp = f_fit.dperp >>> with warnings.catch_warnings(): ... warnings.filterwarnings( ... "ignore", message=descoteaux07_legacy_msg, ... category=PendingDeprecationWarning) ... fodf = f_fit.odf(default_sphere) """ OdfModel.__init__(self, gtab) # round the bvals in order to avoid numerical errors self.bvals = np.round(gtab.bvals / 100) * 100 self.bvecs = gtab.bvecs if sh_order >= 0 and not (bool(sh_order % 2)) and sh_order <= 12: self.sh_order = sh_order else: msg = "sh_order must be a non-zero even positive number " msg += "between 2 and 12" raise ValueError(msg) if sphere is None: sphere = default_sphere self.vertices = sphere.vertices[0:int(sphere.vertices.shape[0] / 2), :] else: self.vertices = sphere self.b0s_mask = self.bvals == 0 self.one_0_bvals = np.r_[0, self.bvals[~self.b0s_mask]] self.one_0_bvecs = np.r_[np.array([0, 0, 0]).reshape(1, 3), self.bvecs[~self.b0s_mask, :]] self.rho = rho_matrix(self.sh_order, self.one_0_bvecs) # signal regularization matrix self.srm = rho_matrix(4, self.one_0_bvecs) self.lb_matrix_signal = lb_forecast(4) self.b_unique = np.sort(np.unique(self.bvals[self.bvals > 0])) self.wls = True self.csd = False self.pos = False if dec_alg.upper() == 'POS': if have_cvxpy: self.wls = False self.pos = True else: msg = 'cvxpy is needed to inforce positivity constraints.' raise ValueError(msg) if dec_alg.upper() == 'CSD': self.csd = True self.lb_matrix = lb_forecast(self.sh_order) self.lambda_lb = lambda_lb self.lambda_csd = lambda_csd self.fod = rho_matrix(sh_order, self.vertices)
def __init__(self, gtab, sh_order=8, lambda_lb=1e-3, dec_alg='CSD', sphere=None, lambda_csd=1.0): r""" Analytical and continuous modeling of the diffusion signal with respect to the FORECAST basis [1,2,3]_. This implementation is a modification of the original FORECAST model presented in [1]_ adapted for multi-shell data as in [2,3]_ . The main idea is to model the diffusion signal as the combination of a single fiber response function $F(\mathbf{b})$ times the fODF $\rho(\mathbf{v})$ ..math:: :nowrap: \begin{equation} E(\mathbf{b}) = \int_{\mathbf{v} \in \mathcal{S}^2} \rho(\mathbf{v}) F({\mathbf{b}} | \mathbf{v}) d \mathbf{v} \end{equation} where $\mathbf{b}$ is the b-vector (b-value times gradient direction) and $\mathbf{v}$ is an unit vector representing a fiber direction. In FORECAST $\rho$ is modeled using real symmetric Spherical Harmonics (SH) and $F(\mathbf(b))$ is an axially symmetric tensor. Parameters ---------- gtab : GradientTable, gradient directions and bvalues container class. sh_order : unsigned int, an even integer that represent the SH order of the basis (max 12) lambda_lb: float, Laplace-Beltrami regularization weight. dec_alg : str, Spherical deconvolution algorithm. The possible values are Weighted Least Squares ('WLS'), Positivity Constraints using CVXPY ('POS') and the Constraint Spherical Deconvolution algorithm ('CSD'). Default is 'CSD'. sphere : array, shape (N,3), sphere points where to enforce positivity when 'POS' or 'CSD' dec_alg are selected. lambda_csd : float, CSD regularization weight. References ---------- .. [1] Anderson A. W., "Measurement of Fiber Orientation Distributions Using High Angular Resolution Diffusion Imaging", Magnetic Resonance in Medicine, 2005. .. [2] Kaden E. et al., "Quantitative Mapping of the Per-Axon Diffusion Coefficients in Brain White Matter", Magnetic Resonance in Medicine, 2016. .. [3] Zucchelli M. et al., "A generalized SMT-based framework for Diffusion MRI microstructural model estimation", MICCAI Workshop on Computational DIFFUSION MRI (CDMRI), 2017. Examples -------- In this example, where the data, gradient table and sphere tessellation used for reconstruction are provided, we model the diffusion signal with respect to the FORECAST and compute the fODF, parallel and perpendicular diffusivity. >>> from dipy.data import get_sphere, get_3shell_gtab >>> gtab = get_3shell_gtab() >>> from dipy.sims.voxel import MultiTensor >>> mevals = np.array(([0.0017, 0.0003, 0.0003], ... [0.0017, 0.0003, 0.0003])) >>> angl = [(0, 0), (60, 0)] >>> data, sticks = MultiTensor(gtab, ... mevals, ... S0=100.0, ... angles=angl, ... fractions=[50, 50], ... snr=None) >>> from dipy.reconst.forecast import ForecastModel >>> fm = ForecastModel(gtab, sh_order=6) >>> f_fit = fm.fit(data) >>> d_par = f_fit.dpar >>> d_perp = f_fit.dperp >>> sphere = get_sphere('symmetric724') >>> fodf = f_fit.odf(sphere) """ OdfModel.__init__(self, gtab) # round the bvals in order to avoid numerical errors self.bvals = np.round(gtab.bvals/100) * 100 self.bvecs = gtab.bvecs if sh_order >= 0 and not(bool(sh_order % 2)) and sh_order <= 12: self.sh_order = sh_order else: msg = "sh_order must be a non-zero even positive number " msg += "between 2 and 12" raise ValueError(msg) if sphere is None: sphere = get_sphere('repulsion724') self.vertices = sphere.vertices[ 0:int(sphere.vertices.shape[0]/2), :] else: self.vertices = sphere self.b0s_mask = self.bvals == 0 self.one_0_bvals = np.r_[0, self.bvals[~self.b0s_mask]] self.one_0_bvecs = np.r_[np.array([0, 0, 0]).reshape( 1, 3), self.bvecs[~self.b0s_mask, :]] self.rho = rho_matrix(self.sh_order, self.one_0_bvecs) # signal regularization matrix self.srm = rho_matrix(4, self.one_0_bvecs) self.lb_matrix_signal = lb_forecast(4) self.b_unique = np.sort(np.unique(self.bvals[self.bvals > 0])) self.wls = True self.csd = False self.pos = False if dec_alg.upper() == 'POS': if have_cvxpy: self.wls = False self.pos = True else: msg = 'cvxpy is needed to inforce positivity constraints.' raise ValueError(msg) if dec_alg.upper() == 'CSD': self.csd = True self.lb_matrix = lb_forecast(self.sh_order) self.lambda_lb = lambda_lb self.lambda_csd = lambda_csd self.fod = rho_matrix(sh_order, self.vertices)
def __init__(self, gtab, method='gqi2', sampling_length=1.2, normalize_peaks=False): r""" Generalized Q-Sampling Imaging [1]_ This model has the same assumptions as the DSI method i.e. Cartesian grid sampling in q-space and fast gradient switching. Implements equations 2.14 from [2]_ for standard GQI and equation 2.16 from [2]_ for GQI2. You can think of GQI2 as an analytical solution of the DSI ODF. Parameters ---------- gtab : object, GradientTable method : str, 'standard' or 'gqi2' sampling_length : float, diffusion sampling length (lambda in eq. 2.14 and 2.16) References ---------- .. [1] Yeh F-C et al., "Generalized Q-Sampling Imaging", IEEE TMI, 2010 .. [2] Garyfallidis E, "Towards an accurate brain tractography", PhD thesis, University of Cambridge, 2012. Notes ----- As of version 0.9, range of the sampling length in GQI2 has changed to match the same scale used in the 'standard' method [1]_. This means that the value of `sampling_length` should be approximately 1 - 1.3 (see [1]_, pg. 1628). Examples -------- Here we create an example where we provide the data, a gradient table and a reconstruction sphere and calculate the ODF for the first voxel in the data. >>> from dipy.data import dsi_voxels >>> data, gtab = dsi_voxels() >>> from dipy.core.subdivide_octahedron import create_unit_sphere >>> sphere = create_unit_sphere(5) >>> from dipy.reconst.gqi import GeneralizedQSamplingModel >>> gq = GeneralizedQSamplingModel(gtab, 'gqi2', 1.1) >>> voxel_signal = data[0, 0, 0] >>> odf = gq.fit(voxel_signal).odf(sphere) See Also -------- dipy.reconst.dsi.DiffusionSpectrumModel """ OdfModel.__init__(self, gtab) self.method = method self.Lambda = sampling_length self.normalize_peaks = normalize_peaks # 0.01506 = 6*D where D is the free water diffusion coefficient # l_values sqrt(6 D tau) D free water diffusion coefficient and # tau included in the b-value scaling = np.sqrt(self.gtab.bvals * 0.01506) tmp = np.tile(scaling, (3, 1)) gradsT = self.gtab.bvecs.T b_vector = gradsT * tmp # element-wise product self.b_vector = b_vector.T
def __init__(self, gtab, response, reg_sphere=None, sh_order=8, lambda_=1, tau=0.1): r""" Constrained Spherical Deconvolution (CSD) [1]_. Spherical deconvolution computes a fiber orientation distribution (FOD), also called fiber ODF (fODF) [2]_, as opposed to a diffusion ODF as the QballModel or the CsaOdfModel. This results in a sharper angular profile with better angular resolution that is the best object to be used for later deterministic and probabilistic tractography [3]_. A sharp fODF is obtained because a single fiber *response* function is injected as *a priori* knowledge. The response function is often data-driven and is thus provided as input to the ConstrainedSphericalDeconvModel. It will be used as deconvolution kernel, as described in [1]_. Parameters ---------- gtab : GradientTable response : tuple A tuple with two elements. The first is the eigen-values as an (3,) ndarray and the second is the signal value for the response function without diffusion weighting. This is to be able to generate a single fiber synthetic signal. The response function will be used as deconvolution kernel ([1]_) reg_sphere : Sphere (optional) sphere used to build the regularization B matrix. Default: 'symmetric362'. sh_order : int (optional) maximal spherical harmonics order. Default: 8 lambda_ : float (optional) weight given to the constrained-positivity regularization part of the deconvolution equation (see [1]_). Default: 1 tau : float (optional) threshold controlling the amplitude below which the corresponding fODF is assumed to be zero. Ideally, tau should be set to zero. However, to improve the stability of the algorithm, tau is set to tau*100 % of the mean fODF amplitude (here, 10% by default) (see [1]_). Default: 0.1 References ---------- .. [1] Tournier, J.D., et al. NeuroImage 2007. Robust determination of the fibre orientation distribution in diffusion MRI: Non-negativity constrained super-resolved spherical deconvolution .. [2] Descoteaux, M., et al. IEEE TMI 2009. Deterministic and Probabilistic Tractography Based on Complex Fibre Orientation Distributions .. [3] C\^ot\'e, M-A., et al. Medical Image Analysis 2013. Tractometer: Towards validation of tractography pipelines .. [4] Tournier, J.D, et al. Imaging Systems and Technology 2012. MRtrix: Diffusion Tractography in Crossing Fiber Regions """ # Initialize the parent class: OdfModel.__init__(self, gtab) m, n = sph_harm_ind_list(sh_order) self.m, self.n = m, n self._where_b0s = lazy_index(gtab.b0s_mask) self._where_dwi = lazy_index(~gtab.b0s_mask) no_params = ((sh_order + 1) * (sh_order + 2)) / 2 if no_params > np.sum(gtab.b0s_mask == False): msg = "Number of parameters required for the fit are more " msg += "than the actual data points" warnings.warn(msg, UserWarning) x, y, z = gtab.gradients[self._where_dwi].T r, theta, phi = cart2sphere(x, y, z) # for the gradient sphere self.B_dwi = real_sph_harm(m, n, theta[:, None], phi[:, None]) # for the sphere used in the regularization positivity constraint if reg_sphere is None: self.sphere = get_sphere('symmetric362') else: self.sphere = reg_sphere r, theta, phi = cart2sphere(self.sphere.x, self.sphere.y, self.sphere.z) self.B_reg = real_sph_harm(m, n, theta[:, None], phi[:, None]) if response is None: self.response = (np.array([0.0015, 0.0003, 0.0003]), 1) else: self.response = response self.S_r = estimate_response(gtab, self.response[0], self.response[1]) self.response_scaling = response[1] r_sh = np.linalg.lstsq(self.B_dwi, self.S_r[self._where_dwi])[0] r_rh = sh_to_rh(r_sh, m, n) self.R = forward_sdeconv_mat(r_rh, n) # scale lambda_ to account for differences in the number of # SH coefficients and number of mapped directions # This is exactly what is done in [4]_ self.lambda_ = (lambda_ * self.R.shape[0] * r_rh[0] / (np.sqrt(self.B_reg.shape[0]) * np.sqrt(362.)) ) self.sh_order = sh_order self.tau = tau
def __init__(self, gtab, method='gqi2', sampling_length=1.2, normalize_peaks=False): r""" Generalized Q-Sampling Imaging [1]_ This model has the same assumptions as the DSI method i.e. Cartesian grid sampling in q-space and fast gradient switching. Implements equations 2.14 from [2]_ for standard GQI and equation 2.16 from [2]_ for GQI2. You can think of GQI2 as an analytical solution of the DSI ODF. Parameters ---------- gtab : object, GradientTable method : str, 'standard' or 'gqi2' sampling_length : float, diffusion sampling length (lambda in eq. 2.14 and 2.16) References ---------- .. [1] Yeh F-C et. al, "Generalized Q-Sampling Imaging", IEEE TMI, 2010 .. [2] Garyfallidis E, "Towards an accurate brain tractography", PhD thesis, University of Cambridge, 2012. Notes ----- As of version 0.9, range of the sampling length in GQI2 has changed to match the same scale used in the 'standard' method [1]_. This means that the value of `sampling_length` should be approximately 1 - 1.3 (see [1]_, pg. 1628). Examples -------- Here we create an example where we provide the data, a gradient table and a reconstruction sphere and calculate the ODF for the first voxel in the data. >>> from dipy.data import dsi_voxels >>> data, gtab = dsi_voxels() >>> from dipy.core.subdivide_octahedron import create_unit_sphere >>> sphere = create_unit_sphere(5) >>> from dipy.reconst.gqi import GeneralizedQSamplingModel >>> gq = GeneralizedQSamplingModel(gtab, 'gqi2', 1.1) >>> voxel_signal = data[0, 0, 0] >>> odf = gq.fit(voxel_signal).odf(sphere) See Also -------- dipy.reconst.dsi.DiffusionSpectrumModel """ OdfModel.__init__(self, gtab) self.method = method self.Lambda = sampling_length self.normalize_peaks = normalize_peaks # 0.01506 = 6*D where D is the free water diffusion coefficient # l_values sqrt(6 D tau) D free water diffusion coefficient and # tau included in the b-value scaling = np.sqrt(self.gtab.bvals * 0.01506) tmp = np.tile(scaling, (3, 1)) gradsT = self.gtab.bvecs.T b_vector = gradsT * tmp # element-wise product self.b_vector = b_vector.T
def __init__(self, gtab, wm_response=np.array([1.7e-3, 0.2e-3, 0.2e-3]), gm_response=0.8e-3, csf_response=3.0e-3, n_iter=600, recon_type='smf', n_coils=1, R=1, voxelwise=True, use_tv=False, sphere=None, verbose=False): ''' Robust and Unbiased Model-BAsed Spherical Deconvolution (RUMBA-SD) [1]_ Modification of the Richardson-Lucy algorithm accounting for Rician and Noncentral Chi noise distributions, which more accurately represent MRI noise. Computes a maximum likelihood estimation of the fiber orientation density function (fODF) at each voxel. Includes white matter compartments alongside optional GM and CSF compartments to account for partial volume effects. This fit can be performed voxelwise or globally. The global fit will proceed more quickly than the voxelwise fit provided that the computer has adequate RAM (>= 16 GB should be sufficient for most datasets). Kernel for deconvolution constructed using a priori knowledge of white matter response function, as well as the mean diffusivity of GM and/or CSF. RUMBA-SD is robust against impulse response imprecision, and thus the default diffusivity values are often adequate [2]_. Parameters ---------- gtab : GradientTable wm_response : 1d ndarray or 2d ndarray or AxSymShResponse, optional Tensor eigenvalues as a (3,) ndarray, multishell eigenvalues as a (len(unique_bvals_tolerance(gtab.bvals))-1, 3) ndarray in order of smallest to largest b-value, or an AxSymShResponse. Default: np.array([1.7e-3, 0.2e-3, 0.2e-3]) gm_response : float, optional Mean diffusivity for GM compartment. If `None`, then grey matter volume fraction is not computed. Default: 0.8e-3 csf_response : float, optional Mean diffusivity for CSF compartment. If `None`, then CSF volume fraction is not computed. Default: 3.0e-3 n_iter : int, optional Number of iterations for fODF estimation. Must be a positive int. Default: 600 recon_type : {'smf', 'sos'}, optional MRI reconstruction method: spatial matched filter (SMF) or sum-of-squares (SoS). SMF reconstruction generates Rician noise while SoS reconstruction generates Noncentral Chi noise. Default: 'smf' n_coils : int, optional Number of coils in MRI scanner -- only relevant in SoS reconstruction. Must be a positive int. Default: 1 R : int, optional Acceleration factor of the acquisition. For SIEMENS, R = iPAT factor. For GE, R = ASSET factor. For PHILIPS, R = SENSE factor. Typical values are 1 or 2. Must be a positive int. Default: 1 voxelwise : bool, optional If true, performs a voxelwise fit. If false, performs a global fit on the entire brain at once. The global fit requires a 4D brain volume in `fit`. Default: True use_tv : bool, optional If true, applies total variation regularization. This only takes effect in a global fit (`voxelwise` is set to `False`). TV can only be applied to 4D brain volumes with no singleton dimensions. Default: False sphere : Sphere, optional Sphere on which to construct fODF. If None, uses `repulsion724`. Default: None verbose : bool, optional If true, logs updates on estimated signal-to-noise ratio after each iteration. This only takes effect in a global fit (`voxelwise` is set to `False`). Default: False References ---------- .. [1] Canales-Rodríguez, E. J., Daducci, A., Sotiropoulos, S. N., Caruyer, E., Aja-Fernández, S., Radua, J., Mendizabal, J. M. Y., Iturria-Medina, Y., Melie-García, L., Alemán-Gómez, Y., Thiran, J.-P., Sarró, S., Pomarol-Clotet, E., & Salvador, R. (2015). Spherical Deconvolution of Multichannel Diffusion MRI Data with Non-Gaussian Noise Models and Spatial Regularization. PLOS ONE, 10(10), e0138910. https://doi.org/10.1371/journal.pone.0138910 .. [2] Dell’Acqua, F., Rizzo, G., Scifo, P., Clarke, R., Scotti, G., & Fazio, F. (2007). A Model-Based Deconvolution Approach to Solve Fiber Crossing in Diffusion-Weighted MR Imaging. IEEE Transactions on Bio-Medical Engineering, 54, 462–472. https://doi.org/10.1109/TBME.2006.888830 ''' if not np.any(gtab.b0s_mask): raise ValueError("Gradient table has no b0 measurements") self.gtab_orig = gtab # save for prediction # Masks to extract b0/non-b0 measurements self.where_b0s = lazy_index(gtab.b0s_mask) self.where_dwi = lazy_index(~gtab.b0s_mask) # Correct gradient table to contain b0 data at the beginning bvals_cor = np.concatenate(([0], gtab.bvals[self.where_dwi])) bvecs_cor = np.concatenate(([[0, 0, 0]], gtab.bvecs[self.where_dwi])) gtab_cor = gradient_table(bvals_cor, bvecs_cor) # Initialize self.gtab OdfModel.__init__(self, gtab_cor) # Store responses self.wm_response = wm_response self.gm_response = gm_response self.csf_response = csf_response # Initializing remaining parameters if R < 1 or n_iter < 1 or n_coils < 1: raise ValueError( f"R, n_iter, and n_coils must be >= 1, but R={R}," + f"n_iter={n_iter}, and n_coils={n_coils} ") self.R = R self.n_iter = n_iter self.recon_type = recon_type self.n_coils = n_coils if voxelwise and use_tv: raise ValueError("Total variation has no effect in voxelwise fit") if voxelwise and verbose: warnings.warn("Verbosity has no effect in voxelwise fit", UserWarning) self.voxelwise = voxelwise self.use_tv = use_tv self.verbose = verbose if sphere is None: self.sphere = get_sphere('repulsion724') else: self.sphere = sphere if voxelwise: self.fit = self._voxelwise_fit else: self.fit = self._global_fit # Fitting parameters self.kernel = None