示例#1
0
def create_intersect_mask(show_list, meanepi, savingpath_percentile, layer,
                          mask_dict, intersection):

    #We create the mask of intersection for all subject for each number of subvectors & each layer
    for number in show_list:
        mask_list = mask_dict[number]
        #in the doc, threshold = 1 will make the function compute the intersection of masks
        #threshold = 0 will compute the union of all mask in mask list
        if intersection == True:
            mask_inter = masking.intersect_masks(mask_list,
                                                 threshold=1,
                                                 connected=False)
        else:
            mask_inter = masking.intersect_masks(mask_list,
                                                 threshold=0,
                                                 connected=False)

        #We save the mask
        if intersection == True:
            mask_path = os.path.join(
                savingpath_percentile, 'mask_intersection_layer_' +
                str(layer) + '_number_' + str(number) + '.nii.gz')
        elif union == True:
            mask_path = os.path.join(
                savingpath_percentile, 'mask_union_layer_' + str(layer) +
                'number' + str(number) + '.nii.gz')
        mask_inter.to_filename(mask_path)

        #we plot the results
        plotting.plot_roi(mask_inter, title='roi', bg_img=meanepi)
示例#2
0
    def create_clean_mask(self, num_std_dev=1.5):
        """
        Create a subject-refined version of the clustering mask.
        """
        import os
        from pynets.core import utils
        from nilearn.masking import intersect_masks
        from nilearn.image import index_img, math_img, resample_img
        mask_name = os.path.basename(self.clust_mask).split('.nii')[0]
        self.atlas = "%s%s%s%s%s" % (mask_name, '_', self.clust_type, '_k', str(self.k))
        print("%s%s%s%s%s%s%s" % ('\nCreating atlas using ', self.clust_type, ' at cluster level ', str(self.k),
                                  ' for ', str(self.atlas), '...\n'))
        self._dir_path = utils.do_dir_path(self.atlas, self.func_file)
        self.uatlas = "%s%s%s%s%s%s%s%s" % (self._dir_path, '/', mask_name, '_clust-', self.clust_type, '_k',
                                            str(self.k), '.nii.gz')

        # Load clustering mask
        self._func_img.set_data_dtype(np.float32)
        func_vol_img = index_img(self._func_img, 1)
        func_vol_img.set_data_dtype(np.uint16)
        clust_mask_res_img = resample_img(nib.load(self.clust_mask), target_affine=func_vol_img.affine,
                                          target_shape=func_vol_img.shape, interpolation='nearest')
        clust_mask_res_img.set_data_dtype(np.uint16)
        func_data = np.asarray(func_vol_img.dataobj).astype('float32')
        func_int_thr = np.round(np.mean(func_data[func_data > 0]) - np.std(func_data[func_data > 0]) * num_std_dev, 3)
        if self.mask is not None:
            self._mask_img = nib.load(self.mask)
            self._mask_img.set_data_dtype(np.uint16)
            mask_res_img = resample_img(self._mask_img, target_affine=func_vol_img.affine,
                                        target_shape=func_vol_img.shape, interpolation='nearest')
            mask_res_img.set_data_dtype(np.uint16)
            self._clust_mask_corr_img = intersect_masks([math_img('img > ' + str(func_int_thr), img=func_vol_img),
                                                         math_img('img > 0.01', img=clust_mask_res_img),
                                                         math_img('img > 0.01', img=mask_res_img)],
                                                        threshold=1, connected=False)
            self._clust_mask_corr_img.set_data_dtype(np.uint16)
            self._mask_img.uncache()
            mask_res_img.uncache()
        else:
            self._clust_mask_corr_img = intersect_masks([math_img('img > ' + str(func_int_thr), img=func_vol_img),
                                                         math_img('img > 0.01', img=clust_mask_res_img)],
                                                        threshold=1, connected=False)
            self._clust_mask_corr_img.set_data_dtype(np.uint16)
        nib.save(self._clust_mask_corr_img, "%s%s%s%s" % (self._dir_path, '/', mask_name, '.nii.gz'))

        del func_data
        func_vol_img.uncache()
        clust_mask_res_img.uncache()

        return self.atlas
示例#3
0
def create_intersect(subject_list):

    fig = plt.figure(figsize=(20, 15))
    mask_list = []
    i = 1

    for subject in tqdm(subject_list):

        if subject < 10:
            subject_str = '0' + str(subject)
        else:
            subject_str = str(subject)

        filename_mask = "/home/brain/datasets/SherlockMerlin_ds001110/sub-" + subject_str + "/func/sub-" + subject_str + "_task-SherlockMovie_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz"
        filename_irm = "/home/brain/datasets/SherlockMerlin_ds001110/sub-" + subject_str + "/func/sub-" + subject_str + "_task-SherlockMovie_bold_space-MNI152NLin2009cAsym_preproc.nii.gz"

        meanepi = (index_img(filename_irm, 22))
        mask_list.append(filename_mask)
        ax = plt.subplot(3, 6, i)
        plotting.plot_roi(filename_mask, bg_img=meanepi, axes=ax, figure=fig)
        i += 1

    mask_inter = masking.intersect_masks(mask_list,
                                         threshold=1,
                                         connected=False)
    ax = plt.subplot(3, 6, i)
    plotting.plot_roi(mask_inter, bg_img=meanepi, axes=ax, figure=fig)
    saving_path = os.path.join(savingpath, 'mask_inter.nii.gz')
    mask_inter.to_filename(saving_path)
    return mask_inter
示例#4
0
def collapse_mask(mask, auto_label=True, custom_mask=None):
    """collapse separate masks into one mask with multiple integers
        overlapping areas are ignored

    Args:
        mask: nibabel or Brain_Data instance
        custom_mask: nibabel instance or string to file path; optional

    Returns:
        out: Brain_Data instance of a mask with different integers indicating
            different masks

    """

    from nltools.data import Brain_Data

    if not isinstance(mask, Brain_Data):
        if isinstance(mask, nib.Nifti1Image):
            mask = Brain_Data(mask, mask=custom_mask)
        else:
            raise ValueError("Make sure mask is a nibabel or Brain_Data "
                             "instance.")

    if len(mask.shape()) > 1:
        if len(mask) > 1:
            out = mask.empty()

            # Create list of masks and find any overlaps
            m_list = []
            for x in range(len(mask)):
                m_list.append(mask[x].to_nifti())
            intersect = intersect_masks(m_list, threshold=1, connected=False)
            intersect = Brain_Data(
                nib.Nifti1Image(np.abs(intersect.get_data() - 1),
                                intersect.get_affine()),
                mask=custom_mask,
            )

            merge = []
            if auto_label:
                # Combine all masks into sequential order
                # ignoring any areas of overlap
                for i in range(len(m_list)):
                    merge.append(
                        np.multiply(
                            Brain_Data(m_list[i], mask=custom_mask).data,
                            intersect.data) * (i + 1))
                out.data = np.sum(np.array(merge).T, 1).astype(int)
            else:
                # Collapse masks using value as label
                for i in range(len(m_list)):
                    merge.append(
                        np.multiply(
                            Brain_Data(m_list[i], mask=custom_mask).data,
                            intersect.data))
                out.data = np.sum(np.array(merge).T, 1)
            return out
    else:
        warnings.warn("Doesn't need to be collapased")
示例#5
0
    def similarity(self, image, method='correlation'):
        """ Calculate similarity of Brain_Data() instance with single Brain_Data or Nibabel image

            Args:
                image: Brain_Data or Nibabel instance of weight map

            Returns:
                pexp: Outputs a vector of pattern expression values

        """

        if not isinstance(image, Brain_Data):
            if isinstance(image, nib.Nifti1Image):
                image = Brain_Data(image)
            else:
                raise ValueError(
                    "Image is not a Brain_Data or nibabel instance")
        dim = image.shape()

        # Check to make sure masks are the same for each dataset and if not create a union mask
        # This might be handy code for a new Brain_Data method
        if np.sum(self.nifti_masker.mask_img.get_data() == 1) != np.sum(
                image.nifti_masker.mask_img.get_data() == 1):
            new_mask = intersect_masks(
                [self.nifti_masker.mask_img, image.nifti_masker.mask_img],
                threshold=1,
                connected=False)
            new_nifti_masker = NiftiMasker(mask_img=new_mask)
            data2 = new_nifti_masker.fit_transform(self.to_nifti())
            image2 = new_nifti_masker.fit_transform(image.to_nifti())
        else:
            data2 = self.data
            image2 = image.data

        # Calculate pattern expression
        if method is 'dot_product':
            if len(image2.shape) > 1:
                if image2.shape[0] > 1:
                    pexp = []
                    for i in range(image2.shape[0]):
                        pexp.append(np.dot(data2, image2[i, :]))
                    pexp = np.array(pexp)
                else:
                    pexp = np.dot(data2, image2)
            else:
                pexp = np.dot(data2, image2)
        elif method is 'correlation':
            if len(image2.shape) > 1:
                if image2.shape[0] > 1:
                    pexp = []
                    for i in range(image2.shape[0]):
                        pexp.append(pearson(image2[i, :], data2))
                    pexp = np.array(pexp)
                else:
                    pexp = pearson(image2, data2)
            else:
                pexp = pearson(image2, data2)
        return pexp
示例#6
0
def _intersect_clustering_mask(clustering, mask):
    "Take 3D Niimg clustering and bigger mask, output reduced mask"
    dat = clustering.get_data()
    new_ = np.zeros_like(dat)
    new_[dat > 0] = 1
    clustering_mask = new_img_like(clustering, new_)
    return intersect_masks([clustering_mask, mask],
                           threshold=1,
                           connected=True)
示例#7
0
    def similarity(self, image, method='correlation'):
        """ Calculate similarity of Brain_Data() instance with single Brain_Data or Nibabel image

            Args:
                self: Brain_Data instance of data to be applied
                image: Brain_Data or Nibabel instance of weight map

            Returns:
                pexp: Outputs a vector of pattern expression values

        """

        if not isinstance(image, Brain_Data):
            if isinstance(image, nib.Nifti1Image):
                image = Brain_Data(image)
            else:
                raise ValueError("Image is not a Brain_Data or nibabel instance")
        dim = image.shape()

        # Check to make sure masks are the same for each dataset and if not create a union mask
        # This might be handy code for a new Brain_Data method
        if np.sum(self.nifti_masker.mask_img.get_data()==1)!=np.sum(image.nifti_masker.mask_img.get_data()==1):
            new_mask = intersect_masks([self.nifti_masker.mask_img, image.nifti_masker.mask_img], threshold=1, connected=False)
            new_nifti_masker = NiftiMasker(mask_img=new_mask)
            data2 = new_nifti_masker.fit_transform(self.to_nifti())
            image2 = new_nifti_masker.fit_transform(image.to_nifti())
        else:
            data2 = self.data
            image2 = image.data


        # Calculate pattern expression
        if method is 'dot_product':
            if len(image2.shape) > 1:
                if image2.shape[0]>1:
                    pexp = []
                    for i in range(image2.shape[0]):
                        pexp.append(np.dot(data2, image2[i,:]))
                    pexp = np.array(pexp)
                else:
                    pexp = np.dot(data2, image2)
            else:
                pexp = np.dot(data2, image2)
        elif method is 'correlation':
            if len(image2.shape) > 1:
                if image2.shape[0]>1:
                    pexp = []
                    for i in range(image2.shape[0]):
                        pexp.append(pearson(image2[i,:], data2))
                    pexp = np.array(pexp)
                else:
                    pexp = pearson(image2, data2)
            else:
                pexp = pearson(image2, data2)
        return pexp
