def fa(self): r""" Fractional anisotropy (FA) calculated from cached eigenvalues. Returns --------- fa : array (V, 1) Calculated FA. Note: range is 0 <= FA <= 1. Notes -------- FA is calculated with the following equation: .. math:: FA = \sqrt{\frac{1}{2}\frac{(\lambda_1-\lambda_2)^2+(\lambda_1- \lambda_3)^2+(\lambda_2-lambda_3)^2}{\lambda_1^2+ \lambda_2^2+\lambda_3^2} } """ evals, wrap = _makearray(self.model_params[..., :3]) ev1 = evals[..., 0] ev2 = evals[..., 1] ev3 = evals[..., 2] fa = np.sqrt(0.5 * ((ev1 - ev2)**2 + (ev2 - ev3)**2 + (ev3 - ev1)**2) / (ev1*ev1 + ev2*ev2 + ev3*ev3)) fa = wrap(np.asarray(fa)) return _filled(fa)
def tensor_eig_from_lo_tri(B, data): """Calculates parameters for creating a Tensor instance Calculates tensor parameters from the six unique tensor elements. This function can be passed to the Tensor class as a fit_method for creating a Tensor instance from tensors stored in a nifti file. Parameters: ----------- B : not currently used data : array_like (..., 6) diffusion tensors elements stored in lower triangular order Returns ------- dti_params Eigen values and vectors, used by the Tensor class to create an instance """ data, wrap = _makearray(data) data_flat = data.reshape((-1, data.shape[-1])) dti_params = np.empty((len(data_flat), 4, 3)) for ii in xrange(len(data_flat)): tensor = from_lower_triangular(data_flat[ii]) eigvals, eigvecs = decompose_tensor(tensor) dti_params[ii, 0] = eigvals dti_params[ii, 1:] = eigvecs dti_params.shape = data.shape[:-1] + (12,) dti_params = wrap(dti_params) return dti_params
def tensor_eig_from_lo_tri(B, data): """Calculates parameters for creating a Tensor instance Calculates tensor parameters from the six unique tensor elements. This function can be passed to the Tensor class as a fit_method for creating a Tensor instance from tensors stored in a nifti file. Parameters: ----------- B : not currently used data : array_like (..., 6) diffusion tensors elements stored in lower triangular order Returns ------- dti_params Eigen values and vectors, used by the Tensor class to create an instance """ data, wrap = _makearray(data) data_flat = data.reshape((-1, data.shape[-1])) dti_params = np.empty((len(data_flat), 4, 3)) for ii in xrange(len(data_flat)): tensor = from_lower_triangular(data_flat[ii]) eigvals, eigvecs = decompose_tensor(tensor) dti_params[ii, 0] = eigvals dti_params[ii, 1:] = eigvecs dti_params.shape = data.shape[:-1] + (12, ) dti_params = wrap(dti_params) return dti_params
def _getD(self): """Calculates the 3x3 diffusion tensor for each voxel""" params, wrap = _makearray(self.model_params) evals = params[..., :3] evecs = params[..., 3:] evals_flat = evals.reshape((-1, 3)) evecs_flat = evecs.reshape((-1, 3, 3)) D_flat = np.empty(evecs_flat.shape) for ii in xrange(len(D_flat)): Q = evecs_flat[ii] L = evals_flat[ii] D_flat[ii] = np.dot(Q * L, Q.T) D = _filled(wrap(D_flat)) D.shape = self.shape + (3, 3) return D
def fa(self, fill_value=0, nonans=True): r""" Fractional anisotropy (FA) calculated from cached eigenvalues. Parameters ---------- fill_value : float value of fa where self.mask == True. nonans : Bool When True, fa is 0 when all eigenvalues are 0, otherwise fa is nan Returns --------- fa : array (V, 1) Calculated FA. Note: range is 0 <= FA <= 1. Notes -------- FA is calculated with the following equation: .. math:: FA = \sqrt{\frac{1}{2}\frac{(\lambda_1-\lambda_2)^2+(\lambda_1- \lambda_3)^2+(\lambda_2-lambda_3)^2}{\lambda_1^2+ \lambda_2^2+\lambda_3^2} } """ evals, wrap = _makearray(self.model_params[..., :3]) ev1 = evals[..., 0] ev2 = evals[..., 1] ev3 = evals[..., 2] if nonans: all_zero = (ev1 == 0) & (ev2 == 0) & (ev3 == 0) else: all_zero = 0.0 fa = np.sqrt( 0.5 * ((ev1 - ev2) ** 2 + (ev2 - ev3) ** 2 + (ev3 - ev1) ** 2) / (ev1 * ev1 + ev2 * ev2 + ev3 * ev3 + all_zero) ) fa = wrap(np.asarray(fa)) return _filled(fa, fill_value)
def fa(self, fill_value=0, nonans=True): r""" Fractional anisotropy (FA) calculated from cached eigenvalues. Parameters ---------- fill_value : float value of fa where self.mask == True. nonans : Bool When True, fa is 0 when all eigenvalues are 0, otherwise fa is nan Returns --------- fa : array (V, 1) Calculated FA. Note: range is 0 <= FA <= 1. Notes -------- FA is calculated with the following equation: .. math:: FA = \sqrt{\frac{1}{2}\frac{(\lambda_1-\lambda_2)^2+(\lambda_1- \lambda_3)^2+(\lambda_2-lambda_3)^2}{\lambda_1^2+ \lambda_2^2+\lambda_3^2} } """ evals, wrap = _makearray(self.model_params[..., :3]) ev1 = evals[..., 0] ev2 = evals[..., 1] ev3 = evals[..., 2] if nonans: all_zero = (ev1 == 0) & (ev2 == 0) & (ev3 == 0) else: all_zero = 0. fa = np.sqrt(0.5 * ((ev1 - ev2)**2 + (ev2 - ev3)**2 + (ev3 - ev1)**2) / (ev1 * ev1 + ev2 * ev2 + ev3 * ev3 + all_zero)) fa = wrap(np.asarray(fa)) return _filled(fa, fill_value)
def ols_fit_tensor(design_matrix, data, min_signal=1): r""" Computes ordinary least squares (OLS) fit to calculate self-diffusion tensor using a linear regression model [1]_. Parameters ---------- design_matrix : array (g, 7) Design matrix holding the covariants used to solve for the regression coefficients. Use design_matrix to build a valid design matrix from bvalues and a gradient table. data : array ([X, Y, Z, ...], g) Data or response variables holding the data. Note that the last dimension should contain the data. It makes no copies of data. min_signal : default = 1 All values below min_signal are repalced with min_signal. This is done in order to avaid taking log(0) durring the tensor fitting. Returns ------- eigvals : array (..., 3) Eigenvalues from eigen decomposition of the tensor. eigvecs : array (..., 3, 3) Associated eigenvectors from eigen decomposition of the tensor. Eigenvectors are columnar (e.g. eigvecs[:,j] is associated with eigvals[j]) See Also -------- WLS_fit_tensor, decompose_tensor, design_matrix Notes ----- This function is offered mainly as a quick comparison to WLS. .. math:: y = \mathrm{data} \\ X = \mathrm{design matrix} \\ \hat{\beta}_\mathrm{OLS} = (X^T X)^{-1} X^T y References ---------- .. [1] Chung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap approaches for estimation of uncertainties of DTI parameters. NeuroImage 33, 531-541. """ data, wrap = _makearray(data) data_flat = data.reshape((-1, data.shape[-1])) evals = np.empty((len(data_flat), 3)) evecs = np.empty((len(data_flat), 3, 3)) dti_params = np.empty((len(data_flat), 4, 3)) # obtain OLS fitting matrix # U,S,V = np.linalg.svd(design_matrix, False) # math: beta_ols = inv(X.T*X)*X.T*y # math: ols_fit = X*beta_ols*inv(y) # ols_fit = np.dot(U, U.T) inv_design = np.linalg.pinv(design_matrix) for param, sig in zip(dti_params, data_flat): param[0], param[1:] = _ols_iter(inv_design, sig, min_signal) dti_params.shape = data.shape[:-1] + (12,) dti_params = wrap(dti_params) return dti_params
def wls_fit_tensor(design_matrix, data, min_signal=1): r""" Computes weighted least squares (WLS) fit to calculate self-diffusion tensor using a linear regression model [1]_. Parameters ---------- design_matrix : array (g, 7) Design matrix holding the covariants used to solve for the regression coefficients. data : array ([X, Y, Z, ...], g) Data or response variables holding the data. Note that the last dimension should contain the data. It makes no copies of data. min_signal : default = 1 All values below min_signal are repalced with min_signal. This is done in order to avaid taking log(0) durring the tensor fitting. Returns ------- eigvals : array (..., 3) Eigenvalues from eigen decomposition of the tensor. eigvecs : array (..., 3, 3) Associated eigenvectors from eigen decomposition of the tensor. Eigenvectors are columnar (e.g. eigvecs[:,j] is associated with eigvals[j]) See Also -------- decompose_tensor Notes ----- In Chung, et al. 2006, the regression of the WLS fit needed an unbiased preliminary estimate of the weights and therefore the ordinary least squares (OLS) estimates were used. A "two pass" method was implemented: 1. calculate OLS estimates of the data 2. apply the OLS estimates as weights to the WLS fit of the data This ensured heteroscadasticity could be properly modeled for various types of bootstrap resampling (namely residual bootstrap). .. math:: y = \mathrm{data} \\ X = \mathrm{design matrix} \\ \hat{\beta}_\mathrm{WLS} = \mathrm{desired regression coefficients (e.g. tensor)}\\ \\ \hat{\beta}_\mathrm{WLS} = (X^T W X)^{-1} X^T W y \\ \\ W = \mathrm{diag}((X \hat{\beta}_\mathrm{OLS})^2), \mathrm{where} \hat{\beta}_\mathrm{OLS} = (X^T X)^{-1} X^T y References ---------- .. _[1] Chung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap approaches for estimation of uncertainties of DTI parameters. NeuroImage 33, 531-541. """ if min_signal <= 0: raise ValueError("min_signal must be > 0") data, wrap = _makearray(data) data_flat = data.reshape((-1, data.shape[-1])) dti_params = np.empty((len(data_flat), 4, 3)) # obtain OLS fitting matrix # U,S,V = np.linalg.svd(design_matrix, False) # math: beta_ols = inv(X.T*X)*X.T*y # math: ols_fit = X*beta_ols*inv(y) # ols_fit = np.dot(U, U.T) ols_fit = _ols_fit_matrix(design_matrix) for param, sig in zip(dti_params, data_flat): param[0], param[1:] = _wls_iter(ols_fit, design_matrix, sig, min_signal=min_signal) dti_params.shape = data.shape[:-1] + (12,) dti_params = wrap(dti_params) return dti_params
def ols_fit_tensor(design_matrix, data, min_signal=1): r""" Computes ordinary least squares (OLS) fit to calculate self-diffusion tensor using a linear regression model [1]_. Parameters ---------- design_matrix : array (g, 7) Design matrix holding the covariants used to solve for the regression coefficients. Use design_matrix to build a valid design matrix from bvalues and a gradient table. data : array ([X, Y, Z, ...], g) Data or response variables holding the data. Note that the last dimension should contain the data. It makes no copies of data. min_signal : default = 1 All values below min_signal are repalced with min_signal. This is done in order to avaid taking log(0) durring the tensor fitting. Returns ------- eigvals : array (..., 3) Eigenvalues from eigen decomposition of the tensor. eigvecs : array (..., 3, 3) Associated eigenvectors from eigen decomposition of the tensor. Eigenvectors are columnar (e.g. eigvecs[:,j] is associated with eigvals[j]) See Also -------- WLS_fit_tensor, decompose_tensor, design_matrix Notes ----- This function is offered mainly as a quick comparison to WLS. .. math:: y = \mathrm{data} \\ X = \mathrm{design matrix} \\ \hat{\beta}_\mathrm{OLS} = (X^T X)^{-1} X^T y References ---------- .. [1] Chung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap approaches for estimation of uncertainties of DTI parameters. NeuroImage 33, 531-541. """ data, wrap = _makearray(data) data_flat = data.reshape((-1, data.shape[-1])) evals = np.empty((len(data_flat), 3)) evecs = np.empty((len(data_flat), 3, 3)) dti_params = np.empty((len(data_flat), 4, 3)) #obtain OLS fitting matrix #U,S,V = np.linalg.svd(design_matrix, False) #math: beta_ols = inv(X.T*X)*X.T*y #math: ols_fit = X*beta_ols*inv(y) #ols_fit = np.dot(U, U.T) inv_design = np.linalg.pinv(design_matrix) for param, sig in zip(dti_params, data_flat): param[0], param[1:] = _ols_iter(inv_design, sig, min_signal) dti_params.shape = data.shape[:-1] + (12, ) dti_params = wrap(dti_params) return dti_params
def wls_fit_tensor(design_matrix, data, min_signal=1): r""" Computes weighted least squares (WLS) fit to calculate self-diffusion tensor using a linear regression model [1]_. Parameters ---------- design_matrix : array (g, 7) Design matrix holding the covariants used to solve for the regression coefficients. data : array ([X, Y, Z, ...], g) Data or response variables holding the data. Note that the last dimension should contain the data. It makes no copies of data. min_signal : default = 1 All values below min_signal are repalced with min_signal. This is done in order to avaid taking log(0) durring the tensor fitting. Returns ------- eigvals : array (..., 3) Eigenvalues from eigen decomposition of the tensor. eigvecs : array (..., 3, 3) Associated eigenvectors from eigen decomposition of the tensor. Eigenvectors are columnar (e.g. eigvecs[:,j] is associated with eigvals[j]) See Also -------- decompose_tensor Notes ----- In Chung, et al. 2006, the regression of the WLS fit needed an unbiased preliminary estimate of the weights and therefore the ordinary least squares (OLS) estimates were used. A "two pass" method was implemented: 1. calculate OLS estimates of the data 2. apply the OLS estimates as weights to the WLS fit of the data This ensured heteroscadasticity could be properly modeled for various types of bootstrap resampling (namely residual bootstrap). .. math:: y = \mathrm{data} \\ X = \mathrm{design matrix} \\ \hat{\beta}_\mathrm{WLS} = \mathrm{desired regression coefficients (e.g. tensor)}\\ \\ \hat{\beta}_\mathrm{WLS} = (X^T W X)^{-1} X^T W y \\ \\ W = \mathrm{diag}((X \hat{\beta}_\mathrm{OLS})^2), \mathrm{where} \hat{\beta}_\mathrm{OLS} = (X^T X)^{-1} X^T y References ---------- .. _[1] Chung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap approaches for estimation of uncertainties of DTI parameters. NeuroImage 33, 531-541. """ if min_signal <= 0: raise ValueError('min_signal must be > 0') data, wrap = _makearray(data) data_flat = data.reshape((-1, data.shape[-1])) dti_params = np.empty((len(data_flat), 4, 3)) #obtain OLS fitting matrix #U,S,V = np.linalg.svd(design_matrix, False) #math: beta_ols = inv(X.T*X)*X.T*y #math: ols_fit = X*beta_ols*inv(y) #ols_fit = np.dot(U, U.T) ols_fit = _ols_fit_matrix(design_matrix) for param, sig in zip(dti_params, data_flat): param[0], param[1:] = _wls_iter(ols_fit, design_matrix, sig, min_signal=min_signal) dti_params.shape = data.shape[:-1] + (12, ) dti_params = wrap(dti_params) return dti_params