コード例 #1
0
def main():
    parser = _build_arg_parser()
    args = parser.parse_args()

    assert_inputs_exist(parser, args.input_sh)
    assert_outputs_exist(parser, args, args.output_name)

    input_basis = args.sh_basis
    output_basis = 'descoteaux07' if input_basis == 'tournier07' else 'tournier07'

    sph_harm_basis_ori = sph_harm_lookup.get(input_basis)
    sph_harm_basis_des = sph_harm_lookup.get(output_basis)

    sphere = get_sphere('repulsion724').subdivide(1)
    img = nib.load(args.input_sh)
    data = img.get_data()
    sh_order = find_order_from_nb_coeff(data)

    b_ori, m_ori, n_ori = sph_harm_basis_ori(sh_order, sphere.theta,
                                             sphere.phi)
    b_des, m_des, n_des = sph_harm_basis_des(sh_order, sphere.theta,
                                             sphere.phi)
    l_des = -n_des * (n_des + 1)
    inv_b_des = smooth_pinv(b_des, 0 * l_des)

    indices = np.argwhere(np.any(data, axis=3))
    for i, ind in enumerate(indices):
        ind = tuple(ind)
        sf_1 = np.dot(data[ind], b_ori.T)
        data[ind] = np.dot(sf_1, inv_b_des.T)

    img = nib.Nifti1Image(data, img.affine, img.header)
    nib.save(nib.Nifti1Image(data, img.affine, img.header), args.output_name)
コード例 #2
0
    def resample_dwi(self, directions=None, sh_order=8, smooth=0.006):
        """ Resamples a diffusion signal according to a set of directions using spherical harmonics.
        Parameters
        -----------
        directions : `dipy.core.sphere.Sphere` object, optional
            Directions the diffusion signal will be resampled to. Directions are
            assumed to be on the whole sphere, not the hemisphere like bvecs.
            If omitted, 100 directions evenly distributed on the sphere will be used.
        sh_order : int, optional
            SH order. Default: 8
        smooth : float, optional
            Lambda-regularization in the SH fit. Default: 0.006.
        """
        data_sh = self.get_spherical_harmonics_coefficients(self.dwi,
                                                            self.bvals,
                                                            self.bvecs,
                                                            sh_order=sh_order,
                                                            smooth=smooth)
        sphere = get_sphere('repulsion100')
        if directions is not None:
            sphere = Sphere(xyz=directions)

        sph_harm_basis = sph_harm_lookup.get("tournier07")
        Ba, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi)
        data_resampled = np.dot(data_sh, Ba.T)

        return data_resampled
コード例 #3
0
ファイル: viz.py プロジェクト: TheoMoutakanni/harmonisation
def print_peaks(sh_signal, mask=None):
    if has_fury:
        data_small = sh_signal[:, :, 50:51]
        ren = window.Renderer()

        sh_order = order_from_ncoef(data_small.shape[-1])
        theta = default_sphere.theta
        phi = default_sphere.phi
        sh_params = SIGNAL_PARAMETERS['processing_params']['sh_params']
        basis_type = sh_params['basis_type']
        sph_harm_basis = sph_harm_lookup.get(basis_type)
        sampling_matrix, m, n = sph_harm_basis(sh_order, theta, phi)
        odfs = np.dot(data_small, sampling_matrix.T)

        odfs = np.clip(odfs, 0, np.max(odfs, -1)[..., None])
        odfs_actor = actor.odf_slicer(odfs,
                                      sphere=default_sphere,
                                      colormap='plasma',
                                      scale=0.4)
        odfs_actor.display(z=0)

        ren.add(odfs_actor)
        print('Saving illustration as csa_odfs.png')
        window.record(ren,
                      n_frames=1,
                      out_path='csa_odfs.png',
                      size=(600, 600))
        window.show(ren)
コード例 #4
0
def get_b_matrix(order, sphere, basis_type, return_all=False):
    sph_harm_basis = sph_harm_lookup.get(basis_type)
    if sph_harm_basis is None:
        raise ValueError("Invalid basis name.")
    b_matrix, m, n = sph_harm_basis(order, sphere.theta, sphere.phi)
    if return_all:
        return b_matrix, m, n
    return b_matrix
コード例 #5
0
def sf_to_sh_invB(sphere, sh_order=8, basis_type=None, smooth=0.0):
    sph_harm_basis = sph_harm_lookup.get(basis_type)
    if sph_harm_basis is None:
        raise ValueError("Invalid basis name.")
    B, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi)
    L = -n * (n + 1)
    invB = smooth_pinv(B, np.sqrt(smooth) * L)
    return invB.T
