Exemple #1
0
def build_coord_list(coords, dwi_dir):
    from nilearn import masking
    try:
        import cPickle as pickle
    except ImportError:
        import _pickle as pickle

    nodif_brain_mask_path = "%s%s" % (dwi_dir, '/nodif_brain_mask.nii.gz')

    x_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0]
    y_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1]
    z_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2]

    def mmToVox(mmcoords):
        voxcoords = ['', '', '']
        voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45)
        voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63)
        voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36)
        return voxcoords

    # Convert coords back to voxels
    coords_vox = []
    for coord in coords:
        coords_vox.append(mmToVox(coord))
    coords = list(tuple(x) for x in coords_vox)
    coord_num = len(coords)

    return coords, coord_num
Exemple #2
0
def coord_masker(mask, coords, label_names, error):
    from nilearn import masking
    x_vox = np.diagonal(masking._load_mask_img(mask)[1][:3, 0:3])[0]
    y_vox = np.diagonal(masking._load_mask_img(mask)[1][:3, 0:3])[1]
    z_vox = np.diagonal(masking._load_mask_img(mask)[1][:3, 0:3])[2]

    def mmToVox(mmcoords):
        voxcoords = ['', '', '']
        voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45)
        voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63)
        voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36)

        return voxcoords

    mask_data, _ = masking._load_mask_img(mask)
    #    mask_coords = list(zip(*np.where(mask_data == True)))
    coords_vox = []
    for i in coords:
        coords_vox.append(mmToVox(i))
    coords_vox = list(tuple(x) for x in coords_vox)

    bad_coords = []
    for coord in coords_vox:
        sphere_vol = np.zeros(mask_data.shape, dtype=bool)
        sphere_vol[tuple(coord)] = 1
        if (mask_data & sphere_vol).any():
            print("%s%s" % (coord, ' falls within mask...'))
            continue
        inds = get_sphere(coord, error, (np.abs(x_vox), y_vox, z_vox),
                          mask_data.shape)
        sphere_vol[tuple(inds.T)] = 1
        if (mask_data & sphere_vol).any():
            print("%s%s%.2f%s" % (coord, ' is within a + or - ', float(error),
                                  ' mm neighborhood...'))
            continue
        bad_coords.append(coord)

    bad_coords = [x for x in bad_coords if x is not None]
    indices = []
    for bad_coord in bad_coords:
        indices.append(coords_vox.index(bad_coord))

    label_names = list(label_names)
    coords = list(tuple(x) for x in coords)
    for ix in sorted(indices, reverse=True):
        print("%s%s%s%s" % ('Removing: ', label_names[ix], ' at ', coords[ix]))
        label_names.pop(ix)
        coords.pop(ix)
    return coords, label_names
Exemple #3
0
    def inverse_transform(self, X, y=None, **kwargs):
        """
        Reconstruct image from transformed data.
        :param X: data
        :param y: targets
        :param kwargs:
        :return:
        """
        X = np.asarray(X)

        # get ROI masks
        atlas_obj = AtlasLibrary().get_atlas(self.atlas_name, self.affine, self.shape, self.mask_threshold)
        roi_objects = self._get_rois(atlas_obj, which_rois=self.rois, background_id=self.background_id)

        unmasked = np.squeeze(np.zeros_like(atlas_obj.map, dtype='float32'))

        for i, roi in enumerate(roi_objects):
            mask, mask_affine = masking._load_mask_img(roi.mask)
            mask_img = image.new_img_like(roi.mask, mask, mask_affine)
            mask_data = _utils.as_ndarray(mask_img.get_fdata(), dtype=np.bool)

            if self.collection_mode == 'list':
                unmasked[mask_data] = X[i]
            else:
                unmasked[mask_data] = X[self.mask_indices == i]

        new_image = image.new_img_like(atlas_obj.atlas, unmasked)
        return new_image
Exemple #4
0
    def make_searchlight_masks(self):
        # Compute world coordinates of all in-mask voxels.
        # Return indices as sparse matrix of 0's and 1's
        print("start get coords")
        world_process_mask = self.data.nifti_masker.fit_transform(self.process_mask)
        world_brain_mask = self.data.nifti_masker.fit_transform(self.data.mask)

        process_mask_1D = world_brain_mask.copy()
        process_mask_1D[:,:] = 0
        no_overlap = np.where( world_process_mask * world_brain_mask > 0 ) #get the indices where at least one entry is 0
        process_mask_1D[no_overlap] = 1 #delete entries for which there is no overlap

        mask, mask_affine = masking._load_mask_img(self.data.mask)
        mask_coords = np.where(mask != 0)
        mc1 = np.reshape(mask_coords[0], (1, -1))
        mc2 = np.reshape(mask_coords[1], (1, -1))
        mc3 = np.reshape(mask_coords[2], (1, -1))
        mask_coords = np.concatenate((mc1.T,mc2.T, mc3.T), axis = 1)

        selected_3D = self.data.nifti_masker.inverse_transform( process_mask_1D )
        process_mask_coords = np.where(selected_3D.get_data()[:,:,:,0] != 0)
        pmc1 = np.reshape(process_mask_coords[0], (1, -1))
        pmc2 = np.reshape(process_mask_coords[1], (1, -1))
        pmc3 = np.reshape(process_mask_coords[2], (1, -1))
        process_mask_coords = np.concatenate((pmc1.T,pmc2.T, pmc3.T), axis = 1)

        clf = neighbors.NearestNeighbors(radius = 3)
        A = clf.fit(mask_coords).radius_neighbors_graph(process_mask_coords)
        del mask_coords, process_mask_coords, selected_3D, no_overlap

        print("Built searchlight masks.")
        print("Each searchlight has on the order of " + str( sum(sum(A[0].toarray())) ) + " voxels")
        self.A = A.tolil()
        self.process_mask_1D = process_mask_1D
Exemple #5
0
def coord_masker(mask, coords, label_names):
    x_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[0]
    y_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[1]
    z_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[2]
    def mmToVox(mmcoords):
        voxcoords = ['','','']
        voxcoords[0] = int((round(int(mmcoords[0])/x_vox))+45)
        voxcoords[1] = int((round(int(mmcoords[1])/y_vox))+63)
        voxcoords[2] = int((round(int(mmcoords[2])/z_vox))+36)
        return voxcoords

    mask_data, _ = masking._load_mask_img(mask)
    mask_coords = list(zip(*np.where(mask_data == True)))
    coords_vox = []
    for i in coords:
        coords_vox.append(mmToVox(i))
    coords_vox = list(tuple(x) for x in coords_vox)

    bad_coords = []
    error=8
    for coord in coords_vox:
        sphere_vol = np.zeros(mask_data.shape, dtype=bool)
        sphere_vol[tuple(coord)] = 1
        if (mask_data & sphere_vol).any():
            print(str(coord) + ' falls within mask...')
            continue
        inds = get_sphere(coord, error, (np.abs(x_vox), y_vox, z_vox), mask_data.shape)
        sphere_vol[tuple(inds.T)] = 1
        if (mask_data & sphere_vol).any():
            print(str(coord) + ' is within a + or - ' + str(error) + ' voxel neighborhood...')
            continue
        bad_coords.append(coord)

    bad_coords = [x for x in bad_coords if x is not None]
    indices=[]
    for bad_coord in bad_coords:
        indices.append(coords_vox.index(bad_coord))

    for ix in sorted(indices, reverse=True):
        print('Removing: ' + str(label_names[ix]) + ' at ' + str(coords[ix]))
        del label_names[ix]
        del coords[ix]
    return(coords, label_names)
Exemple #6
0
def apply_mask_and_get_affinity(seeds,
                                niimg,
                                radius,
                                allow_overlap,
                                n_jobs=1,
                                mask_img=None):
    import time
    start = time.time()

    seeds = list(seeds)
    affine = niimg.affine

    # Compute world coordinates of all in-mask voxels.
    mask_img = check_niimg_3d(mask_img)
    mask_img = image.resample_img(mask_img,
                                  target_affine=affine,
                                  target_shape=niimg.shape[:3],
                                  interpolation='nearest')
    mask, _ = masking._load_mask_img(mask_img)
    mask_coords = list(zip(*np.where(mask != 0)))

    X = masking._apply_mask_fmri(niimg, mask_img)

    # For each seed, get coordinates of nearest voxel
    nearests = joblib.Parallel(n_jobs=n_jobs)(
        joblib.delayed(seed_nearest)(seed_chunk, affine, mask_coords)
        for thread_id, seed_chunk in enumerate(np.array_split(seeds, n_jobs)))
    nearests = [i for j in nearests for i in j]

    mask_coords = np.asarray(list(zip(*mask_coords)))
    mask_coords = coord_transform(mask_coords[0], mask_coords[1],
                                  mask_coords[2], affine)
    mask_coords = np.asarray(mask_coords).T

    clf = neighbors.NearestNeighbors(radius=radius)
    A = clf.fit(mask_coords).radius_neighbors_graph(seeds)
    A = A.tolil()
    for i, nearest in enumerate(nearests):
        if nearest is None:
            continue
        A[i, nearest] = True
    # Include the voxel containing the seed itself if not masked
    mask_coords = mask_coords.astype(int).tolist()
    for i, seed in enumerate(seeds):
        try:
            A[i, mask_coords.index(seed)] = True
        except ValueError:
            # seed is not in the mask
            pass

    if not allow_overlap:
        if np.any(A.sum(axis=0) >= 2):
            raise ValueError('Overlap detected between spheres')

    return X, A
Exemple #7
0
def coord_masker(mask, coords, label_names):
    x_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[0]
    y_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[1]
    z_vox = np.diagonal(masking._load_mask_img(mask)[1][:3,0:3])[2]
    def mmToVox(mmcoords):
        voxcoords = ['','','']
        voxcoords[0] = int((round(int(mmcoords[0])/x_vox))+45)
        voxcoords[1] = int((round(int(mmcoords[1])/y_vox))+63)
        voxcoords[2] = int((round(int(mmcoords[2])/z_vox))+36)
        return voxcoords

    mask_data, _ = masking._load_mask_img(mask)
    mask_coords = list(zip(*np.where(mask_data == True)))
    coords_vox = []
    for i in coords:
        coords_vox.append(mmToVox(i))
    coords_vox = list(tuple(x) for x in coords_vox)

    bad_coords = []
    for coord in coords_vox:
        bad_coord = check_neighborhood(coord, mask_coords)
        bad_coords.append(bad_coord)
    bad_coords = [x for x in bad_coords if x is not None]

    #if __name__ == '__main__':
        #number_processes = (multiprocessing.cpu_count())
        #pool = multiprocessing.Pool(int(number_processes))
        #coord = coords_vox
        #result = pool.map_async(check_neighborhood, coord)
        #pool.close()
        #pool.join()
    #bad_coords = [x for x in result.get() if x is not None]

    indices=[]
    for bad_coord in bad_coords:
        indices.append(coords_vox.index(bad_coord))

    for ix in sorted(indices, reverse=True):
        print('Removing: ' + str(label_names[ix]) + ' at ' + str(coords[ix]))
        del label_names[ix]
        del coords[ix]
    return(coords, label_names)
Exemple #8
0
 def apply_mask(self, series, mask_img):
     """
     Apply mask on series.
     :param series: np.ndarray, data working on
     :param mask_img:
     :return:
     """
     mask_img = _utils.check_niimg_3d(mask_img)
     mask, mask_affine = masking._load_mask_img(mask_img)
     mask_img = image.new_img_like(mask_img, mask, mask_affine)
     mask_data = _utils.as_ndarray(mask_img.get_fdata(),
                                   dtype=np.bool)
     return series[mask_data].T