示例#8
0
def mask_roi(dir_path, roi, mask, img_file):
    """
    Create derivative ROI based on intersection of roi and brain mask.

    Parameters
    ----------
    dir_path : str
        Path to directory containing subject derivative data for given run.
    roi : str
        File path to binarized/boolean region-of-interest Nifti1Image file.
    mask : str
        Path to binarized/boolean brain mask Nifti1Image file.
    img_file : str
        File path to Nifti1Image to use to generate an epi-mask.

    Returns
    -------
    roi : str
        File path to binarized/boolean region-of-interest Nifti1Image file, reduced to the spatial intersection with
        the input brain mask.
    """
    import os.path as op
    from nilearn import masking
    from nilearn.masking import intersect_masks
    from nilearn.image import math_img, resample_img

    img_mask_path = f"{dir_path}/{op.basename(img_file).split('.')[0]}_mask.nii.gz"
    nib.save(masking.compute_epi_mask(img_file), img_mask_path)

    if roi and mask:
        print("Refining ROI...")
        _mask_img = nib.load(img_mask_path)
        _roi_img = nib.load(roi)
        roi_res_img = resample_img(
            _roi_img,
            target_affine=_mask_img.affine,
            target_shape=_mask_img.shape,
            interpolation="nearest",
        )
        masked_roi_img = intersect_masks(
            [
                math_img("img > 0.0", img=_mask_img),
                math_img("img > 0.0", img=roi_res_img),
            ],
            threshold=1,
            connected=False,
        )

        roi_red_path = f"{dir_path}/{op.basename(roi).split('.')[0]}_mask.nii.gz"
        nib.save(masked_roi_img, roi_red_path)
        roi = roi_red_path

    return roi
示例#9
0
    def multivariate_similarity(self, images, method='ols'):
        """ Predict spatial distribution of Brain_Data() instance from linear combination of other Brain_Data() instances or Nibabel images

            Args:
                self: Brain_Data instance of data to be applied
                images: Brain_Data instance of weight map

            Returns:
                out: dictionary of regression statistics in Brain_Data instances {'beta','t','p','df','residual'}

        """
        ## Notes:  Should add ridge, and lasso, elastic net options options

        if len(self.shape()) > 1:
            raise ValueError("This method can only decompose a single brain image.")

        if not isinstance(images, Brain_Data):
            raise ValueError("Images are not a Brain_Data instance")
        dim = images.shape()

        # Check to make sure masks are the same for each dataset and if not create a union mask
        # This might be handy code for a new Brain_Data method
        if np.sum(self.nifti_masker.mask_img.get_data()==1)!=np.sum(images.nifti_masker.mask_img.get_data()==1):
            new_mask = intersect_masks([self.nifti_masker.mask_img, images.nifti_masker.mask_img], threshold=1, connected=False)
            new_nifti_masker = NiftiMasker(mask_img=new_mask)
            data2 = new_nifti_masker.fit_transform(self.to_nifti())
            image2 = new_nifti_masker.fit_transform(images.to_nifti())
        else:
            data2 = self.data
            image2 = images.data

        # Add intercept and transpose
        image2 = np.vstack((np.ones(image2.shape[1]),image2)).T

        # Calculate pattern expression
        if method is 'ols':
            b = np.dot(np.linalg.pinv(image2), data2)
            res = data2 - np.dot(image2,b)
            sigma = np.std(res,axis=0)
            stderr = np.dot(np.matrix(np.diagonal(np.linalg.inv(np.dot(image2.T,image2)))**.5).T,np.matrix(sigma))
            t_out = b /stderr
            df = image2.shape[0]-image2.shape[1]
            p = 2*(1-t.cdf(np.abs(t_out),df))

        return {'beta':b, 't':t_out, 'p':p, 'df':df, 'sigma':sigma, 'residual':res}
示例#10
0
def fit_subject(sub, space):

    funcs = sorted(
        glob(
            f'../derivatives/fmriprep/{sub}/ses-*/func/*task-flocBLOCKED*space-{space}*desc-preproc_bold.nii.gz'
        ))
    masks = [f.replace('preproc_bold', 'brain_mask') for f in funcs]
    mask = masking.intersect_masks(masks, threshold=0.9)

    conf_files = [
        f.split('space')[0] + 'desc-confounds_regressors.tsv' for f in funcs
    ]
    ccols = ['trans_x', 'trans_y', 'trans_z', 'rot_x', 'rot_y', 'rot_z']
    confs = [pd.read_csv(c, sep='\t').loc[:, ccols] for c in conf_files]
    events = [
        f"../{sub}/ses{f.split('ses')[1].split('func')[0]}/func/{op.basename(f).split('desc')[0]}events.tsv"
        for f in conf_files
    ]

    flm = FirstLevelModel(t_r=0.7,
                          slice_time_ref=0.5,
                          drift_model='cosine',
                          high_pass=0.01,
                          mask_img=mask,
                          smoothing_fwhm=3.5,
                          noise_model='ols',
                          verbose=True)
    flm.fit(funcs, events, confs)
    con_defs = [('face', '4*face - object - character - body - place'),
                ('place', '4*place - object - face - character - body'),
                ('body', '4*body - object - face - character - place'),
                ('character', '4*character - object - face - place - body')]
    for name, df in con_defs:
        roi = flm.compute_contrast(df)
        f_out = f'../derivatives/floc/{sub}/rois/{sub}_task-flocBLOCKED_space-{space}_desc-{name}_zscore.nii.gz'
        if not op.isdir(op.dirname(f_out)):
            os.makedirs(op.dirname(f_out))

        roi.to_filename(f_out)
def load_and_append_periodic_runs_single_subject(run1_boldfile, run2_boldfile,
                                                 run1_maskfile, run2_maskfile,
                                                 zscorewithinrun=True,
                                                 connected_clusters=False):
    """
    For a given subject, load the data from the first two runs (periodic stimulation),
    mask with a union of the run masks
    and z score if desired.
    """
    # get union mask
    print('intersecting masks :', '\t', run1_maskfile, '\t', 'and', '\t',run2_maskfile)
    unionmask = intersect_masks([run1_maskfile, run2_maskfile], threshold=0, connected=connected_clusters)
    # load data, apply mask
    run1_arr = apply_mask(load_img(run1_boldfile), mask_img=unionmask).T
    run2_arr = apply_mask(load_img(run2_boldfile), mask_img=unionmask).T
    # zscore within run if desired
    if zscorewithinrun:
        for runimg in [run1_arr, run2_arr]:
            runimg = zscore(np.nan_to_num(runimg), axis=1)
    # concatenate runs
    sub_arr = np.concatenate((run1_arr, run2_arr), axis=1)
    print('finished loading masks: ', run1_maskfile, ' and ', run2_maskfile)
    return sub_arr, unionmask
