Example #1
0
def test_lpca_boundary_behaviour():
    # check is first slice is getting denoised or not ?
    S0 = 100 * np.ones((20, 20, 20, 20), dtype='f8')
    S0[:, :, 0, :] = S0[:, :, 0, :] + 2 * \
        np.random.standard_normal((20, 20, 20))
    S0_first = S0[:, :, 0, :]
    S0ns = localpca(S0, sigma=np.std(S0))
    S0ns_first = S0ns[:, :, 0, :]
    rmses = np.sum(np.abs(S0ns_first - S0_first)) / \
        (100.0 * 20.0 * 20.0 * 20.0)

    # shows that S0n_first is not very close to S0_first
    assert_(rmses > 0.0001)
    assert_equal(np.round(S0ns_first.mean()), 100)

    # Use a volume of sigma, instead of a scalar:
    sigma_vol = np.ones(S0.shape[:-1]) * np.std(S0)
    S0ns = localpca(S0, sigma=sigma_vol)

    rmses = np.sum(np.abs(S0ns_first - S0_first)) / \
        (100.0 * 20.0 * 20.0 * 20.0)

    # shows that S0n_first is not very close to S0_first
    assert_(rmses > 0.0001)
    assert_equal(np.round(S0ns_first.mean()), 100)
Example #2
0
def test_lpca_boundary_behaviour():
    # check is first slice is getting denoised or not ?
    S0 = 100 * np.ones((20, 20, 20, 20), dtype='f8')
    S0[:, :, 0, :] = S0[:, :, 0, :] + 2 * \
        np.random.standard_normal((20, 20, 20))
    S0_first = S0[:, :, 0, :]
    S0ns = localpca(S0, sigma=np.std(S0))
    S0ns_first = S0ns[:, :, 0, :]
    rmses = np.sum(np.abs(S0ns_first - S0_first)) / \
        (100.0 * 20.0 * 20.0 * 20.0)

    # shows that S0n_first is not very close to S0_first
    assert_(rmses > 0.0001)
    assert_equal(np.round(S0ns_first.mean()), 100)

    # Use a volume of sigma, instead of a scalar:
    sigma_vol = np.ones(S0.shape[:-1]) * np.std(S0)
    S0ns = localpca(S0, sigma=sigma_vol)

    rmses = np.sum(np.abs(S0ns_first - S0_first)) / \
        (100.0 * 20.0 * 20.0 * 20.0)

    # shows that S0n_first is not very close to S0_first
    assert_(rmses > 0.0001)
    assert_equal(np.round(S0ns_first.mean()), 100)
Example #3
0
def test_phantom():
    gtab = gen_gtab()
    DWI_clean = rfiw_phantom(gtab, snr=None)
    DWI, sigma = rfiw_phantom(gtab, snr=30)
    # To test without rician correction
    temp = (DWI_clean / sigma)**2
    DWI_clean_wrc = (sigma * np.sqrt(np.pi / 2) * np.exp(-0.5 * temp) *
                     ((1 + 0.5 * temp) * sps.iv(0, 0.25 * temp) +
                      0.5 * temp * sps.iv(1, 0.25 * temp))**2)

    DWI_den = localpca(DWI, sigma, patch_radius=3)
    rmse_den = np.sum(np.abs(DWI_clean - DWI_den)) / np.sum(np.abs(DWI_clean))
    rmse_noisy = np.sum(np.abs(DWI_clean - DWI)) / np.sum(np.abs(DWI_clean))

    rmse_den_wrc = np.sum(np.abs(DWI_clean_wrc - DWI_den)) / np.sum(
        np.abs(DWI_clean_wrc))
    rmse_noisy_wrc = np.sum(np.abs(DWI_clean_wrc - DWI)) / \
        np.sum(np.abs(DWI_clean_wrc))

    assert_(np.max(DWI_clean) / sigma < np.max(DWI_den) / sigma)
    assert_(np.max(DWI_den) / sigma < np.max(DWI) / sigma)
    assert_(rmse_den < rmse_noisy)
    assert_(rmse_den_wrc < rmse_noisy_wrc)

    # Check if the results of different PCA methods (eig, svd) are similar
    DWI_den_svd = localpca(DWI, sigma, pca_method='svd', patch_radius=3)
    assert_array_almost_equal(DWI_den, DWI_den_svd)

    assert_raises(ValueError, localpca, DWI, sigma, pca_method='empty')

    # Try this with a sigma volume, instead of a scalar
    sigma_vol = sigma * np.ones(DWI.shape[:-1])
    mask = np.zeros_like(DWI, dtype=bool)[..., 0]
    mask[2:-2, 2:-2, 2:-2] = True
    DWI_den = localpca(DWI, sigma_vol, mask, patch_radius=3)
    DWI_clean_masked = DWI_clean.copy()
    DWI_clean_masked[~mask] = 0
    DWI_masked = DWI.copy()
    DWI_masked[~mask] = 0
    rmse_den = np.sum(np.abs(DWI_clean_masked - DWI_den)) / np.sum(
        np.abs(DWI_clean_masked))
    rmse_noisy = np.sum(np.abs(DWI_clean_masked - DWI_masked)) / np.sum(
        np.abs(DWI_clean_masked))

    DWI_clean_wrc_masked = DWI_clean_wrc.copy()
    DWI_clean_wrc_masked[~mask] = 0
    rmse_den_wrc = np.sum(np.abs(DWI_clean_wrc_masked - DWI_den)) / np.sum(
        np.abs(DWI_clean_wrc_masked))
    rmse_noisy_wrc = np.sum(np.abs(DWI_clean_wrc_masked - DWI_masked)) / \
        np.sum(np.abs(DWI_clean_wrc_masked))

    assert_(np.max(DWI_clean) / sigma < np.max(DWI_den) / sigma)
    assert_(np.max(DWI_den) / sigma < np.max(DWI) / sigma)
    assert_(rmse_den < rmse_noisy)
    assert_(rmse_den_wrc < rmse_noisy_wrc)
