Пример #1
0
def resection_area_computation(img: Any, _subject_tree=None, _priority=None):
    """turns given `resection map`_ into mni_ coordinate system, uses :func:`nodestimation.project.read_or_write` decorator

        :param img: `resection map`_
        :type img: Any
        :param _subject_tree: representation of patient`s files structure, default None
        :type _subject_tree: *look for SubjectTree in* :mod:`nodestimation.project.annotations` *, optional*
        :param _priority: if several files are read, which one to choose, if None, read all of them, default None
        :type _priority: int, optional
        :return: resection area
        :rtype: np.ndarray_

        .. _mni: https://brainmap.org/training/BrettTransform.html

    """

    res = np.array(img.get_data().tolist())
    img_coordinates = list()
    for i in range(res.shape[0]):
        for j in range(res.shape[1]):
            for k in range(res.shape[2]):
                if res[i, j, k] != 0:
                    img_coordinates.append(np.array([i, j, k]))
    img_coordinates = np.array(img_coordinates)
    mni_coordinates = list()
    for coordinate in img_coordinates:
        mni_coordinates.append(
            np.array(
                image.coord_transform(coordinate[0], coordinate[1],
                                      coordinate[2], img.affine)))
    print(np.array(mni_coordinates).shape)
    return np.array(mni_coordinates)
Пример #2
0
def test_get_mask_measures():
    # Create ellipsoid image
    one_mask_data = np.ones((60, 60, 80))
    affine = np.eye(4)
    affine[0, 0] = .7
    affine[2, 2] = .5
    affine[:3, 3] = np.array([-2, 7, 3])
    one_mask_img = nibabel.Nifti1Image(one_mask_data, affine)
    i, j, k = np.where(one_mask_data <2)   
    voxels_coords = np.array(coord_transform(i, j, k, affine)).T
    center_coords = np.array([ 20.,  31.,  20.])
    positions = voxels_coords - center_coords
    angle = np.pi / 3
    c = np.cos(angle)
    s = np.sin(angle)
    rotation = np.array([[c, -s, 0], [s, c, 0.], [0, 0, 1]])
    lambd = np.eye(3)
    a = 6.
    b = 15.
    c = 16.
    lambd[0, 0] = 1. / a ** 2
    lambd[2, 2] = 1. / b ** 2
    lambd[1, 1] = 1. / c ** 2
    trans_sqrt = np.sqrt(lambd).dot(rotation)
    transformed_positions = trans_sqrt.dot(positions.T).T
    new_voxels = np.sum(transformed_positions ** 2, axis=1) <= 1
    mask_file = os.path.join(tst.tmpdir, 'ellipsoid.nii.gz')
    masking.unmask(new_voxels, one_mask_img).to_filename(mask_file)
    length_ap, length_rl, length_is, symmetry, volume = brain_mask._get_mask_measures(mask_file)
    np.testing.assert_array_almost_equal(length_ap, 2 * c)
    np.testing.assert_array_almost_equal(length_rl, 2 * b, decimal=0)
    np.testing.assert_array_almost_equal(length_is, 2 * a, decimal=0)
    assert_greater(symmetry, .99)
Пример #3
0
def plot_2D_crosscuts(bm_data, coord, fdir):

    # Get the locations of the mni template
    XX, YY, ZZ = np.where(bm_data > 0.1)
    # Transform a few of them in MNI space
    nskip = 29
    xmni, ymni, zmni = coord_transform(XX.ravel()[::nskip],
                                       YY.ravel()[::nskip],
                                       ZZ.ravel()[::nskip], bm.affine)

    # Plot the template and the fieldtrip locations together in a 2D crosscuts way
    fig, ax = plt.subplots(ncols=3, figsize=(15, 5))
    ax[0].scatter(xmni, ymni, s=1)
    ax[1].scatter(xmni, zmni, s=1)
    ax[2].scatter(ymni, zmni, s=1)

    # ax[0].scatter(XX.ravel()[::nskip],YY.ravel()[::nskip], s = bm_data.ravel()[::nskip])
    # ax[1].scatter(XX.ravel()[::nskip],ZZ.ravel()[::nskip], s = bm_data.ravel()[::nskip])
    # ax[2].scatter(YY.ravel()[::nskip],ZZ.ravel()[::nskip], s = bm_data.ravel()[::nskip])

    crosscuts = [[0, 1], [0, 2], [1, 2]]

    for i, cc in enumerate(crosscuts):

        ax[i].scatter(coord[:, cc[0]], coord[:, cc[1]], c='C1', alpha=0.5, s=1)

        ax[i].set_title('{} crosscut'.format(cc))
        ax[i].set_xticks([])
        ax[i].set_yticks([])

    plt.savefig(out_dir + '2Dcrosscut.png', fmt='png', dpi=300)
    plt.close('all')

    return
Пример #4
0
    def transform_to_2d(self, data, affine):
        """Cut the 3D volume into a 2D slice.

        Parameters
        ----------
        data : 3D :class:`~numpy.ndarray`
            The 3D volume to cut.

        affine : 4x4 :class:`~numpy.ndarray`
            The affine of the volume.

        """
        coords = [0, 0, 0]
        if self.direction not in ['x', 'y', 'z']:
            raise ValueError('Invalid value for direction %s' % self.direction)
        coords['xyz'.index(self.direction)] = self.coord
        x_map, y_map, z_map = [
            int(np.round(c))
            for c in coord_transform(coords[0], coords[1], coords[2],
                                     np.linalg.inv(affine))
        ]
        if self.direction == 'y':
            cut = np.rot90(data[:, y_map, :])
        elif self.direction == 'x':
            cut = np.rot90(data[x_map, :, :])
        elif self.direction == 'z':
            cut = np.rot90(data[:, :, z_map])
        return cut