示例#12
0
def test_intersect_masks_filename():
    # Create dummy masks
    mask_a = np.zeros((4, 4, 1), dtype=np.bool)
    mask_a[2:4, 2:4] = 1
    mask_a_img = Nifti1Image(mask_a.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+

    mask_b = np.zeros((4, 4, 1), dtype=np.bool)
    mask_b[1:3, 1:3] = 1
    mask_b_img = Nifti1Image(mask_b.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+

    with write_tmp_imgs(mask_a_img, mask_b_img, create_files=True)\
            as filenames:
        mask_ab = np.zeros((4, 4, 1), dtype=np.bool)
        mask_ab[2, 2] = 1
        mask_ab_ = intersect_masks(filenames, threshold=1.)
        assert_array_equal(mask_ab, get_data(mask_ab_))
示例#13
0
def test_intersect_masks_filename():
    # Create dummy masks
    mask_a = np.zeros((4, 4, 1), dtype=np.bool)
    mask_a[2:4, 2:4] = 1
    mask_a_img = Nifti1Image(mask_a.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+

    mask_b = np.zeros((4, 4, 1), dtype=np.bool)
    mask_b[1:3, 1:3] = 1
    mask_b_img = Nifti1Image(mask_b.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+

    with write_tmp_imgs(mask_a_img, mask_b_img, create_files=True)\
                     as filenames:
        mask_ab = np.zeros((4, 4, 1), dtype=np.bool)
        mask_ab[2, 2] = 1
        mask_ab_ = intersect_masks(filenames, threshold=1.)
        assert_array_equal(mask_ab, mask_ab_.get_data())
示例#14
0
    struct_file = os.path.join(analysis_dir, subject, 'anat',
                               '%s_desc-preproc_T1w.nii.gz' % subject)
    struct_mask_file = os.path.join(analysis_dir, subject, 'anat',
                                    '%s_desc-brain_mask.nii.gz' % subject)

    bold_mask_file = glob(
        os.path.join(
            analysis_dir, subject, 'ses-%d' % session, 'func',
            '%s_ses-%d_task-sequence_run-%d_space-T1w_desc-brain_mask.nii.gz' %
            (subject, session, run)))
    bold_file = path
    struct_img = resample_to_img(struct_file, bold_file)
    struct_mask_img = resample_to_img(struct_mask_file, bold_mask_file)
    bold_img = mean_img(bold_file)
    bold_mask_img = load_img(bold_mask_file)
    mask = intersect_masks((struct_mask_img, bold_mask_img))
    masker = NiftiMasker(mask)
    x = masker.fit_transform(struct_img).ravel()
    y = masker.fit_transform(bold_img).ravel()
    ind = np.logical_and(x > 0, y > 0)
    x = x[ind]
    y = y[ind]
    MI = mutual_info_regression(x.reshape(-1, 1), y)[0]
    cor = pearsonr(x, y)[0]
    res = [subject, session, run, MI, cor]
    print(res)
    results.append(res)
    #plot_epi(struct_img, cut_coords = (0, 0, 0))
    #plot_epi(bold_img, cut_coords = (0, 0, 0))
    #plot_epi(mask, cut_coords = (0, 0, 0))
    #sns.scatterplot(np.log(x), np.log(y))
def group_one_sample_t_test(masks, effects_maps, contrasts, output_dir,
                            start_time=base_reporter.pretty_time(),
                            **kwargs):
    """
    Runs a one-sample t-test procedure for group analysis. Here, we are
    for each experimental condition, only interested refuting the null
    hypothesis H0: "The average effect accross the subjects is zero!"

    Parameters
    ----------
    masks: list of strings or nibabel image objects
        subject masks, one per subject

    effects_maps: list of dicts of lists
        effects maps from subject-level GLM; each entry is a dictionary;
        each entry (indexed by condition id) of this dictionary is the
        filename (or correspinding nibabel image object) for the effects
        maps for that condition (aka contrast),for that subject

    contrasts: dictionary of array_likes
        contrasts vectors, indexed by condition id

    kwargs: dict_like
        kwargs for plot_stats_map API
    """

    # make output directory
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    assert len(masks) == len(effects_maps), (len(masks), len(effects_maps))

    # compute group mask
    group_mask = intersect_masks(masks)

    # construct design matrix (only one covariate, namely the "mean effect")
    design_matrix = np.ones(len(effects_maps)
                            )[:, np.newaxis]  # only the intercept

    group_level_z_maps = {}
    group_level_t_maps = {}
    for contrast_id in contrasts:
        print "\tcontrast id: %s" % contrast_id

        # effects maps will be the input to the second level GLM
        first_level_image = nibabel.concat_images(
            [x[contrast_id] for x in effects_maps])

        # fit 2nd level GLM for given contrast
        group_model = FirstLevelGLM(first_level_image,
                                      design_matrix, group_mask)
        group_model.fit(do_scaling=False, model='ols')

        # specify and estimate the contrast
        contrast_val = np.array(([[1.]])
                                )  # the only possible contrast !
        z_map, t_map = group_model.contrast(
            contrast_val, con_id='one_sample %s' % contrast_id, output_z=True,
            output_stat=True)

        # save map
        for map_type, map_img in zip(["z", "t"], [z_map, t_map]):
            map_dir = os.path.join(output_dir, '%s_maps' % map_type)
            if not os.path.exists(map_dir):
                os.makedirs(map_dir)
            map_path = os.path.join(map_dir, 'group_level_%s.nii.gz' % (
                    contrast_id))
            print "\t\tWriting %s ..." % map_path
            nibabel.save(map_img, map_path)
            if map_type == "z":
                group_level_z_maps[contrast_id] = map_path
            elif map_type == "t":
                group_level_z_maps[contrast_id] = map_path

    # do stats report
    stats_report_filename = os.path.join(output_dir, "report_stats.html")
    generate_subject_stats_report(stats_report_filename, contrasts,
                                  group_level_z_maps, group_mask,
                                  start_time=start_time,
                                  **kwargs)

    print "\r\nStatistic report written to %s\r\n" % (
        stats_report_filename)

    return group_level_z_maps
示例#16
0
def test_intersect_masks():
    """ Test the intersect_masks function
    """

    # Create dummy masks
    mask_a = np.zeros((4, 4, 1), dtype=np.bool)
    mask_a[2:4, 2:4] = 1
    mask_a_img = Nifti1Image(mask_a.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+

    mask_b = np.zeros((4, 4, 1), dtype=np.bool)
    mask_b[1:3, 1:3] = 1
    mask_b_img = Nifti1Image(mask_b.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+

    mask_c = np.zeros((4, 4, 1), dtype=np.bool)
    mask_c[:, 2] = 1
    mask_c[0, 0] = 1
    mask_c_img = Nifti1Image(mask_c.astype(int), np.eye(4))

    # +---+---+---+---+
    # | X |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+

    mask_ab = np.zeros((4, 4, 1), dtype=np.bool)
    mask_ab[2, 2] = 1
    mask_ab_ = intersect_masks([mask_a_img, mask_b_img], threshold=1.)
    assert_array_equal(mask_ab, mask_ab_.get_data())

    mask_abc = mask_a + mask_b + mask_c
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=0.,
                                connected=False)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc[0, 0] = 0
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=0.)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc = mask_ab
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=1.)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc[1, 2] = 1
    mask_abc[3, 2] = 1
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img])
    assert_array_equal(mask_abc, mask_abc_.get_data())
示例#17
0
def create_bestvoxels_mask(roi_img, localizer_img, toppercentile=25):
    """ select voxels within roi_img having the largest values in localizer_img """
    masked_data = apply_mask(localizer_img, roi_img)
    threshold = scoreatpercentile(masked_data, 100 - toppercentile)
    mask = binarize_img(localizer_img, threshold)
    return intersect_masks((roi_img, mask), threshold=1)
示例#18
0
def create_localizer_mask(roi_img, localizer_img, loc_threshold):
    """ select voxels within roi_img that have a value above loc_threshold in localizer_img """
    locmask = binarize_img(localizer_img, loc_threshold)
    return intersect_masks((roi_img, locmask), threshold=1)
示例#19
0
def prep_tissues(t1_mask, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, cmc_step_size=0.2):
    """
    Estimate a tissue classifier for tractography.

    Parameters
    ----------
    t1_mask : str
        File path to a T1w mask.
    gm_in_dwi : str
        File path to grey-matter tissue segmentation Nifti1Image.
    vent_csf_in_dwi : str
        File path to ventricular CSF tissue segmentation Nifti1Image.
    wm_in_dwi : str
        File path to white-matter tissue segmentation Nifti1Image.
    tiss_class : str
        Tissue classification method.
    cmc_step_size : float
        Step size from CMC tissue classification method.

    Returns
    -------
    tiss_classifier : obj
        Tissue classifier object.

    References
    ----------
    .. [1] Zhang, Y., Brady, M. and Smith, S. Segmentation of Brain MR Images
      Through a Hidden Markov Random Field Model and the Expectation-Maximization
      Algorithm IEEE Transactions on Medical Imaging, 20(1): 45-56, 2001
    .. [2] Avants, B. B., Tustison, N. J., Wu, J., Cook, P. A. and Gee, J. C.
      An open source multivariate framework for n-tissue segmentation with
      evaluation on public data. Neuroinformatics, 9(4): 381-400, 2011.

    """
    try:
        import cPickle as pickle
    except ImportError:
        import _pickle as pickle
    from dipy.tracking.stopping_criterion import ActStoppingCriterion, CmcStoppingCriterion, BinaryStoppingCriterion
    from nilearn.masking import intersect_masks
    from nilearn.image import math_img

    # Loads mask
    mask_img = nib.load(t1_mask)
    # Load tissue maps and prepare tissue classifier
    wm_img = nib.load(wm_in_dwi)
    gm_img = nib.load(gm_in_dwi)
    gm_mask_data = np.asarray(gm_img.dataobj)
    wm_mask_data = np.asarray(wm_img.dataobj)
    vent_csf_in_dwi_data = np.asarray(nib.load(vent_csf_in_dwi).dataobj)
    if tiss_class == 'act':
        background = np.ones(mask_img.shape)
        background[(gm_mask_data + wm_mask_data + vent_csf_in_dwi_data) > 0] = 0
        gm_mask_data[background > 0] = 1
        tiss_classifier = ActStoppingCriterion(gm_mask_data, vent_csf_in_dwi_data)
        del background
    elif tiss_class == 'bin':
        tiss_classifier = BinaryStoppingCriterion(np.asarray(intersect_masks([math_img('img > 0.0', img=mask_img),
                                                                              math_img('img > 0.0', img=wm_img)],
                                                                             threshold=1, connected=False).dataobj))
    elif tiss_class == 'cmc':
        voxel_size = np.average(mask_img.header['pixdim'][1:4])
        tiss_classifier = CmcStoppingCriterion.from_pve(wm_mask_data, gm_mask_data, vent_csf_in_dwi_data,
                                                        step_size=cmc_step_size, average_voxel_size=voxel_size)
    elif tiss_class == 'wb':
        tiss_classifier = BinaryStoppingCriterion(np.asarray(mask_img.dataobj).astype('bool'))
    else:
        raise ValueError('Tissue classifier cannot be none.')

    del gm_mask_data, wm_mask_data, vent_csf_in_dwi_data
    mask_img.uncache()
    gm_img.uncache()
    wm_img.uncache()

    return tiss_classifier
示例#20
0
def track_ensemble(target_samples, atlas_data_wm_gm_int, labels_im_file,
                   recon_path, sphere, directget, curv_thr_list, step_list,
                   track_type, maxcrossing, roi_neighborhood_tol, min_length,
                   waymask, B0_mask, t1w2dwi, gm_in_dwi, vent_csf_in_dwi,
                   wm_in_dwi, tiss_class, cache_dir):
    """
    Perform native-space ensemble tractography, restricted to a vector of ROI
    masks.

    target_samples : int
        Total number of streamline samples specified to generate streams.
    atlas_data_wm_gm_int : str
        File path to Nifti1Image in T1w-warped native diffusion space,
        restricted to wm-gm interface.
    parcels : list
        List of 3D boolean numpy arrays of atlas parcellation ROI masks from a
        Nifti1Image in T1w-warped native diffusion space.
    recon_path : str
        File path to diffusion reconstruction model.
    tiss_classifier : str
        Tissue classification method.
    sphere : obj
        DiPy object for modeling diffusion directions on a sphere.
    directget : str
        The statistical approach to tracking. Options are: det (deterministic),
        closest (clos), and prob (probabilistic).
    curv_thr_list : list
        List of integer curvature thresholds used to perform ensemble tracking.
    step_list : list
        List of float step-sizes used to perform ensemble tracking.
    track_type : str
        Tracking algorithm used (e.g. 'local' or 'particle').
    maxcrossing : int
        Maximum number if diffusion directions that can be assumed per voxel
        while tracking.
    roi_neighborhood_tol : float
        Distance (in the units of the streamlines, usually mm). If any
        coordinate in the streamline is within this distance from the center
        of any voxel in the ROI, the filtering criterion is set to True for
        this streamline, otherwise False. Defaults to the distance between
        the center of each voxel and the corner of the voxel.
    min_length : int
        Minimum fiber length threshold in mm.
    waymask_data : ndarray
        Tractography constraint mask array in native diffusion space.
    B0_mask_data : ndarray
        B0 brain mask data.
    n_seeds_per_iter : int
        Number of seeds from which to initiate tracking for each unique
        ensemble combination. By default this is set to 250.
    max_length : int
        Maximum number of steps to restrict tracking.
    particle_count
        pft_back_tracking_dist : float
        Distance in mm to back track before starting the particle filtering
        tractography. The total particle filtering tractography distance is
        equal to back_tracking_dist + front_tracking_dist. By default this is
        set to 2 mm.
    pft_front_tracking_dist : float
        Distance in mm to run the particle filtering tractography after the
        the back track distance. The total particle filtering tractography
        distance is equal to back_tracking_dist + front_tracking_dist. By
        default this is set to 1 mm.
    particle_count : int
        Number of particles to use in the particle filter.
    min_separation_angle : float
        The minimum angle between directions [0, 90].

    Returns
    -------
    streamlines : ArraySequence
        DiPy list/array-like object of streamline points from tractography.

    References
    ----------
    .. [1] Takemura, H., Caiafa, C. F., Wandell, B. A., & Pestilli, F. (2016).
      Ensemble Tractography. PLoS Computational Biology.
      https://doi.org/10.1371/journal.pcbi.1004692

    """
    import os
    import gc
    import time
    import warnings
    from joblib import Parallel, delayed
    import itertools
    from pynets.dmri.track import run_tracking
    from colorama import Fore, Style
    from pynets.dmri.utils import generate_sl
    from nibabel.streamlines.array_sequence import concatenate, ArraySequence
    from pynets.core.utils import save_3d_to_4d
    from nilearn.masking import intersect_masks
    from nilearn.image import math_img
    from pynets.core.utils import load_runconfig
    warnings.filterwarnings("ignore")

    tmp_files_dir = f"{cache_dir}/tmp_files"
    joblib_dir = f"{cache_dir}/joblib_tracking"
    os.makedirs(tmp_files_dir, exist_ok=True)
    os.makedirs(joblib_dir, exist_ok=True)

    hardcoded_params = load_runconfig()
    nthreads = hardcoded_params["nthreads"][0]
    n_seeds_per_iter = \
        hardcoded_params['tracking']["n_seeds_per_iter"][0]
    max_length = \
        hardcoded_params['tracking']["max_length"][0]
    pft_back_tracking_dist = \
        hardcoded_params['tracking']["pft_back_tracking_dist"][0]
    pft_front_tracking_dist = \
        hardcoded_params['tracking']["pft_front_tracking_dist"][0]
    particle_count = \
        hardcoded_params['tracking']["particle_count"][0]
    min_separation_angle = \
        hardcoded_params['tracking']["min_separation_angle"][0]
    min_streams = \
        hardcoded_params['tracking']["min_streams"][0]
    timeout = hardcoded_params['tracking']["track_timeout"][0]

    all_combs = list(itertools.product(step_list, curv_thr_list))

    # Construct seeding mask
    seeding_mask = f"{tmp_files_dir}/seeding_mask.nii.gz"
    if waymask is not None and os.path.isfile(waymask):
        waymask_img = math_img("img > 0.0075", img=nib.load(waymask))
        waymask_img.to_filename(waymask)
        atlas_data_wm_gm_int_img = intersect_masks(
            [
                waymask_img,
                math_img("img > 0.001", img=nib.load(atlas_data_wm_gm_int)),
                math_img("img > 0.001", img=nib.load(labels_im_file))
            ],
            threshold=1,
            connected=False,
        )
        nib.save(atlas_data_wm_gm_int_img, seeding_mask)
    else:
        atlas_data_wm_gm_int_img = intersect_masks(
            [
                math_img("img > 0.001", img=nib.load(atlas_data_wm_gm_int)),
                math_img("img > 0.001", img=nib.load(labels_im_file))
            ],
            threshold=1,
            connected=False,
        )
        nib.save(atlas_data_wm_gm_int_img, seeding_mask)

    tissues4d = save_3d_to_4d([
        B0_mask, labels_im_file, seeding_mask, t1w2dwi, gm_in_dwi,
        vent_csf_in_dwi, wm_in_dwi
    ])

    # Commence Ensemble Tractography
    start = time.time()
    stream_counter = 0

    all_streams = []
    ix = 0

    try:
        while float(stream_counter) < float(target_samples) and \
                float(ix) < 0.50*float(len(all_combs)):
            with Parallel(n_jobs=nthreads,
                          backend='loky',
                          mmap_mode='r+',
                          temp_folder=joblib_dir,
                          verbose=0,
                          timeout=timeout) as parallel:
                out_streams = parallel(
                    delayed(run_tracking)
                    (i, recon_path, n_seeds_per_iter, directget, maxcrossing,
                     max_length, pft_back_tracking_dist,
                     pft_front_tracking_dist, particle_count,
                     roi_neighborhood_tol, waymask, min_length, track_type,
                     min_separation_angle, sphere, tiss_class, tissues4d,
                     tmp_files_dir) for i in all_combs)

                out_streams = [
                    i for i in out_streams if i is not None
                    and i is not ArraySequence() and len(i) > 0
                ]

                if len(out_streams) > 1:
                    out_streams = concatenate(out_streams, axis=0)

                if len(out_streams) < min_streams:
                    ix += 2
                    print(f"Fewer than {min_streams} streamlines tracked "
                          f"on last iteration with cache directory: "
                          f"{cache_dir}. Loosening tolerance and "
                          f"anatomical constraints. Check {tissues4d} or "
                          f"{recon_path} for errors...")
                    # if track_type != 'particle':
                    #     tiss_class = 'wb'
                    roi_neighborhood_tol = float(roi_neighborhood_tol) * 1.25
                    # min_length = float(min_length) * 0.9875
                    continue
                else:
                    ix -= 1

                # Append streamline generators to prevent exponential growth
                # in memory consumption
                all_streams.extend([generate_sl(i) for i in out_streams])
                stream_counter += len(out_streams)
                del out_streams

                print("%s%s%s%s" % (
                    "\nCumulative Streamline Count: ",
                    Fore.CYAN,
                    stream_counter,
                    "\n",
                ))
                gc.collect()
                print(Style.RESET_ALL)
        os.system(f"rm -rf {joblib_dir}/*")
    except BaseException:
        os.system(f"rm -rf {tmp_files_dir} &")
        return None

    if ix >= 0.75*len(all_combs) and \
            float(stream_counter) < float(target_samples):
        print(f"Tractography failed. >{len(all_combs)} consecutive sampling "
              f"iterations with few streamlines.")
        os.system(f"rm -rf {tmp_files_dir} &")
        return None
    else:
        os.system(f"rm -rf {tmp_files_dir} &")
        print("Tracking Complete: ", str(time.time() - start))

    del parallel, all_combs
    gc.collect()

    if stream_counter != 0:
        print('Generating final ArraySequence...')
        return ArraySequence([ArraySequence(i) for i in all_streams])
    else:
        print('No streamlines generated!')
        return None
示例#21
0
subs = sorted([os.path.basename(s) for s in glob('../derivatives/fmriprep/sub-??')])
R = []
for sub in subs:
    funcs = sorted(glob(f'../derivatives/fmriprep/{sub}/ses-*/func/*task-face*MNI*desc-preproc_bold.nii.gz'))
    confs = sorted(glob(f'../derivatives/fmriprep/{sub}/ses-*/func/*task-face*desc-confounds_regressors.tsv'))
    masks = [f.replace('preproc_bold', 'brain_mask') for f in funcs]
    
    events = sorted(glob(f'../{sub}/ses-*/func/*task-face*events.tsv'))
    cols = ['rot_x', 'rot_y', 'rot_z', 'trans_x', 'trans_y', 'trans_z']
    confs = [pd.read_csv(c, sep='\t').loc[:, cols] for c in confs]
    events = [pd.read_csv(e, sep='\t').drop('trial_type', axis=1).rename({'expression': 'trial_type'}, axis=1)
              for e in events]
    events = [e.loc[~e['trial_type'].isna(), :] for e in events]
    print(events)
    mask = masking.intersect_masks(masks, threshold=1)
    flm = FirstLevelModel(
        t_r=0.7,
        slice_time_ref=0.5,
        hrf_model='glover',
        drift_model='cosine',
        high_pass=0.01,
        noise_model='ols',
        mask_img=mask,
        verbose=True,
        smoothing_fwhm=4,
        n_jobs=10
    )
    flm.fit(funcs, confounds=confs, events=events)
    con = flm.compute_contrast('smiling - neutral')
    #roi = image.resample_to_img(roi, con, interpolation='nearest')
示例#22
0
def test_intersect_masks():
    """ Test the intersect_masks function
    """

    # Create dummy masks
    mask_a = np.zeros((4, 4, 1), dtype=np.bool)
    mask_a[2:4, 2:4] = 1
    mask_a_img = Nifti1Image(mask_a.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+

    mask_b = np.zeros((4, 4, 1), dtype=np.bool)
    mask_b[1:3, 1:3] = 1
    mask_b_img = Nifti1Image(mask_b.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+

    mask_c = np.zeros((4, 4, 1), dtype=np.bool)
    mask_c[:, 2] = 1
    mask_c[0, 0] = 1
    mask_c_img = Nifti1Image(mask_c.astype(int), np.eye(4))

    # +---+---+---+---+
    # | X |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+

    mask_ab = np.zeros((4, 4, 1), dtype=np.bool)
    mask_ab[2, 2] = 1
    mask_ab_ = intersect_masks([mask_a_img, mask_b_img], threshold=1.)
    assert_array_equal(mask_ab, mask_ab_.get_data())
    # Test intersect mask images with '>f8'. This function uses
    # largest_connected_component to check if intersect_masks passes with
    # connected=True (which is by default)
    mask_a_img_change_dtype = Nifti1Image(mask_a_img.get_data().astype('>f8'),
                                          affine=mask_a_img.get_affine())
    mask_b_img_change_dtype = Nifti1Image(mask_b_img.get_data().astype('>f8'),
                                          affine=mask_b_img.get_affine())
    mask_ab_change_type = intersect_masks([mask_a_img_change_dtype,
                                           mask_b_img_change_dtype],
                                          threshold=1.)
    assert_array_equal(mask_ab, mask_ab_change_type.get_data())

    mask_abc = mask_a + mask_b + mask_c
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=0., connected=False)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc[0, 0] = 0
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=0.)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc = mask_ab
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=1.)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc[1, 2] = 1
    mask_abc[3, 2] = 1
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img])
    assert_array_equal(mask_abc, mask_abc_.get_data())