Example #4
0
def test_phantom():
    gtab = gen_gtab()
    DWI_clean = rfiw_phantom(gtab, snr=None)
    DWI, sigma = rfiw_phantom(gtab, snr=30)
    # To test without rician correction
    temp = (DWI_clean / sigma)**2
    DWI_clean_wrc = (sigma * np.sqrt(np.pi / 2) * np.exp(-0.5 * temp) *
                     ((1 + 0.5 * temp) * sps.iv(0, 0.25 * temp) + 0.5 * temp *
                     sps.iv(1, 0.25 * temp))**2)

    DWI_den = localpca(DWI, sigma, patch_radius=3)
    rmse_den = np.sum(np.abs(DWI_clean - DWI_den)) / np.sum(np.abs(DWI_clean))
    rmse_noisy = np.sum(np.abs(DWI_clean - DWI)) / np.sum(np.abs(DWI_clean))

    rmse_den_wrc = np.sum(np.abs(DWI_clean_wrc - DWI_den)
                          ) / np.sum(np.abs(DWI_clean_wrc))
    rmse_noisy_wrc = np.sum(np.abs(DWI_clean_wrc - DWI)) / \
        np.sum(np.abs(DWI_clean_wrc))

    assert_(np.max(DWI_clean) / sigma < np.max(DWI_den) / sigma)
    assert_(np.max(DWI_den) / sigma < np.max(DWI) / sigma)
    assert_(rmse_den < rmse_noisy)
    assert_(rmse_den_wrc < rmse_noisy_wrc)

    # Check if the results of different PCA methods (eig, svd) are similar
    DWI_den_svd = localpca(DWI, sigma, pca_method='svd', patch_radius=3)
    assert_array_almost_equal(DWI_den, DWI_den_svd)

    assert_raises(ValueError, localpca, DWI, sigma, pca_method='empty')

    # Try this with a sigma volume, instead of a scalar
    sigma_vol = sigma * np.ones(DWI.shape[:-1])
    mask = np.zeros_like(DWI, dtype=bool)[..., 0]
    mask[2:-2, 2:-2, 2:-2] = True
    DWI_den = localpca(DWI, sigma_vol, mask, patch_radius=3)
    DWI_clean_masked = DWI_clean.copy()
    DWI_clean_masked[~mask] = 0
    DWI_masked = DWI.copy()
    DWI_masked[~mask] = 0
    rmse_den = np.sum(np.abs(DWI_clean_masked - DWI_den)) / np.sum(np.abs(
            DWI_clean_masked))
    rmse_noisy = np.sum(np.abs(DWI_clean_masked - DWI_masked)) / np.sum(np.abs(
            DWI_clean_masked))

    DWI_clean_wrc_masked = DWI_clean_wrc.copy()
    DWI_clean_wrc_masked[~mask] = 0
    rmse_den_wrc = np.sum(np.abs(DWI_clean_wrc_masked - DWI_den)
                          ) / np.sum(np.abs(DWI_clean_wrc_masked))
    rmse_noisy_wrc = np.sum(np.abs(DWI_clean_wrc_masked - DWI_masked)) / \
        np.sum(np.abs(DWI_clean_wrc_masked))

    assert_(np.max(DWI_clean) / sigma < np.max(DWI_den) / sigma)
    assert_(np.max(DWI_den) / sigma < np.max(DWI) / sigma)
    assert_(rmse_den < rmse_noisy)
    assert_(rmse_den_wrc < rmse_noisy_wrc)