Exemple #9
0
def parcel_masker(mask, coords, parcel_list, label_names, dir_path, ID):
    from pynets import nodemaker
    from nilearn.image import resample_img
    from nilearn import masking
    ##For parcel masking, specify overlap thresh and error cushion in mm voxels
    perc_overlap = 0.75 ##Default is >=90% overlap

    mask_img = nib.load(mask)
    mask_data, _ = masking._load_mask_img(mask)

    i = 0
    indices = []
    for parcel in parcel_list:
        parcel_vol = np.zeros(mask_data.shape, dtype=bool)
        parcel_data_reshaped = resample_img(parcel, target_affine=mask_img.affine,
                               target_shape=mask_data.shape).get_data()
        parcel_vol[parcel_data_reshaped==1] = 1
        
        ##Count number of unique voxels where overlap of parcel and mask occurs
        overlap_count = len(np.unique(np.where((mask_data.astype('uint8')==1) & (parcel_vol.astype('uint8')==1))))
        
        ##Count number of total unique voxels within the parcel
        total_count = len(np.unique(np.where(((parcel_vol.astype('uint8')==1)))))
        
        ##Calculate % overlap
        try:
            overlap = float(overlap_count/total_count)
        except:
            overlap = float(0)
        
        if overlap >= perc_overlap:
            print(str(round(100*overlap,1)) + '% of parcel ' + str(label_names[i]) + ' falls within mask...')
        else:
            indices.append(i)
        i = i + 1

    label_names_adj=list(label_names)
    coords_adj = list(tuple(x) for x in coords)
    parcel_list_adj = parcel_list
    for ix in sorted(indices, reverse=True):
        print('Removing: ' + str(label_names_adj[ix]) + ' at ' + str(coords_adj[ix]))
        label_names_adj.pop(ix)
        coords_adj.pop(ix)
        parcel_list_adj.pop(ix)
        
    ##Create a resampled 3D atlas that can be viewed alongside mask img for QA
    resampled_parcels_nii_path = dir_path + '/' + ID + '_parcels_resampled2mask_' + str(os.path.basename(mask).split('.')[0]) + '.nii.gz'
    resampled_parcels_atlas, _ = nodemaker.create_parcel_atlas(parcel_list_adj)
    resampled_parcels_map_nifti = resample_img(resampled_parcels_atlas, target_affine=mask_img.affine, target_shape=mask_data.shape)
    nib.save(resampled_parcels_map_nifti, resampled_parcels_nii_path)
    return(coords_adj, label_names_adj, parcel_list_adj)
Exemple #10
0
    def fit(self, imgs, y, y_mask=None, groups=None, X=None, A=None):

        # check if image is 4D
        imgs = check_niimg_4d(imgs)

        # Get the seeds
        process_mask_img = self.process_mask_img
        if self.process_mask_img is None:
            process_mask_img = self.mask_img

        # Compute world coordinates of the seeds
        process_mask, process_mask_affine = masking._load_mask_img(
            process_mask_img)
        process_mask_coords = np.where(process_mask != 0)
        process_mask_coords = coord_transform(process_mask_coords[0],
                                              process_mask_coords[1],
                                              process_mask_coords[2],
                                              process_mask_affine)
        process_mask_coords = np.asarray(process_mask_coords).T

        import time

        start = time.time()
        print("GETTING SEARCHLIGHT SPHERES")

        X, A = apply_mask_and_get_affinity(process_mask_coords,
                                           imgs,
                                           self.radius,
                                           True,
                                           mask_img=self.mask_img,
                                           n_jobs=self.n_jobs)

        self.X = X
        self.A = A
        self.y = y
        self.process_mask = process_mask

        elapsed = time.time() - start
        print(elapsed)

        print("FITTING")
        scores = search_light_rsa(X, y, None, A, y_mask, self.n_jobs,
                                  self.verbose)

        scores_3D = np.zeros((process_mask.shape) + (len(y), ))
        for i in range(len(y)):
            scores_3D[process_mask, i] = scores[:, i]
        self.scores_ = scores_3D
        return self
    def fit(self, imgs, y, groups=None):
        """Fit the spatiotemporal searchlight

        Parameters
        ----------
        imgs : Niimg-like object
            See http://nilearn.github.io/manipulating_images/input_output.html
            Use 5D image. [x voxels, y voxels, z voxels, trials, time series of each trials]

        y : 1D array-like
            Target variable to predict. Must have exactly as many elements as trials in imgs.

        groups : array-like, optional
            group label for each sample for cross validation. Must have
            exactly as many elements as trials in imgs. default None
            NOTE: will have no effect for scikit learn < 0.18 (as nilearn says)
        """

        # check if image is 5D, simply.
        if len(imgs.shape) != 5:
            raise ValueError('This SpatioTemporalSearhcLight instance needs 5D image.')

        # Get the seeds
        process_mask_img = self.mask_img

        # Compute world coordinates of the seeds
        process_mask, process_mask_affine = masking._load_mask_img(process_mask_img)
        process_mask_coords = np.where(process_mask != 0)
        process_mask_coords = coord_transform(
            process_mask_coords[0], process_mask_coords[1],
            process_mask_coords[2], process_mask_affine)
        process_mask_coords = np.asarray(process_mask_coords).T

        X, A = _apply_mask_and_get_affinity(
            process_mask_coords, imgs, self.radius, True,
            mask_img=self.mask_img)

        # Run Searchlight
        scores = self._search_light(X, y, A, groups=groups)
        scores_3D = np.zeros(process_mask.shape)
        scores_3D[process_mask] = scores

        self.scores_ = scores_3D

        return self
Exemple #12
0
    def make_searchlight_masks(self):
        ''' Compute world coordinates of all in-mask voxels.
            Returns a list of masks, one mask for each searchlight. For a whole brain,
            this will generate thousands of masks. Returns masks in lil format
            (efficient for storing sparse matrices)'''
        # Compute world coordinates of all in-mask voxels.
        # Return indices as sparse matrix of 0's and 1's
        print("start get coords")
        world_process_mask = self.data.nifti_masker.fit_transform(
            self.process_mask)
        world_brain_mask = self.data.nifti_masker.fit_transform(self.data.mask)

        process_mask_1D = world_brain_mask.copy()
        process_mask_1D[:, :] = 0
        no_overlap = np.where(
            world_process_mask * world_brain_mask >
            0)  #get the indices where at least one entry is 0
        process_mask_1D[
            no_overlap] = 1  #delete entries for which there is no overlap

        mask, mask_affine = masking._load_mask_img(self.data.mask)
        mask_coords = np.where(mask != 0)
        mc1 = np.reshape(mask_coords[0], (1, -1))
        mc2 = np.reshape(mask_coords[1], (1, -1))
        mc3 = np.reshape(mask_coords[2], (1, -1))
        mask_coords = np.concatenate((mc1.T, mc2.T, mc3.T), axis=1)

        selected_3D = self.data.nifti_masker.inverse_transform(process_mask_1D)
        process_mask_coords = np.where(selected_3D.get_data()[:, :, :, 0] != 0)
        pmc1 = np.reshape(process_mask_coords[0], (1, -1))
        pmc2 = np.reshape(process_mask_coords[1], (1, -1))
        pmc3 = np.reshape(process_mask_coords[2], (1, -1))
        process_mask_coords = np.concatenate((pmc1.T, pmc2.T, pmc3.T), axis=1)

        clf = neighbors.NearestNeighbors(radius=3)
        A = clf.fit(mask_coords).radius_neighbors_graph(process_mask_coords)
        del mask_coords, process_mask_coords, selected_3D, no_overlap

        print("Built searchlight masks.")
        print("Each searchlight has on the order of " +
              str(sum(sum(A[0].toarray()))) + " voxels")
        self.A = A.tolil()
        self.process_mask_1D = process_mask_1D
Exemple #13
0
def parcel_masker(mask, coords, parcel_list, label_names, dir_path, ID,
                  perc_overlap):
    from pynets import nodemaker
    from nilearn.image import resample_img
    from nilearn import masking

    mask_img = nib.load(mask)
    mask_data, _ = masking._load_mask_img(mask)

    i = 0
    indices = []
    for parcel in parcel_list:
        parcel_vol = np.zeros(mask_data.shape, dtype=bool)
        parcel_data_reshaped = resample_img(
            parcel,
            target_affine=mask_img.affine,
            target_shape=mask_data.shape).get_data()
        parcel_vol[parcel_data_reshaped == 1] = 1

        # Count number of unique voxels where overlap of parcel and mask occurs
        overlap_count = len(
            np.unique(
                np.where((mask_data.astype('uint8') == 1)
                         & (parcel_vol.astype('uint8') == 1))))

        # Count number of total unique voxels within the parcel
        total_count = len(
            np.unique(np.where((parcel_vol.astype('uint8') == 1))))

        # Calculate % overlap
        try:
            overlap = float(overlap_count / total_count)
        except RuntimeWarning:
            print('\nWarning: No overlap with mask!\n')
            overlap = float(0)

        if overlap >= perc_overlap:
            print("%.2f%s%s%s" % (100 * overlap, '% of parcel ',
                                  label_names[i], ' falls within mask...'))
        else:
            indices.append(i)
        i = i + 1

    label_names_adj = list(label_names)
    coords_adj = list(tuple(x) for x in coords)
    parcel_list_adj = parcel_list
    for ix in sorted(indices, reverse=True):
        print("%s%s%s%s" %
              ('Removing: ', label_names_adj[ix], ' at ', coords_adj[ix]))
        label_names_adj.pop(ix)
        coords_adj.pop(ix)
        parcel_list_adj.pop(ix)

    # Create a resampled 3D atlas that can be viewed alongside mask img for QA
    resampled_parcels_nii_path = "%s%s%s%s%s%s" % (
        dir_path, '/', ID, '_parcels_resampled2mask_',
        os.path.basename(mask).split('.')[0], '.nii.gz')
    resampled_parcels_atlas, _ = nodemaker.create_parcel_atlas(parcel_list_adj)
    resampled_parcels_map_nifti = resample_img(resampled_parcels_atlas,
                                               target_affine=mask_img.affine,
                                               target_shape=mask_data.shape)
    nib.save(resampled_parcels_map_nifti, resampled_parcels_nii_path)
    return coords_adj, label_names_adj, parcel_list_adj
Exemple #14
0
    def fit(self, imgs, y):
        """Fit the searchlight

        Parameters
        ----------
        imgs : List of images
        y : 1D array-like
            Target variable to predict. Must have exactly as many elements as
            3D images in img.

        Attributes
        ----------
        `scores_` : numpy.ndarray
            search_light scores. Same shape as input parameter
            process_mask_img.
        """

        # Compute world coordinates of all in-mask voxels.
        self.affine = nibabel.load(imgs[0]).affine if isinstance(
            imgs[0], str) else imgs[0].affine
        mask, mask_affine = masking._load_mask_img(self.mask_img)
        mask_coords = np.where(mask != 0)
        mask_coords = np.asarray(
            mask_coords + (np.ones(len(mask_coords[0]), dtype=np.int), ))
        mask_coords = np.dot(mask_affine, mask_coords)[:3].T
        # Compute world coordinates of all in-process mask voxels
        if self.process_mask_img is None:
            process_mask = mask
            process_mask_coords_world = mask_coords
        else:
            process_mask, process_mask_affine = \
                masking._load_mask_img(self.process_mask_img)
            process_mask_coords = np.where(process_mask != 0)
            process_mask_coords_world = \
                np.asarray(process_mask_coords
                           + (np.ones(len(process_mask_coords[0]),
                                      dtype=np.int),))
            process_mask_coords_world = np.dot(process_mask_affine,
                                               process_mask_coords_world)[:3].T

        clf = neighbors.NearestNeighbors(radius=self.radius)
        A = clf.fit(mask_coords).radius_neighbors_graph(
            process_mask_coords_world)
        if self.process_mask_img is not None:
            empty_ind = [i for i in range(A.shape[0]) if A[i, :].getnnz() == 0]
            if empty_ind:
                warn(
                    'Skipping %g voxels of processing mask outside mask_img (first index: %g)'
                    % (len(empty_ind), empty_ind[0]))
                A = A[list(set(range(A.shape[0])) - set(empty_ind)), :]
                process_mask[tuple(
                    np.asarray(process_mask_coords)[:, empty_ind])] = False

        A = A.tolil()

        # scores is an 1D array of CV scores with length equals to the number
        # of voxels in processing mask (columns in process_mask)
        # X = masking._apply_mask_fmri(imgs, self.mask_img)
        X = NiftiMasker(mask_img=self.mask_img).fit_transform(imgs)

        estimator = self.estimator
        if isinstance(estimator, str):
            estimator = ESTIMATOR_CATALOG[estimator](**self.estimator_params)
        elif hasattr(estimator,
                     '__name__'):  # check if estimator has to be initialized
            estimator = estimator(**self.estimator_params)
        else:
            estimator.set_params(**self.estimator_params)

        scores = search_light(X, y, estimator, A, self.scoring, self.cv,
                              self.n_jobs, self.verbose)
        scores_3D = np.zeros(process_mask.shape)
        scores_3D[process_mask] = scores
        self.scores_ = scores_3D
        return self