コード例 #6
0
ファイル: neurotools.py プロジェクト: nih23/learn2track
def resample_dwi(dwi,
                 bvals,
                 bvecs,
                 directions=None,
                 sh_order=8,
                 smooth=0.006,
                 mean_centering=True):
    """ Resamples a diffusion signal according to a set of directions using spherical harmonics.

    Parameters
    -----------
    dwi : `nibabel.NiftiImage` object
        Diffusion signal as weighted images (4D).
    bvals : ndarray shape (N,)
        B-values used with each direction.
    bvecs : ndarray shape (N, 3)
        Directions of the diffusion signal. Directions are
        assumed to be only on the hemisphere.
    directions : `dipy.core.sphere.Sphere` object, optional
        Directions the diffusion signal will be resampled to. Directions are
        assumed to be on the whole sphere, not the hemisphere like bvecs.
        If omitted, 100 directions evenly distributed on the sphere will be used.
    sh_order : int, optional
        SH order. Default: 8
    smooth : float, optional
        Lambda-regularization in the SH fit. Default: 0.006.
    mean_centering : bool
        If True, signal will have zero mean in each direction for all nonzero voxels

    Returns
    -------
    ndarray
        Diffusion weights resampled according to `sphere`.
    """
    data_sh = get_spherical_harmonics_coefficients(dwi,
                                                   bvals,
                                                   bvecs,
                                                   sh_order=sh_order,
                                                   smooth=smooth,
                                                   mean_centering=False)

    sphere = get_sphere('repulsion100')
    # sphere = get_sphere('repulsion724')
    if directions is not None:
        sphere = Sphere(xyz=bvecs[1:])

    sph_harm_basis = sph_harm_lookup.get('mrtrix')
    Ba, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi)
    data_resampled = np.dot(data_sh, Ba.T)

    if mean_centering:
        # Normalization in each direction (zero mean)
        idx = data_resampled.sum(axis=-1).nonzero()
        means = data_resampled[idx].mean(axis=0)
        data_resampled[idx] -= means

    return data_resampled
コード例 #7
0
ファイル: dwi.py プロジェクト: ppoulin91/dwi_ml
def resample_raw_dwi_from_sh(dwi_image: nib.Nifti1Image,
                             gradient_table: GradientTable,
                             sh_basis: str = 'descoteaux07',
                             sphere: Sphere = None,
                             sh_order: int = 8,
                             smooth: float = 0.006):
    """Resample a diffusion signal according to a set of directions using
    spherical harmonics.

    Parameters
    ----------
    dwi_image : nib.Nifti1Image object
        Diffusion signal as weighted images (4D).
    gradient_table : GradientTable
        Dipy object that contains all bvals and bvecs.
    sh_basis: str
        Either 'tournier07' or 'descoteaux07'. Default: descoteaux07.
    sphere : dipy.core.sphere.Sphere, optional
        Directions the diffusion signal will be resampled to. Directions are
        assumed to be on the whole sphere, not the hemisphere like bvecs.
        If omitted, 100 directions evenly distributed on the sphere will be
        used (Dipy's "repulsion100").
    sh_order : int, optional
        SH order to fit, by default 8.
    smooth : float, optional
        Lambda-regularization coefficient in the SH fit, by default 0.006.

    Returns
    -------
    resampled_dwi : np.ndarray (4D)
        Resampled "raw" diffusion signal.
    """
    validate_sh_basis_choice(sh_basis)

    # Get the "real" SH fit
    # sphere = None, so it computes the sh coefficients based on the bvecs.
    data_sh = compute_sh_coefficients(dwi_image,
                                      gradient_table,
                                      sh_order,
                                      basis_type=sh_basis,
                                      smooth=smooth)

    # Get new directions
    if sphere is None:
        sphere = get_sphere("repulsion100")
    sh_basis = sph_harm_lookup.get(sh_basis)

    # Resample data
    # B.T contains the new sampling scheme and B*data_sh projects to the sphere.
    # B : 2-D array; real harmonics sampled at (\theta, \phi)
    # m : array; degree of the sampled harmonics.
    # l : array; order of the sampled harmonics.
    B, m, l = sh_basis(sh_order, sphere.theta, sphere.phi)
    data_resampled = np.dot(data_sh, B.T)

    return data_resampled
コード例 #8
0
ファイル: neurotools.py プロジェクト: szho42/learn2track
def get_spherical_harmonics_coefficients(dwi, bvals, bvecs, sh_order=8, smooth=0.006, first=False, mean_centering=True):
    """ Compute coefficients of the spherical harmonics basis.

    Parameters
    -----------
    dwi : `nibabel.NiftiImage` object
        Diffusion signal as weighted images (4D).
    bvals : ndarray shape (N,)
        B-values used with each direction.
    bvecs : ndarray shape (N, 3)
        Directions of the diffusion signal. Directions are
        assumed to be only on the hemisphere.
    sh_order : int, optional
        SH order. Default: 8
    smooth : float, optional
        Lambda-regularization in the SH fit. Default: 0.006.
    mean_centering : bool
        If True, signal will have zero mean in each direction for all nonzero voxels

    Returns
    -------
    sh_coeffs : ndarray of shape (X, Y, Z, #coeffs)
        Spherical harmonics coefficients at every voxel. The actual number of
        coeffs depends on `sh_order`.
    """
    bvals = np.asarray(bvals)
    bvecs = np.asarray(bvecs)
    dwi_weights = dwi.get_data().astype("float32")

    # Exract the averaged b0.
    b0_idx = bvals == 0
    b0 = dwi_weights[..., b0_idx].mean(axis=3)

    # Extract diffusion weights and normalize by the b0.
    bvecs = bvecs[np.logical_not(b0_idx)]
    weights = dwi_weights[..., np.logical_not(b0_idx)]
    weights = normalize_dwi(weights, b0)

    # Assuming all directions are on the hemisphere.
    raw_sphere = HemiSphere(xyz=bvecs)

    # Fit SH to signal
    sph_harm_basis = sph_harm_lookup.get('mrtrix')
    Ba, m, n = sph_harm_basis(sh_order, raw_sphere.theta, raw_sphere.phi)
    L = -n * (n + 1)
    invB = smooth_pinv(Ba, np.sqrt(smooth) * L)
    data_sh = np.dot(weights, invB.T)

    if mean_centering:
        # Normalization in each direction (zero mean)
        idx = data_sh.sum(axis=-1).nonzero()
        means = data_sh[idx].mean(axis=0)
        data_sh[idx] -= means

    return data_sh