Example #5
0
 def _preprocess(self, data_container: DataContainer) -> DataContainer:
     dc = super()._preprocess(data_container)
     sigma = pca_noise_estimate(dc.dwi, dc.gtab, correct_bias=True,
                                smooth=self.smooth)
     dwi = localpca(dc.dwi, sigma=sigma,
                    patch_radius=self.patch_radius)
     return DataContainer(dc.bvals, dc.bvecs, dc.gtab, dc.t1, dwi, dc.aff, dc.binary_mask, dc.b0, dc.fa)
Example #6
0
def test_lpca_random_noise():
    S0 = 100 + 2 * np.random.standard_normal((22, 23, 30, 20))
    S0ns = localpca(S0, sigma=np.std(S0))

    assert_(S0ns.min() > S0.min())
    assert_(S0ns.max() < S0.max())
    assert_equal(np.round(S0ns.mean()), 100)
Example #7
0
def test_lpca_rmse():
    S0_w_noise = 100 + 2 * np.random.standard_normal((22, 23, 30, 20))
    rmse_w_noise = np.sqrt(np.mean((S0_w_noise - 100)**2))
    S0_denoised = localpca(S0_w_noise, sigma=np.std(S0_w_noise))
    rmse_denoised = np.sqrt(np.mean((S0_denoised - 100)**2))
    # Denoising should always improve the RMSE:
    assert_(rmse_denoised < rmse_w_noise)
Example #8
0
def test_lpca_rmse():
    S0_w_noise = 100 + 2 * np.random.standard_normal((22, 23, 30, 20))
    rmse_w_noise = np.sqrt(np.mean((S0_w_noise - 100) ** 2))
    S0_denoised = localpca(S0_w_noise, sigma=np.std(S0_w_noise))
    rmse_denoised = np.sqrt(np.mean((S0_denoised - 100) ** 2))
    # Denoising should always improve the RMSE:
    assert_(rmse_denoised < rmse_w_noise)
Example #9
0
def test_lpca_random_noise():
    S0 = 100 + 2 * np.random.standard_normal((22, 23, 30, 20))
    S0ns = localpca(S0, sigma=np.std(S0))

    assert_(S0ns.min() > S0.min())
    assert_(S0ns.max() < S0.max())
    assert_equal(np.round(S0ns.mean()), 100)
def denoise(diff, gtab, affine_diff):
    # PCA-based denoising algorithms are effective denoising methods because they explore the redundancy of the multi-dimensional information of diffusion-weighted datasets.

    sigma = dipy.denoise.pca_noise_estimate.pca_noise_estimate(
        diff, gtab, correct_bias=True, smooth=3)
    den = localpca(diff, sigma, tau_factor=2.3, patch_radius=2)
    nib.save(nib.Nifti1Image(den, affine_diff), 'denoised.nii.gz')
    return den
Example #11
0
    def _retrieve_data(self, file_names, denoise=False, b0_threshold=10):
        """
        Reads data from specific files and returns them as object.

        This functions reads the filenames of the DWI image and loads/parses them accordingly.
        Also, it denoises them, if specified and generates a b0 image.

        The `file_names` param should be a dict with the following keys:
        `['bvals', 'bvecs', 'img', 't1', 'mask']`

        Parameters
        ----------
        file_names : dict
            The filenames, or relative paths from `self.path`.
        denoise : bool, optional
            A boolean indicating wether the given data should be denoised, by default False
        b0_threshold : float, optional
            A single value indicating the b0 threshold used for b0 calculation, by default 10.0

        Returns
        -------
        RawData
            An object holding all data as attributes, usable for further processing.

        Raises
        ------
        DataContainerNotLoadableError
            This error is thrown if one or multiple files cannot be found.
        """
        data = RawData()
        try:
            data.bvals, data.bvecs = read_bvals_bvecs(os.path.join(self.path, file_names['bvals']),
                                                      os.path.join(self.path, file_names['bvecs']))
            data.img = nb.load(os.path.join(self.path, file_names['img']))
            data.t1 = nb.load(os.path.join(self.path, file_names['t1'])).get_data()
        except FileNotFoundError as error:
            raise DataContainerNotLoadableError(self.path, error.filename) from None

        data.gtab = gradient_table(bvals=data.bvals, bvecs=data.bvecs)
        data.dwi = data.img.get_data().astype("float32")
        data.aff = data.img.affine
        data.fa = None

        if denoise:
            sigma = pca_noise_estimate(data.dwi, data.gtab, correct_bias=True,
                                       smooth=Config.get_config().getint("denoise", "smooth",
                                                                         fallback="3"))
            data.dwi = localpca(data.dwi, sigma=sigma,
                                patch_radius=Config.get_config().getint("denoise", "pathRadius",
                                                                        fallback="2"))
        if 'mask' in file_names:
            data.binarymask = nb.load(os.path.join(self.path, file_names['mask'])).get_data()
        else:
            _, data.binarymask = median_otsu(data.dwi[..., 0], 2, 1)

        data.b0 = data.dwi[..., data.bvals < b0_threshold].mean(axis=-1)

        return data