Exemple #15
0
def run_struct_mapping(FSLDIR, ID, bedpostx_dir, dir_path, NETWORK, coords_MNI,
                       node_size, atlas_select, atlas_name, label_names,
                       plot_switch):
    edge_threshold = 0.90
    connectome_fdt_thresh = 1000

    ####Auto-set INPUTS####
    nodif_brain_mask_path = bedpostx_dir + '/nodif_brain_mask.nii.gz'
    merged_th_samples_path = bedpostx_dir + '/merged_th1samples.nii.gz'
    merged_f_samples_path = bedpostx_dir + '/merged_f1samples.nii.gz'
    merged_ph_samples_path = bedpostx_dir + '/merged_ph1samples.nii.gz'
    input_MNI = FSLDIR + '/data/standard/MNI152_T1_2mm_brain.nii.gz'
    probtrackx_output_dir_path = bedpostx_dir + '/probtrackx_' + NETWORK
    ####Auto-set INPUTS####

    ##Delete any existing roi spheres
    del_files_spheres = glob.glob(bedpostx_dir + '/roi_sphere*diff.nii.gz')
    try:
        for i in del_files_spheres:
            os.remove(i)
    except:
        pass

    ##Create transform matrix between diff and MNI using FLIRT
    flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                    name='coregister')
    flirt.inputs.reference = merged_f_samples_path
    flirt.inputs.in_file = input_MNI
    flirt.inputs.out_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat'
    flirt.run()

    ##Apply transform between diff and MNI using FLIRT
    flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                    name='coregister')
    flirt.inputs.reference = merged_f_samples_path
    flirt.inputs.in_file = input_MNI
    flirt.inputs.apply_xfm = True
    flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat'
    flirt.inputs.out_file = bedpostx_dir + '/xfms/MNI2diff_affine.nii.gz'
    flirt.run()

    x_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0]
    y_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1]
    z_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2]

    def mmToVox(mmcoords):
        voxcoords = ['', '', '']
        voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45)
        voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63)
        voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36)
        return voxcoords

    ##Convert coords back to voxels
    coords_vox = []
    for coord in coords_MNI:
        coords_vox.append(mmToVox(coord))
    coords = list(tuple(x) for x in coords_vox)

    j = 0
    for i in coords:
        ##Grow spheres at ROI
        X = coords[j][0]
        Y = coords[j][1]
        Z = coords[j][2]
        out_file1 = bedpostx_dir + '/roi_point_' + str(j) + '.nii.gz'
        args = '-mul 0 -add 1 -roi ' + str(X) + ' 1 ' + str(Y) + ' 1 ' + str(
            Z) + ' 1 0 1'
        maths = fsl.ImageMaths(in_file=input_MNI,
                               op_string=args,
                               out_file=out_file1)
        os.system(maths.cmdline + ' -odt float')

        out_file2 = bedpostx_dir + '/roi_sphere_' + str(j) + '.nii.gz'
        args = '-kernel sphere ' + str(node_size) + ' -fmean -bin'
        maths = fsl.ImageMaths(in_file=out_file1,
                               op_string=args,
                               out_file=out_file2)
        os.system(maths.cmdline + ' -odt float')

        ##Map ROIs from Standard Space to diffusion Space:
        ##Applying xfm and input matrix to transform ROI's between diff and MNI using FLIRT,
        flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                        name='coregister')
        flirt.inputs.reference = nodif_brain_mask_path
        flirt.inputs.in_file = out_file2
        out_file_diff = out_file2.split('.nii')[0] + '_diff.nii.gz'
        flirt.inputs.out_file = out_file_diff
        flirt.inputs.apply_xfm = True
        flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat'
        flirt.run()
        j = j + 1

    if not os.path.exists(probtrackx_output_dir_path):
        os.makedirs(probtrackx_output_dir_path)

    seed_files = glob.glob(bedpostx_dir + '/*diff.nii.gz')
    seeds_text = probtrackx_output_dir_path + '/masks.txt'
    try:
        os.remove(seeds_text)
    except OSError:
        pass
    seeds_file_list = []
    for seed_file in seed_files:
        seeds_file_list.append(seed_file)
    f = open(seeds_text, 'w')
    l1 = map(lambda x: x + '\n', seeds_file_list)
    f.writelines(l1)
    f.close()

    del_files_points = glob.glob(bedpostx_dir + '/roi_point*.nii.gz')
    for i in del_files_points:
        os.remove(i)

    del_files_spheres = glob.glob(bedpostx_dir + '/roi_sphere*[!diff].nii.gz')
    for i in del_files_spheres:
        os.remove(i)

    mx_path = dir_path + '/' + str(ID) + '_' + NETWORK + '_structural_mx.txt'
    probtrackx2 = pe.Node(interface=fsl.ProbTrackX2(), name='probtrackx2')
    probtrackx2.inputs.network = True
    probtrackx2.inputs.seed = seeds_text
    probtrackx2.inputs.onewaycondition = True
    probtrackx2.inputs.c_thresh = 0.2
    probtrackx2.inputs.n_steps = 2000
    probtrackx2.inputs.step_length = 0.5
    probtrackx2.inputs.n_samples = 5000
    probtrackx2.inputs.dist_thresh = 0.0
    probtrackx2.inputs.opd = True
    probtrackx2.inputs.loop_check = True
    probtrackx2.inputs.omatrix1 = True
    probtrackx2.overwrite = True
    probtrackx2.inputs.verbose = True
    probtrackx2.inputs.mask = nodif_brain_mask_path
    probtrackx2.inputs.out_dir = probtrackx_output_dir_path
    probtrackx2.inputs.thsamples = merged_th_samples_path
    probtrackx2.inputs.fsamples = merged_f_samples_path
    probtrackx2.inputs.phsamples = merged_ph_samples_path
    probtrackx2.iterables = ("seed", seed_files)
    try:
        probtrackx2.inputs.avoid_mp = vetricular_CSF_mask_path
    except:
        pass
    probtrackx2.run()
    del (probtrackx2)

    if os.path.exists(probtrackx_output_dir_path + '/fdt_network_matrix'):
        mx = np.genfromtxt(probtrackx_output_dir_path + '/fdt_network_matrix')

        waytotal = np.genfromtxt(probtrackx_output_dir_path + '/waytotal')
        np.seterr(divide='ignore', invalid='ignore')
        conn_matrix = np.divide(mx, waytotal)
        conn_matrix[np.isnan(conn_matrix)] = 0
        conn_matrix = np.nan_to_num(conn_matrix)
        conn_matrix = normalize(conn_matrix)

        ##Save matrix
        out_path_mx = dir_path + '/' + str(
            ID) + '_' + NETWORK + '_structural_mx.txt'
        np.savetxt(out_path_mx, conn_matrix, delimiter='\t')

        if plot_switch == True:
            rois_num = conn_matrix.shape[0]
            print("Creating plot of dimensions:\n" + str(rois_num) + ' x ' +
                  str(rois_num))
            plt.figure(figsize=(10, 10))
            plt.imshow(conn_matrix,
                       interpolation="nearest",
                       vmax=1,
                       vmin=-1,
                       cmap=plt.cm.RdBu_r)

            ##And display the labels
            plt.colorbar()
            plt.title(atlas_select.upper() + ' ' + NETWORK +
                      ' Structural Connectivity')

            out_path_fig = dir_path + '/' + str(
                ID) + '_' + NETWORK + '_structural_adj_mat.png'
            plt.savefig(out_path_fig)
            plt.close()

            conn_matrix_symm = np.maximum(conn_matrix, conn_matrix.transpose())

        fdt_paths_loc = probtrackx_output_dir_path + '/fdt_paths.nii.gz'

        ##Plotting with glass brain
        ##Create transform matrix between diff and MNI using FLIRT
        flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                        name='coregister')
        flirt.inputs.reference = input_MNI
        flirt.inputs.in_file = nodif_brain_mask_path
        flirt.inputs.out_matrix_file = bedpostx_dir + '/xfms/diff2MNI.mat'
        flirt.run()

        ##Apply transform between diff and MNI using FLIRT
        flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                        name='coregister')
        flirt.inputs.reference = input_MNI
        flirt.inputs.in_file = nodif_brain_mask_path
        flirt.inputs.apply_xfm = True
        flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/diff2MNI.mat'
        flirt.inputs.out_file = bedpostx_dir + '/xfms/diff2MNI_affine.nii.gz'
        flirt.run()

        flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                        name='coregister')
        flirt.inputs.reference = input_MNI
        flirt.inputs.in_file = fdt_paths_loc
        out_file_MNI = fdt_paths_loc.split('.nii')[0] + '_MNI.nii.gz'
        flirt.inputs.out_file = out_file_MNI
        flirt.inputs.apply_xfm = True
        flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/diff2MNI.mat'
        flirt.run()

        fdt_paths_MNI_loc = probtrackx_output_dir_path + '/fdt_paths_MNI.nii.gz'

        if plot_switch == True:
            norm = colors.Normalize(vmin=-1, vmax=1)
            clust_pal = sns.color_palette("Blues_r", 4)
            clust_colors = colors.to_rgba_array(clust_pal)

            connectome = plotting.plot_connectome(
                conn_matrix_symm,
                coords_MNI,
                edge_threshold=edge_threshold,
                node_color=clust_colors,
                edge_cmap=plotting.cm.black_blue_r)
            connectome.add_overlay(img=fdt_paths_MNI_loc,
                                   threshold=connectome_fdt_thresh,
                                   cmap=plotting.cm.cyan_copper_r)
            out_file_path = dir_path + '/structural_connectome_fig_' + NETWORK + '_' + str(
                ID) + '.png'
            plt.savefig(out_file_path)
            plt.close()

            from pynets import plotting as pynplot
            NETWORK = NETWORK + '_structural'
            pynplot.plot_connectogram(conn_matrix, conn_model, atlas_name,
                                      dir_path, ID, NETWORK, label_names)

        if NETWORK != None:
            est_path = dir_path + '/' + ID + '_' + NETWORK + '_structural_est.txt'
        else:
            est_path = dir_path + '/' + ID + '_structural_est.txt'
        try:
            np.savetxt(est_path, conn_matrix_symm, delimiter='\t')
        except RuntimeError:
            print('Diffusion network connectome failed!')
    return (est_path)
