def test_diffusivities(): psphere = get_sphere('symmetric362') bvecs = np.concatenate(([[0, 0, 0]], psphere.vertices)) bvals = np.zeros(len(bvecs)) + 1000 bvals[0] = 0 gtab = grad.gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0001], [0.0015, 0.0003, 0.0003])) mevecs = [np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]), np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]])] S = single_tensor(gtab, 100, mevals[0], mevecs[0], snr=None) dm = dti.TensorModel(gtab, 'LS') dmfit = dm.fit(S) md = mean_diffusivity(dmfit.evals) Trace = trace(dmfit.evals) rd = radial_diffusivity(dmfit.evals) ad = axial_diffusivity(dmfit.evals) lin = linearity(dmfit.evals) plan = planarity(dmfit.evals) spher = sphericity(dmfit.evals) assert_almost_equal(md, (0.0015 + 0.0003 + 0.0001) / 3) assert_almost_equal(Trace, (0.0015 + 0.0003 + 0.0001)) assert_almost_equal(ad, 0.0015) assert_almost_equal(rd, (0.0003 + 0.0001) / 2) assert_almost_equal(lin, (0.0015 - 0.0003)/Trace) assert_almost_equal(plan, 2 * (0.0003 - 0.0001)/Trace) assert_almost_equal(spher, (3 * 0.0001)/Trace)
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix): """ Compute DTI. :param fname_in: input 4d file. :param bvals: bvals txt file :param bvecs: bvecs txt file :param prefix: output prefix. Example: "dti_" :return: True/False """ # Open file. from msct_image import Image nii = Image(fname_in) data = nii.data print('data.shape (%d, %d, %d, %d)' % data.shape) # open bvecs/bvals from dipy.io import read_bvals_bvecs bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs) from dipy.core.gradients import gradient_table gtab = gradient_table(bvals, bvecs) # # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image. # from dipy.segment.mask import median_otsu # maskdata, mask = median_otsu(data, 3, 1, True, vol_idx=range(10, 50), dilate=2) # print('maskdata.shape (%d, %d, %d, %d)' % maskdata.shape) # fit tensor model import dipy.reconst.dti as dti tenmodel = dti.TensorModel(gtab) tenfit = tenmodel.fit(data) # Compute metrics printv('Computing metrics...', param.verbose) # FA from dipy.reconst.dti import fractional_anisotropy nii.data = fractional_anisotropy(tenfit.evals) nii.setFileName(prefix + 'FA.nii.gz') nii.save('float32') # MD from dipy.reconst.dti import mean_diffusivity nii.data = mean_diffusivity(tenfit.evals) nii.setFileName(prefix + 'MD.nii.gz') nii.save('float32') # RD from dipy.reconst.dti import radial_diffusivity nii.data = radial_diffusivity(tenfit.evals) nii.setFileName(prefix + 'RD.nii.gz') nii.save('float32') # AD from dipy.reconst.dti import axial_diffusivity nii.data = axial_diffusivity(tenfit.evals) nii.setFileName(prefix + 'AD.nii.gz') nii.save('float32') return True
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix): """ Compute DTI. :param fname_in: input 4d file. :param bvals: bvals txt file :param bvecs: bvecs txt file :param prefix: output prefix. Example: "dti_" :return: True/False """ # Open file. from msct_image import Image nii = Image(fname_in) data = nii.data print('data.shape (%d, %d, %d, %d)' % data.shape) # open bvecs/bvals from dipy.io import read_bvals_bvecs bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs) from dipy.core.gradients import gradient_table gtab = gradient_table(bvals, bvecs) # # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image. # from dipy.segment.mask import median_otsu # maskdata, mask = median_otsu(data, 3, 1, True, vol_idx=range(10, 50), dilate=2) # print('maskdata.shape (%d, %d, %d, %d)' % maskdata.shape) # fit tensor model import dipy.reconst.dti as dti tenmodel = dti.TensorModel(gtab) tenfit = tenmodel.fit(data) # Compute metrics printv('Computing metrics...', param.verbose) # FA from dipy.reconst.dti import fractional_anisotropy nii.data = fractional_anisotropy(tenfit.evals) nii.setFileName(prefix+'FA.nii.gz') nii.save('float32') # MD from dipy.reconst.dti import mean_diffusivity nii.data = mean_diffusivity(tenfit.evals) nii.setFileName(prefix+'MD.nii.gz') nii.save('float32') # RD from dipy.reconst.dti import radial_diffusivity nii.data = radial_diffusivity(tenfit.evals) nii.setFileName(prefix+'RD.nii.gz') nii.save('float32') # AD from dipy.reconst.dti import axial_diffusivity nii.data = axial_diffusivity(tenfit.evals) nii.setFileName(prefix+'AD.nii.gz') nii.save('float32') return True
def test_single_voxel_DKI_stats(): # tests if AK and RK are equal to expected values for a single fiber # simulate randomly oriented ADi = 0.00099 ADe = 0.00226 RDi = 0 RDe = 0.00087 # Reference values AD = fie * ADi + (1 - fie) * ADe AK = 3 * fie * (1 - fie) * ((ADi - ADe) / AD)**2 RD = fie * RDi + (1 - fie) * RDe RK = 3 * fie * (1 - fie) * ((RDi - RDe) / RD)**2 ref_vals = np.array([AD, AK, RD, RK]) # simulate fiber randomly oriented theta = random.uniform(0, 180) phi = random.uniform(0, 320) angles = [(theta, phi), (theta, phi)] mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]]) frac = [fie * 100, (1 - fie) * 100] signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, S0=100, angles=angles, fractions=frac, snr=None) evals, evecs = decompose_tensor(from_lower_triangular(dt)) dki_par = np.concatenate((evals, evecs[0], evecs[1], evecs[2], kt), axis=0) # Estimates using dki functions ADe1 = dti.axial_diffusivity(evals) RDe1 = dti.radial_diffusivity(evals) AKe1 = axial_kurtosis(dki_par) RKe1 = radial_kurtosis(dki_par) e1_vals = np.array([ADe1, AKe1, RDe1, RKe1]) assert_array_almost_equal(e1_vals, ref_vals) # Estimates using the kurtosis class object dkiM = dki.DiffusionKurtosisModel(gtab_2s) dkiF = dkiM.fit(signal) e2_vals = np.array([dkiF.ad, dkiF.ak(), dkiF.rd, dkiF.rk()]) assert_array_almost_equal(e2_vals, ref_vals) # test MK (note this test correspond to the MK singularity L2==L3) MK_as = dkiF.mk() sph = Sphere(xyz=gtab.bvecs[gtab.bvals > 0]) MK_nm = np.mean(dkiF.akc(sph)) assert_array_almost_equal(MK_as, MK_nm, decimal=1)
def hindered_rd(self): """ Returns the radial diffusivity of the hindered compartment. Note ----- The hindered diffusion tensor can be seem as the tissue's extra-cellular diffusion compartment [1]_. References ---------- .. [1] Fieremans, E., Jensen, J.H., Helpern, J.A., 2011. White Matter Characterization with Diffusion Kurtosis Imaging. Neuroimage 58(1): 177-188. doi:10.1016/j.neuroimage.2011.06.006 """ return radial_diffusivity(self.hindered_evals)
def hindered_rd(self): """ Returns the radial diffusivity of the hindered compartment. Notes ----- The hindered diffusion tensor can be seem as the tissue's extra-cellular diffusion compartment [1]_. References ---------- .. [1] Fieremans, E., Jensen, J.H., Helpern, J.A., 2011. White Matter Characterization with Diffusion Kurtosis Imaging. Neuroimage 58(1): 177-188. doi:10.1016/j.neuroimage.2011.06.006 """ return radial_diffusivity(self.hindered_evals)
def test_single_voxel_DKI_stats(): # tests if AK and RK are equal to expected values for a single fiber # simulate randomly oriented ADi = 0.00099 ADe = 0.00226 RDi = 0 RDe = 0.00087 # Reference values AD = fie * ADi + (1 - fie) * ADe AK = 3 * fie * (1 - fie) * ((ADi-ADe) / AD) ** 2 RD = fie * RDi + (1 - fie) * RDe RK = 3 * fie * (1 - fie) * ((RDi-RDe) / RD) ** 2 ref_vals = np.array([AD, AK, RD, RK]) # simulate fiber randomly oriented theta = random.uniform(0, 180) phi = random.uniform(0, 320) angles = [(theta, phi), (theta, phi)] mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]]) frac = [fie * 100, (1 - fie) * 100] signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, S0=100, angles=angles, fractions=frac, snr=None) evals, evecs = decompose_tensor(from_lower_triangular(dt)) dki_par = np.concatenate((evals, evecs[0], evecs[1], evecs[2], kt), axis=0) # Estimates using dki functions ADe1 = dti.axial_diffusivity(evals) RDe1 = dti.radial_diffusivity(evals) AKe1 = axial_kurtosis(dki_par) RKe1 = radial_kurtosis(dki_par) e1_vals = np.array([ADe1, AKe1, RDe1, RKe1]) assert_array_almost_equal(e1_vals, ref_vals) # Estimates using the kurtosis class object dkiM = dki.DiffusionKurtosisModel(gtab_2s) dkiF = dkiM.fit(signal) e2_vals = np.array([dkiF.ad, dkiF.ak(), dkiF.rd, dkiF.rk()]) assert_array_almost_equal(e2_vals, ref_vals) # test MK (note this test correspond to the MK singularity L2==L3) MK_as = dkiF.mk() sph = Sphere(xyz=gtab.bvecs[gtab.bvals > 0]) MK_nm = np.mean(dkiF.akc(sph)) assert_array_almost_equal(MK_as, MK_nm, decimal=1)
def calculate_scalars(tensor_data, mask): ''' Calculate the scalar images from the tensor returns: FA, MD, TR, AX, RAD ''' mask = np.asarray(mask, dtype=np.bool) shape = mask.shape data = dti.from_lower_triangular(tensor_data[mask]) w, v = dti.decompose_tensor(data) w = np.squeeze(w) v = np.squeeze(v) md = np.zeros(shape) md[mask] = dti.mean_diffusivity(w, axis=-1) fa = np.zeros(shape) fa[mask] = dti.fractional_anisotropy(w, axis=-1) tr = np.zeros(shape) tr[mask] = dti.trace(w, axis=-1) ax = np.zeros(shape) ax[mask] = dti.axial_diffusivity(w, axis=-1) rad = np.zeros(shape) rad[mask] = dti.radial_diffusivity(w, axis=-1) return fa, md, tr, ax, rad
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix, method, file_mask): """ Compute DTI. :param fname_in: input 4d file. :param bvals: bvals txt file :param bvecs: bvecs txt file :param prefix: output prefix. Example: "dti_" :param method: algo for computing dti :return: True/False """ # Open file. from msct_image import Image nii = Image(fname_in) data = nii.data print('data.shape (%d, %d, %d, %d)' % data.shape) # open bvecs/bvals from dipy.io import read_bvals_bvecs bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs) from dipy.core.gradients import gradient_table gtab = gradient_table(bvals, bvecs) # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image. if not file_mask == '': printv('Open mask file...', param.verbose) # open mask file nii_mask = Image(file_mask) mask = nii_mask.data # fit tensor model printv('Computing tensor using "'+method+'" method...', param.verbose) import dipy.reconst.dti as dti if method == 'standard': tenmodel = dti.TensorModel(gtab) if file_mask == '': tenfit = tenmodel.fit(data) else: tenfit = tenmodel.fit(data, mask) elif method == 'restore': import dipy.denoise.noise_estimate as ne sigma = ne.estimate_sigma(data) dti_restore = dti.TensorModel(gtab, fit_method='RESTORE', sigma=sigma) if file_mask == '': tenfit = dti_restore.fit(data) else: tenfit = dti_restore.fit(data, mask) # Compute metrics printv('Computing metrics...', param.verbose) # FA from dipy.reconst.dti import fractional_anisotropy nii.data = fractional_anisotropy(tenfit.evals) nii.setFileName(prefix+'FA.nii.gz') nii.save('float32') # MD from dipy.reconst.dti import mean_diffusivity nii.data = mean_diffusivity(tenfit.evals) nii.setFileName(prefix+'MD.nii.gz') nii.save('float32') # RD from dipy.reconst.dti import radial_diffusivity nii.data = radial_diffusivity(tenfit.evals) nii.setFileName(prefix+'RD.nii.gz') nii.save('float32') # AD from dipy.reconst.dti import axial_diffusivity nii.data = axial_diffusivity(tenfit.evals) nii.setFileName(prefix+'AD.nii.gz') nii.save('float32') return True
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix, method, file_mask): """ Compute DTI. :param fname_in: input 4d file. :param bvals: bvals txt file :param bvecs: bvecs txt file :param prefix: output prefix. Example: "dti_" :param method: algo for computing dti :return: True/False """ # Open file. from msct_image import Image nii = Image(fname_in) data = nii.data sct.printv('data.shape (%d, %d, %d, %d)' % data.shape) # open bvecs/bvals from dipy.io import read_bvals_bvecs bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs) from dipy.core.gradients import gradient_table gtab = gradient_table(bvals, bvecs) # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image. if not file_mask == '': sct.printv('Open mask file...', param.verbose) # open mask file nii_mask = Image(file_mask) mask = nii_mask.data # fit tensor model sct.printv('Computing tensor using "' + method + '" method...', param.verbose) import dipy.reconst.dti as dti if method == 'standard': tenmodel = dti.TensorModel(gtab) if file_mask == '': tenfit = tenmodel.fit(data) else: tenfit = tenmodel.fit(data, mask) elif method == 'restore': import dipy.denoise.noise_estimate as ne sigma = ne.estimate_sigma(data) dti_restore = dti.TensorModel(gtab, fit_method='RESTORE', sigma=sigma) if file_mask == '': tenfit = dti_restore.fit(data) else: tenfit = dti_restore.fit(data, mask) # Compute metrics sct.printv('Computing metrics...', param.verbose) # FA from dipy.reconst.dti import fractional_anisotropy nii.data = fractional_anisotropy(tenfit.evals) nii.setFileName(prefix + 'FA.nii.gz') nii.save('float32') # MD from dipy.reconst.dti import mean_diffusivity nii.data = mean_diffusivity(tenfit.evals) nii.setFileName(prefix + 'MD.nii.gz') nii.save('float32') # RD from dipy.reconst.dti import radial_diffusivity nii.data = radial_diffusivity(tenfit.evals) nii.setFileName(prefix + 'RD.nii.gz') nii.save('float32') # AD from dipy.reconst.dti import axial_diffusivity nii.data = axial_diffusivity(tenfit.evals) nii.setFileName(prefix + 'AD.nii.gz') nii.save('float32') return True
def main(): parser = _build_args_parser() args = parser.parse_args() if not args.not_all: args.fa = args.fa or 'fa.nii.gz' args.ga = args.ga or 'ga.nii.gz' args.rgb = args.rgb or 'rgb.nii.gz' args.md = args.md or 'md.nii.gz' args.ad = args.ad or 'ad.nii.gz' args.rd = args.rd or 'rd.nii.gz' args.mode = args.mode or 'mode.nii.gz' args.norm = args.norm or 'tensor_norm.nii.gz' args.tensor = args.tensor or 'tensor.nii.gz' args.evecs = args.evecs or 'tensor_evecs.nii.gz' args.evals = args.evals or 'tensor_evals.nii.gz' args.residual = args.residual or 'dti_residual.nii.gz' args.p_i_signal =\ args.p_i_signal or 'physically_implausible_signals_mask.nii.gz' args.pulsation = args.pulsation or 'pulsation_and_misalignment.nii.gz' outputs = [args.fa, args.ga, args.rgb, args.md, args.ad, args.rd, args.mode, args.norm, args.tensor, args.evecs, args.evals, args.residual, args.p_i_signal, args.pulsation] if args.not_all and not any(outputs): parser.error('When using --not_all, you need to specify at least ' + 'one metric to output.') assert_inputs_exist( parser, [args.input, args.bvals, args.bvecs], args.mask) assert_outputs_exist(parser, args, outputs) img = nib.load(args.input) data = img.get_data() affine = img.get_affine() if args.mask is None: mask = None else: mask = nib.load(args.mask).get_data().astype(np.bool) # Validate bvals and bvecs logging.info('Tensor estimation with the %s method...', args.method) bvals, bvecs = read_bvals_bvecs(args.bvals, args.bvecs) if not is_normalized_bvecs(bvecs): logging.warning('Your b-vectors do not seem normalized...') bvecs = normalize_bvecs(bvecs) check_b0_threshold(args, bvals.min()) gtab = gradient_table(bvals, bvecs, b0_threshold=bvals.min()) # Get tensors if args.method == 'restore': sigma = ne.estimate_sigma(data) tenmodel = TensorModel(gtab, fit_method=args.method, sigma=sigma, min_signal=_get_min_nonzero_signal(data)) else: tenmodel = TensorModel(gtab, fit_method=args.method, min_signal=_get_min_nonzero_signal(data)) tenfit = tenmodel.fit(data, mask) FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if args.tensor: # Get the Tensor values and format them for visualisation # in the Fibernavigator. tensor_vals = lower_triangular(tenfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] fiber_tensors = nib.Nifti1Image( tensor_vals_reordered.astype(np.float32), affine) nib.save(fiber_tensors, args.tensor) if args.fa: fa_img = nib.Nifti1Image(FA.astype(np.float32), affine) nib.save(fa_img, args.fa) if args.ga: GA = geodesic_anisotropy(tenfit.evals) GA[np.isnan(GA)] = 0 ga_img = nib.Nifti1Image(GA.astype(np.float32), affine) nib.save(ga_img, args.ga) if args.rgb: RGB = color_fa(FA, tenfit.evecs) rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine) nib.save(rgb_img, args.rgb) if args.md: MD = mean_diffusivity(tenfit.evals) md_img = nib.Nifti1Image(MD.astype(np.float32), affine) nib.save(md_img, args.md) if args.ad: AD = axial_diffusivity(tenfit.evals) ad_img = nib.Nifti1Image(AD.astype(np.float32), affine) nib.save(ad_img, args.ad) if args.rd: RD = radial_diffusivity(tenfit.evals) rd_img = nib.Nifti1Image(RD.astype(np.float32), affine) nib.save(rd_img, args.rd) if args.mode: # Compute tensor mode inter_mode = dipy_mode(tenfit.quadratic_form) # Since the mode computation can generate NANs when not masked, # we need to remove them. non_nan_indices = np.isfinite(inter_mode) mode = np.zeros(inter_mode.shape) mode[non_nan_indices] = inter_mode[non_nan_indices] mode_img = nib.Nifti1Image(mode.astype(np.float32), affine) nib.save(mode_img, args.mode) if args.norm: NORM = norm(tenfit.quadratic_form) norm_img = nib.Nifti1Image(NORM.astype(np.float32), affine) nib.save(norm_img, args.norm) if args.evecs: evecs = tenfit.evecs.astype(np.float32) evecs_img = nib.Nifti1Image(evecs, affine) nib.save(evecs_img, args.evecs) # save individual e-vectors also e1_img = nib.Nifti1Image(evecs[..., 0], affine) e2_img = nib.Nifti1Image(evecs[..., 1], affine) e3_img = nib.Nifti1Image(evecs[..., 2], affine) nib.save(e1_img, add_filename_suffix(args.evecs, '_v1')) nib.save(e2_img, add_filename_suffix(args.evecs, '_v2')) nib.save(e3_img, add_filename_suffix(args.evecs, '_v3')) if args.evals: evals = tenfit.evals.astype(np.float32) evals_img = nib.Nifti1Image(evals, affine) nib.save(evals_img, args.evals) # save individual e-values also e1_img = nib.Nifti1Image(evals[..., 0], affine) e2_img = nib.Nifti1Image(evals[..., 1], affine) e3_img = nib.Nifti1Image(evals[..., 2], affine) nib.save(e1_img, add_filename_suffix(args.evals, '_e1')) nib.save(e2_img, add_filename_suffix(args.evals, '_e2')) nib.save(e3_img, add_filename_suffix(args.evals, '_e3')) if args.p_i_signal: S0 = np.mean(data[..., gtab.b0s_mask], axis=-1, keepdims=True) DWI = data[..., ~gtab.b0s_mask] pis_mask = np.max(S0 < DWI, axis=-1) if args.mask is not None: pis_mask *= mask pis_img = nib.Nifti1Image(pis_mask.astype(np.int16), affine) nib.save(pis_img, args.p_i_signal) if args.pulsation: STD = np.std(data[..., ~gtab.b0s_mask], axis=-1) if args.mask is not None: STD *= mask std_img = nib.Nifti1Image(STD.astype(np.float32), affine) nib.save(std_img, add_filename_suffix(args.pulsation, '_std_dwi')) if np.sum(gtab.b0s_mask) <= 1: logger.info('Not enough b=0 images to output standard ' 'deviation map') else: if len(np.where(gtab.b0s_mask)) == 2: logger.info('Only two b=0 images. Be careful with the ' 'interpretation of this std map') STD = np.std(data[..., gtab.b0s_mask], axis=-1) if args.mask is not None: STD *= mask std_img = nib.Nifti1Image(STD.astype(np.float32), affine) nib.save(std_img, add_filename_suffix(args.pulsation, '_std_b0')) if args.residual: # Mean residual image S0 = np.mean(data[..., gtab.b0s_mask], axis=-1) data_p = tenfit.predict(gtab, S0) R = np.mean(np.abs(data_p[..., ~gtab.b0s_mask] - data[..., ~gtab.b0s_mask]), axis=-1) if args.mask is not None: R *= mask R_img = nib.Nifti1Image(R.astype(np.float32), affine) nib.save(R_img, args.residual) # Each volume's residual statistics if args.mask is None: logger.info("Outlier detection will not be performed, since no " "mask was provided.") stats = [dict.fromkeys(['label', 'mean', 'iqr', 'cilo', 'cihi', 'whishi', 'whislo', 'fliers', 'q1', 'med', 'q3'], []) for i in range(data.shape[-1])] # stats with format for boxplots # Note that stats will be computed manually and plotted using bxp # but could be computed using stats = cbook.boxplot_stats # or pyplot.boxplot(x) R_k = np.zeros(data.shape[-1]) # mean residual per DWI std = np.zeros(data.shape[-1]) # std residual per DWI q1 = np.zeros(data.shape[-1]) # first quartile per DWI q3 = np.zeros(data.shape[-1]) # third quartile per DWI iqr = np.zeros(data.shape[-1]) # interquartile per DWI percent_outliers = np.zeros(data.shape[-1]) nb_voxels = np.count_nonzero(mask) for k in range(data.shape[-1]): x = np.abs(data_p[..., k] - data[..., k])[mask] R_k[k] = np.mean(x) std[k] = np.std(x) q3[k], q1[k] = np.percentile(x, [75, 25]) iqr[k] = q3[k] - q1[k] stats[k]['med'] = (q1[k] + q3[k]) / 2 stats[k]['mean'] = R_k[k] stats[k]['q1'] = q1[k] stats[k]['q3'] = q3[k] stats[k]['whislo'] = q1[k] - 1.5 * iqr[k] stats[k]['whishi'] = q3[k] + 1.5 * iqr[k] stats[k]['label'] = k # Outliers are observations that fall below Q1 - 1.5(IQR) or # above Q3 + 1.5(IQR) We check if a voxel is an outlier only if # we have a mask, else we are biased. if args.mask is not None: outliers = (x < stats[k]['whislo']) | (x > stats[k]['whishi']) percent_outliers[k] = np.sum(outliers)/nb_voxels*100 # What would be our definition of too many outliers? # Maybe mean(all_means)+-3SD? # Or we let people choose based on the figure. # if percent_outliers[k] > ???? : # logger.warning(' Careful! Diffusion-Weighted Image' # ' i=%s has %s %% outlier voxels', # k, percent_outliers[k]) # Saving all statistics as npy values residual_basename, _ = split_name_with_nii(args.residual) res_stats_basename = residual_basename + ".npy" np.save(add_filename_suffix( res_stats_basename, "_mean_residuals"), R_k) np.save(add_filename_suffix(res_stats_basename, "_q1_residuals"), q1) np.save(add_filename_suffix(res_stats_basename, "_q3_residuals"), q3) np.save(add_filename_suffix(res_stats_basename, "_iqr_residuals"), iqr) np.save(add_filename_suffix(res_stats_basename, "_std_residuals"), std) # Showing results in graph if args.mask is None: fig, axe = plt.subplots(nrows=1, ncols=1, squeeze=False) else: fig, axe = plt.subplots(nrows=1, ncols=2, squeeze=False, figsize=[10, 4.8]) # Default is [6.4, 4.8]. Increasing width to see better. medianprops = dict(linestyle='-', linewidth=2.5, color='firebrick') meanprops = dict(linestyle='-', linewidth=2.5, color='green') axe[0, 0].bxp(stats, showmeans=True, meanline=True, showfliers=False, medianprops=medianprops, meanprops=meanprops) axe[0, 0].set_xlabel('DW image') axe[0, 0].set_ylabel('Residuals per DWI volume. Red is median,\n' 'green is mean. Whiskers are 1.5*interquartile') axe[0, 0].set_title('Residuals') axe[0, 0].set_xticks(range(0, q1.shape[0], 5)) axe[0, 0].set_xticklabels(range(0, q1.shape[0], 5)) if args.mask is not None: axe[0, 1].plot(range(data.shape[-1]), percent_outliers) axe[0, 1].set_xticks(range(0, q1.shape[0], 5)) axe[0, 1].set_xticklabels(range(0, q1.shape[0], 5)) axe[0, 1].set_xlabel('DW image') axe[0, 1].set_ylabel('Percentage of outlier voxels') axe[0, 1].set_title('Outliers') plt.savefig(residual_basename + '_residuals_stats.png')
def run(self, input_files, bvalues_files, bvectors_files, mask_files, b0_threshold=50, bvecs_tol=0.01, save_metrics=[], out_dir='', out_tensor='tensors.nii.gz', out_fa='fa.nii.gz', out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz', out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz', out_evec='evecs.nii.gz', out_eval='evals.nii.gz', nifti_tensor=True): """ Workflow for tensor reconstruction and for computing DTI metrics. using Weighted Least-Squares. Performs a tensor reconstruction on the files by 'globing' ``input_files`` and saves the DTI metrics in a directory specified by ``out_dir``. Parameters ---------- input_files : string Path to the input volumes. This path may contain wildcards to process multiple inputs at once. bvalues_files : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. bvectors_files : string Path to the bvectors files. This path may contain wildcards to use multiple bvectors files at once. mask_files : string Path to the input masks. This path may contain wildcards to use multiple masks at once. b0_threshold : float, optional Threshold used to find b0 volumes. bvecs_tol : float, optional Threshold used to check that norm(bvec) = 1 +/- bvecs_tol b-vectors are unit vectors. save_metrics : variable string, optional List of metrics to save. Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval out_dir : string, optional Output directory. (default current directory) out_tensor : string, optional Name of the tensors volume to be saved. Per default, this will be saved following the nifti standard: with the tensor elements as Dxx, Dxy, Dyy, Dxz, Dyz, Dzz on the last (5th) dimension of the volume (shape: (i, j, k, 1, 6)). If `nifti_tensor` is False, this will be saved in an alternate format that is used by other software (e.g., FSL): a 4-dimensional volume (shape (i, j, k, 6)) with Dxx, Dxy, Dxz, Dyy, Dyz, Dzz on the last dimension. out_fa : string, optional Name of the fractional anisotropy volume to be saved. out_ga : string, optional Name of the geodesic anisotropy volume to be saved. out_rgb : string, optional Name of the color fa volume to be saved. out_md : string, optional Name of the mean diffusivity volume to be saved. out_ad : string, optional Name of the axial diffusivity volume to be saved. out_rd : string, optional Name of the radial diffusivity volume to be saved. out_mode : string, optional Name of the mode volume to be saved. out_evec : string, optional Name of the eigenvectors volume to be saved. out_eval : string, optional Name of the eigenvalues to be saved. nifti_tensor : bool, optional Whether the tensor is saved in the standard Nifti format or in an alternate format that is used by other software (e.g., FSL): a 4-dimensional volume (shape (i, j, k, 6)) with Dxx, Dxy, Dxz, Dyy, Dyz, Dzz on the last dimension. References ---------- .. [1] Basser, P.J., Mattiello, J., LeBihan, D., 1994. Estimation of the effective self-diffusion tensor from the NMR spin echo. J Magn Reson B 103, 247-254. .. [2] Basser, P., Pierpaoli, C., 1996. Microstructural and physiological features of tissues elucidated by quantitative diffusion-tensor MRI. Journal of Magnetic Resonance 111, 209-219. .. [3] Lin-Ching C., Jones D.K., Pierpaoli, C. 2005. RESTORE: Robust estimation of tensors by outlier rejection. MRM 53: 1088-1095 .. [4] hung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap approaches for estimation of uncertainties of DTI parameters. NeuroImage 33, 531-541. """ io_it = self.get_io_iterator() for dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, \ omode, oevecs, oevals in io_it: logging.info('Computing DTI metrics for {0}'.format(dwi)) data, affine = load_nifti(dwi) if mask is not None: mask = load_nifti_data(mask).astype(bool) tenfit, _ = self.get_fitted_tensor(data, mask, bval, bvec, b0_threshold, bvecs_tol) if not save_metrics: save_metrics = [ 'fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode', 'evec', 'eval', 'tensor' ] FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if 'tensor' in save_metrics: tensor_vals = lower_triangular(tenfit.quadratic_form) if nifti_tensor: ten_img = nifti1_symmat(tensor_vals, affine=affine) else: alt_order = [0, 1, 3, 2, 4, 5] ten_img = nib.Nifti1Image( tensor_vals[..., alt_order].astype(np.float32), affine) nib.save(ten_img, otensor) if 'fa' in save_metrics: save_nifti(ofa, FA.astype(np.float32), affine) if 'ga' in save_metrics: GA = geodesic_anisotropy(tenfit.evals) save_nifti(oga, GA.astype(np.float32), affine) if 'rgb' in save_metrics: RGB = color_fa(FA, tenfit.evecs) save_nifti(orgb, np.array(255 * RGB, 'uint8'), affine) if 'md' in save_metrics: MD = mean_diffusivity(tenfit.evals) save_nifti(omd, MD.astype(np.float32), affine) if 'ad' in save_metrics: AD = axial_diffusivity(tenfit.evals) save_nifti(oad, AD.astype(np.float32), affine) if 'rd' in save_metrics: RD = radial_diffusivity(tenfit.evals) save_nifti(orad, RD.astype(np.float32), affine) if 'mode' in save_metrics: MODE = get_mode(tenfit.quadratic_form) save_nifti(omode, MODE.astype(np.float32), affine) if 'evec' in save_metrics: save_nifti(oevecs, tenfit.evecs.astype(np.float32), affine) if 'eval' in save_metrics: save_nifti(oevals, tenfit.evals.astype(np.float32), affine) dname_ = os.path.dirname(oevals) if dname_ == '': logging.info('DTI metrics saved in current directory') else: logging.info('DTI metrics saved in {0}'.format(dname_))
def main(): parser = buildArgsParser() args = parser.parse_args() # Load data img = nib.load(args.input) data = img.get_data() affine = img.get_affine() # Setting suffix savename if args.savename is None: filename = "" else: filename = args.savename + "_" if os.path.exists(filename + 'fa.nii.gz'): if not args.overwrite: raise ValueError("File " + filename + "fa.nii.gz" + " already exists. Use -f option to overwrite.") print (filename + "fa.nii.gz", " already exists and will be overwritten.") if args.mask is not None: mask = nib.load(args.mask).get_data() else: print("No mask specified. Computing mask with median_otsu.") data, mask = median_otsu(data) mask_img = nib.Nifti1Image(mask.astype(np.float32), affine) nib.save(mask_img, filename + 'mask.nii.gz') # Get tensors print('Tensor estimation...') b_vals, b_vecs = read_bvals_bvecs(args.bvals, args.bvecs) gtab = gradient_table_from_bvals_bvecs(b_vals, b_vecs) tenmodel = TensorModel(gtab) tenfit = tenmodel.fit(data, mask) # FA print('Computing FA...') FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 # RGB print('Computing RGB...') FA = np.clip(FA, 0, 1) RGB = color_fa(FA, tenfit.evecs) if args.all : print('Computing Diffusivities...') # diffusivities MD = mean_diffusivity(tenfit.evals) AD = axial_diffusivity(tenfit.evals) RD = radial_diffusivity(tenfit.evals) print('Computing Mode...') MODE = mode(tenfit.quadratic_form) print('Saving tensor coefficients and metrics...') # Get the Tensor values and format them for visualisation in the Fibernavigator. tensor_vals = lower_triangular(tenfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] fiber_tensors = nib.Nifti1Image(tensor_vals_reordered.astype(np.float32), affine) nib.save(fiber_tensors, filename + 'tensors.nii.gz') # Save - for some reason this is not read properly by the FiberNav md_img = nib.Nifti1Image(MD.astype(np.float32), affine) nib.save(md_img, filename + 'md.nii.gz') ad_img = nib.Nifti1Image(AD.astype(np.float32), affine) nib.save(ad_img, filename + 'ad.nii.gz') rd_img = nib.Nifti1Image(RD.astype(np.float32), affine) nib.save(rd_img, filename + 'rd.nii.gz') mode_img = nib.Nifti1Image(MODE.astype(np.float32), affine) nib.save(mode_img, filename + 'mode.nii.gz') fa_img = nib.Nifti1Image(FA.astype(np.float32), affine) nib.save(fa_img, filename + 'fa.nii.gz') rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine) nib.save(rgb_img, filename + 'rgb.nii.gz')
def run(self, input_files, bvalues_files, bvectors_files, mask_files, b0_threshold=50, bvecs_tol=0.01, save_metrics=[], out_dir='', out_tensor='tensors.nii.gz', out_fa='fa.nii.gz', out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz', out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz', out_evec='evecs.nii.gz', out_eval='evals.nii.gz'): """ Workflow for tensor reconstruction and for computing DTI metrics. using Weighted Least-Squares. Performs a tensor reconstruction on the files by 'globing' ``input_files`` and saves the DTI metrics in a directory specified by ``out_dir``. Parameters ---------- input_files : string Path to the input volumes. This path may contain wildcards to process multiple inputs at once. bvalues_files : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. bvectors_files : string Path to the bvectors files. This path may contain wildcards to use multiple bvectors files at once. mask_files : string Path to the input masks. This path may contain wildcards to use multiple masks at once. (default: No mask used) b0_threshold : float, optional Threshold used to find b=0 directions (default 0.0) bvecs_tol : float, optional Threshold used to check that norm(bvec) = 1 +/- bvecs_tol b-vectors are unit vectors (default 0.01) save_metrics : variable string, optional List of metrics to save. Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval (default [] (all)) out_dir : string, optional Output directory (default input file directory) out_tensor : string, optional Name of the tensors volume to be saved (default 'tensors.nii.gz') out_fa : string, optional Name of the fractional anisotropy volume to be saved (default 'fa.nii.gz') out_ga : string, optional Name of the geodesic anisotropy volume to be saved (default 'ga.nii.gz') out_rgb : string, optional Name of the color fa volume to be saved (default 'rgb.nii.gz') out_md : string, optional Name of the mean diffusivity volume to be saved (default 'md.nii.gz') out_ad : string, optional Name of the axial diffusivity volume to be saved (default 'ad.nii.gz') out_rd : string, optional Name of the radial diffusivity volume to be saved (default 'rd.nii.gz') out_mode : string, optional Name of the mode volume to be saved (default 'mode.nii.gz') out_evec : string, optional Name of the eigenvectors volume to be saved (default 'evecs.nii.gz') out_eval : string, optional Name of the eigenvalues to be saved (default 'evals.nii.gz') References ---------- .. [1] Basser, P.J., Mattiello, J., LeBihan, D., 1994. Estimation of the effective self-diffusion tensor from the NMR spin echo. J Magn Reson B 103, 247-254. .. [2] Basser, P., Pierpaoli, C., 1996. Microstructural and physiological features of tissues elucidated by quantitative diffusion-tensor MRI. Journal of Magnetic Resonance 111, 209-219. .. [3] Lin-Ching C., Jones D.K., Pierpaoli, C. 2005. RESTORE: Robust estimation of tensors by outlier rejection. MRM 53: 1088-1095 .. [4] hung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap approaches for estimation of uncertainties of DTI parameters. NeuroImage 33, 531-541. """ io_it = self.get_io_iterator() for dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, \ omode, oevecs, oevals in io_it: logging.info('Computing DTI metrics for {0}'.format(dwi)) data, affine = load_nifti(dwi) if mask is not None: mask = nib.load(mask).get_data().astype(np.bool) tenfit, _ = self.get_fitted_tensor(data, mask, bval, bvec, b0_threshold, bvecs_tol) if not save_metrics: save_metrics = ['fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode', 'evec', 'eval', 'tensor'] FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if 'tensor' in save_metrics: tensor_vals = lower_triangular(tenfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] save_nifti(otensor, tensor_vals_reordered.astype(np.float32), affine) if 'fa' in save_metrics: save_nifti(ofa, FA.astype(np.float32), affine) if 'ga' in save_metrics: GA = geodesic_anisotropy(tenfit.evals) save_nifti(oga, GA.astype(np.float32), affine) if 'rgb' in save_metrics: RGB = color_fa(FA, tenfit.evecs) save_nifti(orgb, np.array(255 * RGB, 'uint8'), affine) if 'md' in save_metrics: MD = mean_diffusivity(tenfit.evals) save_nifti(omd, MD.astype(np.float32), affine) if 'ad' in save_metrics: AD = axial_diffusivity(tenfit.evals) save_nifti(oad, AD.astype(np.float32), affine) if 'rd' in save_metrics: RD = radial_diffusivity(tenfit.evals) save_nifti(orad, RD.astype(np.float32), affine) if 'mode' in save_metrics: MODE = get_mode(tenfit.quadratic_form) save_nifti(omode, MODE.astype(np.float32), affine) if 'evec' in save_metrics: save_nifti(oevecs, tenfit.evecs.astype(np.float32), affine) if 'eval' in save_metrics: save_nifti(oevals, tenfit.evals.astype(np.float32), affine) dname_ = os.path.dirname(oevals) if dname_ == '': logging.info('DTI metrics saved in current directory') else: logging.info( 'DTI metrics saved in {0}'.format(dname_))
gtab = cg.gradient_table(bvals, bvecs) # noise estimation from the b=0 sigma = ne.estimate_sigma(dataraw[:,:,:,bvals==0]) sigmamean=np.mean(sigma) # tensor computation using restore tenmodel=dti.TensorModel(gtab,fit_method='RESTORE', sigma=sigmamean) tenfit = tenmodel.fit(data) # Derivated measures from dipy.reconst.dti import fractional_anisotropy, mean_diffusivity, radial_diffusivity, axial_diffusivity,mode FA = fractional_anisotropy(tenfit.evals) MD = mean_diffusivity(tenfit.evals) AD = axial_diffusivity(tenfit.evals) RD = radial_diffusivity(tenfit.evals) MO = mode(tenfit.evecs) tenfit.evals[np.isnan(tenfit.evals)] = 0 evals1_img = nib.Nifti1Image(tenfit.evals[:,:,:,0].astype(np.float32), img.get_affine()) nib.save(evals1_img, output+'_restore_L1.nii.gz') evals2_img = nib.Nifti1Image(tenfit.evals[:,:,:,1].astype(np.float32), img.get_affine()) nib.save(evals2_img, output+'_restore_L2.nii.gz') evals3_img = nib.Nifti1Image(tenfit.evals[:,:,:,2].astype(np.float32), img.get_affine()) nib.save(evals3_img, output+'_restore_L3.nii.gz') tenfit.evecs[np.isnan(tenfit.evecs)] = 0 evecs_img1 = nib.Nifti1Image(tenfit.evecs[:,:,:,:,0].astype(np.float32), img.get_affine()) nib.save(evecs_img1, output+'_restore_V1.nii.gz') evecs_img2 = nib.Nifti1Image(tenfit.evecs[:,:,:,:,1].astype(np.float32), img.get_affine()) nib.save(evecs_img2, output+'_restore_V2.nii.gz')
def dmri_recon(sid, data_dir, out_dir, resolution, recon='csd', dirs='', num_threads=2): import tempfile #tempfile.tempdir = '/om/scratch/Fri/ksitek/' import os oldval = None if 'MKL_NUM_THREADS' in os.environ: oldval = os.environ['MKL_NUM_THREADS'] os.environ['MKL_NUM_THREADS'] = '%d' % num_threads ompoldval = None if 'OMP_NUM_THREADS' in os.environ: ompoldval = os.environ['OMP_NUM_THREADS'] os.environ['OMP_NUM_THREADS'] = '%d' % num_threads import nibabel as nib import numpy as np from glob import glob if resolution == '0.2mm': filename = 'Reg_S64550_nii4d.nii' #filename = 'angular_resample/dwi_%s.nii.gz'%dirs fimg = os.path.abspath(glob(os.path.join(data_dir, filename))[0]) else: filename = 'Reg_S64550_nii4d_resamp-%s.nii.gz' % (resolution) fimg = os.path.abspath( glob(os.path.join(data_dir, 'resample', filename))[0]) print("dwi file = %s" % fimg) fbval = os.path.abspath( glob(os.path.join(data_dir, 'bvecs', 'camino_120_RAS.bvals'))[0]) print("bval file = %s" % fbval) fbvec = os.path.abspath( glob(os.path.join(data_dir, 'bvecs', 'camino_120_RAS_flipped-xy.bvecs'))[0]) # 'angular_resample', # 'dwi_%s.bvecs'%dirs))[0]) print("bvec file = %s" % fbvec) img = nib.load(fimg) data = img.get_fdata() affine = img.get_affine() prefix = sid from dipy.io import read_bvals_bvecs bvals, bvecs = read_bvals_bvecs(fbval, fbvec) ''' from dipy.core.gradients import vector_norm b0idx = [] for idx, val in enumerate(bvals): if val < 1: pass #bvecs[idx] = [1, 0, 0] else: b0idx.append(idx) #print "b0idx=%d"%idx #print "input bvecs:" #print bvecs bvecs[b0idx, :] = bvecs[b0idx, :]/vector_norm(bvecs[b0idx])[:, None] #print "bvecs after normalization:" #print bvecs ''' from dipy.core.gradients import gradient_table gtab = gradient_table(bvals, bvecs) gtab.bvecs.shape == bvecs.shape gtab.bvecs gtab.bvals.shape == bvals.shape gtab.bvals #from dipy.segment.mask import median_otsu #b0_mask, mask = median_otsu(data[:, :, :, b0idx].mean(axis=3).squeeze(), 4, 4) if resolution == '0.2mm': mask_name = 'Reg_S64550_nii_b0-slice_mask.nii.gz' fmask1 = os.path.join(data_dir, mask_name) else: mask_name = 'Reg_S64550_nii_b0-slice_mask_resamp-%s.nii.gz' % ( resolution) fmask1 = os.path.join(data_dir, 'resample', mask_name) print("fmask file = %s" % fmask1) mask = nib.load(fmask1).get_fdata() ''' DTI model & save metrics ''' from dipy.reconst.dti import TensorModel print("running tensor model") tenmodel = TensorModel(gtab) tenfit = tenmodel.fit(data, mask) from dipy.reconst.dti import fractional_anisotropy print("running FA") FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 fa_img = nib.Nifti1Image(FA, img.get_affine()) tensor_fa_file = os.path.abspath('%s_tensor_fa.nii.gz' % (prefix)) nib.save(fa_img, tensor_fa_file) from dipy.reconst.dti import axial_diffusivity print("running AD") AD = axial_diffusivity(tenfit.evals) AD[np.isnan(AD)] = 0 ad_img = nib.Nifti1Image(AD, img.get_affine()) tensor_ad_file = os.path.abspath('%s_tensor_ad.nii.gz' % (prefix)) nib.save(ad_img, tensor_ad_file) from dipy.reconst.dti import radial_diffusivity print("running RD") RD = radial_diffusivity(tenfit.evals) RD[np.isnan(RD)] = 0 rd_img = nib.Nifti1Image(RD, img.get_affine()) tensor_rd_file = os.path.abspath('%s_tensor_rd.nii.gz' % (prefix)) nib.save(rd_img, tensor_rd_file) from dipy.reconst.dti import mean_diffusivity print("running MD") MD = mean_diffusivity(tenfit.evals) MD[np.isnan(MD)] = 0 md_img = nib.Nifti1Image(MD, img.get_affine()) tensor_md_file = os.path.abspath('%s_tensor_md.nii.gz' % (prefix)) nib.save(md_img, tensor_md_file) evecs = tenfit.evecs evec_img = nib.Nifti1Image(evecs, img.get_affine()) tensor_evec_file = os.path.abspath('%s_tensor_evec.nii.gz' % (prefix)) nib.save(evec_img, tensor_evec_file) ''' ODF model ''' useFA = True print("creating %s model" % recon) if recon == 'csd': from dipy.reconst.csdeconv import ConstrainedSphericalDeconvModel from dipy.reconst.csdeconv import auto_response response, ratio = auto_response(gtab, data, roi_radius=10, fa_thr=0.5) # 0.7 model = ConstrainedSphericalDeconvModel(gtab, response) useFA = True return_sh = True elif recon == 'csa': from dipy.reconst.shm import CsaOdfModel, normalize_data model = CsaOdfModel(gtab, sh_order=8) useFA = True return_sh = True elif recon == 'gqi': from dipy.reconst.gqi import GeneralizedQSamplingModel model = GeneralizedQSamplingModel(gtab) return_sh = False else: raise ValueError('only csd, csa supported currently') from dipy.reconst.dsi import (DiffusionSpectrumDeconvModel, DiffusionSpectrumModel) model = DiffusionSpectrumDeconvModel(gtab) '''reconstruct ODFs''' from dipy.data import get_sphere sphere = get_sphere('symmetric724') #odfs = fit.odf(sphere) # with CSD/GQI, uses > 50GB per core; don't get greedy with cores! from dipy.reconst.peaks import peaks_from_model print("running peaks_from_model") peaks = peaks_from_model( model=model, data=data, sphere=sphere, mask=mask, return_sh=return_sh, return_odf=False, normalize_peaks=True, npeaks=5, relative_peak_threshold=.5, min_separation_angle=10, #25, parallel=num_threads > 1, nbr_processes=num_threads) # save the peaks from dipy.io.peaks import save_peaks peaks_file = os.path.abspath('%s_peaks.pam5' % (prefix)) save_peaks(peaks_file, peaks) # save the spherical harmonics shm_coeff_file = os.path.abspath('%s_shm_coeff.nii.gz' % (prefix)) if return_sh: shm_coeff = peaks.shm_coeff nib.save(nib.Nifti1Image(shm_coeff, img.get_affine()), shm_coeff_file) else: # if it's not a spherical model, output it as an essentially null file np.savetxt(shm_coeff_file, [0]) # save the generalized fractional anisotropy image gfa_img = nib.Nifti1Image(peaks.gfa, img.get_affine()) model_gfa_file = os.path.abspath('%s_%s_gfa.nii.gz' % (prefix, recon)) nib.save(gfa_img, model_gfa_file) #from dipy.reconst.dti import quantize_evecs #peak_indices = quantize_evecs(tenfit.evecs, sphere.vertices) #eu = EuDX(FA, peak_indices, odf_vertices = sphere.vertices, #a_low=0.2, seeds=10**6, ang_thr=35) ''' probabilistic tracking ''' ''' from dipy.direction import ProbabilisticDirectionGetter from dipy.tracking.local import LocalTracking from dipy.tracking.streamline import Streamlines from dipy.io.streamline import save_trk prob_dg = ProbabilisticDirectionGetter.from_shcoeff(shm_coeff, max_angle=45., sphere=sphere) streamlines_generator = LocalTracking(prob_dg, affine, step_size=.5, max_cross=1) # Generate streamlines object streamlines = Streamlines(streamlines_generator) affine = img.get_affine() vox_size=fa_img.get_header().get_zooms()[:3] fname = os.path.abspath('%s_%s_prob_streamline.trk' % (prefix, recon)) save_trk(fname, streamlines, affine, vox_size=vox_size) ''' ''' deterministic tracking with EuDX method''' from dipy.tracking.eudx import EuDX print("reconstructing with EuDX") if useFA: eu = EuDX( FA, peaks.peak_indices[..., 0], odf_vertices=sphere.vertices, a_low=0.001, # default is 0.0239 seeds=10**6, ang_thr=75) else: eu = EuDX( peaks.gfa, peaks.peak_indices[..., 0], odf_vertices=sphere.vertices, #a_low=0.1, seeds=10**6, ang_thr=45) sl_fname = os.path.abspath('%s_%s_det_streamline.trk' % (prefix, recon)) # trying new dipy.io.streamline module, per email to neuroimaging list # 2018.04.05 from nibabel.streamlines import Field from nibabel.orientations import aff2axcodes affine = img.get_affine() vox_size = fa_img.get_header().get_zooms()[:3] fov_shape = FA.shape[:3] if vox_size is not None and fov_shape is not None: hdr = {} hdr[Field.VOXEL_TO_RASMM] = affine.copy() hdr[Field.VOXEL_SIZES] = vox_size hdr[Field.DIMENSIONS] = fov_shape hdr[Field.VOXEL_ORDER] = "".join(aff2axcodes(affine)) tractogram = nib.streamlines.Tractogram(eu) tractogram.affine_to_rasmm = affine trk_file = nib.streamlines.TrkFile(tractogram, header=hdr) nib.streamlines.save(trk_file, sl_fname) if oldval: os.environ['MKL_NUM_THREADS'] = oldval else: del os.environ['MKL_NUM_THREADS'] if ompoldval: os.environ['OMP_NUM_THREADS'] = ompoldval else: del os.environ['OMP_NUM_THREADS'] print('all output files created') return (tensor_fa_file, tensor_evec_file, model_gfa_file, sl_fname, affine, tensor_ad_file, tensor_rd_file, tensor_md_file, shm_coeff_file, peaks_file)
def fwdti_processing(base_dir, subject_id, visit_id, output_dir, init_method="md", init_values_extraction="intensity", csf_roi=None, wm_roi=None, template="MNI152_T1_2mm.nii.gz", denoised_data=True, bg_wm_bound=1, csf_bound=75, write_masks=True, indexes=["FA", "MD", "FW"], dof=6, output_type="NIFTI", median_radius=3, numpass=1, autocrop=False, dilate=1, learning_rate=0.0025, iterations=50): """Function to derive dti indexes from dwi data using dipy functions Parameters ---------- base_dir : absolute path pointing at the root directory of the bids repository subject_id: string, the tag subject (i.e. sub-sublabel) of the subject to treat visit_id: the VALUE of the session tag to be treated (i.e. for ses-02, only "02" need to be entered) output_dir: absolute path of the directories were the indexes will be written init_method: string. should the Beltrami optimization be initialized using the mean diffusivity or the hybrid method (see BeltramiModel help). Default to md but hybrid is suggested Accepted values are "md" and "hybrid" init_values_extraction: string. if hybrid has been chosen as initialization, how the initial values for wm and csf should be extracted ? If "registration" is chosen, csf and wm roi will be registered to diffusion image and the median value extracted. If "intensity" than an intensity based threshold is applied to b0 image to segment wm and csf and median values from these masks are extracted. csf_roi: absolute path of the roi representative of the csf. It should be in the same space as "template" and binary. Default to None wm_roi: absolute path of the roi representative of the wm. It should be in in the same space as "template" and binary. Default to None template: name of the file with extension of the template to be used for inverse registation of the rois. bg_wm_bound: int. Percentile of the boundary between background and white matter csf_bound: Percentile of the boundary between wm and csf denoised_data: boolean, should the denoised (True) or only the eddy current correct and realigned data (False) be used for fitting ? write_masks: boolean. If intensity threshold method has been choses, should the masks be written ? This is useful for debugging. Default to True indexes : list, a list of the indexes that will be written, accepted values are ["FA", "MD", "RD", "AD", "FW"] output_type: ["NIFTI", "NIFTI_GZ"], the type of nifti output desired, ... : other parameters related to the dipy functions used """ if output_type == "NIFTI": ext = ".nii" elif output_type == "NIFTI_GZ": ext = ".nii.gz" else: raise ValueError( "Output file type {} not recognized".format(output_type)) diff_dir = "{}/{}/ses-{}/dwi".format(base_dir, subject_id, visit_id) fbval = glob("{}/*bval".format(diff_dir))[0] fbvec = glob("{}/*bvec".format(diff_dir))[0] if (init_method == "hybrid" and init_values_extraction == "registration") and (csf_roi == None or wm_roi == None): raise ValueError( "You chose hybrid initialization method without specifing a csf_roi, a wm_roi or both" ) dti_preroc_dir = "{}/derivatives/fsl-dipy_dti-preproc/{}/ses-{}".format( base_dir, subject_id, visit_id) if denoised_data: fdwi = glob("{}/*_denoised*".format(dti_preroc_dir))[0] else: fdwi = glob("{}/*_ec.nii*".format(dti_preroc_dir))[0] bvals, bvecs = read_bvals_bvecs(fbval, fbvec) bvals = bvals / 1000 gtab = gradient_table(bvals, bvecs, b0_threshold=0) img = nb.load(fdwi) mask = nb.load(glob("{}/*_mask.nii*".format(dti_preroc_dir))[0]) x_ix, y_ix, z_ix, mask_crop, maskdata_crop = crop_and_indexes(mask, img) if init_method == "md": print("Fitting tensor") tenmodel = fwdti.BeltramiModel(gtab, learning_rate=learning_rate, iterations=iterations) elif init_method == "hybrid": if init_values_extraction == "registration": print("Registering csf and wm rois") try: csf_mean, wm_mean = hybrid_rois_registration( base_dir=base_dir, subject_id=subject_id, visit_id=visit_id, output_dir=output_dir, csf_roi=csf_roi, wm_roi=wm_roi, template=template, dof=dof, output_type=output_type) except: raise BaseException( "Could not perform the necessary registration for hybrid initialization for subject {}_ses-{}" .format(subject_id, visit_id)) elif init_values_extraction == "intensity": print("Performing intensity based csf and wm extraction") try: csf_mean, wm_mean = hybrid_intensity_threshold_based( base_dir=base_dir, subject_id=subject_id, visit_id=visit_id, output_dir=output_dir, bg_wm_bound=bg_wm_bound, csf_bound=csf_bound, denoised_data=denoised_data, write_masks=write_masks, output_type=output_type, median_radius=median_radius, numpass=numpass, autocrop=autocrop, dilate=dilate) except: raise BaseException( "Could not perform the intensity based values extraction for hybrid initialization for subject {}_ses-{}" .format(subject_id, visit_id)) print("Fitting tensor") tenmodel = fwdti.BeltramiModel(gtab, init_method="hybrid", Stissue=wm_mean, Swater=csf_mean) else: raise ValueError( "{} is an unknwon initialization method".format(init_method)) tenfit = tenmodel.fit(maskdata_crop) output_base_name = splitext(PurePath(fbval).parts[-1])[0] if "FA" in indexes: print("Computing fwFA") FA = fwdti.fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = FA * mask_crop fa_img = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(fa_img, "{}/{}_fwFA{}".format(output_dir, output_base_name, ext)) if "MD" in indexes: print("Computing fwMD") MD = fwdti.mean_diffusivity(tenfit.evals) MD[np.isnan(MD)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = MD * mask_crop MD_img = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(MD_img, "{}/{}_fwMD{}".format(output_dir, output_base_name, ext)) if "RD" in indexes: print("Computing fwRD") RD = radial_diffusivity(tenfit.evals) RD[np.isnan(RD)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = RD * mask_crop RD_img = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(RD_img, "{}/{}_fwRD{}".format(output_dir, output_base_name, ext)) if "AD" in indexes: print("Computing fwAD") AD = axial_diffusivity(tenfit.evals) AD[np.isnan(AD)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = AD * mask_crop AD_img = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(AD_img, "{}/{}_fwAD{}".format(output_dir, output_base_name, ext)) if "FW" in indexes: print("Computing FW") FW = tenfit.fw FW[np.isnan(FW)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = FW * mask_crop fw_image = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(fw_image, "{}/{}_FW{}".format(output_dir, output_base_name, ext)) # def diff_direct_registration_crossectional(base_dir, # subject_id, # visit_id, # output_dir, # tbss_like = True, # output_type = "NIFTI", # template = "/usr/local/fsl/data/standard/FMRIB58_FA_1mm.nii.gz", # config_file = "/usr/local/fsl/etc/flirtsch/FA_2_FMRIB58_1mm.cnf"): # dti_dir = "{}/derivatives/dipy_dti/{}/ses-{}".format(base_dir, subject_id, visit_id) # fdwi = glob("{}/*FA.nii*".format(dti_dir))[0] # output_base_name = get_base_name_all_type(fdwi) # other_indexes = glob("{}/*nii*".format(dti_dir)) # other_indexes.remove(fdwi) # if output_type == "NIFTI": # ext = ".nii" # elif output_type == "NIFTI_GZ": # ext = ".nii.gz" # else: # raise ValueError("Output file type {} not recognized".format(output_type)) # flirt = FLIRT() # fnirt = FNIRT() # apply_warp = ApplyWarp() # flirt.inputs.reference = template # flirt.inputs.output_type = output_type # fnirt.inputs.ref_file = template # fnirt.inputs.output_type = output_type # fnirt.inputs.config_file = config_file # fnirt.inputs.log_file = "{}/{}_fnirt.txt".format(output_dir, output_base_name) # apply_warp.inputs.ref_file = template # apply_warp.inputs.output_type = output_type # if tbss_like: # img = nb.load(fdwi) # img_data = img.get_fdata() # binary_wm = np.zeros_like(img_data) # binary_wm[img_data != 0] = 1 # eroded_wm_mask = binary_erosion(binary_wm) # eroded_wm = img_data * (eroded_wm_mask * 1) # eroded_wm[:,:,0] = 0 # eroded_wm[:,:,-1] = 0 # clean_fa = nb.Nifti1Image(eroded_wm, img.affine, img.header) # nb.save(clean_fa, "{}/{}_clean{}".format(output_dir, output_base_name, ext)) # flirt.inputs.in_file = "{}/{}_clean{}".format(output_dir, output_base_name, ext) # flirt.inputs.out_file = "{}/{}_clean_linear{}".format(output_dir, output_base_name, ext) # flirt.inputs.out_matrix_file = "{}/{}_clean_linear.mat".format(output_dir, output_base_name) # print("running linear registration") # flirt.run() # fnirt.inputs.in_file = "{}/{}_clean_linear{}".format(output_dir, output_base_name, ext) # fnirt.inputs.warped_file = "{}/{}_clean_nonlinear{}".format(output_dir, output_base_name, ext) # fnirt.inputs.field_file = "{}/{}_clean_nonlinearfield{}".format(output_dir, output_base_name, ext) # print("running non linear registration") # fnirt.run() # else: # flirt.inputs.in_file = fdwi # flirt.inputs.out_file = "{}/{}_linear{}".format(output_dir, output_base_name, ext) # flirt.inputs.out_matrix_file = "{}/{}_linear.mat".format(output_dir, output_base_name) # print("running linear registration") # flirt.run() # fnirt.inputs.in_file = "{}/{}_linear{}".format(output_dir, output_base_name, ext) # fnirt.inputs.warped_file = "{}/{}_nonlinear{}".format(output_dir, output_base_name, ext) # fnirt.inputs.field_file = "{}/{}_nonlinearfield{}".format(output_dir, output_base_name, ext) # print("running non linear registration") # fnirt.run() # apply_warp.inputs.premat = flirt.inputs.out_matrix_file # apply_warp.inputs.field_file = fnirt.inputs.field_file # print("applying warp") # for f in other_indexes: # output_base_name = get_base_name_all_type(f) # apply_warp.inputs.in_file = f # apply_warp.inputs.out_file = "{}/{}_nonlinear{}".format(output_dir, output_base_name, ext) # apply_warp.run() # def diff_direct_registration_longitudinal(base_dir, # subject_id, # output_dir, # tbss_like = True, # output_type = "NIFTI", # template = "/usr/local/fsl/data/standard/FMRIB58_FA_1mm.nii.gz", # config_file = "/usr/local/fsl/etc/flirtsch/FA_2_FMRIB58_1mm.cnf"): # if output_type == "NIFTI": # ext = ".nii" # elif output_type == "NIFTI_GZ": # ext = ".nii.gz" # else: # raise ValueError("Output file type {} not recognized".format(output_type)) # dti_dir = "{}/derivatives/dipy_dti/{}".format(base_dir, subject_id) # fdwi_01 = glob("{}/ses-01/*FA.nii*".format(dti_dir))[0] # fdwi_02 = glob("{}/ses-02/*FA.nii*".format(dti_dir))[0] # # output_base_name = get_base_name_all_type(fdwi) # # other_indexes = glob("{}/*nii*".format(dti_dir)) # # other_indexes.remove(fdwi) # if tbss_like: # for el in [fdwi_01, fdwi_02]: # output_base_name = get_base_name_all_type(el) # img = nb.load(el) # img_data = img.get_fdata() # binary_wm = np.zeros_like(img_data) # binary_wm[img_data != 0] = 1 # eroded_wm_mask = binary_erosion(binary_wm) # eroded_wm = img_data * (eroded_wm_mask * 1) # eroded_wm[:,:,0] = 0 # eroded_wm[:,:,-1] = 0 # clean_fa = nb.Nifti1Image(eroded_wm, img.affine, img.header) # nb.save(clean_fa, "{}/{}_clean{}".format(output_dir, output_base_name, ext)) # #flirt back and forth # clean_01 = glob("{}/*ses-01*_clean*".format(output_dir, output_base_name)) # clean_02 = glob("{}/*ses-02*_clean*".format(output_dir, output_base_name)) # flirt = FLIRT() # flirt.inputs.in_file = clean_01 # flirt.inputs.reference = clean_02 # flirt.inputs.output_type = output_type # flirt.inputs.out_file = "{}/t1_to_t2{}".format(output_dir, ext) # flirt.inputs.out_matrix_file = "{}/t1_to_t2.mat".format(output_dir) # flirt.run() # flirt.inputs.in_file = clean_02 # flirt.inputs.reference = clean_01 # flirt.inputs.output_type = output_type # flirt.inputs.out_file = "{}/t2_to_t1{}".format(output_dir, ext) # flirt.inputs.out_matrix_file = "{}/t2_to_t1.mat".format(output_dir) # mat_transform = ConvertXFM() # mat_transform.inputs.in_file = "{}/t2_to_t1.mat".format(output_dir) # mat_transform.inputs.inverse_xfm = True # mat_transform.inputs.out_file = "{}/t2_to_t1_inverted.mat".format(output_dir) # fnirt = FNIRT() # apply_warp = ApplyWarp() # flirt.inputs.reference = template # flirt.inputs.output_type = output_type # fnirt.inputs.ref_file = template # fnirt.inputs.output_type = output_type # fnirt.inputs.config_file = config_file # fnirt.inputs.log_file = "{}/{}_fnirt.txt".format(output_dir, output_base_name) # apply_warp.inputs.ref_file = template # apply_warp.inputs.output_type = output_type # if tbss_like: # img = nb.load(fdwi) # img_data = img.get_fdata() # binary_wm = np.zeros_like(img_data) # binary_wm[img_data != 0] = 1 # eroded_wm_mask = binary_erosion(binary_wm) # eroded_wm = img_data * (eroded_wm_mask * 1) # eroded_wm[:,:,0] = 0 # eroded_wm[:,:,-1] = 0 # clean_fa = nb.Nifti1Image(eroded_wm, img.affine, img.header) # nb.save(clean_fa, "{}/{}_clean{}".format(output_dir, output_base_name, ext)) # flirt.inputs.in_file = "{}/{}_clean{}".format(output_dir, output_base_name, ext) # flirt.inputs.out_file = "{}/{}_clean_linear{}".format(output_dir, output_base_name, ext) # flirt.inputs.out_matrix_file = "{}/{}_clean_linear.mat".format(output_dir, output_base_name) # print("running linear registration") # flirt.run() # fnirt.inputs.in_file = "{}/{}_clean_linear{}".format(output_dir, output_base_name, ext) # fnirt.inputs.warped_file = "{}/{}_clean_nonlinear{}".format(output_dir, output_base_name, ext) # fnirt.inputs.field_file = "{}/{}_clean_nonlinearfield{}".format(output_dir, output_base_name, ext) # print("running non linear registration") # fnirt.run() # else: # flirt.inputs.in_file = fdwi # flirt.inputs.out_file = "{}/{}_linear{}".format(output_dir, output_base_name, ext) # flirt.inputs.out_matrix_file = "{}/{}_linear.mat".format(output_dir, output_base_name) # print("running linear registration") # flirt.run() # fnirt.inputs.in_file = "{}/{}_linear{}".format(output_dir, output_base_name, ext) # fnirt.inputs.warped_file = "{}/{}_nonlinear{}".format(output_dir, output_base_name, ext) # fnirt.inputs.field_file = "{}/{}_nonlinearfield{}".format(output_dir, output_base_name, ext) # print("running non linear registration") # fnirt.run() # apply_warp.inputs.premat = flirt.inputs.out_matrix_file # apply_warp.inputs.field_file = fnirt.inputs.field_file # print("applying warp") # for f in other_indexes: # output_base_name = get_base_name_all_type(f) # apply_warp.inputs.in_file = f # apply_warp.inputs.out_file = "{}/{}_nonlinear{}".format(output_dir, output_base_name, ext) # apply_warp.run()
def dti_processing(base_dir, subject_id, visit_id, output_dir, denoised_data=True, indexes=["FA", "MD"], output_type="NIFTI"): """Function to derive dti indexes from dwi data using dipy functions Parameters ---------- base_dir : absolute path pointing at the root directory of the bids repository subject_id: string, the tag subject (i.e. sub-sublabel) of the subject to treat visit_id: the VALUE of the session tag to be treated (i.e. for ses-02, only "02" need to be entered) output_dir: absolute path of the directories were the indexes will be written denoised_data: boolean, should the denoised (True) or only the eddy current correct and realigned data (False) be used for fitting ? indexes : list, a list of the indexes that will be written, accepted values are ["FA", "MD", "RD", "AD"] ... : other parameters related to the dipy functions used """ if output_type == "NIFTI": ext = ".nii" elif output_type == "NIFTI_GZ": ext = ".nii.gz" else: raise ValueError( "Output file type {} not recognized".format(output_type)) diff_dir = "{}/{}/ses-{}/dwi".format(base_dir, subject_id, visit_id) fbval = glob("{}/*bval".format(diff_dir))[0] fbvec = glob("{}/*bvec".format(diff_dir))[0] dti_preroc_dir = "{}/derivatives/fsl-dipy_dti-preproc/{}/ses-{}".format( base_dir, subject_id, visit_id) if denoised_data: fdwi = glob("{}/*_denoised*".format(dti_preroc_dir))[0] else: fdwi = glob("{}/*_masked.nii*".format(dti_preroc_dir))[0] bvals, bvecs = read_bvals_bvecs(fbval, fbvec) gtab = gradient_table(bvals, bvecs) img = nb.load(fdwi) mask = nb.load(glob("{}/*_mask.nii*".format(dti_preroc_dir))[0]) x_ix, y_ix, z_ix, mask_crop, maskdata_crop = crop_and_indexes(mask, img) tenmodel = dti.TensorModel(gtab) tenfit = tenmodel.fit(maskdata_crop) output_base_name = get_base_name_all_type(fbval) if "FA" in indexes: print("Computing FA") FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = FA * mask_crop fa_img = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(fa_img, "{}/{}_FA{}".format(output_dir, output_base_name, ext)) if "MD" in indexes: print("Computing MD") MD = mean_diffusivity(tenfit.evals) MD[np.isnan(MD)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = MD * mask_crop md_img = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(md_img, "{}/{}_MD{}".format(output_dir, output_base_name, ext)) if "RD" in indexes: print("Computing RD") RD = radial_diffusivity(tenfit.evals) RD[np.isnan(RD)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = RD * mask_crop rd_img = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(rd_img, "{}/{}_RD{}".format(output_dir, output_base_name, ext)) if "AD" in indexes: print("Computing AD") AD = axial_diffusivity(tenfit.evals) AD[np.isnan(AD)] = 0 opt = np.zeros(mask.shape) opt[x_ix, y_ix, z_ix] = AD * mask_crop ad_img = nb.Nifti1Image(opt.astype(np.float32), img.affine) nb.save(ad_img, "{}/{}_AD{}".format(output_dir, output_base_name, ext))
def main(): parser = _build_args_parser() args = parser.parse_args() if not args.not_all: args.fa = args.fa or 'fa.nii.gz' args.ga = args.ga or 'ga.nii.gz' args.rgb = args.rgb or 'rgb.nii.gz' args.md = args.md or 'md.nii.gz' args.ad = args.ad or 'ad.nii.gz' args.rd = args.rd or 'rd.nii.gz' args.mode = args.mode or 'mode.nii.gz' args.norm = args.norm or 'tensor_norm.nii.gz' args.tensor = args.tensor or 'tensor.nii.gz' args.evecs = args.evecs or 'tensor_evecs.nii.gz' args.evals = args.evals or 'tensor_evals.nii.gz' args.residual = args.residual or 'dti_residual.nii.gz' args.p_i_signal =\ args.p_i_signal or 'physically_implausible_signals_mask.nii.gz' args.pulsation = args.pulsation or 'pulsation_and_misalignment.nii.gz' outputs = [args.fa, args.ga, args.rgb, args.md, args.ad, args.rd, args.mode, args.norm, args.tensor, args.evecs, args.evals, args.residual, args.p_i_signal, args.pulsation] if args.not_all and not any(outputs): parser.error('When using --not_all, you need to specify at least ' + 'one metric to output.') assert_inputs_exist( parser, [args.input, args.bvals, args.bvecs], [args.mask]) assert_outputs_exists(parser, args, outputs) img = nib.load(args.input) data = img.get_data() affine = img.get_affine() if args.mask is None: mask = None else: mask = nib.load(args.mask).get_data().astype(np.bool) # Validate bvals and bvecs logging.info('Tensor estimation with the %s method...', args.method) bvals, bvecs = read_bvals_bvecs(args.bvals, args.bvecs) if not is_normalized_bvecs(bvecs): logging.warning('Your b-vectors do not seem normalized...') bvecs = normalize_bvecs(bvecs) check_b0_threshold(args, bvals.min()) gtab = gradient_table(bvals, bvecs, b0_threshold=bvals.min()) # Get tensors if args.method == 'restore': sigma = ne.estimate_sigma(data) tenmodel = TensorModel(gtab, fit_method=args.method, sigma=sigma, min_signal=_get_min_nonzero_signal(data)) else: tenmodel = TensorModel(gtab, fit_method=args.method, min_signal=_get_min_nonzero_signal(data)) tenfit = tenmodel.fit(data, mask) FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if args.tensor: # Get the Tensor values and format them for visualisation # in the Fibernavigator. tensor_vals = lower_triangular(tenfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] fiber_tensors = nib.Nifti1Image( tensor_vals_reordered.astype(np.float32), affine) nib.save(fiber_tensors, args.tensor) if args.fa: fa_img = nib.Nifti1Image(FA.astype(np.float32), affine) nib.save(fa_img, args.fa) if args.ga: GA = geodesic_anisotropy(tenfit.evals) GA[np.isnan(GA)] = 0 ga_img = nib.Nifti1Image(GA.astype(np.float32), affine) nib.save(ga_img, args.ga) if args.rgb: RGB = color_fa(FA, tenfit.evecs) rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine) nib.save(rgb_img, args.rgb) if args.md: MD = mean_diffusivity(tenfit.evals) md_img = nib.Nifti1Image(MD.astype(np.float32), affine) nib.save(md_img, args.md) if args.ad: AD = axial_diffusivity(tenfit.evals) ad_img = nib.Nifti1Image(AD.astype(np.float32), affine) nib.save(ad_img, args.ad) if args.rd: RD = radial_diffusivity(tenfit.evals) rd_img = nib.Nifti1Image(RD.astype(np.float32), affine) nib.save(rd_img, args.rd) if args.mode: # Compute tensor mode inter_mode = dipy_mode(tenfit.quadratic_form) # Since the mode computation can generate NANs when not masked, # we need to remove them. non_nan_indices = np.isfinite(inter_mode) mode = np.zeros(inter_mode.shape) mode[non_nan_indices] = inter_mode[non_nan_indices] mode_img = nib.Nifti1Image(mode.astype(np.float32), affine) nib.save(mode_img, args.mode) if args.norm: NORM = norm(tenfit.quadratic_form) norm_img = nib.Nifti1Image(NORM.astype(np.float32), affine) nib.save(norm_img, args.norm) if args.evecs: evecs = tenfit.evecs.astype(np.float32) evecs_img = nib.Nifti1Image(evecs, affine) nib.save(evecs_img, args.evecs) # save individual e-vectors also e1_img = nib.Nifti1Image(evecs[..., 0], affine) e2_img = nib.Nifti1Image(evecs[..., 1], affine) e3_img = nib.Nifti1Image(evecs[..., 2], affine) nib.save(e1_img, add_filename_suffix(args.evecs, '_v1')) nib.save(e2_img, add_filename_suffix(args.evecs, '_v2')) nib.save(e3_img, add_filename_suffix(args.evecs, '_v3')) if args.evals: evals = tenfit.evals.astype(np.float32) evals_img = nib.Nifti1Image(evals, affine) nib.save(evals_img, args.evals) # save individual e-values also e1_img = nib.Nifti1Image(evals[..., 0], affine) e2_img = nib.Nifti1Image(evals[..., 1], affine) e3_img = nib.Nifti1Image(evals[..., 2], affine) nib.save(e1_img, add_filename_suffix(args.evals, '_e1')) nib.save(e2_img, add_filename_suffix(args.evals, '_e2')) nib.save(e3_img, add_filename_suffix(args.evals, '_e3')) if args.p_i_signal: S0 = np.mean(data[..., gtab.b0s_mask], axis=-1, keepdims=True) DWI = data[..., ~gtab.b0s_mask] pis_mask = np.max(S0 < DWI, axis=-1) if args.mask is not None: pis_mask *= mask pis_img = nib.Nifti1Image(pis_mask.astype(np.int16), affine) nib.save(pis_img, args.p_i_signal) if args.pulsation: STD = np.std(data[..., ~gtab.b0s_mask], axis=-1) if args.mask is not None: STD *= mask std_img = nib.Nifti1Image(STD.astype(np.float32), affine) nib.save(std_img, add_filename_suffix(args.pulsation, '_std_dwi')) if np.sum(gtab.b0s_mask) <= 1: logger.info('Not enough b=0 images to output standard ' 'deviation map') else: if len(np.where(gtab.b0s_mask)) == 2: logger.info('Only two b=0 images. Be careful with the ' 'interpretation of this std map') STD = np.std(data[..., gtab.b0s_mask], axis=-1) if args.mask is not None: STD *= mask std_img = nib.Nifti1Image(STD.astype(np.float32), affine) nib.save(std_img, add_filename_suffix(args.pulsation, '_std_b0')) if args.residual: if args.mask is None: logger.info("Outlier detection will not be performed, since no " "mask was provided.") S0 = np.mean(data[..., gtab.b0s_mask], axis=-1) data_p = tenfit.predict(gtab, S0) R = np.mean(np.abs(data_p[..., ~gtab.b0s_mask] - data[..., ~gtab.b0s_mask]), axis=-1) if args.mask is not None: R *= mask R_img = nib.Nifti1Image(R.astype(np.float32), affine) nib.save(R_img, args.residual) R_k = np.zeros(data.shape[-1]) # mean residual per DWI std = np.zeros(data.shape[-1]) # std residual per DWI q1 = np.zeros(data.shape[-1]) # first quartile q3 = np.zeros(data.shape[-1]) # third quartile iqr = np.zeros(data.shape[-1]) # interquartile for i in range(data.shape[-1]): x = np.abs(data_p[..., i] - data[..., i])[mask] R_k[i] = np.mean(x) std[i] = np.std(x) q3[i], q1[i] = np.percentile(x, [75, 25]) iqr[i] = q3[i] - q1[i] # Outliers are observations that fall below Q1 - 1.5(IQR) or # above Q3 + 1.5(IQR) We check if a volume is an outlier only if # we have a mask, else we are biased. if args.mask is not None and R_k[i] < (q1[i] - 1.5 * iqr[i]) \ or R_k[i] > (q3[i] + 1.5 * iqr[i]): logger.warning('WARNING: Diffusion-Weighted Image i=%s is an ' 'outlier', i) residual_basename, _ = split_name_with_nii(args.residual) res_stats_basename = residual_basename + ".npy" np.save(add_filename_suffix( res_stats_basename, "_mean_residuals"), R_k) np.save(add_filename_suffix(res_stats_basename, "_q1_residuals"), q1) np.save(add_filename_suffix(res_stats_basename, "_q3_residuals"), q3) np.save(add_filename_suffix(res_stats_basename, "_iqr_residuals"), iqr) np.save(add_filename_suffix(res_stats_basename, "_std_residuals"), std) # To do: I would like to have an error bar with q1 and q3. # Now, q1 acts as a std dwi = np.arange(R_k[~gtab.b0s_mask].shape[0]) plt.bar(dwi, R_k[~gtab.b0s_mask], 0.75, color='y', yerr=q1[~gtab.b0s_mask]) plt.xlabel('DW image') plt.ylabel('Mean residuals +- q1') plt.title('Residuals') plt.savefig(residual_basename + '_residuals_stats.png')
nib.save(nib.Nifti1Image(MD.astype(np.float32), affine), os.path.join(path_output, ref_name_only + '_MD' + d.extension)) list_maps.append( os.path.join(path_output, ref_name_only + '_MD' + d.extension)) print(d.separador + d.separador + 'computing of AD map') AD = dti.axial_diffusivity(evals) nib.save(nib.Nifti1Image(AD.astype(np.float32), affine), os.path.join(path_output, ref_name_only + '_AD' + d.extension)) list_maps.append( os.path.join(path_output, ref_name_only + '_AD' + d.extension)) print(d.separador + d.separador + 'computing of RD map') RD = dti.radial_diffusivity(evals) nib.save(nib.Nifti1Image(RD.astype(np.float32), affine), os.path.join(path_output, ref_name_only + '_RD' + d.extension)) list_maps.append( os.path.join(path_output, ref_name_only + '_RD' + d.extension)) sphere = get_sphere('symmetric724') peak_indices = quantize_evecs(evecs, sphere.vertices) eu = EuDX(FA.astype('f8'), peak_indices, seeds=300000, odf_vertices=sphere.vertices, a_low=0.15) tensor_streamlines = [streamline for streamline in eu]
def run_to_estimate_dti_maps(path_input, path_output, file_tensor_fitevals="", file_tensor_fitevecs="", fbval="", fbvec=""): folder = os.path.dirname(path_input) if fbval == "" or fbvec == "": folder_sujeto = path_output for l in os.listdir(folder_sujeto): if "TENSOR" in l and "bval" in l: fbval = os.path.join(folder_sujeto, l) if "TENSOR" in l and "bvec" in l: fbvec = os.path.join(folder_sujeto, l) if file_tensor_fitevals == "" or file_tensor_fitevecs == "": for i in os.listdir(folder): if "DTIEvals" in i: file_tensor_fitevals = os.path.join(folder, i) for i in os.listdir(folder): if "DTIEvecs" in i: file_tensor_fitevecs = os.path.join(folder, i) if not os.path.exists(os.path.join(folder, "list_maps.txt")): # def to_estimate_dti_maps(path_dwi_input, path_output, file_tensor_fitevecs, file_tensor_fitevals): ref_name_only = utils.to_extract_filename(file_tensor_fitevecs) ref_name_only = ref_name_only[:-9] list_maps = [] img_tensorFitevecs = nib.load(file_tensor_fitevecs) img_tensorFitevals = nib.load(file_tensor_fitevals) evecs = img_tensorFitevecs.get_data() evals = img_tensorFitevals.get_data() affine = img_tensorFitevecs.affine print(d.separador + d.separador + 'computing of FA map') FA = fractional_anisotropy(evals) FA[np.isnan(FA)] = 0 nib.save( nib.Nifti1Image(FA.astype(np.float32), affine), os.path.join(path_output, ref_name_only + '_FA' + d.extension)) list_maps.append( os.path.join(path_output, ref_name_only + '_FA' + d.extension)) print(d.separador + d.separador + 'computing of Color FA map') FA2 = np.clip(FA, 0, 1) RGB = color_fa(FA2, evecs) nib.save( nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine), os.path.join(path_output, ref_name_only + '_FA_RGB' + d.extension)) print(d.separador + d.separador + 'computing of MD map') MD = dti.mean_diffusivity(evals) nib.save( nib.Nifti1Image(MD.astype(np.float32), affine), os.path.join(path_output, ref_name_only + '_MD' + d.extension)) list_maps.append( os.path.join(path_output, ref_name_only + '_MD' + d.extension)) print(d.separador + d.separador + 'computing of AD map') AD = dti.axial_diffusivity(evals) nib.save( nib.Nifti1Image(AD.astype(np.float32), affine), os.path.join(path_output, ref_name_only + '_AD' + d.extension)) list_maps.append( os.path.join(path_output, ref_name_only + '_AD' + d.extension)) print(d.separador + d.separador + 'computing of RD map') RD = dti.radial_diffusivity(evals) nib.save( nib.Nifti1Image(RD.astype(np.float32), affine), os.path.join(path_output, ref_name_only + '_RD' + d.extension)) list_maps.append( os.path.join(path_output, ref_name_only + '_RD' + d.extension)) sphere = get_sphere('symmetric724') peak_indices = quantize_evecs(evecs, sphere.vertices) eu = EuDX(FA.astype('f8'), peak_indices, seeds=300000, odf_vertices=sphere.vertices, a_low=0.15) tensor_streamlines = [streamline for streamline in eu] hdr = nib.trackvis.empty_header() hdr['voxel_size'] = nib.load(path_input).header.get_zooms()[:3] hdr['voxel_order'] = 'LAS' hdr['dim'] = FA.shape tensor_streamlines_trk = ((sl, None, None) for sl in tensor_streamlines) nib.trackvis.write(os.path.join( path_output, ref_name_only + '_tractography_EuDx.trk'), tensor_streamlines_trk, hdr, points_space='voxel') print(list_maps) with open(os.path.join(path_output, "list_maps.txt"), "w") as f: for s in list_maps: f.write(str(s) + "\n") return path_input
def run(self, input_files, bvalues, bvectors, mask_files, b0_threshold=0.0, save_metrics=[], out_dir='', out_tensor='tensors.nii.gz', out_fa='fa.nii.gz', out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz', out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz', out_evec='evecs.nii.gz', out_eval='evals.nii.gz'): """ Workflow for tensor reconstruction and for computing DTI metrics. Performs a tensor reconstruction on the files by 'globing' ``input_files`` and saves the DTI metrics in a directory specified by ``out_dir``. Parameters ---------- input_files : string Path to the input volumes. This path may contain wildcards to process multiple inputs at once. bvalues : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. bvectors : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. mask_files : string Path to the input masks. This path may contain wildcards to use multiple masks at once. (default: No mask used) b0_threshold : float, optional Threshold used to find b=0 directions (default 0.0) save_metrics : variable string, optional List of metrics to save. Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval (default [] (all)) out_dir : string, optional Output directory (default input file directory) out_tensor : string, optional Name of the tensors volume to be saved (default 'tensors.nii.gz') out_fa : string, optional Name of the fractional anisotropy volume to be saved (default 'fa.nii.gz') out_ga : string, optional Name of the geodesic anisotropy volume to be saved (default 'ga.nii.gz') out_rgb : string, optional Name of the color fa volume to be saved (default 'rgb.nii.gz') out_md : string, optional Name of the mean diffusivity volume to be saved (default 'md.nii.gz') out_ad : string, optional Name of the axial diffusivity volume to be saved (default 'ad.nii.gz') out_rd : string, optional Name of the radial diffusivity volume to be saved (default 'rd.nii.gz') out_mode : string, optional Name of the mode volume to be saved (default 'mode.nii.gz') out_evec : string, optional Name of the eigenvectors volume to be saved (default 'evecs.nii.gz') out_eval : string, optional Name of the eigenvalues to be saved (default 'evals.nii.gz') """ io_it = self.get_io_iterator() for dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, \ omode, oevecs, oevals in io_it: logging.info('Computing DTI metrics for {0}'.format(dwi)) img = nib.load(dwi) data = img.get_data() affine = img.get_affine() if mask is None: mask = None else: mask = nib.load(mask).get_data().astype(np.bool) tenfit, _ = self.get_fitted_tensor(data, mask, bval, bvec, b0_threshold) if not save_metrics: save_metrics = [ 'fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode', 'evec', 'eval', 'tensor' ] FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if 'tensor' in save_metrics: tensor_vals = lower_triangular(tenfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] fiber_tensors = nib.Nifti1Image( tensor_vals_reordered.astype(np.float32), affine) nib.save(fiber_tensors, otensor) if 'fa' in save_metrics: fa_img = nib.Nifti1Image(FA.astype(np.float32), affine) nib.save(fa_img, ofa) if 'ga' in save_metrics: GA = geodesic_anisotropy(tenfit.evals) ga_img = nib.Nifti1Image(GA.astype(np.float32), affine) nib.save(ga_img, oga) if 'rgb' in save_metrics: RGB = color_fa(FA, tenfit.evecs) rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine) nib.save(rgb_img, orgb) if 'md' in save_metrics: MD = mean_diffusivity(tenfit.evals) md_img = nib.Nifti1Image(MD.astype(np.float32), affine) nib.save(md_img, omd) if 'ad' in save_metrics: AD = axial_diffusivity(tenfit.evals) ad_img = nib.Nifti1Image(AD.astype(np.float32), affine) nib.save(ad_img, oad) if 'rd' in save_metrics: RD = radial_diffusivity(tenfit.evals) rd_img = nib.Nifti1Image(RD.astype(np.float32), affine) nib.save(rd_img, orad) if 'mode' in save_metrics: MODE = get_mode(tenfit.quadratic_form) mode_img = nib.Nifti1Image(MODE.astype(np.float32), affine) nib.save(mode_img, omode) if 'evec' in save_metrics: evecs_img = nib.Nifti1Image(tenfit.evecs.astype(np.float32), affine) nib.save(evecs_img, oevecs) if 'eval' in save_metrics: evals_img = nib.Nifti1Image(tenfit.evals.astype(np.float32), affine) nib.save(evals_img, oevals) logging.info('DTI metrics saved in {0}'.format( os.path.dirname(oevals)))
def dmri_recon(sid, data_dir, out_dir, resolution, recon='csd', num_threads=2): import tempfile #tempfile.tempdir = '/om/scratch/Fri/ksitek/' import os oldval = None if 'MKL_NUM_THREADS' in os.environ: oldval = os.environ['MKL_NUM_THREADS'] os.environ['MKL_NUM_THREADS'] = '%d' % num_threads ompoldval = None if 'OMP_NUM_THREADS' in os.environ: ompoldval = os.environ['OMP_NUM_THREADS'] os.environ['OMP_NUM_THREADS'] = '%d' % num_threads import nibabel as nib import numpy as np from glob import glob if resolution == '0.2mm': filename = 'Reg_S64550_nii4d.nii' fimg = os.path.abspath(glob(os.path.join(data_dir, filename))[0]) else: filename = 'Reg_S64550_nii4d_resamp-%s.nii.gz'%(resolution) fimg = os.path.abspath(glob(os.path.join(data_dir, 'resample', filename))[0]) print("dwi file = %s"%fimg) fbvec = os.path.abspath(glob(os.path.join(data_dir, 'bvecs', 'camino_120_RAS_flipped-xy.bvecs'))[0]) print("bvec file = %s"%fbvec) fbval = os.path.abspath(glob(os.path.join(data_dir, 'bvecs', 'camino_120_RAS.bvals'))[0]) print("bval file = %s"%fbval) img = nib.load(fimg) data = img.get_data() affine = img.get_affine() prefix = sid from dipy.io import read_bvals_bvecs from dipy.core.gradients import vector_norm bvals, bvecs = read_bvals_bvecs(fbval, fbvec) b0idx = [] for idx, val in enumerate(bvals): if val < 1: pass #bvecs[idx] = [1, 0, 0] else: b0idx.append(idx) #print "b0idx=%d"%idx #print "input bvecs:" #print bvecs bvecs[b0idx, :] = bvecs[b0idx, :]/vector_norm(bvecs[b0idx])[:, None] #print "bvecs after normalization:" #print bvecs from dipy.core.gradients import gradient_table gtab = gradient_table(bvals, bvecs) gtab.bvecs.shape == bvecs.shape gtab.bvecs gtab.bvals.shape == bvals.shape gtab.bvals from dipy.reconst.csdeconv import auto_response response, ratio = auto_response(gtab, data, roi_radius=10, fa_thr=0.1) # 0.7 #from dipy.segment.mask import median_otsu #b0_mask, mask = median_otsu(data[:, :, :, b0idx].mean(axis=3).squeeze(), 4, 4) if resolution == '0.2mm': mask_name = 'Reg_S64550_nii_b0-slice_mask.nii.gz' fmask1 = os.path.join(data_dir, mask_name) else: mask_name = 'Reg_S64550_nii_b0-slice_mask_resamp-%s.nii.gz'%(resolution) fmask1 = os.path.join(data_dir, 'resample', mask_name) print("fmask file = %s"%fmask1) mask = nib.load(fmask1).get_data() useFA = True print("creating model") if recon == 'csd': from dipy.reconst.csdeconv import ConstrainedSphericalDeconvModel model = ConstrainedSphericalDeconvModel(gtab, response) useFA = True elif recon == 'csa': from dipy.reconst.shm import CsaOdfModel, normalize_data model = CsaOdfModel(gtab, 4) useFA = False else: raise ValueError('only csd, csa supported currently') from dipy.reconst.dsi import (DiffusionSpectrumDeconvModel, DiffusionSpectrumModel) model = DiffusionSpectrumDeconvModel(gtab) fit = model.fit(data) from dipy.data import get_sphere sphere = get_sphere('symmetric724') #odfs = fit.odf(sphere) from dipy.reconst.peaks import peaks_from_model print("running peaks_from_model") peaks = peaks_from_model(model=model, data=data, sphere=sphere, mask=mask, return_sh=True, return_odf=False, normalize_peaks=True, npeaks=5, relative_peak_threshold=.5, min_separation_angle=25, parallel=num_threads > 1, nbr_processes=num_threads) from dipy.reconst.dti import TensorModel print("running tensor model") tenmodel = TensorModel(gtab) tenfit = tenmodel.fit(data, mask) from dipy.reconst.dti import fractional_anisotropy print("running FA") FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 fa_img = nib.Nifti1Image(FA, img.get_affine()) tensor_fa_file = os.path.abspath('%s_tensor_fa.nii.gz' % (prefix)) nib.save(fa_img, tensor_fa_file) from dipy.reconst.dti import axial_diffusivity print("running AD") AD = axial_diffusivity(tenfit.evals) AD[np.isnan(AD)] = 0 ad_img = nib.Nifti1Image(AD, img.get_affine()) tensor_ad_file = os.path.abspath('%s_tensor_ad.nii.gz' % (prefix)) nib.save(ad_img, tensor_ad_file) from dipy.reconst.dti import radial_diffusivity print("running RD") RD = radial_diffusivity(tenfit.evals) RD[np.isnan(RD)] = 0 rd_img = nib.Nifti1Image(RD, img.get_affine()) tensor_rd_file = os.path.abspath('%s_tensor_rd.nii.gz' % (prefix)) nib.save(rd_img, tensor_rd_file) from dipy.reconst.dti import mean_diffusivity print("running MD") MD = mean_diffusivity(tenfit.evals) MD[np.isnan(MD)] = 0 md_img = nib.Nifti1Image(MD, img.get_affine()) tensor_md_file = os.path.abspath('%s_tensor_md.nii.gz' % (prefix)) nib.save(md_img, tensor_md_file) evecs = tenfit.evecs evec_img = nib.Nifti1Image(evecs, img.get_affine()) tensor_evec_file = os.path.abspath('%s_tensor_evec.nii.gz' % (prefix)) nib.save(evec_img, tensor_evec_file) shm_coeff = fit.shm_coeff shm_coeff_file = os.path.abspath('%s_shm_coeff.nii.gz' % (prefix)) nib.save(nib.Nifti1Image(shm_coeff, img.get_affine()), shm_coeff_file) #from dipy.reconst.dti import quantize_evecs #peak_indices = quantize_evecs(tenfit.evecs, sphere.vertices) #eu = EuDX(FA, peak_indices, odf_vertices = sphere.vertices, #a_low=0.2, seeds=10**6, ang_thr=35) fa_img = nib.Nifti1Image(peaks.gfa, img.get_affine()) model_gfa_file = os.path.abspath('%s_%s_gfa.nii.gz' % (prefix, recon)) nib.save(fa_img, model_gfa_file) from dipy.tracking.eudx import EuDX print("reconstructing with EuDX") if useFA: eu = EuDX(FA, peaks.peak_indices[..., 0], odf_vertices = sphere.vertices, #a_low=0.1, seeds=10**6, ang_thr=45) else: eu = EuDX(peaks.gfa, peaks.peak_indices[..., 0], odf_vertices = sphere.vertices, #a_low=0.1, seeds=10**6, ang_thr=45) sl_fname = os.path.abspath('%s_%s_streamline.trk' % (prefix, recon)) """ #import dipy.tracking.metrics as dmetrics streamlines = ((sl, None, None) for sl in eu) # if dmetrics.length(sl) > 15) hdr = nib.trackvis.empty_header() hdr['voxel_size'] = fa_img.get_header().get_zooms()[:3] hdr['voxel_order'] = 'RAS' #LAS hdr['dim'] = FA.shape[:3] nib.trackvis.write(sl_fname, streamlines, hdr, points_space='voxel') """ # trying new dipy.io.streamline module, per email to neuroimaging list # 2018.04.05 from nibabel.streamlines import Field from nibabel.orientations import aff2axcodes affine = img.get_affine() vox_size=fa_img.get_header().get_zooms()[:3] fov_shape=FA.shape[:3] if vox_size is not None and fov_shape is not None: hdr = {} hdr[Field.VOXEL_TO_RASMM] = affine.copy() hdr[Field.VOXEL_SIZES] = vox_size hdr[Field.DIMENSIONS] = fov_shape hdr[Field.VOXEL_ORDER] = "".join(aff2axcodes(affine)) tractogram = nib.streamlines.Tractogram(eu) tractogram.affine_to_rasmm = affine trk_file = nib.streamlines.TrkFile(tractogram, header=hdr) nib.streamlines.save(trk_file, sl_fname) if oldval: os.environ['MKL_NUM_THREADS'] = oldval else: del os.environ['MKL_NUM_THREADS'] if ompoldval: os.environ['OMP_NUM_THREADS'] = ompoldval else: del os.environ['OMP_NUM_THREADS'] assert tensor_fa_file assert tensor_evec_file assert model_gfa_file assert tensor_ad_file assert tensor_rd_file assert tensor_md_file assert shm_coeff_file print('all output files created') return tensor_fa_file, tensor_evec_file, model_gfa_file, sl_fname, affine, tensor_ad_file, tensor_rd_file, tensor_md_file, shm_coeff_file
def run(self, input_files, bvalues, bvectors, mask_files, b0_threshold=0.0, save_metrics=[], out_dir='', out_tensor='tensors.nii.gz', out_fa='fa.nii.gz', out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz', out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz', out_evec='evecs.nii.gz', out_eval='evals.nii.gz'): """ Workflow for tensor reconstruction and for computing DTI metrics. Performs a tensor reconstruction on the files by 'globing' ``input_files`` and saves the DTI metrics in a directory specified by ``out_dir``. Parameters ---------- input_files : string Path to the input volumes. This path may contain wildcards to process multiple inputs at once. bvalues : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. bvectors : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. mask_files : string Path to the input masks. This path may contain wildcards to use multiple masks at once. (default: No mask used) b0_threshold : float, optional Threshold used to find b=0 directions (default 0.0) save_metrics : variable string, optional List of metrics to save. Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval (default [] (all)) out_dir : string, optional Output directory (default input file directory) out_tensor : string, optional Name of the tensors volume to be saved (default 'tensors.nii.gz') out_fa : string, optional Name of the fractional anisotropy volume to be saved (default 'fa.nii.gz') out_ga : string, optional Name of the geodesic anisotropy volume to be saved (default 'ga.nii.gz') out_rgb : string, optional Name of the color fa volume to be saved (default 'rgb.nii.gz') out_md : string, optional Name of the mean diffusivity volume to be saved (default 'md.nii.gz') out_ad : string, optional Name of the axial diffusivity volume to be saved (default 'ad.nii.gz') out_rd : string, optional Name of the radial diffusivity volume to be saved (default 'rd.nii.gz') out_mode : string, optional Name of the mode volume to be saved (default 'mode.nii.gz') out_evec : string, optional Name of the eigenvectors volume to be saved (default 'evecs.nii.gz') out_eval : string, optional Name of the eigenvalues to be saved (default 'evals.nii.gz') """ io_it = self.get_io_iterator() for dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, \ omode, oevecs, oevals in io_it: logging.info('Computing DTI metrics for {0}'.format(dwi)) img = nib.load(dwi) data = img.get_data() affine = img.get_affine() if mask is None: mask = None else: mask = nib.load(mask).get_data().astype(np.bool) tenfit, _ = self.get_fitted_tensor(data, mask, bval, bvec, b0_threshold) if not save_metrics: save_metrics = ['fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode', 'evec', 'eval', 'tensor'] FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if 'tensor' in save_metrics: tensor_vals = lower_triangular(tenfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] fiber_tensors = nib.Nifti1Image(tensor_vals_reordered.astype( np.float32), affine) nib.save(fiber_tensors, otensor) if 'fa' in save_metrics: fa_img = nib.Nifti1Image(FA.astype(np.float32), affine) nib.save(fa_img, ofa) if 'ga' in save_metrics: GA = geodesic_anisotropy(tenfit.evals) ga_img = nib.Nifti1Image(GA.astype(np.float32), affine) nib.save(ga_img, oga) if 'rgb' in save_metrics: RGB = color_fa(FA, tenfit.evecs) rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine) nib.save(rgb_img, orgb) if 'md' in save_metrics: MD = mean_diffusivity(tenfit.evals) md_img = nib.Nifti1Image(MD.astype(np.float32), affine) nib.save(md_img, omd) if 'ad' in save_metrics: AD = axial_diffusivity(tenfit.evals) ad_img = nib.Nifti1Image(AD.astype(np.float32), affine) nib.save(ad_img, oad) if 'rd' in save_metrics: RD = radial_diffusivity(tenfit.evals) rd_img = nib.Nifti1Image(RD.astype(np.float32), affine) nib.save(rd_img, orad) if 'mode' in save_metrics: MODE = get_mode(tenfit.quadratic_form) mode_img = nib.Nifti1Image(MODE.astype(np.float32), affine) nib.save(mode_img, omode) if 'evec' in save_metrics: evecs_img = nib.Nifti1Image(tenfit.evecs.astype(np.float32), affine) nib.save(evecs_img, oevecs) if 'eval' in save_metrics: evals_img = nib.Nifti1Image(tenfit.evals.astype(np.float32), affine) nib.save(evals_img, oevals) logging.info('DTI metrics saved in {0}'. format(os.path.dirname(oevals)))
def run(self, input_files, bvalues_files, bvectors_files, mask_files, b0_threshold=50.0, save_metrics=[], out_dir='', out_dt_tensor='dti_tensors.nii.gz', out_fa='fa.nii.gz', out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz', out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz', out_evec='evecs.nii.gz', out_eval='evals.nii.gz', out_dk_tensor="dki_tensors.nii.gz", out_mk="mk.nii.gz", out_ak="ak.nii.gz", out_rk="rk.nii.gz"): """ Workflow for Diffusion Kurtosis reconstruction and for computing DKI metrics. Performs a DKI reconstruction on the files by 'globing' ``input_files`` and saves the DKI metrics in a directory specified by ``out_dir``. Parameters ---------- input_files : string Path to the input volumes. This path may contain wildcards to process multiple inputs at once. bvalues_files : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. bvectors_files : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. mask_files : string Path to the input masks. This path may contain wildcards to use multiple masks at once. (default: No mask used) b0_threshold : float, optional Threshold used to find b0 volumes. save_metrics : variable string, optional List of metrics to save. Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval out_dir : string, optional Output directory. (default current directory) out_dt_tensor : string, optional Name of the tensors volume to be saved. out_dk_tensor : string, optional Name of the tensors volume to be saved. out_fa : string, optional Name of the fractional anisotropy volume to be saved. out_ga : string, optional Name of the geodesic anisotropy volume to be saved. out_rgb : string, optional Name of the color fa volume to be saved. out_md : string, optional Name of the mean diffusivity volume to be saved. out_ad : string, optional Name of the axial diffusivity volume to be saved. out_rd : string, optional Name of the radial diffusivity volume to be saved. out_mode : string, optional Name of the mode volume to be saved. out_evec : string, optional Name of the eigenvectors volume to be saved. out_eval : string, optional Name of the eigenvalues to be saved. out_mk : string, optional Name of the mean kurtosis to be saved. out_ak : string, optional Name of the axial kurtosis to be saved. out_rk : string, optional Name of the radial kurtosis to be saved. References ---------- .. [1] Tabesh, A., Jensen, J.H., Ardekani, B.A., Helpern, J.A., 2011. Estimation of tensors and tensor-derived measures in diffusional kurtosis imaging. Magn Reson Med. 65(3), 823-836 .. [2] Jensen, Jens H., Joseph A. Helpern, Anita Ramani, Hanzhang Lu, and Kyle Kaczynski. 2005. Diffusional Kurtosis Imaging: The Quantification of Non-Gaussian Water Diffusion by Means of Magnetic Resonance Imaging. MRM 53 (6):1432-40. """ io_it = self.get_io_iterator() for (dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, omode, oevecs, oevals, odk_tensor, omk, oak, ork) in io_it: logging.info('Computing DKI metrics for {0}'.format(dwi)) data, affine = load_nifti(dwi) if mask is not None: mask = load_nifti_data(mask).astype(bool) dkfit, _ = self.get_fitted_tensor(data, mask, bval, bvec, b0_threshold) if not save_metrics: save_metrics = [ 'mk', 'rk', 'ak', 'fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode', 'evec', 'eval', 'dt_tensor', 'dk_tensor' ] evals, evecs, kt = split_dki_param(dkfit.model_params) FA = fractional_anisotropy(evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if 'dt_tensor' in save_metrics: tensor_vals = lower_triangular(dkfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] save_nifti(otensor, tensor_vals_reordered.astype(np.float32), affine) if 'dk_tensor' in save_metrics: save_nifti(odk_tensor, dkfit.kt.astype(np.float32), affine) if 'fa' in save_metrics: save_nifti(ofa, FA.astype(np.float32), affine) if 'ga' in save_metrics: GA = geodesic_anisotropy(dkfit.evals) save_nifti(oga, GA.astype(np.float32), affine) if 'rgb' in save_metrics: RGB = color_fa(FA, dkfit.evecs) save_nifti(orgb, np.array(255 * RGB, 'uint8'), affine) if 'md' in save_metrics: MD = mean_diffusivity(dkfit.evals) save_nifti(omd, MD.astype(np.float32), affine) if 'ad' in save_metrics: AD = axial_diffusivity(dkfit.evals) save_nifti(oad, AD.astype(np.float32), affine) if 'rd' in save_metrics: RD = radial_diffusivity(dkfit.evals) save_nifti(orad, RD.astype(np.float32), affine) if 'mode' in save_metrics: MODE = get_mode(dkfit.quadratic_form) save_nifti(omode, MODE.astype(np.float32), affine) if 'evec' in save_metrics: save_nifti(oevecs, dkfit.evecs.astype(np.float32), affine) if 'eval' in save_metrics: save_nifti(oevals, dkfit.evals.astype(np.float32), affine) if 'mk' in save_metrics: save_nifti(omk, dkfit.mk().astype(np.float32), affine) if 'ak' in save_metrics: save_nifti(oak, dkfit.ak().astype(np.float32), affine) if 'rk' in save_metrics: save_nifti(ork, dkfit.rk().astype(np.float32), affine) logging.info('DKI metrics saved in {0}'.format( os.path.dirname(oevals)))
def run(self, input_files, bvalues_files, bvectors_files, mask_files, b0_threshold=0.0, bvecs_tol=0.01, save_metrics=[], out_dir='', out_tensor='tensors.nii.gz', out_fa='fa.nii.gz', out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz', out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz', out_evec='evecs.nii.gz', out_eval='evals.nii.gz'): """ Workflow for tensor reconstruction and for computing DTI metrics. using Weighted Least-Squares. Performs a tensor reconstruction on the files by 'globing' ``input_files`` and saves the DTI metrics in a directory specified by ``out_dir``. Parameters ---------- input_files : string Path to the input volumes. This path may contain wildcards to process multiple inputs at once. bvalues_files : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. bvectors_files : string Path to the bvectors files. This path may contain wildcards to use multiple bvectors files at once. mask_files : string Path to the input masks. This path may contain wildcards to use multiple masks at once. (default: No mask used) b0_threshold : float, optional Threshold used to find b=0 directions (default 0.0) bvecs_tol : float, optional Threshold used to check that norm(bvec) = 1 +/- bvecs_tol b-vectors are unit vectors (default 0.01) save_metrics : variable string, optional List of metrics to save. Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval (default [] (all)) out_dir : string, optional Output directory (default input file directory) out_tensor : string, optional Name of the tensors volume to be saved (default 'tensors.nii.gz') out_fa : string, optional Name of the fractional anisotropy volume to be saved (default 'fa.nii.gz') out_ga : string, optional Name of the geodesic anisotropy volume to be saved (default 'ga.nii.gz') out_rgb : string, optional Name of the color fa volume to be saved (default 'rgb.nii.gz') out_md : string, optional Name of the mean diffusivity volume to be saved (default 'md.nii.gz') out_ad : string, optional Name of the axial diffusivity volume to be saved (default 'ad.nii.gz') out_rd : string, optional Name of the radial diffusivity volume to be saved (default 'rd.nii.gz') out_mode : string, optional Name of the mode volume to be saved (default 'mode.nii.gz') out_evec : string, optional Name of the eigenvectors volume to be saved (default 'evecs.nii.gz') out_eval : string, optional Name of the eigenvalues to be saved (default 'evals.nii.gz') References ---------- .. [1] Basser, P.J., Mattiello, J., LeBihan, D., 1994. Estimation of the effective self-diffusion tensor from the NMR spin echo. J Magn Reson B 103, 247-254. .. [2] Basser, P., Pierpaoli, C., 1996. Microstructural and physiological features of tissues elucidated by quantitative diffusion-tensor MRI. Journal of Magnetic Resonance 111, 209-219. .. [3] Lin-Ching C., Jones D.K., Pierpaoli, C. 2005. RESTORE: Robust estimation of tensors by outlier rejection. MRM 53: 1088-1095 .. [4] hung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap approaches for estimation of uncertainties of DTI parameters. NeuroImage 33, 531-541. """ io_it = self.get_io_iterator() for dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, \ omode, oevecs, oevals in io_it: logging.info('Computing DTI metrics for {0}'.format(dwi)) img = nib.load(dwi) data = img.get_data() affine = img.affine if mask is not None: mask = nib.load(mask).get_data().astype(np.bool) tenfit, _ = self.get_fitted_tensor(data, mask, bval, bvec, b0_threshold, bvecs_tol) if not save_metrics: save_metrics = [ 'fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode', 'evec', 'eval', 'tensor' ] FA = fractional_anisotropy(tenfit.evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if 'tensor' in save_metrics: tensor_vals = lower_triangular(tenfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] fiber_tensors = nib.Nifti1Image( tensor_vals_reordered.astype(np.float32), affine) nib.save(fiber_tensors, otensor) if 'fa' in save_metrics: fa_img = nib.Nifti1Image(FA.astype(np.float32), affine) nib.save(fa_img, ofa) if 'ga' in save_metrics: GA = geodesic_anisotropy(tenfit.evals) ga_img = nib.Nifti1Image(GA.astype(np.float32), affine) nib.save(ga_img, oga) if 'rgb' in save_metrics: RGB = color_fa(FA, tenfit.evecs) rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine) nib.save(rgb_img, orgb) if 'md' in save_metrics: MD = mean_diffusivity(tenfit.evals) md_img = nib.Nifti1Image(MD.astype(np.float32), affine) nib.save(md_img, omd) if 'ad' in save_metrics: AD = axial_diffusivity(tenfit.evals) ad_img = nib.Nifti1Image(AD.astype(np.float32), affine) nib.save(ad_img, oad) if 'rd' in save_metrics: RD = radial_diffusivity(tenfit.evals) rd_img = nib.Nifti1Image(RD.astype(np.float32), affine) nib.save(rd_img, orad) if 'mode' in save_metrics: MODE = get_mode(tenfit.quadratic_form) mode_img = nib.Nifti1Image(MODE.astype(np.float32), affine) nib.save(mode_img, omode) if 'evec' in save_metrics: evecs_img = nib.Nifti1Image(tenfit.evecs.astype(np.float32), affine) nib.save(evecs_img, oevecs) if 'eval' in save_metrics: evals_img = nib.Nifti1Image(tenfit.evals.astype(np.float32), affine) nib.save(evals_img, oevals) dname_ = os.path.dirname(oevals) if dname_ == '': logging.info('DTI metrics saved in current directory') else: logging.info('DTI metrics saved in {0}'.format(dname_))
def run(self, input_files, bvalues_files, bvectors_files, mask_files, b0_threshold=50.0, save_metrics=[], out_dir='', out_dt_tensor='dti_tensors.nii.gz', out_fa='fa.nii.gz', out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz', out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz', out_evec='evecs.nii.gz', out_eval='evals.nii.gz', out_dk_tensor="dki_tensors.nii.gz", out_mk="mk.nii.gz", out_ak="ak.nii.gz", out_rk="rk.nii.gz"): """ Workflow for Diffusion Kurtosis reconstruction and for computing DKI metrics. Performs a DKI reconstruction on the files by 'globing' ``input_files`` and saves the DKI metrics in a directory specified by ``out_dir``. Parameters ---------- input_files : string Path to the input volumes. This path may contain wildcards to process multiple inputs at once. bvalues_files : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. bvectors_files : string Path to the bvalues files. This path may contain wildcards to use multiple bvalues files at once. mask_files : string Path to the input masks. This path may contain wildcards to use multiple masks at once. (default: No mask used) b0_threshold : float, optional Threshold used to find b=0 directions (default 0.0) save_metrics : variable string, optional List of metrics to save. Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval (default [] (all)) out_dir : string, optional Output directory (default input file directory) out_dt_tensor : string, optional Name of the tensors volume to be saved (default: 'dti_tensors.nii.gz') out_dk_tensor : string, optional Name of the tensors volume to be saved (default 'dki_tensors.nii.gz') out_fa : string, optional Name of the fractional anisotropy volume to be saved (default 'fa.nii.gz') out_ga : string, optional Name of the geodesic anisotropy volume to be saved (default 'ga.nii.gz') out_rgb : string, optional Name of the color fa volume to be saved (default 'rgb.nii.gz') out_md : string, optional Name of the mean diffusivity volume to be saved (default 'md.nii.gz') out_ad : string, optional Name of the axial diffusivity volume to be saved (default 'ad.nii.gz') out_rd : string, optional Name of the radial diffusivity volume to be saved (default 'rd.nii.gz') out_mode : string, optional Name of the mode volume to be saved (default 'mode.nii.gz') out_evec : string, optional Name of the eigenvectors volume to be saved (default 'evecs.nii.gz') out_eval : string, optional Name of the eigenvalues to be saved (default 'evals.nii.gz') out_mk : string, optional Name of the mean kurtosis to be saved (default: 'mk.nii.gz') out_ak : string, optional Name of the axial kurtosis to be saved (default: 'ak.nii.gz') out_rk : string, optional Name of the radial kurtosis to be saved (default: 'rk.nii.gz') References ---------- .. [1] Tabesh, A., Jensen, J.H., Ardekani, B.A., Helpern, J.A., 2011. Estimation of tensors and tensor-derived measures in diffusional kurtosis imaging. Magn Reson Med. 65(3), 823-836 .. [2] Jensen, Jens H., Joseph A. Helpern, Anita Ramani, Hanzhang Lu, and Kyle Kaczynski. 2005. Diffusional Kurtosis Imaging: The Quantification of Non-Gaussian Water Diffusion by Means of Magnetic Resonance Imaging. MRM 53 (6):1432-40. """ io_it = self.get_io_iterator() for (dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, omode, oevecs, oevals, odk_tensor, omk, oak, ork) in io_it: logging.info('Computing DKI metrics for {0}'.format(dwi)) data, affine = load_nifti(dwi) if mask is not None: mask = nib.load(mask).get_data().astype(np.bool) dkfit, _ = self.get_fitted_tensor(data, mask, bval, bvec, b0_threshold) if not save_metrics: save_metrics = ['mk', 'rk', 'ak', 'fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode', 'evec', 'eval', 'dt_tensor', 'dk_tensor'] evals, evecs, kt = split_dki_param(dkfit.model_params) FA = fractional_anisotropy(evals) FA[np.isnan(FA)] = 0 FA = np.clip(FA, 0, 1) if 'dt_tensor' in save_metrics: tensor_vals = lower_triangular(dkfit.quadratic_form) correct_order = [0, 1, 3, 2, 4, 5] tensor_vals_reordered = tensor_vals[..., correct_order] save_nifti(otensor, tensor_vals_reordered.astype(np.float32), affine) if 'dk_tensor' in save_metrics: save_nifti(odk_tensor, dkfit.kt.astype(np.float32), affine) if 'fa' in save_metrics: save_nifti(ofa, FA.astype(np.float32), affine) if 'ga' in save_metrics: GA = geodesic_anisotropy(dkfit.evals) save_nifti(oga, GA.astype(np.float32), affine) if 'rgb' in save_metrics: RGB = color_fa(FA, dkfit.evecs) save_nifti(orgb, np.array(255 * RGB, 'uint8'), affine) if 'md' in save_metrics: MD = mean_diffusivity(dkfit.evals) save_nifti(omd, MD.astype(np.float32), affine) if 'ad' in save_metrics: AD = axial_diffusivity(dkfit.evals) save_nifti(oad, AD.astype(np.float32), affine) if 'rd' in save_metrics: RD = radial_diffusivity(dkfit.evals) save_nifti(orad, RD.astype(np.float32), affine) if 'mode' in save_metrics: MODE = get_mode(dkfit.quadratic_form) save_nifti(omode, MODE.astype(np.float32), affine) if 'evec' in save_metrics: save_nifti(oevecs, dkfit.evecs.astype(np.float32), affine) if 'eval' in save_metrics: save_nifti(oevals, dkfit.evals.astype(np.float32), affine) if 'mk' in save_metrics: save_nifti(omk, dkfit.mk().astype(np.float32), affine) if 'ak' in save_metrics: save_nifti(oak, dkfit.ak().astype(np.float32), affine) if 'rk' in save_metrics: save_nifti(ork, dkfit.rk().astype(np.float32), affine) logging.info('DKI metrics saved in {0}'. format(os.path.dirname(oevals)))
def to_estimate_dti_maps(path_dwi_input, path_output, file_tensor_fitevecs, file_tensor_fitevals): ref_name_only = utils.to_extract_filename(file_tensor_fitevecs) ref_name_only = ref_name_only[:-9] list_maps = [] img_tensorFitevecs = nib.load(file_tensor_fitevecs) img_tensorFitevals = nib.load(file_tensor_fitevals) evecs = img_tensorFitevecs.get_data() evals = img_tensorFitevals.get_data() affine = img_tensorFitevecs.affine print(d.separador + d.separador + 'computing of FA map') FA = fractional_anisotropy(evals) FA[np.isnan(FA)] = 0 nib.save(nib.Nifti1Image(FA.astype(np.float32), affine), path_output + ref_name_only + '_FA' + d.extension) list_maps.append(path_output + ref_name_only + '_FA' + d.extension) print(d.separador + d.separador + 'computing of Color FA map') FA2 = np.clip(FA, 0, 1) RGB = color_fa(FA2, evecs) nib.save(nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine), path_output + ref_name_only + '_FA_RGB' + d.extension) print(d.separador + d.separador + 'computing of MD map') MD = dti.mean_diffusivity(evals) nib.save(nib.Nifti1Image(MD.astype(np.float32), affine), path_output + ref_name_only + '_MD' + d.extension) list_maps.append(path_output + ref_name_only + '_MD' + d.extension) print(d.separador + d.separador + 'computing of AD map') AD = dti.axial_diffusivity(evals) nib.save(nib.Nifti1Image(AD.astype(np.float32), affine), path_output + ref_name_only + '_AD' + d.extension) list_maps.append(path_output + ref_name_only + '_AD' + d.extension) print(d.separador + d.separador + 'computing of RD map') RD = dti.radial_diffusivity(evals) nib.save(nib.Nifti1Image(RD.astype(np.float32), affine), path_output + ref_name_only + '_RD' + d.extension) list_maps.append(path_output + ref_name_only + '_RD' + d.extension) sphere = get_sphere('symmetric724') peak_indices = quantize_evecs(evecs, sphere.vertices) eu = EuDX(FA.astype('f8'), peak_indices, seeds=300000, odf_vertices=sphere.vertices, a_low=0.15) tensor_streamlines = [streamline for streamline in eu] hdr = nib.trackvis.empty_header() hdr['voxel_size'] = nib.load(path_dwi_input).get_header().get_zooms()[:3] hdr['voxel_order'] = 'LAS' hdr['dim'] = FA.shape tensor_streamlines_trk = ((sl, None, None) for sl in tensor_streamlines) nib.trackvis.write(path_output + ref_name_only + '_tractography_EuDx.trk', tensor_streamlines_trk, hdr, points_space='voxel') return list_maps