Example #1
0
def test_peaks_shm_coeff():

    SNR = 100
    S0 = 100

    _, fbvals, fbvecs = get_data('small_64D')

    from dipy.data import get_sphere

    sphere = get_sphere('repulsion724')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))

    data, _ = multi_tensor(gtab,
                           mevals,
                           S0,
                           angles=[(0, 0), (60, 0)],
                           fractions=[50, 50],
                           snr=SNR)

    from dipy.reconst.shm import CsaOdfModel

    model = CsaOdfModel(gtab, 4)

    pam = peaks_from_model(model,
                           data[None, :],
                           sphere,
                           .5,
                           45,
                           return_odf=True,
                           return_sh=True)
    # Test that spherical harmonic coefficients return back correctly
    odf2 = np.dot(pam.shm_coeff, pam.B)
    assert_array_almost_equal(pam.odf, odf2)
    assert_equal(pam.shm_coeff.shape[-1], 45)

    pam = peaks_from_model(model,
                           data[None, :],
                           sphere,
                           .5,
                           45,
                           return_odf=True,
                           return_sh=False)
    assert_equal(pam.shm_coeff, None)

    pam = peaks_from_model(model,
                           data[None, :],
                           sphere,
                           .5,
                           45,
                           return_odf=True,
                           return_sh=True,
                           sh_basis_type='mrtrix')

    odf2 = np.dot(pam.shm_coeff, pam.B)
    assert_array_almost_equal(pam.odf, odf2)
Example #2
0
def test_peaksFromModelParallel():
    SNR = 100
    S0 = 100

    _, fbvals, fbvecs = get_data('small_64D')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003],
                       [0.0015, 0.0003, 0.0003]))

    data, _ = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)],
                           fractions=[50, 50], snr=SNR)

    # test equality with/without multiprocessing
    model = SimpleOdfModel(gtab)
    pam_multi = peaks_from_model(model, data, _sphere, .5, 45,
                                 normalize_peaks=True, return_odf=True,
                                 return_sh=True, parallel=True)

    pam_single = peaks_from_model(model, data, _sphere, .5, 45,
                                  normalize_peaks=True, return_odf=True,
                                  return_sh=True, parallel=False)

    assert_equal(pam_multi.gfa.dtype, pam_single.gfa.dtype)
    assert_equal(pam_multi.gfa.shape, pam_single.gfa.shape)
    assert_array_almost_equal(pam_multi.gfa, pam_single.gfa)

    assert_equal(pam_multi.qa.dtype, pam_single.qa.dtype)
    assert_equal(pam_multi.qa.shape, pam_single.qa.shape)
    assert_array_almost_equal(pam_multi.qa, pam_single.qa)

    assert_equal(pam_multi.peak_values.dtype, pam_single.peak_values.dtype)
    assert_equal(pam_multi.peak_values.shape, pam_single.peak_values.shape)
    assert_array_almost_equal(pam_multi.peak_values, pam_single.peak_values)

    assert_equal(pam_multi.peak_indices.dtype, pam_single.peak_indices.dtype)
    assert_equal(pam_multi.peak_indices.shape, pam_single.peak_indices.shape)
    assert_array_equal(pam_multi.peak_indices, pam_single.peak_indices)

    assert_equal(pam_multi.peak_dirs.dtype, pam_single.peak_dirs.dtype)
    assert_equal(pam_multi.peak_dirs.shape, pam_single.peak_dirs.shape)
    assert_array_almost_equal(pam_multi.peak_dirs, pam_single.peak_dirs)

    assert_equal(pam_multi.shm_coeff.dtype, pam_single.shm_coeff.dtype)
    assert_equal(pam_multi.shm_coeff.shape, pam_single.shm_coeff.shape)
    assert_array_almost_equal(pam_multi.shm_coeff, pam_single.shm_coeff)

    assert_equal(pam_multi.odf.dtype, pam_single.odf.dtype)
    assert_equal(pam_multi.odf.shape, pam_single.odf.shape)
    assert_array_almost_equal(pam_multi.odf, pam_single.odf)
Example #3
0
def test_peaksFromModelParallel():
    SNR = 100
    S0 = 100

    _, fbvals, fbvecs = get_data('small_64D')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003],
                       [0.0015, 0.0003, 0.0003]))

    data, _ = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)],
                           fractions=[50, 50], snr=SNR)

    # test equality with/without multiprocessing
    model = SimpleOdfModel(gtab)
    pam_multi = peaks_from_model(model, data, _sphere, .5, 45,
                                 normalize_peaks=True, return_odf=True,
                                 return_sh=True, parallel=True)

    pam_single = peaks_from_model(model, data, _sphere, .5, 45,
                                  normalize_peaks=True, return_odf=True,
                                  return_sh=True, parallel=False)

    assert_equal(pam_multi.gfa.dtype, pam_single.gfa.dtype)
    assert_equal(pam_multi.gfa.shape, pam_single.gfa.shape)
    assert_array_almost_equal(pam_multi.gfa, pam_single.gfa)

    assert_equal(pam_multi.qa.dtype, pam_single.qa.dtype)
    assert_equal(pam_multi.qa.shape, pam_single.qa.shape)
    assert_array_almost_equal(pam_multi.qa, pam_single.qa)

    assert_equal(pam_multi.peak_values.dtype, pam_single.peak_values.dtype)
    assert_equal(pam_multi.peak_values.shape, pam_single.peak_values.shape)
    assert_array_almost_equal(pam_multi.peak_values, pam_single.peak_values)

    assert_equal(pam_multi.peak_indices.dtype, pam_single.peak_indices.dtype)
    assert_equal(pam_multi.peak_indices.shape, pam_single.peak_indices.shape)
    assert_array_equal(pam_multi.peak_indices, pam_single.peak_indices)

    assert_equal(pam_multi.peak_dirs.dtype, pam_single.peak_dirs.dtype)
    assert_equal(pam_multi.peak_dirs.shape, pam_single.peak_dirs.shape)
    assert_array_almost_equal(pam_multi.peak_dirs, pam_single.peak_dirs)

    assert_equal(pam_multi.shm_coeff.dtype, pam_single.shm_coeff.dtype)
    assert_equal(pam_multi.shm_coeff.shape, pam_single.shm_coeff.shape)
    assert_array_almost_equal(pam_multi.shm_coeff, pam_single.shm_coeff)

    assert_equal(pam_multi.odf.dtype, pam_single.odf.dtype)
    assert_equal(pam_multi.odf.shape, pam_single.odf.shape)
    assert_array_almost_equal(pam_multi.odf, pam_single.odf)
Example #4
0
 def get_fiber_direction(self):
     # Getting fiber direction
     csamodel = shm.CsaOdfModel(self.gtab, 6)
     if self.atlas == "stanford":
         white_matter = binary_dilation((self.labels == 1)
                                        | (self.labels == 2))
     elif self.atlas == "desikan":
         white_matter = binary_dilation((self.labels == 41)
                                        | (self.labels == 2))
     if self.data.shape[:3] == white_matter.shape:
         csapeaks = peaks.peaks_from_model(model=csamodel,
                                           data=self.data,
                                           sphere=peaks.default_sphere,
                                           relative_peak_threshold=.8,
                                           min_separation_angle=45,
                                           mask=white_matter)
         # mask, b0_mask = self.create_mask()
         # self.make_tensor(b0_mask)
         # csd_peaks = self.make_csd(mask, b0_mask)
     else:
         print(f"{LogLVL.lvl1}ERR: dimensions are different:")
         print(f"{LogLVL.lvl2}data shape:         {self.data.shape}")
         print(f"{LogLVL.lvl2}white matter shape: {white_matter.shape}")
         print(f"{LogLVL.lvl1}ERR: cannot continue")
         csapeaks = None
     return csapeaks, white_matter
Example #5
0
def test_peaksFromModel():
    data = np.zeros((10, 2))

    # Test basic case
    model = SimpleOdfModel(_gtab)
    odf_argmax = _odf.argmax()
    pam = peaks_from_model(model, data, _sphere, .5, 45, normalize_peaks=True)

    assert_array_equal(pam.gfa, gfa(_odf))
    assert_array_equal(pam.peak_values[:, 0], 1.)
    assert_array_equal(pam.peak_values[:, 1:], 0.)
    mn, mx = _odf.min(), _odf.max()
    assert_array_equal(pam.qa[:, 0], (mx - mn) / mx)
    assert_array_equal(pam.qa[:, 1:], 0.)
    assert_array_equal(pam.peak_indices[:, 0], odf_argmax)
    assert_array_equal(pam.peak_indices[:, 1:], -1)

    # Test that odf array matches and is right shape
    pam = peaks_from_model(model, data, _sphere, .5, 45, return_odf=True)
    expected_shape = (len(data), len(_odf))
    assert_equal(pam.odf.shape, expected_shape)
    assert_((_odf == pam.odf).all())
    assert_array_equal(pam.peak_values[:, 0], _odf.max())

    # Test mask
    mask = (np.arange(10) % 2) == 1

    pam = peaks_from_model(model,
                           data,
                           _sphere,
                           .5,
                           45,
                           mask=mask,
                           normalize_peaks=True)
    assert_array_equal(pam.gfa[~mask], 0)
    assert_array_equal(pam.qa[~mask], 0)
    assert_array_equal(pam.peak_values[~mask], 0)
    assert_array_equal(pam.peak_indices[~mask], -1)

    assert_array_equal(pam.gfa[mask], gfa(_odf))
    assert_array_equal(pam.peak_values[mask, 0], 1.)
    assert_array_equal(pam.peak_values[mask, 1:], 0.)
    mn, mx = _odf.min(), _odf.max()
    assert_array_equal(pam.qa[mask, 0], (mx - mn) / mx)
    assert_array_equal(pam.qa[mask, 1:], 0.)
    assert_array_equal(pam.peak_indices[mask, 0], odf_argmax)
    assert_array_equal(pam.peak_indices[mask, 1:], -1)