Exemple #16
0
def reg_coords2diff(coords, bedpostx_dir, node_size, dir_path):
    try:
        FSLDIR = os.environ['FSLDIR']
    except NameError:
        print('FSLDIR environment variable not set!')
    import glob
    import nipype.interfaces.fsl as fsl
    import nipype.pipeline.engine as pe
    from nilearn import masking
    try:
        import cPickle as pickle
    except ImportError:
        import _pickle as pickle

    pick_dump = True
    volumes_dir = "%s%s%s" % (dir_path, '/volumes_', str(node_size))
    nodif_brain_mask_path = "%s%s" % (bedpostx_dir, '/nodif_brain_mask.nii.gz')
    merged_f_samples_path = "%s%s" % (bedpostx_dir, '/merged_f1samples.nii.gz')

    x_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0]
    y_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1]
    z_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2]

    def mmToVox(mmcoords):
        voxcoords = ['', '', '']
        voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45)
        voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63)
        voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36)
        return voxcoords

    # Convert coords back to voxels
    coords_vox = []
    for coord in coords:
        coords_vox.append(mmToVox(coord))
    coords = list(tuple(x) for x in coords_vox)

    j = 0
    for i in coords:
        # Grow spheres at ROI
        X = coords[j][0]
        Y = coords[j][1]
        Z = coords[j][2]
        out_file1 = "%s%s%s%s" % (volumes_dir, '/roi_point_', str(j),
                                  '.nii.gz')
        args = "%s%s%s%s%s%s%s" % ('-mul 0 -add 1 -roi ', str(X), ' 1 ',
                                   str(Y), ' 1 ', str(Z), ' 1 0 1')
        maths = fsl.ImageMaths(in_file=FSLDIR +
                               '/data/standard/MNI152_T1_1mm_brain.nii.gz',
                               op_string=args,
                               out_file=out_file1)
        os.system(maths.cmdline + ' -odt float')

        out_file2 = "%s%s%s%s" % (volumes_dir, '/region_', str(j), '.nii.gz')
        args = "%s%s%s" % ('-kernel sphere ', str(node_size), ' -fmean -bin')
        maths = fsl.ImageMaths(in_file=out_file1,
                               op_string=args,
                               out_file=out_file2)
        os.system(maths.cmdline + ' -odt float')

        # Map ROIs from Standard Space to diffusion Space:
        # Applying xfm and input matrix to transform ROI's between diff and MNI using FLIRT,
        flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                        name='coregister')
        flirt.inputs.reference = merged_f_samples_path
        flirt.inputs.in_file = out_file2
        out_file_diff = "%s%s" % (out_file2.split('.nii')[0], '_diff.nii.gz')
        flirt.inputs.out_file = out_file_diff
        flirt.inputs.out_matrix_file = '/tmp/out_flirt.mat'
        flirt.inputs.apply_xfm = True
        flirt.inputs.in_matrix_file = "%s%s" % (bedpostx_dir,
                                                '/xfms/MNI2diff.mat')
        flirt.run()
        j = j + 1

    args = '-bin'
    maths = fsl.ImageMaths(in_file=out_file_diff,
                           op_string=args,
                           out_file=out_file_diff)
    print('\nBinarizing custom mask...')
    os.system(maths.cmdline)

    del_files_points = glob.glob(volumes_dir + '/roi_point*')
    if len(del_files_points) > 0:
        for i in del_files_points:
            os.remove(i)

    spheres_list = [i for i in os.listdir(volumes_dir) if 'diff.nii.gz' in i]
    if pick_dump is True:
        # Save coords to pickle
        coord_path = "%s%s" % (dir_path, '/coords.pkl')
        with open(coord_path, 'wb') as f:
            pickle.dump(coords, f, protocol=2)

    return spheres_list
Exemple #17
0
def get_searchlight_neighbours_matrix(mask_file, radius=6):
    """

    Parameters
    ----------
    mask_file : string
        Path to mask-file.
    radius : integer
        Searchlight radius in mm.

    Returns
    -------
    A : ndarray, shape(n_voxel, n_voxel)
        Affinity matrix. A[i,j]==1 if voxel_i, voxel_j are neighbours
        and 0 otherwise

    Examples
    --------
    >>> A = get_searchlight_neighbours_matrix('MNI152_2mm_brain_mask.nii')
    >>> A.shape
    """

    # heavily borrowed from nilearn: http://nilearn.github.io/
    from nilearn import image
    from nilearn import masking
    from nilearn.image.resampling import coord_transform
    from distutils.version import LooseVersion
    import sklearn
    from sklearn import neighbors
    from nilearn._utils.niimg_conversions import check_niimg_3d

    def _apply_mask_and_get_affinity(seeds,
                                     niimg,
                                     radius,
                                     allow_overlap,
                                     mask_img=None):
        seeds = list(seeds)
        aff = niimg.get_affine()

        # Compute world coordinates of all in-mask voxels.
        if mask_img is not None:
            mask_img = check_niimg_3d(mask_img)
            mask_img = image.resample_img(mask_img,
                                          target_affine=aff,
                                          target_shape=niimg.shape[:3],
                                          interpolation='nearest')
            mask, _ = masking._load_mask_img(mask_img)
            mask_coords = list(zip(*np.where(mask != 0)))

            # X = masking._apply_mask_fmri(niimg, mask_img)
        else:
            mask_coords = list(np.ndindex(niimg.shape[:3]))

        # For each seed, get coordinates of nearest voxel
        nearests = []
        for sx, sy, sz in seeds:
            nearest = np.round(coord_transform(sx, sy, sz, np.linalg.inv(aff)))
            nearest = nearest.astype(int)
            nearest = (nearest[0], nearest[1], nearest[2])
            try:
                nearests.append(mask_coords.index(nearest))
            except ValueError:
                nearests.append(None)

        mask_coords = np.asarray(list(zip(*mask_coords)))
        mask_coords = coord_transform(mask_coords[0], mask_coords[1],
                                      mask_coords[2], aff)
        mask_coords = np.asarray(mask_coords).T

        if (radius is not None
                and LooseVersion(sklearn.__version__) < LooseVersion('0.16')):
            # Fix for scikit learn versions below 0.16. See
            # https://github.com/scikit-learn/scikit-learn/issues/4072
            radius += 1e-6

        clf = neighbors.NearestNeighbors(radius=radius)
        A = clf.fit(mask_coords).radius_neighbors_graph(seeds)
        A = A.tolil()

        for i, nearest in enumerate(nearests):
            if nearest is None:
                continue
            A[i, nearest] = True

        # Include the voxel containing the seed itself if not masked
        mask_coords = mask_coords.astype(int).tolist()
        for i, seed in enumerate(seeds):
            try:
                A[i, mask_coords.index(seed)] = True
            except ValueError:
                # seed is not in the mask
                pass

        if not allow_overlap:
            if np.any(A.sum(axis=0) >= 2):
                raise ValueError('Overlap detected between spheres')

        return A

    process_mask_img = nib.load(mask_file)

    # Compute world coordinates of the seeds
    process_mask, process_mask_affine = masking._load_mask_img(
        process_mask_img)
    process_mask_coords = np.where(process_mask != 0)
    process_mask_coords = coord_transform(process_mask_coords[0],
                                          process_mask_coords[1],
                                          process_mask_coords[2],
                                          process_mask_affine)
    process_mask_coords = np.asarray(process_mask_coords).T

    A = _apply_mask_and_get_affinity(process_mask_coords,
                                     process_mask_img,
                                     radius,
                                     True,
                                     mask_img=process_mask_img)

    return A  # .toarray().astype('bool')
Exemple #18
0
def coords_masker(roi, coords, label_names, mask, error):
    from nilearn import masking

    if mask and roi == mask:
        error = 0

    mask_data, mask_aff = masking._load_mask_img(roi)
    x_vox = np.diagonal(mask_aff[:3, 0:3])[0]
    y_vox = np.diagonal(mask_aff[:3, 0:3])[1]
    z_vox = np.diagonal(mask_aff[:3, 0:3])[2]

    def mmToVox(mask_aff, mmcoords):
        return nib.affines.apply_affine(np.linalg.inv(mask_aff), mmcoords)


#    mask_coords = list(zip(*np.where(mask_data == True)))

    coords_vox = []
    for i in coords:
        coords_vox.append(mmToVox(mask_aff, i))
    coords_vox = list(
        tuple(map(lambda y: isinstance(y, float) and int(round(y, 0)), x))
        for x in coords_vox)
    bad_coords = []
    for coords in coords_vox:
        sphere_vol = np.zeros(mask_data.shape, dtype=bool)
        sphere_vol[tuple(coords)] = 1
        if (mask_data & sphere_vol).any():
            print("%s%s" % (coords, ' falls within roi mask...'))
            continue
        inds = get_sphere(coords, error, (np.abs(x_vox), y_vox, z_vox),
                          mask_data.shape)
        sphere_vol[tuple(inds.T)] = 1
        if (mask_data & sphere_vol).any():
            print("%s%s%.2f%s" % (coords, ' is within a + or - ', float(error),
                                  ' mm neighborhood...'))
            continue
        bad_coords.append(coords)

    bad_coords = [x for x in bad_coords if x is not None]
    indices = []
    for bad_coords in bad_coords:
        indices.append(coords_vox.index(bad_coords))

    label_names = list(label_names)
    coords = list(tuple(x) for x in coords_vox)
    try:
        for ix in sorted(indices, reverse=True):
            print("%s%s%s%s" %
                  ('Removing: ', label_names[ix], ' at ', coords[ix]))
            label_names.pop(ix)
            coords.pop(ix)
    except RuntimeError:
        print(
            'ERROR: Restrictive masking. No coords remain after masking with brain mask/roi...'
        )

    if len(coords) <= 1:
        raise ValueError(
            '\nERROR: ROI mask was likely too restrictive and yielded < 2 remaining coords'
        )

    return coords, label_names
Exemple #19
0
def reg_coords2diff(coords, bedpostx_dir, node_size):
    try:
        FSLDIR = os.environ['FSLDIR']
    except NameError:
        print('FSLDIR environment variable not set!')
    import glob
    import nipype.interfaces.fsl as fsl
    import nipype.pipeline.engine as pe
    from nilearn import masking

    volumes_dir = bedpostx_dir + '/volumes'
    nodif_brain_mask_path = bedpostx_dir + '/nodif_brain_mask.nii.gz'
    merged_f_samples_path = bedpostx_dir + '/merged_f1samples.nii.gz'

    x_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0]
    y_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1]
    z_vox = np.diagonal(
        masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2]

    def mmToVox(mmcoords):
        voxcoords = ['', '', '']
        voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45)
        voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63)
        voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36)
        return voxcoords

    ##Convert coords back to voxels
    coords_vox = []
    for coord in coords:
        coords_vox.append(mmToVox(coord))
    coords = list(tuple(x) for x in coords_vox)

    j = 0
    for i in coords:
        ##Grow spheres at ROI
        X = coords[j][0]
        Y = coords[j][1]
        Z = coords[j][2]
        out_file1 = volumes_dir + '/roi_point_' + str(j) + '.nii.gz'
        args = '-mul 0 -add 1 -roi ' + str(X) + ' 1 ' + str(Y) + ' 1 ' + str(
            Z) + ' 1 0 1'
        maths = fsl.ImageMaths(in_file=FSLDIR +
                               '/data/standard/MNI152_T1_1mm_brain.nii.gz',
                               op_string=args,
                               out_file=out_file1)
        os.system(maths.cmdline + ' -odt float')

        out_file2 = volumes_dir + '/region_' + str(j) + '.nii.gz'
        args = '-kernel sphere ' + str(node_size) + ' -fmean -bin'
        maths = fsl.ImageMaths(in_file=out_file1,
                               op_string=args,
                               out_file=out_file2)
        os.system(maths.cmdline + ' -odt float')

        ##Map ROIs from Standard Space to diffusion Space:
        ##Applying xfm and input matrix to transform ROI's between diff and MNI using FLIRT,
        flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                        name='coregister')
        flirt.inputs.reference = merged_f_samples_path
        flirt.inputs.in_file = out_file2
        out_file_diff = out_file2.split('.nii')[0] + '_diff.nii.gz'
        flirt.inputs.out_file = out_file_diff
        flirt.inputs.out_matrix_file = '/tmp/out_flirt.mat'
        flirt.inputs.apply_xfm = True
        flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat'
        flirt.run()
        j = j + 1

    del_files_points = glob.glob(volumes_dir + '/roi_point*')
    try:
        for i in del_files_points:
            os.remove(i)
    except:
        pass

    spheres_list = [i for i in os.listdir(volumes_dir) if 'diff.nii' in i]
    return spheres_list
Exemple #20
0
    def _apply_mask_and_get_affinity(seeds,
                                     niimg,
                                     radius,
                                     allow_overlap,
                                     mask_img=None):
        seeds = list(seeds)
        aff = niimg.get_affine()

        # Compute world coordinates of all in-mask voxels.
        if mask_img is not None:
            mask_img = check_niimg_3d(mask_img)
            mask_img = image.resample_img(mask_img,
                                          target_affine=aff,
                                          target_shape=niimg.shape[:3],
                                          interpolation='nearest')
            mask, _ = masking._load_mask_img(mask_img)
            mask_coords = list(zip(*np.where(mask != 0)))

            # X = masking._apply_mask_fmri(niimg, mask_img)
        else:
            mask_coords = list(np.ndindex(niimg.shape[:3]))

        # For each seed, get coordinates of nearest voxel
        nearests = []
        for sx, sy, sz in seeds:
            nearest = np.round(coord_transform(sx, sy, sz, np.linalg.inv(aff)))
            nearest = nearest.astype(int)
            nearest = (nearest[0], nearest[1], nearest[2])
            try:
                nearests.append(mask_coords.index(nearest))
            except ValueError:
                nearests.append(None)

        mask_coords = np.asarray(list(zip(*mask_coords)))
        mask_coords = coord_transform(mask_coords[0], mask_coords[1],
                                      mask_coords[2], aff)
        mask_coords = np.asarray(mask_coords).T

        if (radius is not None
                and LooseVersion(sklearn.__version__) < LooseVersion('0.16')):
            # Fix for scikit learn versions below 0.16. See
            # https://github.com/scikit-learn/scikit-learn/issues/4072
            radius += 1e-6

        clf = neighbors.NearestNeighbors(radius=radius)
        A = clf.fit(mask_coords).radius_neighbors_graph(seeds)
        A = A.tolil()

        for i, nearest in enumerate(nearests):
            if nearest is None:
                continue
            A[i, nearest] = True

        # Include the voxel containing the seed itself if not masked
        mask_coords = mask_coords.astype(int).tolist()
        for i, seed in enumerate(seeds):
            try:
                A[i, mask_coords.index(seed)] = True
            except ValueError:
                # seed is not in the mask
                pass

        if not allow_overlap:
            if np.any(A.sum(axis=0) >= 2):
                raise ValueError('Overlap detected between spheres')

        return A
