Skip to content

Commit

Permalink
[FIX] ensure that dataframes can be used as input for second level GL…
Browse files Browse the repository at this point in the history
…M (estimation and contrast) (#3879)

* regression test and fix

* Apply suggestions from code review

* update chngelog

* fix

* rm test files

* Apply suggestions from code review

Co-authored-by: Yasmin <63292494+ymzayek@users.noreply.github.com>

* use write_fake_bold_img

---------

Co-authored-by: Yasmin <63292494+ymzayek@users.noreply.github.com>
  • Loading branch information
Remi-Gau and ymzayek committed Aug 7, 2023
1 parent af36c18 commit 960de1e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 9 deletions.
2 changes: 2 additions & 0 deletions doc/changes/latest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Fixes

- Fix bug that would prevent loading the confounds of a gifti file in actual fmriprep datasets (:gh:`3819` by `Rémi Gau`_).

- Fix bug that prevented using dataframes as input for second level GLM when computing contrasts (:gh:`3879` by `Rémi Gau`_).

- Fix bug in :func:`~glm.first_level.first_level_from_bids` that returned no confound files if the corresponding bold files contained derivatives BIDS entities (:gh:`3742` by `Rémi Gau`_).

- Fix bug in :func:`~glm.first_level.first_level_from_bids` that would throw a warning about ``slice_time_ref`` not being provided even when it was (:gh:`3811` by `Rémi Gau`_).
Expand Down
20 changes: 11 additions & 9 deletions nilearn/glm/second_level/second_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,17 @@ def _check_confounds(confounds):


def _check_first_level_contrast(second_level_input, first_level_contrast):
if isinstance(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"
)
if (
isinstance(second_level_input, list)
and isinstance(second_level_input[0], FirstLevelModel)
and 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."
)


def _check_output_type(output_type, valid_types):
Expand Down
23 changes: 23 additions & 0 deletions nilearn/glm/tests/test_second_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from nilearn._utils import testing
from nilearn._utils.data_gen import (
generate_fake_fmri_data_and_design,
write_fake_bold_img,
write_fake_fmri_data_and_design,
)
from nilearn.glm.first_level import FirstLevelModel, run_glm
Expand Down Expand Up @@ -1178,3 +1179,25 @@ def test_second_level_contrast_computation_with_memory_caching():
# Delete objects attached to files to avoid WindowsError when deleting
# temporary directory (in Windows)
del func_img, model, X, Y


def test_second_lvl_dataframe_computation(tmp_path):
"""Check that contrast can be computed when using dataframes as input.
See bug https://github.com/nilearn/nilearn/issues/3871
"""
shape = (7, 8, 9, 1)
file_path = write_fake_bold_img(
file_path=tmp_path / "img.nii.gz", shape=shape
)

dfcols = ["subject_label", "map_name", "effects_map_path"]
dfrows = [
["01", "a", file_path],
["02", "a", file_path],
["03", "a", file_path],
]
niidf = pd.DataFrame(dfrows, columns=dfcols)

model = SecondLevelModel().fit(niidf)
model.compute_contrast(first_level_contrast="a")

0 comments on commit 960de1e

Please sign in to comment.