Example #12
0
def test_lpca_sharpness():
    S0 = np.ones((30, 30, 30, 20), dtype=np.float64) * 100
    S0[10:20, 10:20, 10:20, :] = 50
    S0[20:30, 20:30, 20:30, :] = 0
    S0 = S0 + 20 * np.random.standard_normal((30, 30, 30, 20))
    S0ns = localpca(S0, sigma=20.0)
    # check the edge gradient
    edgs = np.abs(np.mean(S0ns[8, 10:20, 10:20] - S0ns[12, 10:20, 10:20]) - 50)
    assert_(edgs < 2)
Example #13
0
def test_lpca_sharpness():
    S0 = np.ones((30, 30, 30, 20), dtype=np.float64) * 100
    S0[10:20, 10:20, 10:20, :] = 50
    S0[20:30, 20:30, 20:30, :] = 0
    S0 = S0 + 20 * np.random.standard_normal((30, 30, 30, 20))
    S0ns = localpca(S0, sigma=20.0)
    # check the edge gradient
    edgs = np.abs(np.mean(S0ns[8, 10:20, 10:20] - S0ns[12, 10:20, 10:20]) - 50)
    assert_(edgs < 2)
Example #14
0
def test_phantom():
    gtab = gen_gtab()
    DWI_clean = rfiw_phantom(gtab, snr=None)
    DWI, sigma = rfiw_phantom(gtab, snr=30)
    # To test without rician correction
    temp = (DWI_clean / sigma)**2
    DWI_clean_wrc = (sigma * np.sqrt(np.pi / 2) * np.exp(-0.5 * temp) *
                     ((1 + 0.5 * temp) * sps.iv(0, 0.25 * temp) +
                      0.5 * temp * sps.iv(1, 0.25 * temp))**2)

    DWI_den = localpca(DWI, sigma, patch_radius=3)
    rmse_den = np.sum(np.abs(DWI_clean - DWI_den)) / np.sum(np.abs(DWI_clean))
    rmse_noisy = np.sum(np.abs(DWI_clean - DWI)) / np.sum(np.abs(DWI_clean))

    rmse_den_wrc = np.sum(np.abs(DWI_clean_wrc - DWI_den)) / np.sum(
        np.abs(DWI_clean_wrc))
    rmse_noisy_wrc = np.sum(np.abs(DWI_clean_wrc - DWI)) / \
        np.sum(np.abs(DWI_clean_wrc))

    assert_(np.max(DWI_clean) / sigma < np.max(DWI_den) / sigma)
    assert_(np.max(DWI_den) / sigma < np.max(DWI) / sigma)
    assert_(rmse_den < rmse_noisy)
    assert_(rmse_den_wrc < rmse_noisy_wrc)

    # Try this with a sigma volume, instead of a scalar
    sigma_vol = sigma * np.ones(DWI.shape[:-1])
    DWI_den = localpca(DWI, sigma_vol, patch_radius=3)
    rmse_den = np.sum(np.abs(DWI_clean - DWI_den)) / np.sum(np.abs(DWI_clean))
    rmse_noisy = np.sum(np.abs(DWI_clean - DWI)) / np.sum(np.abs(DWI_clean))

    rmse_den_wrc = np.sum(np.abs(DWI_clean_wrc - DWI_den)) / np.sum(
        np.abs(DWI_clean_wrc))
    rmse_noisy_wrc = np.sum(np.abs(DWI_clean_wrc - DWI)) / \
        np.sum(np.abs(DWI_clean_wrc))

    assert_(np.max(DWI_clean) / sigma < np.max(DWI_den) / sigma)
    assert_(np.max(DWI_den) / sigma < np.max(DWI) / sigma)
    assert_(rmse_den < rmse_noisy)
    assert_(rmse_den_wrc < rmse_noisy_wrc)