Exemple #21
0
def import_mat_func(input_file, ID, atlas_select, NETWORK, pynets_dir,
                    node_size, mask, thr, graph, parlistfile, sps_model,
                    all_nets):
    if '.nii' in input_file and parlistfile == None and NETWORK == None:
        if graph == False:
            func_file = input_file

            if all_nets != None:
                func_img = nib.load(func_file)
                par_path = pynets_dir + '/RSN_refs/yeo.nii.gz'
                par_img = nib.load(par_path)
                par_data = par_img.get_data()

                ref_dict = {
                    0: 'unknown',
                    1: 'VIS',
                    2: 'SM',
                    3: 'DA',
                    4: 'VA',
                    5: 'LIM',
                    6: 'FP',
                    7: 'DEF'
                }

                def get_ref_net(x, y, z):
                    aff_inv = npl.inv(func_img.affine)
                    # apply_affine(aff, (x,y,z)) # vox to mni
                    vox_coord = apply_affine(aff_inv, (x, y, z))  # mni to vox
                    return ref_dict[int(par_data[int(vox_coord[0]),
                                                 int(vox_coord[1]),
                                                 int(vox_coord[2])])]

            dir_path = os.path.dirname(os.path.realpath(func_file))
            atlas = getattr(datasets, 'fetch_%s' % atlas_select)()
            atlas_name = atlas['description'].splitlines()[0]
            print(atlas_name + ' comes with {0}.'.format(atlas.keys()))
            print("\n")
            coords = np.vstack(
                (atlas.rois['x'], atlas.rois['y'], atlas.rois['z'])).T
            if all_nets != None:
                membership = pd.Series([
                    get_ref_net(coord[0], coord[1], coord[2])
                    for coord in coords
                ])
            print('Stacked atlas coordinates in array of shape {0}.'.format(
                coords.shape))
            print("\n")
            if mask is not None:
                from nilearn import masking
                mask_data, _ = masking._load_mask_img(mask)
                mask_coords = list(zip(*np.where(mask_data != 0)))
                for coord in coords:
                    if tuple(coord) not in mask_coords:
                        print('Removing coordinate: ' + str(tuple(coord)) +
                              ' since it falls outside of network mask...')
                        ix = np.where(coords == coord)[0][0]
                        coords = np.delete(coords, ix, axis=0)
                        print(str(len(coords)))
                        print("\n")
            spheres_masker = input_data.NiftiSpheresMasker(
                seeds=coords,
                radius=float(node_size),
                memory='nilearn_cache',
                memory_level=5,
                verbose=2)
            time_series = spheres_masker.fit_transform(func_file)
            correlation_measure = ConnectivityMeasure(kind='correlation')
            correlation_matrix = correlation_measure.fit_transform(
                [time_series])[0]
            print("\n")
            print('Time series has {0} samples'.format(time_series.shape[0]))
            print("\n")
        else:
            correlation_matrix = genfromtxt(graph, delimiter='\t')
        plt.imshow(correlation_matrix,
                   vmin=-1.,
                   vmax=1.,
                   cmap='RdBu_r',
                   interpolation='nearest')
        plt.colorbar()
        plt.title(atlas_name + ' correlation matrix')
        out_path_fig = dir_path + '/' + ID + '_' + atlas_name + '_adj_mat_corr.png'
        plt.savefig(out_path_fig)
        plt.close()
        ##Tweak edge_threshold to keep only the strongest connections.
        atlast_graph_title = atlas_name + ' correlation graph'
        if mask is None:
            atlast_graph_title = atlas_name + ' correlation graph'
        else:
            atlast_graph_title = atlas_name + ' Masked Nodes'
        edge_threshold = str(float(thr) * 100) + '%'

        # plot graph:
        if all_nets != None:
            # coloring code:
            n = len(membership.unique())
            clust_pal = sns.color_palette("Set1", n)
            clust_lut = dict(
                zip(map(str, np.unique(membership.astype('category'))),
                    clust_pal))
            clust_colors = colors.to_rgba_array(membership.map(clust_lut))

            plotting.plot_connectome(correlation_matrix,
                                     coords,
                                     node_color=clust_colors,
                                     title=atlast_graph_title,
                                     edge_threshold=edge_threshold,
                                     node_size=20,
                                     colorbar=True)
        else:
            plotting.plot_connectome(correlation_matrix,
                                     coords,
                                     title=atlast_graph_title,
                                     edge_threshold=edge_threshold,
                                     node_size=20,
                                     colorbar=True)
        out_path_fig = dir_path + '/' + ID + '_' + atlas_name + '_connectome_viz.png'
        plt.savefig(out_path_fig)
        plt.close()
        time_series_path = dir_path + '/' + ID + '_ts.txt'
        np.savetxt(time_series_path, time_series, delimiter='\t')
        mx = genfromtxt(time_series_path, delimiter='')

    elif '.nii' in input_file and parlistfile != None and NETWORK == None:  # block of code for whole brain parcellations
        if all_nets != None:
            par_path = pynets_dir + '/RSN_refs/yeo.nii.gz'
            par_img = nib.load(par_path)
            par_data = par_img.get_data()

            ref_dict = {
                0: 'unknown',
                1: 'VIS',
                2: 'SM',
                3: 'DA',
                4: 'VA',
                5: 'LIM',
                6: 'FP',
                7: 'DEF'
            }

            def get_ref_net(x, y, z):
                aff_inv = npl.inv(bna_img.affine)
                # apply_affine(aff, (x,y,z)) # vox to mni
                vox_coord = apply_affine(aff_inv, (x, y, z))  # mni to vox
                return ref_dict[int(par_data[int(vox_coord[0]),
                                             int(vox_coord[1]),
                                             int(vox_coord[2])])]

        func_file = input_file
        dir_path = os.path.dirname(os.path.realpath(func_file))

        atlas_name = parlistfile.split('/')[-1].split('.')[0]
        # Code for getting name and coordinates of parcels.
        # Adapted from Dan L. (https://github.com/danlurie/despolab_lesion/blob/master/code/sandbox/Sandbox%20-%20Calculate%20and%20plot%20HCP%20mean%20matrix.ipynb)
        bna_img = nib.load(parlistfile)
        bna_data = bna_img.get_data()
        if bna_img.get_data_dtype() != np.dtype(np.int):
            bna_data_for_coords = bna_img.get_data()
            # Number of parcels:
            par_max = np.ceil(np.max(bna_data_for_coords)).astype('int')
            bna_data = bna_data.astype('int16')
        else:
            par_max = np.max(bna_data)

        img_stack = []
        for idx in range(1, par_max + 1):
            roi_img = bna_data == idx
            img_stack.append(roi_img)
        img_stack = np.array(img_stack)
        img_list = []
        for idx in range(par_max):
            roi_img = nilearn.image.new_img_like(bna_img, img_stack[idx])
            img_list.append(roi_img)

        bna_4D = nilearn.image.concat_imgs(img_list)
        coords = []
        for roi_img in img_list:
            coords.append(nilearn.plotting.find_xyz_cut_coords(roi_img))
        coords = np.array(coords)
        if all_nets != None:
            membership = pd.Series([
                get_ref_net(coord[0], coord[1], coord[2]) for coord in coords
            ])
        # atlas = getattr(datasets, 'fetch_%s' % atlas_select)()
        # atlas_name = atlas['description'].splitlines()[0]
        print("\n")
        print(atlas_name + ' comes with {0}.'.format(par_max) + 'parcels')
        print("\n")
        print("\n")
        print('Stacked atlas coordinates in array of shape {0}.'.format(
            coords.shape))
        print("\n")
        if mask is not None:
            from nilearn import masking
            mask_data, _ = masking._load_mask_img(mask)
            mask_coords = list(zip(*np.where(mask_data != 0)))
            for coord in coords:
                if tuple(coord) not in mask_coords:
                    print('Removing coordinate: ' + str(tuple(coord)) +
                          ' since it falls outside of network mask...')
                    ix = np.where(coords == coord)[0][0]
                    coords = np.delete(coords, ix, axis=0)
                    print(str(len(coords)))

        ##extract time series from whole brain parcellaions:
        parcellation = nib.load(parlistfile)
        parcel_masker = input_data.NiftiLabelsMasker(labels_img=parcellation,
                                                     background_label=0,
                                                     memory='nilearn_cache',
                                                     memory_level=5)
        time_series = parcel_masker.fit_transform(func_file)
        ##old ref code for coordinate parcellations:
        #spheres_masker = input_data.NiftiSpheresMasker(seeds=coords, radius=float(node_size), memory='nilearn_cache', memory_level=2, verbose=2)
        #time_series = spheres_masker.fit_transform(func_file)
        correlation_measure = ConnectivityMeasure(kind='correlation')
        correlation_matrix = correlation_measure.fit_transform([time_series
                                                                ])[0]
        print("\n")
        print('Time series has {0} samples'.format(time_series.shape[0]))
        print("\n")
        plt.imshow(correlation_matrix,
                   vmin=-1.,
                   vmax=1.,
                   cmap='RdBu_r',
                   interpolation='nearest')
        plt.colorbar()
        plt.title(atlas_name + ' correlation matrix')
        out_path_fig = dir_path + '/' + ID + '_' + atlas_name + '_adj_mat_corr.png'
        plt.savefig(out_path_fig)
        plt.close()
        ##Tweak edge_threshold to keep only the strongest connections.
        atlast_graph_title = atlas_name + ' correlation graph'
        if mask is None:
            atlast_graph_title = atlas_name + ' correlation graph'
        else:
            atlast_graph_title = atlas_name + ' Masked Nodes'
        edge_threshold = str(float(thr) * 100) + '%'

        if all_nets != None:
            # coloring code:
            n = len(membership.unique())
            clust_pal = sns.color_palette("Set1", n)
            clust_lut = dict(
                zip(map(str, np.unique(membership.astype('category'))),
                    clust_pal))
            clust_colors = colors.to_rgba_array(membership.map(clust_lut))
            plotting.plot_connectome(correlation_matrix,
                                     coords,
                                     node_color=clust_colors,
                                     title=atlast_graph_title,
                                     edge_threshold=edge_threshold,
                                     node_size=20,
                                     colorbar=True)
        else:
            plotting.plot_connectome(correlation_matrix,
                                     coords,
                                     title=atlast_graph_title,
                                     edge_threshold=edge_threshold,
                                     node_size=20,
                                     colorbar=True)
        out_path_fig = dir_path + '/' + ID + '_' + atlas_name + '_connectome_viz.png'
        plt.savefig(out_path_fig)
        plt.close()
        time_series_path = dir_path + '/' + ID + '_ts.txt'
        np.savetxt(time_series_path, time_series, delimiter='\t')
        mx = genfromtxt(time_series_path, delimiter='')

    elif '.nii' in input_file and NETWORK != None:
        func_file = input_file

        ##Reference RSN list
        load_path = pynets_dir + '/RSN_refs/' + NETWORK + '_coords.csv'
        df = pd.read_csv(load_path).ix[:, 0:4]
        i = 1
        coords = []
        labels = []
        for i in range(len(df)):
            print("ROI Reference #: " + str(i))
            x = int(df.ix[i, 1])
            y = int(df.ix[i, 2])
            z = int(df.ix[i, 3])
            print("X:" + str(x) + " Y:" + str(y) + " Z:" + str(z))
            coords.append((x, y, z))
            labels.append(i)
        print("\n")
        print(coords)
        print(labels)
        print("\n")
        print("-------------------")
        i + 1
        dir_path = os.path.dirname(os.path.realpath(func_file))

        ##Grow ROIs
        ##If masking, remove those coords that fall outside of the mask
        if mask != None:
            from nilearn import masking
            mask_data, _ = masking._load_mask_img(mask)
            mask_coords = list(zip(*np.where(mask_data != 0)))
            for coord in coords:
                if coord in mask_coords:
                    print('Removing coordinate: ' + str(coord) +
                          ' since it falls outside of network mask...')
                    coords.remove(coord)
        masker = input_data.NiftiSpheresMasker(seeds=coords,
                                               radius=float(node_size),
                                               allow_overlap=True,
                                               memory_level=5,
                                               memory='nilearn_cache',
                                               verbose=2)
        time_series = masker.fit_transform(func_file)
        for time_serie, label in zip(time_series.T, labels):
            plt.plot(time_serie, label=label)
        plt.title(NETWORK + ' Network Time Series')
        plt.xlabel('Scan Number')
        plt.ylabel('Normalized Signal')
        plt.legend()
        plt.tight_layout()
        out_path_fig = dir_path + '/' + ID + '_' + NETWORK + '_TS_plot.png'
        plt.savefig(out_path_fig)
        plt.close()
        connectivity_measure = ConnectivityMeasure(kind='correlation')
        correlation_matrix = connectivity_measure.fit_transform([time_series
                                                                 ])[0]
        plot_title = NETWORK + ' Network Time Series'
        plotting.plot_connectome(correlation_matrix, coords, title=plot_title)
        ##Display connectome with hemispheric projections.
        title = "Connectivity Projected on the " + NETWORK
        out_path_fig = dir_path + '/' + ID + '_' + NETWORK + '_connectome_plot.png'
        plotting.plot_connectome(correlation_matrix,
                                 coords,
                                 title=title,
                                 display_mode='lyrz',
                                 output_file=out_path_fig)
        time_series_path = dir_path + '/' + ID + '_' + NETWORK + '_ts.txt'
        np.savetxt(time_series_path, time_series, delimiter='\t')
        mx = genfromtxt(time_series_path, delimiter='')
    else:
        DR_st_1 = input_file
        dir_path = os.path.dirname(os.path.realpath(DR_st_1))
        mx = genfromtxt(DR_st_1, delimiter='')
    from sklearn.covariance import GraphLassoCV, ShrunkCovariance, graph_lasso
    estimator = GraphLassoCV()
    try:
        est = estimator.fit(mx)
    except:
        print(
            "Error: Lasso sparse matrix modeling failed. Check your input time-series data..."
        )