示例#23
0
文件: interfaces.py 项目: dPys/PyNets
    def prepare_inputs(self, num_std_dev=1.5):
        """Helper function to creating temporary nii's and prepare inputs from
         time-series extraction"""
        import os.path as op
        import nibabel as nib
        from nilearn.image import math_img, index_img, resample_to_img
        from nilearn.masking import intersect_masks

        if not op.isfile(self.func_file):
            raise FileNotFoundError(
                "\nFunctional data input not found! Check that the"
                " file(s) specified with the -i "
                "flag exist(s)")

        if self.conf:
            if not op.isfile(self.conf):
                raise FileNotFoundError(
                    "\nConfound regressor file not found! Check "
                    "that the file(s) specified with the -conf flag "
                    "exist(s)")

        self._func_img = nib.load(self.func_file)
        self._func_img.set_data_dtype(np.float32)

        func_vol_img = index_img(self._func_img, 1)
        func_vol_img.set_data_dtype(np.uint16)
        func_data = np.asarray(func_vol_img.dataobj, dtype=np.float32)
        func_int_thr = np.round(
            np.mean(func_data[func_data > 0]) -
            np.std(func_data[func_data > 0]) * num_std_dev,
            3,
        )
        hdr = self._func_img.header

        self._net_parcels_map_nifti = nib.load(self.net_parcels_nii_path,
                                               mmap=True)
        self._net_parcels_map_nifti.set_data_dtype(np.int16)

        if self.hpass:
            if len(hdr.get_zooms()) == 4:
                self._t_r = float(hdr.get_zooms()[-1])
            else:
                self._t_r = None
        else:
            self._t_r = None

        if self.hpass is not None:
            if float(self.hpass) > 0:
                self.hpass = float(self.hpass)
                self._detrending = False
            else:
                self.hpass = None
                self._detrending = True
        else:
            self.hpass = None
            self._detrending = True

        if self.mask is not None:
            # Ensure mask is binary and contains only voxels that also
            # overlap with the parcellation and first functional volume
            self._mask_img = intersect_masks(
                [
                    math_img(f"img > {func_int_thr}", img=func_vol_img),
                    math_img("img > 0.0001",
                             img=resample_to_img(nib.load(self.mask),
                                                 func_vol_img))
                ],
                threshold=1,
                connected=False,
            )
            self._mask_img.set_data_dtype(np.uint16)
        else:
            print("Warning: Proceeding to extract time-series without a "
                  "brain mask...")
            self._mask_img = None

        if self.smooth:
            if float(self.smooth) > 0:
                print(f"Smoothing FWHM: {self.smooth} mm\n")

        if self.hpass:
            print(f"Applying high-pass filter: {self.hpass} Hz\n")

        return
heschl_mask = "/data2/azubaidi/ForrestGumpHearingLoss/BIDS_ForrGump/" \
              + "derivatives/fmriprep/ROIs/HeschisGyrus/mni_Heschl_ROI.nii.gz"

base_path = '/data2/azubaidi/ForrestGumpHearingLoss/BIDS_ForrGump/derivatives/encoding_results/temporal_lobe_mask' \
            '/lagging0to-15.3_permutation_train_only/sub-10/acq-N4/'
scores_path = base_path + 'sub-10_task-aomovie_acq-N4_desc-scores.nii.gz'
pval_path = base_path + 'sub-10_task-aomovie_acq-N4_desc-permutationpval.pkl'
masks = base_path + 'sub-10_task-aomovie_acq-N4_desc-masks.pkl'
perm_all_path = base_path + 'sub-10_task-aomovie_acq-N4_desc-permutations.pkl'

mask = joblib.load(masks)[0]
roi_mask = resample_img(heschl_mask,
                        mask._affine,
                        mask.shape,
                        interpolation='nearest')
