Beispiel #1
0
def preprocess(num, subj, subj_dir, subj_warp_dir, force_warp=False):
    bold_path = 'BOLD/task001_run00%i/bold_dico_bold7Tp1_to_subjbold7Tp1.nii.gz' % (num+1)
    bold_path = os.path.join(DATA_DIR, subj, bold_path)
    template_path = os.path.join(DATA_DIR, 'templates', 'grpbold7Tp1', 'brain.nii.gz')
    warp_path = os.path.join(DATA_DIR, subj, 'templates', 'bold7Tp1', 'in_grpbold7Tp1', 'subj2tmpl_warp.nii.gz')

    output_path = os.path.join(subj_warp_dir, 'run00%i.nii.gz' % num)

    if force_warp or not os.path.exists(output_path):
        print 'Warping image #%i...' % num
        subprocess.call(['fsl5.0-applywarp', '-i', bold_path, '-o', output_path, '-r', template_path, '-w', warp_path, '-d', 'float'])
    else:
        print 'Reusing cached warp image #%i' % num

    print 'Loading image #%i...' % num
    bold = load(output_path)

    masker = NiftiMasker(load(MASK_FILE))
    # masker = niftimasker(load(MASK_FILE), detrend=true, smoothing_fwhm=4.0,
    #                     high_pass=0.01, t_r=2.0, standardize=true)
    masker.fit()
    print 'Removing confounds from image #%i...' % num
    data = masker.transform(bold, confounds(num, subj))
    print 'Detrending image #%i...' % num
    filtered = np.float32(savgol_filter(data, 61, 5, axis=0))
    img = masker.inverse_transform(data-filtered)
    print 'Smoothing image #%i...' % num
    img = image.smooth_img(img, 4.0)
    print 'Saving image #%i...' % num
    save(img, os.path.join(subj_dir, 'run00%i.nii.gz' % num))
    print 'Finished with image #%i' % num
Beispiel #2
0
def load_data():
    with open(expanduser('~/data/HCP_unmasked/data.json'), 'r') as f:
        data = json.load(f)
        for this_data in data:
            this_data['array'] += '.npy'
        mask_img = expanduser('~/data/HCP_mask/mask_img.nii.gz')
    masker = NiftiMasker(mask_img=mask_img, smoothing_fwhm=4,
                         standardize=True)
    masker.fit()
    smith2009 = fetch_atlas_smith_2009()
    init = smith2009.rsn70
    dict_init = masker.transform(init)
    return masker, dict_init, sorted(data, key=lambda t: t['filename'])
Beispiel #3
0
class SmoothResampleMasker(BaseMasker):

    def __init__(self, mask_img=None, smoothing_fwhm=None, resampling=None, searchlight=False):

        self.mask_img = mask_img
        self.smoothing_fwhm = smoothing_fwhm
        self.resampling = resampling
        self.searchlight = searchlight

        self.masker = None

    def fit(self):

        if self.resampling is not None:
            self.mask_img = resample_img(self.mask_img, target_affine=np.diag(self.resampling * np.ones(3)))
        self.masker = NiftiMasker(mask_img=self.mask_img)
        self.masker.fit()

        return self

    def transform(self, imgs, confounds=None):

        smooth_prefix = '' if self.smoothing_fwhm is None else 's%g' % self.smoothing_fwhm
        resample_prefix = '' if self.smoothing_fwhm is None else 'r%g' % self.smoothing_fwhm

        if not isinstance(imgs, list):
            imgs = [imgs]

        path_first = imgs[0] if isinstance(imgs[0], str) else imgs[0].get_filename()

        path_first_resampled = os.path.join(os.path.dirname(path_first), resample_prefix + os.path.basename(path_first))
        path_first_smoothed = os.path.join(os.path.dirname(path_first), smooth_prefix + resample_prefix + os.path.basename(path_first))

        if self.resampling is not None and self.smoothing_fwhm is not None:
            if self.resampling is not None:
                if not os.path.exists(path_first_resampled) and not os.path.exists(path_first_smoothed):
                    imgs = resample_img(imgs, target_affine=np.diag(self.resampling * np.ones(3)))
                else:
                    imgs = []
            if self.smoothing_fwhm is not None:
                if not os.path.exists(path_first_smoothed):
                    imgs = smooth_img(imgs, self.smoothing_fwhm)
                else:
                    imgs = []
        else:
            imgs = [check_niimg_3d(img) for img in imgs]

        return self.masker.transform(imgs)
def test_multi_pca_score():
    shape = (6, 8, 10, 5)
    affine = np.eye(4)
    rng = np.random.RandomState(0)

    # Create a "multi-subject" dataset
    imgs = []
    for i in range(8):
        this_img = rng.normal(size=shape)
        imgs.append(nibabel.Nifti1Image(this_img, affine))

    mask_img = nibabel.Nifti1Image(np.ones(shape[:3], dtype=np.int8), affine)

    # Assert that score is between zero and one
    multi_pca = MultiPCA(mask=mask_img, random_state=0, memory_level=0,
                         n_components=3)
    multi_pca.fit(imgs)
    s = multi_pca.score(imgs)
    assert_true(np.all(s <= 1))
    assert_true(np.all(0 <= s))

    # Assert that score does not fail with single subject data
    multi_pca = MultiPCA(mask=mask_img, random_state=0, memory_level=0,
                         n_components=3)
    multi_pca.fit(imgs[0])
    s = multi_pca.score(imgs[0])
    assert_true(isinstance(s, float))
    assert(0. <= s <= 1.)

    # Assert that score is one for n_components == n_sample
    # in single subject configuration
    multi_pca = MultiPCA(mask=mask_img, random_state=0, memory_level=0,
                         n_components=5)
    multi_pca.fit(imgs[0])
    s = multi_pca.score(imgs[0])
    assert_almost_equal(s, 1., 1)

    # Per component score
    multi_pca = MultiPCA(mask=mask_img, random_state=0, memory_level=0,
                         n_components=5)
    multi_pca.fit(imgs[0])
    masker = NiftiMasker(mask_img).fit()
    s = multi_pca._raw_score(masker.transform(imgs[0]), per_component=True)
    assert_equal(s.shape, (5,))
    assert_true(np.all(s <= 1))
    assert_true(np.all(0 <= s))
Beispiel #5
0
def get_init_objective(output_dir):
    mask, func_filenames = get_hcp_data(raw=True)

    masker = NiftiMasker(mask_img=mask, smoothing_fwhm=None,
                         standardize=False)
    masker.fit()

    rsn70 = fetch_atlas_smith_2009().rsn70
    components = masker.transform(rsn70)
    print(components.shape)
    enet_scale(components.T, inplace=True)
    print(np.sum(np.abs(components), axis=1))
    test_data = func_filenames[(-n_test_records * 2)::2]

    n_samples, n_voxels = np.load(test_data[-1], mmap_mode='r').shape
    X = np.empty((n_test_records * n_samples, n_voxels))

    for i, this_data in enumerate(test_data):
        X[i * n_samples:(i + 1) * n_samples] = np.load(this_data,
                                                       mmap_mode='r')
    exp_var = {}
    for alpha in [1e-2, 1e-3, 1e-4]:
        exp_var[alpha] = objective_function(X, components, alpha)
    json.dump(open(join(output_dir, 'init_objective.json'), 'r'))
Beispiel #6
0
class SecondLevelModel(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for multiple subject
    fMRI data

    Parameters
    ----------

    mask_img: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters. Automatic mask computation assumes first level imgs have
        already been masked.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory: string, optional
        Path to the directory used to cache the masking process and the glm
        fit. By default, no caching is done. Creates instance of joblib.Memory.

    memory_level: integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.
        If 0 prints nothing. If 1 prints final computation time.
        If 2 prints masker computation details.

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    minimize_memory : boolean, optional
        Gets rid of some variables on the model fit results that are not
        necessary for contrast computation and would only be useful for
        further inspection of model details. This has an important impact
        on memory consumption. True by default.

    """
    @replace_parameters({'mask': 'mask_img'}, end_version='next')
    def __init__(self, mask_img=None, smoothing_fwhm=None,
                 memory=Memory(None), memory_level=1, verbose=0,
                 n_jobs=1, minimize_memory=True):
        self.mask_img = mask_img
        self.smoothing_fwhm = smoothing_fwhm
        if isinstance(memory, _basestring):
            self.memory = Memory(memory)
        else:
            self.memory = memory
        self.memory_level = memory_level
        self.verbose = verbose
        self.n_jobs = n_jobs
        self.minimize_memory = minimize_memory
        self.second_level_input_ = None
        self.confounds_ = None

    def fit(self, second_level_input, confounds=None, design_matrix=None):
        """ Fit the second-level GLM

        1. create design matrix
        2. do a masker job: fMRI_data -> Y
        3. fit regression to (Y, X)

        Parameters
        ----------
        second_level_input: list of `FirstLevelModel` objects or pandas
                            DataFrame or list of Niimg-like objects.

            Giving FirstLevelModel objects will allow to easily compute
            the second level contast of arbitrary first level contrasts thanks
            to the first_level_contrast argument of the compute_contrast
            method. Effect size images will be computed for each model to
            contrast at the second level.

            If a pandas DataFrame, then they have to contain subject_label,
            map_name and effects_map_path. It can contain multiple maps that
            would be selected during contrast estimation with the argument
            first_level_contrast of the compute_contrast function. The
            DataFrame will be sorted based on the subject_label column to avoid
            order inconsistencies when extracting the maps. So the rows of the
            automatically computed design matrix, if not provided, will
            correspond to the sorted subject_label column.

            If list of Niimg-like objects then this is taken literally as Y
            for the model fit and design_matrix must be provided.

        confounds: pandas DataFrame, optional
            Must contain a subject_label column. All other columns are
            considered as confounds and included in the model. If
            design_matrix is provided then this argument is ignored.
            The resulting second level design matrix uses the same column
            names as in the given DataFrame for confounds. At least two columns
            are expected, "subject_label" and at least one confound.

        design_matrix: pandas DataFrame, optional
            Design matrix to fit the GLM. The number of rows
            in the design matrix must agree with the number of maps derived
            from second_level_input.
            Ensure that the order of maps given by a second_level_input
            list of Niimgs matches the order of the rows in the design matrix.

        """
        # check second_level_input
        _check_second_level_input(second_level_input, design_matrix,
                                  confounds=confounds)

        # check confounds
        _check_confounds(confounds)

        # check design matrix
        _check_design_matrix(design_matrix)

        # sort a pandas dataframe by subject_label to avoid inconsistencies
        # with the design matrix row order when automatically extracting maps
        if isinstance(second_level_input, pd.DataFrame):
            columns = second_level_input.columns.tolist()
            column_index = columns.index('subject_label')
            sorted_matrix = sorted(
                second_level_input.values, key=lambda x: x[column_index])
            sorted_input = pd.DataFrame(sorted_matrix, columns=columns)
            second_level_input = sorted_input

        self.second_level_input_ = second_level_input
        self.confounds_ = confounds

        # Report progress
        t0 = time.time()
        if self.verbose > 0:
            sys.stderr.write("Fitting second level model. "
                             "Take a deep breath\r")

        # Select sample map for masker fit and get subjects_label for design
        if isinstance(second_level_input, pd.DataFrame):
            sample_map = second_level_input['effects_map_path'][0]
            labels = second_level_input['subject_label']
            subjects_label = labels.values.tolist()
        elif isinstance(second_level_input, Nifti1Image):
            sample_map = mean_img(second_level_input)
        elif isinstance(second_level_input[0], FirstLevelModel):
            sample_model = second_level_input[0]
            sample_condition = sample_model.design_matrices_[0].columns[0]
            sample_map = sample_model.compute_contrast(
                sample_condition, output_type='effect_size')
            labels = [model.subject_label for model in second_level_input]
            subjects_label = labels
        else:
            # In this case design matrix had to be provided
            sample_map = mean_img(second_level_input)

        # Create and set design matrix, if not given
        if design_matrix is None:
            design_matrix = make_second_level_design_matrix(subjects_label,
                                                            confounds)
        self.design_matrix_ = design_matrix

        # Learn the mask. Assume the first level imgs have been masked.
        if not isinstance(self.mask_img, NiftiMasker):
            self.masker_ = NiftiMasker(
                mask_img=self.mask_img, smoothing_fwhm=self.smoothing_fwhm,
                memory=self.memory, verbose=max(0, self.verbose - 1),
                memory_level=self.memory_level)
        else:
            self.masker_ = clone(self.mask_img)
            for param_name in ['smoothing_fwhm', 'memory', 'memory_level']:
                our_param = getattr(self, param_name)
                if our_param is None:
                    continue
                if getattr(self.masker_, param_name) is not None:
                    warn('Parameter %s of the masker overriden' % param_name)
                setattr(self.masker_, param_name, our_param)
        self.masker_.fit(sample_map)

        # Report progress
        if self.verbose > 0:
            sys.stderr.write("\nComputation of second level model done in "
                             "%i seconds\n" % (time.time() - t0))

        return self

    def compute_contrast(
            self, second_level_contrast=None, first_level_contrast=None,
            second_level_stat_type=None, output_type='z_score'):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.

        Parameters
        ----------
        second_level_contrast: str or array of shape (n_col), optional
            Where ``n_col`` is the number of columns of the design matrix,
            The string can be a formula compatible with the linear constraint
            of the Patsy library. Basically one can use the name of the
            conditions as they appear in the design matrix of
            the fitted model combined with operators /\*+- and numbers.
            Please check the patsy documentation for formula examples:
            http://patsy.readthedocs.io/en/latest/API-reference.html#patsy.DesignInfo.linear_constraint
            The default (None) is accepted if the design matrix has a single
            column, in which case the only possible contrast array([1]) is
            applied; when the design matrix has multiple columns, an error is
            raised.

        first_level_contrast: str or array of shape (n_col) with respect to
                              FirstLevelModel, optional

            In case a list of FirstLevelModel was provided as
            second_level_input, we have to provide a contrast to apply to
            the first level models to get the corresponding list of images
            desired, that would be tested at the second level. In case a
            pandas DataFrame was provided as second_level_input this is the
            map name to extract from the pandas dataframe map_name column.
            It has to be a 't' contrast.

        second_level_stat_type: {'t', 'F'}, optional
            Type of the second level contrast

        output_type: str, optional
            Type of the output map. Can be 'z_score', 'stat', 'p_value',
            'effect_size', 'effect_variance' or 'all'

        Returns
        -------
        output_image: Nifti1Image
            The desired output image(s). If ``output_type == 'all'``, then
            the output is a dictionary of images, keyed by the type of image.

        """
        if self.second_level_input_ is None:
            raise ValueError('The model has not been fit yet')

        # check first_level_contrast
        _check_first_level_contrast(self.second_level_input_,
                                    first_level_contrast)

        # check contrast and obtain con_val
        con_val = _get_con_val(second_level_contrast, self.design_matrix_)

        # check output type
        # 'all' is assumed to be the final entry;
        # if adding more, place before 'all'
        valid_types = ['z_score', 'stat', 'p_value', 'effect_size',
                       'effect_variance', 'all']
        _check_output_type(output_type, valid_types)

        # Get effect_maps appropriate for chosen contrast
        effect_maps = _infer_effect_maps(self.second_level_input_,
                                         first_level_contrast)
        # Check design matrix X and effect maps Y agree on number of rows
        _check_effect_maps(effect_maps, self.design_matrix_)

        # Fit an Ordinary Least Squares regression for parametric statistics
        Y = self.masker_.transform(effect_maps)
        if self.memory:
            mem_glm = self.memory.cache(run_glm, ignore=['n_jobs'])
        else:
            mem_glm = run_glm
        labels, results = mem_glm(Y, self.design_matrix_.values,
                                  n_jobs=self.n_jobs, noise_model='ols')

        # We save memory if inspecting model details is not necessary
        if self.minimize_memory:
            for key in results:
                results[key] = SimpleRegressionResults(results[key])
        self.labels_ = labels
        self.results_ = results

        # We compute contrast object
        if self.memory:
            mem_contrast = self.memory.cache(compute_contrast)
        else:
            mem_contrast = compute_contrast
        contrast = mem_contrast(self.labels_, self.results_, con_val,
                                second_level_stat_type)

        output_types = \
            valid_types[:-1] if output_type == 'all' else [output_type]

        outputs = {}
        for output_type_ in output_types:
            # We get desired output from contrast object
            estimate_ = getattr(contrast, output_type_)()
            # Prepare the returned images
            output = self.masker_.inverse_transform(estimate_)
            contrast_name = str(con_val)
            output.header['descrip'] = (
                '%s of contrast %s' % (output_type, contrast_name))
            outputs[output_type_] = output

        return outputs if output_type == 'all' else output
labels = np.int32(labels)

# contrasts are IN ORDER -> shuffle!
new_inds = np.arange(0, X_task.shape[0])
np.random.shuffle(new_inds)
X_task = X_task[new_inds]
labels = labels[new_inds]
# subs = subs[new_inds]

# rest
# X_rest = nifti_masker.transform('preload_HR20persub_10mm_ero2.nii')
# X_rest = nifti_masker.transform('dump_rs_spca_s12_tmp')
rs_spca_data = joblib.load('dump_rs_spca_s12_tmp')
rs_spca_niis = nib.Nifti1Image(rs_spca_data,
                               nifti_masker.mask_img_.get_affine())
X_rest = nifti_masker.transform(rs_spca_niis)
del rs_spca_niis
del rs_spca_data

X_task = StandardScaler().fit_transform(X_task)
X_rest = StandardScaler().fit_transform(X_rest)

# ARCHI task
AT_niis, AT_labels, AT_subs = joblib.load('preload_AT_3mm')
AT_X = nifti_masker.transform(AT_niis)
AT_X = StandardScaler().fit_transform(AT_X)
print('done :)')


def make_new_noise(masker):
    # CONST
            'cos_ring_pos':
            pjoin(work_dir, 'res_stats_exp_ring_pa', 'z_score_maps',
                  'cos.nii.gz'),
            'sin_ring_pos':
            pjoin(work_dir, 'res_stats_exp_ring_pa', 'z_score_maps',
                  'sin.nii.gz'),
            'sin_ring_neg':
            pjoin(work_dir, 'res_stats_cont_ring_ap', 'z_score_maps',
                  'sin.nii.gz'),
            'cos_ring_neg':
            pjoin(work_dir, 'res_stats_cont_ring_ap', 'z_score_maps',
                  'cos.nii.gz')
        }
        retino_coefs = {}
        for key in retino_imgs.keys():
            retino_coefs[key] = masker.transform(retino_imgs[key])

        phase_wedge, phase_ring, phase_hemo = phase_maps(
            retino_coefs,
            offset_ring=np.pi,
            offset_wedge=0.,
            do_wedge=True,
            do_ring=True,
        )

        phase_wedge_img = masker.inverse_transform(phase_wedge)
        phase_ring_img = masker.inverse_transform(phase_ring)
        phase_hemo_img = masker.inverse_transform(phase_hemo)

        phase_wedge_img.to_filename(pjoin(write_dir, 'phase_wedge.nii.gz'))
        phase_ring_img.to_filename(pjoin(write_dir, 'phase_ring.nii.gz'))
Beispiel #9
0
X_test = nibabel.Nifti1Image(niimgs.get_data()[:, :, :, condition_mask_test],
                             niimgs.get_affine())
y_test = target[condition_mask_test]

y_train[y_train == 'scissors'] = 1
y_train[y_train == 'scrambledpix'] = -1
y_train = np.array(y_train.astype('double'))

y_test[y_test == 'scissors'] = 1
y_test[y_test == 'scrambledpix'] = -1
y_test = np.array(y_test.astype('double'))

masker = NiftiMasker(mask_strategy='epi', standardize=True)

X_train = masker.fit_transform(X_train)
X_test = masker.transform(X_test)

mask = masker.mask_img_.get_data().astype(np.bool)
mask = _crop_mask(mask)
background_img = mean_img(data_files.func[0])

X_train, y_train, _, y_train_mean, _ = center_data(X_train,
                                                   y_train,
                                                   fit_intercept=True,
                                                   normalize=False,
                                                   copy=False)
X_test -= X_train.mean(axis=0)
X_test /= np.std(X_train, axis=0)
alpha = 1
ratio = 0.5
k = 200
Beispiel #10
0
# get HCP data
HCP_contrasts = [
    'REWARD-PUNISH', 'PUNISH-REWARD', 'SHAPES-FACES', 'FACES-SHAPES',
    'RANDOM-TOM', 'TOM-RANDOM', 'MATH-STORY', 'STORY-MATH', 'T-AVG', 'F-H',
    'H-F', 'MATCH-REL', 'REL-MATCH', 'BODY-AVG', 'FACE-AVG', 'PLACE-AVG',
    'TOOL-AVG', '2BK-0BK'
]
mean_supp = np.zeros((18, mask_nvox))
from nilearn.image import resample_img
for itask, task in enumerate(HCP_contrasts):
    cur_nii = op.join(means_path, 'mean_%s.nii.gz' % (task))
    print(cur_nii)
    res_nii = resample_img(cur_nii,
                           target_affine=nifti_masker.mask_img_.get_affine(),
                           target_shape=nifti_masker.mask_img_.shape)
    task_mean = nifti_masker.transform(res_nii)
    mean_supp[itask, :] = task_mean
mean_supp_z = zscore(mean_supp, axis=1)

# get classification weights
lr_supp = np.load(op.join(LR_DIR, 'V0comps.npy'))
lr_supp_z = zscore(lr_supp, axis=1)

# get LR/AE weights
WRITE_DIR = 'nips3mm_recovery'
lambs = [0.25, 0.5, 0.75, 1]
import re
from scipy.stats import pearsonr
for n_comp in [5]:
    corr_means_lr = np.zeros((len(lambs), 18))
    corr_means_lr_ae = np.zeros((len(lambs), 18))
### Visualize the mask ########################################################
import matplotlib.pyplot as plt
import numpy as np
import nibabel
plt.figure()
plt.axis('off')
plt.imshow(np.rot90(nibabel.load(dataset.func[0]).get_data()[..., 20, 0]),
          interpolation='nearest', cmap=plt.cm.gray)
ma = np.ma.masked_equal(mask, False)
plt.imshow(np.rot90(ma[..., 20]), interpolation='nearest', cmap=plt.cm.autumn,
          alpha=0.5)
plt.title("Mask")

### Preprocess data ###########################################################
nifti_masker.fit(dataset.func[0])
fmri_masked = nifti_masker.transform(dataset.func[0])

### Run an algorithm ##########################################################
from sklearn.decomposition import FastICA
n_components = 20
ica = FastICA(n_components=n_components, random_state=42)
components_masked = ica.fit_transform(fmri_masked.T).T

### Reverse masking ###########################################################
components = nifti_masker.inverse_transform(components_masked)