#        emp_cov = covariance.empirical_covariance(mx)
#        shrunk_cov = covariance.shrunk_covariance(emp_cov, shrinkage=0.8) # Set shrinkage closer to 1 for poorly-conditioned data
#
#        alphaRange = 10.0 ** np.arange(-8,0) # 1e-7 to 1e-1 by order of magnitude
#        for alpha in alphaRange:
#            try:
#                estimator = covariance.graph_lasso(shrunk_cov, alpha)
#                print("Calculated graph-lasso covariance matrix for alpha=%s"%alpha)
#            except FloatingPointError:
#                print("Failed at alpha=%s"%alpha)
#        estimator = ShrunkCovariance()
#        est = estimator.fit(mx)
    if NETWORK != None:
        est_path = dir_path + '/' + ID + '_' + NETWORK + '_est%s.txt' % (
            '_sps_inv' if sps_model else '')
    else:
        est_path = dir_path + '/' + ID + '_est%s.txt' % ('_sps_inv'
                                                         if sps_model else '')
    if sps_model == False:
        if NETWORK != None:
            np.savetxt(est_path, correlation_matrix, delimiter='\t')
        else:
            np.savetxt(est_path, correlation_matrix, delimiter='\t')
    elif sps_model == True:
        np.savetxt(est_path, estimator.precision_, delimiter='\t')
    return (mx, est_path)
Exemple #22
0
    def fit(self, imgs, y, data_train=None):
        """Fit the searchlight

        Parameters
        ----------
        img : Niimg-like object
            See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
            4D image.

        y : 1D array-like
            Target variable to predict. Must have exactly as many elements as
            3D images in img.
            
        data_train : np.array, optional
            Data to train on, if data for training is different from X.

        Attributes
        ----------
        `scores_` : numpy.ndarray
            search_light scores. Same shape as input parameter
            process_mask_img.
        """

        # Compute world coordinates of all in-mask voxels.
        mask, mask_affine = masking._load_mask_img(self.mask_img)
        mask_coords = np.where(mask != 0)
        mask_coords = np.asarray(mask_coords + (np.ones(len(mask_coords[0]),
                                                        dtype=np.int),))
        mask_coords = np.dot(mask_affine, mask_coords)[:3].T

        # Compute world coordinates of all in-process mask voxels
        if self.process_mask_img is None:
            process_mask = mask
            process_mask_coords = mask_coords
        else:
            process_mask, process_mask_affine = \
                masking._load_mask_img(self.process_mask_img)
            process_mask_coords = np.where(process_mask != 0)
            process_mask_coords = \
                np.asarray(process_mask_coords
                           + (np.ones(len(process_mask_coords[0]),
                                      dtype=np.int),))
            process_mask_coords = np.dot(process_mask_affine,
                                         process_mask_coords)[:3].T

        clf = neighbors.NearestNeighbors(radius=self.radius)
        A = clf.fit(mask_coords).radius_neighbors_graph(process_mask_coords)
        del process_mask_coords, mask_coords
        A = A.tolil()

        # scores is an 1D array of CV scores with length equals to the number
        # of voxels in processing mask (columns in process_mask)
        X = masking._apply_mask_fmri(imgs,
                nibabel.Nifti1Image(as_ndarray(mask, dtype=np.int8),
                                    mask_affine))

        estimator = self.estimator
        if isinstance(estimator, basestring):
            estimator = ESTIMATOR_CATALOG[estimator]()
        
        # From here starts Dima's modifications, added nii_optional argument
        # to .fit method
        if data_train is None:
            scores = search_light(X, y, estimator, A,
                                  self.scoring, self.cv, self.n_jobs,
                                  self.verbose)
        else:
            scores = search_light(X, y, estimator, A,
                                  self.scoring, self.cv, self.n_jobs,
                                  self.verbose, data_train)
            
        scores_3D = np.zeros(process_mask.shape)
        scores_3D[process_mask] = scores
        self.scores_ = scores_3D
        return self
    def compute_spheres_values(self, imgs):
        start_t = time.time()

        # Force to get a list of imgs even if only one is given
        imgs_to_check = [imgs] if not isinstance(imgs, list) else imgs

        # Load Nifti images
        ref_shape = imgs_to_check[0].dataobj.shape
        ref_affine = imgs_to_check[0].affine
        imgs = []
        for img in imgs_to_check:
            # check if image is 4D
            imgs.append(check_niimg_4d(img))

            # Check that all images have same number of volumes
            if ref_shape != img.dataobj.shape:
                raise ValueError("All fMRI image must have same shape")
            if np.array_equal(ref_affine, img.affine):
                warnings.warn("fMRI images do not have same affine")
        self.ref_img = imgs[0]

        # Compute world coordinates of the seeds
        process_mask_img = check_niimg_3d(self.process_mask_img)
        process_mask_img = image.resample_to_img(
            process_mask_img, imgs[0], interpolation='nearest'
        )
        self.process_mask_img = process_mask_img

        process_mask, process_mask_affine = masking._load_mask_img(
            process_mask_img
        )
        process_mask_coords = np.where(process_mask != 0)
        self.vx_mask_coords = process_mask_coords
        process_mask_coords = coord_transform(
            process_mask_coords[0], process_mask_coords[1],
            process_mask_coords[2], process_mask_affine)
        process_mask_coords = np.asarray(process_mask_coords).T

        if self.verbose:
            print("{} seeds found in the mask".format(len(process_mask_coords)))

        # Compute spheres
        _, A = _apply_mask_and_get_affinity(
            process_mask_coords, imgs[0], self.radius, True,
            mask_img=self.mask_img
        )

        # Number of runs: 1 4D fMRI image / run
        n_runs = len(imgs)

        # Number of spheres (or seed voxels)
        n_spheres = A.shape[0]

        # Number of volumes in each 4D fMRI image
        n_conditions = imgs[0].dataobj.shape[3]

        mask_img = check_niimg_3d(self.mask_img)
        mask_img = image.resample_img(
            mask_img, target_affine=imgs[0].affine,
            target_shape=imgs[0].shape[:3], interpolation='nearest'
        )

        masked_imgs_data = []
        for i_run, img in enumerate(imgs):
            masked_imgs_data.append(masking._apply_mask_fmri(img, mask_img))

        # Extract data of each sphere
        # X will be #spheres x #run x #conditions x #values
        X = []
        for i_sph in range(n_spheres):
            # Indexes of all voxels included in the current sphere
            sph_indexes = A.rows[i_sph]

            if len(sph_indexes) == 0:
                # Append when no data are available around the process voxel
                X.append(np.full((n_runs, n_conditions, 1), 0))
                print("Empty sphere")
            else:
                # Number of voxel in the current sphere
                n_values = len(sph_indexes)

                sub_X = np.empty((n_runs, n_conditions, n_values), dtype=object)
                for i_run, img in enumerate(imgs):
                    for i_cond in range(n_conditions):
                        sub_X[i_run, i_cond] = masked_imgs_data[i_run][i_cond][
                            sph_indexes]
                X.append(sub_X)

        if self.verbose:
            dt = time.time() - start_t
            print("Elapsed time to extract spheres values: {:.01f}s".format(dt))

        self.spheres_values = X
Exemple #24
0
def parcel_masker(roi, coords, parcel_list, labels, dir_path, ID,
                  perc_overlap):
    """
    Evaluate the affinity of any arbitrary list of parcel nodes for a user-specified ROI mask.

    Parameters
    ----------
    roi : str
        File path to binarized/boolean region-of-interest Nifti1Image file.
    coords : list
        List of (x, y, z) tuples in mm-space corresponding to a coordinate atlas used or
        which represent the center-of-mass of each parcellation node.
    parcel_list : list
        List of 3D boolean numpy arrays or binarized Nifti1Images corresponding to ROI masks.
    labels : list
        List of string labels corresponding to ROI nodes.
    dir_path : str
        Path to directory containing subject derivative data for given run.
    ID : str
        A subject id or other unique identifier.
    perc_overlap : float
        Value 0-1 indicating a threshold of spatial overlap to use as a spatial error cushion in the case of
        evaluating ROI-mask membership from a given list of parcel masks.

    Returns
    -------
    coords_adj : list
        Filtered list of (x, y, z) tuples in mm-space with a spatial affinity for the specified ROI mask.
    labels_adj : list
        Filtered list of string labels corresponding to ROI nodes with a spatial affinity for the specified ROI mask.
    parcel_list_adj : list
        Filtered list of 3D boolean numpy arrays or binarized Nifti1Images corresponding to ROI masks with a spatial
        affinity to the specified ROI mask.
    """
    from pynets.core import nodemaker
    from nilearn.image import resample_img
    from nilearn import masking
    import os.path as op

    mask_img = nib.load(roi)
    mask_aff = mask_img.affine
    mask_data, _ = masking._load_mask_img(roi)
    mask_img.uncache()

    i = 0
    indices = []
    for parcel in parcel_list:
        parcel_vol = np.zeros(mask_data.shape, dtype=bool)
        parcel_data_reshaped = np.asarray(
            resample_img(parcel,
                         target_affine=mask_aff,
                         target_shape=mask_data.shape).dataobj)
        parcel_vol[parcel_data_reshaped == 1] = 1

        # Count number of unique voxels where overlap of parcel and mask occurs
        overlap_count = len(
            np.unique(
                np.where((mask_data.astype('uint16') == 1)
                         & (parcel_vol.astype('uint16') == 1))))

        # Count number of total unique voxels within the parcel
        total_count = len(
            np.unique(np.where((parcel_vol.astype('uint16') == 1))))

        # Calculate % overlap
        try:
            overlap = float(overlap_count / total_count)
        except:
            print(
                f"\nWarning: No overlap of parcel {labels[i]} with roi mask!\n"
            )
            overlap = float(0)

        if overlap >= perc_overlap:
            print(
                f"{(100 * overlap):.2f}{'% of parcel '}{labels[i]}{' falls within mask...'}"
            )
        else:
            indices.append(i)
        i = i + 1

    labels_adj = list(labels)
    coords_adj = list(tuple(x) for x in coords)
    parcel_list_adj = parcel_list
    try:
        for ix in sorted(indices, reverse=True):
            print(f"{'Removing: '}{labels_adj[ix]}{' at '}{coords_adj[ix]}")
            del labels_adj[ix], coords_adj[ix], parcel_list_adj[ix]
    except RuntimeError:
        print(
            'ERROR: Restrictive masking. No parcels remain after masking with brain mask/roi...'
        )

    # Create a resampled 3D atlas that can be viewed alongside mask img for QA
    resampled_parcels_nii_path = f"{dir_path}/{ID}_parcels_resampled2roimask_{op.basename(roi).split('.')[0]}.nii.gz"
    resampled_parcels_map_nifti = resample_img(
        nodemaker.create_parcel_atlas(parcel_list_adj)[0],
        target_affine=mask_aff,
        target_shape=mask_data.shape,
        interpolation='nearest')
    nib.save(resampled_parcels_map_nifti, resampled_parcels_nii_path)
    resampled_parcels_map_nifti.uncache()
    if not coords_adj:
        raise ValueError(
            '\nERROR: ROI mask was likely too restrictive and yielded < 2 remaining parcels'
        )

    return coords_adj, labels_adj, parcel_list_adj