コード例 #9
0
ファイル: neurotools.py プロジェクト: ppoulin91/learn2track
def get_spherical_harmonics_coefficients(dwi, bvals, bvecs, sh_order=8, smooth=0.006, first=False):
    """ Compute coefficients of the spherical harmonics basis.

    Parameters
    -----------
    dwi : `nibabel.NiftiImage` object
        Diffusion signal as weighted images (4D).
    bvals : ndarray shape (N,)
        B-values used with each direction.
    bvecs : ndarray shape (N, 3)
        Directions of the diffusion signal. Directions are
        assumed to be only on the hemisphere.
    sh_order : int, optional
        SH order. Default: 8
    smooth : float, optional
        Lambda-regularization in the SH fit. Default: 0.006.

    Returns
    -------
    sh_coeffs : ndarray of shape (X, Y, Z, #coeffs)
        Spherical harmonics coefficients at every voxel. The actual number of
        coeffs depends on `sh_order`.
    """
    bvals = np.asarray(bvals)
    bvecs = np.asarray(bvecs)
    dwi_weights = dwi.get_data().astype("float32")

    # Exract the averaged b0.
    b0_idx = bvals == 0
    b0 = dwi_weights[..., b0_idx].mean(axis=3)

    # Extract diffusion weights and normalize by the b0.
    bvecs = bvecs[np.logical_not(b0_idx)]
    weights = dwi_weights[..., np.logical_not(b0_idx)]
    weights = normalize_dwi(weights, b0)

    # Assuming all directions are on the hemisphere.
    raw_sphere = HemiSphere(xyz=bvecs)

    # Fit SH to signal
    sph_harm_basis = sph_harm_lookup.get('mrtrix')
    Ba, m, n = sph_harm_basis(sh_order, raw_sphere.theta, raw_sphere.phi)
    L = -n * (n + 1)
    invB = smooth_pinv(Ba, np.sqrt(smooth) * L)
    data_sh = np.dot(weights, invB.T)
    return data_sh
コード例 #10
0
    def get_spherical_harmonics_coefficients(self,
                                             dwi_weights,
                                             bvals,
                                             bvecs,
                                             sh_order=8,
                                             smooth=0.006):
        """ Compute coefficients of the spherical harmonics basis.
        Parameters
        -----------
        dwi_weights : `nibabel.NiftiImage` object
            Diffusion signal as weighted images (4D).
        bvals : ndarray shape (N,)
            B-values used with each direction.
        bvecs : ndarray shape (N, 3)
            Directions of the diffusion signal. Directions are
            assumed to be only on the hemisphere.
        sh_order : int, optional
            SH order. Default: 8
        smooth : float, optional
            Lambda-regularization in the SH fit. Default: 0.006.
        Returns
        -------
        sh_coeffs : ndarray of shape (X, Y, Z, #coeffs)
            Spherical harmonics coefficients at every voxel. The actual number of
            coeffs depends on `sh_order`.
        """

        # Exract the averaged b0.
        b0_idx = bvals == 0
        b0 = dwi_weights[..., b0_idx].mean(axis=3) + 1e-10

        # Extract diffusion weights and normalize by the b0.
        bvecs = bvecs[np.logical_not(b0_idx)]
        weights = dwi_weights[..., np.logical_not(b0_idx)]
        weights = self.normalize_dwi(weights, b0)

        # Assuming all directions are on the hemisphere.
        raw_sphere = HemiSphere(xyz=bvecs)

        # Fit SH to signal
        sph_harm_basis = sph_harm_lookup.get("tournier07")
        Ba, m, n = sph_harm_basis(sh_order, raw_sphere.theta, raw_sphere.phi)
        L = -n * (n + 1)
        invB = smooth_pinv(Ba, np.sqrt(smooth) * L)
        data_sh = np.dot(weights, invB.T)
        return data_sh
コード例 #11
0
def resample_dwi(dwi, bvals, bvecs, directions=None, sh_order=8, smooth=0.006):
    """ Resamples a diffusion signal according to a set of directions using spherical harmonics.
    Parameters
    -----------
    dwi : `nibabel.NiftiImage` object
        Diffusion signal as weighted images (4D).
    bvals : ndarray shape (N,)
        B-values used with each direction.
    bvecs : ndarray shape (N, 3)
        Directions of the diffusion signal. Directions are
        assumed to be only on the hemisphere.
    directions : `dipy.core.sphere.Sphere` object, optional
        Directions the diffusion signal will be resampled to. Directions are
        assumed to be on the whole sphere, not the hemisphere like bvecs.
        If omitted, 100 directions evenly distributed on the sphere will be used.
    sh_order : int, optional
        SH order. Default: 8
    smooth : float, optional
        Lambda-regularization in the SH fit. Default: 0.006.
    Returns
    -------
    ndarray
        Diffusion weights resampled according to `sphere`.
    """
    data_sh = get_spherical_harmonics_coefficients(dwi,
                                                   bvals,
                                                   bvecs,
                                                   sh_order=sh_order,
                                                   smooth=smooth)

    # sphere = get_sphere('repulsion100')
    # # sphere = get_sphere('repulsion724')
    # if directions is not None:
    #     # sphere = Sphere(xyz=bvecs[1:])
    sphere = Sphere(xyz=directions)

    sph_harm_basis = sph_harm_lookup.get('tournier07')
    Ba, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi)

    data_resampled = np.dot(data_sh, Ba.T)

    return data_resampled