Example #15
0
def test_lpca_dtype():
    # If out_dtype is not specified, we retain the original precision:
    S0 = 200 * np.ones((20, 20, 20, 3), dtype=np.float64)
    S0ns = localpca(S0, sigma=1)
    assert_equal(S0.dtype, S0ns.dtype)

    S0 = 200 * np.ones((20, 20, 20, 20), dtype=np.uint16)
    S0ns = localpca(S0, sigma=np.ones((20, 20, 20)))
    assert_equal(S0.dtype, S0ns.dtype)

    # If we set out_dtype, we get what we asked for:
    S0 = 200 * np.ones((20, 20, 20, 20), dtype=np.uint16)
    S0ns = localpca(S0, sigma=np.ones((20, 20, 20)), out_dtype=np.float32)
    assert_equal(np.float32, S0ns.dtype)

    # If we set a few entries to zero, this induces negative entries in the
    # Resulting denoised array:
    S0[5:8, 5:8, 5:8] = 0
    # But if we should always get all non-negative results:
    S0ns = localpca(S0, sigma=np.ones((20, 20, 20)), out_dtype=np.uint16)
    assert_(np.all(S0ns >= 0))
    # And no wrap-around to crazy high values:
    assert_(np.all(S0ns <= 200))
Example #16
0
def test_lpca_dtype():
    # If out_dtype is not specified, we retain the original precision:
    S0 = 200 * np.ones((20, 20, 20, 3), dtype=np.float64)
    S0ns = localpca(S0, sigma=1)
    assert_equal(S0.dtype, S0ns.dtype)

    S0 = 200 * np.ones((20, 20, 20, 20), dtype=np.uint16)
    S0ns = localpca(S0, sigma=np.ones((20, 20, 20)))
    assert_equal(S0.dtype, S0ns.dtype)

    # If we set out_dtype, we get what we asked for:
    S0 = 200 * np.ones((20, 20, 20, 20), dtype=np.uint16)
    S0ns = localpca(S0, sigma=np.ones((20, 20, 20)),
                    out_dtype=np.float32)
    assert_equal(np.float32, S0ns.dtype)

    # If we set a few entries to zero, this induces negative entries in the
    # Resulting denoised array:
    S0[5:8, 5:8, 5:8] = 0
    # But if we should always get all non-negative results:
    S0ns = localpca(S0, sigma=np.ones((20, 20, 20)), out_dtype=np.uint16)
    assert_(np.all(S0ns >= 0))
    # And no wrap-around to crazy high values:
    assert_(np.all(S0ns <= 200))
Example #17
0
def execution(self, context):

    data_vol = aims.read(self.dwi_data.fullPath())
    header = data_vol.header()
    data = vol_to_array(data_vol)
    sigma_vol = aims.read(self.sigma.fullPath())
    sigma = vol_to_array(sigma_vol)
    if self.brain_mask is not None:
        brain_mask_vol = aims.read(self.brain_mask.fullPath())
        brain_mask = vol_to_array(brain_mask_vol)
    else:
        brain_mask = None

    denoised_data = localpca(data,
                             sigma,
                             mask=brain_mask,
                             pca_method=self.method,
                             patch_radius=self.patch_radius,
                             tau_factor=self.tau_factor)
    denoised_data_vol = array_to_vol(denoised_data, header=header)
    aims.write(denoised_data_vol, self.denoised_dwi_data.fullPath())