### Show results ##############################################################
components_data = np.ma.masked_equal(components.get_data(), 0)
plt.figure()
plt.axis('off')
plt.imshow(np.rot90(nibabel.load(dataset.func[0]).get_data()[..., 20, 0]),
Beispiel #12
0
class FirstLevelGLM(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for Single-session fMRI data

    Parameters
    ----------
    mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters.

    target_affine: 3x3 or 4x4 matrix, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    target_shape: 3-tuple of integers, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    low_pass: False or float, optional
        This parameter is passed to nilearn.signal.clean.
        Please see the related documentation for details.

    high_pass: False or float, optional
        This parameter is passed to nilearn.signal.clean.
        Please see the related documentation for details.

    t_r: float, optional
        This parameter is passed to nilearn.signal.clean.
        Please see the related documentation for details.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory: instance of joblib.Memory or string
        Used to cache the masking process.
        By default, no caching is done. If a string is given, it is the
        path to the caching directory.

    memory_level: integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    standardize : boolean, optional
        If standardize is True, the time-series are centered and normed:
        their variance is put to 1 in the time dimension.

    percent_signal_change: bool, optional,
        If True, fMRI signals are scaled to percent of the mean value
        Incompatible with standardize (standardize=False is enforced when\
        percent_signal_change is True).

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.

    noise_model : {'ar1', 'ols'}, optional
        the temporal variance model. Defaults to 'ar1'

    Attributes
    ----------
    labels : array of shape (n_voxels,),
        a map of values on voxels used to identify the corresponding model

    results : dict,
        with keys corresponding to the different labels values
        values are RegressionResults instances corresponding to the voxels
    """

    def __init__(self, mask=None, target_affine=None, target_shape=None,
             low_pass=None, high_pass=None, t_r=None, smoothing_fwhm=None,
             memory=Memory(None), memory_level=1, standardize=False,
             percent_signal_change=True, verbose=1, n_jobs=1,
             noise_model='ar1'):
        self.mask = mask
        self.memory = memory
        self.memory_level = memory_level
        self.verbose = verbose
        self.standardize = standardize
        self.n_jobs = n_jobs
        self.low_pass = low_pass
        self.high_pass = high_pass
        self.t_r = t_r
        self.target_affine = target_affine
        self.target_shape = target_shape
        self.smoothing_fwhm = smoothing_fwhm
        self.noise_model = noise_model
        self.percent_signal_change = percent_signal_change
        if self.percent_signal_change:
            self.standardize = False

    def fit(self, imgs, design_matrices):
        """ Fit the GLM

        1. does a masker job: fMRI_data -> Y
        2. fit an ols regression to (Y, X)
        3. fit an AR(1) regression of require
        This results in an internal (labels_, regression_results_) parameters

        Parameters
        ----------
        imgs: Niimg-like object or list of Niimg-like objects,
            See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
            Data on which the GLM will be fitted. If this is a list,
            the affine is considered the same for all.

        design_matrices: pandas DataFrame or list of pandas DataFrames,
            fMRI design matrices
        """
        # First, learn the mask
        if not isinstance(self.mask, NiftiMasker):
            self.masker_ = NiftiMasker(
                mask_img=self.mask, smoothing_fwhm=self.smoothing_fwhm,
                target_affine=self.target_affine,
                standardize=self.standardize, low_pass=self.low_pass,
                high_pass=self.high_pass, mask_strategy='epi',
                t_r=self.t_r, memory=self.memory,
                verbose=max(0, self.verbose - 1),
                target_shape=self.target_shape,
                memory_level=self.memory_level)
        else:
            self.masker_ = clone(self.mask)
            for param_name in ['target_affine', 'target_shape',
                               'smoothing_fwhm', 'low_pass', 'high_pass',
                               't_r', 'memory', 'memory_level']:
                our_param = getattr(self, param_name)
                if our_param is None:
                    continue
                if getattr(self.masker_, param_name) is not None:
                    warn('Parameter %s of the masker overriden' % param_name)
                setattr(self.masker_, param_name, our_param)

        # make design_matrices a list of arrays
        if isinstance(design_matrices, (_basestring, pd.DataFrame)):
            design_matrices_ = [design_matrices]
        else:
            design_matrices_ = [X for X in design_matrices]

        design_matrices = []
        for design_matrix in design_matrices_:
            if isinstance(design_matrix, _basestring):
                loaded = pd.read_csv(design_matrix, index_col=0)
                design_matrices.append(loaded.values)
            elif isinstance(design_matrix, pd.DataFrame):
                design_matrices.append(design_matrix.values)
            else:
                raise TypeError(
                    'Design matrix can only be a pandas DataFrames or a'
                    'string. A %s was provided' % type(design_matrix))

        # make imgs a list of Nifti1Images
        if isinstance(imgs, (Nifti1Image, _basestring)):
            imgs = [imgs]

        if len(imgs) != len(design_matrices):
            raise ValueError(
                'len(imgs) %d does not match len(design_matrices) %d'
                % (len(imgs), len(design_matrices)))

        # Loop on imgs and design matrices
        self.labels_, self.results_ = [], []
        self.masker_.fit(imgs)
        for X, img in zip(design_matrices, imgs):
            Y = self.masker_.transform(img)
            if self.percent_signal_change:
                Y, _ = percent_mean_scaling(Y)
            labels_, results_ = session_glm(
                Y, X, noise_model=self.noise_model, bins=100)
            self.labels_.append(labels_)
            self.results_.append(results_)
        return self

    def transform(self, con_vals, contrast_type=None, contrast_name='',
                  output_z=True, output_stat=False, output_effects=False,
                  output_variance=False):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.
        In multi-session case, outputs the fixed effects map.

        Parameters
        ----------
        con_vals : array or list of arrays of shape (n_col) or (n_dim, n_col)
            where ``n_col`` is the number of columns of the design matrix,
            numerical definition of the contrast (one array per run)

        contrast_type : {'t', 'F'}, optional
            type of the contrast

        contrast_name : str, optional
            name of the contrast

        output_z : bool, optional
            Return or not the corresponding z-stat image

        output_stat : bool, optional
            Return or not the base (t/F) stat image

        output_effects : bool, optional
            Return or not the corresponding effect image

        output_variance : bool, optional
            Return or not the corresponding variance image

        Returns
        -------
        output_images : list of Nifti1Images
            The desired output images

        """
        if self.labels_ is None or self.results_ is None:
            raise ValueError('The model has not been fit yet')

        if isinstance(con_vals, np.ndarray):
            con_vals = [con_vals]
        if len(con_vals) != len(self.results_):
            raise ValueError(
                'contrasts must be a sequence of %d session contrasts' %
                len(self.results_))

        contrast = None
        for i, (labels_, results_, con_val) in enumerate(zip(
                self.labels_, self.results_, con_vals)):
            if np.all(con_val == 0):
                warn('Contrast for session %d is null' % i)
            contrast_ = compute_contrast(labels_, results_, con_val,
                                         contrast_type)
            if contrast is None:
                contrast = contrast_
            else:
                contrast = contrast + contrast_

        if output_z or output_stat:
            # compute the contrast and stat
            contrast.z_score()

        # Prepare the returned images
        do_outputs = [output_z, output_stat, output_effects, output_variance]
        estimates = ['z_score_', 'stat_', 'effect', 'variance']
        descrips = ['z statistic', 'Statistical value', 'Estimated effect',
                    'Estimated variance']
        output_images = []
        for do_output, estimate, descrip in zip(
                do_outputs, estimates, descrips):
            if not do_output:
                continue
            estimate_ = getattr(contrast, estimate)
            if estimate_.ndim == 3:
                shape_ = estimate_.shape
                estimate_ = np.reshape(estimate_,
                                       (shape_[0] * shape_[1], shape_[2]))
            output = self.masker_.inverse_transform(estimate_)
            output.get_header()['descrip'] = (
                '%s of contrast %s' % (descrip, contrast_name))
            output_images.append(output)
        return output_images

    def fit_transform(
        self, design_matrices, fmri_images, con_vals, contrast_type=None,
        contrast_name='', output_z=True, output_stat=False,
        output_effects=False, output_variance=False):
        """ Fit then transform. For more details,
        see FirstLevelGLM.fit and FirstLevelGLM.transform documentation"""
        return self.fit(design_matrices, fmri_images).transform(
            con_vals, contrast_type, contrast_name, output_z=True,
            output_stat=False, output_effects=False, output_variance=False)
Beispiel #13
0
labels = [0 if label==-1 else label for label in labels]
AT_labels = [0 if label==-1 else label for label in AT_labels]

labels = np.int32(labels)
AT_labels = np.int32(AT_labels)

# contrasts are IN ORDER -> shuffle!
new_inds = np.arange(0, X_task.shape[0])
np.random.shuffle(new_inds)
X_task = X_task[new_inds]
labels = labels[new_inds]
# subs = subs[new_inds]

# Resting state data
# Modified by @Gabighz
X_rest = nifti_masker.transform(rest_img)
# X_rest = nifti_masker.transform('dump_rs_spca_s12_tmp')
rs_spca_data = nib.load(rest_img) # was: joblib.load('dump_rs_spca_s12_tmp')
rs_spca_niis = nib.Nifti1Image(rs_spca_data,
                               nifti_masker.mask_img_.affine)
#X_rest = nifti_masker.transform(rs_spca_niis)
del rs_spca_niis
del rs_spca_data

X_task = StandardScaler().fit_transform(X_task)
X_rest = StandardScaler().fit_transform(X_rest)

# ARCHI Task
# NOTE: Used to test out-of-dataset performance
# was AT_niis, AT_labels, AT_subs = joblib.load('preload_AT_3mm')
AT_niis = nib.load(ARCHI_out_of_dataset)
import nibabel
pl.figure()
pl.axis('off')
pl.imshow(np.rot90(nibabel.load(dataset.func[0]).get_data()[..., 20, 0]),
          interpolation='nearest',
          cmap=pl.cm.gray)
ma = np.ma.masked_equal(mask, False)
pl.imshow(np.rot90(ma[..., 20]),
          interpolation='nearest',
          cmap=pl.cm.autumn,
          alpha=0.5)
pl.title("Mask")

### Preprocess data ###########################################################
nifti_masker.fit(dataset.func[0])
fmri_masked = nifti_masker.transform(dataset.func[0])

### Run an algorithm ##########################################################
from sklearn.decomposition import FastICA
n_components = 20
ica = FastICA(n_components=n_components, random_state=42)
components_masked = ica.fit_transform(fmri_masked.T).T

### Reverse masking ###########################################################
components = nifti_masker.inverse_transform(components_masked)

### Show results ##############################################################
components_data = np.ma.masked_equal(components.get_data(), 0)
pl.figure()
pl.axis('off')
pl.imshow(np.rot90(nibabel.load(dataset.func[0]).get_data()[..., 20, 0]),
Beispiel #15
0
from glob import glob
import numpy as np
import os
from nilearn.image import new_img_like
from nilearn.input_data import NiftiMasker
from nilearn.image import resample_to_img

example_img = nib.load(os.path.join("movie_files", "sherlock_movie_s1.nii"))
mask_img = nib.load("sherlock_roi.nii.gz")
mask_img = resample_to_img(mask_img, example_img, interpolation="nearest")
masker = NiftiMasker(
    mask_img=mask_img,
    standardize=True,
    smoothing_fwhm=None,
    detrend=True,
    high_pass=1.0 / 140,
    t_r=1.5,
).fit()

# Let us first split sherlock data into 5 runs
for i, f in enumerate(glob(os.path.join("movie_files", "*"))):
    niimg = nib.load(f)
    X = niimg.get_data()
    X = np.array_split(X, 5, axis=-1)
    for j, x in enumerate(X):
        os.makedirs("masked_movie_files", exist_ok=True)
        np.save(
            os.path.join("masked_movie_files", "sub%i_run%i" % (i, j)),
            masker.transform(new_img_like(niimg, x)).T,
        )
Beispiel #16
0
    def fit(self, imgs, confounds=None):
        """
        Compute the mask and the dynamic parcels across datasets.

        Parameters
        ----------
        imgs: list of Niimg-like objects
            See http://nilearn.github.io/manipulating_images/input_output.html
            Data on which the mask is calculated. If this is a list,
            the affine is considered the same for all.

        confounds: list of CSV file paths or 2D matrices
            This parameter is passed to nilearn.signal.clean. Please see the
            related documentation for details. Should match with the list
            of imgs given.

         Returns
         -------
         self: object
            Returns the instance itself. Contains attributes listed
            at the object level.
        """
        self.masker_ = check_embedded_nifti_masker(self)
        imgs, confounds = self._sanitize_imgs(imgs, confounds)

        # Avoid warning with imgs != None
        # if masker_ has been provided a mask_img
        if self.masker_.mask_img is None:
            self.masker_.fit(imgs)
        else:
            self.masker_.fit()
        self.mask_img_ = self.masker_.mask_img_

        # Load grey_matter segmentation
        if self.grey_matter == "MNI":
            mni = datasets.fetch_icbm152_2009()
            self.grey_matter = mni.gm

        if self.grey_matter is not None:
            masker_anat = NiftiMasker(
                mask_img=self.mask_img_, smoothing_fwhm=self.smoothing_fwhm
            )
            masker_anat.fit(self.grey_matter)
            grey_matter = masker_anat.transform(self.grey_matter)
            self.weights_grey_matter_ = (
                1 - grey_matter
            ) + self.std_grey_matter * grey_matter
        else:
            self.weights_grey_matter_ = None

        # Control random number generation
        self.random_state = check_random_state(self.random_state)

        # Check that number of batches is reasonable
        if self.n_batch > len(imgs):
            warnings.warn(
                "{0} batches were requested, but only {1} datasets available. Using one dataset per batch instead.".format(
                    self.n_batch, len(imgs)
                )
            )
            self.n_batch = len(imgs)

        # mask_and_reduce step
        if self.n_batch > 1:
            stab_maps, dwell_time = self._mask_and_reduce_batch(imgs, confounds)
        else:
            stab_maps, dwell_time = self._mask_and_reduce(imgs, confounds)

        # Return components
        self.components_ = stab_maps
        self.dwell_time_ = dwell_time

        # Create embedding
        self.embedding = Embedding(stab_maps.todense())
        return self
Beispiel #17
0
masker.fit()

n_files = len(nii_paths)
n_vox = r_mask.get_data().sum()

if op.exists('dump_FS.npy'):
    FS = np.load('dump_FS.npy')
    cond_labels = np.load('dump_cond.npy')
    sub_labels = np.load('dump_subs.npy')
else:
    FS = np.zeros((n_files, n_vox))
    for i_nii in range(n_files):
        print('Loading nifti into memory: %i/%i' % (i_nii + 1, n_files))
        data = np.nan_to_num(nib.load(nii_paths[i_nii]).get_data())
        nii = nib.Nifti1Image(data, r_mask.get_affine())
        cur_1d_data = masker.transform(nii)
        FS[i_nii, :] = cur_1d_data

    # save feature space to disk
    np.save('dump_FS', FS)
    np.save('dump_cond', cond_labels)
    np.save('dump_subs', sub_labels)

from sklearn.preprocessing import StandardScaler

FS = StandardScaler().fit_transform(FS)
labels = cond_labels

# type conversion
FS = np.float32(FS)
labels = np.int32(labels)
Beispiel #18
0
def map_threshold(stat_img=None,
                  mask_img=None,
                  level=.001,
                  height_control='fpr',
                  cluster_threshold=0):
    """ Compute the required threshold level and return the thresholded map

    Parameters
    ----------
    stat_img : Niimg-like object or None, optional
       statistical image (presumably in z scale)
       whenever height_control is 'fpr' or None,
       stat_img=None is acceptable.
       If it is 'fdr' or 'bonferroni', an error is raised if stat_img is None.

    mask_img : Niimg-like object, optional,
        mask image

    level: float, optional
        number controling the thresholding (either a p-value or z-scale value).
        Not to be confused with the z-scale threshold: level can be a p-values,
        e.g. "0.05" or another type of number depending on the
        height_control parameter. The z-scale threshold is actually returned by
        the function.

    height_control: string, or None optional
        false positive control meaning of cluster forming
        threshold: 'fpr'|'fdr'|'bonferroni'\|None

    cluster_threshold : float, optional
        cluster size threshold. In the returned thresholded map,
        sets of connected voxels (`clusters`) with size smaller
        than this number will be removed.

    Returns
    -------
    thresholded_map : Nifti1Image,
        the stat_map thresholded at the prescribed voxel- and cluster-level

    threshold: float,
        the voxel-level threshold used actually

    Note
    ----
    If the input image is not z-scaled (i.e. some z-transformed statistic)
    the computed threshold is not rigorous and likely meaningless
    """
    # Check that height_control is correctly specified
    if height_control not in ['fpr', 'fdr', 'bonferroni', None]:
        raise ValueError(
            "height control should be one of ['fpr', 'fdr', 'bonferroni', None]"
        )

    # if height_control is 'fpr' or None, we don't need to look at the data
    # to compute the threhsold
    if height_control == 'fpr':
        threshold = norm.isf(level)
    elif height_control is None:
        threshold = level

    # In this case, and is stat_img is None, we return
    if stat_img is None:
        if height_control in ['fpr', None]:
            return None, threshold
        else:
            raise ValueError(
                'Map_threshold requires stat_img not to be None'
                'when the heigh_control procedure is bonferroni or fdr')

    # Masking
    if mask_img is None:
        masker = NiftiMasker(mask_strategy='background').fit(stat_img)
    else:
        masker = NiftiMasker(mask_img=mask_img).fit()
    stats = np.ravel(masker.transform(stat_img))
    n_voxels = np.size(stats)

    # Thresholding
    if height_control == 'fdr':
        threshold = fdr_threshold(stats, level)
    elif height_control == 'bonferroni':
        threshold = norm.isf(level / n_voxels)
    stats *= (stats > threshold)

    # embed it back to 3D grid
    stat_map = masker.inverse_transform(stats).get_data()

    # Extract connected components above threshold
    label_map, n_labels = label(stat_map > threshold)
    labels = label_map[masker.mask_img_.get_data() > 0]

    for label_ in range(1, n_labels + 1):
        if np.sum(labels == label_) < cluster_threshold:
            stats[labels == label_] = 0

    return masker.inverse_transform(stats), threshold
    masker = NiftiMasker(
        mask_img=mask_img, memory='nilearn_cache', memory_level=1)
    masker = masker.fit()

    # Images may fail to be transformed, and are of different shapes,
    # so we need to transform one-by-one and keep track of failures.
    X = []
    is_usable = np.ones((len(images),), dtype=bool)

    for index, image_path in enumerate(images):
        # load image and remove nan and inf values.
        # applying smooth_img to an image with fwhm=None simply cleans up
        # non-finite values but otherwise doesn't modify the image.
        image = smooth_img(image_path, fwhm=None)
        try:
            X.append(masker.transform(image))
        except Exception as e:
            meta = nv_data['images_meta'][index]
            print("Failed to mask/reshape image: id: {0}; "
                  "name: '{1}'; collection: {2}; error: {3}".format(
                      meta.get('id'), meta.get('name'),
                      meta.get('collection_id'), e))
            is_usable[index] = False

# Now reshape list into 2D matrix, and remove failed images from terms
X = np.vstack(X)
term_weights = term_weights[is_usable, :]


######################################################################
# Run ICA and map components to terms
Beispiel #20
0
            print contr_name
            mri_file = op.join(write_dir, 'mean_' + contr_name + '.nii.gz')
            cur_imgs = stat_paths[key][y_contr[key] == i]
            mean_nifti = mean_img(cur_imgs)
            mean_nifti.to_filename(mri_file)
            
            print "comparing %s with..." % mri_file
            for i_compr, compr_name in enumerate(compr_names):
                for i_ana in range(4):
                    fname_tag = compr_name + '*' + contr_name + '*.nii*'
                    search_str = op.join(reconstr_dir, 'compr2task_' +
                        analysis_modes[4 * i_key + i_ana] + '_' + PEN, fname_tag)
                    l = glob.glob(search_str)
                    print "- %s" % l
                    
                    arr1 = masker.transform(mean_nifti)[0]
                    arr2 = masker.transform(l[0])[0]
                    
                    rho, p = pearsonr(arr1, arr2)
                    mat_rho[key][i_compr, i, i_ana] = rho
                    
                    L1 = np.sum(np.abs(arr1 - arr2))
                    mat_L1[key][i_compr, i, i_ana] = L1
            print '-' * 80

            # render mean
            # my_min = 0.1
            # my_max = 1.5
            # brain = Brain("fsaverage", "split", "inflated",
            #               views=['lat', 'med'],
            #               config_opts=dict(background="black"))
def aCompCor_Muschelli(data_dir, out_dir, subj, task, ventricle_file):
    '''
    data_dir: [string] path to fmriprep output directory, containing subject directories.
    out_dir: [string] path to directory to save aCompCor results to.
    subj: [string] subject ID as it is exists in the fmriprep output directory (e.g. sub-001)
    task: [string] task ID in the BIDS formatted file name.
        e.g. 'stress' for file sub-001_task-stress_bold_space-MNI152NLin2009cAsym_preproc.nii.gz
        If a task has multiple runs, include the run in this variable.
        e.g. rest_run-01 for sub-001_task-rest_run-01_bold_space-MNI152NLin2009cAsym_preproc.nii.gz
    ventricle_file: [string] path and name of ALVIN ventricle mask nifti file.
        Download from https://sites.google.com/site/mrilateralventricle/
    '''
    import os
    import numpy as np
    import pandas as pd
    import nibabel as nib
    from scipy.ndimage.morphology import binary_erosion
    from nilearn.image import resample_img, math_img
    from nilearn.input_data import NiftiMasker
    from sklearn.decomposition import PCA

    print(
        'Performing aCompCor (Muschelli et al. 2014, Neuroimage) on \n subject: %s \n task: %s'
        % (subj, task))
    if not os.path.isdir(os.path.join(out_dir, subj, 'PCA')):
        os.makedirs(os.path.join(out_dir, subj, 'PCA'))
    if not os.path.isdir(os.path.join(out_dir, subj, 'masks')):
        os.makedirs(os.path.join(out_dir, subj, 'masks'))
    ##### White Matter
    WM_file = nib.load(
        os.path.join(
            data_dir, subj, 'anat', subj +
            '_T1w_space-MNI152NLin2009cAsym_class-WM_probtissue.nii.gz'))
    WM_mask = WM_file.get_fdata()
    WM_mask[WM_mask < (np.max(WM_mask) * .99)] = 0
    WM_mask[WM_mask >= (np.max(WM_mask) * .99)] = 1
    WM_mask = binary_erosion(WM_mask).astype(WM_mask.dtype)
    nib.save(
        nib.Nifti1Image(WM_mask, WM_file.affine, WM_file.header),
        os.path.join(out_dir, subj, 'masks',
                     subj + '_task-' + task + '_WM-aCompCorMask.nii.gz'))
    ##### Cerebral Spinal Fluid
    CSF_file = nib.load(
        os.path.join(
            data_dir, subj, 'anat', subj +
            '_T1w_space-MNI152NLin2009cAsym_class-CSF_probtissue.nii.gz'))
    CSF_mask = CSF_file.get_fdata()
    CSF_mask[CSF_mask < (np.max(CSF_mask) * .99)] = 0
    CSF_mask[CSF_mask >= (np.max(CSF_mask) * .99)] = 1
    ventricle_mask = resample_img(nib.load(ventricle_file),
                                  target_affine=CSF_file.affine,
                                  target_shape=CSF_file.shape,
                                  interpolation='nearest')
    CSF_mask = np.multiply(CSF_mask, ventricle_mask.get_fdata())
    nib.save(
        nib.Nifti1Image(CSF_mask, CSF_file.affine, CSF_file.header),
        os.path.join(out_dir, subj, 'masks',
                     subj + '_task-' + task + '_CSF-aCompCorMask.nii.gz'))

    ##### Mask functional data and perform PCA.
    func_file = nib.load(
        os.path.join(
            data_dir, subj, 'func', subj + '_task-' + task +
            '_bold_space-MNI152NLin2009cAsym_preproc.nii.gz'))
    conf_file = os.path.join(data_dir, subj, 'func',
                             subj + '_task-' + task + '_bold_confounds.tsv')

    CSF_fit = resample_img(nib.load(
        os.path.join(out_dir, subj, 'masks',
                     subj + '_task-' + task + '_CSF-aCompCorMask.nii.gz')),
                           target_affine=func_file.affine,
                           target_shape=func_file.shape[0:3],
                           interpolation='nearest')
    WM_fit = resample_img(nib.load(
        os.path.join(out_dir, subj, 'masks',
                     subj + '_task-' + task + '_WM-aCompCorMask.nii.gz')),
                          target_affine=func_file.affine,
                          target_shape=func_file.shape[0:3],
                          interpolation='nearest')
    # White Matter PCA
    niftimask = NiftiMasker(dtype='float32')
    niftimask.fit(math_img('img > 0', img=WM_fit))
    func_WM = niftimask.transform(func_file)
    runPCA = PCA()
    PCA_WM = runPCA.fit(func_WM)
    WM_out = pd.DataFrame(PCA_WM.components_)
    WM_out.columns = [
        'aCompCorWMnoFilter' + str(col) for col in WM_out.columns
    ]
    WM_out.to_csv(os.path.join(out_dir, subj, 'PCA',
                               subj + '_task-' + task + '_WM-aCompCor.csv'),
                  index=False)

    # CSF PCA
    niftimask = NiftiMasker(dtype='float32')
    niftimask.fit(math_img('img > 0', img=CSF_fit))
    func_CSF = niftimask.transform(func_file)
    runPCA = PCA()
    PCA_CSF = runPCA.fit(func_CSF)
    CSF_out = pd.DataFrame(PCA_CSF.components_)
    CSF_out.columns = [
        'aCompCorCSFnoFilter' + str(col) for col in CSF_out.columns
    ]
    CSF_out.to_csv(os.path.join(out_dir, subj, 'PCA',
                                subj + '_task-' + task + '_CSF-aCompCor.csv'),
                   index=False)

    # % Variance components
    var_out = pd.DataFrame({
        'var_WM':
        PCA_WM.explained_variance_,
        'percent_var_WM':
        PCA_WM.explained_variance_ratio_,
        'var_CSF':
        PCA_CSF.explained_variance_,
        'percent_var_CSF':
        PCA_CSF.explained_variance_ratio_,
    })
    var_out.to_csv(
        os.path.join(out_dir, subj, 'PCA',
                     subj + '_task-' + task + '_variance-aCompCor.csv'))
Beispiel #22
0
anat_filename = haxby_dataset.anat[subject_idx]
anat_img = nibabel.load(anat_filename)
fmri_filename = haxby_dataset.func[subject_idx]
fmri_raw_img = nibabel.load(fmri_filename)
shared_affine = fmri_raw_img.get_affine()

print("Build a mask based on the activations.")
epi_masker = NiftiMasker(mask_strategy='epi', detrend=True, standardize=True)
epi_masker = mem.cache(epi_masker.fit)(fmri_raw_img)
plot_roi(epi_masker.mask_img_,
         title='EPI mask',
         cut_coords=cut_coords)

print("Normalize the (transformed) data")  # zscore per pixel, over examples.
from scipy import stats
fmri_masked_vectors = epi_masker.transform(fmri_raw_img)
import pdb; pdb.set_trace()
fmri_normed_vectors = mem.cache(stats.mstats.zscore)(fmri_masked_vectors, axis=0)
fmri_normed_img = epi_masker.inverse_transform(fmri_normed_vectors)

print("Smooth the (spatial) data.")
from nilearn import image
fmri_smooth_img = mem.cache(image.smooth_img)(fmri_normed_img, fwhm=1)

print("Mask the MRI data.")
masked_fmri_vectors = mem.cache(epi_masker.transform)(fmri_smooth_img)
fmri_masked_img = epi_masker.inverse_transform(masked_fmri_vectors)

print("Plot the mean image.")
fig_id = plt.subplot(2, 1, 1)
mean_img = mem.cache(image.mean_img)(fmri_masked_img)
Beispiel #23
0
class SecondLevelModel(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for multiple subject
    fMRI data

    Parameters
    ----------

    mask_img: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters. Automatic mask computation assumes first level imgs have
        already been masked.

    target_affine : 3x3 or 4x4 matrix, optional
        This parameter is passed to :func:`nilearn.image.resample_img`.
        Please see the related documentation for details.

    target_shape : 3-tuple of integers, optional
        This parameter is passed to :func:`nilearn.image.resample_img`.
        Please see the related documentation for details.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory: string, optional
        Path to the directory used to cache the masking process and the glm
        fit. By default, no caching is done. Creates instance of joblib.Memory.

    memory_level: integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.
        If 0 prints nothing. If 1 prints final computation time.
        If 2 prints masker computation details.

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    minimize_memory : boolean, optional
        Gets rid of some variables on the model fit results that are not
        necessary for contrast computation and would only be useful for
        further inspection of model details. This has an important impact
        on memory consumption. True by default.

    """
    def __init__(self,
                 mask_img=None,
                 target_affine=None,
                 target_shape=None,
                 smoothing_fwhm=None,
                 memory=Memory(None),
                 memory_level=1,
                 verbose=0,
                 n_jobs=1,
                 minimize_memory=True):
        self.mask_img = mask_img
        self.target_affine = target_affine
        self.target_shape = target_shape
        self.smoothing_fwhm = smoothing_fwhm
        if isinstance(memory, str):
            self.memory = Memory(memory)
        else:
            self.memory = memory
        self.memory_level = memory_level
        self.verbose = verbose
        self.n_jobs = n_jobs
        self.minimize_memory = minimize_memory
        self.second_level_input_ = None
        self.confounds_ = None

    def fit(self, second_level_input, confounds=None, design_matrix=None):
        """ Fit the second-level GLM

        1. create design matrix
        2. do a masker job: fMRI_data -> Y
        3. fit regression to (Y, X)

        Parameters
        ----------
        second_level_input: list of `FirstLevelModel` objects or pandas
                            DataFrame or list of Niimg-like objects.

            Giving FirstLevelModel objects will allow to easily compute
            the second level contast of arbitrary first level contrasts thanks
            to the first_level_contrast argument of the compute_contrast
            method. Effect size images will be computed for each model to
            contrast at the second level.

            If a pandas DataFrame, then they have to contain subject_label,
            map_name and effects_map_path. It can contain multiple maps that
            would be selected during contrast estimation with the argument
            first_level_contrast of the compute_contrast function. The
            DataFrame will be sorted based on the subject_label column to avoid
            order inconsistencies when extracting the maps. So the rows of the
            automatically computed design matrix, if not provided, will
            correspond to the sorted subject_label column.

            If list of Niimg-like objects then this is taken literally as Y
            for the model fit and design_matrix must be provided.

        confounds: pandas DataFrame, optional
            Must contain a subject_label column. All other columns are
            considered as confounds and included in the model. If
            design_matrix is provided then this argument is ignored.
            The resulting second level design matrix uses the same column
            names as in the given DataFrame for confounds. At least two columns
            are expected, "subject_label" and at least one confound.

        design_matrix: pandas DataFrame, optional
            Design matrix to fit the GLM. The number of rows
            in the design matrix must agree with the number of maps derived
            from second_level_input.
            Ensure that the order of maps given by a second_level_input
            list of Niimgs matches the order of the rows in the design matrix.

        """
        # Prevent circular imports between reporting & stats module
        from nilearn.input_data import NiftiMasker  # noqa

        # check second_level_input
        _check_second_level_input(second_level_input,
                                  design_matrix,
                                  confounds=confounds)

        # check confounds
        _check_confounds(confounds)

        # check design matrix
        _check_design_matrix(design_matrix)

        # sort a pandas dataframe by subject_label to avoid inconsistencies
        # with the design matrix row order when automatically extracting maps
        if isinstance(second_level_input, pd.DataFrame):
            columns = second_level_input.columns.tolist()
            column_index = columns.index('subject_label')
            sorted_matrix = sorted(second_level_input.values,
                                   key=lambda x: x[column_index])
            sorted_input = pd.DataFrame(sorted_matrix, columns=columns)
            second_level_input = sorted_input

        self.second_level_input_ = second_level_input
        self.confounds_ = confounds

        # Report progress
        t0 = time.time()
        if self.verbose > 0:
            sys.stderr.write("Fitting second level model. "
                             "Take a deep breath\r")

        # Select sample map for masker fit and get subjects_label for design
        if isinstance(second_level_input, pd.DataFrame):
            sample_map = second_level_input['effects_map_path'][0]
            labels = second_level_input['subject_label']
            subjects_label = labels.values.tolist()
        elif isinstance(second_level_input, Nifti1Image):
            sample_map = mean_img(second_level_input)
        elif isinstance(second_level_input[0], FirstLevelModel):
            sample_model = second_level_input[0]
            sample_condition = sample_model.design_matrices_[0].columns[0]
            sample_map = sample_model.compute_contrast(
                sample_condition, output_type='effect_size')
            labels = [model.subject_label for model in second_level_input]
            subjects_label = labels
        else:
            # In this case design matrix had to be provided
            sample_map = mean_img(second_level_input)

        # Create and set design matrix, if not given
        if design_matrix is None:
            design_matrix = make_second_level_design_matrix(
                subjects_label, confounds)
        self.design_matrix_ = design_matrix

        # Learn the mask. Assume the first level imgs have been masked.
        if not isinstance(self.mask_img, NiftiMasker):
            self.masker_ = NiftiMasker(mask_img=self.mask_img,
                                       target_affine=self.target_affine,
                                       target_shape=self.target_shape,
                                       smoothing_fwhm=self.smoothing_fwhm,
                                       memory=self.memory,
                                       verbose=max(0, self.verbose - 1),
                                       memory_level=self.memory_level)
        else:
            self.masker_ = clone(self.mask_img)
            for param_name in ['smoothing_fwhm', 'memory', 'memory_level']:
                our_param = getattr(self, param_name)
                if our_param is None:
                    continue
                if getattr(self.masker_, param_name) is not None:
                    warn('Parameter %s of the masker overriden' % param_name)
                setattr(self.masker_, param_name, our_param)
        self.masker_.fit(sample_map)

        # Report progress
        if self.verbose > 0:
            sys.stderr.write("\nComputation of second level model done in "
                             "%i seconds\n" % (time.time() - t0))

        return self

    def compute_contrast(self,
                         second_level_contrast=None,
                         first_level_contrast=None,
                         second_level_stat_type=None,
                         output_type='z_score'):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.

        Parameters
        ----------
        second_level_contrast: str or array of shape (n_col), optional
            Where ``n_col`` is the number of columns of the design matrix. The
            string can be a formula compatible with `pandas.DataFrame.eval`.
            Basically one can use the name of the conditions as they appear in
            the design matrix of the fitted model combined with operators +-
            and combined with numbers with operators +-`*`/. The default (None)
            is accepted if the design matrix has a single column, in which case
            the only possible contrast array((1)) is applied; when the design
            matrix has multiple columns, an error is raised.

        first_level_contrast: str or array of shape (n_col) with respect to
                              FirstLevelModel, optional

            In case a list of FirstLevelModel was provided as
            second_level_input, we have to provide a contrast to apply to
            the first level models to get the corresponding list of images
            desired, that would be tested at the second level. In case a
            pandas DataFrame was provided as second_level_input this is the
            map name to extract from the pandas dataframe map_name column.
            It has to be a 't' contrast.

        second_level_stat_type: {'t', 'F'}, optional
            Type of the second level contrast

        output_type: str, optional
            Type of the output map. Can be 'z_score', 'stat', 'p_value',
            'effect_size', 'effect_variance' or 'all'

        Returns
        -------
        output_image: Nifti1Image
            The desired output image(s). If ``output_type == 'all'``, then
            the output is a dictionary of images, keyed by the type of image.

        """
        if self.second_level_input_ is None:
            raise ValueError('The model has not been fit yet')

        # check first_level_contrast
        _check_first_level_contrast(self.second_level_input_,
                                    first_level_contrast)

        # check contrast and obtain con_val
        con_val = _get_con_val(second_level_contrast, self.design_matrix_)

        # check output type
        # 'all' is assumed to be the final entry;
        # if adding more, place before 'all'
        valid_types = [
            'z_score', 'stat', 'p_value', 'effect_size', 'effect_variance',
            'all'
        ]
        _check_output_type(output_type, valid_types)

        # Get effect_maps appropriate for chosen contrast
        effect_maps = _infer_effect_maps(self.second_level_input_,
                                         first_level_contrast)
        # Check design matrix X and effect maps Y agree on number of rows
        _check_effect_maps(effect_maps, self.design_matrix_)

        # Fit an Ordinary Least Squares regression for parametric statistics
        Y = self.masker_.transform(effect_maps)
        if self.memory:
            mem_glm = self.memory.cache(run_glm, ignore=['n_jobs'])
        else:
            mem_glm = run_glm
        labels, results = mem_glm(Y,
                                  self.design_matrix_.values,
                                  n_jobs=self.n_jobs,
                                  noise_model='ols')

        # We save memory if inspecting model details is not necessary
        if self.minimize_memory:
            for key in results:
                results[key] = SimpleRegressionResults(results[key])
        self.labels_ = labels
        self.results_ = results

        # We compute contrast object
        if self.memory:
            mem_contrast = self.memory.cache(compute_contrast)
        else:
            mem_contrast = compute_contrast
        contrast = mem_contrast(self.labels_, self.results_, con_val,
                                second_level_stat_type)

        output_types = \
            valid_types[:-1] if output_type == 'all' else [output_type]

        outputs = {}
        for output_type_ in output_types:
            # We get desired output from contrast object
            estimate_ = getattr(contrast, output_type_)()
            # Prepare the returned images
            output = self.masker_.inverse_transform(estimate_)
            contrast_name = str(con_val)
            output.header['descrip'] = ('%s of contrast %s' %
                                        (output_type, contrast_name))
            outputs[output_type_] = output

        return outputs if output_type == 'all' else output
Beispiel #24
0
    'MATH-STORY', 'STORY-MATH',
    'T-AVG', 'F-H', 'H-F',
    'MATCH-REL', 'REL-MATCH',

    'BODY-AVG', 'FACE-AVG', 'PLACE-AVG', 'TOOL-AVG',
    '2BK-0BK'
]
mean_supp = np.zeros((18, mask_nvox))
from nilearn.image import resample_img
for itask, task in enumerate(HCP_contrasts):
    cur_nii = op.join(means_path, 'mean_%s.nii.gz' % (task))
    print(cur_nii)
    res_nii = resample_img(cur_nii,
        target_affine=nifti_masker.mask_img_.get_affine(),
        target_shape=nifti_masker.mask_img_.shape)
    task_mean = nifti_masker.transform(res_nii)
    mean_supp[itask, :] = task_mean
mean_supp_z = zscore(mean_supp, axis=1)
    
# get classification weights
lr_supp = np.load(op.join(LR_DIR, 'V0comps.npy'))
lr_supp_z = zscore(lr_supp, axis=1)

# get LR/AE weights
WRITE_DIR = 'nips3mm_recovery'
lambs = [0.25, 0.5, 0.75, 1]
import re
from scipy.stats import pearsonr
for n_comp in [5]:
    corr_means_lr = np.zeros((len(lambs), 18))
    corr_means_lr_ae = np.zeros((len(lambs), 18))
Beispiel #25
0
def non_parametric_inference(second_level_input,
                             confounds=None,
                             design_matrix=None,
                             second_level_contrast=None,
                             mask=None,
                             smoothing_fwhm=None,
                             model_intercept=True,
                             n_perm=10000,
                             two_sided_test=False,
                             random_state=None,
                             n_jobs=1,
                             verbose=0):
    """Generate p-values corresponding to the contrasts provided
    based on permutation testing. This fuction reuses the 'permuted_ols'
    function Nilearn.

    Parameters
    ----------
    second_level_input: pandas DataFrame or list of Niimg-like objects.

        If a pandas DataFrame, then they have to contain subject_label,
        map_name and effects_map_path. It can contain multiple maps that
        would be selected during contrast estimation with the argument
        first_level_contrast of the compute_contrast function. The
        DataFrame will be sorted based on the subject_label column to avoid
        order inconsistencies when extracting the maps. So the rows of the
        automatically computed design matrix, if not provided, will
        correspond to the sorted subject_label column.

        If list of Niimg-like objects then this is taken literally as Y
        for the model fit and design_matrix must be provided.

    confounds: pandas DataFrame, optional
        Must contain a subject_label column. All other columns are
        considered as confounds and included in the model. If
        design_matrix is provided then this argument is ignored.
        The resulting second level design matrix uses the same column
        names as in the given DataFrame for confounds. At least two columns
        are expected, "subject_label" and at least one confound.

    design_matrix: pandas DataFrame, optional
        Design matrix to fit the GLM. The number of rows
        in the design matrix must agree with the number of maps derived
        from second_level_input.
        Ensure that the order of maps given by a second_level_input
        list of Niimgs matches the order of the rows in the design matrix.

    second_level_contrast: str or array of shape (n_col), optional
        Where ``n_col`` is the number of columns of the design matrix.
        The default (None) is accepted if the design matrix has a single
        column, in which case the only possible contrast array((1)) is
        applied; when the design matrix has multiple columns, an error is
        raised.

    mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters. Automatic mask computation assumes first level imgs have
        already been masked.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    model_intercept : bool,
      If True, a constant column is added to the confounding variates
      unless the tested variate is already the intercept.

    n_perm : int,
      Number of permutations to perform.
      Permutations are costly but the more are performed, the more precision
      one gets in the p-values estimation.

    two_sided_test : boolean,
      If True, performs an unsigned t-test. Both positive and negative
      effects are considered; the null hypothesis is that the effect is zero.
      If False, only positive effects are considered as relevant. The null
      hypothesis is that the effect is zero or negative.

    random_state : int or None,
      Seed for random number generator, to have the same permutations
      in each computing units.

    n_jobs : int,
      Number of parallel workers.
      If -1 is provided, all CPUs are used.
      A negative number indicates that all the CPUs except (abs(n_jobs) - 1)
      ones will be used.

    verbose: int, optional
        verbosity level (0 means no message).

    Returns
    -------
    neg_log_corrected_pvals_img: Nifti1Image
        The image which contains negative logarithm of the
        corrected p-values
    """
    # Prevent circular imports between reporting & stats module
    from nilearn.input_data import NiftiMasker  # noqa

    _check_second_level_input(second_level_input,
                              design_matrix,
                              flm_object=False,
                              df_object=False)
    _check_confounds(confounds)
    _check_design_matrix(design_matrix)

    # Report progress
    t0 = time.time()
    if verbose > 0:
        sys.stderr.write("Fitting second level model...")

    # Select sample map for masker fit and get subjects_label for design
    sample_map = mean_img(second_level_input)

    # Learn the mask. Assume the first level imgs have been masked.
    if not isinstance(mask, NiftiMasker):
        masker = NiftiMasker(mask_img=mask,
                             smoothing_fwhm=smoothing_fwhm,
                             memory=Memory(None),
                             verbose=max(0, verbose - 1),
                             memory_level=1)
    else:
        masker = clone(mask)
        if smoothing_fwhm is not None:
            if getattr(masker, 'smoothing_fwhm') is not None:
                warn('Parameter smoothing_fwhm of the masker overriden')
                setattr(masker, 'smoothing_fwhm', smoothing_fwhm)
    masker.fit(sample_map)

    # Report progress
    if verbose > 0:
        sys.stderr.write("\nComputation of second level model done in "
                         "%i seconds\n" % (time.time() - t0))

    # Check and obtain the contrast
    contrast = _get_contrast(second_level_contrast, design_matrix)

    # Get effect_maps
    effect_maps = _infer_effect_maps(second_level_input, None)

    # Check design matrix and effect maps agree on number of rows
    _check_effect_maps(effect_maps, design_matrix)

    # Obtain tested_var
    if contrast in design_matrix.columns.tolist():
        tested_var = np.asarray(design_matrix[contrast])

    # Mask data
    target_vars = masker.transform(effect_maps)

    # Perform massively univariate analysis with permuted OLS
    neg_log_pvals_permuted_ols, _, _ = permuted_ols(
        tested_var,
        target_vars,
        model_intercept=model_intercept,
        n_perm=n_perm,
        two_sided_test=two_sided_test,
        random_state=random_state,
        n_jobs=n_jobs,
        verbose=max(0, verbose - 1))
    neg_log_corrected_pvals_img = masker.inverse_transform(
        np.ravel(neg_log_pvals_permuted_ols))

    return neg_log_corrected_pvals_img
Beispiel #26
0
class Masker(object):
    """
    Class that takes a binary mask.nii file and allows us to use it
    within a volumizer in order to reduce the dimensionality of our data in
    realtime.

    If we have other ROI masks (e.g. wm, csf), we can use them detrend the data
    by setting them as orthogonals.
    """

    def __init__(self, mask_img, center=None, radius=8):
        self.mask_img = mask_img
        self.masker = NiftiMasker(mask_img=mask_img)
        self.fit = False
        # set the mask center
        if center is None:
            self.center = self.find_center_of_mass(self.masker)

        else:
            self.center = center
        print("Center=", center)
        print("COM calc=", self.find_center_of_mass(self.masker))

        # the radius of the mask, used for determining what data to read.
        self.radius = radius
        self.orthogonals = []
        self.use_orthogonal = False
        self.ortho_fits = []

    def reduce_volume(self, volume, method='mean'):
        if not self.fit:
            self.masker.fit(volume)
        if method == 'mean':
            reduced = npm(self.masker.transform(volume['image']))
        return reduced

    def find_center_of_mass(self, niftimasker):
        """
        Find the center of mass of an image given a nifti masker object
        in the z plane. We can use this information to only select dicoms
        we need in a DicomFilter object.
        """

        com = measurements.center_of_mass(
            nibabel.load(niftimasker.mask_img).get_data())
        affine = nibabel.load(niftimasker.mask_img).affine
        offset = affine[0:3, 3]
        tcom = np.dot(affine[0:3, 0:3], com) + offset
        return tcom[2]

    def add_orthogonal(self, mask_img):
        # add another mask_img to our orthogonals with get_orthogonal
        self.use_orthogonal = True
        self.orthogonals.append(NiftiMasker(mask_img=mask_img))
        self.ortho_fits.append(False)

    def get_orthogonals(self, volume):
        """
        Return a list of ROI averages for a volume given a set of
        orthogonal masks
        """
        for i, fit in enumerate(self.ortho_fits):
            if not fit:
                self.orthogonals[i].fit(volume)

        return [npm(x.transform(volume['image'])) for x in self.orthogonals]
Beispiel #27
0
class FirstLevelModel(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model
    for single session fMRI data.

    Parameters
    ----------
    t_r : float
        This parameter indicates repetition times of the experimental runs.
        In seconds. It is necessary to correctly consider times in the design
        matrix. This parameter is also passed to nilearn.signal.clean.
        Please see the related documentation for details.

    slice_time_ref : float, optional (default 0.)
        This parameter indicates the time of the reference slice used in the
        slice timing preprocessing step of the experimental runs. It is
        expressed as a percentage of the t_r (time repetition), so it can have
        values between 0. and 1.

    hrf_model : {'spm', 'spm + derivative', 'spm + derivative + dispersion',
        'glover', 'glover + derivative', 'glover + derivative + dispersion',
        'fir', None}
        String that specifies the hemodynamic response function.
        Defaults to 'glover'.

    drift_model : string, optional
        This parameter specifies the desired drift model for the design
        matrices. It can be 'polynomial', 'cosine' or None.

    high_pass : float, optional
        This parameter specifies the cut frequency of the high-pass filter in
        Hz for the design matrices. Used only if drift_model is 'cosine'.

    drift_order : int, optional
        This parameter specifices the order of the drift model (in case it is
        polynomial) for the design matrices.

    fir_delays : array of shape(n_onsets) or list, optional
        In case of FIR design, yields the array of delays used in the FIR
        model, in scans.

    min_onset : float, optional
        This parameter specifies the minimal onset relative to the design
        (in seconds). Events that start before (slice_time_ref * t_r +
        min_onset) are not considered.

    mask_img : Niimg-like, NiftiMasker object or False, optional
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a NiftiMasker with default
        parameters. If False is given then the data will not be masked.

    target_affine : 3x3 or 4x4 matrix, optional
        This parameter is passed to nilearn.image.resample_img.
        Please see the related documentation for details.

    target_shape : 3-tuple of integers, optional
        This parameter is passed to nilearn.image.resample_img.
        Please see the related documentation for details.

    smoothing_fwhm : float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of
        the spatial smoothing to apply to the signal.

    memory : string, optional
        Path to the directory used to cache the masking process and the glm
        fit. By default, no caching is done.
        Creates instance of joblib.Memory.

    memory_level : integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    standardize : boolean, optional
        If standardize is True, the time-series are centered and normed:
        their variance is put to 1 in the time dimension.

    signal_scaling : False, int or (int, int), optional,
        If not False, fMRI signals are
        scaled to the mean value of scaling_axis given,
        which can be 0, 1 or (0, 1).
        0 refers to mean scaling each voxel with respect to time,
        1 refers to mean scaling each time point with respect to all voxels &
        (0, 1) refers to scaling with respect to voxels and time,
        which is known as grand mean scaling.
        Incompatible with standardize (standardize=False is enforced when
        signal_scaling is not False).

    noise_model : {'ar1', 'ols'}, optional
        The temporal variance model. Defaults to 'ar1'

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.
        If 0 prints nothing. If 1 prints progress by computation of
        each run. If 2 prints timing details of masker and GLM. If 3
        prints masker computation details.

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    minimize_memory : boolean, optional
        Gets rid of some variables on the model fit results that are not
        necessary for contrast computation and would only be useful for
        further inspection of model details. This has an important impact
        on memory consumption. True by default.

    subject_label : string, optional
        This id will be used to identify a `FirstLevelModel` when passed to
        a `SecondLevelModel` object.

    Attributes
    ----------
    labels_ : array of shape (n_voxels,),
        a map of values on voxels used to identify the corresponding model

    results_ : dict,
        with keys corresponding to the different labels values.
        Values are SimpleRegressionResults corresponding to the voxels,
        if minimize_memory is True,
        RegressionResults if minimize_memory is False


    """

    def __init__(self, t_r=None, slice_time_ref=0., hrf_model='glover',
                 drift_model='cosine', high_pass=.01, drift_order=1,
                 fir_delays=[0], min_onset=-24, mask_img=None,
                 target_affine=None, target_shape=None, smoothing_fwhm=None,
                 memory=Memory(None), memory_level=1, standardize=False,
                 signal_scaling=0, noise_model='ar1', verbose=0, n_jobs=1,
                 minimize_memory=True, subject_label=None):
        # design matrix parameters
        self.t_r = t_r
        self.slice_time_ref = slice_time_ref
        self.hrf_model = hrf_model
        self.drift_model = drift_model
        self.high_pass = high_pass
        self.drift_order = drift_order
        self.fir_delays = fir_delays
        self.min_onset = min_onset
        # glm parameters
        self.mask_img = mask_img
        self.target_affine = target_affine
        self.target_shape = target_shape
        self.smoothing_fwhm = smoothing_fwhm
        if isinstance(memory, str):
            self.memory = Memory(memory)
        else:
            self.memory = memory
        self.memory_level = memory_level
        self.standardize = standardize
        if signal_scaling is False:
            self.signal_scaling = signal_scaling
        elif signal_scaling in [0, 1, (0, 1)]:
            self.scaling_axis = signal_scaling
            self.signal_scaling = True
            self.standardize = False
        else:
            raise ValueError('signal_scaling must be "False", "0", "1"'
                             ' or "(0, 1)"')

        self.noise_model = noise_model
        self.verbose = verbose
        self.n_jobs = n_jobs
        self.minimize_memory = minimize_memory
        # attributes
        self.labels_ = None
        self.results_ = None
        self.subject_label = subject_label

    def fit(self, run_imgs, events=None, confounds=None,
            design_matrices=None):
        """ Fit the GLM

        For each run:
        1. create design matrix X
        2. do a masker job: fMRI_data -> Y
        3. fit regression to (Y, X)

        Parameters
        ----------
        run_imgs: Niimg-like object or list of Niimg-like objects,
            See http://nilearn.github.io/manipulating_images/input_output.html#inputing-data-file-names-or-image-objects  # noqa:E501
            Data on which the GLM will be fitted. If this is a list,
            the affine is considered the same for all.

        events: pandas Dataframe or string or list of pandas DataFrames or
                   strings

            fMRI events used to build design matrices. One events object
            expected per run_img. Ignored in case designs is not None.
            If string, then a path to a csv file is expected.

        confounds: pandas Dataframe or string or list of pandas DataFrames or
                   strings

            Each column in a DataFrame corresponds to a confound variable
            to be included in the regression model of the respective run_img.
            The number of rows must match the number of volumes in the
            respective run_img. Ignored in case designs is not None.
            If string, then a path to a csv file is expected.

        design_matrices: pandas DataFrame or list of pandas DataFrames,
            Design matrices that will be used to fit the GLM. If given it
            takes precedence over events and confounds.

        """
        # Local import to prevent circular imports
        from nilearn.input_data import NiftiMasker  # noqa

        # Check arguments
        # Check imgs type
        if events is not None:
            _check_events_file_uses_tab_separators(events_files=events)
        if not isinstance(run_imgs, (list, tuple)):
            run_imgs = [run_imgs]
        if design_matrices is None:
            if events is None:
                raise ValueError('events or design matrices must be provided')
            if self.t_r is None:
                raise ValueError('t_r not given to FirstLevelModel object'
                                 ' to compute design from events')
        else:
            design_matrices = _check_run_tables(run_imgs, design_matrices,
                                                'design_matrices')
        # Check that number of events and confound files match number of runs
        # Also check that events and confound files can be loaded as DataFrame
        if events is not None:
            events = _check_run_tables(run_imgs, events, 'events')
        if confounds is not None:
            confounds = _check_run_tables(run_imgs, confounds, 'confounds')

        # Learn the mask
        if self.mask_img is False:
            # We create a dummy mask to preserve functionality of api
            ref_img = check_niimg(run_imgs[0])
            self.mask_img = Nifti1Image(np.ones(ref_img.shape[:3]),
                                        ref_img.affine)
        if not isinstance(self.mask_img, NiftiMasker):
            self.masker_ = NiftiMasker(mask_img=self.mask_img,
                                       smoothing_fwhm=self.smoothing_fwhm,
                                       target_affine=self.target_affine,
                                       standardize=self.standardize,
                                       mask_strategy='epi',
                                       t_r=self.t_r,
                                       memory=self.memory,
                                       verbose=max(0, self.verbose - 2),
                                       target_shape=self.target_shape,
                                       memory_level=self.memory_level
                                       )
            self.masker_.fit(run_imgs[0])
        else:
            if self.mask_img.mask_img_ is None and self.masker_ is None:
                self.masker_ = clone(self.mask_img)
                for param_name in ['target_affine', 'target_shape',
                                   'smoothing_fwhm', 't_r', 'memory',
                                   'memory_level']:
                    our_param = getattr(self, param_name)
                    if our_param is None:
                        continue
                    if getattr(self.masker_, param_name) is not None:
                        warn('Parameter %s of the masker'
                             ' overriden' % param_name)
                    setattr(self.masker_, param_name, our_param)
                self.masker_.fit(run_imgs[0])
            else:
                self.masker_ = self.mask_img

        # For each run fit the model and keep only the regression results.
        self.labels_, self.results_, self.design_matrices_ = [], [], []
        n_runs = len(run_imgs)
        t0 = time.time()
        for run_idx, run_img in enumerate(run_imgs):
            # Report progress
            if self.verbose > 0:
                percent = float(run_idx) / n_runs
                percent = round(percent * 100, 2)
                dt = time.time() - t0
                # We use a max to avoid a division by zero
                if run_idx == 0:
                    remaining = 'go take a coffee, a big one'
                else:
                    remaining = (100. - percent) / max(0.01, percent) * dt
                    remaining = '%i seconds remaining' % remaining

                sys.stderr.write(
                    "Computing run %d out of %d runs (%s)\n"
                    % (run_idx + 1, n_runs, remaining))

            # Build the experimental design for the glm
            run_img = check_niimg(run_img, ensure_ndim=4)
            if design_matrices is None:
                n_scans = get_data(run_img).shape[3]
                if confounds is not None:
                    confounds_matrix = confounds[run_idx].values
                    if confounds_matrix.shape[0] != n_scans:
                        raise ValueError('Rows in confounds does not match'
                                         'n_scans in run_img at index %d'
                                         % (run_idx,))
                    confounds_names = confounds[run_idx].columns.tolist()
                else:
                    confounds_matrix = None
                    confounds_names = None
                start_time = self.slice_time_ref * self.t_r
                end_time = (n_scans - 1 + self.slice_time_ref) * self.t_r
                frame_times = np.linspace(start_time, end_time, n_scans)
                design = make_first_level_design_matrix(frame_times,
                                                        events[run_idx],
                                                        self.hrf_model,
                                                        self.drift_model,
                                                        self.high_pass,
                                                        self.drift_order,
                                                        self.fir_delays,
                                                        confounds_matrix,
                                                        confounds_names,
                                                        self.min_onset
                                                        )
            else:
                design = design_matrices[run_idx]
            self.design_matrices_.append(design)

            # Mask and prepare data for GLM
            if self.verbose > 1:
                t_masking = time.time()
                sys.stderr.write('Starting masker computation \r')

            Y = self.masker_.transform(run_img)
            del run_img  # Delete unmasked image to save memory

            if self.verbose > 1:
                t_masking = time.time() - t_masking
                sys.stderr.write('Masker took %d seconds       \n'
                                 % t_masking)

            if self.signal_scaling:
                Y, _ = mean_scaling(Y, self.scaling_axis)
            if self.memory:
                mem_glm = self.memory.cache(run_glm, ignore=['n_jobs'])
            else:
                mem_glm = run_glm

            # compute GLM
            if self.verbose > 1:
                t_glm = time.time()
                sys.stderr.write('Performing GLM computation\r')
            labels, results = mem_glm(Y, design.values,
                                      noise_model=self.noise_model,
                                      bins=100, n_jobs=self.n_jobs)
            if self.verbose > 1:
                t_glm = time.time() - t_glm
                sys.stderr.write('GLM took %d seconds         \n' % t_glm)

            self.labels_.append(labels)
            # We save memory if inspecting model details is not necessary
            if self.minimize_memory:
                for key in results:
                    results[key] = SimpleRegressionResults(results[key])
            self.results_.append(results)
            del Y

        # Report progress
        if self.verbose > 0:
            sys.stderr.write("\nComputation of %d runs done in %i seconds\n\n"
                             % (n_runs, time.time() - t0))

        return self

    def compute_contrast(self, contrast_def, stat_type=None,
                         output_type='z_score'):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.
        In multi-session case, outputs the fixed effects map.

        Parameters
        ----------
        contrast_def : str or array of shape (n_col) or list of (string or
                       array of shape (n_col))

            where ``n_col`` is the number of columns of the design matrix,
            (one array per run). If only one array is provided when there
            are several runs, it will be assumed that the same contrast is
            desired for all runs. The string can be a formula compatible with
            `pandas.DataFrame.eval`. Basically one can use the name of the
            conditions as they appear in the design matrix of the fitted model
            combined with operators +- and combined with numbers
            with operators +-`*`/.

        stat_type : {'t', 'F'}, optional
            type of the contrast

        output_type : str, optional
            Type of the output map. Can be 'z_score', 'stat', 'p_value',
            'effect_size', 'effect_variance' or 'all'

        Returns
        -------
        output : Nifti1Image or dict
            The desired output image(s). If ``output_type == 'all'``, then
            the output is a dictionary of images, keyed by the type of image.

        """
        if self.labels_ is None or self.results_ is None:
            raise ValueError('The model has not been fit yet')

        if isinstance(contrast_def, (np.ndarray, str)):
            con_vals = [contrast_def]
        elif isinstance(contrast_def, (list, tuple)):
            con_vals = contrast_def
        else:
            raise ValueError('contrast_def must be an array or str or list of'
                             ' (array or str)')

        # Translate formulas to vectors
        for cidx, (con, design_mat) in enumerate(zip(con_vals,
                                                     self.design_matrices_)
                                                 ):
            design_columns = design_mat.columns.tolist()
            if isinstance(con, str):
                con_vals[cidx] = expression_to_contrast_vector(
                    con, design_columns)

        n_runs = len(self.labels_)
        if len(con_vals) != n_runs:
            warn('One contrast given, assuming it for all %d runs' % n_runs)
            con_vals = con_vals * n_runs

        valid_types = ['z_score', 'stat', 'p_value', 'effect_size',
                       'effect_variance']
        valid_types.append('all')  # ensuring 'all' is the final entry.
        if output_type not in valid_types:
            raise ValueError(
                'output_type must be one of {}'.format(valid_types))
        contrast = _compute_fixed_effect_contrast(self.labels_, self.results_,
                                                  con_vals, stat_type)
        output_types = (valid_types[:-1]
                        if output_type == 'all' else [output_type])
        outputs = {}
        for output_type_ in output_types:
            estimate_ = getattr(contrast, output_type_)()
            # Prepare the returned images
            output = self.masker_.inverse_transform(estimate_)
            contrast_name = str(con_vals)
            output.header['descrip'] = (
                '%s of contrast %s' % (output_type_, contrast_name))
            outputs[output_type_] = output

        return outputs if output_type == 'all' else output

    def _get_voxelwise_model_attribute(self, attribute,
                                       result_as_time_series):
        """Transform RegressionResults instances within a dictionary
        (whose keys represent the autoregressive coefficient under the 'ar1'
        noise model or only 0.0 under 'ols' noise_model and values are the
        RegressionResults instances) into input nifti space.

        Parameters
        ----------
        attribute : str
            an attribute of a RegressionResults instance.
            possible values include: resid, norm_resid, predicted,
            SSE, r_square, MSE.
        result_as_time_series : bool
            whether the RegressionResult attribute has a value
            per timepoint of the input nifti image.

        Returns
        -------
        output : list
            a list of Nifti1Image(s)
        """
        # check if valid attribute is being accessed.
        all_attributes = dict(vars(RegressionResults)).keys()
        possible_attributes = [prop
                               for prop in all_attributes
                               if '__' not in prop
                               ]
        if attribute not in possible_attributes:
            msg = ("attribute must be one of: "
                   "{attr}".format(attr=possible_attributes)
                   )
            raise ValueError(msg)

        if self.minimize_memory:
            raise ValueError(
                'To access voxelwise attributes like '
                'R-squared, residuals, and predictions, '
                'the `FirstLevelModel`-object needs to store '
                'there attributes. '
                'To do so, set `minimize_memory` to `False` '
                'when initializing the `FirstLevelModel`-object.')

        if self.labels_ is None or self.results_ is None:
            raise ValueError('The model has not been fit yet')

        output = []

        for design_matrix, labels, results in zip(self.design_matrices_,
                                                  self.labels_,
                                                  self.results_
                                                  ):
            if result_as_time_series:
                voxelwise_attribute = np.zeros((design_matrix.shape[0],
                                                len(labels))
                                               )
            else:
                voxelwise_attribute = np.zeros((1, len(labels)))

            for label_ in results:
                label_mask = labels == label_
                voxelwise_attribute[:, label_mask] = getattr(results[label_],
                                                             attribute)

            output.append(self.masker_.inverse_transform(voxelwise_attribute))

            return output

    @setattr_on_read
    def residuals(self):
        """Transform voxelwise residuals to the same shape
        as the input Nifti1Image(s)

        Returns
        -------
        output : list
            a list of Nifti1Image(s)
        """
        return self._get_voxelwise_model_attribute('resid',
                                                   result_as_time_series=True)

    @setattr_on_read
    def predicted(self):
        """Transform voxelwise predicted values to the same shape
        as the input Nifti1Image(s)

        Returns
        -------
        output : list
            a list of Nifti1Image(s)
        """
        return self._get_voxelwise_model_attribute('predicted',
                                                   result_as_time_series=True)

    @setattr_on_read
    def r_square(self):
        """Transform voxelwise r-squared values to the same shape
        as the input Nifti1Image(s)

        Returns
        -------
        output : list
            a list of Nifti1Image(s)
        """
        return self._get_voxelwise_model_attribute('r_square',
                                                   result_as_time_series=False
                                                   )
Beispiel #28
0
class SecondLevelModel(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for multiple subject
    fMRI data

    Parameters
    ----------

    mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters. Automatic mask computation assumes first level imgs have
        already been masked.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory: string, optional
        Path to the directory used to cache the masking process and the glm
        fit. By default, no caching is done. Creates instance of joblib.Memory.

    memory_level: integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.
        If 0 prints nothing. If 1 prints final computation time.
        If 2 prints masker computation details.

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    minimize_memory : boolean, optional
        Gets rid of some variables on the model fit results that are not
        necessary for contrast computation and would only be useful for
        further inspection of model details. This has an important impact
        on memory consumption. True by default.

    """
    def __init__(self, mask=None, smoothing_fwhm=None,
                 memory=Memory(None), memory_level=1, verbose=0,
                 n_jobs=1, minimize_memory=True):
        self.mask = mask
        self.smoothing_fwhm = smoothing_fwhm
        if isinstance(memory, _basestring):
            self.memory = Memory(memory)
        else:
            self.memory = memory
        self.memory_level = memory_level
        self.verbose = verbose
        self.n_jobs = n_jobs
        self.minimize_memory = minimize_memory
        self.second_level_input_ = None
        self.confounds_ = None

    def fit(self, second_level_input, confounds=None, design_matrix=None):
        """ Fit the second-level GLM

        1. create design matrix
        2. do a masker job: fMRI_data -> Y
        3. fit regression to (Y, X)

        Parameters
        ----------
        second_level_input: list of `FirstLevelModel` objects or pandas
                            DataFrame or list of Niimg-like objects.

            Giving FirstLevelModel objects will allow to easily compute
            the second level contast of arbitrary first level contrasts thanks
            to the first_level_contrast argument of the compute_contrast
            method. Effect size images will be computed for each model to
            contrast at the second level.

            If a pandas DataFrame, then they have to contain subject_label,
            map_name and effects_map_path. It can contain multiple maps that
            would be selected during contrast estimation with the argument
            first_level_contrast of the compute_contrast function. The
            DataFrame will be sorted based on the subject_label column to avoid
            order inconsistencies when extracting the maps. So the rows of the
            automatically computed design matrix, if not provided, will
            correspond to the sorted subject_label column.
 
            If list of Niimg-like objects then this is taken literally as Y
            for the model fit and design_matrix must be provided.

        confounds: pandas DataFrame, optional
            Must contain a subject_label column. All other columns are
            considered as confounds and included in the model. If
            design_matrix is provided then this argument is ignored.
            The resulting second level design matrix uses the same column
            names as in the given DataFrame for confounds. At least two columns
            are expected, "subject_label" and at least one confound.

        design_matrix: pandas DataFrame, optional
            Design matrix to fit the GLM. The number of rows
            in the design matrix must agree with the number of maps derived
            from second_level_input.
            Ensure that the order of maps given by a second_level_input
            list of Niimgs matches the order of the rows in the design matrix.

        """
        # Check parameters
        # check first level input
        if isinstance(second_level_input, list):
            if len(second_level_input) < 2:
                raise ValueError('A second level model requires a list with at'
                                 'least two first level models or niimgs')
            # Check FirstLevelModel objects case
            if isinstance(second_level_input[0], FirstLevelModel):
                models_input = enumerate(second_level_input)
                for model_idx, first_level_model in models_input:
                    if (first_level_model.labels_ is None or
                            first_level_model.results_ is None):
                        raise ValueError(
                            'Model %s at index %i has not been fit yet'
                            '' % (first_level_model.subject_label, model_idx))
                    if not isinstance(first_level_model, FirstLevelModel):
                        raise ValueError(' object at idx %d is %s instead of'
                                         ' FirstLevelModel object' %
                                         (model_idx, type(first_level_model)))
                    if confounds is not None:
                        if first_level_model.subject_label is None:
                            raise ValueError(
                                'In case confounds are provided, first level '
                                'objects need to provide the attribute '
                                'subject_label to match rows appropriately.'
                                'Model at idx %d does not provide it. '
                                'To set it, you can do '
                                'first_level_model.subject_label = "01"'
                                '' % (model_idx))
            # Check niimgs case
            elif isinstance(second_level_input[0], (str, Nifti1Image)):
                if design_matrix is None:
                    raise ValueError('List of niimgs as second_level_input'
                                     ' require a design matrix to be provided')
                for model_idx, niimg in enumerate(second_level_input):
                    if not isinstance(niimg, (str, Nifti1Image)):
                        raise ValueError(' object at idx %d is %s instead of'
                                         ' Niimg-like object' %
                                         (model_idx, type(niimg)))
        # Check pandas dataframe case
        elif isinstance(second_level_input, pd.DataFrame):
            for col in ['subject_label', 'map_name', 'effects_map_path']:
                if col not in second_level_input.columns:
                    raise ValueError('second_level_input DataFrame must have'
                                     ' columns subject_label, map_name and'
                                     ' effects_map_path')
            # Make sure subject_label contain strings
            second_level_columns = second_level_input.columns.tolist()
            labels_index = second_level_columns.index('subject_label')
            labels_dtype = second_level_input.dtypes[labels_index]
            if not isinstance(labels_dtype, np.object):
                raise ValueError('subject_label column must be of dtype '
                                 'object instead of dtype %s' % labels_dtype)
        elif isinstance(second_level_input, (str, Nifti1Image)):
            if design_matrix is None:
                raise ValueError('List of niimgs as second_level_input'
                                 ' require a design matrix to be provided')
            second_level_input = check_niimg(niimg=second_level_input,
                                             ensure_ndim=4) 
        else:
            raise ValueError('second_level_input must be a list of'
                             ' `FirstLevelModel` objects, a pandas DataFrame'
                             ' or a list Niimg-like objects. Instead %s '
                             'was provided' % type(second_level_input))

        # check confounds
        if confounds is not None:
            if not isinstance(confounds, pd.DataFrame):
                raise ValueError('confounds must be a pandas DataFrame')
            if 'subject_label' not in confounds.columns:
                raise ValueError('confounds DataFrame must contain column'
                                 '"subject_label"')
            if len(confounds.columns) < 2:
                raise ValueError('confounds should contain at least 2 columns'
                                 'one called "subject_label" and the other'
                                 'with a given confound')
            # Make sure subject_label contain strings
            labels_index = confounds.columns.tolist().index('subject_label')
            labels_dtype = confounds.dtypes[labels_index]
            if not isinstance(labels_dtype, np.object):
                raise ValueError('subject_label column must be of dtype '
                                 'object instead of dtype %s' % labels_dtype)

        # check design matrix
        if design_matrix is not None:
            if not isinstance(design_matrix, pd.DataFrame):
                raise ValueError('design matrix must be a pandas DataFrame')

        # sort a pandas dataframe by subject_label to avoid inconsistencies
        # with the design matrix row order when automatically extracting maps
        if isinstance(second_level_input, pd.DataFrame):
            columns = second_level_input.columns.tolist()
            column_index = columns.index('subject_label')
            sorted_matrix = sorted(
                second_level_input.values, key=lambda x: x[column_index])
            sorted_input = pd.DataFrame(sorted_matrix, columns=columns)
            second_level_input = sorted_input

        self.second_level_input_ = second_level_input
        self.confounds_ = confounds

        # Report progress
        t0 = time.time()
        if self.verbose > 0:
            sys.stderr.write("Fitting second level model. "
                             "Take a deep breath\r")

        # Select sample map for masker fit and get subjects_label for design
        if isinstance(second_level_input, pd.DataFrame):
            sample_map = second_level_input['effects_map_path'][0]
            labels = second_level_input['subject_label']
            subjects_label = labels.values.tolist()
        elif isinstance(second_level_input, Nifti1Image):
            sample_map = mean_img(second_level_input)
        elif isinstance(second_level_input[0], FirstLevelModel):
            sample_model = second_level_input[0]
            sample_condition = sample_model.design_matrices_[0].columns[0]
            sample_map = sample_model.compute_contrast(
                sample_condition, output_type='effect_size')
            labels = [model.subject_label for model in second_level_input]
            subjects_label = labels
        else:
            # In this case design matrix had to be provided
            sample_map = mean_img(second_level_input)

        # Create and set design matrix, if not given
        if design_matrix is None:
            design_matrix = make_second_level_design_matrix(subjects_label,
                                                            confounds)
        self.design_matrix_ = design_matrix

        # Learn the mask. Assume the first level imgs have been masked.
        if not isinstance(self.mask, NiftiMasker):
            self.masker_ = NiftiMasker(
                mask_img=self.mask, smoothing_fwhm=self.smoothing_fwhm,
                memory=self.memory, verbose=max(0, self.verbose - 1),
                memory_level=self.memory_level)
        else:
            self.masker_ = clone(self.mask)
            for param_name in ['smoothing_fwhm', 'memory', 'memory_level']:
                our_param = getattr(self, param_name)
                if our_param is None:
                    continue
                if getattr(self.masker_, param_name) is not None:
                    warn('Parameter %s of the masker overriden' % param_name)
                setattr(self.masker_, param_name, our_param)
        self.masker_.fit(sample_map)

        # Report progress
        if self.verbose > 0:
            sys.stderr.write("\nComputation of second level model done in "
                             "%i seconds\n" % (time.time() - t0))

        return self

    def compute_contrast(
            self, second_level_contrast=None, first_level_contrast=None,
            second_level_stat_type=None, output_type='z_score'):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.

        Parameters
        ----------
        second_level_contrast: str or array of shape (n_col), optional
            Where ``n_col`` is the number of columns of the design matrix,
            The string can be a formula compatible with the linear constraint
            of the Patsy library. Basically one can use the name of the
            conditions as they appear in the design matrix of
            the fitted model combined with operators /\*+- and numbers.
            Please check the patsy documentation for formula examples:
            http://patsy.readthedocs.io/en/latest/API-reference.html#patsy.DesignInfo.linear_constraint
            The default (None) is accepted if the design matrix has a single
            column, in which case the only possible contrast array([1]) is
            applied; when the design matrix has multiple columns, an error is
            raised.

        first_level_contrast: str or array of shape (n_col) with respect to
                              FirstLevelModel, optional
                              
            In case a list of FirstLevelModel was provided as
            second_level_input, we have to provide a contrast to apply to
            the first level models to get the corresponding list of images
            desired, that would be tested at the second level. In case a
            pandas DataFrame was provided as second_level_input this is the
            map name to extract from the pandas dataframe map_name column.
            It has to be a 't' contrast.

        second_level_stat_type: {'t', 'F'}, optional
            Type of the second level contrast

        output_type: str, optional
            Type of the output map. Can be 'z_score', 'stat', 'p_value',
            'effect_size' or 'effect_variance'

        Returns
        -------
        output_image: Nifti1Image
            The desired output image

        """
        if self.second_level_input_ is None:
            raise ValueError('The model has not been fit yet')

        # first_level_contrast check
        if isinstance(self.second_level_input_[0], FirstLevelModel):
            if first_level_contrast is None:
                raise ValueError('If second_level_input was a list of '
                                 'FirstLevelModel, then first_level_contrast '
                                 'is mandatory. It corresponds to the '
                                 'second_level_contrast argument of the '
                                 'compute_contrast method of FirstLevelModel')

        # check contrast definition
        if second_level_contrast is None:
            if self.design_matrix_.shape[1] == 1:
                second_level_contrast = np.ones([1])
            else:
                raise ValueError('No second-level contrast is specified.')
        if isinstance(second_level_contrast, np.ndarray):
            con_val = second_level_contrast
            if np.all(con_val == 0):
                raise ValueError('Contrast is null')
        else:
            design_info = DesignInfo(self.design_matrix_.columns.tolist())
            constraint = design_info.linear_constraint(second_level_contrast)
            con_val = constraint.coefs
        # check output type
        if isinstance(output_type, _basestring):
            if output_type not in ['z_score', 'stat', 'p_value', 'effect_size',
                                   'effect_variance']:
                raise ValueError(
                    'output_type must be one of "z_score", "stat"'
                    ', "p_value", "effect_size" or "effect_variance"')
        else:
            raise ValueError('output_type must be one of "z_score", "stat",'
                             ' "p_value", "effect_size" or "effect_variance"')

        # Get effect_maps appropriate for chosen contrast
        effect_maps = _infer_effect_maps(self.second_level_input_,
                                         first_level_contrast)
        # Check design matrix X and effect maps Y agree on number of rows
        if len(effect_maps) != self.design_matrix_.shape[0]:
            raise ValueError(
                'design_matrix does not match the number of maps considered. '
                '%i rows in design matrix do not match with %i maps' %
                (self.design_matrix_.shape[0], len(effect_maps)))

        # Fit an Ordinary Least Squares regression for parametric statistics
        Y = self.masker_.transform(effect_maps)
        if self.memory:
            mem_glm = self.memory.cache(run_glm, ignore=['n_jobs'])
        else:
            mem_glm = run_glm
        labels, results = mem_glm(Y, self.design_matrix_.values,
                                  n_jobs=self.n_jobs, noise_model='ols')
        # We save memory if inspecting model details is not necessary
        if self.minimize_memory:
            for key in results:
                results[key] = SimpleRegressionResults(results[key])
        self.labels_ = labels
        self.results_ = results

        # We compute contrast object
        if self.memory:
            mem_contrast = self.memory.cache(compute_contrast)
        else:
            mem_contrast = compute_contrast
        contrast = mem_contrast(self.labels_, self.results_, con_val,
                                second_level_stat_type)

        # We get desired output from contrast object
        estimate_ = getattr(contrast, output_type)()

        # Prepare the returned images
        output = self.masker_.inverse_transform(estimate_)
        contrast_name = str(con_val)
        output.header['descrip'] = (
            '%s of contrast %s' % (output_type, contrast_name))
        return output
        contrasts = ['face_trusty-gender', 'expression_intention-gender']
    elif task in [
            'hcp_emotion', 'hcp_gambling', 'hcp_language', 'hcp_relational',
            'hcp_social', 'hcp_motor', 'hcp_wm'
    ]:
        contrasts = [c for c in contrasts if c in df_hcp['IBC name'].unique()]

    image_dir = cache
    if task in [
            'ArchiStandard', 'ArchiSpatial', 'ArchiSocial', 'ArchiEmotional'
    ]:
        image_dir = os.path.join(cache, 'archi')
    for contrast in contrasts:
        hcp_img = os.path.join(image_dir, 'mean_z_%s.nii.gz' % contrast)
        imgs = task_df[task_df.contrast == contrast].path.values
        x = masker.transform(imgs).mean(0)
        X.append(x)
        y = masker.transform(hcp_img)[0]
        Y.append(y)
        names.append(contrast)

pretty_names = [
    CONTRASTS[CONTRASTS.contrast == name]['positive label'].values[0] +
    ' vs. ' + CONTRASTS[CONTRASTS.contrast == name]['negative label'].values[0]
    for name in names
]
n_contrasts = len(X)
C = np.corrcoef(np.array(X), np.array(Y))
plt.figure(figsize=(16, 13.2))
ax = plt.subplot(111)
for axis in ['top', 'bottom', 'left', 'right']:
def compute_dices():
    output_dir = expanduser('output/ibc/language44')

    mask = join(output_dir, 'mask_ibc.nii.gz')
    masker = NiftiMasker(mask_img=mask).fit()

    imgs = sorted(glob.glob(join(output_dir, '*_thr.nii.gz')))

    regex = re.compile(r'(?P<contrast>.*)_z_score_(?P<reduction>.*)_'
                       r'(?P<size>.*)_(?P<split>[1-9]*)_thr.nii.gz')

    df = []
    for img in imgs:
        _, filename = os.path.split(img)
        match = regex.match(filename)
        if match:
            contrast = match['contrast']
            reduction = match['reduction']
            size = int(match['size']) if match['size'] != 'none' else 'none'
            split = int(match['split'])
            df.append(
                dict(contrast=contrast,
                     reduction=reduction,
                     size=size,
                     split=split,
                     filename=img))
    df = pd.DataFrame(df)

    intra_dices = []
    ref_df = df.loc[df['reduction'] == 'none']

    for contrast, sub_df in ref_df.groupby(by='contrast'):
        n = sub_df.shape[0]
        components = masker.transform(sub_df['filename']) != 0
        dices = np.array([
            dice_index(components[i], components[j]) for i in range(n - 1)
            for j in range(i + 1, n)
        ])
        print(contrast, dices)
        intra_dices.append(
            dict(contrast=contrast,
                 mean_dice=np.mean(dices),
                 std_dice=np.std(dices)))

    intra_dices = pd.DataFrame(intra_dices)
    stop
    intra_dices.to_pickle(join(output_dir, 'intra_dices.pkl'))

    inter_dices = []
    for (contrast, reduction,
         size), sub_df in df.groupby(by=['contrast', 'reduction', 'size']):
        sub_ref_df = ref_df.loc[ref_df['contrast'] == contrast]
        n = sub_df.shape[0]
        components = masker.transform(sub_df['filename']) != 0
        ref_components = masker.transform(sub_ref_df['filename']) != 0
        dices = np.array(
            [dice_index(components[i], ref_components[i]) for i in range(n)])
        print(contrast, reduction, size, dices)
        inter_dices.append(
            dict(contrast=contrast,
                 reduction=reduction,
                 size=size,
                 mean_dice=np.mean(dices),
                 std_dice=np.std(dices)))

    inter_dices = pd.DataFrame(inter_dices)
    inter_dices.to_pickle(join(output_dir, 'inter_dices.pkl'))
Beispiel #31
0
def nii2cmu(nifti_file,
            mask_file=None,
            smooth=None,
            zscore=False,
            zscore_by_rest=False,
            rest_starts=None,
            rest_ends=None):
    if zscore_by_rest:
        rest_starts = rest_starts.strip('[]')
        rest_starts = [int(s) for s in rest_starts.split(',')]
        rest_ends = rest_ends.strip('[]')
        rest_ends = [int(s) for s in rest_ends.split(',')]
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            image = nib.load(nifti_file)
            mask = NiftiMasker(mask_strategy='background',
                               smoothing_fwhm=smooth,
                               standardize=False)
            if mask_file is None:
                mask.fit(nifti_file)
            else:
                mask.fit(mask_file)
        header = image.header
        sform = image.get_sform()
        voxel_size = header.get_zooms()
        voxel_activations = np.float64(mask.transform(nifti_file)).transpose()
        rest_activations = voxel_activations[:, rest_starts[0]:rest_ends[0]]
        for i in range(1, len(rest_starts)):
            rest_activations = np.hstack(
                (rest_activations,
                 voxel_activations[:, rest_starts[i]:rest_ends[i]]))
        standard_transform = sklearn.preprocessing.StandardScaler().fit(
            rest_activations.T)
        voxel_activations = standard_transform.transform(voxel_activations.T).T
        voxel_coordinates = np.array(np.nonzero(
            mask.mask_img_.dataobj)).transpose()
        voxel_coordinates = np.hstack(
            (voxel_coordinates, np.ones((voxel_coordinates.shape[0], 1))))
        voxel_locations = (voxel_coordinates @ sform.T)[:, :3]
    else:
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            image = nib.load(nifti_file)
            mask = NiftiMasker(mask_strategy='background',
                               smoothing_fwhm=smooth,
                               standardize=zscore)
            if mask_file is None:
                mask.fit(nifti_file)
            else:
                mask.fit(mask_file)

        header = image.header
        sform = image.get_sform()
        voxel_size = header.get_zooms()
        voxel_activations = np.float64(mask.transform(nifti_file)).transpose()
        voxel_coordinates = np.array(np.nonzero(
            mask.mask_img_.dataobj)).transpose()
        voxel_coordinates = np.hstack(
            (voxel_coordinates, np.ones((voxel_coordinates.shape[0], 1))))
        voxel_locations = (voxel_coordinates @ sform.T)[:, :3]

    return {'data': voxel_activations, 'R': voxel_locations}
Beispiel #32
0
class FirstLevelModel(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for single session fMRI data

    Parameters
    ----------
    t_r : float
        This parameter indicates repetition times of the experimental runs.
        In seconds. It is necessary to correctly consider times in the design
        matrix. This parameter is also passed to nilearn.signal.clean.
        Please see the related documentation for details.

    slice_time_ref : float, optional (default 0.)
        This parameter indicates the time of the reference slice used in the
        slice timing preprocessing step of the experimental runs. It is
        expressed as a percentage of the t_r (time repetition), so it can have
        values between 0. and 1.

    hrf_model : string, optional
        This parameter specifies the hemodynamic response function (HRF) for
        the design matrices. It can be 'canonical', 'canonical with derivative'
        or 'fir'.

    drift_model : string, optional
        This parameter specifies the desired drift model for the design
        matrices. It can be 'polynomial', 'cosine' or None.

    period_cut : float, optional
        This parameter specifies the cut period of the low-pass filter in
        seconds for the design matrices.

    drift_order : int, optional
        This parameter specifices the order of the drift model (in case it is
        polynomial) for the design matrices.

    fir_delays : array of shape(n_onsets) or list, optional
        In case of FIR design, yields the array of delays used in the FIR
        model, in seconds.

    min_onset : float, optional
        This parameter specifies the minimal onset relative to the design
        (in seconds). Events that start before (slice_time_ref * t_r +
        min_onset) are not considered.

    mask : Niimg-like, NiftiMasker object or False, optional
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a NiftiMasker with default
        parameters. If False is given then the data will not be masked.

    target_affine : 3x3 or 4x4 matrix, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    target_shape : 3-tuple of integers, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    smoothing_fwhm : float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory : string, optional
        Path to the directory used to cache the masking process and the glm
        fit. By default, no caching is done. Creates instance of joblib.Memory.

    memory_level : integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    standardize : boolean, optional
        If standardize is True, the time-series are centered and normed:
        their variance is put to 1 in the time dimension.

    signal_scaling : False, int or (int, int), optional,
        If not False, fMRI signals are scaled to the mean value of scaling_axis
        given, which can be 0, 1 or (0, 1). 0 refers to mean scaling each voxel
        with respect to time, 1 refers to mean scaling each time point with
        respect to all voxels and (0, 1) refers to scaling with respect to
        voxels and time, which is known as grand mean scaling.
        Incompatible with standardize (standardize=False is enforced when
        signal_scaling is not False).

    noise_model : {'ar1', 'ols'}, optional
        The temporal variance model. Defaults to 'ar1'

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.
        If 0 prints nothing. If 1 prints progress by computation of
        each run. If 2 prints timing details of masker and GLM. If 3
        prints masker computation details.

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    minimize_memory : boolean, optional
        Gets rid of some variables on the model fit results that are not
        necessary for contrast computation and would only be useful for
        further inspection of model details. This has an important impact
        on memory consumption. True by default.

    subject_label : string, optional
        This id will be used to identify a `FirstLevelModel` when passed to
        a `SecondLevelModel` object.

    Attributes
    ----------
    labels : array of shape (n_voxels,),
        a map of values on voxels used to identify the corresponding model

    results : dict,
        with keys corresponding to the different labels values
        values are RegressionResults instances corresponding to the voxels

    """
    def __init__(self,
                 t_r=None,
                 slice_time_ref=0.,
                 hrf_model='glover',
                 drift_model='cosine',
                 period_cut=128,
                 drift_order=1,
                 fir_delays=[0],
                 min_onset=-24,
                 mask=None,
                 target_affine=None,
                 target_shape=None,
                 smoothing_fwhm=None,
                 memory=Memory(None),
                 memory_level=1,
                 standardize=False,
                 signal_scaling=0,
                 noise_model='ar1',
                 verbose=0,
                 n_jobs=1,
                 minimize_memory=True,
                 subject_label=None):
        # design matrix parameters
        self.t_r = t_r
        self.slice_time_ref = slice_time_ref
        self.hrf_model = hrf_model
        self.drift_model = drift_model
        self.period_cut = period_cut
        self.drift_order = drift_order
        self.fir_delays = fir_delays
        self.min_onset = min_onset
        # glm parameters
        self.mask = mask
        self.target_affine = target_affine
        self.target_shape = target_shape
        self.smoothing_fwhm = smoothing_fwhm
        if isinstance(memory, _basestring):
            self.memory = Memory(memory)
        else:
            self.memory = memory
        self.memory_level = memory_level
        self.standardize = standardize

        if signal_scaling is False:
            self.signal_scaling = signal_scaling
        elif (type(signal_scaling) is not bool) and (signal_scaling
                                                     in [0, 1, (0, 1)]):
            self.scaling_axis = signal_scaling
            self.signal_scaling = True
            self.standardize = False
        else:
            raise ValueError('signal_scaling must be "False", "0", "1"'
                             ' or "(0, 1)"')

        self.noise_model = noise_model
        self.verbose = verbose
        self.n_jobs = n_jobs
        self.minimize_memory = minimize_memory
        # attributes
        self.labels_ = None
        self.results_ = None
        self.subject_label = subject_label

    def fit(self, run_imgs, events=None, confounds=None, design_matrices=None):
        """ Fit the GLM

        For each run:
        1. create design matrix X
        2. do a masker job: fMRI_data -> Y
        3. fit regression to (Y, X)

        Parameters
        ----------
        run_imgs: Niimg-like object or list of Niimg-like objects,
            See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
            Data on which the GLM will be fitted. If this is a list,
            the affine is considered the same for all.

        events: pandas Dataframe or string or list of pandas DataFrames or
                   strings,
            fMRI events used to build design matrices. One events object
            expected per run_img. Ignored in case designs is not None.
            If string, then a path to a csv file is expected.

        confounds: pandas Dataframe or string or list of pandas DataFrames or
                   strings,
            Each column in a DataFrame corresponds to a confound variable
            to be included in the regression model of the respective run_img.
            The number of rows must match the number of volumes in the
            respective run_img. Ignored in case designs is not None.
            If string, then a path to a csv file is expected.

        design_matrices: pandas DataFrame or list of pandas DataFrames,
            Design matrices that will be used to fit the GLM. If given it
            takes precedence over events and confounds.

        """
        # Check arguments
        # Check imgs type
        if not isinstance(run_imgs, (list, tuple)):
            run_imgs = [run_imgs]
        if design_matrices is None:
            if events is None:
                raise ValueError('events or design matrices must be provided')
            if self.t_r is None:
                raise ValueError('t_r not given to FirstLevelModel object'
                                 ' to compute design from events')
        else:
            design_matrices = _check_run_tables(run_imgs, design_matrices,
                                                'design_matrices')
        # Check that number of events and confound files match number of runs
        # Also check that events and confound files can be loaded as DataFrame
        if events is not None:
            events = _check_run_tables(run_imgs, events, 'events')

        if confounds is not None:
            confounds = _check_run_tables(run_imgs, confounds, 'confounds')

        # Learn the mask
        if self.mask is False:
            # We create a dummy mask to preserve functionality of api
            ref_img = check_niimg(run_imgs[0])
            self.mask = Nifti1Image(np.ones(ref_img.shape[:3]), ref_img.affine)
        if not isinstance(self.mask, NiftiMasker):
            self.masker_ = NiftiMasker(mask_img=self.mask,
                                       smoothing_fwhm=self.smoothing_fwhm,
                                       target_affine=self.target_affine,
                                       standardize=self.standardize,
                                       mask_strategy='epi',
                                       t_r=self.t_r,
                                       memory=self.memory,
                                       verbose=max(0, self.verbose - 2),
                                       target_shape=self.target_shape,
                                       memory_level=self.memory_level)
            self.masker_.fit(run_imgs[0])
        else:
            if self.mask.mask_img_ is None and self.masker_ is None:
                self.masker_ = clone(self.mask)
                for param_name in [
                        'target_affine', 'target_shape', 'smoothing_fwhm',
                        't_r', 'memory', 'memory_level'
                ]:
                    our_param = getattr(self, param_name)
                    if our_param is None:
                        continue
                    if getattr(self.masker_, param_name) is not None:
                        warn('Parameter %s of the masker'
                             ' overriden' % param_name)
                    setattr(self.masker_, param_name, our_param)
                self.masker_.fit(run_imgs[0])
            else:
                self.masker_ = self.mask

        # For each run fit the model and keep only the regression results.
        self.labels_, self.results_, self.design_matrices_ = [], [], []
        n_runs = len(run_imgs)
        t0 = time.time()
        for run_idx, run_img in enumerate(run_imgs):
            # Report progress
            if self.verbose > 0:
                percent = float(run_idx) / n_runs
                percent = round(percent * 100, 2)
                dt = time.time() - t0
                # We use a max to avoid a division by zero
                if run_idx == 0:
                    remaining = 'go take a coffee, a big one'
                else:
                    remaining = (100. - percent) / max(0.01, percent) * dt
                    remaining = '%i seconds remaining' % remaining

                sys.stderr.write("Computing run %d out of %d runs (%s)\n" %
                                 (run_idx + 1, n_runs, remaining))

            # Build the experimental design for the glm
            run_img = check_niimg(run_img, ensure_ndim=4)
            if design_matrices is None:
                n_scans = run_img.get_data().shape[3]
                if confounds is not None:
                    confounds_matrix = confounds[run_idx].values
                    if confounds_matrix.shape[0] != n_scans:
                        raise ValueError('Rows in confounds does not match'
                                         'n_scans in run_img at index %d' %
                                         (run_idx, ))
                    confounds_names = confounds[run_idx].columns.tolist()
                else:
                    confounds_matrix = None
                    confounds_names = None
                start_time = self.slice_time_ref * self.t_r
                end_time = (n_scans - 1 + self.slice_time_ref) * self.t_r
                frame_times = np.linspace(start_time, end_time, n_scans)
                design = make_design_matrix(frame_times, events[run_idx],
                                            self.hrf_model, self.drift_model,
                                            self.period_cut, self.drift_order,
                                            self.fir_delays, confounds_matrix,
                                            confounds_names, self.min_onset)
            else:
                design = design_matrices[run_idx]
            self.design_matrices_.append(design)

            # Mask and prepare data for GLM
            if self.verbose > 1:
                t_masking = time.time()
                sys.stderr.write('Starting masker computation \r')

            Y = self.masker_.transform(run_img)

            if self.verbose > 1:
                t_masking = time.time() - t_masking
                sys.stderr.write('Masker took %d seconds          \n' %
                                 t_masking)

            if self.signal_scaling:
                Y, _ = mean_scaling(Y, self.scaling_axis)
            if self.memory is not None:
                mem_glm = self.memory.cache(run_glm, ignore=['n_jobs'])
            else:
                mem_glm = run_glm

            # compute GLM
            if self.verbose > 1:
                t_glm = time.time()
                sys.stderr.write('Performing GLM computation\r')
            labels, results = mem_glm(Y,
                                      design.as_matrix(),
                                      noise_model=self.noise_model,
                                      bins=100,
                                      n_jobs=self.n_jobs)
            if self.verbose > 1:
                t_glm = time.time() - t_glm
                sys.stderr.write('GLM took %d seconds         \n' % t_glm)

            self.labels_.append(labels)
            # We save memory if inspecting model details is not necessary
            if self.minimize_memory:
                for key in results:
                    results[key] = SimpleRegressionResults(results[key])
            self.results_.append(results)
            del Y

        # Report progress
        if self.verbose > 0:
            sys.stderr.write(
                "\nComputation of %d runs done in %i seconds\n\n" %
                (n_runs, time.time() - t0))

        return self

    def compute_contrast(self,
                         contrast_def,
                         stat_type=None,
                         output_type='z_score'):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.
        In multi-session case, outputs the fixed effects map.

        Parameters
        ----------
        contrast_def : str or array of shape (n_col) or list of (string or
                       array of shape (n_col))
            where ``n_col`` is the number of columns of the design matrix,
            (one array per run). If only one array is provided when there
            are several runs, it will be assumed that the same contrast is
            desired for all runs. The string can be a formula compatible with
            the linear constraint of the Patsy library. Basically one can use
            the name of the conditions as they appear in the design matrix of
            the fitted model combined with operators /*+- and numbers.
            Please checks the patsy documentation for formula examples:
            http://patsy.readthedocs.io/en/latest/API-reference.html#patsy.DesignInfo.linear_constraint

        stat_type : {'t', 'F'}, optional
            type of the contrast

        output_type : str, optional
            Type of the output map. Can be 'z_score', 'stat', 'p_value',
            'effect_size' or 'effect_variance'

        Returns
        -------
        output : Nifti1Image
            The desired output image

        """
        if self.labels_ is None or self.results_ is None:
            raise ValueError('The model has not been fit yet')

        if isinstance(contrast_def, (np.ndarray, str)):
            con_vals = [contrast_def]
        elif isinstance(contrast_def, (list, tuple)):
            con_vals = contrast_def
        else:
            raise ValueError('contrast_def must be an array or str or list of'
                             ' (array or str)')

        # Translate formulas to vectors with patsy
        design_info = DesignInfo(self.design_matrices_[0].columns.tolist())
        for cidx, con in enumerate(con_vals):
            if not isinstance(con, np.ndarray):
                con_vals[cidx] = design_info.linear_constraint(con).coefs

        n_runs = len(self.labels_)
        if len(con_vals) != n_runs:
            warn('One contrast given, assuming it for all %d runs' % n_runs)
            con_vals = con_vals * n_runs
        if isinstance(output_type, _basestring):
            if output_type not in [
                    'z_score', 'stat', 'p_value', 'effect_size',
                    'effect_variance'
            ]:
                raise ValueError(
                    'output_type must be one of "z_score", "stat",'
                    ' "p_value","effect_size" or "effect_variance"')
        else:
            raise ValueError('output_type must be one of "z_score", "stat",'
                             ' "p_value","effect_size" or "effect_variance"')

        contrast = _fixed_effect_contrast(self.labels_, self.results_,
                                          con_vals, stat_type)

        estimate_ = getattr(contrast, output_type)()
        # Prepare the returned images
        output = self.masker_.inverse_transform(estimate_)
        contrast_name = str(con_vals)
        output.header['descrip'] = ('%s of contrast %s' %
                                    (output_type, contrast_name))

        return output
Beispiel #33
0
def load_data_PercIm_whb(pipeline, subj, newmask):

    #   datapath=input("Please enter the path to the preprocessed data:")
    #   mask_path=input("Please enter the path to the MNI based mask files:")
    #   protocol_path=input("Please enter the path to the protocol files:")
    #   ExpType=input("Please enter experiment type you wish to analyze - Perc or Im:")
    filename_pattern = ".nii.gz"

    datapath = "/home/elena/ATTEND/validataset/data/PI"
    mask_path = "/home/elena/ATTEND/MASKS"

    print(subj)
    print("Loading the data")
    #  print mask

    #MNI SPACE
    subj_path = os.path.join(datapath, subj)

    #NATIVE SPACE
    #subj_path=os.path.join(datapath, subjName, 'preprocessed_native')

    print(subj_path)
    # path, dirs, files = os.walk(subj_path).next()
    n_run = 4  #int(len(dirs)) #int(len(files))
    #NATIVE SPACE
    #n_run = len(files)/2

    #MNI SPACE
    #n_run = int(len(dirs))#len(files)-2
    print(n_run)
    #because apart from run files, coregistration files are also saved in the preprocessed folder, might be subject to change

    nifti_masker = NiftiMasker(
        mask_img=newmask, detrend=True, standardize=True
    )  #, memory_level=3, memory="/home/elena/ATTEND/validataset/TEMP/")

    #print current_mask.shape
    masked_data = [0] * n_run
    masked_data_scaled = [0] * n_run
    min_max_scaler = preprocessing.MinMaxScaler()
    for r in range(0, n_run):
        #NATIVE SPACE
        #run_image = nibabel.load(os.path.join(subj_path, subj+'_native_run'+str(r+1)+filename_pattern))
        #smoothed
        #run_image = nibabel.load(os.path.join(subj_path, subj+'_native_run'+str(r+1)+'_sps6'+filename_pattern))

        if pipeline == 'fts':
            run_image = nibabel.load(
                os.path.join(
                    subj_path, 'r0' + str(r + 1), 'to_standard_fts', subj +
                    '.PI.r0' + str(r + 1) + '.tstost.fts' + filename_pattern))
    #  else:
    #nibabel.load(os.path.join(subj_path, 'r0'+str(r+1), 'to_standard_fts', subj+'.PI''.r0'+str(r+1)+'.tstost.fts' +filename_pattern))
        else:
            if pipeline == 'stf':
                run_image = nibabel.load(
                    os.path.join(
                        subj_path, 'r0' + str(r + 1), 'to_standard_stf',
                        'PI.' + subj + '.r0' + str(r + 1) + '.tost_stf' +
                        filename_pattern))
        nifti_masker.fit(run_image)
        masked_data[r] = nifti_masker.transform(run_image)
        masked_data_scaled[r] = min_max_scaler.fit_transform(masked_data[r])
        print(len(masked_data_scaled[r]))
        print(masked_data_scaled[r].shape)

    return n_run, masked_data_scaled, nifti_masker
Beispiel #34
0
def non_parametric_inference(
        second_level_input, confounds=None, design_matrix=None,
        second_level_contrast=None, mask=None, smoothing_fwhm=None,
        model_intercept=True, n_perm=10000, two_sided_test=False,
        random_state=None, n_jobs=1, verbose=0):
    """Generate p-values corresponding to the contrasts provided
    based on permutation testing. This fuction reuses the 'permuted_ols'
    function Nilearn.

    Parameters
    ----------
    second_level_input: pandas DataFrame or list of Niimg-like objects.

        If a pandas DataFrame, then they have to contain subject_label,
        map_name and effects_map_path. It can contain multiple maps that
        would be selected during contrast estimation with the argument
        first_level_contrast of the compute_contrast function. The
        DataFrame will be sorted based on the subject_label column to avoid
        order inconsistencies when extracting the maps. So the rows of the
        automatically computed design matrix, if not provided, will
        correspond to the sorted subject_label column.

        If list of Niimg-like objects then this is taken literally as Y
        for the model fit and design_matrix must be provided.

    confounds: pandas DataFrame, optional
        Must contain a subject_label column. All other columns are
        considered as confounds and included in the model. If
        design_matrix is provided then this argument is ignored.
        The resulting second level design matrix uses the same column
        names as in the given DataFrame for confounds. At least two columns
        are expected, "subject_label" and at least one confound.

    design_matrix: pandas DataFrame, optional
        Design matrix to fit the GLM. The number of rows
        in the design matrix must agree with the number of maps derived
        from second_level_input.
        Ensure that the order of maps given by a second_level_input
        list of Niimgs matches the order of the rows in the design matrix.

    second_level_contrast: str or array of shape (n_col), optional
        Where ``n_col`` is the number of columns of the design matrix.
        The default (None) is accepted if the design matrix has a single
        column, in which case the only possible contrast array([1]) is
        applied; when the design matrix has multiple columns, an error is
        raised.

    mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters. Automatic mask computation assumes first level imgs have
        already been masked.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    model_intercept : bool,
      If True, a constant column is added to the confounding variates
      unless the tested variate is already the intercept.

    n_perm : int,
      Number of permutations to perform.
      Permutations are costly but the more are performed, the more precision
      one gets in the p-values estimation.

    two_sided_test : boolean,
      If True, performs an unsigned t-test. Both positive and negative
      effects are considered; the null hypothesis is that the effect is zero.
      If False, only positive effects are considered as relevant. The null
      hypothesis is that the effect is zero or negative.

    random_state : int or None,
      Seed for random number generator, to have the same permutations
      in each computing units.

    n_jobs : int,
      Number of parallel workers.
      If -1 is provided, all CPUs are used.
      A negative number indicates that all the CPUs except (abs(n_jobs) - 1)
      ones will be used.

    verbose: int, optional
        verbosity level (0 means no message).

    Returns
    -------
    neg_log_corrected_pvals_img: Nifti1Image
        The image which contains negative logarithm of the
        corrected p-values
    """
    _check_second_level_input(second_level_input, design_matrix,
                              flm_object=False, df_object=False)
    _check_confounds(confounds)
    _check_design_matrix(design_matrix)

    # Report progress
    t0 = time.time()
    if verbose > 0:
        sys.stderr.write("Fitting second level model...")

    # Select sample map for masker fit and get subjects_label for design
    sample_map = mean_img(second_level_input)

    # Learn the mask. Assume the first level imgs have been masked.
    if not isinstance(mask, NiftiMasker):
        masker = NiftiMasker(
            mask_img=mask, smoothing_fwhm=smoothing_fwhm,
            memory=Memory(None), verbose=max(0, verbose - 1),
            memory_level=1)
    else:
        masker = clone(mask)
        if smoothing_fwhm is not None:
            if getattr(masker, 'smoothing_fwhm') is not None:
                warn('Parameter smoothing_fwhm of the masker overriden')
                setattr(masker, 'smoothing_fwhm', smoothing_fwhm)
    masker.fit(sample_map)

    # Report progress
    if verbose > 0:
        sys.stderr.write("\nComputation of second level model done in "
                         "%i seconds\n" % (time.time() - t0))

    # Check and obtain the contrast
    contrast = _get_contrast(second_level_contrast, design_matrix)

    # Get effect_maps
    effect_maps = _infer_effect_maps(second_level_input, None)

    # Check design matrix and effect maps agree on number of rows
    _check_effect_maps(effect_maps, design_matrix)

    # Obtain tested_var
    if contrast in design_matrix.columns.tolist():
        tested_var = np.asarray(design_matrix[contrast])

    # Mask data
    target_vars = masker.transform(effect_maps)

    # Perform massively univariate analysis with permuted OLS
    neg_log_pvals_permuted_ols, _, _ = permuted_ols(
        tested_var, target_vars, model_intercept=model_intercept,
        n_perm=n_perm, two_sided_test=two_sided_test,
        random_state=random_state, n_jobs=n_jobs, verbose=max(0, verbose - 1))
    neg_log_corrected_pvals_img = masker.inverse_transform(
        np.ravel(neg_log_pvals_permuted_ols))

    return neg_log_corrected_pvals_img
Beispiel #35
0
class FirstLevelGLM(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for Single-session fMRI data

    Parameters
    ----------
    mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters.

    target_affine: 3x3 or 4x4 matrix, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    target_shape: 3-tuple of integers, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    low_pass: False or float, optional
        This parameter is passed to nilearn.signal.clean.
        Please see the related documentation for details.

    high_pass: False or float, optional
        This parameter is passed to nilearn.signal.clean.
        Please see the related documentation for details.

    t_r: float, optional
        This parameter is passed to nilearn.signal.clean.
        Please see the related documentation for details.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory: instance of joblib.Memory or string
        Used to cache the masking process.
        By default, no caching is done. If a string is given, it is the
        path to the caching directory.

    memory_level: integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    standardize : boolean, optional
        If standardize is True, the time-series are centered and normed:
        their variance is put to 1 in the time dimension.

    percent_signal_change: bool, optional,
        If True, fMRI signals are scaled to percent of the mean value
        Incompatible with standardize (standardize=False is enforced when\
        percent_signal_change is True).

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.

    noise_model : {'ar1', 'ols'}, optional
        the temporal variance model. Defaults to 'ar1'

    Attributes
    ----------
    labels : array of shape (n_voxels,),
        a map of values on voxels used to identify the corresponding model

    results : dict,
        with keys corresponding to the different labels values
        values are RegressionResults instances corresponding to the voxels
    """
    def __init__(self,
                 mask=None,
                 target_affine=None,
                 target_shape=None,
                 low_pass=None,
                 high_pass=None,
                 t_r=None,
                 smoothing_fwhm=None,
                 memory=Memory(None),
                 memory_level=1,
                 standardize=False,
                 percent_signal_change=True,
                 verbose=1,
                 n_jobs=1,
                 noise_model='ar1'):
        self.mask = mask
        self.memory = memory
        self.memory_level = memory_level
        self.verbose = verbose
        self.standardize = standardize
        self.n_jobs = n_jobs
        self.low_pass = low_pass
        self.high_pass = high_pass
        self.t_r = t_r
        self.target_affine = target_affine
        self.target_shape = target_shape
        self.smoothing_fwhm = smoothing_fwhm
        self.noise_model = noise_model
        self.percent_signal_change = percent_signal_change
        if self.percent_signal_change:
            self.standardize = False

    def fit(self, imgs, design_matrices):
        """ Fit the GLM

        1. does a masker job: fMRI_data -> Y
        2. fit an ols regression to (Y, X)
        3. fit an AR(1) regression of require
        This results in an internal (labels_, regression_results_) parameters

        Parameters
        ----------
        imgs: Niimg-like object or list of Niimg-like objects,
            See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
            Data on which the GLM will be fitted. If this is a list,
            the affine is considered the same for all.

        design_matrices: pandas DataFrame or list of pandas DataFrames,
            fMRI design matrices
        """
        # First, learn the mask
        if not isinstance(self.mask, NiftiMasker):
            self.masker_ = NiftiMasker(mask_img=self.mask,
                                       smoothing_fwhm=self.smoothing_fwhm,
                                       target_affine=self.target_affine,
                                       standardize=self.standardize,
                                       low_pass=self.low_pass,
                                       high_pass=self.high_pass,
                                       mask_strategy='epi',
                                       t_r=self.t_r,
                                       memory=self.memory,
                                       verbose=max(0, self.verbose - 1),
                                       target_shape=self.target_shape,
                                       memory_level=self.memory_level)
        else:
            self.masker_ = clone(self.mask)
            for param_name in [
                    'target_affine', 'target_shape', 'smoothing_fwhm',
                    'low_pass', 'high_pass', 't_r', 'memory', 'memory_level'
            ]:
                our_param = getattr(self, param_name)
                if our_param is None:
                    continue
                if getattr(self.masker_, param_name) is not None:
                    warn('Parameter %s of the masker overriden' % param_name)
                setattr(self.masker_, param_name, our_param)

        # make design_matrices a list of arrays
        if isinstance(design_matrices, (_basestring, pd.DataFrame)):
            design_matrices_ = [design_matrices]
        else:
            design_matrices_ = [X for X in design_matrices]

        design_matrices = []
        for design_matrix in design_matrices_:
            if isinstance(design_matrix, _basestring):
                loaded = pd.read_csv(design_matrix, index_col=0)
                design_matrices.append(loaded.values)
            elif isinstance(design_matrix, pd.DataFrame):
                design_matrices.append(design_matrix.values)
            else:
                raise TypeError(
                    'Design matrix can only be a pandas DataFrames or a'
                    'string. A %s was provided' % type(design_matrix))

        # make imgs a list of Nifti1Images
        if isinstance(imgs, (Nifti1Image, _basestring)):
            imgs = [imgs]

        if len(imgs) != len(design_matrices):
            raise ValueError(
                'len(imgs) %d does not match len(design_matrices) %d' %
                (len(imgs), len(design_matrices)))

        # Loop on imgs and design matrices
        self.labels_, self.results_ = [], []
        self.masker_.fit(imgs)
        for X, img in zip(design_matrices, imgs):
            Y = self.masker_.transform(img)
            if self.percent_signal_change:
                Y, _ = percent_mean_scaling(Y)
            labels_, results_ = session_glm(Y,
                                            X,
                                            noise_model=self.noise_model,
                                            bins=100)
            self.labels_.append(labels_)
            self.results_.append(results_)
        return self

    def transform(self,
                  con_vals,
                  contrast_type=None,
                  contrast_name='',
                  output_z=True,
                  output_stat=False,
                  output_effects=False,
                  output_variance=False):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.
        In multi-session case, outputs the fixed effects map.

        Parameters
        ----------
        con_vals : array or list of arrays of shape (n_col) or (n_dim, n_col)
            where ``n_col`` is the number of columns of the design matrix,
            numerical definition of the contrast (one array per run)

        contrast_type : {'t', 'F'}, optional
            type of the contrast

        contrast_name : str, optional
            name of the contrast

        output_z : bool, optional
            Return or not the corresponding z-stat image

        output_stat : bool, optional
            Return or not the base (t/F) stat image

        output_effects : bool, optional
            Return or not the corresponding effect image

        output_variance : bool, optional
            Return or not the corresponding variance image

        Returns
        -------
        output_images : list of Nifti1Images
            The desired output images

        """
        if self.labels_ is None or self.results_ is None:
            raise ValueError('The model has not been fit yet')

        if isinstance(con_vals, np.ndarray):
            con_vals = [con_vals]
        if len(con_vals) != len(self.results_):
            raise ValueError(
                'contrasts must be a sequence of %d session contrasts' %
                len(self.results_))

        contrast = None
        for i, (labels_, results_, con_val) in enumerate(
                zip(self.labels_, self.results_, con_vals)):
            if np.all(con_val == 0):
                warn('Contrast for session %d is null' % i)
            contrast_ = compute_contrast(labels_, results_, con_val,
                                         contrast_type)
            if contrast is None:
                contrast = contrast_
            else:
                contrast = contrast + contrast_

        if output_z or output_stat:
            # compute the contrast and stat
            contrast.z_score()

        # Prepare the returned images
        do_outputs = [output_z, output_stat, output_effects, output_variance]
        estimates = ['z_score_', 'stat_', 'effect', 'variance']
        descrips = [
            'z statistic', 'Statistical value', 'Estimated effect',
            'Estimated variance'
        ]
        output_images = []
        for do_output, estimate, descrip in zip(do_outputs, estimates,
                                                descrips):
            if not do_output:
                continue
            estimate_ = getattr(contrast, estimate)
            if estimate_.ndim == 3:
                shape_ = estimate_.shape
                estimate_ = np.reshape(estimate_,
                                       (shape_[0] * shape_[1], shape_[2]))
            output = self.masker_.inverse_transform(estimate_)
            output.get_header()['descrip'] = ('%s of contrast %s' %
                                              (descrip, contrast_name))
            output_images.append(output)
        return output_images

    def fit_transform(self,
                      design_matrices,
                      fmri_images,
                      con_vals,
                      contrast_type=None,
                      contrast_name='',
                      output_z=True,
                      output_stat=False,
                      output_effects=False,
                      output_variance=False):
        """ Fit then transform. For more details,
        see FirstLevelGLM.fit and FirstLevelGLM.transform documentation"""
        return self.fit(design_matrices,
                        fmri_images).transform(con_vals,
                                               contrast_type,
                                               contrast_name,
                                               output_z=True,
                                               output_stat=False,
                                               output_effects=False,
                                               output_variance=False)
Beispiel #36
0
"""
for USE_CENTROIDS in USE_CENTROIDS_SET:
    for SPATIAL_NEIGHBORHOOD in SPATIAL_NEIGHBORHOOD_SET:
        for N_CLUSTERS in N_CLUSTERS_SET:
            
            if SPATIAL_NEIGHBORHOOD:
                img_shape = masker.mask_img_.shape
                x,y,z = np.meshgrid(np.arange(img_shape[1]),
                                    np.arange(img_shape[0]),
                                    np.arange(img_shape[2]))
                                    
                x_img = nib.Nifti1Image(x, masker.affine_)
                y_img = nib.Nifti1Image(y, masker.affine_)
                z_img = nib.Nifti1Image(z, masker.affine_)
                
                loc = masker.transform([x_img, y_img, z_img])
            else:
                loc = np.zeros((0, pet_data_masked.shape[1]))
            
            
            ##############################################################################
            # MiniBatch Kmeans
            ##############################################################################
            
            mbk = MiniBatchKMeans(init='k-means++', n_clusters=N_CLUSTERS,
                                  n_init=10, max_no_improvement=10, verbose=0)
            
            pet_loc_data = np.concatenate((pet_data_masked.T, loc.T), axis=1)
            
            mbk.fit(pet_loc_data)
            mbk_means_labels = mbk.labels_
Beispiel #37
0
        contrasts = contrasts[1:]
    elif task in ['HcpGambling', 'HcpLanguage', 'HcpRelational', 'HcpSocial']:
        order = [1, 0]
        contrasts = [contrasts[c] for c in order]
        contrasts = contrasts[1:]
    elif task in ['HcpMotor', 'HcpWm']:
        order = [4, 3, 2, 1, 0]
        contrasts = [contrasts[c] for c in order]
    elif task == 'RSVPLanguage':
        order = [7, 4, 0, 6, 3, 5, 1, 2]
        contrasts = [contrasts[c] for c in order]
        contrasts = contrasts[3:]
    n_contrasts = len(contrasts)
    for contrast in contrasts:
        imgs = task_df[task_df.contrast == contrast].path.values
        X = masker.transform(imgs)
        correlations = append_correlation(imgs, masker, correlations)

    correlations = np.array(correlations)
    # Define subplot box for bar charts and its pos in the fig
    ax = plt.axes(
        [.3 + .48 * column, q * .048 + .115, .21, n_contrasts * .049])
    ax.barh(np.arange(n_contrasts),
            correlations.mean(1),
            .75,
            xerr=correlations.std(1),
            error_kw=dict(capsize=2, captick=3),
            color=colors[j])
    ax.set_yticks(np.arange(n_contrasts))
    new_labels = []
    for i in range(n_contrasts):
Beispiel #38
0
    if len(np.unique(haxby_labels)) != 9:
        print "\n\n\n **** WARNING FOR SUBJECT %d (2) ***** \n\n\n" % si

    # ## Find voxels of interest ##############################################
    print("Build a mask based on the activations.")
    epi_masker = NiftiMasker(mask_strategy='epi',
                             detrend=True,
                             standardize=True)
    epi_masker = mem.cache(epi_masker.fit)(fmri_raw_img)
    plot_roi(epi_masker.mask_img_,
             bg_img=anat_img,
             title='EPI mask (Subj %d)' % si)

    print("Normalize the (transformed) data"
          )  # zscore per pixel, over examples.
    fmri_masked_vectors = epi_masker.transform(fmri_raw_img)
    fmri_normed_vectors = mem.cache(stats.mstats.zscore)(fmri_masked_vectors,
                                                         axis=0)
    fmri_normed_img = epi_masker.inverse_transform(fmri_normed_vectors)

    print("Smooth the (spatial) data.")
    fmri_smooth_img = mem.cache(image.smooth_img)(fmri_normed_img, fwhm=6)

    print("Mask the MRI data.")
    masked_fmri_vectors = mem.cache(epi_masker.transform)(fmri_smooth_img)
    fmri_masked_img = epi_masker.inverse_transform(masked_fmri_vectors)

    # ## Use similarity across conditions as the 4th dimension ##########################################
    print("Compute similarity via ttest.")
    condition_names = list(np.unique(haxby_labels))
    n_conds = len(condition_names)
Beispiel #39
0
def cluster_level_inference(stat_img,
                            mask_img=None,
                            threshold=3.,
                            alpha=.05,
                            verbose=False):
    """ Report the proportion of active voxels for all clusters
    defined by the input threshold.

    Parameters
    ----------
    stat_img : Niimg-like object or None, optional
       statistical image (presumably in z scale)
  
    mask_img : Niimg-like object, optional,
        mask image

    threshold: list of floats, optional
       cluster-forming threshold in z-scale.
  
    alpha: float or list, optional
        level of control on the true positive rate, aka true dsicovery
        proportion

    verbose: bool, optional
        verbosity mode

    Returns
    -------
    proportion_true_discoveries_img: Nifti1Image,
        the statistical map that gives the true positive

    Note
    ----
    This implements the method described in:

    Rosenblatt JD, Finos L, Weeda WD, Solari A, Goeman JJ. All-Resolutions
    Inference for brain imaging. Neuroimage. 2018 Nov 1;181:786-796. doi:
    10.1016/j.neuroimage.2018.07.060
    """
    if not isinstance(threshold, list):
        threshold = [threshold]

    if mask_img is None:
        masker = NiftiMasker(mask_strategy='background').fit(stat_img)
    else:
        masker = NiftiMasker(mask_img=mask_img).fit()
    stats = np.ravel(masker.transform(stat_img))
    hommel_value = _compute_hommel_value(stats, alpha, verbose=verbose)

    # embed it back to 3D grid
    stat_map = get_data(masker.inverse_transform(stats))

    # Extract connected components above threshold
    proportion_true_discoveries_img = math_img('0. * img', img=stat_img)
    proportion_true_discoveries = masker.transform(
        proportion_true_discoveries_img).ravel()

    for threshold_ in sorted(threshold):
        label_map, n_labels = label(stat_map > threshold_)
        labels = label_map[get_data(masker.mask_img_) > 0]
        for label_ in range(1, n_labels + 1):
            # get the z-vals in the cluster
            cluster_vals = stats[labels == label_]
            proportion = _true_positive_fraction(cluster_vals, hommel_value,
                                                 alpha)
            proportion_true_discoveries[labels == label_] = proportion

    proportion_true_discoveries_img = masker.inverse_transform(
        proportion_true_discoveries)
    return proportion_true_discoveries_img
Beispiel #40
0
def map_threshold(stat_img=None,
                  mask_img=None,
                  alpha=.001,
                  threshold=3.,
                  height_control='fpr',
                  cluster_threshold=0):
    """ Compute the required threshold level and return the thresholded map

    Parameters
    ----------
    stat_img : Niimg-like object or None, optional
       statistical image (presumably in z scale)
       whenever height_control is 'fpr' or None,
       stat_img=None is acceptable.
       If it is 'fdr' or 'bonferroni', an error is raised if stat_img is None.

    mask_img : Niimg-like object, optional,
        mask image

    alpha: float or list, optional
        number controlling the thresholding (either a p-value or q-value).
        Its actual meaning depends on the height_control parameter.
        This function translates alpha to a z-scale threshold.

    threshold: float, optional
       desired threshold in z-scale.
       This is used only if height_control is None

    height_control: string, or None optional
        false positive control meaning of cluster forming
        threshold: 'fpr'|'fdr'|'bonferroni'\|None

    cluster_threshold : float, optional
        cluster size threshold. In the returned thresholded map,
        sets of connected voxels (`clusters`) with size smaller
        than this number will be removed.

    Returns
    -------
    thresholded_map : Nifti1Image,
        the stat_map thresholded at the prescribed voxel- and cluster-level

    threshold: float,
        the voxel-level threshold used actually

    Note
    ----
    If the input image is not z-scaled (i.e. some z-transformed statistic)
    the computed threshold is not rigorous and likely meaningless
    """
    height_control_methods = [
        'fpr', 'fdr', 'bonferroni', 'all-resolution-inference', None
    ]
    if height_control not in height_control_methods:
        raise ValueError("height control should be one of {0}",
                         height_control_methods)

    # if height_control is 'fpr' or None, we don't need to look at the data
    # to compute the threshold
    if height_control == 'fpr':
        threshold = norm.isf(alpha)

    # In this case, and if stat_img is None, we return
    if stat_img is None:
        if height_control in ['fpr', None]:
            return None, threshold
        else:
            raise ValueError(
                'Map_threshold requires stat_img not to be None'
                'when the height_control procedure is "bonferroni" or "fdr"')

    if mask_img is None:
        masker = NiftiMasker(mask_strategy='background').fit(stat_img)
    else:
        masker = NiftiMasker(mask_img=mask_img).fit()
    stats = np.ravel(masker.transform(stat_img))
    n_voxels = np.size(stats)

    if height_control == 'fdr':
        threshold = fdr_threshold(stats, alpha)
    elif height_control == 'bonferroni':
        threshold = norm.isf(alpha / n_voxels)
    stats *= (stats > threshold)

    # embed it back to 3D grid
    stat_map = get_data(masker.inverse_transform(stats))

    # Extract connected components above threshold
    label_map, n_labels = label(stat_map > threshold)
    labels = label_map[get_data(masker.mask_img_) > 0]

    for label_ in range(1, n_labels + 1):
        if np.sum(labels == label_) < cluster_threshold:
            stats[labels == label_] = 0

    return masker.inverse_transform(stats), threshold
Beispiel #41
0
def map_threshold(stat_img, mask_img=None, threshold=.001,
                  height_control='fpr', cluster_threshold=0):
    """ Threshold the provided map

    Parameters
    ----------
    stat_img : Niimg-like object,
       statistical image (presumably in z scale)

    mask_img : Niimg-like object, optional,
        mask image

    threshold: float, optional
        cluster forming threshold (either a p-value or z-scale value)

    height_control: string, optional
        false positive control meaning of cluster forming
        threshold: 'fpr'|'fdr'|'bonferroni'|'none'

    cluster_threshold : float, optional
        cluster size threshold

    Returns
    -------
    thresholded_map : Nifti1Image,
        the stat_map theresholded at the prescribed voxel- and cluster-level
        
    threshold: float,
        the voxel-level threshold used actually
    """
    # Masking
    if mask_img is None:
        masker = NiftiMasker(mask_strategy='background').fit(stat_img)
    else:
        masker = NiftiMasker(mask_img=mask_img).fit()
    stats = np.ravel(masker.transform(stat_img))
    n_voxels = np.size(stats)

    # Thresholding
    if height_control == 'fpr':
        z_th = norm.isf(threshold)
    elif height_control == 'fdr':
        z_th = fdr_threshold(stats, threshold)
    elif height_control == 'bonferroni':
        z_th = norm.isf(threshold / n_voxels)
    else:  # Brute-force thresholding
        z_th = threshold
    stats *= (stats > z_th)

    # embed it back to 3D grid
    stat_map = masker.inverse_transform(stats).get_data()

    # Extract connected components above threshold
    label_map, n_labels = label(stat_map > z_th)
    labels = label_map[masker.mask_img_.get_data() > 0]

    for label_ in range(1, n_labels + 1):
        if np.sum(labels == label_) < cluster_threshold:
            stats[labels == label_] = 0

    return masker.inverse_transform(stats), z_th
Beispiel #42
0
class FirstLevelModel(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for single session fMRI data

    Parameters
    ----------
    t_r : float
        This parameter indicates repetition times of the experimental runs.
        In seconds. It is necessary to correctly consider times in the design
        matrix. This parameter is also passed to nilearn.signal.clean.
        Please see the related documentation for details.

    slice_time_ref : float, optional (default 0.)
        This parameter indicates the time of the reference slice used in the
        slice timing preprocessing step of the experimental runs. It is
        expressed as a percentage of the t_r (time repetition), so it can have
        values between 0. and 1.

    hrf_model : {'spm', 'spm + derivative', 'spm + derivative + dispersion',
        'glover', 'glover + derivative', 'glover + derivative + dispersion',
        'fir', None}
        String that specifies the hemodynamic response function. Defaults to 'glover'.

    drift_model : string, optional
        This parameter specifies the desired drift model for the design
        matrices. It can be 'polynomial', 'cosine' or None.

    period_cut : float, optional
        This parameter specifies the cut period of the high-pass filter in
        seconds for the design matrices. Used only if drift_model is 'cosine'.

    drift_order : int, optional
        This parameter specifices the order of the drift model (in case it is
        polynomial) for the design matrices.

    fir_delays : array of shape(n_onsets) or list, optional
        In case of FIR design, yields the array of delays used in the FIR
        model, in seconds.

    min_onset : float, optional
        This parameter specifies the minimal onset relative to the design
        (in seconds). Events that start before (slice_time_ref * t_r +
        min_onset) are not considered.

    mask_img : Niimg-like, NiftiMasker object or False, optional
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a NiftiMasker with default
        parameters. If False is given then the data will not be masked.

    target_affine : 3x3 or 4x4 matrix, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    target_shape : 3-tuple of integers, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    smoothing_fwhm : float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory : string, optional
        Path to the directory used to cache the masking process and the glm
        fit. By default, no caching is done. Creates instance of joblib.Memory.

    memory_level : integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    standardize : boolean, optional
        If standardize is True, the time-series are centered and normed:
        their variance is put to 1 in the time dimension.

    signal_scaling : False, int or (int, int), optional,
        If not False, fMRI signals are scaled to the mean value of scaling_axis
        given, which can be 0, 1 or (0, 1). 0 refers to mean scaling each voxel
        with respect to time, 1 refers to mean scaling each time point with
        respect to all voxels and (0, 1) refers to scaling with respect to
        voxels and time, which is known as grand mean scaling.
        Incompatible with standardize (standardize=False is enforced when
        signal_scaling is not False).

    noise_model : {'ar1', 'ols'}, optional
        The temporal variance model. Defaults to 'ar1'

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.
        If 0 prints nothing. If 1 prints progress by computation of
        each run. If 2 prints timing details of masker and GLM. If 3
        prints masker computation details.

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    minimize_memory : boolean, optional
        Gets rid of some variables on the model fit results that are not
        necessary for contrast computation and would only be useful for
        further inspection of model details. This has an important impact
        on memory consumption. True by default.

    subject_label : string, optional
        This id will be used to identify a `FirstLevelModel` when passed to
        a `SecondLevelModel` object.

    Attributes
    ----------
    labels : array of shape (n_voxels,),
        a map of values on voxels used to identify the corresponding model

    results : dict,
        with keys corresponding to the different labels values
        values are RegressionResults instances corresponding to the voxels

    """
    @replace_parameters({'mask': 'mask_img'}, end_version='next')
    def __init__(self, t_r=None, slice_time_ref=0., hrf_model='glover',
                 drift_model='cosine', period_cut=128, drift_order=1,
                 fir_delays=[0], min_onset=-24, mask_img=None, target_affine=None,
                 target_shape=None, smoothing_fwhm=None, memory=Memory(None),
                 memory_level=1, standardize=False, signal_scaling=0,
                 noise_model='ar1', verbose=0, n_jobs=1,
                 minimize_memory=True, subject_label=None):
        # design matrix parameters
        self.t_r = t_r
        self.slice_time_ref = slice_time_ref
        self.hrf_model = hrf_model
        self.drift_model = drift_model
        self.period_cut = period_cut
        self.drift_order = drift_order
        self.fir_delays = fir_delays
        self.min_onset = min_onset
        # glm parameters
        self.mask_img = mask_img
        self.target_affine = target_affine
        self.target_shape = target_shape
        self.smoothing_fwhm = smoothing_fwhm
        if isinstance(memory, _basestring):
            self.memory = Memory(memory)
        else:
            self.memory = memory
        self.memory_level = memory_level
        self.standardize = standardize
        if signal_scaling is False:
            self.signal_scaling = signal_scaling
        elif signal_scaling in [0, 1, (0, 1)]:
            self.scaling_axis = signal_scaling
            self.signal_scaling = True
            self.standardize = False
        else:
            raise ValueError('signal_scaling must be "False", "0", "1"'
                             ' or "(0, 1)"')
        self.noise_model = noise_model
        self.verbose = verbose
        self.n_jobs = n_jobs
        self.minimize_memory = minimize_memory
        # attributes
        self.labels_ = None
        self.results_ = None
        self.subject_label = subject_label

    def fit(self, run_imgs, events=None, confounds=None,
            design_matrices=None):
        """ Fit the GLM

        For each run:
        1. create design matrix X
        2. do a masker job: fMRI_data -> Y
        3. fit regression to (Y, X)

        Parameters
        ----------
        run_imgs: Niimg-like object or list of Niimg-like objects,
            See http://nilearn.github.io/manipulating_images/input_output.html#inputing-data-file-names-or-image-objects
            Data on which the GLM will be fitted. If this is a list,
            the affine is considered the same for all.

        events: pandas Dataframe or string or list of pandas DataFrames or
                   strings
                   
            fMRI events used to build design matrices. One events object
            expected per run_img. Ignored in case designs is not None.
            If string, then a path to a csv file is expected.

        confounds: pandas Dataframe or string or list of pandas DataFrames or
                   strings
                   
            Each column in a DataFrame corresponds to a confound variable
            to be included in the regression model of the respective run_img.
            The number of rows must match the number of volumes in the
            respective run_img. Ignored in case designs is not None.
            If string, then a path to a csv file is expected.

        design_matrices: pandas DataFrame or list of pandas DataFrames,
            Design matrices that will be used to fit the GLM. If given it
            takes precedence over events and confounds.

        """
        # Check arguments
        # Check imgs type
        if events is not None:
            _check_events_file_uses_tab_separators(
                events_files=events)
        if not isinstance(run_imgs, (list, tuple)):
            run_imgs = [run_imgs]
        if design_matrices is None:
            if events is None:
                raise ValueError('events or design matrices must be provided')
            if self.t_r is None:
                raise ValueError('t_r not given to FirstLevelModel object'
                                 ' to compute design from events')
        else:
            design_matrices = _check_run_tables(run_imgs, design_matrices,
                                                'design_matrices')
        # Check that number of events and confound files match number of runs
        # Also check that events and confound files can be loaded as DataFrame
        if events is not None:
            events = _check_run_tables(run_imgs, events, 'events')
        if confounds is not None:
            confounds = _check_run_tables(run_imgs, confounds, 'confounds')

        # Learn the mask
        if self.mask_img is False:
            # We create a dummy mask to preserve functionality of api
            ref_img = check_niimg(run_imgs[0])
            self.mask_img = Nifti1Image(np.ones(ref_img.shape[:3]),
                                        ref_img.affine)
        if not isinstance(self.mask_img, NiftiMasker):
            self.masker_ = NiftiMasker(
                mask_img=self.mask_img, smoothing_fwhm=self.smoothing_fwhm,
                target_affine=self.target_affine,
                standardize=self.standardize, mask_strategy='epi',
                t_r=self.t_r, memory=self.memory,
                verbose=max(0, self.verbose - 2),
                target_shape=self.target_shape,
                memory_level=self.memory_level)
            self.masker_.fit(run_imgs[0])
        else:
            if self.mask_img.mask_img_ is None and self.masker_ is None:
                self.masker_ = clone(self.mask_img)
                for param_name in ['target_affine', 'target_shape',
                                   'smoothing_fwhm', 't_r', 'memory',
                                   'memory_level']:
                    our_param = getattr(self, param_name)
                    if our_param is None:
                        continue
                    if getattr(self.masker_, param_name) is not None:
                        warn('Parameter %s of the masker'
                             ' overriden' % param_name)
                    setattr(self.masker_, param_name, our_param)
                self.masker_.fit(run_imgs[0])
            else:
                self.masker_ = self.mask_img

        # For each run fit the model and keep only the regression results.
        self.labels_, self.results_, self.design_matrices_ = [], [], []
        n_runs = len(run_imgs)
        t0 = time.time()
        for run_idx, run_img in enumerate(run_imgs):
            # Report progress
            if self.verbose > 0:
                percent = float(run_idx) / n_runs
                percent = round(percent * 100, 2)
                dt = time.time() - t0
                # We use a max to avoid a division by zero
                if run_idx == 0:
                    remaining = 'go take a coffee, a big one'
                else:
                    remaining = (100. - percent) / max(0.01, percent) * dt
                    remaining = '%i seconds remaining' % remaining

                sys.stderr.write(
                    "Computing run %d out of %d runs (%s)\n"
                    % (run_idx + 1, n_runs, remaining))

            # Build the experimental design for the glm
            run_img = check_niimg(run_img, ensure_ndim=4)
            if design_matrices is None:
                n_scans = run_img.get_data().shape[3]
                if confounds is not None:
                    confounds_matrix = confounds[run_idx].values
                    if confounds_matrix.shape[0] != n_scans:
                        raise ValueError('Rows in confounds does not match'
                                         'n_scans in run_img at index %d'
                                         % (run_idx,))
                    confounds_names = confounds[run_idx].columns.tolist()
                else:
                    confounds_matrix = None
                    confounds_names = None
                start_time = self.slice_time_ref * self.t_r
                end_time = (n_scans - 1 + self.slice_time_ref) * self.t_r
                frame_times = np.linspace(start_time, end_time, n_scans)
                design = make_first_level_design_matrix(frame_times, events[run_idx],
                                                        self.hrf_model, self.drift_model,
                                                        self.period_cut, self.drift_order,
                                                        self.fir_delays, confounds_matrix,
                                                        confounds_names, self.min_onset)
            else:
                design = design_matrices[run_idx]
            self.design_matrices_.append(design)

            # Mask and prepare data for GLM
            if self.verbose > 1:
                t_masking = time.time()
                sys.stderr.write('Starting masker computation \r')

            Y = self.masker_.transform(run_img)

            if self.verbose > 1:
                t_masking = time.time() - t_masking
                sys.stderr.write('Masker took %d seconds       \n' % t_masking)

            if self.signal_scaling:
                Y, _ = mean_scaling(Y, self.scaling_axis)
            if self.memory:
                mem_glm = self.memory.cache(run_glm, ignore=['n_jobs'])
            else:
                mem_glm = run_glm

            # compute GLM
            if self.verbose > 1:
                t_glm = time.time()
                sys.stderr.write('Performing GLM computation\r')
            labels, results = mem_glm(Y, design.values,
                                      noise_model=self.noise_model,
                                      bins=100, n_jobs=self.n_jobs)
            if self.verbose > 1:
                t_glm = time.time() - t_glm
                sys.stderr.write('GLM took %d seconds         \n' % t_glm)

            self.labels_.append(labels)
            # We save memory if inspecting model details is not necessary
            if self.minimize_memory:
                for key in results:
                    results[key] = SimpleRegressionResults(results[key])
            self.results_.append(results)
            del Y

        # Report progress
        if self.verbose > 0:
            sys.stderr.write("\nComputation of %d runs done in %i seconds\n\n"
                             % (n_runs, time.time() - t0))

        return self

    def compute_contrast(self, contrast_def, stat_type=None,
                         output_type='z_score'):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.
        In multi-session case, outputs the fixed effects map.

        Parameters
        ----------
        contrast_def : str or array of shape (n_col) or list of (string or
                       array of shape (n_col))
                       
            where ``n_col`` is the number of columns of the design matrix,
            (one array per run). If only one array is provided when there
            are several runs, it will be assumed that the same contrast is
            desired for all runs. The string can be a formula compatible with
            the linear constraint of the Patsy library. Basically one can use
            the name of the conditions as they appear in the design matrix of
            the fitted model combined with operators /\*+- and numbers.
            Please checks the patsy documentation for formula examples:
            http://patsy.readthedocs.io/en/latest/API-reference.html#patsy.DesignInfo.linear_constraint

        stat_type : {'t', 'F'}, optional
            type of the contrast

        output_type : str, optional
            Type of the output map. Can be 'z_score', 'stat', 'p_value',
            'effect_size', 'effect_variance' or 'all'

        Returns
        -------
        output : Nifti1Image or dict
            The desired output image(s). If ``output_type == 'all'``, then
            the output is a dictionary of images, keyed by the type of image.

        """
        if self.labels_ is None or self.results_ is None:
            raise ValueError('The model has not been fit yet')

        if isinstance(contrast_def, (np.ndarray, str)):
            con_vals = [contrast_def]
        elif isinstance(contrast_def, (list, tuple)):
            con_vals = contrast_def
        else:
            raise ValueError('contrast_def must be an array or str or list of'
                             ' (array or str)')

        # Translate formulas to vectors with patsy
        design_info = DesignInfo(self.design_matrices_[0].columns.tolist())
        for cidx, con in enumerate(con_vals):
            if not isinstance(con, np.ndarray):
                con_vals[cidx] = design_info.linear_constraint(con).coefs

        n_runs = len(self.labels_)
        if len(con_vals) != n_runs:
            warn('One contrast given, assuming it for all %d runs' % n_runs)
            con_vals = con_vals * n_runs

        # 'all' is assumed to be the final entry; if adding more, place before 'all'
        valid_types = ['z_score', 'stat', 'p_value', 'effect_size',
                       'effect_variance', 'all']
        if output_type not in valid_types:
            raise ValueError('output_type must be one of {}'.format(valid_types))

        contrast = _fixed_effect_contrast(self.labels_, self.results_,
                                          con_vals, stat_type)

        output_types = valid_types[:-1] if output_type == 'all' else [output_type]

        outputs = {}
        for output_type_ in output_types:
            estimate_ = getattr(contrast, output_type_)()
            # Prepare the returned images
            output = self.masker_.inverse_transform(estimate_)
            contrast_name = str(con_vals)
            output.header['descrip'] = (
                '%s of contrast %s' % (output_type_, contrast_name))
            outputs[output_type_] = output

        return outputs if output_type == 'all' else output
y_test = target[condition_mask_test]

y_train[y_train=='scissors']=1
y_train[y_train=='scrambledpix']=-1
y_train=np.array(y_train.astype('double'))

y_test[y_test=='scissors']=1
y_test[y_test=='scrambledpix']=-1
y_test=np.array(y_test.astype('double'))



masker = NiftiMasker(mask_strategy='epi',standardize=True)
                        
X_train = masker.fit_transform(X_train)
X_test  = masker.transform(X_test)

mask = masker.mask_img_.get_data().astype(np.bool)
mask= _crop_mask(mask)
background_img = mean_img(data_files.func[0])

X_train, y_train, _, y_train_mean, _ = center_data(X_train, y_train, fit_intercept=True, normalize=False,copy=False)
X_test-=X_train.mean(axis=0)
X_test/=np.std(X_train,axis=0)
alpha=1
ratio=0.5
k=200


solver_params = dict(tol=1e-6, max_iter=5000,prox_max_iter=100)
Beispiel #44
0
def map_threshold(stat_img=None, mask_img=None, level=.001,
                  height_control='fpr', cluster_threshold=0):
    """ Compute the required threshold level and return the thresholded map

    Parameters
    ----------
    stat_img : Niimg-like object or None, optional
       statistical image (presumably in z scale)
       whenever height_control is 'fpr' or None,
       stat_img=None is acceptable.
       If it is 'fdr' or 'bonferroni', an error is raised if stat_img is None.

    mask_img : Niimg-like object, optional,
        mask image

    level: float, optional
        number controling the thresholding (either a p-value or z-scale value).
        Not to be confused with the z-scale threshold: level can be a p-values,
        e.g. "0.05" or another type of number depending on the
        height_control parameter. The z-scale threshold is actually returned by
        the function.

    height_control: string, or None optional
        false positive control meaning of cluster forming
        threshold: 'fpr'|'fdr'|'bonferroni'\|None

    cluster_threshold : float, optional
        cluster size threshold. In the returned thresholded map,
        sets of connected voxels (`clusters`) with size smaller
        than this number will be removed.

    Returns
    -------
    thresholded_map : Nifti1Image,
        the stat_map thresholded at the prescribed voxel- and cluster-level

    threshold: float,
        the voxel-level threshold used actually

    Note
    ----
    If the input image is not z-scaled (i.e. some z-transformed statistic)
    the computed threshold is not rigorous and likely meaningless
    """
    # Check that height_control is correctly specified
    if height_control not in ['fpr', 'fdr', 'bonferroni', None]:
        raise ValueError(
            "height control should be one of ['fpr', 'fdr', 'bonferroni', None]")

    # if height_control is 'fpr' or None, we don't need to look at the data
    # to compute the threhsold
    if height_control == 'fpr':
        threshold = norm.isf(level)
    elif height_control is None:
        threshold = level

    # In this case, and is stat_img is None, we return
    if stat_img is None:
        if height_control in ['fpr', None]:
            return None, threshold
        else:
            raise ValueError(
                'Map_threshold requires stat_img not to be None'
                'when the heigh_control procedure is bonferroni or fdr')
    
    # Masking
    if mask_img is None:
        masker = NiftiMasker(mask_strategy='background').fit(stat_img)
    else:
        masker = NiftiMasker(mask_img=mask_img).fit()
    stats = np.ravel(masker.transform(stat_img))
    n_voxels = np.size(stats)

    # Thresholding
    if height_control == 'fdr':
        threshold = fdr_threshold(stats, level)
    elif height_control == 'bonferroni':
        threshold = norm.isf(level / n_voxels)
    stats *= (stats > threshold)

    # embed it back to 3D grid
    stat_map = masker.inverse_transform(stats).get_data()

    # Extract connected components above threshold
    label_map, n_labels = label(stat_map > threshold)
    labels = label_map[masker.mask_img_.get_data() > 0]

    for label_ in range(1, n_labels + 1):
        if np.sum(labels == label_) < cluster_threshold:
            stats[labels == label_] = 0

    return masker.inverse_transform(stats), threshold
Beispiel #45
0
labels = np.int32(labels)

# contrasts are IN ORDER -> shuffle!
new_inds = np.arange(0, X_task.shape[0])
np.random.shuffle(new_inds)
X_task = X_task[new_inds]
labels = labels[new_inds]
# subs = subs[new_inds]

# rest
# X_rest = nifti_masker.transform('preload_HR20persub_10mm_ero2.nii')
# X_rest = nifti_masker.transform('dump_rs_spca_s12_tmp')
rs_spca_data = joblib.load('dump_rs_spca_s12_tmp')
rs_spca_niis = nib.Nifti1Image(rs_spca_data,
                               nifti_masker.mask_img_.get_affine())
X_rest = nifti_masker.transform(rs_spca_niis)
del rs_spca_niis
del rs_spca_data

X_task = StandardScaler().fit_transform(X_task)
X_rest = StandardScaler().fit_transform(X_rest)

# ARCHI task
AT_niis, AT_labels, AT_subs = joblib.load('preload_AT_3mm')
AT_X = nifti_masker.transform(AT_niis)
AT_X = StandardScaler().fit_transform(AT_X)
print('done :)')

##############################################################################
# define computation graph
##############################################################################
Beispiel #46
0
class SecondLevelModel(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for multiple subject
    fMRI data

    Parameters
    ----------

    mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters. Automatic mask computation assumes first level imgs have
        already been masked.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory: string, optional
        Path to the directory used to cache the masking process and the glm
        fit. By default, no caching is done. Creates instance of joblib.Memory.

    memory_level: integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.
        If 0 prints nothing. If 1 prints final computation time.
        If 2 prints masker computation details.

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    minimize_memory : boolean, optional
        Gets rid of some variables on the model fit results that are not
        necessary for contrast computation and would only be useful for
        further inspection of model details. This has an important impact
        on memory consumption. True by default.

    """
    def __init__(self,
                 mask=None,
                 smoothing_fwhm=None,
                 memory=None,
                 memory_level=1,
                 verbose=0,
                 n_jobs=1,
                 minimize_memory=True):
        self.mask = mask
        self.smoothing_fwhm = smoothing_fwhm
        self.memory = memory
        self.memory_level = memory_level
        self.verbose = verbose
        self.n_jobs = n_jobs
        self.minimize_memory = minimize_memory
        self.second_level_input_ = None
        self.confounds_ = None

    def fit(self, second_level_input, confounds=None, design_matrix=None):
        """ Fit the second-level GLM

        1. create design matrix
        2. do a masker job: fMRI_data -> Y
        3. fit regression to (Y, X)

        Parameters
        ----------
        second_level_input: list of `FirstLevelModel` objects or pandas
                            DataFrame or list of Niimg-like objects.
            Giving FirstLevelModel objects will allow to easily compute
            the second level contast of arbitrary first level contrasts thanks
            to the first_level_contrast argument of the compute_contrast
            method. Effect size images will be computed for each model to
            contrast at the second level.

            If a pandas DataFrame, then they have to contain subject_label,
            map_name and effects_map_path. It can contain multiple maps that
            would be selected during contrast estimation with the argument
            first_level_contrast of the compute_contrast function. The
            DataFrame will be sorted based on the subject_label column to avoid
            order inconsistencies when extracting the maps. So the rows of the
            automatically computed design matrix, if not provided, will
            correspond to the sorted subject_label column.
 
            If list of Niimg-like objects then this is taken literally as Y
            for the model fit and design_matrix must be provided.

        confounds: pandas DataFrame, optional
            Must contain a subject_label column. All other columns are
            considered as confounds and included in the model. If
            design_matrix is provided then this argument is ignored.
            The resulting second level design matrix uses the same column
            names as in the given DataFrame for confounds. At least two columns
            are expected, "subject_label" and at least one confound.

        design_matrix: pandas DataFrame, optional
            Design matrix to fit the GLM. The number of rows
            in the design matrix must agree with the number of maps derived
            from second_level_input.
            Ensure that the order of maps given by a second_level_input
            list of Niimgs matches the order of the rows in the design matrix.
            Must contain a column of 1s with column name 'intercept'.
        """
        # Check parameters
        # check first level input
        if isinstance(second_level_input, list):
            if len(second_level_input) < 2:
                raise ValueError('A second level model requires a list with at'
                                 'least two first level models or niimgs')
            # Check FirstLevelModel objects case
            if isinstance(second_level_input[0], FirstLevelModel):
                models_input = enumerate(second_level_input)
                for model_idx, first_level_model in models_input:
                    if (first_level_model.labels_ is None
                            or first_level_model.results_ is None):
                        raise ValueError(
                            'Model %s at index %i has not been fit yet'
                            '' % (first_level_model.subject_label, model_idx))
                    if not isinstance(first_level_model, FirstLevelModel):
                        raise ValueError(' object at idx %d is %s instead of'
                                         ' FirstLevelModel object' %
                                         (model_idx, type(first_level_model)))
                    if confounds is not None:
                        if first_level_model.subject_label is None:
                            raise ValueError(
                                'In case confounds are provided, first level '
                                'objects need to provide the attribute '
                                'subject_label to match rows appropriately.'
                                'Model at idx %d does not provide it. '
                                'To set it, you can do '
                                'first_level_model.subject_label = "01"'
                                '' % (model_idx))
            # Check niimgs case
            elif isinstance(second_level_input[0], (str, Nifti1Image)):
                if design_matrix is None:
                    raise ValueError('List of niimgs as second_level_input'
                                     ' require a design matrix to be provided')
                for model_idx, niimg in enumerate(second_level_input):
                    if not isinstance(niimg, (str, Nifti1Image)):
                        raise ValueError(' object at idx %d is %s instead of'
                                         ' Niimg-like object' %
                                         (model_idx, type(niimg)))
        # Check pandas dataframe case
        elif isinstance(second_level_input, pd.DataFrame):
            for col in ['subject_label', 'map_name', 'effects_map_path']:
                if col not in second_level_input.columns:
                    raise ValueError('second_level_input DataFrame must have'
                                     ' columns subject_label, map_name and'
                                     ' effects_map_path')
            # Make sure subject_label contain strings
            second_level_columns = second_level_input.columns.tolist()
            labels_index = second_level_columns.index('subject_label')
            labels_dtype = second_level_input.dtypes[labels_index]
            if not isinstance(labels_dtype, np.object):
                raise ValueError('subject_label column must be of dtype '
                                 'object instead of dtype %s' % labels_dtype)
        else:
            raise ValueError('second_level_input must be a list of'
                             ' `FirstLevelModel` objects, a pandas DataFrame'
                             ' or a list Niimg-like objects. Instead %s '
                             'was provided' % type(second_level_input))

        # check confounds
        if confounds is not None:
            if not isinstance(confounds, pd.DataFrame):
                raise ValueError('confounds must be a pandas DataFrame')
            if 'subject_label' not in confounds.columns:
                raise ValueError('confounds DataFrame must contain column'
                                 '"subject_label"')
            if len(confounds.columns) < 2:
                raise ValueError('confounds should contain at least 2 columns'
                                 'one called "subject_label" and the other'
                                 'with a given confound')
            # Make sure subject_label contain strings
            labels_index = confounds.columns.tolist().index('subject_label')
            labels_dtype = confounds.dtypes[labels_index]
            if not isinstance(labels_dtype, np.object):
                raise ValueError('subject_label column must be of dtype '
                                 'object instead of dtype %s' % labels_dtype)

        # check design matrix
        if design_matrix is not None:
            if not isinstance(design_matrix, pd.DataFrame):
                raise ValueError('design matrix must be a pandas DataFrame')
            if 'intercept' not in design_matrix.columns:
                raise ValueError('design matrix must contain "intercept"')

        # sort a pandas dataframe by subject_label to avoid inconsistencies
        # with the design matrix row order when automatically extracting maps
        if isinstance(second_level_input, pd.DataFrame):
            # Avoid pandas df.sort_value to keep compatibility with numpy 1.8
            # also pandas df.sort since it is completely deprecated.
            columns = second_level_input.columns.tolist()
            column_index = columns.index('subject_label')
            sorted_matrix = sorted(second_level_input.as_matrix(),
                                   key=lambda x: x[column_index])
            sorted_input = pd.DataFrame(sorted_matrix, columns=columns)
            second_level_input = sorted_input

        self.second_level_input_ = second_level_input
        self.confounds_ = confounds

        # Report progress
        t0 = time.time()
        if self.verbose > 0:
            sys.stderr.write("Fitting second level model. "
                             "Take a deep breath\r")

        # Select sample map for masker fit and get subjects_label for design
        if isinstance(second_level_input, pd.DataFrame):
            sample_map = second_level_input['effects_map_path'][0]
            labels = second_level_input['subject_label']
            subjects_label = labels.values.tolist()
        elif isinstance(second_level_input[0], FirstLevelModel):
            sample_model = second_level_input[0]
            sample_condition = sample_model.design_matrices_[0].columns[0]
            sample_map = sample_model.compute_contrast(
                sample_condition, output_type='effect_size')
            labels = [model.subject_label for model in second_level_input]
            subjects_label = labels
        else:
            # In this case design matrix had to be provided
            sample_map = second_level_input[0]

        # Create and set design matrix, if not given
        if design_matrix is None:
            design_matrix = create_second_level_design(subjects_label,
                                                       confounds)
        self.design_matrix_ = design_matrix

        # Learn the mask. Assume the first level imgs have been masked.
        if not isinstance(self.mask, NiftiMasker):
            self.masker_ = NiftiMasker(mask_img=self.mask,
                                       smoothing_fwhm=self.smoothing_fwhm,
                                       memory=self.memory,
                                       verbose=max(0, self.verbose - 1),
                                       memory_level=self.memory_level)
        else:
            self.masker_ = clone(self.mask)
            for param_name in ['smoothing_fwhm', 'memory', 'memory_level']:
                our_param = getattr(self, param_name)
                if our_param is None:
                    continue
                if getattr(self.masker_, param_name) is not None:
                    warn('Parameter %s of the masker overriden' % param_name)
                setattr(self.masker_, param_name, our_param)
        self.masker_.fit(sample_map)

        # Report progress
        if self.verbose > 0:
            sys.stderr.write("\nComputation of second level model done in "
                             "%i seconds\n" % (time.time() - t0))

        return self

    def compute_contrast(self,
                         second_level_contrast='intercept',
                         first_level_contrast=None,
                         second_level_stat_type=None,
                         output_type='z_score'):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.

        Parameters
        ----------
        second_level_contrast: str or array of shape (n_col), optional
            Where ``n_col`` is the number of columns of the design matrix,
            The string can be a formula compatible with the linear constraint
            of the Patsy library. Basically one can use the name of the
            conditions as they appear in the design matrix of
            the fitted model combined with operators /*+- and numbers.
            Please check the patsy documentation for formula examples:
            http://patsy.readthedocs.io/en/latest/API-reference.html#patsy.DesignInfo.linear_constraint

            VERY IMPORTANT: The 'intercept' corresponds to the second level
            effect after taking confounders in consideration. If there are
            no confounders then this will be equivalent to a simple t test.
            By default we compute the 'intercept' second level contrast.

        first_level_contrast: str or array of shape (n_col) with respect to
                              FirstLevelModel, optional
            In case a list of FirstLevelModel was provided as
            second_level_input, we have to provide a contrast to apply to
            the first level models to get the corresponding list of images
            desired, that would be tested at the second level. In case a
            pandas DataFrame was provided as second_level_input this is the
            map name to extract from the pandas dataframe map_name column.
            It has to be a 't' contrast.

        second_level_stat_type: {'t', 'F'}, optional
            Type of the second level contrast

        output_type: str, optional
            Type of the output map. Can be 'z_score', 'stat', 'p_value',
            'effect_size' or 'effect_variance'

        Returns
        -------
        output_image: Nifti1Image
            The desired output image

        """
        if self.second_level_input_ is None:
            raise ValueError('The model has not been fit yet')

        # first_level_contrast check
        if isinstance(self.second_level_input_[0], FirstLevelModel):
            if first_level_contrast is None:
                raise ValueError('If second_level_input was a list of '
                                 'FirstLevelModel, then first_level_contrast '
                                 'is mandatory. It corresponds to the '
                                 'second_level_contrast argument of the '
                                 'compute_contrast method of FirstLevelModel')

        # check contrast definition
        if isinstance(second_level_contrast, np.ndarray):
            con_val = second_level_contrast
            if np.all(con_val == 0):
                raise ValueError('Contrast is null')
        else:
            design_info = DesignInfo(self.design_matrix_.columns.tolist())
            constraint = design_info.linear_constraint(second_level_contrast)
            con_val = constraint.coefs
        # check output type
        if isinstance(output_type, _basestring):
            if output_type not in [
                    'z_score', 'stat', 'p_value', 'effect_size',
                    'effect_variance'
            ]:
                raise ValueError(
                    'output_type must be one of "z_score", "stat"'
                    ', "p_value", "effect_size" or "effect_variance"')
        else:
            raise ValueError('output_type must be one of "z_score", "stat",'
                             ' "p_value", "effect_size" or "effect_variance"')

        # Get effect_maps appropriate for chosen contrast
        effect_maps = _infer_effect_maps(self.second_level_input_,
                                         first_level_contrast)
        # check design matrix X and effect maps Y agree on number of rows
        if len(effect_maps) != self.design_matrix_.shape[0]:
            raise ValueError(
                'design_matrix does not match the number of maps considered. '
                '%i rows in design matrix do not match with %i maps' %
                (self.design_matrix_.shape[0], len(effect_maps)))

        # Fit an OLS regression for parametric statistics
        Y = self.masker_.transform(effect_maps)
        if self.memory is not None:
            arg_ignore = ['n_jobs']
            mem_glm = self.memory.cache(run_glm, ignore=arg_ignore)
        else:
            mem_glm = run_glm
        labels, results = mem_glm(Y,
                                  self.design_matrix_.as_matrix(),
                                  n_jobs=self.n_jobs,
                                  noise_model='ols')
        # We save memory if inspecting model details is not necessary
        if self.minimize_memory:
            for key in results:
                results[key] = SimpleRegressionResults(results[key])
        self.labels_ = labels
        self.results_ = results

        # We compute contrast object
        if self.memory is not None:
            mem_contrast = self.memory.cache(compute_contrast)
        else:
            mem_contrast = compute_contrast
        contrast = mem_contrast(self.labels_, self.results_, con_val,
                                second_level_stat_type)

        # We get desired output from contrast object
        estimate_ = getattr(contrast, output_type)()

        # Prepare the returned images
        output = self.masker_.inverse_transform(estimate_)
        contrast_name = str(con_val)
        output.header['descrip'] = ('%s of contrast %s' %
                                    (output_type, contrast_name))
        return output
                                    prior_group)
    meta_files = [path.replace('~', project_dir) for path in meta_files_pathes]
    meta_categories = [
        nifti_path.split(os.sep)[-1].split('_')[-1].split('.nii')[0]
        for nifti_path in meta_files
    ]
    print 'Found %i %s meta priors' % (len(meta_files), prior_group)

    # concatenate priors
    GM_masker = NiftiMasker(project_dir + '/data/raw/ref_vbm_bin.nii.gz')
    GM_masker.fit()
    prior_voxels = []
    meta_check1 = []
    for meta_file in meta_files:
        prior = nib.load(meta_file)
        prior_masked = GM_masker.transform(prior)
        prior_voxels.append(prior_masked[0])
        meta_check1.append(meta_file)
    prior_array = np.array(prior_voxels)

    # process prior_space
    if method == 'ha_pc':
        new_prior_array = copy.deepcopy(prior_array)
    elif method == 'md_pc':
        new_prior_array = prior_array - np.mean(prior_array, axis=0)
    elif method == 'ts_pc':
        new_prior_array = preprocessing.StandardScaler().fit_transform(
            prior_array)

    # extract voxel maps for each prior and k
    for k in str(k_list).split(','):
Beispiel #48
0
def compute_fixed_effects(contrast_imgs, variance_imgs, mask=None,
                          precision_weighted=False):
    """Compute the fixed effects, given images of effects and variance

    Parameters
    ----------
    contrast_imgs : list of Nifti1Images or strings
        The input contrast images.

    variance_imgs : list of Nifti1Images or strings
        The input variance images.

    mask : Nifti1Image or NiftiMasker instance or None, optional
        Mask image. If None, it is recomputed from contrast_imgs.

    precision_weighted : Bool, optional
        Whether fixed effects estimates should be weighted by inverse
        variance or not. Default=False.

    Returns
    -------
    fixed_fx_contrast_img : Nifti1Image
        The fixed effects contrast computed within the mask.

    fixed_fx_variance_img : Nifti1Image
        The fixed effects variance computed within the mask.

    fixed_fx_t_img : Nifti1Image
        The fixed effects t-test computed within the mask.

    Notes
    -----
    This function is experimental.
    It may change in any future release of Nilearn.

    """
    if len(contrast_imgs) != len(variance_imgs):
        raise ValueError(
            'The number of contrast images (%d) '
            'differs from the number of variance images (%d). '
            % (len(contrast_imgs), len(variance_imgs))
        )

    if isinstance(mask, NiftiMasker):
        masker = mask.fit()
    elif mask is None:
        masker = NiftiMasker().fit(contrast_imgs)
    else:
        masker = NiftiMasker(mask_img=mask).fit()

    variances = masker.transform(variance_imgs)
    contrasts = masker.transform(contrast_imgs)

    (fixed_fx_contrast,
     fixed_fx_variance, fixed_fx_t) = _compute_fixed_effects_params(
        contrasts, variances, precision_weighted)

    fixed_fx_contrast_img = masker.inverse_transform(fixed_fx_contrast)
    fixed_fx_variance_img = masker.inverse_transform(fixed_fx_variance)
    fixed_fx_t_img = masker.inverse_transform(fixed_fx_t)
    return fixed_fx_contrast_img, fixed_fx_variance_img, fixed_fx_t_img
Beispiel #49
0
    masker.fit()
    n_vox = r_mask.get_data().sum()

    n_files = len(nii_paths)

    if op.exists('dump_FS.npy'):
        FS = np.load('dump_FS.npy')
        cond_labels = np.load('dump_cond.npy')
        sub_labels = np.load('dump_subs.npy')
    else:
        FS = np.zeros((n_files, n_vox))
        for i_nii in range(n_files):
            print('Loading nifti into memory: %i/%i' % (i_nii + 1, n_files))
            data = np.nan_to_num(nib.load(nii_paths[i_nii]).get_data())
            nii = nib.Nifti1Image(data, r_mask.get_affine())
            cur_1d_data = masker.transform(nii)
            FS[i_nii, :] = cur_1d_data

        # save feature space to disk
        np.save('dump_FS', FS)
        np.save('dump_cond', cond_labels)
        np.save('dump_subs', sub_labels)

    from sklearn.preprocessing import StandardScaler

    FS = StandardScaler().fit_transform(FS)
    labels = cond_labels

    # type conversion
    FS = np.float32(FS)
    labels = np.int32(labels)
mask_img = nifti_masker.mask_img_

### Visualize the mask ########################################################
import matplotlib.pyplot as plt
from nilearn.plotting import plot_roi
from nilearn.image.image import mean_img

# calculate mean image for the background
mean_func_img = mean_img(func_filename)

plot_roi(mask_img, mean_func_img, display_mode='y', cut_coords=4, title="Mask")


### Preprocess data ###########################################################
nifti_masker.fit(func_filename)
fmri_masked = nifti_masker.transform(func_filename)

### Run an algorithm ##########################################################
from sklearn.decomposition import FastICA
n_components = 20
ica = FastICA(n_components=n_components, random_state=42)
components_masked = ica.fit_transform(fmri_masked.T).T

### Reverse masking ###########################################################
components = nifti_masker.inverse_transform(components_masked)

### Show results ##############################################################
from nilearn.plotting import plot_stat_map
from nilearn.image import index_img

plot_stat_map(index_img(components, 0), mean_func_img, display_mode='y',
target_header = masknii.get_header()
target_shape = masknii.shape
nifti_masker = NiftiMasker(mask_img=masknii, smoothing_fwhm=False,
                           standardize=False)
nifti_masker.fit()
nifti_masker.mask_img_.to_filename("debug_mask.nii")

for compr_name in ['PCA', 'FactorAnalysis',
                   'FastICA', 'SparsePCA']:
    for sample in ['AT', 'HT']:

        FS_nii, labels, subs = joblib.load('preload_2nd_' + sample)

        print('%s in %s' % (compr_name, sample))

        FS = nifti_masker.transform(FS_nii)

        compressor = joblib.load('preload_compr_HT%s40' % compr_name)

        FS_loadings = compressor.transform(FS)
        from scipy.stats import f_oneway

        for group, group_name in zip([labels, subs],
                                     ['tasks', 'subjects']):
            print(group_name)
            array_form = [FS_loadings[group_tag == group].ravel() for group_tag in np.unique(group)]

            fvalue, pvalue = f_oneway(*array_form)
            print('F-Value: %.4f' % fvalue)
            print('P-Value: %.16f' % pvalue)
class FirstLevelModel(BaseEstimator, TransformerMixin, CacheMixin):
    """ Implementation of the General Linear Model for single session fMRI data

    Parameters
    ----------

    t_r: float
        This parameter indicates repetition times of the experimental runs.
        In seconds. It is necessary to correctly consider times in the design
        matrix. This parameter is also passed to nilearn.signal.clean.
        Please see the related documentation for details.

    slice_time_ref: float, optional (default 0.)
        This parameter indicates the time of the reference slice used in the
        slice timing preprocessing step of the experimental runs. It is
        expressed as a percentage of the t_r (time repetition), so it can have
        values between 0. and 1.

    hrf_model : string, optional
        This parameter specifies the hemodynamic response function (HRF) for
        the design matrices. It can be 'canonical', 'canonical with derivative'
        or 'fir'.

    drift_model : string, optional
        This parameter specifies the desired drift model for the design
        matrices. It can be 'polynomial', 'cosine' or 'blank'.

    period_cut : float, optional
        This parameter specifies the cut period of the low-pass filter in
        seconds for the design matrices.

    drift_order : int, optional
        This parameter specifices the order of the drift model (in case it is
        polynomial) for the design matrices.

    fir_delays : array of shape(n_onsets) or list, optional
        In case of FIR design, yields the array of delays used in the FIR
        model, in seconds.

    min_onset : float, optional
        This parameter specifies the minimal onset relative to the design
        (in seconds). Events that start before (slice_time_ref * t_r +
        min_onset) are not considered.

    mask: Niimg-like, NiftiMasker or MultiNiftiMasker object, optional,
        Mask to be used on data. If an instance of masker is passed,
        then its mask will be used. If no mask is given,
        it will be computed automatically by a MultiNiftiMasker with default
        parameters.

    target_affine: 3x3 or 4x4 matrix, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    target_shape: 3-tuple of integers, optional
        This parameter is passed to nilearn.image.resample_img. Please see the
        related documentation for details.

    smoothing_fwhm: float, optional
        If smoothing_fwhm is not None, it gives the size in millimeters of the
        spatial smoothing to apply to the signal.

    memory: string, optional
        Path to the directory used to cache the masking process and the glm
        fit. By default, no caching is done. Creates instance of joblib.Memory.

    memory_level: integer, optional
        Rough estimator of the amount of memory used by caching. Higher value
        means more memory for caching.

    standardize : boolean, optional
        If standardize is True, the time-series are centered and normed:
        their variance is put to 1 in the time dimension.

    signal_scaling: False, int or (int, int), optional,
        If not False, fMRI signals are scaled to the mean value of scaling_axis
        given, which can be 0, 1 or (0, 1). 0 refers to mean scaling each voxel
        with respect to time, 1 refers to mean scaling each time point with
        respect to all voxels and (0, 1) refers to scaling with respect to
        voxels and time, which is known as grand mean scaling.
        Incompatible with standardize (standardize=False is enforced when
        signal_scaling is not False).

    noise_model : {'ar1', 'ols'}, optional
        The temporal variance model. Defaults to 'ar1'

    verbose : integer, optional
        Indicate the level of verbosity. By default, nothing is printed.

    n_jobs : integer, optional
        The number of CPUs to use to do the computation. -1 means
        'all CPUs', -2 'all CPUs but one', and so on.

    minimize_memory : boolean, optional
        Gets rid of some variables on the model fit results that are not
        necessary for contrast computation and would only be useful for
        further inspection of model details. This has an important impact
        on memory consumption. True by default.

    Attributes
    ----------
    labels : array of shape (n_voxels,),
        a map of values on voxels used to identify the corresponding model

    results : dict,
        with keys corresponding to the different labels values
        values are RegressionResults instances corresponding to the voxels
    """
    def __init__(self, t_r=None, slice_time_ref=0., hrf_model='glover',
                 drift_model='cosine', period_cut=128, drift_order=1,
                 fir_delays=[0], min_onset=-24, mask=None, target_affine=None,
                 target_shape=None, smoothing_fwhm=None, memory=Memory(None),
                 memory_level=1, standardize=False, signal_scaling=0,
                 noise_model='ar1', verbose=1, n_jobs=1,
                 minimize_memory=True):
        # design matrix parameters
        self.t_r = t_r
        self.slice_time_ref = slice_time_ref
        self.hrf_model = hrf_model
        self.drift_model = drift_model
        self.period_cut = period_cut
        self.drift_order = drift_order
        self.fir_delays = fir_delays
        self.min_onset = min_onset
        # glm parameters
        self.mask = mask
        self.target_affine = target_affine
        self.target_shape = target_shape
        self.smoothing_fwhm = smoothing_fwhm
        if isinstance(memory, _basestring):
            self.memory = Memory(memory)
        else:
            self.memory = memory
        self.memory_level = memory_level
        self.standardize = standardize
        if signal_scaling in [0, 1, (0, 1)]:
            self.scaling_axis = signal_scaling
            self.signal_scaling = True
            self.standardize = False
        elif signal_scaling is False:
            self.signal_scaling = signal_scaling
        else:
            raise ValueError('signal_scaling must be "False", "0", "1"'
                             ' or "(0, 1)"')
        self.noise_model = noise_model
        self.verbose = verbose
        self.n_jobs = n_jobs
        self.minimize_memory = minimize_memory
        # attributes
        self.labels_ = None
        self.results_ = None

    def fit(self, run_imgs, paradigms=None, confounds=None,
            design_matrices=None):
        """ Fit the GLM

        For each run:
        1. create design matrix X
        2. do a masker job: fMRI_data -> Y
        3. fit regression to (Y, X)

        Parameters
        ----------
        run_imgs: Niimg-like object or list of Niimg-like objects,
            See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
            Data on which the GLM will be fitted. If this is a list,
            the affine is considered the same for all.

        paradigms: pandas Dataframe or string or list of pandas DataFrames or
                   strings,
            fMRI paradigms used to build design matrices. One paradigm expected
            per run_img. Ignored in case designs is not None.

        confounds: pandas Dataframe or string or list of pandas DataFrames or
                   strings,
            Each column in a DataFrame corresponds to a confound variable
            to be included in the regression model of the respective run_img.
            The number of rows must match the number of volumes in the
            respective run_img. Ignored in case designs is not None.

        design_matrices: pandas DataFrame or list of pandas DataFrames,
            Design matrices that will be used to fit the GLM.
        """
        # Check arguments
        # Check imgs type
        if not isinstance(run_imgs, (list, tuple)):
            run_imgs = [run_imgs]
        for rimg in run_imgs:
            if not isinstance(rimg, (_basestring, Nifti1Image)):
                raise ValueError('run_imgs must be Niimg-like object or list'
                                 ' of Niimg-like objects')
        # check all information necessary to build design matrices is available
        if design_matrices is None:
            if paradigms is None:
                raise ValueError('paradigms or design matrices must be provided')
            if self.t_r is None:
                raise ValueError('t_r not given to FirstLevelModel object'
                                 ' to compute design from paradigm')
        else:
            design_matrices = _check_run_tables(run_imgs, design_matrices,
                                                'design_matrices')
        # check the number of paradigm and confound files match number of runs
        # Also check paradigm and confound files can be loaded as DataFrame
        if paradigms is not None:
            paradigms = _check_run_tables(run_imgs, paradigms, 'paradigms')

        if confounds is not None:
            confounds = _check_run_tables(run_imgs, confounds, 'confounds')

        # Learn the mask
        if not isinstance(self.mask, NiftiMasker):
            self.masker_ = NiftiMasker(
                mask_img=self.mask, smoothing_fwhm=self.smoothing_fwhm,
                target_affine=self.target_affine,
                standardize=self.standardize, mask_strategy='epi',
                t_r=self.t_r, memory=self.memory,
                verbose=max(0, self.verbose - 1),
                target_shape=self.target_shape,
                memory_level=self.memory_level)
        else:
            self.masker_ = clone(self.mask)
            for param_name in ['target_affine', 'target_shape',
                               'smoothing_fwhm', 'low_pass', 'high_pass',
                               't_r', 'memory', 'memory_level']:
                our_param = getattr(self, param_name)
                if our_param is None:
                    continue
                if getattr(self.masker_, param_name) is not None:
                    warn('Parameter %s of the masker overriden' % param_name)
                setattr(self.masker_, param_name, our_param)
        self.masker_.fit(run_imgs[0])

        # For each run fit the model and keep only the regression results.
        self.labels_, self.results_, self.design_matrices_ = [], [], []
        n_runs = len(run_imgs)
        t0 = time.time()
        for run_idx, run_img in enumerate(run_imgs):
            # Report progress
            if self.verbose > 0:
                percent = float(run_idx) / n_runs
                percent = round(percent * 100, 2)
                dt = time.time() - t0
                # We use a max to avoid a division by zero
                if run_idx == 0:
                    remaining = 'go take a coffee, a big one'
                else:
                    remaining = (100. - percent) / max(0.01, percent) * dt
                    remaining = '%i seconds remaining' % remaining
                sys.stderr.write(" " * 100 + "\r")
                sys.stderr.write(
                    "Computing run %d out of %d runs (%s)\r"
                    % (run_idx, n_runs, remaining))

            # Build the experimental design for the glm
            run_img = check_niimg(run_img, ensure_ndim=4)
            if design_matrices is None:
                n_scans = run_img.get_data().shape[3]
                if confounds is not None:
                    confounds_matrix = confounds[run_idx].values
                    if confounds_matrix.shape[0] != n_scans:
                        raise ValueError('Rows in confounds does not match'
                                         'n_scans in run_img at index %d'
                                         % (run_idx,))
                    confounds_names = confounds[run_idx].columns
                else:
                    confounds_matrix = None
                    confounds_names = None
                start_time = self.slice_time_ref * self.t_r
                end_time = (n_scans - 1 + self.slice_time_ref) * self.t_r
                frame_times = np.linspace(start_time, end_time, n_scans)
                design = make_design_matrix(frame_times, paradigms[run_idx],
                                            self.hrf_model, self.drift_model,
                                            self.period_cut, self.drift_order,
                                            self.fir_delays, confounds_matrix,
                                            confounds_names, self.min_onset)
            else:
                design = design_matrices[run_idx]
            self.design_matrices_.append(design)

            # Compute GLM
            Y = self.masker_.transform(run_img)
            if self.signal_scaling:
                Y, _ = mean_scaling(Y, self.scaling_axis)
            if self.memory is not None:
                mem_glm = self.memory.cache(run_glm)
            else:
                mem_glm = run_glm
            labels, results = mem_glm(Y, design,
                                      noise_model=self.noise_model,
                                      bins=100, n_jobs=self.n_jobs)
            self.labels_.append(labels)
            # We save memory if inspecting model details is not necessary
            if self.minimize_memory:
                for key in results:
                    results[key] = SimpleRegressionResults(results[key])
            self.results_.append(results)
            del Y

        # Report progress
        if self.verbose > 0:
            sys.stderr.write("\nComputation of %d runs done in %i seconds\n"
                             % (n_runs, time.time() - t0))

        return self

    def compute_contrast(self, contrast_def, contrast_name=None,
                         stat_type=None, output_type='z_score'):
        """Generate different outputs corresponding to
        the contrasts provided e.g. z_map, t_map, effects and variance.
        In multi-session case, outputs the fixed effects map.

        Parameters
        ----------
        contrast_def : array or list of arrays of shape (n_col) or (n_run, n_col)
            where ``n_col`` is the number of columns of the design matrix,
            (one array per run). If only one array is provided when there
            are several runs, it will be assumed that the same contrast is
            desired for all runs

        contrast_name : str, optional
            name of the contrast

        stat_type : {'t', 'F'}, optional
            type of the contrast

        output_type : str, optional
            Type of the output map. Can be 'z_score', 'stat', 'p_value',
            'effect_size' or 'effect_variance'

        Returns
        -------
        output_image : Nifti1Image
            The desired output image

        """
        if self.labels_ is None or self.results_ is None:
            raise ValueError('The model has not been fit yet')

        if isinstance(contrast_def, np.ndarray):
            con_vals = [contrast_def]
        elif isinstance(contrast_def, (list, tuple)):
            con_vals = contrast_def
            for cidx, con in enumerate(contrast_def):
                if not isinstance(con, np.ndarray):
                    raise ValueError('contrast_def at index %i is not an'
                                     ' array' % cidx)
        else:
            raise ValueError('contrast_def must be an array or list of arrays')
        n_runs = len(self.labels_)
        if len(con_vals) != n_runs:
            warn('One contrast given, assuming it for all %d runs' % n_runs)
            con_vals = con_vals * n_runs
        if isinstance(output_type, _basestring):
            if output_type not in ['z_score', 'stat', 'p_value', 'effect_size',
                                   'effect_variance']:
                raise ValueError('output_type must be one of "z_score", "stat",'
                                 ' "p_value","effect_size" or "effect_variance"')
        else:
            raise ValueError('output_type must be one of "z_score", "stat",'
                             ' "p_value","effect_size" or "effect_variance"')

        if self.memory is not None:
            arg_ignore = ['labels', 'results']
            mem_contrast = self.memory.cache(_fixed_effect_contrast,
                                             ignore=arg_ignore)
        else:
            mem_contrast = _fixed_effect_contrast
        contrast = mem_contrast(self.labels_, self.results_, con_vals,
                                stat_type)

        estimate_ = getattr(contrast, output_type)()
        # Prepare the returned images
        output = self.masker_.inverse_transform(estimate_)
        if contrast_name is None:
            contrast_name = str(con_vals)
        output.get_header()['descrip'] = (
            '%s of contrast %s' % (output_type, contrast_name))
        return output
Beispiel #53
0
X_task, labels = joblib.load('preload_HT_3mm')

labels = np.int32(labels)

# contrasts are IN ORDER -> shuffle!
new_inds = np.arange(0, X_task.shape[0])
np.random.shuffle(new_inds)
X_task = X_task[new_inds]
labels = labels[new_inds]
# subs = subs[new_inds]

X_task = StandardScaler().fit_transform(X_task)

# ARCHI task
AT_niis, AT_labels, AT_subs = joblib.load('preload_AT_3mm')
AT_X = nifti_masker.transform(AT_niis)
AT_X = StandardScaler().fit_transform(AT_X)
print('done :)')

##############################################################################
# define computation graph
##############################################################################

class SSEncoder(BaseEstimator):
    def __init__(self, gain1, learning_rate, max_epochs=100,
                 l1=0.1, l2=0.1):
        """
        Parameters
        ----------
        lambda : float
            Mediates between AE and LR. lambda==1 equates with LR only.