コード例 #12
0
ファイル: neurotools.py プロジェクト: ppoulin91/learn2track
def resample_dwi(dwi, bvals, bvecs, directions=None, sh_order=8, smooth=0.006):
    """ Resamples a diffusion signal according to a set of directions using spherical harmonics.

    Parameters
    -----------
    dwi : `nibabel.NiftiImage` object
        Diffusion signal as weighted images (4D).
    bvals : ndarray shape (N,)
        B-values used with each direction.
    bvecs : ndarray shape (N, 3)
        Directions of the diffusion signal. Directions are
        assumed to be only on the hemisphere.
    directions : `dipy.core.sphere.Sphere` object, optional
        Directions the diffusion signal will be resampled to. Directions are
        assumed to be on the whole sphere, not the hemisphere like bvecs.
        If omitted, 100 directions evenly distributed on the sphere will be used.
    sh_order : int, optional
        SH order. Default: 8
    smooth : float, optional
        Lambda-regularization in the SH fit. Default: 0.006.

    Returns
    -------
    ndarray
        Diffusion weights resampled according to `sphere`.
    """
    data_sh = get_spherical_harmonics_coefficients(dwi, bvals, bvecs, sh_order=sh_order, smooth=smooth)

    sphere = get_sphere('repulsion100')
    # sphere = get_sphere('repulsion724')
    if directions is not None:
        sphere = Sphere(xyz=bvecs[1:])

    sph_harm_basis = sph_harm_lookup.get('mrtrix')
    Ba, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi)
    data_resampled = np.dot(data_sh, Ba.T)
    return data_resampled
コード例 #13
0
ファイル: odf.py プロジェクト: Vincent-Methot/dipy
def peaks_from_model(model, data, sphere, relative_peak_threshold,
                     min_separation_angle, mask=None, return_odf=False,
                     return_sh=True, gfa_thr=0, normalize_peaks=False,
                     sh_order=8, sh_basis_type=None):
    """Fits the model to data and computes peaks and metrics

    Parameters
    ----------
    model : a model instance
        `model` will be used to fit the data.
    sphere : Sphere
        The Sphere providing discrete directions for evaluation.
    relative_peak_threshold : float
        Only return peaks greater than ``relative_peak_threshold * m`` where m
        is the largest peak.
    min_separation_angle : float in [0, 90] The minimum distance between
        directions. If two peaks are too close only the larger of the two is
        returned.
    mask : array, optional
        If `mask` is provided, voxels that are False in `mask` are skipped and
        no peaks are returned.
    return_odf : bool
        If True, the odfs are returned.
    return_sh : bool
        If True, the odf as spherical harmonics coefficients is returned
    gfa_thr : float
        Voxels with gfa less than `gfa_thr` are skipped, no peaks are returned.
    normalize_peaks : bool
        If true, all peak values are calculated relative to `max(odf)`.
    sh_order : int, optional
        Maximum SH order in the SH fit.  For `sh_order`, there will be
        ``(sh_order + 1) * (sh_order + 2) / 2`` SH coefficients (default 8).
    sh_basis_type : {None, 'mrtrix', 'fibernav'}
        ``None`` for the default dipy basis which is the fibernav basis,
        ``mrtrix`` for the MRtrix basis, and
        ``fibernav`` for the FiberNavigator basis
    
    Returns
    -------
    pam : PeaksAndMetrics
        an object with ``gfa``, ``peak_values``, ``peak_indices``, ``odf``,
        ``shm_coeffs`` as attributes

    """

    data_flat = data.reshape((-1, data.shape[-1]))
    size = len(data_flat)
    if mask is None:
        mask = np.ones(size, dtype='bool')
    else:
        mask = mask.ravel()
        if len(mask) != size:
            raise ValueError("mask is not the same size as data")

    npeaks = 5
    sh_smooth=0
    gfa_array = np.zeros(size)
    qa_array = np.zeros((size, npeaks))
    peak_values = np.zeros((size, npeaks))
    peak_indices = np.zeros((size, npeaks), dtype='int')
    peak_indices.fill(-1)

    if return_sh:

        #import here to avoid circular imports
        from dipy.reconst.shm import sph_harm_lookup, smooth_pinv

        sph_harm_basis = sph_harm_lookup.get(sh_basis_type)
        if sph_harm_basis is None:
            raise ValueError("Invalid basis name.")
        B, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi)
        L = -n * (n + 1)
        invB = smooth_pinv(B, np.sqrt(sh_smooth) * L)
        n_shm_coeff = (sh_order + 2) * (sh_order + 1) / 2
        shm_coeff = np.zeros((size, n_shm_coeff))
        invB = invB.T
        #sh = np.dot(sf, invB.T)

    if return_odf:
        odf_array = np.zeros((size, len(sphere.vertices)))

    global_max = -np.inf
    for i, sig in enumerate(data_flat):
        if not mask[i]:
            continue
        odf = model.fit(sig).odf(sphere)

        if return_sh:
            shm_coeff[i] = np.dot(odf, invB)

        if return_odf:
            odf_array[i] = odf

        gfa_array[i] = gfa(odf)
        if gfa_array[i] < gfa_thr:
            global_max = max(global_max, odf.max())
            continue

        # Get peaks of odf
        _, pk, ind = peak_directions(odf, sphere, relative_peak_threshold,
                                     min_separation_angle)

        # Calculate peak metrics
        global_max = max(global_max, pk[0])
        n = min(npeaks, len(pk))
        qa_array[i, :n] = pk[:n] - odf.min()
        if normalize_peaks:
            peak_values[i, :n] = pk[:n] / pk[0]
        else:
            peak_values[i, :n] = pk[:n]
        peak_indices[i, :n] = ind[:n]

    shape = data.shape[:-1]
    gfa_array = gfa_array.reshape(shape)
    qa_array = qa_array.reshape(shape + (npeaks,)) / global_max
    peak_values = peak_values.reshape(shape + (npeaks,))
    peak_indices = peak_indices.reshape(shape + (npeaks,))

    pam = PeaksAndMetrics()
    pam.peak_values = peak_values
    pam.peak_indices = peak_indices
    pam.gfa = gfa_array
    pam.qa = qa_array

    if return_sh:
        pam.shm_coeff = shm_coeff.reshape(shape + (n_shm_coeff,))
        pam.invB = invB
    else:
        pam.shm_coeff = None
        pam.invB = None

    if return_odf:
        pam.odf = odf_array.reshape(shape + odf_array.shape[-1:])
    else:
        pam.odf = None

    return pam