Example #18
0
def dti_preprocessing(diff_dir,
                      output_dir,
                      denoise=True,
                      ref_slice=0,
                      median_radius=3,
                      numpass=1,
                      autocrop=False,
                      dilate=2,
                      selem=10,
                      output_type="NIFTI"):
    """Function to realign, eddy current correct and eventually denoise diffusion data        
        Parameters
        ----------
        diff_dir : absolute path pointing at directory sub-id_visit-id/dwi where dwi acquisition 
                    (as a single 4D nii or nii file), bvec and bval files are stored
        output_dir: absolute path of the directories were the indexes will be written
        denoise : boolean, should denoise using Marcenko-Pastur PCA algorithm be performed
        fill : boolean, sometimes oshu method create hole in the mask, especially if you are working with populations
                that may have very low values at B0 in certain structures. Fill use erosion based reconstruction methods
                to fill in-mask holes.
        output_type: ["NIFTI", "NIFTI_GZ"], the type of nifti output desired,
        ... : other parameters related to the nipype and dipy functions used
        """
    fdwi = glob("{}/*nii*".format(diff_dir))[0]
    output_base_name = get_base_name_all_type(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))
    ec_out_file = "{}/{}_ec{}".format(output_dir, output_base_name, ext)
    if not (isfile(ec_out_file)):
        ec = EddyCorrect(in_file=fdwi, out_file=ec_out_file)
        ec.inputs.output_type = output_type
        print("Eddy Correction")
        ec.run()
    else:
        print("Skipping EC")
    mask_name, masked_name = custom_brain_extraction(output_base_name,
                                                     ec_out_file, output_dir,
                                                     output_type,
                                                     median_radius, numpass,
                                                     autocrop, dilate, selem)
    if denoise:
        denoised_out_file = "{}/{}_denoised{}".format(output_dir,
                                                      output_base_name, ext)
        if not (isfile(denoised_out_file)):
            print("Denoising")
            fbval = glob("{}/*bval".format(diff_dir))[0]
            fbvec = glob("{}/*bvec".format(diff_dir))[0]
            bvals, bvecs = read_bvals_bvecs(fbval, fbvec)
            gtab = gradient_table(bvals, bvecs)
            img = nb.load(masked_name)
            mask = nb.load(mask_name)
            x_ix, y_ix, z_ix, mask_crop, maskdata_crop = crop_and_indexes(
                mask, img)
            sigma = pca_noise_estimate(maskdata_crop,
                                       gtab,
                                       correct_bias=True,
                                       smooth=3)
            denoised_arr = localpca(maskdata_crop,
                                    sigma,
                                    tau_factor=2.3,
                                    patch_radius=2)
            opt = np.zeros(img.shape)
            opt[x_ix, y_ix, z_ix, :] = denoised_arr
            den_img = nb.Nifti1Image(opt.astype(np.float32), img.affine)
            nb.save(den_img, denoised_out_file)
Example #19
0
    def run(self,
            input_files,
            bvalues_files,
            bvectors_files,
            sigma=0,
            b0_threshold=50,
            bvecs_tol=0.01,
            patch_radius=2,
            pca_method='eig',
            tau_factor=2.3,
            out_dir='',
            out_denoised='dwi_lpca.nii.gz'):
        r"""Workflow wrapping LPCA denoising method.

        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.
        sigma : float, optional
            Standard deviation of the noise estimated from the data.
            Default 0: it means sigma value estimation with the Manjon2013
            algorithm [3]_.
        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.
        patch_radius : int, optional
            The radius of the local patch to be taken around each voxel (in
            voxels) For example, for a patch radius with value 2, and assuming
            the input image is a 3D image, the denoising will take place in
            blocks of 5x5x5 voxels.
        pca_method : string, optional
            Use either eigenvalue decomposition ('eig') or singular value
            decomposition ('svd') for principal component analysis. The default
            method is 'eig' which is faster. However, occasionally 'svd' might
            be more accurate.
        tau_factor : float, optional
            Thresholding of PCA eigenvalues is done by nulling out eigenvalues
            that are smaller than:

            .. math ::

                    \tau = (\tau_{factor} \sigma)^2

            \tau_{factor} can be change to adjust the relationship between the
            noise standard deviation and the threshold \tau. If \tau_{factor}
            is set to None, it will be automatically calculated using the
            Marcenko-Pastur distribution [2]_.
        out_dir : string, optional
            Output directory. (default current directory)
        out_denoised : string, optional
            Name of the resulting denoised volume.

        References
        ----------
        .. [1] Veraart J, Novikov DS, Christiaens D, Ades-aron B, Sijbers,
        Fieremans E, 2016. Denoising of Diffusion MRI using random
        matrix theory. Neuroimage 142:394-406.
        doi: 10.1016/j.neuroimage.2016.08.016

        .. [2] Veraart J, Fieremans E, Novikov DS. 2016. Diffusion MRI noise
        mapping using random matrix theory. Magnetic Resonance in
        Medicine.
        doi: 10.1002/mrm.26059.

        .. [3] Manjon JV, Coupe P, Concha L, Buades A, Collins DL (2013)
        Diffusion Weighted Image Denoising Using Overcomplete Local
        PCA. PLoS ONE 8(9): e73021.
        https://doi.org/10.1371/journal.pone.0073021

        """
        io_it = self.get_io_iterator()
        for dwi, bval, bvec, odenoised in io_it:
            logging.info('Denoising %s', dwi)
            data, affine, image = load_nifti(dwi, return_img=True)

            if not sigma:
                logging.info('Estimating sigma')
                bvals, bvecs = read_bvals_bvecs(bval, bvec)
                gtab = gradient_table(bvals,
                                      bvecs,
                                      b0_threshold=b0_threshold,
                                      atol=bvecs_tol)
                sigma = pca_noise_estimate(data,
                                           gtab,
                                           correct_bias=True,
                                           smooth=3)
                logging.debug('Found sigma %s', sigma)

            denoised_data = localpca(data,
                                     sigma=sigma,
                                     patch_radius=patch_radius,
                                     pca_method=pca_method,
                                     tau_factor=tau_factor)
            save_nifti(odenoised, denoised_data, affine, image.header)

            logging.info('Denoised volume saved as %s', odenoised)