Пример #5
0
 def get_coords_ball(r2):
     vox_coords = np.unravel_index(r2.get_fdata().argmax(), r2.shape)
     coords = image.coord_transform(*vox_coords, thr_r2.affine)
     _, ball =_apply_mask_and_get_affinity([list(coords)], image.concat_imgs([r2]), 3., True)
     ball = ball.toarray().reshape(r2.shape)* 100.
     ball = image.new_img_like(r2, ball.astype(int))
     
     return coords, ball
Пример #6
0
    def _run_interface(self, runtime):
        import os.path as op
        import nibabel.gifti as ng
        import numpy as np
        import skimage.measure as sm
        import nilearn.image as nimg

        import slam.io as sio
        import slam.differential_geometry as sdg

        from nipype.utils.filemanip import split_filename

        # Generate output mesh filename from the input image name
        _, fname, _ = split_filename(self.inputs.image_file)
        gii_file = op.abspath(op.join(runtime.cwd, fname + ".gii"))

        # Load the largest connected component of the input image
        img = nimg.largest_connected_component_img(self.inputs.image_file)

        # TODO: check if the input image is correct (binary)

        # Run the marching cube algorithm
        verts, faces, normals, values = sm.marching_cubes_lewiner(
            img.get_data(), self.inputs.level)

        # Convert vertices coordinates to image space
        # TODO: check that is correct by plotting the mesh on the image
        x, y, z = nimg.coord_transform(verts[:, 0], verts[:, 1], verts[:, 2],
                                       img.affine)
        mm_verts = np.array([x, y, z]).T

        # Save the mesh as Gifti
        # FIXME: FreeView can not open the mesh (but anatomist do)
        gii = ng.GiftiImage(darrays=[
            ng.GiftiDataArray(mm_verts, intent='NIFTI_INTENT_POINTSET'),
            ng.GiftiDataArray(faces, intent='NIFTI_INTENT_TRIANGLE')
        ])
        gii.meta = ng.GiftiMetaData().from_dict({
            "volume_file":
            self.inputs.image_file,
            "marching_cube_level":
            str(self.inputs.level),
            "smoothing_iterations":
            str(self.inputs.smoothing_iter),
            "smoothing_dt":
            str(self.inputs.smoothing_dt)
        })
        ng.write(gii, gii_file)

        # Optional: Smooth the marching cube output with SLAM
        if self.inputs.smoothing_iter > 0:
            mesh = sdg.laplacian_mesh_smoothing(
                sio.load_mesh(gii_file),
                nb_iter=self.inputs.smoothing_iter,
                dt=self.inputs.smoothing_dt)
            sio.write_mesh(mesh, gii_file)

        return runtime
Пример #7
0
def coords_to_img(coords, fwhm=9.0):
    mask = load_mni152_brain_mask()
    masker = NiftiMasker(mask).fit()
    voxels = np.asarray(
        image.coord_transform(*coords.T, np.linalg.pinv(mask.affine)),
        dtype=int,
    ).T
    peaks = np.zeros(mask.shape)
    np.add.at(peaks, tuple(voxels.T), 1.0)
    peaks_img = image.new_img_like(mask, peaks)
    img = image.smooth_img(peaks_img, fwhm=fwhm)
    img = masker.inverse_transform(masker.transform(img).squeeze())
    return img
Пример #8
0
def roi_map_scatter(roi, beta_map, ref_vol_img):
    # get coordinates of roi, calculate bounds
    coords = np.argwhere(load_img(roi).get_fdata() != 0)
    roi_max_bounds = np.max(coords, 0)
    roi_min_bounds = np.min(coords, 0)
    roi_center_native = np.mean(coords, 0)
    roi_center_ras = coord_transform(*roi_center_native, ref_vol_img.affine)

    print(
        f"****\n{roi} extends from {roi_max_bounds} to {roi_min_bounds} and is centered at:\n{roi_center_native} (native) = {roi_center_ras} (RAS)",
        sep='\n')

    # mask the beta map with the roi mask
    beta_masker = NiftiMasker(mask_img=roi)
    roi_betas = beta_masker.fit_transform(beta_map)[0]
    roi_beta_min = np.min(roi_betas)
    roi_beta_max = np.max(roi_betas)

    print(coords.shape, roi_betas.shape)
    coords_ras = np.array(
        coord_transform(coords[:, 0], coords[:, 1], coords[:, 2],
                        ref_vol_img.affine))

    plt.scatter(coords_ras[0, :], roi_betas)
    plt.xlabel("Left - Right")
    plt.ylabel(f"{op.basename(beta_map)}")
    plt.show()
    plt.close()
    plt.scatter(coords_ras[1, :], roi_betas)
    plt.xlabel("Posterior - Anterior")
    plt.ylabel(f"{op.basename(beta_map)}")
    plt.show()
    plt.close()
    # plot histogram of beta values within roi mask
    plt.scatter(coords_ras[2, :], roi_betas)
    plt.xlabel("Inferior - Superior")
    plt.ylabel(f"{op.basename(beta_map)}")
    plt.show()
    plt.close()
Пример #9
0
def find_atlas(volume):
    #atlas = fetch_atlas_destrieux_2009(lateralized=True, data_dir=None, url=None, resume=True, verbose=1)
    atlas = fetch_atlas_aal(version='SPM12',
                            data_dir=None,
                            url=None,
                            resume=True,
                            verbose=1)
    dictionary = dict(zip([int(i) for i in atlas.indices], atlas.labels))
    A = load_img(atlas.maps).affine
    trA = np.linalg.inv(A)
    atlas_map = load_img(atlas.maps).get_fdata()
    affine = [[-3, 0, 0, 78], [0, 3, 0, -112], [0, 0, 6, -50], [0, 0, 0, 1]]

    def cast(x, y, z, affine, trA):
        coord = coord_transform(x, y, z, affine)
        return np.dot(trA, [coord[0], coord[1], coord[2], 1])

    def find(x, y, z, affine, trA):
        vox_coord = cast(x, y, z, affine, trA)
        label = atlas_map[int(vox_coord[0]),
                          int(vox_coord[1]),
                          int(vox_coord[2])]
        if int(label) == 0: return
        return dictionary[int(label)]

    index = np.where(volume > 0.8)
    for i in range(np.sum(volume > 0.8)):
        x, y, z = index[0][i], index[1][i], index[2][i]
        print(x, y, z, coord_transform(x, y, z, affine),
              find(x, y, z, affine, trA), volume[x, y, z])

    index = np.where(volume < -0.8)
    for i in range(np.sum(volume < -0.8)):
        x, y, z = index[0][i], index[1][i], index[2][i]
        print(x, y, z, coord_transform(x, y, z, affine),
              find(x, y, z, affine, trA), volume[x, y, z])