roi_mask = intersect_masks([mask, roi_mask])
mean_scores = mean_img(scores_path)
perm_all = joblib.load(perm_all_path)
pval = joblib.load(pval_path)
pval = unmask(pval, mask)
pval = apply_mask(pval, roi_mask)
n_permutations = perm_all.shape[1]
thresh = 1.0 / n_permutations
pval_mask = pval > thresh
pval[pval_mask] = 0
pvals = unmask(pval, roi_mask)
selected_r_scores = apply_mask(mean_scores, roi_mask)
selected_r_scores[pval_mask] = 0
selected_r_scores = unmask(selected_r_scores, roi_mask)

display = plotting.plot_glass_brain(pvals,
示例#25
0
def test_intersect_masks():
    """ Test the intersect_masks function
    """

    # Create dummy masks
    mask_a = np.zeros((4, 4, 1), dtype=np.bool)
    mask_a[2:4, 2:4] = 1
    mask_a_img = Nifti1Image(mask_a.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+

    mask_b = np.zeros((4, 4, 1), dtype=np.bool)
    mask_b[1:3, 1:3] = 1
    mask_b_img = Nifti1Image(mask_b.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+

    mask_c = np.zeros((4, 4, 1), dtype=np.bool)
    mask_c[:, 2] = 1
    mask_c[0, 0] = 1
    mask_c_img = Nifti1Image(mask_c.astype(int), np.eye(4))

    # +---+---+---+---+
    # | X |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+

    mask_ab = np.zeros((4, 4, 1), dtype=np.bool)
    mask_ab[2, 2] = 1
    mask_ab_ = intersect_masks([mask_a_img, mask_b_img], threshold=1.)
    assert_array_equal(mask_ab, mask_ab_.get_data())

    mask_abc = mask_a + mask_b + mask_c
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=0., connected=False)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc[0, 0] = 0
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=0.)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc = mask_ab
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=1.)
    assert_array_equal(mask_abc, mask_abc_.get_data())

    mask_abc[1, 2] = 1
    mask_abc[3, 2] = 1
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img])
    assert_array_equal(mask_abc, mask_abc_.get_data())
示例#26
0
def preprocess_funcs(ddict, cfg, logger):
    """ Preprocesses a set of functional files (either volumetric nifti or
    surface gifti); masking, high-pass filter (DCT) and normalization only.
    """

    if 'fs' not in cfg['space']:  # no need for mask in surface files
        if ddict['gm_prob'] is None:  # use functional brain masks
            logger.info("Creating mask by intersection of fMRI masks")
            fmasks = [
                f.replace('desc-preproc_bold', 'desc-brain_mask')
                for f in ddict['funcs']
            ]
            mask = masking.intersect_masks(fmasks, threshold=0.8)
        else:
            # Using provided masks
            logger.info("Creating mask using GM probability map")

            # Downsample (necessary by default)
            gm_prob = image.resample_to_img(ddict['gm_prob'],
                                            ddict['funcs'][0])
            gm_prob_data = gm_prob.get_fdata()

            # Threshold
            gm_prob_data = (gm_prob_data >= cfg['gm_thresh']).astype(int)
            mask = nib.Nifti1Image(gm_prob_data, affine=gm_prob.affine)
    else:
        # If fsaverage{5,6} space, don't use any mask
        mask = None

    ddict['mask'] = mask
    logger.info("Starting preprocessing of functional data ... ")

    out = Parallel(n_jobs=cfg['n_cpus'])(
        delayed(_run_func_parallel)(ddict, cfg, run, func, logger)
        for run, func in enumerate(
            tqdm_ctm(ddict['funcs'], tdesc('Preprocessing funcs:'))))

    # Concatenate data in time dimension
    data = np.vstack([d[0] for d in out])
    run_idx = np.concatenate([r[1] for r in out]).astype(int)

    # Save functional data, ALWAYS as npy file (saves time/disk space)
    save_data(data,
              cfg,
              ddict,
              par_dir='preproc',
              run=None,
              desc='preproc',
              dtype='bold')

    # Save run_idx
    out_dir = op.join(cfg['save_dir'], 'preproc')
    np.save(op.join(out_dir, f"task-{cfg['c_task']}_run_idx.npy"), run_idx)

    # Extract TRs
    ddict['trs'] = [o[2] for o in out]
    logger.info(f"Found the following TRs across runs: {ddict['trs']}")

    # Save mask
    save_data(ddict['mask'],
              cfg,
              ddict,
              par_dir='preproc',
              run=None,
              desc='preproc',
              dtype='mask',
              nii=True)

    # Store in data-dictionary (ddict)
    ddict['preproc_func'] = data
    ddict['run_idx'] = run_idx
    return ddict
示例#27
0
    # Create a precise brain mask, by combining RATS and SPM
    sammba_brain_mask_file = os.path.join(
        sammba_dir, 'anat_n0_unifized_brain_mask.nii.gz')
    spm_tissues_files = [
        os.path.join(spm_dir,
                     'c{0}anat_n0_clear_hd.nii'.format(n))  # Try after N3
        for n in range(1, 4)
    ]
    rough_mask_img = image.math_img('np.max(imgs, axis=-1) > .01',
                                    imgs=spm_tissues_files)
    spm_labels_img = image.math_img('img * (np.argmax(imgs, axis=-1) + 1)',
                                    img=rough_mask_img,
                                    imgs=spm_tissues_files)
    spm_gm_wm_img = image.math_img('np.logical_or(img==1, img==2)',
                                   img=spm_labels_img)
    brain_mask_img = masking.intersect_masks(
        [sammba_brain_mask_file, spm_gm_wm_img], threshold=0)
    brain_mask_file = os.path.join(sammba_dir,
                                   'anat_n0_precise_brain_mask.nii.gz')
    brain_contour_file = compute_mask_contour(brain_mask_file)
    check_niimg(brain_contour_file).to_filename(
        os.path.join(spm_dir, 'anat_n0_precise_brain_mask_contour.nii'))

    nwarp_apply = afni.NwarpApply().run
    transforms = [
        os.path.join(sammba_dir,
                     'anat_n0_unifized_affine_general_warped_WARP.nii.gz'),
        os.path.join(sammba_dir, 'anat_n0_unifized_masked_aff.aff12.1D')
    ]
    warp = "'" + ' '.join(transforms) + "'"
    sammba_registered_contour_file = fname_presuffix(brain_contour_file,
                                                     suffix='_warped',
示例#28
0
def atlas2t1w2dwi_align(
    uatlas,
    uatlas_parcels,
    atlas,
    t1w_brain,
    t1w_brain_mask,
    mni2t1w_warp,
    t1_aligned_mni,
    ap_path,
    t1w2dwi_bbr_xfm,
    mni2t1_xfm,
    t1w2dwi_xfm,
    wm_gm_int_in_dwi,
    aligned_atlas_t1mni,
    aligned_atlas_skull,
    dwi_aligned_atlas,
    dwi_aligned_atlas_wmgm_int,
    B0_mask,
    simple,
):
    """
    A function to perform atlas alignment atlas --> T1 --> dwi.
    Tries nonlinear registration first, and if that fails, does a linear registration instead. For this to succeed,
    must first have called t1w2dwi_align.
    """
    from nilearn.image import resample_to_img
    from pynets.core.utils import checkConsecutive
    from pynets.registration import reg_utils as regutils
    from nilearn.image import math_img
    from nilearn.masking import intersect_masks

    template_img = nib.load(t1_aligned_mni)
    if uatlas_parcels:
        uatlas_res_template = resample_to_img(nib.load(uatlas_parcels),
                                              template_img,
                                              interpolation="nearest")
    else:
        uatlas_res_template = resample_to_img(nib.load(uatlas),
                                              template_img,
                                              interpolation="nearest")
    uatlas_res_template_data = np.asarray(uatlas_res_template.dataobj)
    uatlas_res_template_data[
        uatlas_res_template_data != uatlas_res_template_data.astype(int)] = 0

    uatlas_res_template = nib.Nifti1Image(
        uatlas_res_template_data.astype("int32"),
        affine=uatlas_res_template.affine,
        header=uatlas_res_template.header,
    )
    nib.save(uatlas_res_template, aligned_atlas_t1mni)

    if simple is False:
        try:
            regutils.apply_warp(
                t1w_brain,
                aligned_atlas_t1mni,
                aligned_atlas_skull,
                warp=mni2t1w_warp,
                interp="nn",
                sup=True,
                mask=t1w_brain_mask,
            )

            # Apply linear transformation from template to dwi space
            regutils.align(
                aligned_atlas_skull,
                ap_path,
                init=t1w2dwi_bbr_xfm,
                out=dwi_aligned_atlas,
                dof=6,
                searchrad=True,
                interp="nearestneighbour",
                cost="mutualinfo",
            )

        except BaseException:
            print(
                "Warning: Atlas is not in correct dimensions, or input is low quality,\nusing linear template "
                "registration.")

            regutils.align(
                aligned_atlas_t1mni,
                t1w_brain,
                init=mni2t1_xfm,
                out=aligned_atlas_skull,
                dof=6,
                searchrad=True,
                interp="nearestneighbour",
                cost="mutualinfo",
            )

            regutils.align(
                aligned_atlas_skull,
                ap_path,
                init=t1w2dwi_bbr_xfm,
                out=dwi_aligned_atlas,
                dof=6,
                searchrad=True,
                interp="nearestneighbour",
                cost="mutualinfo",
            )

    else:
        regutils.align(
            aligned_atlas_t1mni,
            t1w_brain,
            init=mni2t1_xfm,
            out=aligned_atlas_skull,
            dof=6,
            searchrad=True,
            interp="nearestneighbour",
            cost="mutualinfo",
        )

        regutils.align(
            aligned_atlas_skull,
            ap_path,
            init=t1w2dwi_xfm,
            out=dwi_aligned_atlas,
            dof=6,
            searchrad=True,
            interp="nearestneighbour",
            cost="mutualinfo",
        )

    atlas_img = nib.load(dwi_aligned_atlas)
    wm_gm_img = nib.load(wm_gm_int_in_dwi)
    wm_gm_mask_img = math_img("img > 0", img=wm_gm_img)
    atlas_mask_img = math_img("img > 0", img=atlas_img)

    uatlas_res_template_data = np.asarray(atlas_img.dataobj)
    uatlas_res_template_data[
        uatlas_res_template_data != uatlas_res_template_data.astype(int)] = 0

    atlas_img_corr = nib.Nifti1Image(
        uatlas_res_template_data.astype("uint32"),
        affine=atlas_img.affine,
        header=atlas_img.header,
    )

    dwi_aligned_atlas_wmgm_int_img = intersect_masks(
        [wm_gm_mask_img, atlas_mask_img], threshold=0, connected=False)

    nib.save(atlas_img_corr, dwi_aligned_atlas)
    nib.save(dwi_aligned_atlas_wmgm_int_img, dwi_aligned_atlas_wmgm_int)

    os.system(
        f"fslmaths {dwi_aligned_atlas} -mas {B0_mask} {dwi_aligned_atlas} "
        f"2>/dev/null")

    os.system(f"fslmaths {dwi_aligned_atlas_wmgm_int} -mas {B0_mask} "
              f"{dwi_aligned_atlas_wmgm_int} 2>/dev/null")

    final_dat = atlas_img_corr.get_fdata()
    unique_a = sorted(set(np.array(final_dat.flatten().tolist())))

    if not checkConsecutive(unique_a):
        print("Warning! Non-consecutive integers found in parcellation...")

    atlas_img.uncache()
    atlas_img_corr.uncache()
    atlas_mask_img.uncache()
    wm_gm_img.uncache()
    wm_gm_mask_img.uncache()

    return dwi_aligned_atlas_wmgm_int, dwi_aligned_atlas, aligned_atlas_t1mni
示例#29
0
def test_intersect_masks():
    """ Test the intersect_masks function
    """

    # Create dummy masks
    mask_a = np.zeros((4, 4, 1), dtype=np.bool)
    mask_a[2:4, 2:4] = 1
    mask_a_img = Nifti1Image(mask_a.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+
    # |   |   | X | X |
    # +---+---+---+---+

    mask_b = np.zeros((4, 4, 1), dtype=np.bool)
    mask_b[1:3, 1:3] = 1
    mask_b_img = Nifti1Image(mask_b.astype(int), np.eye(4))

    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   | X | X |   |
    # +---+---+---+---+
    # |   |   |   |   |
    # +---+---+---+---+

    mask_c = np.zeros((4, 4, 1), dtype=np.bool)
    mask_c[:, 2] = 1
    mask_c[0, 0] = 1
    mask_c_img = Nifti1Image(mask_c.astype(int), np.eye(4))

    # +---+---+---+---+
    # | X |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+
    # |   |   | X |   |
    # +---+---+---+---+

    mask_ab = np.zeros((4, 4, 1), dtype=np.bool)
    mask_ab[2, 2] = 1
    mask_ab_ = intersect_masks([mask_a_img, mask_b_img], threshold=1.)
    assert_array_equal(mask_ab, get_data(mask_ab_))
    # Test intersect mask images with '>f8'. This function uses
    # largest_connected_component to check if intersect_masks passes with
    # connected=True (which is by default)
    mask_a_img_change_dtype = Nifti1Image(get_data(mask_a_img).astype('>f8'),
                                          affine=mask_a_img.affine)
    mask_b_img_change_dtype = Nifti1Image(get_data(mask_b_img).astype('>f8'),
                                          affine=mask_b_img.affine)
    mask_ab_change_type = intersect_masks(
        [mask_a_img_change_dtype, mask_b_img_change_dtype], threshold=1.)
    assert_array_equal(mask_ab, get_data(mask_ab_change_type))

    mask_abc = mask_a + mask_b + mask_c
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=0.,
                                connected=False)
    assert_array_equal(mask_abc, get_data(mask_abc_))

    mask_abc[0, 0] = 0
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=0.)
    assert_array_equal(mask_abc, get_data(mask_abc_))

    mask_abc = mask_ab
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img],
                                threshold=1.)
    assert_array_equal(mask_abc, get_data(mask_abc_))

    mask_abc[1, 2] = 1
    mask_abc[3, 2] = 1
    mask_abc_ = intersect_masks([mask_a_img, mask_b_img, mask_c_img])
    assert_array_equal(mask_abc, get_data(mask_abc_))
            subjects = Parallel(
                n_jobs=n_jobs, verbose=100)(delayed(
                    run_suject_level1_glm)(
                        subject_data,
                        **kwargs) for subject_data in subjects)
        else:
            subjects = [run_suject_level1_glm(subject_data,
                                              **kwargs)
                        for subject_data in subjects]
        subjects = [subject for subject in subjects if subject]

        # level 2
        stats_start_time = pretty_time()
        mask_images = [subject_data.mask for subject_data in subjects]
        group_mask = nibabel.Nifti1Image(
            intersect_masks(mask_images).astype(np.int8),
            nibabel.load(mask_images[0]).get_affine())
        nibabel.save(group_mask, os.path.join(
                task_output_dir, "mask.nii.gz"))

        print "... done.\r\n"
        print "Group GLM"
        contrasts = subjects[0].contrasts
        subjects_effects_maps = [subject_data.effects_maps
                                 for subject_data in subjects]

        group_one_sample_t_test(
            mask_images,
            subjects_effects_maps,
            contrasts,
            task_output_dir,
示例#31
0
def create_spherical_roi_volumes(node_size, coords, template_mask):
    """
    Create volume ROI mask of spheres from a given set of coordinates and radius.

    Parameters
    ----------
    node_size : int
        Spherical centroid node size in the case that coordinate-based centroids
        are used as ROI's for tracking.
    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.
    template_mask : str
        Path to binarized version of standard (MNI)-space template Nifti1Image file.

    Returns
    -------
    parcel_list : list
        List of 3D boolean numpy arrays or binarized Nifti1Images corresponding to ROI masks.
    par_max : int
        The maximum label intensity in the parcellation image.
    node_size : int
        Spherical centroid node size in the case that coordinate-based centroids
        are used as ROI's for tracking.
    parc : bool
        Indicates whether to use the raw parcels as ROI nodes instead of coordinates at their center-of-mass.
    """
    from pynets.core.nodemaker import get_sphere, mmToVox
    from nilearn.masking import intersect_masks

    mask_img = nib.load(template_mask)
    mask_aff = mask_img.affine
    mask_shape = mask_img.shape
    mask_img.uncache()

    print(f"Creating spherical ROI atlas with radius: {node_size}")

    coords_vox = []
    for i in coords:
        coords_vox.append(mmToVox(mask_aff, i))
    coords_vox = list(set(list(tuple(x) for x in coords_vox)))

    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]

    parcel_list_all = []
    i = 0
    for coord in coords_vox:
        sphere_vol = np.zeros(mask_shape, dtype=bool)
        sphere_vol[tuple(
            get_sphere(coord, node_size, (np.abs(x_vox), y_vox, z_vox),
                       mask_shape).T)] = i * 1
        parcel_list_all.append(
            nib.Nifti1Image(sphere_vol.astype('bool').astype('uint16'),
                            affine=mask_aff))
        i += 1

    # remove the intersection
    parcel_intersect = np.invert(
        np.asarray(intersect_masks(parcel_list_all,
                                   threshold=1).dataobj).astype('bool'))

    parcel_list = []
    for mask in parcel_list_all:
        non_ovlp = np.asarray(mask.dataobj) * parcel_intersect
        parcel_list.append(
            nib.Nifti1Image(non_ovlp.astype('uint16'), affine=mask_aff))

    par_max = len(coords)
    if par_max > 0:
        parc = True
    else:
        raise ValueError('Number of nodes is zero.')

    return parcel_list, par_max, node_size, parc
