def test_process_second_level_input_as_firstlevelmodels(): """Unit tests for function _process_second_level_input_as_firstlevelmodels(). """ from nilearn.glm.second_level.second_level import _process_second_level_input_as_firstlevelmodels # noqa shapes, rk = [(7, 8, 9, 15)], 3 mask, fmri_data, design_matrices = \ generate_fake_fmri_data_and_design(shapes, rk) list_of_flm = [ FirstLevelModel(mask_img=mask, subject_label=f"sub-{i}").fit( fmri_data[0], design_matrices=design_matrices[0]) for i in range(3) ] sample_map, subjects_label =\ _process_second_level_input_as_firstlevelmodels(list_of_flm) assert subjects_label == [f"sub-{i}" for i in range(3)] assert isinstance(sample_map, Nifti1Image) assert sample_map.shape == (7, 8, 9)
def test_compute_contrast_num_contrasts(): shapes, rk = ((7, 8, 7, 15), (7, 8, 7, 19), (7, 8, 7, 13)), 3 mask, fmri_data, design_matrices =\ generate_fake_fmri_data_and_design(shapes, rk) # Fit a glm with 3 sessions and design matrices multi_session_model = FirstLevelModel(mask_img=mask).fit( fmri_data, design_matrices=design_matrices) # raise when n_contrast != n_runs | 1 with pytest.raises(ValueError): multi_session_model.compute_contrast([np.eye(rk)[1]] * 2) multi_session_model.compute_contrast([np.eye(rk)[1]] * 3) with pytest.warns(UserWarning, match='One contrast given, ' 'assuming it for all 3 runs'): multi_session_model.compute_contrast([np.eye(rk)[1]])
def test_high_level_glm_one_session(): shapes, rk = [(7, 8, 9, 15)], 3 mask, fmri_data, design_matrices = generate_fake_fmri_data_and_design(shapes, rk) # Give an unfitted NiftiMasker as mask_img and check that we get an error masker = NiftiMasker(mask) with pytest.raises(ValueError, match="It seems that NiftiMasker has not been fitted."): single_session_model = FirstLevelModel(mask_img=masker).fit( fmri_data[0], design_matrices=design_matrices[0]) # Give a fitted NiftiMasker with a None mask_img_ attribute # and check that the masker parameters are overriden by the # FirstLevelModel parameters masker.fit() masker.mask_img_ = None with pytest.warns(UserWarning, match="Parameter memory of the masker overriden"): single_session_model = FirstLevelModel(mask_img=masker).fit( fmri_data[0], design_matrices=design_matrices[0]) # Give a fitted NiftiMasker masker = NiftiMasker(mask) masker.fit() single_session_model = FirstLevelModel(mask_img=masker).fit( fmri_data[0], design_matrices=design_matrices[0]) assert single_session_model.masker_ == masker # Call with verbose (improve coverage) single_session_model = FirstLevelModel(mask_img=None, verbose=1).fit( fmri_data[0], design_matrices=design_matrices[0]) single_session_model = FirstLevelModel(mask_img=None).fit( fmri_data[0], design_matrices=design_matrices[0]) assert isinstance(single_session_model.masker_.mask_img_, Nifti1Image) single_session_model = FirstLevelModel(mask_img=mask).fit( fmri_data[0], design_matrices=design_matrices[0]) z1 = single_session_model.compute_contrast(np.eye(rk)[:1]) assert isinstance(z1, Nifti1Image)
def test_first_level_hrf_model(hrf_model, spaces): """ Ensure that FirstLevelModel runs without raising errors for different values of hrf_model. In particular, one checks that it runs without raising errors when given a custom response function. Also ensure that it computes contrasts without raising errors, even when event (ie condition) names have spaces. """ shapes, rk = [(10, 10, 10, 25)], 3 mask, fmri_data, _ =\ generate_fake_fmri_data_and_design(shapes, rk) events = basic_paradigm(condition_names_have_spaces=spaces) model = FirstLevelModel(t_r=2.0, mask_img=mask, hrf_model=hrf_model) model.fit(fmri_data, events) columns = model.design_matrices_[0].columns model.compute_contrast(f"{columns[0]}-{columns[1]}")
def test_high_level_glm_different_design_matrices_formulas(): # test that one can estimate a contrast when design matrices are different shapes, rk = ((7, 8, 7, 15), (7, 8, 7, 19)), 3 mask, fmri_data, design_matrices = generate_fake_fmri_data_and_design(shapes, rk) # make column names identical design_matrices[1].columns = design_matrices[0].columns # add a column to the second design matrix design_matrices[1]['new'] = np.ones((19, 1)) # Fit a glm with two sessions and design matrices multi_session_model = FirstLevelModel(mask_img=mask).fit( fmri_data, design_matrices=design_matrices) # Compute contrast with formulas cols_formula = tuple(design_matrices[0].columns[:2]) formula = "%s-%s" % cols_formula with pytest.warns(UserWarning, match='One contrast given, assuming it for all 2 runs'): z_joint_formula = multi_session_model.compute_contrast( formula, output_type='effect_size')
def test_second_level_voxelwise_attribute_errors(attribute): """Tests that an error is raised when trying to access voxelwise attributes before fitting the model, before computing a contrast, and when not setting ``minimize_memory`` to ``True``. """ shapes = ((7, 8, 9, 1), ) mask, fmri_data, _ = generate_fake_fmri_data_and_design(shapes) model = SecondLevelModel(mask_img=mask, minimize_memory=False) with pytest.raises(ValueError, match="The model has no results."): getattr(model, attribute) Y = fmri_data * 4 X = pd.DataFrame([[1]] * 4, columns=['intercept']) model.fit(Y, design_matrix=X) with pytest.raises(ValueError, match="The model has no results."): getattr(model, attribute) with pytest.raises(ValueError, match="attribute must be one of"): model._get_voxelwise_model_attribute("foo", True) model = SecondLevelModel(mask_img=mask, minimize_memory=True) model.fit(Y, design_matrix=X) model.compute_contrast() with pytest.raises(ValueError, match="To access voxelwise attributes"): getattr(model, attribute)
def test_high_level_glm_different_design_matrices(): # test that one can estimate a contrast when design matrices are different shapes, rk = ((7, 8, 7, 15), (7, 8, 7, 19)), 3 mask, fmri_data, design_matrices = generate_fake_fmri_data_and_design( shapes, rk) # add a column to the second design matrix design_matrices[1]['new'] = np.ones((19, 1)) # Fit a glm with two sessions and design matrices multi_session_model = FirstLevelModel(mask_img=mask).fit( fmri_data, design_matrices=design_matrices) z_joint = multi_session_model.compute_contrast( [np.eye(rk)[:1], np.eye(rk + 1)[:1]], output_type='effect_size') assert z_joint.shape == (7, 8, 7) # compare the estimated effects to seprarately-fitted models model1 = FirstLevelModel(mask_img=mask).fit( fmri_data[0], design_matrices=design_matrices[0]) z1 = model1.compute_contrast(np.eye(rk)[:1], output_type='effect_size') model2 = FirstLevelModel(mask_img=mask).fit( fmri_data[1], design_matrices=design_matrices[1]) z2 = model2.compute_contrast(np.eye(rk + 1)[:1], output_type='effect_size') assert_almost_equal(z1.get_data() + z2.get_data(), 2 * z_joint.get_data())
def test_first_level_predictions_r_square(): shapes, rk = [(10, 10, 10, 25)], 3 mask, fmri_data, design_matrices = generate_fake_fmri_data_and_design(shapes, rk) for i in range(len(design_matrices)): design_matrices[i].iloc[:, 0] = 1 model = FirstLevelModel(mask_img=mask, signal_scaling=False, minimize_memory=False, noise_model='ols') model.fit(fmri_data, design_matrices=design_matrices) pred = model.predicted[0] data = fmri_data[0] r_square_3d = model.r_square[0] y_predicted = model.masker_.transform(pred) y_measured = model.masker_.transform(data) assert_almost_equal(np.mean(y_predicted - y_measured), 0) r_square_2d = model.masker_.transform(r_square_3d) assert_array_less(0., r_square_2d)
def test_check_second_level_input(): from nilearn.glm.second_level.second_level import _check_second_level_input with pytest.raises(ValueError, match="A second level model requires a list with at " "least two first level models or niimgs"): _check_second_level_input([FirstLevelModel()], pd.DataFrame()) with pytest.raises(ValueError, match="Model sub_1 at index 0 has not been fit yet"): _check_second_level_input([ FirstLevelModel(subject_label="sub_{}".format(i)) for i in range(1, 3) ], pd.DataFrame()) with InTemporaryDirectory(): shapes, rk = [(7, 8, 9, 15)], 3 mask, fmri_data, design_matrices = \ generate_fake_fmri_data_and_design(shapes, rk) input_models = [ FirstLevelModel(mask_img=mask).fit( fmri_data[0], design_matrices=design_matrices[0]) ] obj = lambda: None obj.results_ = "foo" obj.labels_ = "bar" with pytest.raises(ValueError, match=" object at idx 1 is <class 'function'> " "instead of FirstLevelModel object"): _check_second_level_input(input_models + [obj], pd.DataFrame()) with pytest.raises(ValueError, match="In case confounds are provided, first level " "objects need to provide the attribute " "subject_label"): _check_second_level_input(input_models * 2, pd.DataFrame(), confounds=pd.DataFrame()) with pytest.raises(ValueError, match="List of niimgs as second_level_input " "require a design matrix to be provided"): _check_second_level_input(fmri_data * 2, None) _check_second_level_input(fmri_data[0], pd.DataFrame()) with pytest.raises(ValueError, match=" object at idx 1 is <class 'int'> instead"): _check_second_level_input(["foo", 1], pd.DataFrame()) with pytest.raises(ValueError, match="second_level_input DataFrame must have columns " "subject_label, map_name and effects_map_path"): _check_second_level_input(pd.DataFrame(columns=["foo", "bar"]), pd.DataFrame()) with pytest.raises(ValueError, match="subject_label column must contain only strings"): _check_second_level_input( pd.DataFrame({ "subject_label": [1, 2], "map_name": ["a", "b"], "effects_map_path": ["c", "d"] }), pd.DataFrame()) with pytest.raises(ValueError, match="List of niimgs as second_level_input " "require a design matrix to be provided"): _check_second_level_input("foo", None) with pytest.raises(ValueError, match="second_level_input must be a list of"): _check_second_level_input(1, None) with pytest.raises(ValueError, match="second_level_input must be a list"): _check_second_level_input(1, None, flm_object=False)