Example #20
0
def test_lpca_static():
    S0 = 100 * np.ones((20, 20, 20, 20), dtype='f8')
    S0ns = localpca(S0, sigma=np.ones((20, 20, 20), dtype=np.float64))
    assert_array_almost_equal(S0, S0ns)
Example #21
0
def test_lpca_static():
    S0 = 100 * np.ones((20, 20, 20, 20), dtype='f8')
    S0ns = localpca(S0, sigma=np.ones((20, 20, 20), dtype=np.float64))
    assert_array_almost_equal(S0, S0ns)
Example #22
0
from dipy.reconst.dti import TensorModel

duration1 = time() - t1

# print('BIAC006'+' DTI duration %.3f' % (duration1,))

lpca_path = outpath + '/LPCA_' + id + '_nii4D.nii.gz'
if path.exists(lpca_path):
    print('File already exists; Skipping LPCA denoising (path: ' + lpca_path +
          ')')
else:
    print('Beginning LPCA denoising for: ' + id + '.  (Expected result: ' +
          lpca_path + ')')
    t = time()

    print(data.shape)
    data2 = data
    sigma1 = pca_noise_estimate(data2, gtab, correct_bias=True, smooth=1)
    print("Sigma estimation time", time() - t)

    #lpca
    t = time()
    denoised_arr = localpca(data2,
                            sigma=sigma1,
                            patch_radius=2,
                            pca_method='svd',
                            tau_factor=2.3)
    save_nifti(lpca_path, denoised_arr, affine)
    print("Time taken for local PCA denoising", -t + time())
Example #23
0
t = time()
sigma = pca_noise_estimate(data, gtab, correct_bias=True, smooth=3)
print("Sigma estimation time", time() - t)
"""
Perform the localPCA using the function localpca.

The localpca algorithm takes into account for the directional
information in the diffusion MR data. It performs PCA on local 4D patch and
then thresholds it using the local variance estimate done by noise estimation
function, then performing PCA reconstruction on it gives us the deniosed
estimate.
"""

t = time()

denoised_arr = localpca(data, sigma=sigma, patch_radius=2)

print("Time taken for local PCA (slow)", -t + time())
"""
Let us plot the axial slice of the original and denoised data.
We visualize all the slices (22 in total)
"""

sli = data.shape[2] // 2
gra = data.shape[3] // 2
orig = data[:, :, sli, gra]
den = denoised_arr[:, :, sli, gra]
rms_diff = np.sqrt((orig - den)**2)

fig, ax = plt.subplots(1, 3)
ax[0].imshow(orig, cmap='gray', origin='lower', interpolation='none')
Example #24
0
## Perform the localPCA using the function localpca.