Exemple #25
0
 def apply_mask(self, series, mask_img):
     mask_img = _utils.check_niimg_3d(mask_img)
     mask, mask_affine = masking._load_mask_img(mask_img)
     mask_img = image.new_img_like(mask_img, mask, mask_affine)
     mask_data = _utils.as_ndarray(mask_img.get_data(), dtype=np.bool)
     return series[mask_data].T
Exemple #26
0
def import_mat_func(input_file, ID, atlas_select, NETWORK, pynets_dir, node_size, mask, thr):
    if '.nii' in input_file and NETWORK == None:
        func_file=input_file
        dir_path = os.path.dirname(os.path.realpath(func_file))
        atlas = getattr(datasets, 'fetch_%s' % atlas_select)()
        atlas_name = atlas['description'].splitlines()[0]
        print("\n")
        print(atlas_name + ' comes with {0}.'.format(atlas.keys()))
        print("\n")
        coords = np.vstack((atlas.rois['x'], atlas.rois['y'], atlas.rois['z'])).T
        print("\n")
        print('Stacked atlas coordinates in array of shape {0}.'.format(coords.shape))
        print("\n")
        if mask is not None:
            from nilearn import masking
            mask_data, _ = masking._load_mask_img(mask)
            mask_coords = list(zip(*np.where(mask_data != 0)))
            for coord in coords:
                if tuple(coord) not in mask_coords:
                    print('Removing coordinate: ' + str(tuple(coord)) + ' since it falls outside of network mask...')
                    ix = np.where(coords == coord)[0][0]
                    coords = np.delete(coords, ix, axis=0)
                    print(str(len(coords)))
        spheres_masker = input_data.NiftiSpheresMasker(seeds=coords, radius=float(node_size), memory='nilearn_cache', memory_level=5, verbose=2, standardize=True)
        time_series = spheres_masker.fit_transform(func_file)
        correlation_measure = ConnectivityMeasure(kind='correlation')
        correlation_matrix = correlation_measure.fit_transform([time_series])[0]
        print("\n")
        print('Time series has {0} samples'.format(time_series.shape[0]))
        print("\n")
        plt.imshow(correlation_matrix, vmin=-1., vmax=1., cmap='RdBu_r', interpolation='nearest')
        plt.colorbar()
        plt.title(atlas_name + ' correlation matrix')
        out_path_fig=dir_path + '/' + ID + '_' + atlas_name + '_adj_mat_cov.png'
        plt.savefig(out_path_fig)
        plt.close()
        # Tweak edge_threshold to keep only the strongest connections.
        atlast_graph_title = atlas_name + ' correlation graph'
        if mask is None:
            atlast_graph_title = atlas_name + ' correlation graph'
        else:
            atlast_graph_title = atlas_name + ' Masked Nodes'
        edge_threshold = str(float(thr)*100) +'%'
        plotting.plot_connectome(correlation_matrix, coords, title=atlast_graph_title, edge_threshold=edge_threshold, node_size=20, colorbar=True)
        out_path_fig=dir_path + '/' + ID + '_' + atlas_name + '_connectome_viz.png'
        plt.savefig(out_path_fig)
        plt.close()
        time_series_path = dir_path + '/' + ID + '_ts.txt'
        np.savetxt(time_series_path, time_series, delimiter='\t')
        mx = genfromtxt(time_series_path, delimiter='')

    elif '.nii' in input_file and NETWORK != None:
        func_file=input_file

        ##Reference RSN list
    	load_path= pynets_dir + '/RSN_refs/' + NETWORK + '_coords.csv'
    	df = pd.read_csv(load_path).ix[:,0:4]
    	i=1
    	coords = []
    	labels = []
    	for i in range(len(df)):
      	    print("ROI Reference #: " + str(i))
      	    x = int(df.ix[i,1])
      	    y = int(df.ix[i,2])
      	    z = int(df.ix[i,3])
      	    print("X:" + str(x) + " Y:" + str(y) + " Z:" + str(z))
      	    coords.append((x, y, z))
      	    labels.append(i)
      	print("\n")
     	print(coords)
      	print(labels)
      	print("\n")
      	print("-------------------")
      	i + 1
        dir_path = os.path.dirname(os.path.realpath(func_file))

        ##Grow ROIs
        ##If masking, remove those coords that fall outside of the mask
        if mask != None:
            from nilearn import masking
            mask_data, _ = masking._load_mask_img(mask)
            mask_coords = list(zip(*np.where(mask_data != 0)))
            for coord in coords:
                if coord in mask_coords:
                    print('Removing coordinate: ' + str(coord) + ' since it falls outside of network mask...')
                    coords.remove(coord)
        masker = input_data.NiftiSpheresMasker(
            seeds=coords, radius=float(node_size), allow_overlap=True, memory_level=5,
            memory='nilearn_cache', verbose=2, standardize=True)
        time_series = masker.fit_transform(func_file)
        for time_serie, label in zip(time_series.T, labels):
            plt.plot(time_serie, label=label)
        plt.title(NETWORK + ' Network Time Series')
        plt.xlabel('Scan Number')
        plt.ylabel('Normalized Signal')
        plt.legend()
        plt.tight_layout()
        out_path_fig=dir_path + '/' + ID + '_' + NETWORK + '_TS_plot.png'
        plt.savefig(out_path_fig)
        plt.close()
        connectivity_measure = ConnectivityMeasure(kind='partial correlation')
        partial_correlation_matrix = connectivity_measure.fit_transform([time_series])[0]
        plot_title = NETWORK + ' Network Time Series'
        plotting.plot_connectome(partial_correlation_matrix, coords,
                                 title=plot_title)
        # Display connectome with hemispheric projections.
        title = "Connectivity Projected on the " + NETWORK
        out_path_fig=dir_path + '/' + ID + '_' + NETWORK + '_connectome_plot.png'
        plotting.plot_connectome(partial_correlation_matrix, coords, title=title,
        display_mode='lyrz', output_file=out_path_fig)
        time_series_path = dir_path + '/' + ID + '_' + NETWORK + '_ts.txt'
        np.savetxt(time_series_path, time_series, delimiter='\t')
        mx = genfromtxt(time_series_path, delimiter='')
    else:
        DR_st_1=input_file
        dir_path = os.path.dirname(os.path.realpath(DR_st_1))
        mx = genfromtxt(DR_st_1, delimiter='')
    from sklearn.covariance import GraphLassoCV, ShrunkCovariance, graph_lasso
    estimator = GraphLassoCV()
    try:
        est = estimator.fit(mx)
    except:
#        print("WARNING: Lasso Cross-Validation Failed. Using Shrunk Covariance instead...")
#        emp_cov = covariance.empirical_covariance(mx)
#        shrunk_cov = covariance.shrunk_covariance(emp_cov, shrinkage=0.8) # Set shrinkage closer to 1 for poorly-conditioned data
#
#        alphaRange = 10.0 ** np.arange(-8,0) # 1e-7 to 1e-1 by order of magnitude
#        for alpha in alphaRange:
#            try:
#                estimator = covariance.graph_lasso(shrunk_cov, alpha)
#                print("Calculated graph-lasso covariance matrix for alpha=%s"%alpha)
#            except FloatingPointError:
#                print("Failed at alpha=%s"%alpha)
        estimator = ShrunkCovariance()
        est = estimator.fit(mx)
    if NETWORK != None:
        est_path_cov = dir_path + '/' + ID + '_' + NETWORK + '_est_cov.txt'
        est_path_sps_inv_cov = dir_path + '/' + ID + '_' + NETWORK + '_est_sps_inv_cov.txt'
    else:
        est_path_cov = dir_path + '/' + ID + '_est_cov.txt'
        est_path_sps_inv_cov = dir_path + '/' + ID + '_est_sps_inv_cov.txt'
    np.savetxt(est_path_cov, estimator.covariance_, delimiter='\t')
    np.savetxt(est_path_sps_inv_cov, estimator.precision_, delimiter='\t')
    return(mx, est_path_cov, est_path_sps_inv_cov)
Exemple #27
0
def coords_masker(roi, coords, labels, error):
    """
    Evaluate the affinity of any arbitrary list of coordinate nodes for a user-specified ROI mask.

    Parameters
    ----------
    roi : str
        File path to binarized/boolean region-of-interest Nifti1Image file.
    coords : list
        List of (x, y, z) tuples in mm-space corresponding to a coordinate atlas used or
        which represent the center-of-mass of each parcellation node.
    labels : list
        List of string labels corresponding to ROI nodes.
    error : int
        Rounded euclidean distance, in units of voxel number, to use as a spatial error cushion in the case of
        evaluating the spatial affinity of a given list of coordinates to the given ROI mask.

    Returns
    -------
    coords : list
        Filtered list of (x, y, z) tuples in mm-space with a spatial affinity for the specified ROI mask.
    labels : list
        Filtered list of string labels corresponding to ROI nodes with a spatial affinity for the specified ROI mask.
    """
    from nilearn import masking
    from pynets.core.nodemaker import mmToVox

    mask_data, mask_aff = masking._load_mask_img(roi)
    x_vox = np.diagonal(mask_aff[:3, 0:3])[0]
    y_vox = np.diagonal(mask_aff[:3, 0:3])[1]
    z_vox = np.diagonal(mask_aff[:3, 0:3])[2]

    #    mask_coords = list(zip(*np.where(mask_data == True)))
    coords_vox = []
    for i in coords:
        coords_vox.append(mmToVox(mask_aff, i))
    coords_vox = list(
        tuple(map(lambda y: isinstance(y, float) and int(round(y, 0)), x))
        for x in coords_vox)
    #coords_vox = list(set(list(tuple(x) for x in coords_vox)))
    bad_coords = []
    for coord_vox in coords_vox:
        sphere_vol = np.zeros(mask_data.shape, dtype=bool)
        sphere_vol[tuple(coord_vox)] = 1
        if (mask_data & sphere_vol).any():
            print(f"{coord_vox}{' falls within mask...'}")
            continue
        inds = get_sphere(coord_vox, error, (np.abs(x_vox), y_vox, z_vox),
                          mask_data.shape)
        sphere_vol[tuple(inds.T)] = 1
        if (mask_data & sphere_vol).any():
            print(
                f"{coord_vox}{' is within a + or - '}{float(error):.2f}{' mm neighborhood...'}"
            )
            continue
        bad_coords.append(coord_vox)

    bad_coords = [x for x in bad_coords if x is not None]
    indices = []
    for bad_coords in bad_coords:
        indices.append(coords_vox.index(bad_coords))

    labels = list(labels)
    coords = list(tuple(x) for x in coords)
    try:
        for ix in sorted(indices, reverse=True):
            print(f"{'Removing: '}{labels[ix]}{' at '}{coords[ix]}")
            del labels[ix], coords[ix]

    except RuntimeError:
        print(
            'ERROR: Restrictive masking. No coords remain after masking with brain mask/roi...'
        )

    if len(coords) <= 1:
        raise ValueError(
            '\nERROR: ROI mask was likely too restrictive and yielded < 2 remaining coords'
        )

    return coords, labels
