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

[ENH] Allow pandas.Series as valid input for second_level_input #4070

Merged
merged 5 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
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
6 changes: 4 additions & 2 deletions nilearn/_utils/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,8 +795,10 @@ def custom_function(vertices):
"second_level_input"
] = """
second_level_input : :obj:`list` of \
:class:`~nilearn.glm.first_level.FirstLevelModel` objects \
or :class:`pandas.DataFrame` or :obj:`list` of Niimg-like objects.
:class:`~nilearn.glm.first_level.FirstLevelModel` objects or \
:class:`pandas.DataFrame` or \
:obj:`list` of Niimg-like objects or \
:obj:`pandas.Series` of Niimg-like objects.

- Giving :class:`~nilearn.glm.first_level.FirstLevelModel` objects
will allow to easily compute the second level contrast of arbitrary first
Expand Down
6 changes: 6 additions & 0 deletions nilearn/glm/second_level/second_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ def _check_input_type(second_level_input):
"""Determine the type of input provided."""
if isinstance(second_level_input, pd.DataFrame):
return "df_object"
if isinstance(second_level_input, pd.Series):
return "pd_series"
if isinstance(second_level_input, (str, Nifti1Image)):
return "nii_object"
if isinstance(second_level_input, list):
Expand All @@ -56,6 +58,7 @@ def _check_input_type(second_level_input):
"second_level_input must be "
"either a pandas DataFrame, "
"a Niimg-like object, "
"a pandas Series of Niimg-like object, "
"a list of Niimg-like object or "
"a list of FirstLevelModel objects. "
f"Got {_return_type(second_level_input)} instead"
Expand Down Expand Up @@ -105,6 +108,9 @@ def _check_input_as_type(
):
if input_type == "flm_object":
_check_input_as_first_level_model(second_level_input, none_confounds)
elif input_type == "pd_series":
second_level_input = second_level_input.to_list()
_check_input_as_nifti_images(second_level_input, none_design_matrix)
elif input_type == "nii_object":
_check_input_as_nifti_images(second_level_input, none_design_matrix)
else:
Expand Down
20 changes: 20 additions & 0 deletions nilearn/glm/tests/test_second_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,26 @@ def test_fmri_inputs(tmp_path, rng):
SecondLevelModel().fit(niimg_4d, None, sdes)


def test_fmri_pand_series_as_inputs(tmp_path, rng):
Remi-Gau marked this conversation as resolved.
Show resolved Hide resolved
# prepare correct input dataframe and lists
p, q = 80, 10
X = rng.standard_normal(size=(p, q))
shapes = (SHAPE,)
_, FUNCFILE, _ = write_fake_fmri_data_and_design(
shapes, file_path=tmp_path
)
FUNCFILE = FUNCFILE[0]

# dataframes as input
sdes = pd.DataFrame(X[:3, :3], columns=["intercept", "b", "c"])
niidf = pd.DataFrame({"filepaths": [FUNCFILE, FUNCFILE, FUNCFILE]})
SecondLevelModel().fit(
second_level_input=niidf["filepaths"],
confounds=None,
design_matrix=sdes,
)


def test_fmri_inputs_errors(tmp_path):
# Test processing of FMRI inputs
# prepare fake data
Expand Down