Source code for dipy.reconst.utils

import numpy as np


[docs] def dki_design_matrix(gtab): r"""Construct B design matrix for DKI. Parameters ---------- gtab : GradientTable Measurement directions. Returns ------- B : array (N, 22) Design matrix or B matrix for the DKI model .. math:: B[j, :] = (Bxx, Bxy, Byy, Bxz, Byz, Bzz, Bxxxx, Byyyy, Bzzzz, Bxxxy, Bxxxz, Bxyyy, Byyyz, Bxzzz, Byzzz, Bxxyy, Bxxzz, Byyzz, Bxxyz, Bxyyz, Bxyzz, BlogS0) """ b = gtab.bvals bvec = gtab.bvecs B = np.zeros((len(b), 22)) B[:, 0] = -b * bvec[:, 0] * bvec[:, 0] B[:, 1] = -2 * b * bvec[:, 0] * bvec[:, 1] B[:, 2] = -b * bvec[:, 1] * bvec[:, 1] B[:, 3] = -2 * b * bvec[:, 0] * bvec[:, 2] B[:, 4] = -2 * b * bvec[:, 1] * bvec[:, 2] B[:, 5] = -b * bvec[:, 2] * bvec[:, 2] B[:, 6] = b * b * bvec[:, 0] ** 4 / 6 B[:, 7] = b * b * bvec[:, 1] ** 4 / 6 B[:, 8] = b * b * bvec[:, 2] ** 4 / 6 B[:, 9] = 4 * b * b * bvec[:, 0] ** 3 * bvec[:, 1] / 6 B[:, 10] = 4 * b * b * bvec[:, 0] ** 3 * bvec[:, 2] / 6 B[:, 11] = 4 * b * b * bvec[:, 1] ** 3 * bvec[:, 0] / 6 B[:, 12] = 4 * b * b * bvec[:, 1] ** 3 * bvec[:, 2] / 6 B[:, 13] = 4 * b * b * bvec[:, 2] ** 3 * bvec[:, 0] / 6 B[:, 14] = 4 * b * b * bvec[:, 2] ** 3 * bvec[:, 1] / 6 B[:, 15] = b * b * bvec[:, 0] ** 2 * bvec[:, 1] ** 2 B[:, 16] = b * b * bvec[:, 0] ** 2 * bvec[:, 2] ** 2 B[:, 17] = b * b * bvec[:, 1] ** 2 * bvec[:, 2] ** 2 B[:, 18] = 2 * b * b * bvec[:, 0] ** 2 * bvec[:, 1] * bvec[:, 2] B[:, 19] = 2 * b * b * bvec[:, 1] ** 2 * bvec[:, 0] * bvec[:, 2] B[:, 20] = 2 * b * b * bvec[:, 2] ** 2 * bvec[:, 0] * bvec[:, 1] B[:, 21] = -np.ones(len(b)) return B
[docs] def cti_design_matrix(gtab1, gtab2): r"""Construct B design matrix for CTI. Parameters ---------- gtab1: dipy.core.gradients.GradientTable A GradientTable class instance for first DDE diffusion epoch gtab2: dipy.core.gradients.GradientTable A GradientTable class instance for second DDE diffusion epoch Returns ------- B: array(N, 43) Design matrix or B matrix for the CTI model assuming multiple Gaussian Components """ b1 = gtab1.bvals b2 = gtab2.bvals n1 = gtab1.bvecs n2 = gtab2.bvecs B = np.zeros((len(b1), 43)) B[:, 0] = -b1 * (n1[:, 0] ** 2) - b2 * (n2[:, 0] ** 2) B[:, 1] = -2 * b1 * n1[:, 0] * n1[:, 1] - 2 * b2 * n2[:, 0] * n2[:, 1] B[:, 2] = -b1 * n1[:, 1] ** 2 - b2 * n2[:, 1] ** 2 B[:, 3] = -2 * b1 * n1[:, 0] * n1[:, 2] - 2 * b2 * n2[:, 0] * n2[:, 2] B[:, 4] = -2 * b1 * n1[:, 1] * n1[:, 2] - 2 * b2 * n2[:, 1] * n2[:, 2] B[:, 5] = -b1 * n1[:, 2] ** 2 - b2 * n2[:, 2] ** 2 B[:, 6] = (b1 * b1 * n1[:, 0] ** 4 + b2 * b2 * n2[:, 0] ** 4) / 6 B[:, 7] = (b1 * b1 * n1[:, 1] ** 4 + b2 * b2 * n2[:, 1] ** 4) / 6 B[:, 8] = (b1 * b1 * n1[:, 2] ** 4 + b2 * b2 * n2[:, 2] ** 4) / 6 B[:, 9] = ( 2 * b1 * b1 * n1[:, 0] ** 3 * n1[:, 1] + 2 * b2 * b2 * n2[:, 0] ** 3 * n2[:, 1] ) / 3 B[:, 10] = ( 2 * b1 * b1 * n1[:, 0] ** 3 * n1[:, 2] + 2 * b2 * b2 * n2[:, 0] ** 3 * n2[:, 2] ) / 3 B[:, 11] = ( 2 * b1 * b1 * n1[:, 1] ** 3 * n1[:, 0] + 2 * b2 * b2 * n2[:, 1] ** 3 * n2[:, 0] ) / 3 B[:, 12] = ( 2 * b1 * b1 * n1[:, 1] ** 3 * n1[:, 2] + 2 * b2 * b2 * n2[:, 1] ** 3 * n2[:, 2] ) / 3 B[:, 13] = ( 2 * b1 * b1 * n1[:, 2] ** 3 * n1[:, 0] + 2 * b2 * b2 * n2[:, 2] ** 3 * n2[:, 0] ) / 3 B[:, 14] = ( 2 * b1 * b1 * n1[:, 2] ** 3 * n1[:, 1] + 2 * b2 * b2 * n2[:, 2] ** 3 * n2[:, 1] ) / 3 B[:, 15] = ( b1 * b1 * n1[:, 0] ** 2 * n1[:, 1] ** 2 + b2 * b2 * n2[:, 0] ** 2 * n2[:, 1] ** 2 ) B[:, 16] = ( b1 * b1 * n1[:, 0] ** 2 * n1[:, 2] ** 2 + b2 * b2 * n2[:, 0] ** 2 * n2[:, 2] ** 2 ) B[:, 17] = ( b1 * b1 * n1[:, 1] ** 2 * n1[:, 2] ** 2 + b2 * b2 * n2[:, 1] ** 2 * n2[:, 2] ** 2 ) B[:, 18] = ( 2 * b1 * b1 * n1[:, 0] ** 2 * n1[:, 1] * n1[:, 2] + 2 * b2 * b2 * n2[:, 0] ** 2 * n2[:, 1] * n2[:, 2] ) B[:, 19] = ( 2 * b1 * b1 * n1[:, 1] ** 2 * n1[:, 0] * n1[:, 2] + 2 * b2 * b2 * n2[:, 1] ** 2 * n2[:, 0] * n2[:, 2] ) B[:, 20] = ( 2 * b1 * b1 * n1[:, 2] ** 2 * n1[:, 0] * n1[:, 1] + 2 * b2 * b2 * n2[:, 2] ** 2 * n2[:, 0] * n2[:, 1] ) B[:, 21] = b1 * n1[:, 0] ** 2 * b2 * n2[:, 0] ** 2 B[:, 22] = b1 * n1[:, 1] ** 2 * b2 * n2[:, 1] ** 2 B[:, 23] = b1 * n1[:, 2] ** 2 * b2 * n2[:, 2] ** 2 B[:, 24] = ( b1 * n1[:, 1] ** 2 * b2 * n2[:, 2] ** 2 + b1 * n1[:, 2] ** 2 * b2 * n2[:, 1] ** 2 ) B[:, 25] = ( b1 * n1[:, 0] ** 2 * b2 * n2[:, 2] ** 2 + b1 * n1[:, 2] ** 2 * b2 * n2[:, 0] ** 2 ) B[:, 26] = ( b1 * n1[:, 0] ** 2 * b2 * n2[:, 1] ** 2 + b1 * n1[:, 1] ** 2 * b2 * n2[:, 0] ** 2 ) B[:, 27] = 2 * ( b1 * n1[:, 0] ** 2 * b2 * n2[:, 1] * n2[:, 2] + b1 * n1[:, 1] * n1[:, 2] * b2 * n2[:, 0] ** 2 ) B[:, 28] = 2 * ( b1 * n1[:, 0] ** 2 * b2 * n2[:, 0] * n2[:, 2] + b1 * n1[:, 0] * n1[:, 2] * b2 * n2[:, 0] ** 2 ) B[:, 29] = 2 * ( b1 * n1[:, 0] ** 2 * b2 * n2[:, 0] * n2[:, 1] + b1 * n1[:, 0] * n1[:, 1] * b2 * n2[:, 0] ** 2 ) B[:, 30] = 2 * ( b1 * n1[:, 1] ** 2 * b2 * n2[:, 1] * n2[:, 2] + b1 * n1[:, 1] * n1[:, 2] * b2 * n2[:, 1] ** 2 ) B[:, 31] = 2 * ( b1 * n1[:, 1] ** 2 * b2 * n2[:, 0] * n2[:, 2] + b1 * n1[:, 0] * n1[:, 2] * b2 * n2[:, 1] ** 2 ) B[:, 32] = 2 * ( b1 * n1[:, 1] ** 2 * b2 * n2[:, 1] * n2[:, 0] + b1 * n1[:, 1] * n1[:, 0] * b2 * n2[:, 1] ** 2 ) B[:, 33] = 2 * ( b1 * n1[:, 2] ** 2 * b2 * n2[:, 2] * n2[:, 1] + b1 * n1[:, 2] * n1[:, 1] * b2 * n2[:, 2] ** 2 ) B[:, 34] = 2 * ( b1 * n1[:, 2] ** 2 * b2 * n2[:, 2] * n2[:, 0] + b1 * n1[:, 2] * n1[:, 0] * b2 * n2[:, 2] ** 2 ) B[:, 35] = 2 * ( b1 * n1[:, 2] ** 2 * b2 * n2[:, 0] * n2[:, 1] + b1 * n1[:, 0] * n1[:, 1] * b2 * n2[:, 2] ** 2 ) B[:, 36] = 4 * (b1 * n1[:, 1] * n1[:, 2] * b2 * n2[:, 1] * n2[:, 2]) B[:, 37] = 4 * (b1 * n1[:, 0] * n1[:, 2] * b2 * n2[:, 0] * n2[:, 2]) B[:, 38] = 4 * (b1 * n1[:, 0] * n1[:, 1] * b2 * n2[:, 0] * n2[:, 1]) B[:, 39] = 4 * ( b1 * n1[:, 0] * n1[:, 2] * b2 * n2[:, 1] * n2[:, 2] + b1 * n1[:, 1] * n1[:, 2] * b2 * n2[:, 0] * n2[:, 2] ) B[:, 40] = 4 * ( b1 * n1[:, 0] * n1[:, 1] * b2 * n2[:, 0] * n2[:, 2] + b1 * n1[:, 0] * n1[:, 2] * b2 * n2[:, 0] * n2[:, 1] ) B[:, 41] = 4 * ( b1 * n1[:, 0] * n1[:, 1] * b2 * n2[:, 1] * n2[:, 2] + b1 * n1[:, 1] * n1[:, 2] * b2 * n2[:, 0] * n2[:, 1] ) B[:, 42] = -np.ones(len(b1)) return B
def _roi_in_volume(data_shape, roi_center, roi_radii): """Ensures that a cuboid ROI is in a data volume. Parameters ---------- data_shape : ndarray Shape of the data roi_center : ndarray, (3,) Center of ROI in data. roi_radii : ndarray, (3,) Radii of cuboid ROI Returns ------- roi_radii : ndarray, (3,) Truncated radii of cuboid ROI. It remains unchanged if the ROI was already contained inside the data volume. """ for i in range(len(roi_center)): inf_lim = int(roi_center[i] - roi_radii[i]) sup_lim = int(roi_center[i] + roi_radii[i]) if inf_lim < 0 or sup_lim >= data_shape[i]: roi_radii[i] = min(int(roi_center[i]), int(data_shape[i] - roi_center[i])) return roi_radii def _mask_from_roi(data_shape, roi_center, roi_radii): """Produces a mask from a cuboid ROI defined by center and radii. Parameters ---------- data_shape : array-like, (3,) Shape of the data from which the ROI is taken. roi_center : array-like, (3,) Center of ROI in data. roi_radii : array-like, (3,) Radii of cuboid ROI. Returns ------- mask : ndarray Mask of the cuboid ROI. """ ci, cj, ck = roi_center wi, wj, wk = roi_radii interval_i = slice(int(ci - wi), int(ci + wi) + 1) interval_j = slice(int(cj - wj), int(cj + wj) + 1) interval_k = slice(int(ck - wk), int(ck + wk) + 1) if wi == 0: interval_i = ci elif wj == 0: interval_j = cj elif wk == 0: interval_k = ck mask = np.zeros(data_shape, dtype=np.int64) mask[interval_i, interval_j, interval_k] = 1 return mask
[docs] def convert_tensors(tensor, from_format, to_format): """Convert tensors from one format to another. Parameters ---------- tensor : ndarray Input tensor. from_format : str Format of the input tensor. Options: 'dipy', 'mrtrix', 'ants', 'fsl'. to_format : str Format of the output tensor. Options: 'dipy', 'mrtrix', 'ants', 'fsl'. Notes ----- - DIPY order: [Dxx, Dxy, Dyy, Dxz, Dyz, Dzz]. Shape: [i, j , k, 6]. See: https://github.com/dipy/dipy/blob/master/dipy/reconst/dti.py#L1639 - MRTRIX order: [Dxx, Dyy, Dzz, Dxy, Dxz, Dyz] Shape: [i, j , k, 6]. See: https://mrtrix.readthedocs.io/en/dev/reference/commands/dwi2tensor.html # noqa - ANTS: [Dxx, Dxy, Dyy, Dxz, Dyz, Dzz]. Shape: [i, j , k, 1, 6] - Note the extra dimension (5D) See: https://github.com/ANTsX/ANTs/wiki/Importing-diffusion-tensor-data-from-other-software # noqa - FSL: [Dxx, Dxy, Dxz, Dyy, Dyz, Dzz] Shape: [i, j , k, 6]. (Also used for the Fibernavigator) Ref: https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FDT/UserGuide """ # noqa: E501 tensor_order = { "fsl": [[0, 1, 3, 2, 4, 5], [0, 1, 3, 2, 4, 5]], "mrtrix": [[0, 3, 1, 4, 5, 2], [0, 2, 5, 1, 3, 4]], "dipy": [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]], "ants": [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]], } if from_format.lower() not in tensor_order.keys(): raise ValueError(f"Unknown tensor format: {from_format}") if to_format.lower() not in tensor_order.keys(): raise ValueError(f"Unknown tensor format: {to_format}") if from_format.lower() == to_format.lower(): return tensor if from_format.lower() in ["ants", "dipy"]: tensor = np.squeeze(tensor) if tensor.ndim == 5 else tensor tensor_dipy = tensor[..., tensor_order[from_format.lower()][0]] if to_format.lower() == "ants": tensor_dipy = tensor_dipy[:, :, :, np.newaxis, :] return tensor_dipy elif to_format.lower() == "dipy": return tensor_dipy tensor_reordered = tensor_dipy[..., tensor_order[to_format.lower()][1]] return tensor_reordered