Exemple #28
0
def grow_nodes(bedpostx_dir, coords, node_size, parc, parcel_list,
               net_parcels_map_nifti, network):
    from nilearn import masking
    import nipype.interfaces.fsl as fsl
    import nipype.pipeline.engine as pe
    import glob
    ####Custom inputs####
    try:
        FSLDIR = os.environ['FSLDIR']
    except NameError:
        print('FSLDIR environment variable not set!')
    nodif_brain_mask_path = bedpostx_dir + '/nodif_brain_mask.nii.gz'
    input_MNI = FSLDIR + '/data/standard/MNI152_T1_1mm_brain.nii.gz'
    volumes_dir = bedpostx_dir + '/volumes'

    ####Custom inputs####

    def save_parcel_vols(bedpostx_dir, parcel_list, net_parcels_map_nifti):
        import os
        import time
        if net_parcels_map_nifti:
            net_parcels_map_file = bedpostx_dir + '/net_parcels_map_nifti.nii.gz'
            nib.save(net_parcels_map_nifti, net_parcels_map_file)
        volumes_dir = bedpostx_dir + '/volumes'
        if not os.path.exists(volumes_dir):
            os.mkdir(volumes_dir)
        num_vols = len(parcel_list)
        i = 0
        for vol in parcel_list:
            out_path = volumes_dir + '/region_' + str(i) + '.nii.gz'
            nib.save(vol, out_path)
            i = i + 1
        num_vols_pres = float(len(next(os.walk(volumes_dir))[2]))
        while num_vols_pres < float(num_vols):
            time.sleep(1)
            num_vols_pres = float(len(next(os.walk(volumes_dir))[2]))
        return

    save_parcel_vols(bedpostx_dir, parcel_list, net_parcels_map_nifti)

    ##Delete any existing roi spheres
    del_files_spheres = glob.glob(volumes_dir + '/roi_sphere*')
    try:
        for i in del_files_spheres:
            os.remove(i)
    except:
        pass

    del_files_parcels = glob.glob(volumes_dir + '/roi_parcel*')
    try:
        for i in del_files_parcels:
            os.remove(i)
    except:
        pass

    del_files_points = glob.glob(volumes_dir + '/roi_point*')
    try:
        for i in del_files_points:
            os.remove(i)
    except:
        pass

    if parc == False:

        x_vox = np.diagonal(
            masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[0]
        y_vox = np.diagonal(
            masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[1]
        z_vox = np.diagonal(
            masking._load_mask_img(nodif_brain_mask_path)[1][:3, 0:3])[2]

        def mmToVox(mmcoords):
            voxcoords = ['', '', '']
            voxcoords[0] = int((round(int(mmcoords[0]) / x_vox)) + 45)
            voxcoords[1] = int((round(int(mmcoords[1]) / y_vox)) + 63)
            voxcoords[2] = int((round(int(mmcoords[2]) / z_vox)) + 36)
            return voxcoords

        ##Convert coords back to voxels
        coords_vox = []
        for coord in coords:
            coords_vox.append(mmToVox(coord))
        coords = list(tuple(x) for x in coords_vox)

        j = 0
        for i in coords:
            ##Grow spheres at ROI
            X = coords[j][0]
            Y = coords[j][1]
            Z = coords[j][2]
            out_file1 = volumes_dir + '/roi_point_' + str(j) + '.nii.gz'
            args = '-mul 0 -add 1 -roi ' + str(X) + ' 1 ' + str(
                Y) + ' 1 ' + str(Z) + ' 1 0 1'
            maths = fsl.ImageMaths(in_file=input_MNI,
                                   op_string=args,
                                   out_file=out_file1)
            os.system(maths.cmdline + ' -odt float')

            out_file2 = volumes_dir + '/roi_sphere_' + str(j) + '.nii.gz'
            args = '-kernel sphere ' + str(node_size) + ' -fmean -bin'
            maths = fsl.ImageMaths(in_file=out_file1,
                                   op_string=args,
                                   out_file=out_file2)
            os.system(maths.cmdline + ' -odt float')

            ##Map ROIs from Standard Space to diffusion Space:
            ##Applying xfm and input matrix to transform ROI's between diff and MNI using FLIRT,
            flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                            name='coregister')
            flirt.inputs.reference = nodif_brain_mask_path
            flirt.inputs.in_file = out_file2
            out_file_diff = out_file2.split('.nii')[0] + '_diff.nii.gz'
            flirt.inputs.out_file = out_file_diff
            flirt.inputs.apply_xfm = True
            flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat'
            flirt.run()
            j = j + 1

        del_files_points = glob.glob(volumes_dir + '/roi_point*')
        try:
            for i in del_files_points:
                os.remove(i)
        except:
            pass
    else:
        i = 0
        for parcel in os.listdir(volumes_dir):
            out_file = volumes_dir + '/roi_parcel_' + str(i) + '_diff.nii.gz'
            flirt = pe.Node(interface=fsl.FLIRT(cost_func='mutualinfo'),
                            name='coregister')
            flirt.inputs.reference = nodif_brain_mask_path
            flirt.inputs.in_file = volumes_dir + '/' + parcel
            out_file_diff = out_file.split('.nii')[0] + '_diff.nii.gz'
            flirt.inputs.out_file = out_file_diff
            flirt.inputs.apply_xfm = True
            flirt.inputs.in_matrix_file = bedpostx_dir + '/xfms/MNI2diff.mat'
            flirt.run()
            i = i + 1

    def create_seed_mask_file(bedpostx_dir, network):
        if network:
            probtrackx_output_dir_path = bedpostx_dir + '/probtrackx_' + network
        else:
            probtrackx_output_dir_path = bedpostx_dir + '/probtrackx_Whole_brain'

        if not os.path.exists(probtrackx_output_dir_path):
            os.makedirs(probtrackx_output_dir_path)

        seed_files = glob.glob(bedpostx_dir + '/volumes/*diff.nii.gz')
        seeds_text = probtrackx_output_dir_path + '/masks.txt'
        try:
            os.remove(seeds_text)
        except OSError:
            pass
        seeds_file_list = []
        for seed_file in seed_files:
            seeds_file_list.append(seed_file)
        f = open(seeds_text, 'w')
        l1 = map(lambda x: x + '\n', seeds_file_list)
        f.writelines(l1)
        f.close()
        return (seeds_text, probtrackx_output_dir_path)

    [seeds_text, probtrackx_output_dir_path
     ] = create_seed_mask_file(bedpostx_dir, network)

    return (seeds_text, probtrackx_output_dir_path)
Exemple #29
0
def parcel_masker(roi, coords, parcel_list, label_names, dir_path, ID, mask,
                  perc_overlap):
    from pynets import nodemaker
    from nilearn.image import resample_img
    from nilearn import masking
    import os.path as op

    if mask and roi == mask:
        perc_overlap = 0.9

    mask_img = nib.load(roi)
    mask_data, _ = masking._load_mask_img(roi)

    i = 0
    indices = []
    for parcel in parcel_list:
        parcel_vol = np.zeros(mask_data.shape, dtype=bool)
        parcel_data_reshaped = resample_img(
            parcel,
            target_affine=mask_img.affine,
            target_shape=mask_data.shape).get_fdata()
        parcel_vol[parcel_data_reshaped == 1] = 1
        # Count number of unique voxels where overlap of parcel and mask occurs
        overlap_count = len(
            np.unique(
                np.where((mask_data.astype('uint8') == 1)
                         & (parcel_vol.astype('uint8') == 1))))
        # Count number of total unique voxels within the parcel
        total_count = len(
            np.unique(np.where((parcel_vol.astype('uint8') == 1))))
        # Calculate % overlap
        try:
            overlap = float(overlap_count / total_count)
        except RuntimeWarning:
            print('\nWarning: No overlap with roi mask!\n')
            overlap = float(0)

        if overlap >= perc_overlap:
            print("%.2f%s%s%s" % (100 * overlap, '% of parcel ',
                                  label_names[i], ' falls within roi mask...'))
        else:
            indices.append(i)
        i = i + 1

    label_names_adj = list(label_names)
    coords_adj = list(tuple(x) for x in coords)
    parcel_list_adj = parcel_list
    try:
        for ix in sorted(indices, reverse=True):
            print("%s%s%s%s" %
                  ('Removing: ', label_names_adj[ix], ' at ', coords_adj[ix]))
            label_names_adj.pop(ix)
            coords_adj.pop(ix)
            parcel_list_adj.pop(ix)
    except RuntimeError:
        print(
            'ERROR: Restrictive masking. No parcels remain after masking with brain mask/roi...'
        )

    # Create a resampled 3D atlas that can be viewed alongside mask img for QA
    resampled_parcels_nii_path = "%s%s%s%s%s%s" % (
        dir_path, '/', ID, '_parcels_resampled2roimask_',
        op.basename(roi).split('.')[0], '.nii.gz')
    resampled_parcels_atlas, _ = nodemaker.create_parcel_atlas(parcel_list_adj)
    resampled_parcels_map_nifti = resample_img(resampled_parcels_atlas,
                                               target_affine=mask_img.affine,
                                               target_shape=mask_data.shape)
    nib.save(resampled_parcels_map_nifti, resampled_parcels_nii_path)
    mask_img.uncache()
    resampled_parcels_map_nifti.uncache()
    if not coords_adj:
        raise ValueError(
            '\nERROR: ROI mask was likely too restrictive and yielded < 2 remaining parcels'
        )

    return coords_adj, label_names_adj, parcel_list_adj
def _apply_mask_and_get_affinity(seeds,
                                 niimg,
                                 radius,
                                 allow_overlap,
                                 mask_img=None):
    seeds = list(seeds)
    affine = niimg.affine

    # Compute world coordinates of all in-mask voxels.

    if mask_img is not None:
        mask_img = check_niimg_3d(mask_img)
        mask_img = image.resample_img(mask_img,
                                      target_affine=affine,
                                      target_shape=niimg.shape[:3],
                                      interpolation='nearest')
        mask, _ = masking._load_mask_img(mask_img)
        mask_coords = list(zip(*np.where(mask != 0)))

        X = masking._apply_mask_fmri(niimg, mask_img)
    else:
        if np.isnan(np.sum(_safe_get_data(niimg))):
            warnings.warn('The imgs you have fed into fit_transform() contains'
                          ' NaN values which will be converted to zeroes ')
            X = _safe_get_data(niimg, True).reshape([-1, niimg.shape[3]]).T
        else:
            X = _safe_get_data(niimg).reshape([-1, niimg.shape[3]]).T
        mask_coords = list(np.ndindex(niimg.shape[:3]))

    # For each seed, get coordinates of nearest voxel
    nearests = []
    for sx, sy, sz in seeds:
        nearest = np.round(coord_transform(sx, sy, sz, np.linalg.inv(affine)))
        nearest = nearest.astype(int)
        nearest = (nearest[0], nearest[1], nearest[2])
        try:
            nearests.append(mask_coords.index(nearest))
        except ValueError:
            nearests.append(None)

    mask_coords = np.asarray(list(zip(*mask_coords)))
    mask_coords = coord_transform(mask_coords[0], mask_coords[1],
                                  mask_coords[2], affine)
    mask_coords = np.asarray(mask_coords).T

    clf = neighbors.NearestNeighbors(radius=radius)
    A = clf.fit(mask_coords).radius_neighbors_graph(seeds)
    A = A.tolil()
    for i, nearest in enumerate(nearests):
        if nearest is None:
            continue
        A[i, nearest] = True

    # Include the voxel containing the seed itself if not masked
    mask_coords = mask_coords.astype(int).tolist()
    for i, seed in enumerate(seeds):
        try:
            A[i, mask_coords.index(seed)] = True
        except ValueError:
            # seed is not in the mask
            pass

    if not allow_overlap:
        if np.any(A.sum(axis=0) >= 2):
            raise ValueError('Overlap detected between spheres')

    return X, A