Example #6
0
def test_PeaksAndMetricsDirectionGetter():
    class SillyModel(object):
        def fit(self, data, mask=None):
            return SillyFit(self)

    class SillyFit(object):
        def __init__(self, model):
            self.model = model

        def odf(self, sphere):
            odf = np.zeros(sphere.theta.shape)
            r = np.random.randint(0, len(odf))
            odf[r] = 1
            return odf

    def get_direction(dg, point, dir):
        newdir = dir.copy()
        state = dg.get_direction(point, newdir)
        return (state, np.array(newdir))

    data = np.random.random((3, 4, 5, 2))
    peaks = peaks_from_model(SillyModel(), data, default_sphere, relative_peak_threshold=0.5, min_separation_angle=25)
    peaks._initialize()

    up = np.zeros(3)
    up[2] = 1.0
    down = -up

    for i in range(3 - 1):
        for j in range(4 - 1):
            for k in range(5 - 1):
                point = np.array([i, j, k], dtype=float)

                # Test that the angle threshold rejects points
                peaks.ang_thr = 0.0
                state, nd = get_direction(peaks, point, up)
                npt.assert_equal(state, 1)

                # Here we leverage the fact that we know Hemispheres project
                # all their vertices into the z >= 0 half of the sphere.
                peaks.ang_thr = 90.0
                state, nd = get_direction(peaks, point, up)
                npt.assert_equal(state, 0)
                expected_dir = peaks.peak_dirs[i, j, k, 0]
                npt.assert_array_almost_equal(nd, expected_dir)
                state, nd = get_direction(peaks, point, down)
                npt.assert_array_almost_equal(nd, -expected_dir)

                # Check that we can get directions at non-integer points
                point += np.random.random(3)
                state, nd = get_direction(peaks, point, up)
                npt.assert_equal(state, 0)

                # Check that points are rounded to get initial direction
                point -= 0.5
                id = peaks.initial_direction(point)
                # id should be a (1, 3) array
                npt.assert_array_almost_equal(id, [expected_dir])
Example #7
0
def test_peaksFromModel():
    data = np.zeros((10, 2))

    # Test basic case
    model = SimpleOdfModel(_gtab)
    odf_argmax = _odf.argmax()
    pam = peaks_from_model(model, data, _sphere, .5, 45, normalize_peaks=True)

    assert_array_equal(pam.gfa, gfa(_odf))
    assert_array_equal(pam.peak_values[:, 0], 1.)
    assert_array_equal(pam.peak_values[:, 1:], 0.)
    mn, mx = _odf.min(), _odf.max()
    assert_array_equal(pam.qa[:, 0], (mx - mn) / mx)
    assert_array_equal(pam.qa[:, 1:], 0.)
    assert_array_equal(pam.peak_indices[:, 0], odf_argmax)
    assert_array_equal(pam.peak_indices[:, 1:], -1)

    # Test that odf array matches and is right shape
    pam = peaks_from_model(model, data, _sphere, .5, 45, return_odf=True)
    expected_shape = (len(data), len(_odf))
    assert_equal(pam.odf.shape, expected_shape)
    assert_((_odf == pam.odf).all())
    assert_array_equal(pam.peak_values[:, 0], _odf.max())

    # Test mask
    mask = (np.arange(10) % 2) == 1

    pam = peaks_from_model(model, data, _sphere, .5, 45, mask=mask,
                           normalize_peaks=True)
    assert_array_equal(pam.gfa[~mask], 0)
    assert_array_equal(pam.qa[~mask], 0)
    assert_array_equal(pam.peak_values[~mask], 0)
    assert_array_equal(pam.peak_indices[~mask], -1)

    assert_array_equal(pam.gfa[mask], gfa(_odf))
    assert_array_equal(pam.peak_values[mask, 0], 1.)
    assert_array_equal(pam.peak_values[mask, 1:], 0.)
    mn, mx = _odf.min(), _odf.max()
    assert_array_equal(pam.qa[mask, 0], (mx - mn) / mx)
    assert_array_equal(pam.qa[mask, 1:], 0.)
    assert_array_equal(pam.peak_indices[mask, 0], odf_argmax)
    assert_array_equal(pam.peak_indices[mask, 1:], -1)
Example #8
0
def test_peaks_shm_coeff():

    SNR = 100
    S0 = 100

    _, fbvals, fbvecs = get_data('small_64D')

    from dipy.data import get_sphere

    sphere = get_sphere('repulsion724')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003],
                       [0.0015, 0.0003, 0.0003]))

    data, _ = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (60, 0)],
                           fractions=[50, 50], snr=SNR)

    from dipy.reconst.shm import CsaOdfModel

    model = CsaOdfModel(gtab, 4)

    pam = peaks_from_model(model, data[None, :], sphere, .5, 45,
                           return_odf=True, return_sh=True)
    # Test that spherical harmonic coefficients return back correctly
    odf2 = np.dot(pam.shm_coeff, pam.B)
    assert_array_almost_equal(pam.odf, odf2)
    assert_equal(pam.shm_coeff.shape[-1], 45)

    pam = peaks_from_model(model, data[None, :], sphere, .5, 45,
                           return_odf=True, return_sh=False)
    assert_equal(pam.shm_coeff, None)

    pam = peaks_from_model(model, data[None, :], sphere, .5, 45,
                           return_odf=True, return_sh=True,
                           sh_basis_type='mrtrix')

    odf2 = np.dot(pam.shm_coeff, pam.B)
    assert_array_almost_equal(pam.odf, odf2)
Example #9
0
    def make_csd(self, mask, b0_mask):
        """
            Constrained Spherical Deconvolution (CSD)
            https://dipy.org/documentation/0.16.0./examples_built/tracking_quick_start/
            https://dipy.org/documentation/0.16.0./examples_built/introduction_to_basic_tracking/
            Another kind of tracking : https://dipy.org/documentation/1.2.0./examples_built/tracking_introduction_eudx/#example-tracking-introduction-eudx
                https://github.com/dipy/dipy/blob/master/doc/examples/tracking_deterministic.py
        """
        # we need to estimate the response function and create a model
        response, ratio = auto_response(self.gtab,
                                        self.data,
                                        roi_radius=10,
                                        fa_thr=0.7)
        csd_model = ConstrainedSphericalDeconvModel(self.gtab, response)

        # Using peaks
        sphere = get_sphere('symmetric724')
        csd_peaks = peaks.peaks_from_model(model=csd_model,
                                           data=b0_mask,
                                           sphere=peaks.default_sphere,
                                           mask=mask,
                                           relative_peak_threshold=.5,
                                           min_separation_angle=25,
                                           parallel=True)
        self.save_plot(csd_peaks.gfa[:, :, 35].T, f"{self.subj_id}_csd")
        # Note:The GFA values of the FODs don’t classify gray matter and white matter well
        # View csd_peaks
        # from dipy.viz import window, actor, has_fury, colormap as cmap

        # interactive = True
        # if has_fury:
        #     scene = window.Scene()
        #     scene.add(actor.peak_slicer(csd_peaks.peak_dirs,
        #                                 csd_peaks.peak_values,
        #                                 colors=None))

        #     window.record(scene, out_path='csd_direction_field.png', size=(900, 900))

        #     if interactive:
        #         window.show(scene, size=(800, 800))
        ##  Restrict the fiber tracking to areas with good directionality information using tensor model
        # - with cropped data
        return csd_peaks
Example #10
0
    def run(self,
            input_files,
            bvalues_files,
            bvectors_files,
            mask_files,
            b0_threshold=50.0,
            bvecs_tol=0.01,
            roi_center=None,
            roi_radii=10,
            fa_thr=0.7,
            frf=None,
            extract_pam_values=False,
            sh_order=8,
            odf_to_sh_order=8,
            parallel=False,
            nbr_processes=None,
            out_dir='',
            out_pam='peaks.pam5',
            out_shm='shm.nii.gz',
            out_peaks_dir='peaks_dirs.nii.gz',
            out_peaks_values='peaks_values.nii.gz',
            out_peaks_indices='peaks_indices.nii.gz',
            out_gfa='gfa.nii.gz'):
        """ Constrained spherical deconvolution

        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 b0 volumes.
        bvecs_tol : float, optional
            Bvecs should be unit vectors.
        roi_center : variable int, optional
            Center of ROI in data. If center is None, it is assumed that it is
            the center of the volume with shape `data.shape[:3]`.
        roi_radii : int or array-like, optional
            radii of cuboid ROI in voxels.
        fa_thr : float, optional
            FA threshold for calculating the response function.
        frf : variable float, optional
            Fiber response function can be for example inputed as 15 4 4
            (from the command line) or [15, 4, 4] from a Python script to be
            converted to float and multiplied by 10**-4 . If None
            the fiber response function will be computed automatically.
        extract_pam_values : bool, optional
            Save or not to save pam volumes as single nifti files.
        sh_order : int, optional
            Spherical harmonics order used in the CSA fit.
        odf_to_sh_order : int, optional
            Spherical harmonics order used for peak_from_model to compress
            the ODF to spherical harmonics coefficients.
        parallel : bool, optional
            Whether to use parallelization in peak-finding during the
            calibration procedure.
        nbr_processes : int, optional
            If `parallel` is True, the number of subprocesses to use
            (default multiprocessing.cpu_count()).
        out_dir : string, optional
            Output directory. (default current directory)
        out_pam : string, optional
            Name of the peaks volume to be saved.
        out_shm : string, optional
            Name of the spherical harmonics volume to be saved.
        out_peaks_dir : string, optional
            Name of the peaks directions volume to be saved.
        out_peaks_values : string, optional
            Name of the peaks values volume to be saved.
        out_peaks_indices : string, optional
            Name of the peaks indices volume to be saved.
        out_gfa : string, optional
            Name of the generalized FA volume to be saved.


        References
        ----------
        .. [1] Tournier, J.D., et al. NeuroImage 2007. Robust determination of
           the fibre orientation distribution in diffusion MRI: Non-negativity
           constrained super-resolved spherical deconvolution.
        """
        io_it = self.get_io_iterator()

        for (dwi, bval, bvec, maskfile, opam, oshm, opeaks_dir, opeaks_values,
             opeaks_indices, ogfa) in io_it:

            logging.info('Loading {0}'.format(dwi))
            data, affine = load_nifti(dwi)

            bvals, bvecs = read_bvals_bvecs(bval, bvec)
            print(b0_threshold, bvals.min())
            if b0_threshold < bvals.min():
                warn(
                    "b0_threshold (value: {0}) is too low, increase your "
                    "b0_threshold. It should be higher than the first b0 value "
                    "({1}).".format(b0_threshold, bvals.min()))
            gtab = gradient_table(bvals,
                                  bvecs,
                                  b0_threshold=b0_threshold,
                                  atol=bvecs_tol)
            mask_vol = load_nifti_data(maskfile).astype(bool)

            n_params = ((sh_order + 1) * (sh_order + 2)) / 2
            if data.shape[-1] < n_params:
                raise ValueError('You need at least {0} unique DWI volumes to '
                                 'compute fiber odfs. You currently have: {1}'
                                 ' DWI volumes.'.format(
                                     n_params, data.shape[-1]))

            if frf is None:
                logging.info('Computing response function')
                if roi_center is not None:
                    logging.info(
                        'Response ROI center:\n{0}'.format(roi_center))
                    logging.info('Response ROI radii:\n{0}'.format(roi_radii))
                response, ratio = auto_response_ssst(gtab,
                                                     data,
                                                     roi_center=roi_center,
                                                     roi_radii=roi_radii,
                                                     fa_thr=fa_thr)
                response = list(response)

            else:
                logging.info('Using response function')
                if isinstance(frf, str):
                    l01 = np.array(literal_eval(frf), dtype=np.float64)
                else:
                    l01 = np.array(frf, dtype=np.float64)

                l01 *= 10**-4
                response = np.array([l01[0], l01[1], l01[1]])
                ratio = l01[1] / l01[0]
                response = (response, ratio)

            logging.info("Eigenvalues for the frf of the input"
                         " data are :{0}".format(response[0]))
            logging.info(
                'Ratio for smallest to largest eigen value is {0}'.format(
                    ratio))

            peaks_sphere = default_sphere

            logging.info('CSD computation started.')
            csd_model = ConstrainedSphericalDeconvModel(gtab,
                                                        response,
                                                        sh_order=sh_order)

            peaks_csd = peaks_from_model(model=csd_model,
                                         data=data,
                                         sphere=peaks_sphere,
                                         relative_peak_threshold=.5,
                                         min_separation_angle=25,
                                         mask=mask_vol,
                                         return_sh=True,
                                         sh_order=sh_order,
                                         normalize_peaks=True,
                                         parallel=parallel,
                                         nbr_processes=nbr_processes)
            peaks_csd.affine = affine

            save_peaks(opam, peaks_csd)

            logging.info('CSD computation completed.')

            if extract_pam_values:
                peaks_to_niftis(peaks_csd,
                                oshm,
                                opeaks_dir,
                                opeaks_values,
                                opeaks_indices,
                                ogfa,
                                reshape_dirs=True)

            dname_ = os.path.dirname(opam)
            if dname_ == '':
                logging.info('Pam5 file saved in current directory')
            else:
                logging.info('Pam5 file saved in {0}'.format(dname_))

            return io_it
