8.6.7. Massively univariate analysis of face vs house recognition¶

A permuted Ordinary Least Squares algorithm is run at each voxel in order to detemine whether or not it behaves differently under a “face viewing” condition and a “house viewing” condition. We consider the mean image per session and per condition. Otherwise, the observations cannot be exchanged at random because a time dependance exists between observations within a same session (see [1] for more detailed explanations).

The example shows the small differences that exist between Bonferroni-corrected p-values and family-wise corrected p-values obtained from a permutation test combined with a max-type procedure [2]. Bonferroni correction is a bit conservative, as revealed by the presence of a few false negative.

8.6.7.1. References¶

[1] Winkler, A. M. et al. (2014).

Permutation inference for the general linear model. Neuroimage.

[2] Anderson, M. J. & Robinson, J. (2001).

Permutation tests for linear models. Australian & New Zealand Journal of Statistics, 43(1), 75-88. (http://avesbiodiv.mncn.csic.es/estadistica/permut2.pdf)

```# Author: Virgile Fritsch, <virgile.fritsch@inria.fr>, Feb. 2014
```

```from nilearn import datasets
haxby_dataset = datasets.fetch_haxby(subjects=[2])

# print basic information on the dataset
print('Functional nifti image (4D) is located at: %s' % haxby_dataset.func[0])
```

Out:

```Mask nifti image (3D) is located at: /home/emdupre/nilearn_data/haxby2001/mask.nii.gz
Functional nifti image (4D) is located at: /home/emdupre/nilearn_data/haxby2001/subj2/bold.nii.gz
```

```mask_filename = haxby_dataset.mask
smoothing_fwhm=8,
memory='nilearn_cache', memory_level=1)  # cache options
func_filename = haxby_dataset.func[0]
```

Restrict to faces and houses

```import numpy as np
import pandas as pd
conditions = labels['labels']
categories = conditions.unique()
conditions_encoded = np.zeros_like(conditions)
for c, category in enumerate(categories):
conditions_encoded[conditions == category] = c
sessions = labels['chunks']

# We consider the mean image per session and per condition.
# Otherwise, the observations cannot be exchanged at random because
# a time dependence exists between observations within a same session.
n_sessions = np.unique(sessions).size
grouped_fmri_masked = np.empty((2 * n_sessions,  # two conditions per session
grouped_conditions_encoded = np.empty((2 * n_sessions, 1))

for s in range(n_sessions):
grouped_conditions_encoded[2 * s] = conditions_encoded[
grouped_conditions_encoded[2 * s + 1] = conditions_encoded[
```

Perform massively univariate analysis with permuted OLS

We use a two-sided t-test to compute p-values, but we keep trace of the effect sign to add it back at the end and thus observe the signed effect

```from nilearn.mass_univariate import permuted_ols
neg_log_pvals, t_scores_original_data, _ = permuted_ols(
# + intercept as a covariate by default
n_perm=10000, two_sided_test=True,
n_jobs=1)  # can be changed to use more CPUs
signed_neg_log_pvals = neg_log_pvals * np.sign(t_scores_original_data)
signed_neg_log_pvals)
```

scikit-learn F-scores for comparison

F-test does not allow to observe the effect sign (pure two-sided test)

```from sklearn.feature_selection import f_regression
_, pvals_bonferroni = f_regression(
grouped_conditions_encoded)  # f_regression implicitly adds intercept
pvals_bonferroni[np.isnan(pvals_bonferroni)] = 1
pvals_bonferroni[pvals_bonferroni > 1] = 1
neg_log_pvals_bonferroni = -np.log10(pvals_bonferroni)
neg_log_pvals_bonferroni)
```

Out:

```/home/emdupre/miniconda3/envs/nilearn/lib/python3.7/site-packages/sklearn/utils/validation.py:760: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
y = column_or_1d(y, warn=True)
```

Visualization

```import matplotlib.pyplot as plt
from nilearn.plotting import plot_stat_map, show

# Use the fmri mean image as a surrogate of anatomical data
from nilearn import image
from nilearn.image import get_data

mean_fmri_img = image.mean_img(func_filename)

threshold = -np.log10(0.1)  # 10% corrected

vmax = min(signed_neg_log_pvals.max(),
neg_log_pvals_bonferroni.max())

# Plot thresholded p-values map corresponding to F-scores
threshold=threshold, cmap=plt.cm.RdBu_r,
display_mode='z', cut_coords=[-1, ],
vmax=vmax)

n_detections = (neg_log_pvals_bonferroni_data > threshold).sum()
title = ('Negative \$\log_{10}\$ p-values'
'\n(Parametric two-sided F-test'
'\n+ Bonferroni correction)'
'\n%d detections') % n_detections

display.title(title, y=1.1)

# Plot permutation p-values map
threshold=threshold, cmap=plt.cm.RdBu_r,
display_mode='z', cut_coords=[-1, ],
vmax=vmax)

n_detections = (np.abs(signed_neg_log_pvals) > threshold).sum()
title = ('Negative \$\log_{10}\$ p-values'
'\n(Non-parametric two-sided test'
'\n+ max-type correction)'
'\n%d detections') % n_detections

display.title(title, y=1.1)

show()
```

Out:

```/home/emdupre/Desktop/open_source/nilearn/nilearn/plotting/displays.py:1596: MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance.  In a future version, a new instance will always be created and returned.  Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.
fraction * (x1 - x0), y1 - y0])
```

Total running time of the script: ( 0 minutes 33.734 seconds)

Gallery generated by Sphinx-Gallery