コード例 #14
0
ファイル: dipyPowMap.py プロジェクト: faskowit/antsEpiCorr
def main():
    params = readArgs()
    # read in from the command line
    read_args = params.collect_args()
    params.check_args(read_args)

    # get img obj
    dwi_img = nib.load(params.dwi_)
    mask_img = nib.load(params.mask_)

    from dipy.io import read_bvals_bvecs
    bvals, bvecs = read_bvals_bvecs(params.bval_, params.bvec_)

    # need to create the gradient table yo
    from dipy.core.gradients import gradient_table
    gtab = gradient_table(bvals, bvecs, b0_threshold=25)

    # get the data from image objects
    dwi_data = dwi_img.get_data()
    mask_data = mask_img.get_data()
    # and get affine
    img_affine = dwi_img.affine

    from dipy.data import get_sphere
    sphere = get_sphere('repulsion724')

    from dipy.segment.mask import applymask
    dwi_data = applymask(dwi_data, mask_data)

    printfl('dwi_data.shape (%d, %d, %d, %d)' % dwi_data.shape)
    printfl('\nYour bvecs look like this:{0}'.format(bvecs))
    printfl('\nYour bvals look like this:{0}\n'.format(bvals))

    from dipy.reconst.shm import anisotropic_power, sph_harm_lookup, smooth_pinv, normalize_data
    from dipy.core.sphere import HemiSphere

    smooth = 0.0
    normed_data = normalize_data(dwi_data, gtab.b0s_mask)
    normed_data = normed_data[..., np.where(1 - gtab.b0s_mask)[0]]

    from dipy.core.gradients import gradient_table_from_bvals_bvecs
    gtab2 = gradient_table_from_bvals_bvecs(
        gtab.bvals[np.where(1 - gtab.b0s_mask)[0]],
        gtab.bvecs[np.where(1 - gtab.b0s_mask)[0]])

    signal_native_pts = HemiSphere(xyz=gtab2.bvecs)
    sph_harm_basis = sph_harm_lookup.get(None)
    Ba, m, n = sph_harm_basis(params.sh_order_, signal_native_pts.theta,
                              signal_native_pts.phi)

    L = -n * (n + 1)
    invB = smooth_pinv(Ba, np.sqrt(smooth) * L)

    # fit SH basis to DWI signal
    normed_data_sh = np.dot(normed_data, invB.T)

    # power map call
    printfl("fitting power map")
    pow_map = anisotropic_power(normed_data_sh,
                                norm_factor=0.00001,
                                power=2,
                                non_negative=True)

    pow_map_img = nib.Nifti1Image(pow_map.astype(np.float32), img_affine)
    # make output name
    out_name = ''.join(
        [params.output_, '_powMap_sh',
         str(params.sh_order_), '.nii.gz'])

    printfl("writing power map to: {}".format(out_name))
    nib.save(pow_map_img, out_name)