Example #11
0
    def run(self,
            input_files,
            bvalues_files,
            bvectors_files,
            mask_files,
            sh_order=6,
            odf_to_sh_order=8,
            b0_threshold=50.0,
            bvecs_tol=0.01,
            extract_pam_values=False,
            parallel=False,
            nbr_processes=None,
            out_dir='',
            out_pam='peaks.pam5',
            out_shm='shm.nii.gz',
            out_peaks_dir='peaks_dirs.nii.gz',
            out_peaks_values='peaks_values.nii.gz',
            out_peaks_indices='peaks_indices.nii.gz',
            out_gfa='gfa.nii.gz'):
        """ Constant Solid Angle.

        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)
        sh_order : int, optional
            Spherical harmonics order used in the CSA fit.
        odf_to_sh_order : int, optional
            Spherical harmonics order used for peak_from_model to compress
            the ODF to spherical harmonics coefficients.
        b0_threshold : float, optional
            Threshold used to find b0 volumes.
        bvecs_tol : float, optional
            Threshold used so that norm(bvec)=1.
        extract_pam_values : bool, optional
            Whether or not to save pam volumes as single nifti files.
        parallel : bool, optional
            Whether to use parallelization in peak-finding during the
            calibration procedure.
        nbr_processes : int, optional
            If `parallel` is True, the number of subprocesses to use
            (default multiprocessing.cpu_count()).
        out_dir : string, optional
            Output directory. (default current directory)
        out_pam : string, optional
            Name of the peaks volume to be saved.
        out_shm : string, optional
            Name of the spherical harmonics volume to be saved.
        out_peaks_dir : string, optional
            Name of the peaks directions volume to be saved.
        out_peaks_values : string, optional
            Name of the peaks values volume to be saved.
        out_peaks_indices : string, optional
            Name of the peaks indices volume to be saved.
        out_gfa : string, optional
            Name of the generalized FA volume to be saved.

        References
        ----------
        .. [1] Aganj, I., et al. 2009. ODF Reconstruction in Q-Ball Imaging
           with Solid Angle Consideration.
        """
        io_it = self.get_io_iterator()

        for (dwi, bval, bvec, maskfile, opam, oshm, opeaks_dir, opeaks_values,
             opeaks_indices, ogfa) in io_it:

            logging.info('Loading {0}'.format(dwi))
            data, affine = load_nifti(dwi)

            bvals, bvecs = read_bvals_bvecs(bval, bvec)
            if b0_threshold < bvals.min():
                warn(
                    "b0_threshold (value: {0}) is too low, increase your "
                    "b0_threshold. It should be higher than the first b0 value "
                    "({1}).".format(b0_threshold, bvals.min()))
            gtab = gradient_table(bvals,
                                  bvecs,
                                  b0_threshold=b0_threshold,
                                  atol=bvecs_tol)
            mask_vol = load_nifti_data(maskfile).astype(bool)

            peaks_sphere = default_sphere

            logging.info('Starting CSA computations {0}'.format(dwi))

            csa_model = CsaOdfModel(gtab, sh_order)

            peaks_csa = peaks_from_model(model=csa_model,
                                         data=data,
                                         sphere=peaks_sphere,
                                         relative_peak_threshold=.5,
                                         min_separation_angle=25,
                                         mask=mask_vol,
                                         return_sh=True,
                                         sh_order=odf_to_sh_order,
                                         normalize_peaks=True,
                                         parallel=parallel,
                                         nbr_processes=nbr_processes)
            peaks_csa.affine = affine

            save_peaks(opam, peaks_csa)

            logging.info('Finished CSA {0}'.format(dwi))

            if extract_pam_values:
                peaks_to_niftis(peaks_csa,
                                oshm,
                                opeaks_dir,
                                opeaks_values,
                                opeaks_indices,
                                ogfa,
                                reshape_dirs=True)

            dname_ = os.path.dirname(opam)
            if dname_ == '':
                logging.info('Pam5 file saved in current directory')
            else:
                logging.info('Pam5 file saved in {0}'.format(dname_))

            return io_it
Example #12
0
def test_peaksFromModel():
    data = np.zeros((10, 2))

    for sphere in [_sphere, get_sphere('symmetric642')]:
        # Test basic case
        model = SimpleOdfModel(_gtab)
        _odf = (sphere.vertices * [1, 2, 3]).sum(-1)
        odf_argmax = _odf.argmax()
        pam = peaks_from_model(model,
                               data,
                               sphere,
                               .5,
                               45,
                               normalize_peaks=True)

        assert_array_equal(pam.gfa, gfa(_odf))
        assert_array_equal(pam.peak_values[:, 0], 1.)
        assert_array_equal(pam.peak_values[:, 1:], 0.)
        mn, mx = _odf.min(), _odf.max()
        assert_array_equal(pam.qa[:, 0], (mx - mn) / mx)
        assert_array_equal(pam.qa[:, 1:], 0.)
        assert_array_equal(pam.peak_indices[:, 0], odf_argmax)
        assert_array_equal(pam.peak_indices[:, 1:], -1)

        # Test that odf array matches and is right shape
        pam = peaks_from_model(model, data, sphere, .5, 45, return_odf=True)
        expected_shape = (len(data), len(_odf))
        assert_equal(pam.odf.shape, expected_shape)
        assert_((_odf == pam.odf).all())
        assert_array_equal(pam.peak_values[:, 0], _odf.max())

        # Test mask
        mask = (np.arange(10) % 2) == 1

        pam = peaks_from_model(model,
                               data,
                               sphere,
                               .5,
                               45,
                               mask=mask,
                               normalize_peaks=True)
        assert_array_equal(pam.gfa[~mask], 0)
        assert_array_equal(pam.qa[~mask], 0)
        assert_array_equal(pam.peak_values[~mask], 0)
        assert_array_equal(pam.peak_indices[~mask], -1)

        assert_array_equal(pam.gfa[mask], gfa(_odf))
        assert_array_equal(pam.peak_values[mask, 0], 1.)
        assert_array_equal(pam.peak_values[mask, 1:], 0.)
        mn, mx = _odf.min(), _odf.max()
        assert_array_equal(pam.qa[mask, 0], (mx - mn) / mx)
        assert_array_equal(pam.qa[mask, 1:], 0.)
        assert_array_equal(pam.peak_indices[mask, 0], odf_argmax)
        assert_array_equal(pam.peak_indices[mask, 1:], -1)

        # Test serialization and deserialization:
        for normalize_peaks in [True, False]:
            for return_odf in [True, False]:
                for return_sh in [True, False]:
                    pam = peaks_from_model(model,
                                           data,
                                           sphere,
                                           .5,
                                           45,
                                           normalize_peaks=normalize_peaks,
                                           return_odf=return_odf,
                                           return_sh=return_sh)

                    b = BytesIO()
                    pickle.dump(pam, b)
                    b.seek(0)
                    new_pam = pickle.load(b)
                    b.close()

                    for attr in [
                            'peak_dirs', 'peak_values', 'peak_indices', 'gfa',
                            'qa', 'shm_coeff', 'B', 'odf'
                    ]:
                        assert_array_equal(getattr(pam, attr),
                                           getattr(new_pam, attr))
                        assert_array_equal(pam.sphere.vertices,
                                           new_pam.sphere.vertices)
Example #13
0
def test_peaksFromModelParallel():
    SNR = 100
    S0 = 100

    _, fbvals, fbvecs = get_fnames('small_64D')

    bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs)

    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))

    data, _ = multi_tensor(gtab,
                           mevals,
                           S0,
                           angles=[(0, 0), (60, 0)],
                           fractions=[50, 50],
                           snr=SNR)

    for sphere in [_sphere, get_sphere('symmetric724')]:

        # test equality with/without multiprocessing
        model = SimpleOdfModel(gtab)
        pam_multi = peaks_from_model(model,
                                     data,
                                     sphere,
                                     .5,
                                     45,
                                     normalize_peaks=True,
                                     return_odf=True,
                                     return_sh=True,
                                     parallel=True)

        pam_single = peaks_from_model(model,
                                      data,
                                      sphere,
                                      .5,
                                      45,
                                      normalize_peaks=True,
                                      return_odf=True,
                                      return_sh=True,
                                      parallel=False)

        pam_multi_inv1 = peaks_from_model(model,
                                          data,
                                          sphere,
                                          .5,
                                          45,
                                          normalize_peaks=True,
                                          return_odf=True,
                                          return_sh=True,
                                          parallel=True,
                                          nbr_processes=0)

        pam_multi_inv2 = peaks_from_model(model,
                                          data,
                                          sphere,
                                          .5,
                                          45,
                                          normalize_peaks=True,
                                          return_odf=True,
                                          return_sh=True,
                                          parallel=True,
                                          nbr_processes=-2)

        for pam in [pam_multi, pam_multi_inv1, pam_multi_inv2]:
            assert_equal(pam.gfa.dtype, pam_single.gfa.dtype)
            assert_equal(pam.gfa.shape, pam_single.gfa.shape)
            assert_array_almost_equal(pam.gfa, pam_single.gfa)

            assert_equal(pam.qa.dtype, pam_single.qa.dtype)
            assert_equal(pam.qa.shape, pam_single.qa.shape)
            assert_array_almost_equal(pam.qa, pam_single.qa)

            assert_equal(pam.peak_values.dtype, pam_single.peak_values.dtype)
            assert_equal(pam.peak_values.shape, pam_single.peak_values.shape)
            assert_array_almost_equal(pam.peak_values, pam_single.peak_values)

            assert_equal(pam.peak_indices.dtype, pam_single.peak_indices.dtype)
            assert_equal(pam.peak_indices.shape, pam_single.peak_indices.shape)
            assert_array_equal(pam.peak_indices, pam_single.peak_indices)

            assert_equal(pam.peak_dirs.dtype, pam_single.peak_dirs.dtype)
            assert_equal(pam.peak_dirs.shape, pam_single.peak_dirs.shape)
            assert_array_almost_equal(pam.peak_dirs, pam_single.peak_dirs)

            assert_equal(pam.shm_coeff.dtype, pam_single.shm_coeff.dtype)
            assert_equal(pam.shm_coeff.shape, pam_single.shm_coeff.shape)
            assert_array_almost_equal(pam.shm_coeff, pam_single.shm_coeff)

            assert_equal(pam.odf.dtype, pam_single.odf.dtype)
            assert_equal(pam.odf.shape, pam_single.odf.shape)
            assert_array_almost_equal(pam.odf, pam_single.odf)