Пример #10
0
def extract_img_value_for_mni_coords(mni_coords, img):
    '''Extract image value for specific mni coordinates.
    
    Args: 
        mni_coords (tuple):
            MNI coordinates x, y, z.
        img (Nifti1Image):
            3D Nifti image. Can be atlas image, statistical map, T1, etc.
    
    Returns:
        Image value for voxel closest to specified MNI coordinates.
    '''    
    array_coords = image.coord_transform(*mni_coords, np.linalg.inv(img.affine))
    array_coords = tuple(round(array_coord) for array_coord in array_coords)
    return img.get_fdata()[array_coords]
    def get_seeds(self, nifti_img_path, connect_diag=True, min_size=100):
        """
        Get the seeds from regions in a group parcellation Nifti image
        :param nifti_img_path: str
            Path to the group parcellation Nifti image
        :param connect_diag: See the documentation of nilearn.regions.connected_label_regions

        :param min_size: See the documentation of nilearn.regions.connected_label_regions

        :return:
            l_medoids: list of tuple of shape (x,y,z)
                Each tuple represents the coordinates of the seed voxel of a region
            l_medoids_coord_mniL list of tuple of shape (x,y,z)
                Each tuple represents the coordinates of the seed voxel of a region in MNI coordinates
        """

        mist_img = nb.load(nifti_img_path)

        regions = connected_label_regions(nifti_img_path, connect_diag=connect_diag, min_size=min_size).get_data()

        labels_regions = np.unique(regions)

        # Apply the kmedoids clustering for each region
        l_medoids = []
        for label in range(1, len(labels_regions)):
            label_coords = np.argwhere(regions == label)

            kmedoids_instance = kmedoids(label_coords, [0])

            kmedoids_instance.process()

            medoid = kmedoids_instance.get_medoids()

            elem = tuple(label_coords[medoid[0]])

            l_medoids.append(elem)

        l_medoids_coord_mni = [coord_transform(medoid[0], medoid[1], medoid[2], mist_img.get_affine())
                               for medoid in l_medoids]

        return l_medoids, l_medoids_coord_mni
Пример #12
0
def nifti_to_txt(filename_nii, filename_txt="auto"):
    """
    Extracts possible coordinates from a NiFTI template and saves them as a .txt file.
    """
    # Read template image
    img = image.load_img(filename_nii)
    # Extract gray matter voxels
    dat = img.get_fdata()
    x, y, z = np.where(dat == 1.0)
    # Convert to MNI space
    affine = img.affine
    within_mni = image.coord_transform(x=x, y=y, z=z, affine=affine)
    within_mni = np.array(within_mni).T
    # Create automatic output filename
    if filename_txt == "auto":
        basename_nii = path.basename(filename_nii)
        basename_txt = "within_" + basename_txt
        filename_txt = filename_nii.replace(basename_nii, basename_txt)
    # Save possible MNI coordinates
    _ = np.savetxt(filename_txt, within_mni, fmt="%i")
    return within_mni
Пример #13
0
 def convert_coordinates(self, x, y, z):
     niimg = datasets.load_mni152_template()
     converted = image.coord_transform((x, y, z), niimg.affine)
     print("CONVERTED COORDINATES: ", converted)
Пример #14
0
    bm = load_mni152_brain_mask()
    bm_data = bm.get_fdata()
    Lx, Ly, Lz = bm_data.shape

    # Apply shift and scaling to the data and reorder the axis in pos
    shift = np.array([0, 40, 40])
    scale = np.array([1, 1, 1])
    ix, iy, iz = [1, 0, 2]
    pos_ref = np.array([pos[:, ix], pos[:, iy], pos[:, iz]]).T
    transformed_pos = pos_ref * scale[None, :] - shift[None, :]

    # Plot a 2d crosscut overview to check that the scaling makes sense
    plot_2D_crosscuts(bm_data, transformed_pos, fdir)

    # Send the position to volume space
    pos_volume = coord_transform(transformed_pos[:, 0], transformed_pos[:, 1],
                                 transformed_pos[:, 2], inv(bm.affine))
    loc_volume = np.round(pos_volume).astype(int).T

    # Plot the location of source detection on a brain template
    #     plot_sources_on_brain(loc_volume,bm,bm_data)

    # Define the window for temporal averaging
    dt = (time[1] - time[0]) * av_win
    time_av = np.arange(time[0], time[-1], dt)
    t_size = len(time_av)
    print(
        'The software is currently averaging the time traces over a time window of {} s'
        .format(dt))
    print('This will result in a nifti file with {} volumes.'.format(t_size))

    print(fun.shape)
Пример #15
0
    bg_img = "BG.nii.gz"
    img = "vol0000.nii.gz"
    sl = int(100)
    outpng = "test"
    lthresh = float(4)
    useatlas = "empty.nii.gz"
    annotate = "0"
    alpha = 0.4

alpha = 0.3
#bgrange = sys.argv[2]
#ulthresh = sys.argv[5]
img = image.load_img(img)
useatlas = '1'
img.get_fdata()[img.get_fdata() < 0] = 0
(x, y, z) = image.coord_transform(0, 0, sl, img.affine)
print(sl, x, y, z)