示例#32
0
文件: track.py 项目: dPys/PyNets
def prep_tissues(t1_mask,
                 gm_in_dwi,
                 vent_csf_in_dwi,
                 wm_in_dwi,
                 tiss_class,
                 B0_mask,
                 cmc_step_size=0.2):
    """
    Estimate a tissue classifier for tractography.

    Parameters
    ----------
    t1_mask : Nifti1Image
        T1w mask img.
    gm_in_dwi : Nifti1Image
        Grey-matter tissue segmentation Nifti1Image.
    vent_csf_in_dwi : Nifti1Image
        Ventricular CSF tissue segmentation Nifti1Image.
    wm_in_dwi : Nifti1Image
        White-matter tissue segmentation Nifti1Image.
    tiss_class : str
        Tissue classification method.
    cmc_step_size : float
        Step size from CMC tissue classification method.

    Returns
    -------
    tiss_classifier : obj
        Tissue classifier object.

    References
    ----------
    .. [1] Zhang, Y., Brady, M. and Smith, S. Segmentation of Brain MR Images
      Through a Hidden Markov Random Field Model and the
      Expectation-Maximization Algorithm IEEE Transactions on Medical Imaging,
      20(1): 45-56, 2001
    .. [2] Avants, B. B., Tustison, N. J., Wu, J., Cook, P. A. and Gee, J. C.
      An open source multivariate framework for n-tissue segmentation with
      evaluation on public data. Neuroinformatics, 9(4): 381-400, 2011.
    """
    import gc
    from dipy.tracking.stopping_criterion import (
        ActStoppingCriterion,
        CmcStoppingCriterion,
        BinaryStoppingCriterion,
    )
    from nilearn.masking import intersect_masks
    from nilearn.image import math_img

    # Load B0 mask
    B0_mask_img = math_img("img > 0.01", img=B0_mask)

    # Load t1 mask
    mask_img = math_img("img > 0.01", img=t1_mask)

    # Load tissue maps and prepare tissue classifier
    wm_mask_img = math_img("img > 0.01", img=wm_in_dwi)
    gm_mask_img = math_img("img > 0.01", img=gm_in_dwi)
    vent_csf_in_dwi_img = math_img("img > 0.01", img=vent_csf_in_dwi)
    gm_data = np.asarray(gm_mask_img.dataobj, dtype=np.float32)
    wm_data = np.asarray(wm_mask_img.dataobj, dtype=np.float32)
    vent_csf_in_dwi_data = np.asarray(vent_csf_in_dwi_img.dataobj,
                                      dtype=np.float32)
    if tiss_class == "act":
        background = np.ones(mask_img.shape)
        background[(gm_data + wm_data + vent_csf_in_dwi_data) > 0] = 0
        gm_data[background > 0] = 1
        tiss_classifier = ActStoppingCriterion(gm_data, vent_csf_in_dwi_data)
        del background
    elif tiss_class == "wm":
        tiss_classifier = BinaryStoppingCriterion(
            np.asarray(
                intersect_masks(
                    [
                        mask_img, wm_mask_img, B0_mask_img,
                        nib.Nifti1Image(np.invert(
                            vent_csf_in_dwi_data.astype('bool')).astype('int'),
                                        affine=mask_img.affine)
                    ],
                    threshold=1,
                    connected=False,
                ).dataobj))
    elif tiss_class == "cmc":
        tiss_classifier = CmcStoppingCriterion.from_pve(
            wm_data,
            gm_data,
            vent_csf_in_dwi_data,
            step_size=cmc_step_size,
            average_voxel_size=np.average(mask_img.header["pixdim"][1:4]),
        )
    elif tiss_class == "wb":
        tiss_classifier = BinaryStoppingCriterion(
            np.asarray(
                intersect_masks(
                    [
                        mask_img,
                        B0_mask_img,
                        nib.Nifti1Image(np.invert(
                            vent_csf_in_dwi_data.astype('bool')).astype('int'),
                                        affine=mask_img.affine),
                    ],
                    threshold=1,
                    connected=False,
                ).dataobj))
    else:
        raise ValueError("Tissue classifier cannot be none.")

    B0_mask_img.uncache()
    mask_img.uncache()
    wm_mask_img.uncache()
    gm_mask_img.uncache()
    del gm_data, wm_data, vent_csf_in_dwi_data
    gc.collect()

    return tiss_classifier