Example #14
0
def compute_fodf(data,
                 bvals,
                 bvecs,
                 full_frf,
                 sh_order=8,
                 nbr_processes=None,
                 mask=None,
                 sh_basis='descoteaux07',
                 return_sh=True,
                 n_peaks=5,
                 force_b0_threshold=False):
    """
     Script to compute Constrained Spherical Deconvolution (CSD) fiber ODFs.

     By default, will output all possible files, using default names. Specific
     names can be specified using the file flags specified in the "File flags"
     section.

    If --not_all is set, only the files specified explicitly by the flags
    will be output.

    See [Tournier et al. NeuroImage 2007] and [Cote et al Tractometer MedIA 2013]
    for quantitative comparisons with Sharpening Deconvolution Transform (SDT).

    Parameters
    ----------
    data: ndarray
        4D Input diffusion volume with shape (X, Y, Z, N)
    bvals: ndarray
        1D bvals array with shape (N,)
    bvecs: ndarray
        2D (normalized) bvecs array with shape (N, 3)
    full_frf: ndarray
        frf data, ex, loaded from a frf_file, with shape (4,).
    sh_order: int, optional
        SH order used for the CSD. (Default: 8)
    nbr_processes: int, optional
        Number of sub processes to start. Default = none, i.e use the cpu count.
        If 0, use all processes.
    mask: ndarray, optional
        3D mask with shape (X,Y,Z)
        Binary mask. Only the data inside the mask will be used for
        computations and reconstruction. Useful if no white matter mask is
        available.
    sh_basis: str, optional
        Spherical harmonics basis used for the SH coefficients.Must be either
        'descoteaux07' or 'tournier07' (default 'descoteaux07')
        - 'descoteaux07': SH basis from the Descoteaux et al. MRM 2007 paper
        - 'tournier07': SH basis from the Tournier et al. NeuroImage 2007 paper.
    return_sh: bool, optional
        If true, returns the sh.
    n_peaks: int, optional
        Nb of peaks for the fodf. Default: copied dipy's default, i.e. 5.
    force_b0_threshold: bool, optional
        If True, will continue even if the minimum bvalue is suspiciously high.

    Returns
    -------
    peaks_csd: PeaksAndMetrics
        An object with ``gfa``, ``peak_directions``, ``peak_values``,
        ``peak_indices``, ``odf``, ``shm_coeffs`` as attributes
    """

    # Checking data and sh_order
    check_b0_threshold(force_b0_threshold, bvals.min())
    if data.shape[-1] < (sh_order + 1) * (sh_order + 2) / 2:
        logging.warning(
            'We recommend having at least {} unique DWI volumes, but you '
            'currently have {} volumes. Try lowering the parameter sh_order '
            'in case of non convergence.'.format(
                (sh_order + 1) * (sh_order + 2) / 2, data.shape[-1]))

    # Checking bvals, bvecs values and loading gtab
    if not is_normalized_bvecs(bvecs):
        logging.warning('Your b-vectors do not seem normalized...')
        bvecs = normalize_bvecs(bvecs)
    gtab = gradient_table(bvals, bvecs, b0_threshold=bvals.min())

    # Checking full_frf and separating it
    if not full_frf.shape[0] == 4:
        raise ValueError('FRF file did not contain 4 elements. '
                         'Invalid or deprecated FRF format')
    frf = full_frf[0:3]
    mean_b0_val = full_frf[3]

    # Checking if we will use parallel processing
    parallel = True
    if nbr_processes is not None:
        if nbr_processes == 0:  # Will use all processed
            nbr_processes = None
        elif nbr_processes == 1:
            parallel = False
        elif nbr_processes < 0:
            raise ValueError('nbr_processes should be positive.')

    # Checking sh basis
    validate_sh_basis_choice(sh_basis)

    # Loading the spheres
    reg_sphere = get_sphere('symmetric362')
    peaks_sphere = get_sphere('symmetric724')

    # Computing CSD
    csd_model = ConstrainedSphericalDeconvModel(gtab, (frf, mean_b0_val),
                                                reg_sphere=reg_sphere,
                                                sh_order=sh_order)

    # Computing peaks. Run in parallel, using the default number of processes
    # (default: CPU count)
    peaks_csd = peaks_from_model(model=csd_model,
                                 data=data,
                                 sphere=peaks_sphere,
                                 relative_peak_threshold=.5,
                                 min_separation_angle=25,
                                 mask=mask,
                                 return_sh=return_sh,
                                 sh_basis_type=sh_basis,
                                 sh_order=sh_order,
                                 normalize_peaks=True,
                                 npeaks=n_peaks,
                                 parallel=parallel,
                                 nbr_processes=nbr_processes)

    return peaks_csd
Example #15
0
"""
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,
                            relative_peak_threshold=.5,
                            min_separation_angle=25,
                            sphere=sphere,
                            mask=mask)

ap = shm.anisotropic_power(peaks.shm_coeff)

plt.matshow(np.rot90(ap[:, :, 10]), cmap=plt.cm.bone)
#plt.savefig("anisotropic_power_map.png")
plt.show()
"""
.. figure:: anisotropic_power_map.png
   :align: center

   Anisotropic Power Map (Axial Slice)
"""
Example #16
0
ren = window.Renderer()
ren.add(fodf_spheres)

print('Saving illustration as sf_odfs.png')
window.record(ren, out_path='sf_odfs.png', size=(1000, 1000))
if interactive:
    window.show(ren)

"""
We can extract the peaks from the ODF, and plot these as well
"""

sf_peaks = dpp.peaks_from_model(sf_model,
                                data_small,
                                sphere,
                                relative_peak_threshold=.5,
                                min_separation_angle=25,
                                return_sh=False)


window.clear(ren)
fodf_peaks = actor.peak_slicer(sf_peaks.peak_dirs, sf_peaks.peak_values, scale=1.3)
ren.add(fodf_peaks)

print('Saving illustration as sf_peaks.png')
window.record(ren, out_path='sf_peaks.png', size=(1000, 1000))
if interactive:
    window.show(ren)

"""
Finally, we plot both the peaks and the ODFs, overlayed:
Example #17
0
                                colormap='plasma')

ren = window.Renderer()
ren.add(fodf_spheres)

print('Saving illustration as sf_odfs.png')
window.record(ren, out_path='sf_odfs.png', size=(1000, 1000))
if interactive:
    window.show(ren)
"""
We can extract the peaks from the ODF, and plot these as well
"""

sf_peaks = dpp.peaks_from_model(sf_model,
                                data_small,
                                sphere,
                                relative_peak_threshold=.5,
                                min_separation_angle=25,
                                return_sh=False)

window.clear(ren)
fodf_peaks = actor.peak_slicer(sf_peaks.peak_dirs, sf_peaks.peak_values)
ren.add(fodf_peaks)

print('Saving illustration as sf_peaks.png')
window.record(ren, out_path='sf_peaks.png', size=(1000, 1000))
if interactive:
    window.show(ren)
"""
Finally, we plot both the peaks and the ODFs, overlayed:
"""
Example #18
0
    def run(self, input_files, bvalues_files, bvectors_files, mask_files,
            sh_order=6, odf_to_sh_order=8, b0_threshold=50.0, bvecs_tol=0.01,
            extract_pam_values=False, parallel=False, nbr_processes=None,
            out_dir='',
            out_pam='peaks.pam5', out_shm='shm.nii.gz',
            out_peaks_dir='peaks_dirs.nii.gz',
            out_peaks_values='peaks_values.nii.gz',
            out_peaks_indices='peaks_indices.nii.gz',
            out_gfa='gfa.nii.gz'):
        """ Constant Solid Angle.

        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)
        sh_order : int, optional
            Spherical harmonics order (default 6) used in the CSA fit.
        odf_to_sh_order : int, optional
            Spherical harmonics order used for peak_from_model to compress
            the ODF to spherical harmonics coefficients (default 8)
        b0_threshold : float, optional
            Threshold used to find b=0 directions
        bvecs_tol : float, optional
            Threshold used so that norm(bvec)=1 (default 0.01)
        extract_pam_values : bool, optional
            Wheter or not to save pam volumes as single nifti files.
        parallel : bool, optional
            Whether to use parallelization in peak-finding during the
            calibration procedure. Default: False
        nbr_processes : int, optional
            If `parallel` is True, the number of subprocesses to use
            (default multiprocessing.cpu_count()).
        out_dir : string, optional
            Output directory (default input file directory)
        out_pam : string, optional
            Name of the peaks volume to be saved (default 'peaks.pam5')
        out_shm : string, optional
            Name of the shperical harmonics volume to be saved
            (default 'shm.nii.gz')
        out_peaks_dir : string, optional
            Name of the peaks directions volume to be saved
            (default 'peaks_dirs.nii.gz')
        out_peaks_values : string, optional
            Name of the peaks values volume to be saved
            (default 'peaks_values.nii.gz')
        out_peaks_indices : string, optional
            Name of the peaks indices volume to be saved
            (default 'peaks_indices.nii.gz')
        out_gfa : string, optional
            Name of the generalise fa volume to be saved (default 'gfa.nii.gz')

        References
        ----------
        .. [1] Aganj, I., et al. 2009. ODF Reconstruction in Q-Ball Imaging
           with Solid Angle Consideration.
        """
        io_it = self.get_io_iterator()

        for (dwi, bval, bvec, maskfile, opam, oshm, opeaks_dir,
             opeaks_values, opeaks_indices, ogfa) in io_it:

            logging.info('Loading {0}'.format(dwi))
            data, affine = load_nifti(dwi)

            bvals, bvecs = read_bvals_bvecs(bval, bvec)
            if b0_threshold < bvals.min():
                warn("b0_threshold (value: {0}) is too low, increase your "
                     "b0_threshold. It should higher than the first b0 value "
                     "({1}).".format(b0_threshold, bvals.min()))
            gtab = gradient_table(bvals, bvecs,
                                  b0_threshold=b0_threshold, atol=bvecs_tol)
            mask_vol = nib.load(maskfile).get_data().astype(np.bool)

            peaks_sphere = get_sphere('repulsion724')

            logging.info('Starting CSA computations {0}'.format(dwi))

            csa_model = CsaOdfModel(gtab, sh_order)

            peaks_csa = peaks_from_model(model=csa_model,
                                         data=data,
                                         sphere=peaks_sphere,
                                         relative_peak_threshold=.5,
                                         min_separation_angle=25,
                                         mask=mask_vol,
                                         return_sh=True,
                                         sh_order=odf_to_sh_order,
                                         normalize_peaks=True,
                                         parallel=parallel,
                                         nbr_processes=nbr_processes)
            peaks_csa.affine = affine

            save_peaks(opam, peaks_csa)

            logging.info('Finished CSA {0}'.format(dwi))

            if extract_pam_values:
                peaks_to_niftis(peaks_csa, oshm, opeaks_dir,
                                opeaks_values,
                                opeaks_indices, ogfa, reshape_dirs=True)

            dname_ = os.path.dirname(opam)
            if dname_ == '':
                logging.info('Pam5 file saved in current directory')
            else:
                logging.info(
                        'Pam5 file saved in {0}'.format(dname_))

            return io_it