コード例 #15
0
def peaks_from_model(model,
                     data,
                     sphere,
                     relative_peak_threshold,
                     min_separation_angle,
                     mask=None,
                     return_odf=False,
                     return_sh=True,
                     gfa_thr=0,
                     normalize_peaks=False,
                     sh_order=8,
                     sh_basis_type=None):
    """Fits the model to data and computes peaks and metrics

    Parameters
    ----------
    model : a model instance
        `model` will be used to fit the data.
    sphere : Sphere
        The Sphere providing discrete directions for evaluation.
    relative_peak_threshold : float
        Only return peaks greater than ``relative_peak_threshold * m`` where m
        is the largest peak.
    min_separation_angle : float in [0, 90] The minimum distance between
        directions. If two peaks are too close only the larger of the two is
        returned.
    mask : array, optional
        If `mask` is provided, voxels that are False in `mask` are skipped and
        no peaks are returned.
    return_odf : bool
        If True, the odfs are returned.
    return_sh : bool
        If True, the odf as spherical harmonics coefficients is returned
    gfa_thr : float
        Voxels with gfa less than `gfa_thr` are skipped, no peaks are returned.
    normalize_peaks : bool
        If true, all peak values are calculated relative to `max(odf)`.
    sh_order : int, optional
        Maximum SH order in the SH fit.  For `sh_order`, there will be
        ``(sh_order + 1) * (sh_order + 2) / 2`` SH coefficients (default 8).
    sh_basis_type : {None, 'mrtrix', 'fibernav'}
        ``None`` for the default dipy basis which is the fibernav basis,
        ``mrtrix`` for the MRtrix basis, and
        ``fibernav`` for the FiberNavigator basis
    
    Returns
    -------
    pam : PeaksAndMetrics
        an object with ``gfa``, ``peak_values``, ``peak_indices``, ``odf``,
        ``shm_coeffs`` as attributes

    """

    data_flat = data.reshape((-1, data.shape[-1]))
    size = len(data_flat)
    if mask is None:
        mask = np.ones(size, dtype='bool')
    else:
        mask = mask.ravel()
        if len(mask) != size:
            raise ValueError("mask is not the same size as data")

    npeaks = 5
    sh_smooth = 0
    gfa_array = np.zeros(size)
    qa_array = np.zeros((size, npeaks))
    peak_values = np.zeros((size, npeaks))
    peak_indices = np.zeros((size, npeaks), dtype='int')
    peak_indices.fill(-1)

    if return_sh:

        #import here to avoid circular imports
        from dipy.reconst.shm import sph_harm_lookup, smooth_pinv

        sph_harm_basis = sph_harm_lookup.get(sh_basis_type)
        if sph_harm_basis is None:
            raise ValueError("Invalid basis name.")
        B, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi)
        L = -n * (n + 1)
        invB = smooth_pinv(B, np.sqrt(sh_smooth) * L)
        n_shm_coeff = (sh_order + 2) * (sh_order + 1) / 2
        shm_coeff = np.zeros((size, n_shm_coeff))
        invB = invB.T
        #sh = np.dot(sf, invB.T)

    if return_odf:
        odf_array = np.zeros((size, len(sphere.vertices)))

    global_max = -np.inf
    for i, sig in enumerate(data_flat):
        if not mask[i]:
            continue
        odf = model.fit(sig).odf(sphere)

        if return_sh:
            shm_coeff[i] = np.dot(odf, invB)

        if return_odf:
            odf_array[i] = odf

        gfa_array[i] = gfa(odf)
        if gfa_array[i] < gfa_thr:
            global_max = max(global_max, odf.max())
            continue

        # Get peaks of odf
        _, pk, ind = peak_directions(odf, sphere, relative_peak_threshold,
                                     min_separation_angle)

        # Calculate peak metrics
        global_max = max(global_max, pk[0])
        n = min(npeaks, len(pk))
        qa_array[i, :n] = pk[:n] - odf.min()
        if normalize_peaks:
            peak_values[i, :n] = pk[:n] / pk[0]
        else:
            peak_values[i, :n] = pk[:n]
        peak_indices[i, :n] = ind[:n]

    shape = data.shape[:-1]
    gfa_array = gfa_array.reshape(shape)
    qa_array = qa_array.reshape(shape + (npeaks, )) / global_max
    peak_values = peak_values.reshape(shape + (npeaks, ))
    peak_indices = peak_indices.reshape(shape + (npeaks, ))

    pam = PeaksAndMetrics()
    pam.peak_values = peak_values
    pam.peak_indices = peak_indices
    pam.gfa = gfa_array
    pam.qa = qa_array

    if return_sh:
        pam.shm_coeff = shm_coeff.reshape(shape + (n_shm_coeff, ))
        pam.invB = invB
    else:
        pam.shm_coeff = None
        pam.invB = None

    if return_odf:
        pam.odf = odf_array.reshape(shape + odf_array.shape[-1:])
    else:
        pam.odf = None

    return pam
コード例 #16
0
ファイル: best_fiber_tracking.py プロジェクト: nipy/dipy_qa
def show_odfs_and_fa(fa, pam, mask, affine, sphere, ftmp='odf.mmap',
                     basis_type=None, norm_odfs=True, scale_odfs=0.5):
    
    renderer = window.Renderer()
    renderer.background((1, 1, 1))
    
    slice_actor = actor.slicer(fa) #, value_range)
    
    odf_shape = fa.shape + (sphere.vertices.shape[0],)
    odfs = np.memmap(ftmp, dtype=np.float32, mode='w+',
                     shape=odf_shape)
    
    sph_harm_basis = sph_harm_lookup.get(basis_type)

    if sph_harm_basis is None:
        raise ValueError("Invalid basis name.")
    B, m, n = sph_harm_basis(8, sphere.theta, sphere.phi)

    odfs[:] = np.dot(pam.shm_coeff.astype('f4'), B.T.astype('f4'))
    
    odf_slicer = actor.odf_slicer(odfs, mask=mask,
                                  sphere=sphere, scale=scale_odfs,
                                  norm=norm_odfs, colormap='magma')
        
    renderer.add(odf_slicer)
    renderer.add(slice_actor)
    
    show_m = window.ShowManager(renderer, size=(2000, 1000))
    show_m.initialize()
    
    """
    We'll start by creating the panel and adding it to the ``ShowManager``
    """
    
    label_position = ui.TextBlock2D(text='Position:')
    label_value = ui.TextBlock2D(text='Value:')
    
    result_position = ui.TextBlock2D(text='')
    result_value = ui.TextBlock2D(text='')
    line_slider_z = ui.LineSlider2D(min_value=0,
                                    max_value=shape[2] - 1,
                                    initial_value=shape[2] / 2,
                                    text_template="{value:.0f}",
                                    length=140)
    
    def change_slice_z(i_ren, obj, slider):
        z = int(np.round(slider.value))
        slice_actor.display(z=z)
        odf_slicer.display(z=z)
        show_m.render()
    
    line_slider_z.add_callback(line_slider_z.slider_disk,
                               "LeftButtonReleaseEvent",
                               change_slice_z)
    
    panel_picking = ui.Panel2D(center=(200, 120),
                               size=(250, 225),
                               color=(0, 0, 0),
                               opacity=0.75,
                               align="left")
    
    # panel_picking.add_element(label_position, 'relative', (0.1, 0.55))
    # panel_picking.add_element(label_value, 'relative', (0.1, 0.25))
    
    # panel_picking.add_element(result_position, 'relative', (0.45, 0.55))
    # panel_picking.add_element(result_value, 'relative', (0.45, 0.25))
    
    panel_picking.add_element(line_slider_z, 'relative', (0.5, 0.9))
    
    show_m.ren.add(panel_picking)
    
    def left_click_callback(obj, ev):
        """Get the value of the clicked voxel and show it in the panel."""
        event_pos = show_m.iren.GetEventPosition()
    
        obj.picker.Pick(event_pos[0],
                        event_pos[1],
                        0,
                        show_m.ren)
    
        i, j, k = obj.picker.GetPointIJK()
        print(i,j,k)
        result_position.message = '({}, {}, {})'.format(str(i), str(j), str(k))
        result_value.message = '%.3f' % fa[i, j, k]
    
    slice_actor.SetInterpolate(True)
    slice_actor.AddObserver('LeftButtonPressEvent', left_click_callback, 1.0)
        
    show_m.start()
    
    odfs._mmap.close()
    del odfs
    os.remove(ftmp)