示例#33
0
def group_one_sample_t_test(masks,
                            effects_maps,
                            contrasts,
                            output_dir,
                            start_time=base_reporter.pretty_time(),
                            **kwargs):
    """
    Runs a one-sample t-test procedure for group analysis. Here, we are
    for each experimental condition, only interested refuting the null
    hypothesis H0: "The average effect accross the subjects is zero!"

    Parameters
    ----------
    masks: list of strings or nibabel image objects
        subject masks, one per subject

    effects_maps: list of dicts of lists
        effects maps from subject-level GLM; each entry is a dictionary;
        each entry (indexed by condition id) of this dictionary is the
        filename (or correspinding nibabel image object) for the effects
        maps for that condition (aka contrast),for that subject

    contrasts: dictionary of array_likes
        contrasts vectors, indexed by condition id

    kwargs: dict_like
        kwargs for plot_stats_map API
    """

    # make output directory
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    assert len(masks) == len(effects_maps), (len(masks), len(effects_maps))

    # compute group mask
    group_mask = intersect_masks(masks)

    # construct design matrix (only one covariate, namely the "mean effect")
    design_matrix = np.ones(
        len(effects_maps))[:, np.newaxis]  # only the intercept

    group_level_z_maps = {}
    group_level_t_maps = {}
    for contrast_id in contrasts:
        print("\tcontrast id: %s" % contrast_id)

        # effects maps will be the input to the second level GLM
        first_level_image = nibabel.concat_images(
            [x[contrast_id] for x in effects_maps])

        # fit 2nd level GLM for given contrast
        group_model = FirstLevelGLM(first_level_image, design_matrix,
                                    group_mask)
        group_model.fit(do_scaling=False, model='ols')

        # specify and estimate the contrast
        contrast_val = np.array(([[1.]]))  # the only possible contrast !
        z_map, t_map = group_model.contrast(contrast_val,
                                            con_id='one_sample %s' %
                                            contrast_id,
                                            output_z=True,
                                            output_stat=True)

        # save map
        for map_type, map_img in zip(["z", "t"], [z_map, t_map]):
            map_dir = os.path.join(output_dir, '%s_maps' % map_type)
            if not os.path.exists(map_dir):
                os.makedirs(map_dir)
            map_path = os.path.join(map_dir,
                                    'group_level_%s.nii.gz' % (contrast_id))
            print("\t\tWriting %s ..." % map_path)
            nibabel.save(map_img, map_path)
            if map_type == "z":
                group_level_z_maps[contrast_id] = map_path
            elif map_type == "t":
                group_level_z_maps[contrast_id] = map_path

    # do stats report
    stats_report_filename = os.path.join(output_dir, "report_stats.html")
    generate_subject_stats_report(stats_report_filename,
                                  contrasts,
                                  group_level_z_maps,
                                  group_mask,
                                  start_time=start_time,
                                  **kwargs)

    print("\r\nStatistic report written to %s\r\n" % stats_report_filename)

    return group_level_z_maps
示例#34
0
文件: track.py 项目: dPys/PyNets
def track_ensemble(target_samples,
                   atlas_data_wm_gm_int,
                   labels_im_file,
                   recon_path,
                   sphere,
                   traversal,
                   curv_thr_list,
                   step_list,
                   track_type,
                   maxcrossing,
                   roi_neighborhood_tol,
                   min_length,
                   waymask,
                   B0_mask,
                   t1w2dwi,
                   gm_in_dwi,
                   vent_csf_in_dwi,
                   wm_in_dwi,
                   tiss_class,
                   BACKEND='threading'):
    """
    Perform native-space ensemble tractography, restricted to a vector of ROI
    masks.

    Parameters
    ----------
    target_samples : int
        Total number of streamline samples specified to generate streams.
    atlas_data_wm_gm_int : str
        File path to Nifti1Image in T1w-warped native diffusion space,
        restricted to wm-gm interface.
    parcels : list
        List of 3D boolean numpy arrays of atlas parcellation ROI masks from a
        Nifti1Image in T1w-warped native diffusion space.
    recon_path : str
        File path to diffusion reconstruction model.
    tiss_classifier : str
        Tissue classification method.
    sphere : obj
        DiPy object for modeling diffusion directions on a sphere.
    traversal : str
        The statistical approach to tracking. Options are: det (deterministic),
        closest (clos), and prob (probabilistic).
    curv_thr_list : list
        List of integer curvature thresholds used to perform ensemble tracking.
    step_list : list
        List of float step-sizes used to perform ensemble tracking.
    track_type : str
        Tracking algorithm used (e.g. 'local' or 'particle').
    maxcrossing : int
        Maximum number if diffusion directions that can be assumed per voxel
        while tracking.
    roi_neighborhood_tol : float
        Distance (in the units of the streamlines, usually mm). If any
        coordinate in the streamline is within this distance from the center
        of any voxel in the ROI, the filtering criterion is set to True for
        this streamline, otherwise False. Defaults to the distance between
        the center of each voxel and the corner of the voxel.
    min_length : int
        Minimum fiber length threshold in mm.
    waymask_data : ndarray
        Tractography constraint mask array in native diffusion space.
    B0_mask_data : ndarray
        B0 brain mask data.
    n_seeds_per_iter : int
        Number of seeds from which to initiate tracking for each unique
        ensemble combination. By default this is set to 250.
    max_length : int
        Maximum number of steps to restrict tracking.
    particle_count
        pft_back_tracking_dist : float
        Distance in mm to back track before starting the particle filtering
        tractography. The total particle filtering tractography distance is
        equal to back_tracking_dist + front_tracking_dist. By default this is
        set to 2 mm.
    pft_front_tracking_dist : float
        Distance in mm to run the particle filtering tractography after the
        the back track distance. The total particle filtering tractography
        distance is equal to back_tracking_dist + front_tracking_dist. By
        default this is set to 1 mm.
    particle_count : int
        Number of particles to use in the particle filter.
    min_separation_angle : float
        The minimum angle between directions [0, 90].

    Returns
    -------
    streamlines : ArraySequence
        DiPy list/array-like object of streamline points from tractography.

    References
    ----------
    .. [1] Takemura, H., Caiafa, C. F., Wandell, B. A., & Pestilli, F. (2016).
      Ensemble Tractography. PLoS Computational Biology.
      https://doi.org/10.1371/journal.pcbi.1004692
    """
    import os
    import gc
    import time
    import warnings
    import time
    import tempfile
    from joblib import Parallel, delayed, Memory
    import itertools
    import pickle5 as pickle
    from pynets.dmri.track import run_tracking
    from colorama import Fore, Style
    from pynets.dmri.utils import generate_sl
    from nibabel.streamlines.array_sequence import concatenate, ArraySequence
    from pynets.core.utils import save_3d_to_4d
    from nilearn.masking import intersect_masks
    from nilearn.image import math_img
    from pynets.core.utils import load_runconfig
    from dipy.tracking import utils

    warnings.filterwarnings("ignore")

    pickle.HIGHEST_PROTOCOL = 5
    joblib_dir = tempfile.mkdtemp()
    os.makedirs(joblib_dir, exist_ok=True)

    hardcoded_params = load_runconfig()
    nthreads = hardcoded_params["omp_threads"][0]
    os.environ['MKL_NUM_THREADS'] = str(nthreads)
    os.environ['OPENBLAS_NUM_THREADS'] = str(nthreads)
    n_seeds_per_iter = \
        hardcoded_params['tracking']["n_seeds_per_iter"][0]
    max_length = \
        hardcoded_params['tracking']["max_length"][0]
    pft_back_tracking_dist = \
        hardcoded_params['tracking']["pft_back_tracking_dist"][0]
    pft_front_tracking_dist = \
        hardcoded_params['tracking']["pft_front_tracking_dist"][0]
    particle_count = \
        hardcoded_params['tracking']["particle_count"][0]
    min_separation_angle = \
        hardcoded_params['tracking']["min_separation_angle"][0]
    min_streams = \
        hardcoded_params['tracking']["min_streams"][0]
    seeding_mask_thr = hardcoded_params['tracking']["seeding_mask_thr"][0]
    timeout = hardcoded_params['tracking']["track_timeout"][0]

    all_combs = list(itertools.product(step_list, curv_thr_list))

    # Construct seeding mask
    seeding_mask = f"{os.path.dirname(labels_im_file)}/seeding_mask.nii.gz"
    if waymask is not None and os.path.isfile(waymask):
        waymask_img = math_img(f"img > {seeding_mask_thr}",
                               img=nib.load(waymask))
        waymask_img.to_filename(waymask)
        atlas_data_wm_gm_int_img = intersect_masks(
            [
                waymask_img,
                math_img("img > 0.001", img=nib.load(atlas_data_wm_gm_int)),
                math_img("img > 0.001", img=nib.load(labels_im_file))
            ],
            threshold=1,
            connected=False,
        )
        nib.save(atlas_data_wm_gm_int_img, seeding_mask)
    else:
        atlas_data_wm_gm_int_img = intersect_masks(
            [
                math_img("img > 0.001", img=nib.load(atlas_data_wm_gm_int)),
                math_img("img > 0.001", img=nib.load(labels_im_file))
            ],
            threshold=1,
            connected=False,
        )
        nib.save(atlas_data_wm_gm_int_img, seeding_mask)

    tissues4d = save_3d_to_4d([
        B0_mask, labels_im_file, seeding_mask, t1w2dwi, gm_in_dwi,
        vent_csf_in_dwi, wm_in_dwi
    ])

    # Commence Ensemble Tractography
    start = time.time()
    stream_counter = 0

    all_streams = []
    ix = 0

    memory = Memory(location=joblib_dir, mmap_mode='r+', verbose=0)
    os.chdir(f"{memory.location}/joblib")

    @memory.cache
    def load_recon_data(recon_path):
        import h5py
        with h5py.File(recon_path, 'r') as hf:
            recon_data = hf['reconstruction'][:].astype('float32')
        hf.close()
        return recon_data

    recon_shelved = load_recon_data.call_and_shelve(recon_path)

    @memory.cache
    def load_tissue_data(tissues4d):
        return nib.load(tissues4d)

    tissue_shelved = load_tissue_data.call_and_shelve(tissues4d)

    try:
        while float(stream_counter) < float(target_samples) and \
                float(ix) < 0.50*float(len(all_combs)):
            with Parallel(n_jobs=nthreads,
                          backend=BACKEND,
                          mmap_mode='r+',
                          verbose=0) as parallel:

                out_streams = parallel(
                    delayed(run_tracking)
                    (i, recon_shelved, n_seeds_per_iter, traversal,
                     maxcrossing, max_length, pft_back_tracking_dist,
                     pft_front_tracking_dist, particle_count,
                     roi_neighborhood_tol, min_length, track_type,
                     min_separation_angle, sphere, tiss_class, tissue_shelved)
                    for i in all_combs)

                out_streams = list(filter(None, out_streams))

                if len(out_streams) > 1:
                    out_streams = concatenate(out_streams, axis=0)
                else:
                    continue

                if waymask is not None and os.path.isfile(waymask):
                    try:
                        out_streams = out_streams[utils.near_roi(
                            out_streams,
                            np.eye(4),
                            np.asarray(
                                nib.load(waymask).dataobj).astype("bool"),
                            tol=int(round(roi_neighborhood_tol * 0.50, 1)),
                            mode="all")]
                    except BaseException:
                        print(f"\n{Fore.RED}No streamlines generated in "
                              f"waymask vacinity\n")
                        print(Style.RESET_ALL)
                        return None

                if len(out_streams) < min_streams:
                    ix += 1
                    print(f"\n{Fore.YELLOW}Fewer than {min_streams} "
                          f"streamlines tracked "
                          f"on last iteration...\n")
                    print(Style.RESET_ALL)
                    if ix > 5:
                        print(f"\n{Fore.RED}No streamlines generated\n")
                        print(Style.RESET_ALL)
                        return None
                    continue
                else:
                    ix -= 1

                stream_counter += len(out_streams)
                all_streams.extend([generate_sl(i) for i in out_streams])
                del out_streams

                print("%s%s%s%s" % (
                    "\nCumulative Streamline Count: ",
                    Fore.CYAN,
                    stream_counter,
                    "\n",
                ))
                gc.collect()
                print(Style.RESET_ALL)

                if time.time() - start > timeout:
                    print(f"\n{Fore.RED}Warning: Tractography timed "
                          f"out: {time.time() - start}")
                    print(Style.RESET_ALL)
                    memory.clear(warn=False)
                    return None

    except RuntimeError as e:
        print(f"\n{Fore.RED}Error: Tracking failed due to:\n{e}\n")
        print(Style.RESET_ALL)
        memory.clear(warn=False)
        return None

    print("Tracking Complete: ", str(time.time() - start))

    memory.clear(warn=False)

    del parallel, all_combs
    gc.collect()

    if stream_counter != 0:
        print('Generating final ...')
        return ArraySequence([ArraySequence(i) for i in all_streams])
    else:
        print(f"\n{Fore.RED}No streamlines generated!")
        print(Style.RESET_ALL)
        return None