Example #19
0
    from dipy.segment.mask import median_otsu

    bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs)
    gtab = gradient_table(bvals, bvecs)
    data, affine = load_nifti(fdwi)

    maskdata, mask = median_otsu(data, 3, 1, False, vol_idx=range(1, 20))

    from dipy.reconst.dti import TensorModel

    tensor_model = TensorModel(gtab, fit_method='WLS')
    tensor_fit = tensor_model.fit(data, mask)

    FA = tensor_fit.fa

    from dipy.reconst.shm import CsaOdfModel
    from dipy.data import get_sphere
    from dipy.direction.peaks import peaks_from_model

    sphere = get_sphere('repulsion724')

    csamodel = CsaOdfModel(gtab, 4)
    pam = peaks_from_model(model=csamodel,
                           data=maskdata,
                           sphere=sphere,
                           relative_peak_threshold=.5,
                           min_separation_angle=25,
                           mask=mask,
                           return_odf=False,
                           normalize_peaks=True)
Example #20
0
    def run(self, input_files, bvalues_files, bvectors_files, mask_files,
            b0_threshold=50.0, bvecs_tol=0.01, roi_center=None, roi_radius=10,
            fa_thr=0.7, frf=None, extract_pam_values=False, sh_order=8,
            odf_to_sh_order=8, parallel=False, nbr_processes=None,
            out_dir='',
            out_pam='peaks.pam5', out_shm='shm.nii.gz',
            out_peaks_dir='peaks_dirs.nii.gz',
            out_peaks_values='peaks_values.nii.gz',
            out_peaks_indices='peaks_indices.nii.gz', out_gfa='gfa.nii.gz'):
        """ Constrained spherical deconvolution

        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
        bvecs_tol : float, optional
            Bvecs should be unit vectors. (default:0.01)
        roi_center : variable int, optional
            Center of ROI in data. If center is None, it is assumed that it is
            the center of the volume with shape `data.shape[:3]` (default None)
        roi_radius : int, optional
            radius of cubic ROI in voxels (default 10)
        fa_thr : float, optional
            FA threshold for calculating the response function (default 0.7)
        frf : variable float, optional
            Fiber response function can be for example inputed as 15 4 4
            (from the command line) or [15, 4, 4] from a Python script to be
            converted to float and mutiplied by 10**-4 . If None
            the fiber response function will be computed automatically
            (default: None).
        extract_pam_values : bool, optional
            Save or not to save pam volumes as single nifti files.
        sh_order : int, optional
            Spherical harmonics order (default 6) used in the CSA fit.
        odf_to_sh_order : int, optional
            Spherical harmonics order used for peak_from_model to compress
            the ODF to spherical harmonics coefficients (default 8)
        parallel : bool, optional
            Whether to use parallelization in peak-finding during the
            calibration procedure. Default: False
        nbr_processes : int, optional
            If `parallel` is True, the number of subprocesses to use
            (default multiprocessing.cpu_count()).
        out_dir : string, optional
            Output directory (default input file directory)
        out_pam : string, optional
            Name of the peaks volume to be saved (default 'peaks.pam5')
        out_shm : string, optional
            Name of the shperical harmonics volume to be saved
            (default 'shm.nii.gz')
        out_peaks_dir : string, optional
            Name of the peaks directions volume to be saved
            (default 'peaks_dirs.nii.gz')
        out_peaks_values : string, optional
            Name of the peaks values volume to be saved
            (default 'peaks_values.nii.gz')
        out_peaks_indices : string, optional
            Name of the peaks indices volume to be saved
            (default 'peaks_indices.nii.gz')
        out_gfa : string, optional
            Name of the generalise fa volume to be saved (default 'gfa.nii.gz')


        References
        ----------
        .. [1] Tournier, J.D., et al. NeuroImage 2007. Robust determination of
           the fibre orientation distribution in diffusion MRI: Non-negativity
           constrained super-resolved spherical deconvolution.
        """
        io_it = self.get_io_iterator()

        for (dwi, bval, bvec, maskfile, opam, oshm, opeaks_dir, opeaks_values,
             opeaks_indices, ogfa) in io_it:

            logging.info('Loading {0}'.format(dwi))
            data, affine = load_nifti(dwi)

            bvals, bvecs = read_bvals_bvecs(bval, bvec)
            print(b0_threshold, bvals.min())
            if b0_threshold < bvals.min():
                warn("b0_threshold (value: {0}) is too low, increase your "
                     "b0_threshold. It should higher than the first b0 value "
                     "({1}).".format(b0_threshold, bvals.min()))
            gtab = gradient_table(bvals, bvecs, b0_threshold=b0_threshold,
                                  atol=bvecs_tol)
            mask_vol = nib.load(maskfile).get_data().astype(np.bool)

            n_params = ((sh_order + 1) * (sh_order + 2)) / 2
            if data.shape[-1] < n_params:
                raise ValueError(
                    'You need at least {0} unique DWI volumes to '
                    'compute fiber odfs. You currently have: {1}'
                    ' DWI volumes.'.format(n_params, data.shape[-1]))

            if frf is None:
                logging.info('Computing response function')
                if roi_center is not None:
                    logging.info('Response ROI center:\n{0}'
                                 .format(roi_center))
                    logging.info('Response ROI radius:\n{0}'
                                 .format(roi_radius))
                response, ratio, nvox = auto_response(
                        gtab, data,
                        roi_center=roi_center,
                        roi_radius=roi_radius,
                        fa_thr=fa_thr,
                        return_number_of_voxels=True)
                response = list(response)

            else:
                logging.info('Using response function')
                if isinstance(frf, str):
                    l01 = np.array(literal_eval(frf), dtype=np.float64)
                else:
                    l01 = np.array(frf, dtype=np.float64)

                l01 *= 10 ** -4
                response = np.array([l01[0], l01[1], l01[1]])
                ratio = l01[1] / l01[0]
                response = (response, ratio)

            logging.info("Eigenvalues for the frf of the input"
                         " data are :{0}".format(response[0]))
            logging.info('Ratio for smallest to largest eigen value is {0}'
                         .format(ratio))

            peaks_sphere = get_sphere('repulsion724')

            logging.info('CSD computation started.')
            csd_model = ConstrainedSphericalDeconvModel(gtab, response,
                                                        sh_order=sh_order)

            peaks_csd = peaks_from_model(model=csd_model,
                                         data=data,
                                         sphere=peaks_sphere,
                                         relative_peak_threshold=.5,
                                         min_separation_angle=25,
                                         mask=mask_vol,
                                         return_sh=True,
                                         sh_order=sh_order,
                                         normalize_peaks=True,
                                         parallel=parallel,
                                         nbr_processes=nbr_processes)
            peaks_csd.affine = affine

            save_peaks(opam, peaks_csd)

            logging.info('CSD computation completed.')

            if extract_pam_values:
                peaks_to_niftis(peaks_csd, oshm, opeaks_dir, opeaks_values,
                                opeaks_indices, ogfa, reshape_dirs=True)

            dname_ = os.path.dirname(opam)
            if dname_ == '':
                logging.info('Pam5 file saved in current directory')
            else:
                logging.info(
                        'Pam5 file saved in {0}'.format(dname_))

            return io_it
Example #21
0
def fiber_tracking(subject):
    # declare the type of algorithm, \in [deterministic, probabilitic]
    algo = 'deterministic'
    #     algo = 'probabilitic'
    '''
    @param subject: string represents the subject name
    @param algo: the name for the algorithms, \in ['deterministic', 'probabilitic']
    @return streamlines: for saving the final results and visualization
    '''

    print('processing for', subject)
    fname, bval_fname, bvec_fname, label_fname = get_file_names(subject)

    data, sub_affine, img = load_nifti(fname, return_img=True)
    bvals, bvecs = read_bvals_bvecs(bval_fname, bvec_fname)
    gtab = gradient_table(bvals, bvecs)
    labels = load_nifti_data(label_fname)

    print('data loading complete.\n')
    ##################################################################

    # set mask(s) and seed(s)
    # global_mask = binary_dilation((data[:, :, :, 0] != 0))
    global_mask = binary_dilation((labels == 1) | (labels == 2))
    #     global_mask = binary_dilation((labels == 2) | (labels == 32) | (labels == 76))
    affine = np.eye(4)
    seeds = utils.seeds_from_mask(global_mask, affine, density=1)
    print('mask(s) and seed(s) set complete.\n')
    ##################################################################

    print('getting directions from diffusion dataset...')

    # define tracking mask with Constant Solid Angle (CSA)
    csamodel = CsaOdfModel(gtab, 6)
    stopping_criterion = BinaryStoppingCriterion(global_mask)

    # define direction criterion
    direction_criterion = None
    print('Compute directions...')
    if algo == "deterministic":
        # EuDX
        direction_criterion = peaks.peaks_from_model(
            model=csamodel,
            data=data,
            sphere=peaks.default_sphere,
            relative_peak_threshold=.8,
            min_separation_angle=45,
            mask=global_mask)


