Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] Refactor design matrix and contrast formula for the two-sample T-test example #4407

Merged
merged 16 commits into from
May 27, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 17 additions & 11 deletions examples/05_glm_second_level/plot_second_level_two_sample_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,30 @@
second_level_input = sample_vertical["cmaps"] + sample_horizontal["cmaps"]

# %%
# Next, we model the effect of conditions (sample 1 vs sample 2).
# Next, we assign the subjects for vertical and horizontal checkerboard respectively.
import numpy as np

condition_effect = np.hstack(([1] * n_subjects, [-1] * n_subjects))
vertical_subjects = np.hstack(([1] * n_subjects, [0] * n_subjects))
horizontal_subjects = np.hstack(([0] * n_subjects, [1] * n_subjects))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I should have been clearer, but when you do this you make the design matrix rank deficient: the sum of these two regressors, is equal to the some of all the subject regressors.
This means that the design matrix is no longer invertible, and some contrasts are not estimable. Normally, you should get a warning when you run that code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for that mistake for the paired design matrix.
Now I have modified the paired design matrix as follows:

$$\begin{bmatrix} 1 & 1 & 0 & \cdots & 0\\\ 1 & 0 & 1 & \cdots & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots\\\ 1 & 0 & 0 & \cdots & 1\\\ 0 & 1 & 0 & \cdots & 0\\\ 0 & 0 & 1 & \cdots & 0\\\ \vdots & \vdots & \vdots & \ddots & \vdots\\\ 0 & 0 & 0 & \cdots & 1 \end{bmatrix}$$

which rank is 17.

The unpaired design matrix is now added a intercept column as follows:

$$\begin{bmatrix} 1 & 1 \\\ 1 & 1 \\\ 1 & 1 \\\ \vdots & \vdots \\\ 0 & 1 \\\ 0 & 1 \\\ 0 & 1 \end{bmatrix}$$

Its rank is 2 which is a full column rank matrix.


# %%
# The design matrix for the unpaired test doesn't need any more columns
# The design matrix for the unpaired test doesn't need any more columns,
# as this would cause the design matrix rank-deficient.
# For the paired test, we include an intercept for each subject.
subject_effect = np.vstack((np.eye(n_subjects), np.eye(n_subjects)))
subjects = [f"S{i:02d}" for i in range(1, n_subjects + 1)]

# %%
# We then assemble those into design matrices
unpaired_design_matrix = pd.DataFrame(
condition_effect[:, np.newaxis], columns=["vertical vs horizontal"]
unpaired_design_matrix = pd.DataFrame({
Remi-Gau marked this conversation as resolved.
Show resolved Hide resolved
"vertical": vertical_subjects,
"horizontal": horizontal_subjects,
}
)

paired_design_matrix = pd.DataFrame(
np.hstack((condition_effect[:, np.newaxis], subject_effect)),
columns=["vertical vs horizontal"] + subjects,
np.hstack((vertical_subjects[:, np.newaxis], horizontal_subjects[:, np.newaxis], subject_effect)),
columns=["vertical"] + ["horizontal"] + subjects,
)

# %%
Expand Down Expand Up @@ -111,16 +115,18 @@
)

# %%
# Estimating the :term:`contrast` is simple. To do so, we provide the column
# name of the design matrix. The argument 'output_type' is set to return all
# Estimating the :term:`contrast` is simple. To do so, we provide a string of formula
# with the column name of the design matrix. In the case of estimating the vertical vs horizontal,
# we can use the following formula: "vertical - horizontal".
# The argument 'output_type' is set to return all
# available outputs so that we can compare differences in the effect size,
# variance, and z-score.
stat_maps_unpaired = second_level_model_unpaired.compute_contrast(
"vertical vs horizontal", output_type="all"
"vertical - horizontal", output_type="all"
)

stat_maps_paired = second_level_model_paired.compute_contrast(
"vertical vs horizontal", output_type="all"
"vertical - horizontal", output_type="all"
)

# %%
Expand Down