コード例 #17
0
def show_odfs_and_fa(fa,
                     pam,
                     mask,
                     affine,
                     sphere,
                     ftmp='odf.mmap',
                     basis_type=None,
                     norm_odfs=True,
                     scale_odfs=0.5):

    renderer = window.Renderer()
    renderer.background((1, 1, 1))

    slice_actor = actor.slicer(fa)  #, value_range)

    odf_shape = fa.shape + (sphere.vertices.shape[0], )
    odfs = np.memmap(ftmp, dtype=np.float32, mode='w+', shape=odf_shape)

    sph_harm_basis = sph_harm_lookup.get(basis_type)

    if sph_harm_basis is None:
        raise ValueError("Invalid basis name.")
    B, m, n = sph_harm_basis(8, sphere.theta, sphere.phi)

    odfs[:] = np.dot(pam.shm_coeff.astype('f4'), B.T.astype('f4'))

    odf_slicer = actor.odf_slicer(odfs,
                                  mask=mask,
                                  sphere=sphere,
                                  scale=scale_odfs,
                                  norm=norm_odfs,
                                  colormap='magma')

    renderer.add(odf_slicer)
    renderer.add(slice_actor)

    show_m = window.ShowManager(renderer, size=(2000, 1000))
    show_m.initialize()
    """
    We'll start by creating the panel and adding it to the ``ShowManager``
    """

    label_position = ui.TextBlock2D(text='Position:')
    label_value = ui.TextBlock2D(text='Value:')

    result_position = ui.TextBlock2D(text='')
    result_value = ui.TextBlock2D(text='')
    line_slider_z = ui.LineSlider2D(min_value=0,
                                    max_value=shape[2] - 1,
                                    initial_value=shape[2] / 2,
                                    text_template="{value:.0f}",
                                    length=140)

    def change_slice_z(i_ren, obj, slider):
        z = int(np.round(slider.value))
        slice_actor.display(z=z)
        odf_slicer.display(z=z)
        show_m.render()

    line_slider_z.add_callback(line_slider_z.slider_disk,
                               "LeftButtonReleaseEvent", change_slice_z)

    panel_picking = ui.Panel2D(center=(200, 120),
                               size=(250, 225),
                               color=(0, 0, 0),
                               opacity=0.75,
                               align="left")

    # panel_picking.add_element(label_position, 'relative', (0.1, 0.55))
    # panel_picking.add_element(label_value, 'relative', (0.1, 0.25))

    # panel_picking.add_element(result_position, 'relative', (0.45, 0.55))
    # panel_picking.add_element(result_value, 'relative', (0.45, 0.25))

    panel_picking.add_element(line_slider_z, 'relative', (0.5, 0.9))

    show_m.ren.add(panel_picking)

    def left_click_callback(obj, ev):
        """Get the value of the clicked voxel and show it in the panel."""
        event_pos = show_m.iren.GetEventPosition()

        obj.picker.Pick(event_pos[0], event_pos[1], 0, show_m.ren)

        i, j, k = obj.picker.GetPointIJK()
        print(i, j, k)
        result_position.message = '({}, {}, {})'.format(str(i), str(j), str(k))
        result_value.message = '%.3f' % fa[i, j, k]

    slice_actor.SetInterpolate(True)
    slice_actor.AddObserver('LeftButtonPressEvent', left_click_callback, 1.0)

    show_m.start()

    odfs._mmap.close()
    del odfs
    os.remove(ftmp)