smith = datasets.fetch_atlas_smith_2009()
if useatlas == '0':
    atlas = image.load_img(smith.bm10)
    atlas = image.index_img(atlas, (7, 8, 9))

    print(useatlas)
    display = plotting.plot_prob_atlas(
        atlas,
        bg_img=bg_img,
        #colorbar=True,
        black_bg=True,
        display_mode='z',
        cut_coords=(z, ),  # display_mode="z", cut_coords = 3, 
def index_to_xy_coord(x, y, z=10):
    '''Transforms data index to coordinates of the background + offset'''
    coords = coord_transform(x, y, z, affine=thresholded_score_map_img.affine)
    return np.array(coords)[np.newaxis, :] + np.array([0, 1, 0])
Пример #17
0
from nilearn import datasets, image
import numpy as np

niimg = datasets.load_mni152_template()
print(niimg.get_data().shape)
result = image.coord_transform(54, 10, 38, niimg.affine)
print(np.asarray(result) / 1000)
Пример #18
0
def plot_scores(scores_path, save_path, glassbrain_save, mask_path, select_voxels_by_pval=False, perm_path=None,
                roi_mask=None):
    print('Plotting', save_path)
    from nilearn import plotting
    mask = joblib.load(mask_path)[0]
    mean_scores = mean_img(scores_path)
    img = load_img(scores_path)
    if roi_mask:
        roi_mask = resample_img(roi_mask, mask._affine, mask.shape, interpolation='nearest')
        roi_mask = intersect_masks([mask, roi_mask])
    if select_voxels_by_pval:
        perm_all = joblib.load(perm_path.format('s'))
        pval = joblib.load(perm_path.format('pval'))
        selection_mask = mask
        if roi_mask:
            pval = unmask(pval, mask)
            pval = apply_mask(pval, roi_mask)
            selection_mask = roi_mask
        n_permutations = perm_all.shape[1]
        thresh = 1.0 / n_permutations
        pval_mask = pval > thresh

        mean_scores = apply_mask(mean_scores, selection_mask)
        mean_scores[pval_mask] = 0
        mean_scores = unmask(mean_scores, selection_mask)
        img = apply_mask(img, selection_mask)
        img[np.broadcast_to(pval_mask, (img.shape[0], pval_mask.shape[0]))] = 0
        img = unmask(img, selection_mask)
    elif roi_mask:
        mean_scores = apply_mask(mean_scores, roi_mask)
        mean_scores = unmask(mean_scores, roi_mask)
        img = apply_mask(img, roi_mask)
        img = unmask(img, roi_mask)

    data = img.dataobj
    avg_max = np.max(mean_scores.dataobj)
    avg_argmax = np.unravel_index(np.argmax(mean_scores.dataobj), mean_scores.shape)
    total_max = np.max(data)
    total_argmax = np.unravel_index(np.argmax(data), data.shape)
    fold0_max = np.max(data[..., 0])
    fold0_argmax = np.unravel_index(np.argmax(data[..., 0]), data.shape[:-1])
    avg_argmax_mni = coord_transform(*avg_argmax, mask.affine)
    fold0_argmax_mni = coord_transform(*fold0_argmax, mask.affine)
    total_argmax_mni = coord_transform(*total_argmax[:3], mask.affine)

    def _plot_helper(scores, markers, save_suffix, title):
        thresh = 0.0  # 0.05
        display = plotting.plot_stat_map(scores, threshold=thresh, title=title)
        display.add_markers([markers], marker_color='w', marker_size=50)
        #    display.add_contours(temporal_lobe_mask,filled=False,colors='m')
        #    display.add_contours(heschl_mask,filled=False,colors='g')
        plt.gcf().savefig(save_path + save_suffix)
        plt.close()
        display = plotting.plot_glass_brain(scores, threshold=thresh, colorbar=True,
                                            display_mode='lzry', plot_abs=False)
        display.add_contours(temporal_lobe_mask, filled=False, colors='m')
        display.add_contours(heschl_mask, filled=False, colors='g')
        display.add_markers([markers], marker_color='w', marker_size=50)
        # proxy artist trick to make legend
        from matplotlib.patches import Rectangle
        cont1 = Rectangle((0, 0), 1, 1, fc="magenta")
        cont2 = Rectangle((0, 0), 1, 1, fc="green")
        plt.legend([cont1, cont2], ['Temporal lobe', 'Heschl gyrus'])
        plt.gcf().savefig(glassbrain_save + save_suffix)
        plt.close()

    title = 'Avg %.3f %s' % (avg_max, str(avg_argmax_mni))
    _plot_helper(mean_scores, avg_argmax_mni, '_avg.png', title)
    title = 'Fold 0 %.3f %s' % (fold0_max, str(fold0_argmax_mni))
    _plot_helper(img.slicer[..., 0], fold0_argmax_mni, '_fold0.png', title)
    title = 'Total %.3f %s fold %d' % (total_max, str(total_argmax_mni), total_argmax[3])
    _plot_helper(img.slicer[..., total_argmax[3]], total_argmax_mni, '_total.png', title)
Пример #19
0
    filters = make_lcmv(evoked.info,
                        fwd,
                        cov,
                        reg=0.05,
                        pick_ori='max-power',
                        weight_norm='unit-noise-gain',
                        reduce_rank=True)
    stc = apply_lcmv(evoked, filters, max_ori_out='signed')

    max_vetrs_across_time = np.argmax(stc.rh_data, axis=0)
    verts = stc.vertices[0][max_vetrs_across_time]

    tbas = []
    for v in verts:
        mni = mne.vertex_to_mni(v, 0, 'fsaverage')[0]
        tal_coord = coord_transform(mni[0], mni[1], mni[2], affine)
        ba = tal_to_ba[int(tal_coord[0]), int(tal_coord[1]), int(tal_coord[2])]
        tbas.append(ba)
    if yi in tbas:
        ypred.append(yi)
    else:
        k = classes_to_keep.copy()
        k.remove(yi)
        ti = random.randint(0, 13)
        ypred.append(k[ti])
    print(ypred[i])
np.save('y.npy', y)
np.save('ypred.npy', ypred)

from sklearn.metrics import f1_score
print(f1_score(y, ypred, average='macro'))
Пример #20
0
def driver(image_file, output_directory, mask_file=None, erode=3, clean=False,
           mode='single', apply_noise=None, no_scale=False, intensity=0.01,
           location=[], force=False, verbose=False, **kwargs):
    scale = not no_scale
    if apply_noise:
        output_file = op.splitext(apply_noise)[0]
        # Handle special case: apply_noise and clean means delete noisy image.
        if clean:
            # TODO: generalize to other output image formats
            if op.isfile(output_file + ".nii.gz"):
                os.remove(output_file + ".nii.gz")
            return 0
    else:
        # Create output filename for noise data
        bname = op.basename(image_file).split(".")[0]
        modifier = "_1vox-" + str(uuid.uuid1())[0:8]
        output_file = op.join(output_directory, bname + modifier)

    # Load nifti images and extract their data
    image_loaded = nib.load(image_file)
    image_data = image_loaded.get_data()

    # If a noise file is provided, use it to grab noise features
    if apply_noise:
        with open(apply_noise) as fhandle:
            noise_data = json.loads(fhandle.read())

        scale = noise_data['scale']
        intensity = noise_data['intensity']
        loc = [tuple(vl) for vl in noise_data["voxel_location"]]
        mm_loc = noise_data["mm_location"]
        original_hash = noise_data['matrix_hash']

    # If not, generate noise based on parameters from the command-line
    else:
        original_hash = None

        if not mask_file:
            raise ValueError("Must provide a mask for generating noise.")
        mask_loaded = nib.load(mask_file)
        mask_data = mask_loaded.get_data()

        # Generate noise based on input params
        loc = generate_noise_params(image_data, mask=mask_data, erode=erode,
                                    location=location, force=force, mode=mode)

    # Apply noise to image
    output_data, output_hash = apply_noise_params(image_data, loc, scale=scale,
                                                  intensity=intensity)

    # Verify that the hashes match for our noisy images.
    if original_hash and output_hash != original_hash:
        print("WARNING: Noisy image hash is different from expected hash.")

    # Only create noise JSON if there wasn't one provided
    if not apply_noise:
        # Get noise locations in mm (useful for visualizing)
        mm_loc = []
        for l in loc:
            tmp_mm = nilimage.coord_transform(l[0], l[1], l[2],
                                              image_loaded.affine)
            mm_loc += [tuple(float(tmm) for tmm in tmp_mm)]

        # Save noise information to a JSON file
        with open(output_file + ".json", 'w') as fhandle:
            noisedict = {"voxel_location": loc,
                         "mm_location": mm_loc,
                         "base_image": image_file,
                         "matrix_hash": output_hash,
                         "scale": scale,
                         "intensity": intensity}
            fhandle.write(json.dumps(noisedict, indent=4, sort_keys=True))

    if verbose:
        print("Noise added in matrix coordinates at: {0}".format(loc))
        print("Noise added in mm coordinates at: {0}".format(mm_loc))
        print("Image stored in: {0}".format(output_file))

    # If we're being clean, return without saving an image.
    if not clean:
        image_writer(output_file + ".nii.gz", image_loaded, output_data)
Пример #21
0
# VISUALIZATION
# T1 weighted image for background
anatDir = os.path.join(dataDir,'derivatives_selected/fmriprep/sub-09/anat/')
imageT1 = os.path.join(anatDir,
                       'sub-09_space-MNI152NLin2009cAsym_desc-preproc_T1w.nii.gz')

# Thresholded zstat image
fThZStat=os.path.join(statsDir,'threshold_file/zstat' + contInd + '_threshold.nii.gz')
thImageStat=nib.load(fThZStat)

# global maximum cooridnates
X_zstat = nib.load(imgZStat).get_data()  # loading the zstat image
globalMax = np.unravel_index(np.argmax(X_zstat), X_zstat.shape) # voxel space
globalMaxMNI = coord_transform(globalMax[0],
                               globalMax[1],
                               globalMax[2],
                               thImageStat.affine)  # MNI space

# blob overlay at global max
plot_stat_map(thImageStat, bg_img=imageT1,
              colorbar=True, threshold=2.3, black_bg=True,
              draw_cross=True,
              cut_coords=globalMaxMNI)

# interactive visualization
view_img(thImageStat, bg_img=imageT1, cmap='black_red',
         symmetric_cmap=False, annotate=True,
         colorbar=True, threshold=2.3, black_bg=True,
         cut_coords=globalMaxMNI)
Пример #22
0
def extract_roi_info(statfile,
                     stat_name=None,
                     roi_type='unilateral',
                     per_cluster=True,
                     cluster_engine='scipy',
                     min_clust_size=20,
                     stat_threshold=None,
                     mask_threshold=20,
                     save_indices=True,
                     verbose=True):
    """
    Extracts information per ROI for a given statistics-file.
    Reads in a thresholded (!) statistics-file (such as a thresholded z- or
    t-stat from a FSL first-level directory) and calculates for a set of ROIs
    the number of significant voxels included and its maximum value
    (+ coordinates). Saves a csv-file in the same directory as the
    statistics-file. Assumes that the statistics file is in MNI152 2mm space.

    Parameters
    ----------
    statfile : str
        Absolute path to statistics-file (nifti) that needs to be evaluated.
    stat_name : str
        Name for the contrast/stat-file that is being analyzed.
    roi_type : str
        Whether to  use unilateral or bilateral masks (thus far, only Harvard-
        Oxford atlas masks are supported.)
    per_cluster : bool
        Whether to evaluate the statistics-file as a whole (per_cluster=False)
        or per cluster separately (per_cluster=True).
    cluster_engine : str
        Which 'engine' to use for clustering; can be 'scipy' (default), using
        scipy.ndimage.measurements.label, or 'fsl' (using FSL's cluster
        commmand).
    min_clust_size : int
        Minimum cluster size (i.e. clusters with fewer voxels than this number
        are discarded; also, ROIs containing fewer voxels than this will not
        be listed on the CSV.
    stat_threshold : int or float
        If the stat-file contains uncorrected data, stat_threshold can be used
        to set a lower bound.
    mask_threshold : bool
        Threshold for probabilistics masks, such as the Harvard-Oxford masks.
        Default of 25 is chosen as this minimizes overlap between adjacent
        masks while still covering most of the entire brain.
    save_indices : bool
        Whether to save the indices (coordinates) of peaks of clusters.
    verbose : bool
        Whether to print some output regarding the parsing process.

    Returns
    -------
    df : Dataframe
        Dataframe corresponding to the written csv-file.
    """

    if isinstance(statfile, str):
        data = nib.load(statfile).get_data()
    else:
        data = statfile

    sign_mask = np.ones(shape=data.shape)
    sign_mask[data < 0] = -1

    mni_affine = load_mni152_template().affine

    if stat_threshold:
        data[data < stat_threshold] = 0

    if roi_type == 'unilateral':
        cort_rois = fetch_atlas_harvard_oxford('cort-maxprob-thr0-2mm',
                                               symmetric_split=True)
        subc_rois = fetch_atlas_harvard_oxford('sub-maxprob-thr0-2mm',
                                               symmetric_split=True)
    else:
        cort_rois = fetch_atlas_harvard_oxford('cort-maxprob-thr0-2mm',
                                               symmetric_split=True)
        subc_rois = fetch_atlas_harvard_oxford('sub-maxprob-thr0-2mm',
                                               symmetric_split=True)

    cort_rois['idx'] = np.arange(len(cort_rois['labels']))
    subc_rois['idx'] = np.arange(len(subc_rois['labels']))

    df_list = []

    # Start clustering of data
    clustered, _ = label(data > 0)
    values, counts = np.unique(clustered.ravel(), return_counts=True)
    n_clust = np.argmax(np.sort(counts)[::-1] < min_clust_size)

    if n_clust == 0:
        print('No (sufficiently large) clusters!')
        return 0

    # Sort and trim
    cluster_nrs = values[counts.argsort()[::-1][:n_clust]]
    cluster_nrs = np.delete(cluster_nrs, 0)

    print('Analyzing %i clusters for %s' % (len(cluster_nrs), stat_name))

    cluster_list = []
    # Looping over clusters
    for i, cluster_id in enumerate(cluster_nrs):

        if verbose:
            print('Processing cluster %i' % (i + 1))

        cl_mask = clustered == cluster_id
        k = cl_mask.sum()
        mx = data[cl_mask].max()

        tmp = np.zeros(data.shape)
        tmp[cl_mask] = data[cl_mask] == mx

        # in case of multiple voxels with same stat / weight
        if np.sum(tmp == 1) > 1:
            X, Y, Z = [coord[0] for coord in np.where(tmp == 1)]
        else:
            X, Y, Z = np.where(tmp == 1)

        # if weight / stat is negative, change sign of mx
        if sign_mask[X, Y, Z] < 0:
            mx = -mx

        # convert to MNI-coordinates
        X, Y, Z = coord_transform(X, Y, Z, mni_affine)

        # This is purely for formatting issues
        if i == 0:
            c = stat_name
        else:
            c = ''

        to_append = {
            'Contrast': c,
            'cluster': (i + 1),
            'k cluster': str(k),
            'max cluster': mx,
            'x': str(X[0]),
            'y': str(Y[0]),
            'z': str(Z[0]),
            'Region': '',
            'k region': '',
            'max region': ''
        }

        cluster_list.append(to_append)

        roi_list = []
        # Loop over ROIs
        for i_atlas, atlas in enumerate([cort_rois, subc_rois]):
            maps = atlas['maps'].get_data()

            for ii_roi, mask_name in enumerate(atlas['labels']):
                roi_mask = maps == atlas['idx'][ii_roi]
                overlap = (cl_mask.astype(int) + roi_mask.astype(int)) == 2
                k = overlap.sum()

                if k > 0:
                    mx = data[overlap].max()
                    tmp = np.zeros(data.shape)
                    tmp[overlap] = data[overlap] == mx

                    # in case of multiple voxels with same stat / weight
                    if np.sum(tmp == 1) > 1:
                        X, Y, Z = [coord[0] for coord in np.where(tmp == 1)]
                    else:
                        X, Y, Z = np.where(tmp == 1)

                    # if sign of weight / stat is negative, change sign of mx
                    if sign_mask[X, Y, Z] < 0:
                        mx = -mx

                    # convert to MNI-coordinates
                    X, Y, Z = coord_transform(X, Y, Z, mni_affine)

                else:
                    # If no voxels, write some default values
                    mx = 0
                    X, Y, Z = 0, 0, 0

                if ii_roi == 0:
                    cluster_list[-1]['Region'] = mask_name
                    cluster_list[-1]['k region'] = k
                    cluster_list[-1]['max region'] = mx
                else:

                    to_append = {
                        'Contrast': '',
                        'cluster': (i + 1 + 0.1),
                        'k cluster': '',
                        'max cluster': '',
                        'x': '',
                        'y': '',
                        'z': '',
                        'Region': mask_name,
                        'k region': k,
                        'max region': mx
                    }

                    if k > cluster_list[-1]['k region']:
                        to_append['Region'] = cluster_list[-1]['Region']
                        to_append['k region'] = cluster_list[-1]['k region']
                        maxr = cluster_list[-1]['max region']
                        to_append['max region'] = maxr
                        cluster_list[-1]['Region'] = mask_name
                        cluster_list[-1]['k region'] = k
                        cluster_list[-1]['max region'] = mx

                    roi_list.append(to_append)

            roi_dfs = pd.concat([pd.DataFrame(tmp, [0]) for tmp in roi_list])
            roi_dfs = roi_dfs[roi_dfs['k region'] > min_clust_size]
            roi_dfs = roi_dfs.sort_values(by=['cluster', 'k region'],
                                          ascending=[True, False])

            whiteline = {
                key: '' if key != 'cluster' else (i + 1 + 0.1)
                for key in roi_dfs.keys()
            }

            roi_dfs = roi_dfs.append(whiteline, ignore_index=True)
            df_list.append(pd.DataFrame(cluster_list[-1], [0]))
            df_list.append(roi_dfs)

        # Concatenate dataframes!
        df = pd.concat(df_list)
        # Some cleaning / processing
        cols_ordered = [
            'Contrast', 'cluster', 'k cluster', 'max cluster', 'x', 'y', 'z',
            'Region', 'k region', 'max region'
        ]
        df = df[cols_ordered]

        df['cluster'] = [
            '' if (val % 1) != 0 else str(val) for val in df['cluster']
        ]

    filename = op.join(op.dirname(statfile), 'roi_info_%s.csv' % stat_name)
    df.to_csv(filename, index=False, header=True, sep='\t')

    return df
Пример #23
0
 def cast(x, y, z, affine, trA):
     coord = coord_transform(x, y, z, affine)
     return np.dot(trA, [coord[0], coord[1], coord[2], 1])
Пример #24
0
        _, fname, _ = split_filename(self.inputs.image_file)
        gii_file = op.abspath(op.join(runtime.cwd, fname + ".gii"))

        # Load the largest connected component of the input image
        img = nimg.largest_connected_component_img(self.inputs.image_file)

        # TODO: check if the input image is correct (binary)

        # Run the marching cube algorithm
        verts, faces, normals, values = sm.marching_cubes_lewiner(
            img.get_data(), self.inputs.level)
>>>>>>> 02924efd7fd9ff93e10f0e0030a43b878812e288

        # Convert vertices coordinates to image space
        # TODO: check that is correct by plotting the mesh on the image
        x, y, z = nimg.coord_transform(
            verts[:, 0], verts[:, 1], verts[:, 2], img.affine)
        mm_verts = np.array([x, y, z]).T

        # Save the mesh as Gifti
        # FIXME: FreeView can not open the mesh (but anatomist do)
        gii = ng.GiftiImage(darrays=[
            ng.GiftiDataArray(mm_verts, intent='NIFTI_INTENT_POINTSET'),
            ng.GiftiDataArray(faces, intent='NIFTI_INTENT_TRIANGLE')])
        gii.meta = ng.GiftiMetaData().from_dict({
<<<<<<< HEAD
            "volume_file": self.input_spec.image_file,
            "marching_cube_level": self.input_spec.level,
            "smoothing_iterations": self.input_spec.smoothing_iter,
            "smoothing_dt": self.input_spec.smoothing_dt
=======
            "volume_file": self.inputs.image_file,
Пример #25
0
def index_to_xy_coord(x, y, z=10):
    '''Transforms data index to coordinates of the background + offset'''
    coords = coord_transform(x, y, z,
                             affine=thresholded_score_map_img.affine)
    return np.array(coords)[np.newaxis, :] + np.array([0, 1, 0])
Пример #26
0
def create_screenshot(
    slice,
    t1_img,
    seg_img,
    affine,
    view,
    cmap,
    output_dir,
    w=256,
    h=256,
    dpi=1024,
    alpha=0.15,
    dim=-1,
    quality=95,
    optimize=True,
):
    with Xvfb() as xvfb:
        # TODO: Moved this config here for now, maybe move out of the function later?
        view_info = {
            "coronal": ("y", False, True),
            "axial": ("z", False, True),
            "sagittal": ("x", False, True),
        }
        mode, reverse, flip = view_info[view]

        output_dir = Path(f"{output_dir}/{view}")
        output_dir.mkdir(parents=True, exist_ok=True)

        image_buffer = BytesIO()
        fig = plt.figure(figsize=(w, h), dpi=dpi)
        # TODO- cleanup, may be a better way but not bothering for now...
        # coords are (y, z, x)
        if view == "sagittal":
            val = image.coord_transform(128, 128, slice, affine)[0]
        elif view == "coronal":
            val = image.coord_transform(slice, 128, 128, affine)[1]
        elif view == "axial":
            val = image.coord_transform(128, slice, 128, affine)[2]
        else:
            raise ValueError(f"view {view} not supported")
        if reverse:
            flip_list = range(256, 0, -1)
            output_file = str(output_dir / f"{view}_{flip_list[slice]:03d}.jpg"
                              )  # reverse ordering of numberings
        else:
            output_file = str(output_dir / f"{view}_{slice+1:03d}.jpg")

        nilearn.plotting.plot_anat(
            seg_img,
            bg_img=t1_img,
            display_mode=mode,
            cut_coords=[(val)],
            annotate=False,
            black_bg=True,
            figure=fig,
            output_file=image_buffer,
            cmap=cmap,
            vmin=100,
            vmax=115,
            alpha=alpha,
            dim=dim,
        )

        image_buffer.seek(0)
        img = Image.open(image_buffer)
        if flip:
            out = img.transpose(Image.FLIP_LEFT_RIGHT).convert("RGB")
        else:
            out = img.convert("RGB")
        out.save(output_file, quality=quality, optimize=optimize)
        image_buffer.close()
        plt.close("all")
Пример #27
0
import matplotlib.pyplot as plt
from nilearn.plotting import plot_stat_map, view_img
from nilearn.image import math_img, coord_transform

# Directory and file business
dataDir = '/tmp/Data/ds114'  # Data directory
anatDir = os.path.join(dataDir,'derivatives_selected/fmriprep/sub-09/anat/')
imageT1 = os.path.join(anatDir,
                       'sub-09_space-MNI152NLin2009cAsym_desc-preproc_T1w.nii.gz')
featDir = os.path.join(dataDir,
                       'WorkflowOutput/feat_dir/run0.feat/')
statDir = os.path.join(featDir,'stats')
imageStat = os.path.join(statDir, 'zstat6.nii.gz')

# thresholding the stat image to positive values only for visualization
thImageStat = math_img("np.ma.masked_less(img, 0)",
                                     img=imageStat)

# stat map at the maximum
plot_stat_map(thImageStat, bg_img=imageT1,
              colorbar=True, threshold=2.3, black_bg=True,
              draw_cross=True,
              cut_coords=coord_transform(23,27,36,thImageStat.affine))


# interactive visualization
view_img(thImageStat, bg_img=imageT1, cmap='black_red',
         symmetric_cmap=False, annotate=True,
         colorbar=True, threshold=2.3, black_bg=True,
         cut_coords=coord_transform(23,27,36,thImageStat.affine))
Пример #28
0
def vol_ba():
    cor_vols = list(
        filter(None, os.popen('find processed_data -name bold_mcf_brainCorNorm_*.nii.gz').read().split('\n')))
    # MNI to TAL Transform
    affine = np.zeros((4, 4))
    affine[0] = [0.88, 0, 0, -0.8]
    affine[1] = [0, 0.97, 0, -3.32]
    affine[2] = [0, 0.05, 0.88, -0.44]
    affine[3] = [0, 0, 0, 1]

    with open('/gpfs/hpchome/gagand87/project/tal_to_BA.pkl', 'rb') as handle:
        tal_to_ba = pickle.load(handle)

    for ind, vol in enumerate(cor_vols):
        ba_intensity = {'Amygdala': [],
                        'Anterior Commissure': [],
                        'Anterior Nucleus': [],
                        'Background': [],
                        'Brodmann area 1': [],
                        'Brodmann area 10': [],
                        'Brodmann area 11': [],
                        'Brodmann area 13': [],
                        'Brodmann area 17': [],
                        'Brodmann area 18': [],
                        'Brodmann area 19': [],
                        'Brodmann area 2': [],
                        'Brodmann area 20': [],
                        'Brodmann area 21': [],
                        'Brodmann area 22': [],
                        'Brodmann area 23': [],
                        'Brodmann area 24': [],
                        'Brodmann area 25': [],
                        'Brodmann area 27': [],
                        'Brodmann area 28': [],
                        'Brodmann area 29': [],
                        'Brodmann area 3': [],
                        'Brodmann area 30': [],
                        'Brodmann area 31': [],
                        'Brodmann area 32': [],
                        'Brodmann area 33': [],
                        'Brodmann area 34': [],
                        'Brodmann area 35': [],
                        'Brodmann area 36': [],
                        'Brodmann area 37': [],
                        'Brodmann area 38': [],
                        'Brodmann area 39': [],
                        'Brodmann area 4': [],
                        'Brodmann area 40': [],
                        'Brodmann area 41': [],
                        'Brodmann area 42': [],
                        'Brodmann area 43': [],
                        'Brodmann area 44': [],
                        'Brodmann area 45': [],
                        'Brodmann area 46': [],
                        'Brodmann area 47': [],
                        'Brodmann area 5': [],
                        'Brodmann area 6': [],
                        'Brodmann area 7': [],
                        'Brodmann area 8': [],
                        'Brodmann area 9': [],
                        'Caudate Body': [],
                        'Caudate Head': [],
                        'Caudate Tail': [],
                        'Corpus Callosum': [],
                        'Dentate': [],
                        'Hippocampus': [],
                        'Hypothalamus': [],
                        'Lateral Dorsal Nucleus': [],
                        'Lateral Geniculum Body': [],
                        'Lateral Globus Pallidus': [],
                        'Lateral Posterior Nucleus': [],
                        'Mammillary Body': [],
                        'Medial Dorsal Nucleus': [],
                        'Medial Geniculum Body': [],
                        'Medial Globus Pallidus': [],
                        'Midline Nucleus': [],
                        'Optic Tract': [],
                        'Pulvinar': [],
                        'Putamen': [],
                        'Red Nucleus': [],
                        'Substania Nigra': [],
                        'Subthalamic Nucleus': [],
                        'Ventral Anterior Nucleus': [],
                        'Ventral Lateral Nucleus': [],
                        'Ventral Posterior Lateral Nucleus': [],
                        'Ventral Posterior Medial Nucleus': []}
        vol_name_parts = vol.split('/')
        BA_intensity_file_name = vol_name_parts[0] + '/' + vol_name_parts[1] + '/' + vol_name_parts[
            2] + '/' + 'BA_Intensity/bold_mcf_brain_BA_Intensity' + str(ind) + '.pkl'
        fmri = image.load_img(vol)
        fmri_data = fmri.get_data()
        for i in range(fmri.shape[0]):
            for j in range(fmri.shape[1]):
                for k in range(fmri.shape[2]):
                    mni_coord = coord_transform(i, j, k, fmri.affine)
                    tal_coord = coord_transform(mni_coord[0], mni_coord[1], mni_coord[2], affine)
                    # Since tal coordinates range is (-70.0, -102.0, -42.0) to (70.0, 69.0, 67.0), we ignore the rest of the coordinates
                    if -70 <= tal_coord[0] <= 70 and -102 <= tal_coord[1] <= 69 and -42 <= tal_coord[2] <= 67:
                        t_coord = [0] * 3
                        t_coord[0] = round(tal_coord[0])
                        t_coord[1] = round(tal_coord[1])
                        t_coord[2] = round(tal_coord[2])
                        ba_intensity[tal_to_ba[(t_coord[0], t_coord[1], t_coord[2])]].append(fmri_data[i, j, k])

        with bz2.BZ2File(BA_intensity_file_name, 'wb') as handle:
            pickle.dump(ba_intensity, handle)