The localpca algorithm takes into account the multi-dimensional information of
the diffusion MR data. It performs PCA on local 4D patch and
then removes the noise components by thresholding the lowest eigenvalues.
The eigenvalue threshold will be computed from the local variance estimate
performed by the ``pca_noise_estimate`` function, if this is inputted in the
main ``localpca`` function. The relationship between the noise variance
estimate and the eigenvalue threshold can be adjusted using the input parameter
``tau_factor``. According to Manjon et al. [Manjon2013]_, this parameter is set
to 2.3.
"""

t = time()

denoised_arr = localpca(data, sigma, tau_factor=2.3, patch_radius=2)

print("Time taken for local PCA (slow)", -t + time())
"""
The ``localpca`` function returns the denoised data which is plotted below
(middle panel) together with the original version of the data (left panel) and
the algorithm residual (right panel) .
"""

sli = data.shape[2] // 2
gra = data.shape[3] // 2
orig = data[:, :, sli, gra]
den = denoised_arr[:, :, sli, gra]
rms_diff = np.sqrt((orig - den)**2)

fig, ax = plt.subplots(1, 3)
Example #25
0
def main(dwiFname, bvalFname, bvecFname, oFname, plot):
    """Main."""
    """
    
    Load one of the datasets. These data were acquired with 63 gradients and 1
    non-diffusion (b=0) image.
    
    """

    data, affine = load_nifti(dwiFname)
    bvals, bvecs = read_bvals_bvecs(bvalFname, bvecFname)
    gtab = gradient_table(bvals, bvecs)

    print("Input Volume", data.shape)
    """
    Estimate the noise standard deviation
    =====================================
    
    We use the ``pca_noise_estimate`` method to estimate the value of sigma to be
    used in local PCA algorithm proposed by Manjon et al. [Manjon2013]_.
    It takes both data and the gradient table object as input and returns an
    estimate of local noise standard deviation as a 3D array. We return a smoothed
    version, where a Gaussian filter with radius 3 voxels has been applied to the
    estimate of the noise before returning it.
    
    We correct for the bias due to Rician noise, based on an equation developed by
    Koay and Basser [Koay2006]_.
    
    """

    t = time()
    sigma = pca_noise_estimate(data, gtab, correct_bias=True, smooth=3)
    print("Sigma estimation time", time() - t)
    """
    Perform the localPCA using the function `localpca`
    ==================================================
    
    The localpca algorithm takes into account the multi-dimensional information of
    the diffusion MR data. It performs PCA on local 4D patch and
    then removes the noise components by thresholding the lowest eigenvalues.
    The eigenvalue threshold will be computed from the local variance estimate
    performed by the ``pca_noise_estimate`` function, if this is inputted in the
    main ``localpca`` function. The relationship between the noise variance
    estimate and the eigenvalue threshold can be adjusted using the input parameter
    ``tau_factor``. According to Manjon et al. [Manjon2013]_, this parameter is set
    to 2.3.
    """

    t = time()

    denoised_arr = localpca(data, sigma, tau_factor=2.3, patch_radius=3)

    print("Time taken for local PCA (slow)", -t + time())
    """
    The ``localpca`` function returns the denoised data which is plotted below
    (middle panel) together with the original version of the data (left panel) and
    the algorithm residual (right panel) .
    """
    if plot:

        sli = data.shape[2] // 2
        gra = data.shape[3] // 2
        orig = data[:, :, sli, gra]
        den = denoised_arr[:, :, sli, gra]
        rms_diff = np.sqrt((orig - den)**2)

        fig, ax = plt.subplots(1, 3)
        ax[0].imshow(orig, cmap='gray', origin='lower', interpolation='none')
        ax[0].set_title('Original')
        ax[0].set_axis_off()
        ax[1].imshow(den, cmap='gray', origin='lower', interpolation='none')
        ax[1].set_title('Denoised Output')
        ax[1].set_axis_off()
        ax[2].imshow(rms_diff,
                     cmap='gray',
                     origin='lower',
                     interpolation='none')
        ax[2].set_title('Residual')
        ax[2].set_axis_off()
        plt.savefig(oFname + '.png', bbox_inches='tight')

        print("Result figure saved to: " + oFname + ".png")
    """
    .. figure:: denoised_localpca.png
       :align: center
    
    Below we show how the denoised data can be saved.
    """

    nib.save(nib.Nifti1Image(denoised_arr, affine), oFname + '.nii.gz')

    print("Denoised dataset saved to: " + oFname + ".nii.gz")
    """
Example #26
0
sigma = pca_noise_estimate(data, gtab, correct_bias=True, smooth=3)
print("Sigma estimation time", time() - t)

"""
Perform the localPCA using the function localpca.

The localpca algorithm takes into account for the directional
information in the diffusion MR data. It performs PCA on local 4D patch and
then thresholds it using the local variance estimate done by noise estimation
function, then performing PCA reconstruction on it gives us the deniosed
estimate.
"""

t = time()

denoised_arr = localpca(data, sigma=sigma, patch_radius=2)

print("Time taken for local PCA (slow)", -t + time())

"""
Let us plot the axial slice of the original and denoised data.
We visualize all the slices (22 in total)
"""

sli = data.shape[2] // 2
gra = data.shape[3] // 2
orig = data[:, :, sli, gra]
den = denoised_arr[:, :, sli, gra]
rms_diff = np.sqrt((orig - den) ** 2)

fig, ax = plt.subplots(1, 3)