Ejemplo n.º 1
0
def test_mppca_returned_sigma():
    DWIgt = rfiw_phantom(gtab, snr=None)
    std_gt = 0.02
    noise = std_gt * np.random.standard_normal(DWIgt.shape)
    DWInoise = DWIgt + noise

    # Case that sigma is estimated using mpPCA
    DWIden0, sigma = mppca(DWInoise, patch_radius=2, return_sigma=True)
    msigma = np.mean(sigma)
    std_error = abs(msigma - std_gt) / std_gt * 100
    assert_(std_error < 5)

    # Case that sigma is inputed (sigma outputed should be the same as the one
    # inputed)
    DWIden1, rsigma = genpca(DWInoise,
                             sigma=sigma,
                             tau_factor=None,
                             patch_radius=2,
                             return_sigma=True)
    assert_array_almost_equal(rsigma, sigma)

    # DWIden1 should be very similar to DWIden0
    rmse_den = np.sum(np.abs(DWIden1 - DWIden0)) / np.sum(np.abs(DWIden0))
    rmse_ref = np.sum(np.abs(DWIden1 - DWIgt)) / np.sum(np.abs(DWIgt))
    assert_(rmse_den < rmse_ref)
Ejemplo n.º 2
0
    def run(self, input_files, patch_radius=2, pca_method='eig',
            return_sigma=False, out_dir='', out_denoised='dwi_mppca.nii.gz',
            out_sigma='dwi_sigma.nii.gz'):
        r"""Workflow wrapping Marcenko-Pastur PCA denoising method.

        Parameters
        ----------
        input_files : string
            Path to the input volumes. This path may contain wildcards to
            process multiple inputs at once.
        patch_radius : variable 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.
        return_sigma : bool, optional
            If true, a noise standard deviation estimate based on the
            Marcenko-Pastur distribution is returned [2]_.
        out_dir : string, optional
            Output directory. (default current directory)
        out_denoised : string, optional
            Name of the resulting denoised volume.
        out_sigma : string, optional
            Name of the resulting sigma 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.

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

            denoised_data, sigma = mppca(data, patch_radius=patch_radius,
                                         pca_method=pca_method,
                                         return_sigma=True)

            save_nifti(odenoised, denoised_data, affine, image.header)
            logging.info('Denoised volume saved as %s', odenoised)
            if return_sigma:
                save_nifti(osigma, sigma, affine, image.header)
                logging.info('Sigma volume saved as %s', osigma)
Ejemplo n.º 3
0
def test_mppca_in_phantom():
    DWIgt = rfiw_phantom(gtab, snr=None)
    std_gt = 0.02
    noise = std_gt * np.random.standard_normal(DWIgt.shape)
    DWInoise = DWIgt + noise
    DWIden = mppca(DWInoise, patch_radius=2)

    # Test if denoised data is closer to ground truth than noisy data
    rmse_den = np.sum(np.abs(DWIgt - DWIden)) / np.sum(np.abs(DWIgt))
    rmse_noisy = np.sum(np.abs(DWIgt - DWInoise)) / np.sum(np.abs(DWIgt))
    assert_(rmse_den < rmse_noisy)
Ejemplo n.º 4
0
gtab = gradient_table(bvals[sel_b], bvecs[sel_b])

print(data.shape)
"""
As one can see from its shape, the selected data contains a total of 67
volumes of images corresponding to all the diffusion gradient directions
of the selected b-values.

The PCA denoising using the Marcenko-Pastur distribution can be performed by
calling the function ``mppca``:
"""

t = time()

denoised_arr = mppca(data, patch_radius=2)

print("Time taken for local MP-PCA ", -t + time())
"""
Internally, the ``mppca`` algorithm denoises the diffusion-weighted data
using a 3D sliding window which is defined by the variable patch_radius.
In total, this window should comprise a larger number of voxels than the number
of diffusion-weighted volumes. Since our data has a total of 67 volumes, the
patch_radius is set to 2 which corresponds to a 5x5x5 sliding window
comprising a total of 125 voxels.

To assess the performance of the Marcenko-Pastur PCA denoising algorithm,
an axial slice of the original data, denoised data, and residuals are plotted
below:
"""
Ejemplo n.º 5
0
gtab = gradient_table(bvals[sel_b], bvecs[sel_b])
"""
We make use of the ``median_otsu`` method to generate the mask for the data as
follows:
"""

b0_mask, mask = median_otsu(data, median_radius=2, numpass=1, vol_idx=[0, 1])

print(data.shape)
"""
As one can see from its shape, the selected data contains a total of 67
volumes of images corresponding to all the diffusion gradient directions
of the selected b-values and call the ``mppca`` as follows:
"""

denoised_arr = mppca(data, mask=mask, patch_radius=2)
"""
Now we will use the denoised array (``denoised_arr``) obtained from ``mppca``
in the rest of the steps in the tutorial.

As for the next step, we generate the anisotropic powermap introduced by
[DellAcqua2014]_. To do so, we make use of the Q-ball Model as follows:
"""

qball_model = shm.QballModel(gtab, 8)
"""
We generate the peaks from the ``qball_model`` as follows:
"""

peaks = dp.peaks_from_model(model=qball_model,
                            data=denoised_arr,
Ejemplo n.º 6
0
                             autocrop=False,
                             dilate=1)
"""
Since the diffusion kurtosis models involves the estimation of a large number
of parameters [TaxCMW2015]_ and since the non-Gaussian components of the
diffusion signal are more sensitive to artefacts [NetoHe2012]_, it might be
favorable to suppress the effects of noise and artefacts before diffusion
kurtosis fitting. In this example the effects of noise are suppressed using the
Marcenko-Pastur PCA denoising algorithm (:ref:`example-denoise-mppca`) and
the Gibbs artefact suppression algorithm (:ref:`example-denoise-gibbs`). Due
to the dataset's large number of diffusion-weighted volumes, these algorithm
might take some hours to process.
"""

print("Denoising")
den, sig = mppca(data, patch_radius=4, return_sigma=True)

print("Removing Gibbs artifacts")
deng = gibbs_removal(den, slice_axis=2)

# img = nib.load('denoised_mppca.nii.gz')
# img = nib.load('data_mppca_gibbs.nii.gz')
# deng = img.get_fdata()
""" Before carrying on with dki processing, I will just visually inspect the
quality of data and preprocessing step. In the figure below, I am ploting a
slice of the raw and denoised + gibbs suppressed data (upper panels).  Lower
left panel show the difference between raw and denoised data - this difference
map does not present anatomicaly information, indicating that PCA denoising
suppression noise with minimal low of anatomical information. Lower right map
shows the noise std estimate. Lower noise std values are underestimated in
background since noise in background appraoches a Rayleigh distribution.