#         # Deterministic Algorithm (select direction with max probability)
#         direction_criterion = DeterministicMaximumDirectionGetter.from_shcoeff(
#             csd_fit.shm_coeff,
#             max_angle=30.,
#             sphere=default_sphere)
    else:
        response, ratio = auto_response(gtab, data, roi_radius=10, fa_thr=0.7)

        # fit the reconstruction model with Constrained Spherical Deconvolusion (CSD)
        csd_model = ConstrainedSphericalDeconvModel(gtab, response, sh_order=6)
        csd_fit = csd_model.fit(data, mask=global_mask)

        #         gfa = csamodel.fit(data, mask=global_mask).gfa
        #     stopping_criterion = ThresholdStoppingCriterion(gfa, .25)

        # Probabilitic Algorithm
        direction_criterion = ProbabilisticDirectionGetter.from_shcoeff(
            csd_fit.shm_coeff, max_angle=30., sphere=default_sphere)

    print('direction computation complete.\n')
    ##################################################################

    print('start tracking process...')
    # start tracking
    streamline_generator = LocalTracking(direction_criterion,
                                         stopping_criterion,
                                         seeds,
                                         affine=affine,
                                         step_size=0.5)

    # Generate streamlines object
    streamlines = Streamlines(streamline_generator)

    sft = StatefulTractogram(streamlines, img, Space.RASMM)

    print('traking complete.\n')
    ##################################################################

    return {
        "subject": subject,
        "streamlines": streamlines,
        "sft": sft,
        "affine": sub_affine,
        "data": data,
        "img": img,
        "labels": labels
    }
def main():
    parser = _build_arg_parser()
    args = parser.parse_args()

    if not args.not_all:
        args.gfa = args.gfa or 'gfa.nii.gz'
        args.peaks = args.peaks or 'peaks.nii.gz'
        args.peak_indices = args.peak_indices or 'peaks_indices.nii.gz'
        args.sh = args.sh or 'sh.nii.gz'
        args.nufo = args.nufo or 'nufo.nii.gz'
        args.a_power = args.a_power or 'anisotropic_power.nii.gz'

    arglist = [
        args.gfa, args.peaks, args.peak_indices, args.sh, args.nufo,
        args.a_power
    ]
    if args.not_all and not any(arglist):
        parser.error('When using --not_all, you need to specify at least ' +
                     'one file to output.')

    assert_inputs_exist(parser, [args.in_dwi, args.in_bval, args.in_bvec])
    assert_outputs_exist(parser, args, arglist)
    validate_nbr_processes(parser, args)

    nbr_processes = args.nbr_processes
    parallel = nbr_processes > 1

    # Load data
    img = nib.load(args.in_dwi)
    data = img.get_fdata(dtype=np.float32)

    bvals, bvecs = read_bvals_bvecs(args.in_bval, args.in_bvec)

    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())

    sphere = get_sphere('symmetric724')

    mask = None
    if args.mask:
        mask = get_data_as_mask(nib.load(args.mask))

        # Sanity check on shape of mask
        if mask.shape != data.shape[:-1]:
            raise ValueError('Mask shape does not match data shape.')

    if args.use_qball:
        model = QballModel(gtab, sh_order=args.sh_order, smooth=DEFAULT_SMOOTH)
    else:
        model = CsaOdfModel(gtab,
                            sh_order=args.sh_order,
                            smooth=DEFAULT_SMOOTH)

    odfpeaks = peaks_from_model(model=model,
                                data=data,
                                sphere=sphere,
                                relative_peak_threshold=.5,
                                min_separation_angle=25,
                                mask=mask,
                                return_odf=False,
                                normalize_peaks=True,
                                return_sh=True,
                                sh_order=int(args.sh_order),
                                sh_basis_type=args.sh_basis,
                                npeaks=5,
                                parallel=parallel,
                                nbr_processes=nbr_processes)

    if args.gfa:
        nib.save(nib.Nifti1Image(odfpeaks.gfa.astype(np.float32), img.affine),
                 args.gfa)

    if args.peaks:
        nib.save(
            nib.Nifti1Image(reshape_peaks_for_visualization(odfpeaks),
                            img.affine), args.peaks)

    if args.peak_indices:
        nib.save(nib.Nifti1Image(odfpeaks.peak_indices, img.affine),
                 args.peak_indices)

    if args.sh:
        nib.save(
            nib.Nifti1Image(odfpeaks.shm_coeff.astype(np.float32), img.affine),
            args.sh)

    if args.nufo:
        peaks_count = (odfpeaks.peak_indices > -1).sum(3)
        nib.save(nib.Nifti1Image(peaks_count.astype(np.int32), img.affine),
                 args.nufo)

    if args.a_power:
        odf_a_power = anisotropic_power(odfpeaks.shm_coeff)
        nib.save(nib.Nifti1Image(odf_a_power.astype(np.float32), img.affine),
                 args.a_power)
Example #23
0
                    sh_image.SetPixel(x, y, z, sh_coeffs[z, y, x, :])
        sh_image.SetOrigin(in_image.GetOrigin())
        sh_image.SetSpacing(in_image.GetSpacing())
        sh_image.SetDirection(in_image.GetDirection())

    if num_peaks > 0:

        print('Calculating peaks')
        sys.stdout.flush()
        # calculate peak image
        data = np.nan_to_num(data)
        sf_peaks = dpp.peaks_from_model(
            model,
            data,
            sphere,
            relative_peak_threshold=relative_peak_threshold,
            min_separation_angle=min_separation_angle,
            return_sh=False,
            npeaks=num_peaks,
            parallel=True,
            mask=mask)

        # reshape to be MITK/MRtrix compliant
        s = sf_peaks.peak_dirs.shape
        peaks = sf_peaks.peak_dirs.reshape((s[0], s[1], s[2], num_peaks * 3),
                                           order='C')
        peaks = np.nan_to_num(peaks)
        peak_image = sitk.Image([data.shape[2], data.shape[1], data.shape[0]],
                                sitk.sitkVectorFloat32, num_peaks * 3)

        # scale peaks
        max_peak = 1.0
Example #24
0
for i_par in tqdm(range(len(par_vec)), ascii=True):

    par = par_vec[i_par]

    sf_model = sfm.SparseFascicleModel(gtab_test,
                                       sphere=sphere,
                                       l1_ratio=0.5,
                                       alpha=par,
                                       response=response[0])
    '''sf_fit = sf_model.fit( hardi_d_img_test_np, mask )
    sf_odf = sf_fit.odf(sphere)'''

    sf_peaks = dpp.peaks_from_model(sf_model,
                                    hardi_d_img_test_np,
                                    sphere,
                                    relative_peak_threshold=0.5,
                                    min_separation_angle=30,
                                    return_sh=False)

    peak_vals = sf_peaks.peak_values
    peak_dirs = sf_peaks.peak_dirs

    img_mos_dipy = np.sum(peak_vals > 0.1, axis=-1)

    img_mos_dipy[mask == 0] = 0

    mose_temp = img_mos_dipy.astype(np.int)

    Mose_CM = np.zeros((6, 6))

    for i in range(len(ind_1)):
Example #25
0
"""
We've loaded an image called ``labels_img`` which is a map of tissue types such
that every integer value in the array ``labels`` represents an anatomical
structure or tissue type [#]_. For this example, the image was created so that
white matter voxels have values of either 1 or 2. We'll use
``peaks_from_model`` to apply the ``CsaOdfModel`` to each white matter voxel
and estimate fiber orientations which we can use for tracking. We will also
dilate this mask by 1 voxel to ensure streamlines reach the grey matter.
"""

white_matter = binary_dilation((labels == 1) | (labels == 2))
csamodel = shm.CsaOdfModel(gtab, 6)
csapeaks = peaks.peaks_from_model(model=csamodel,
                                  data=data,
                                  sphere=peaks.default_sphere,
                                  relative_peak_threshold=.8,
                                  min_separation_angle=45,
                                  mask=white_matter)

"""
Now we can use EuDX to track all of the white matter. To keep things reasonably
fast we use ``density=1`` which will result in 1 seeds per voxel. The stopping
criterion, determining when the tracking stops, is set to stop when the
tracking exit the white matter.
"""

seeds = utils.seeds_from_mask(white_matter, density=1)
stopping_criterion = BinaryStoppingCriterion(white_matter)
affine = np.eye(4)