コード例 #18
0
ファイル: odf.py プロジェクト: swederik/dipy
def peaks_from_model(model, data, sphere, relative_peak_threshold,
                     min_separation_angle, mask=None, return_odf=False,
                     return_sh=True, gfa_thr=0, normalize_peaks=False,
                     sh_order=8, sh_basis_type=None, ravel_peaks=False,
                     npeaks=5, parallel=False, nbr_process=None):
    """Fits the model to data and computes peaks and metrics

    Parameters
    ----------
    model : a model instance
        `model` will be used to fit the data.
    sphere : Sphere
        The Sphere providing discrete directions for evaluation.
    relative_peak_threshold : float
        Only return peaks greater than ``relative_peak_threshold * m`` where m
        is the largest peak.
    min_separation_angle : float in [0, 90] The minimum distance between
        directions. If two peaks are too close only the larger of the two is
        returned.
    mask : array, optional
        If `mask` is provided, voxels that are False in `mask` are skipped and
        no peaks are returned.
    return_odf : bool
        If True, the odfs are returned.
    return_sh : bool
        If True, the odf as spherical harmonics coefficients is returned
    gfa_thr : float
        Voxels with gfa less than `gfa_thr` are skipped, no peaks are returned.
    normalize_peaks : bool
        If true, all peak values are calculated relative to `max(odf)`.
    sh_order : int, optional
        Maximum SH order in the SH fit.  For `sh_order`, there will be
        ``(sh_order + 1) * (sh_order + 2) / 2`` SH coefficients (default 8).
    sh_basis_type : {None, 'mrtrix', 'fibernav'}
        ``None`` for the default dipy basis which is the fibernav basis,
        ``mrtrix`` for the MRtrix basis, and
        ``fibernav`` for the FiberNavigator basis
    ravel_peaks : bool
        If True, the peaks are returned as [x1, y1, z1, ..., xn, yn, zn] instead
        of Nx3. Set this flag to True if you want to visualize the peaks in the
        fibernavigator or in mrtrix.
    npeaks : int
        Maximum number of peaks found (default 5 peaks).
    parallel: bool
        If True, use multiprocessing to compute peaks and metric (default False).
    nbr_process: int
        If `parallel == True`, the number of subprocess to use (default multiprocessing.cpu_count()).

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

    """

    if parallel:
        return __peaks_from_model_parallel(model,
                                           data, sphere,
                                           relative_peak_threshold,
                                           min_separation_angle,
                                           mask, return_odf,
                                           return_sh,
                                           gfa_thr,
                                           normalize_peaks,
                                           sh_order,
                                           sh_basis_type,
                                           ravel_peaks,
                                           npeaks,
                                           nbr_process)

    shape = data.shape[:-1]
    if mask is None:
        mask = np.ones(shape, dtype='bool')
    else:
        if mask.shape != shape:
            raise ValueError("Mask is not the same shape as data.")

    sh_smooth = 0
    gfa_array = np.zeros(shape)
    qa_array = np.zeros((shape + (npeaks,)))

    peak_dirs = np.zeros((shape + (npeaks, 3)))
    peak_values = np.zeros((shape + (npeaks,)))
    peak_indices = np.zeros((shape + (npeaks,)), dtype='int')
    peak_indices.fill(-1)

    if return_sh:
        # import here to avoid circular imports
        from dipy.reconst.shm import sph_harm_lookup, smooth_pinv

        sph_harm_basis = sph_harm_lookup.get(sh_basis_type)
        if sph_harm_basis is None:
            raise ValueError("Invalid basis name.")
        B, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi)
        L = -n * (n + 1)
        invB = smooth_pinv(B, np.sqrt(sh_smooth) * L)
        n_shm_coeff = (sh_order + 2) * (sh_order + 1) / 2
        shm_coeff = np.zeros((shape + (n_shm_coeff,)))
        invB = invB.T

    if return_odf:
        odf_array = np.zeros((shape + (len(sphere.vertices),)))

    global_max = -np.inf
    for idx in ndindex(shape):
        if not mask[idx]:
            continue

        odf = model.fit(data[idx]).odf(sphere)

        if return_sh:
            shm_coeff[idx] = np.dot(odf, invB)

        if return_odf:
            odf_array[idx] = odf

        gfa_array[idx] = gfa(odf)
        if gfa_array[idx] < gfa_thr:
            global_max = max(global_max, odf.max())
            continue

        # Get peaks of odf
        direction, pk, ind = peak_directions(
            odf, sphere, relative_peak_threshold,
            min_separation_angle)

        # Calculate peak metrics
        global_max = max(global_max, pk[0])
        n = min(npeaks, len(pk))
        qa_array[idx][:n] = pk[:n] - odf.min()

        peak_dirs[idx][:n] = direction[:n]
        peak_indices[idx][:n] = ind[:n]
        peak_values[idx][:n] = pk[:n]

        if normalize_peaks:
            peak_values[idx][:n] /= pk[0]
            peak_dirs[idx] *= peak_values[idx][:, None]

    #gfa_array = gfa_array
    qa_array /= global_max
    #peak_values = peak_values
    #peak_indices = peak_indices

    # The fibernavigator only supports float32. Since this form is mainly
    # for external visualisation, we enforce float32.
    if ravel_peaks:
        peak_dirs = peak_dirs.reshape(shape + (3 * npeaks,)).astype('float32')

    pam = PeaksAndMetrics()
    pam.peak_dirs = peak_dirs
    pam.peak_values = peak_values
    pam.peak_indices = peak_indices
    pam.gfa = gfa_array
    pam.qa = qa_array

    if return_sh:
        pam.shm_coeff = shm_coeff
        pam.invB = invB
    else:
        pam.shm_coeff = None
        pam.invB = None

    if return_odf:
        pam.odf = odf_array
    else:
        pam.odf = None

    return pam