示例#35
0
def atlas2t1w2dwi_align(
    uatlas,
    uatlas_parcels,
    atlas,
    t1w_brain,
    t1w_brain_mask,
    mni2t1w_warp,
    t1_aligned_mni,
    ap_path,
    mni2t1_xfm,
    t1w2dwi_xfm,
    wm_gm_int_in_dwi,
    aligned_atlas_t1mni,
    aligned_atlas_skull,
    dwi_aligned_atlas,
    dwi_aligned_atlas_wmgm_int,
    B0_mask,
    mni2dwi_xfm,
    simple,
):
    """
    A function to perform atlas alignment atlas --> T1 --> dwi.
    Tries nonlinear registration first, and if that fails, does a linear
    registration instead. For this to succeed, must first have called
    t1w2dwi_align.
    """
    import time
    from nilearn.image import resample_to_img
    from pynets.core.utils import checkConsecutive
    from pynets.registration import utils as regutils
    from nilearn.image import math_img
    from nilearn.masking import intersect_masks

    template_img = nib.load(t1_aligned_mni)
    if uatlas_parcels:
        atlas_img_orig = nib.load(uatlas_parcels)
    else:
        atlas_img_orig = nib.load(uatlas)

    old_count = len(np.unique(np.asarray(atlas_img_orig.dataobj)))

    uatlas_res_template = resample_to_img(atlas_img_orig,
                                          template_img,
                                          interpolation="nearest")

    uatlas_res_template = nib.Nifti1Image(
        np.asarray(uatlas_res_template.dataobj).astype('uint16'),
        affine=uatlas_res_template.affine,
        header=uatlas_res_template.header,
    )
    nib.save(uatlas_res_template, aligned_atlas_t1mni)

    if simple is False:
        try:
            regutils.apply_warp(
                t1w_brain,
                aligned_atlas_t1mni,
                aligned_atlas_skull,
                warp=mni2t1w_warp,
                interp="nn",
                sup=True,
                mask=t1w_brain_mask,
            )
            time.sleep(0.5)

            # Apply linear transformation from template to dwi space
            regutils.applyxfm(ap_path,
                              aligned_atlas_skull,
                              t1w2dwi_xfm,
                              dwi_aligned_atlas,
                              interp="nearestneighbour")
            time.sleep(0.5)
        except BaseException:
            print(
                "Warning: Atlas is not in correct dimensions, or input is low"
                " quality,\nusing linear template registration.")

            regutils.applyxfm(t1w_brain,
                              aligned_atlas_t1mni,
                              mni2t1_xfm,
                              aligned_atlas_skull,
                              interp="nearestneighbour")
            time.sleep(0.5)
            combine_xfms(mni2t1_xfm, t1w2dwi_xfm, mni2dwi_xfm)
            time.sleep(0.5)
            regutils.applyxfm(ap_path,
                              aligned_atlas_t1mni,
                              mni2dwi_xfm,
                              dwi_aligned_atlas,
                              interp="nearestneighbour")
            time.sleep(0.5)
    else:
        regutils.applyxfm(t1w_brain,
                          aligned_atlas_t1mni,
                          mni2t1_xfm,
                          aligned_atlas_skull,
                          interp="nearestneighbour")
        time.sleep(0.5)
        combine_xfms(mni2t1_xfm, t1w2dwi_xfm, mni2dwi_xfm)
        time.sleep(0.5)
        regutils.applyxfm(ap_path,
                          aligned_atlas_t1mni,
                          mni2dwi_xfm,
                          dwi_aligned_atlas,
                          interp="nearestneighbour")
        time.sleep(0.5)

    atlas_img = nib.load(dwi_aligned_atlas)
    wm_gm_img = nib.load(wm_gm_int_in_dwi)
    wm_gm_mask_img = math_img("img > 0", img=wm_gm_img)
    atlas_mask_img = math_img("img > 0", img=atlas_img)

    atlas_img_corr = nib.Nifti1Image(
        np.asarray(atlas_img.dataobj).astype('uint16'),
        affine=atlas_img.affine,
        header=atlas_img.header,
    )

    # Get the union of masks
    dwi_aligned_atlas_wmgm_int_img = intersect_masks(
        [wm_gm_mask_img, atlas_mask_img], threshold=0, connected=False)

    nib.save(atlas_img_corr, dwi_aligned_atlas)
    nib.save(dwi_aligned_atlas_wmgm_int_img, dwi_aligned_atlas_wmgm_int)

    dwi_aligned_atlas = regutils.apply_mask_to_image(dwi_aligned_atlas,
                                                     B0_mask,
                                                     dwi_aligned_atlas)

    time.sleep(0.5)

    dwi_aligned_atlas_wmgm_int = regutils.apply_mask_to_image(
        dwi_aligned_atlas_wmgm_int, B0_mask, dwi_aligned_atlas_wmgm_int)

    time.sleep(0.5)
    final_dat = atlas_img_corr.get_fdata()
    unique_a = sorted(set(np.array(final_dat.flatten().tolist())))

    if not checkConsecutive(unique_a):
        print("Warning! Non-consecutive integers found in parcellation...")

    new_count = len(unique_a)
    diff = np.abs(np.int(float(new_count) - float(old_count)))
    print(f"Previous label count: {old_count}")
    print(f"New label count: {new_count}")
    print(f"Labels dropped: {diff}")

    atlas_img.uncache()
    atlas_img_corr.uncache()
    atlas_img_orig.uncache()
    atlas_mask_img.uncache()
    wm_gm_img.uncache()
    wm_gm_mask_img.uncache()

    return dwi_aligned_atlas_wmgm_int, dwi_aligned_atlas, aligned_atlas_skull
示例#36
0
文件: interfaces.py 项目: dPys/PyNets
    def create_clean_mask(self, num_std_dev=1.5):
        """
        Create a subject-refined version of the clustering mask.
        """
        import os
        from pynets.core import utils
        from nilearn.masking import intersect_masks
        from nilearn.image import index_img, math_img, resample_img

        mask_name = os.path.basename(self.clust_mask).split(".nii")[0]
        self.atlas = f"{mask_name}{'_'}{self.clust_type}{'_k'}{str(self.k)}"
        print(f"\nCreating atlas using {self.clust_type} at cluster level"
              f" {str(self.k)} for {str(self.atlas)}...\n")
        self._dir_path = utils.do_dir_path(self.atlas, self.outdir)
        self.parcellation = f"{self._dir_path}/{mask_name}_" \
                            f"clust-{self.clust_type}" \
                            f"_k{str(self.k)}.nii.gz"

        # Load clustering mask
        self._func_img.set_data_dtype(np.float32)
        func_vol_img = index_img(self._func_img, 1)
        func_vol_img.set_data_dtype(np.uint16)
        clust_mask_res_img = resample_img(
            nib.load(self.clust_mask),
            target_affine=func_vol_img.affine,
            target_shape=func_vol_img.shape,
            interpolation="nearest",
        )
        clust_mask_res_img.set_data_dtype(np.uint16)
        func_data = np.asarray(func_vol_img.dataobj, dtype=np.float32)
        func_int_thr = np.round(
            np.mean(func_data[func_data > 0]) -
            np.std(func_data[func_data > 0]) * num_std_dev,
            3,
        )
        if self.mask is not None:
            self._mask_img = nib.load(self.mask)
            self._mask_img.set_data_dtype(np.uint16)
            mask_res_img = resample_img(
                self._mask_img,
                target_affine=func_vol_img.affine,
                target_shape=func_vol_img.shape,
                interpolation="nearest",
            )
            mask_res_img.set_data_dtype(np.uint16)
            self._clust_mask_corr_img = intersect_masks(
                [
                    math_img(f"img > {func_int_thr}", img=func_vol_img),
                    math_img("img > 0.01", img=clust_mask_res_img),
                    math_img("img > 0.01", img=mask_res_img),
                ],
                threshold=1,
                connected=False,
            )
            self._clust_mask_corr_img.set_data_dtype(np.uint16)
            self._mask_img.uncache()
            mask_res_img.uncache()
        else:
            self._clust_mask_corr_img = intersect_masks(
                [
                    math_img("img > " + str(func_int_thr), img=func_vol_img),
                    math_img("img > 0.01", img=clust_mask_res_img),
                ],
                threshold=1,
                connected=False,
            )
            self._clust_mask_corr_img.set_data_dtype(np.uint16)
        nib.save(self._clust_mask_corr_img,
                 f"{self._dir_path}{'/'}{mask_name}{'.nii.gz'}")

        del func_data
        func_vol_img.uncache()
        clust_mask_res_img.uncache()

        return self.atlas
def average_brain_mask(derivatives=DERIVATIVES):
    """Compute an average brain masks across all the brain masks available"""
    from nilearn.masking import intersect_masks
    masks = glob.glob(os.path.join(derivatives, 'sub-*/ses-00/mask.nii.gz'))
    return (intersect_masks(masks, .25))
        if n_jobs > 1:
            subjects = Parallel(n_jobs=n_jobs, verbose=100)(
                delayed(run_suject_level1_glm)(subject_data, **kwargs)
                for subject_data in subjects)
        else:
            subjects = [
                run_suject_level1_glm(subject_data, **kwargs)
                for subject_data in subjects
            ]
        subjects = [subject for subject in subjects if subject]

        # level 2
        stats_start_time = pretty_time()
        mask_images = [subject_data.mask for subject_data in subjects]
        group_mask = nibabel.Nifti1Image(
            intersect_masks(mask_images).astype(np.int8),
            nibabel.load(mask_images[0]).get_affine())
        nibabel.save(group_mask, os.path.join(task_output_dir, "mask.nii.gz"))

        print "... done.\r\n"
        print "Group GLM"
        contrasts = subjects[0].contrasts
        subjects_effects_maps = [
            subject_data.effects_maps for subject_data in subjects
        ]

        group_one_sample_t_test(
            mask_images,
            subjects_effects_maps,
            contrasts,
            task_output_dir,
示例#39
0
test_set = ['left button press (auditory cue)']
ref = [contrast for contrast in contrasts if contrast not in test_set]
n_ref = len(ref)

nifti_masker = NiftiMasker('mask_GM_forFunc.nii')
affine = load(nifti_masker.mask).get_affine()

# fetch the data
ref_imgs = datasets.fetch_localizer_contrasts(ref).cmaps
n_subjects = len(ref_imgs) / n_ref

# Create a population mask
one_contrast = [img for img in ref_imgs if 'horizontal' in img]
mask_ = compute_multi_background_mask(one_contrast)
mask_image = intersect_masks(['mask_GM_forFunc.nii', mask_])
mask = mask_image.get_data()
n_voxels = mask.sum()
save(mask_image, '/tmp/mask.nii')
nifti_masker = NiftiMasker(mask_image)

# write directory
write_dir = op.join(getcwd(), 'results')
if not op.exists(write_dir):
    mkdir(write_dir)


###############################################################################

# Global parameters
n_clusters = 5000