streamline_generator = LocalTracking(csapeaks, stopping_criterion, seeds,
Example #26
0
                        continue
                    sh_image.SetPixel(x, y, z, sh_coeffs[z, y, x, :])
        sh_image.SetOrigin(in_image.GetOrigin())
        sh_image.SetSpacing(in_image.GetSpacing())
        sh_image.SetDirection(in_image.GetDirection())

    if num_peaks > 0:

        print('Calculating peaks')
        sys.stdout.flush()
        # calculate peak image
        data = np.nan_to_num(data)
        sf_peaks = dpp.peaks_from_model(model,
                                        data,
                                        sphere,
                                        relative_peak_threshold=relative_peak_threshold,
                                        min_separation_angle=min_separation_angle,
                                        return_sh=False, npeaks=num_peaks, parallel=True,
                                        mask=mask)

        # reshape to be MITK/MRtrix compliant
        s = sf_peaks.peak_dirs.shape
        peaks = sf_peaks.peak_dirs.reshape((s[0], s[1], s[2], num_peaks * 3), order='C')
        peaks = np.nan_to_num(peaks)
        peak_image = sitk.Image([data.shape[2], data.shape[1], data.shape[0]], sitk.sitkVectorFloat32, num_peaks * 3)

        # scale peaks
        max_peak = 1.0
        if normalize_peaks:
            max_peak = np.max(sf_peaks.peak_values)
        if max_peak <= 0:
Example #27
0
def test_PeaksAndMetricsDirectionGetter():

    class SillyModel(object):
        def fit(self, data, mask=None):
            return SillyFit(self)

    class SillyFit(object):

        def __init__(self, model):
            self.model = model

        def odf(self, sphere):
            odf = np.zeros(sphere.theta.shape)
            r = np.random.randint(0, len(odf))
            odf[r] = 1
            return odf

    def get_direction(dg, point, dir):
        newdir = dir.copy()
        state = dg.get_direction(point, newdir)
        return (state, np.array(newdir))

    data = np.random.random((3, 4, 5, 2))
    peaks = peaks_from_model(SillyModel(), data, default_sphere,
                             relative_peak_threshold=.5,
                             min_separation_angle=25)
    peaks._initialize()

    up = np.zeros(3)
    up[2] = 1.
    down = -up

    for i in range(3-1):
        for j in range(4-1):
            for k in range(5-1):
                point = np.array([i, j, k], dtype=float)

                # Test that the angle threshold rejects points
                peaks.ang_thr = 0.
                state, nd = get_direction(peaks, point, up)
                npt.assert_equal(state, 1)

                # Here we leverage the fact that we know Hemispheres project
                # all their vertices into the z >= 0 half of the sphere.
                peaks.ang_thr = 90.
                state, nd = get_direction(peaks, point, up)
                npt.assert_equal(state, 0)
                expected_dir = peaks.peak_dirs[i, j, k, 0]
                npt.assert_array_almost_equal(nd, expected_dir)
                state, nd = get_direction(peaks, point, down)
                npt.assert_array_almost_equal(nd, -expected_dir)

                # Check that we can get directions at non-integer points
                point += np.random.random(3)
                state, nd = get_direction(peaks, point, up)
                npt.assert_equal(state, 0)

                # Check that points are rounded to get initial direction
                point -= .5
                initial_dir = peaks.initial_direction(point)
                # It should be a (1, 3) array
                npt.assert_array_almost_equal(initial_dir, [expected_dir])

    peaks1 = peaks_from_model(SillyModel(), data, default_sphere,
                              relative_peak_threshold=.5,
                              min_separation_angle=25,
                              npeaks=1)
    peaks1._initialize()
    point = np.array([1, 1, 1], dtype=float)

    # it should have one direction
    npt.assert_array_almost_equal(len(peaks1.initial_direction(point)), 1)
    npt.assert_array_almost_equal(len(peaks.initial_direction(point)), 1)
Example #28
0
def test_peaksFromModel():
    data = np.zeros((10, 2))

    for sphere in [_sphere, get_sphere('symmetric642')]:
        # Test basic case
        model = SimpleOdfModel(_gtab)
        _odf = (sphere.vertices * [1, 2, 3]).sum(-1)
        odf_argmax = _odf.argmax()
        pam = peaks_from_model(model, data, sphere, .5, 45,
                               normalize_peaks=True)

        assert_array_equal(pam.gfa, gfa(_odf))
        assert_array_equal(pam.peak_values[:, 0], 1.)
        assert_array_equal(pam.peak_values[:, 1:], 0.)
        mn, mx = _odf.min(), _odf.max()
        assert_array_equal(pam.qa[:, 0], (mx - mn) / mx)
        assert_array_equal(pam.qa[:, 1:], 0.)
        assert_array_equal(pam.peak_indices[:, 0], odf_argmax)
        assert_array_equal(pam.peak_indices[:, 1:], -1)

        # Test that odf array matches and is right shape
        pam = peaks_from_model(model, data, sphere, .5, 45, return_odf=True)
        expected_shape = (len(data), len(_odf))
        assert_equal(pam.odf.shape, expected_shape)
        assert_((_odf == pam.odf).all())
        assert_array_equal(pam.peak_values[:, 0], _odf.max())

        # Test mask
        mask = (np.arange(10) % 2) == 1

        pam = peaks_from_model(model, data, sphere, .5, 45, mask=mask,
                            normalize_peaks=True)
        assert_array_equal(pam.gfa[~mask], 0)
        assert_array_equal(pam.qa[~mask], 0)
        assert_array_equal(pam.peak_values[~mask], 0)
        assert_array_equal(pam.peak_indices[~mask], -1)

        assert_array_equal(pam.gfa[mask], gfa(_odf))
        assert_array_equal(pam.peak_values[mask, 0], 1.)
        assert_array_equal(pam.peak_values[mask, 1:], 0.)
        mn, mx = _odf.min(), _odf.max()
        assert_array_equal(pam.qa[mask, 0], (mx - mn) / mx)
        assert_array_equal(pam.qa[mask, 1:], 0.)
        assert_array_equal(pam.peak_indices[mask, 0], odf_argmax)
        assert_array_equal(pam.peak_indices[mask, 1:], -1)

        # Test serialization and deserialization:
        for normalize_peaks in [True, False]:
            for return_odf in [True, False]:
                for return_sh in [True, False]:
                    pam = peaks_from_model(model, data, sphere, .5, 45,
                                        normalize_peaks=normalize_peaks,
                                        return_odf=return_odf,
                                        return_sh=return_sh)

                    b = BytesIO()
                    pickle.dump(pam, b)
                    b.seek(0)
                    new_pam = pickle.load(b)
                    b.close()

                    for attr in ['peak_dirs', 'peak_values', 'peak_indices',
                                'gfa', 'qa', 'shm_coeff', 'B', 'odf']:
                        assert_array_equal(getattr(pam, attr),
                                        getattr(new_pam, attr))
                        assert_array_equal(pam.sphere.vertices,
                                        new_pam.sphere.vertices)
Example #29
0
def recursive_response(gtab,
                       data,
                       mask=None,
                       sh_order=8,
                       peak_thr=0.01,
                       init_fa=0.08,
                       init_trace=0.0021,
                       iter=8,
                       convergence=0.001,
                       parallel=True,
                       nbr_processes=None,
                       sphere=default_sphere):
    """ Recursive calibration of response function using peak threshold

    Parameters
    ----------
    gtab : GradientTable
    data : ndarray
        diffusion data
    mask : ndarray, optional
        mask for recursive calibration, for example a white matter mask. It has
        shape `data.shape[0:3]` and dtype=bool. Default: use the entire data
        array.
    sh_order : int, optional
        maximal spherical harmonics order. Default: 8
    peak_thr : float, optional
        peak threshold, how large the second peak can be relative to the first
        peak in order to call it a single fiber population [1]. Default: 0.01
    init_fa : float, optional
        FA of the initial 'fat' response function (tensor). Default: 0.08
    init_trace : float, optional
        trace of the initial 'fat' response function (tensor). Default: 0.0021
    iter : int, optional
        maximum number of iterations for calibration. Default: 8.
    convergence : float, optional
        convergence criterion, maximum relative change of SH
        coefficients. Default: 0.001.
    parallel : bool, optional
        Whether to use parallelization in peak-finding during the calibration
        procedure. Default: True
    nbr_processes: int
        If `parallel` is True, the number of subprocesses to use
        (default multiprocessing.cpu_count()).
    sphere : Sphere, optional.
        The sphere used for peak finding. Default: default_sphere.

    Returns
    -------
    response : ndarray
        response function in SH coefficients

    Notes
    -----
    In CSD there is an important pre-processing step: the estimation of the
    fiber response function. Using an FA threshold is not a very robust method.
    It is dependent on the dataset (non-informed used subjectivity), and still
    depends on the diffusion tensor (FA and first eigenvector),
    which has low accuracy at high b-value. This function recursively
    calibrates the response function, for more information see [1].

    References
    ----------
    .. [1] Tax, C.M.W., et al. NeuroImage 2014. Recursive calibration of
           the fiber response function for spherical deconvolution of
           diffusion MRI data.
    """
    S0 = 1.
    evals = fa_trace_to_lambdas(init_fa, init_trace)
    res_obj = (evals, S0)

    if mask is None:
        data = data.reshape(-1, data.shape[-1])
    else:
        data = data[mask]

    n = np.arange(0, sh_order + 1, 2)
    where_dwi = lazy_index(~gtab.b0s_mask)
    response_p = np.ones(len(n))

    for _ in range(iter):
        r_sh_all = np.zeros(len(n))
        csd_model = ConstrainedSphericalDeconvModel(gtab,
                                                    res_obj,
                                                    sh_order=sh_order)

        csd_peaks = peaks_from_model(model=csd_model,
                                     data=data,
                                     sphere=sphere,
                                     relative_peak_threshold=peak_thr,
                                     min_separation_angle=25,
                                     parallel=parallel,
                                     nbr_processes=nbr_processes)

        dirs = csd_peaks.peak_dirs
        vals = csd_peaks.peak_values
        single_peak_mask = (vals[:, 1] / vals[:, 0]) < peak_thr
        data = data[single_peak_mask]
        dirs = dirs[single_peak_mask]

        for num_vox in range(data.shape[0]):
            rotmat = vec2vec_rotmat(dirs[num_vox, 0], np.array([0, 0, 1]))

            rot_gradients = np.dot(rotmat, gtab.gradients.T).T

            x, y, z = rot_gradients[where_dwi].T
            r, theta, phi = cart2sphere(x, y, z)
            # for the gradient sphere
            B_dwi = real_sph_harm(0, n, theta[:, None], phi[:, None])
            r_sh_all += np.linalg.lstsq(B_dwi,
                                        data[num_vox, where_dwi],
                                        rcond=-1)[0]

        response = r_sh_all / data.shape[0]
        res_obj = AxSymShResponse(data[:, gtab.b0s_mask].mean(), response)

        change = abs((response_p - response) / response_p)
        if all(change < convergence):
            break

        response_p = response

    return res_obj
Example #30
0
def recursive_response(gtab, data, mask=None, sh_order=8, peak_thr=0.01,
                       init_fa=0.08, init_trace=0.0021, iter=8,
                       convergence=0.001, parallel=True, nbr_processes=None,
                       sphere=default_sphere):
    """ Recursive calibration of response function using peak threshold

    Parameters
    ----------
    gtab : GradientTable
    data : ndarray
        diffusion data
    mask : ndarray, optional
        mask for recursive calibration, for example a white matter mask. It has
        shape `data.shape[0:3]` and dtype=bool. Default: use the entire data
        array.
    sh_order : int, optional
        maximal spherical harmonics order. Default: 8
    peak_thr : float, optional
        peak threshold, how large the second peak can be relative to the first
        peak in order to call it a single fiber population [1]. Default: 0.01
    init_fa : float, optional
        FA of the initial 'fat' response function (tensor). Default: 0.08
    init_trace : float, optional
        trace of the initial 'fat' response function (tensor). Default: 0.0021
    iter : int, optional
        maximum number of iterations for calibration. Default: 8.
    convergence : float, optional
        convergence criterion, maximum relative change of SH
        coefficients. Default: 0.001.
    parallel : bool, optional
        Whether to use parallelization in peak-finding during the calibration
        procedure. Default: True
    nbr_processes: int
        If `parallel` is True, the number of subprocesses to use
        (default multiprocessing.cpu_count()).
    sphere : Sphere, optional.
        The sphere used for peak finding. Default: default_sphere.

    Returns
    -------
    response : ndarray
        response function in SH coefficients

    Notes
    -----
    In CSD there is an important pre-processing step: the estimation of the
    fiber response function. Using an FA threshold is not a very robust method.
    It is dependent on the dataset (non-informed used subjectivity), and still
    depends on the diffusion tensor (FA and first eigenvector),
    which has low accuracy at high b-value. This function recursively
    calibrates the response function, for more information see [1].

    References
    ----------
    .. [1] Tax, C.M.W., et al. NeuroImage 2014. Recursive calibration of
           the fiber response function for spherical deconvolution of
           diffusion MRI data.
    """
    S0 = 1.
    evals = fa_trace_to_lambdas(init_fa, init_trace)
    res_obj = (evals, S0)

    if mask is None:
        data = data.reshape(-1, data.shape[-1])
    else:
        data = data[mask]

    n = np.arange(0, sh_order + 1, 2)
    where_dwi = lazy_index(~gtab.b0s_mask)
    response_p = np.ones(len(n))

    for num_it in range(iter):
        r_sh_all = np.zeros(len(n))
        csd_model = ConstrainedSphericalDeconvModel(gtab, res_obj,
                                                    sh_order=sh_order)

        csd_peaks = peaks_from_model(model=csd_model,
                                     data=data,
                                     sphere=sphere,
                                     relative_peak_threshold=peak_thr,
                                     min_separation_angle=25,
                                     parallel=parallel,
                                     nbr_processes=nbr_processes)

        dirs = csd_peaks.peak_dirs
        vals = csd_peaks.peak_values
        single_peak_mask = (vals[:, 1] / vals[:, 0]) < peak_thr
        data = data[single_peak_mask]
        dirs = dirs[single_peak_mask]

        for num_vox in range(data.shape[0]):
            rotmat = vec2vec_rotmat(dirs[num_vox, 0], np.array([0, 0, 1]))

            rot_gradients = np.dot(rotmat, gtab.gradients.T).T

            x, y, z = rot_gradients[where_dwi].T
            r, theta, phi = cart2sphere(x, y, z)
            # for the gradient sphere
            B_dwi = real_sph_harm(0, n, theta[:, None], phi[:, None])
            r_sh_all += np.linalg.lstsq(B_dwi, data[num_vox, where_dwi])[0]

        response = r_sh_all / data.shape[0]
        res_obj = AxSymShResponse(data[:, gtab.b0s_mask].mean(), response)

        change = abs((response_p - response) / response_p)
        if all(change < convergence):
            break

        response_p = response

    return res_obj
Example #31
0
sphere = get_sphere()
from dipy.reconst import sfm
sf_model = sfm.SparseFascicleModel(gtab, sphere=sphere,
                                   l1_ratio=0.5, alpha=0.001,
                                   response=response[0])

"""
We fit this model to the data in each voxel in the white-matter mask, so that
we can use these directions in tracking:
"""

from dipy.direction.peaks import peaks_from_model

pnm = peaks_from_model(sf_model, data, sphere,
                       relative_peak_threshold=.5,
                       min_separation_angle=25,
                       mask=white_matter,
                       parallel=True
                       )

"""
A ThresholdTissueClassifier object is used to segment the data to track only
through areas in which the Generalized Fractional Anisotropy (GFA) is
sufficiently high.
"""

from dipy.tracking.local import ThresholdTissueClassifier
classifier = ThresholdTissueClassifier(pnm.gfa, .25)

"""
Tracking will be started from a set of seeds evenly distributed in the white
matter:
Example #32
0
def test_peaksFromModelParallel():
    SNR = 100
    S0 = 100

    _, fbvals, fbvecs = get_fnames('small_64D')

    bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs)

    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))

    data, _ = multi_tensor(gtab,
                           mevals,
                           S0,
                           angles=[(0, 0), (60, 0)],
                           fractions=[50, 50],
                           snr=SNR)

    for sphere in [_sphere, default_sphere]:

        # test equality with/without multiprocessing
        model = SimpleOdfModel(gtab)
        pam_multi = peaks_from_model(model,
                                     data,
                                     sphere,
                                     .5,
                                     45,
                                     normalize_peaks=True,
                                     return_odf=True,
                                     return_sh=True,
                                     parallel=True)

        pam_single = peaks_from_model(model,
                                      data,
                                      sphere,
                                      .5,
                                      45,
                                      normalize_peaks=True,
                                      return_odf=True,
                                      return_sh=True,
                                      parallel=False)

        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always", category=UserWarning)
            pam_multi_inv1 = peaks_from_model(model,
                                              data,
                                              sphere,
                                              .5,
                                              45,
                                              normalize_peaks=True,
                                              return_odf=True,
                                              return_sh=True,
                                              parallel=True,
                                              nbr_processes=0)

            pam_multi_inv2 = peaks_from_model(model,
                                              data,
                                              sphere,
                                              .5,
                                              45,
                                              normalize_peaks=True,
                                              return_odf=True,
                                              return_sh=True,
                                              parallel=True,
                                              nbr_processes=-2)
            assert_(len(w) == 2)
            assert_(issubclass(w[0].category, UserWarning))
            assert_(issubclass(w[1].category, UserWarning))
            assert_("Invalid number of processes " in str(w[0].message))
            assert_("Invalid number of processes " in str(w[1].message))

            for pam in [pam_multi, pam_multi_inv1, pam_multi_inv2]:
                assert_equal(pam.gfa.dtype, pam_single.gfa.dtype)
                assert_equal(pam.gfa.shape, pam_single.gfa.shape)
                assert_array_almost_equal(pam.gfa, pam_single.gfa)

                assert_equal(pam.qa.dtype, pam_single.qa.dtype)
                assert_equal(pam.qa.shape, pam_single.qa.shape)
                assert_array_almost_equal(pam.qa, pam_single.qa)

                assert_equal(pam.peak_values.dtype,
                             pam_single.peak_values.dtype)
                assert_equal(pam.peak_values.shape,
                             pam_single.peak_values.shape)
                assert_array_almost_equal(pam.peak_values,
                                          pam_single.peak_values)

                assert_equal(pam.peak_indices.dtype,
                             pam_single.peak_indices.dtype)
                assert_equal(pam.peak_indices.shape,
                             pam_single.peak_indices.shape)
                assert_array_equal(pam.peak_indices, pam_single.peak_indices)

                assert_equal(pam.peak_dirs.dtype, pam_single.peak_dirs.dtype)
                assert_equal(pam.peak_dirs.shape, pam_single.peak_dirs.shape)
                assert_array_almost_equal(pam.peak_dirs, pam_single.peak_dirs)

                assert_equal(pam.shm_coeff.dtype, pam_single.shm_coeff.dtype)
                assert_equal(pam.shm_coeff.shape, pam_single.shm_coeff.shape)
                assert_array_almost_equal(pam.shm_coeff, pam_single.shm_coeff)

                assert_equal(pam.odf.dtype, pam_single.odf.dtype)
                assert_equal(pam.odf.shape, pam_single.odf.shape)
                assert_array_almost_equal(pam.odf, pam_single.odf)
Example #33
0
sphere = get_sphere()
from dipy.reconst import sfm
sf_model = sfm.SparseFascicleModel(gtab, sphere=sphere,
                                   l1_ratio=0.5, alpha=0.001,
                                   response=response[0])

"""
We fit this model to the data in each voxel in the white-matter mask, so that
we can use these directions in tracking:
"""

from dipy.direction.peaks import peaks_from_model

pnm = peaks_from_model(sf_model, data, sphere,
                       relative_peak_threshold=.5,
                       min_separation_angle=25,
                       mask=white_matter,
                       parallel=True
                       )

"""
A ThresholdTissueClassifier object is used to segment the data to track only
through areas in which the Generalized Fractional Anisotropy (GFA) is
sufficiently high.
"""

from dipy.tracking.local import ThresholdTissueClassifier
classifier = ThresholdTissueClassifier(pnm.gfa, .25)

"""
Tracking will be started from a set of seeds evenly distributed in the white
matter:
def main():
    parser = _build_arg_parser()
    args = parser.parse_args()
    logging.basicConfig(level=logging.INFO)

    if not args.not_all:
        args.fodf = args.fodf or 'fodf.nii.gz'
        args.peaks = args.peaks or 'peaks.nii.gz'
        args.peak_indices = args.peak_indices or 'peak_indices.nii.gz'

    arglist = [args.fodf, args.peaks, args.peak_indices]
    if args.not_all and not any(arglist):
        parser.error('When using --not_all, you need to specify at least '
                     'one file to output.')

    assert_inputs_exist(parser,
                        [args.input, args.bvals, args.bvecs, args.frf_file])
    assert_outputs_exist(parser, args, arglist)

    nbr_processes = args.nbr_processes
    parallel = True
    if nbr_processes is not None:
        if nbr_processes <= 0:
            nbr_processes = None
        elif nbr_processes == 1:
            parallel = False

    full_frf = np.loadtxt(args.frf_file)

    if not full_frf.shape[0] == 4:
        raise ValueError('FRF file did not contain 4 elements. '
                         'Invalid or deprecated FRF format')

    frf = full_frf[0:3]
    mean_b0_val = full_frf[3]

    vol = nib.load(args.input)
    data = vol.get_data()

    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())

    if args.mask is None:
        mask = None
    else:
        mask = nib.load(args.mask).get_data().astype(np.bool)

    # Raise warning for sh order if there is not enough DWIs
    if data.shape[-1] < (args.sh_order + 1) * (args.sh_order + 2) / 2:
        warnings.warn(
            'We recommend having at least {} unique DWIs volumes, but you '
            'currently have {} volumes. Try lowering the parameter --sh_order '
            'in case of non convergence.'.format(
                (args.sh_order + 1) * (args.sh_order + 2) / 2, data.shape[-1]))

    reg_sphere = get_sphere('symmetric362')
    peaks_sphere = get_sphere('symmetric724')

    csd_model = ConstrainedSphericalDeconvModel(gtab, (frf, mean_b0_val),
                                                reg_sphere=reg_sphere,
                                                sh_order=args.sh_order)

    peaks_csd = peaks_from_model(model=csd_model,
                                 data=data,
                                 sphere=peaks_sphere,
                                 relative_peak_threshold=.5,
                                 min_separation_angle=25,
                                 mask=mask,
                                 return_sh=True,
                                 sh_basis_type=args.sh_basis,
                                 sh_order=args.sh_order,
                                 normalize_peaks=True,
                                 parallel=parallel,
                                 nbr_processes=nbr_processes)

    if args.fodf:
        nib.save(
            nib.Nifti1Image(peaks_csd.shm_coeff.astype(np.float32),
                            vol.affine), args.fodf)

    if args.peaks:
        nib.save(
            nib.Nifti1Image(reshape_peaks_for_visualization(peaks_csd),
                            vol.affine), args.peaks)

    if args.peak_indices:
        nib.save(nib.Nifti1Image(peaks_csd.peak_indices, vol.affine),
                 args.peak_indices)