def test_z_score_opposite_contrast(): fmri, mask = generate_fake_fmri(shape=(50, 20, 50), length=96, rand_gen=np.random.RandomState(42)) nifti_masker = NiftiMasker(mask_img=mask) data = nifti_masker.fit_transform(fmri) frametimes = np.linspace(0, (96 - 1) * 2, 96) for i in [0, 20]: design_matrix = make_first_level_design_matrix( frametimes, hrf_model='spm', add_regs=np.array(data[:, i]).reshape(-1, 1)) c1 = np.array([1] + [0] * (design_matrix.shape[1] - 1)) c2 = np.array([0] + [1] + [0] * (design_matrix.shape[1] - 2)) contrasts = {'seed1 - seed2': c1 - c2, 'seed2 - seed1': c2 - c1} fmri_glm = FirstLevelModel(t_r=2., noise_model='ar1', standardize=False, hrf_model='spm', drift_model='cosine') fmri_glm.fit(fmri, design_matrices=design_matrix) z_map_seed1_vs_seed2 = fmri_glm.compute_contrast( contrasts['seed1 - seed2'], output_type='z_score') z_map_seed2_vs_seed1 = fmri_glm.compute_contrast( contrasts['seed2 - seed1'], output_type='z_score') assert_almost_equal(z_map_seed1_vs_seed2.get_data().min(), -z_map_seed2_vs_seed1.get_data().max(), decimal=10) assert_almost_equal(z_map_seed1_vs_seed2.get_data().max(), -z_map_seed2_vs_seed1.get_data().min(), decimal=10)
def test_first_level_residuals(): shapes, rk = [(10, 10, 10, 100)], 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 # Check that voxelwise model attributes cannot be # accessed if minimize_memory is set to True model = FirstLevelModel(mask_img=mask, minimize_memory=True, noise_model='ols') model.fit(fmri_data, design_matrices=design_matrices) with pytest.raises(ValueError, match="To access voxelwise attributes"): residuals = model.residuals[0] model = FirstLevelModel(mask_img=mask, minimize_memory=False, noise_model='ols') # Check that trying to access residuals without fitting # raises an error with pytest.raises(ValueError, match="The model has not been fit yet"): residuals = model.residuals[0] model.fit(fmri_data, design_matrices=design_matrices) # For coverage with pytest.raises(ValueError, match="attribute must be one of"): model._get_voxelwise_model_attribute("foo", True) residuals = model.residuals[0] mean_residuals = model.masker_.transform(residuals).mean(0) assert_array_almost_equal(mean_residuals, 0)
def test_first_level_with_no_signal_scaling(): """ test to ensure that the FirstLevelModel works correctly with a signal_scaling==False. In particular, that derived theta are correct for a constant design matrix with a single valued fmri image """ shapes, rk = [(3, 1, 1, 2)], 1 fmri_data = list() design_matrices = list() design_matrices.append( pd.DataFrame(np.ones((shapes[0][-1], rk)), columns=list('abcdefghijklmnopqrstuvwxyz')[:rk])) # Check error with invalid signal_scaling values with pytest.raises(ValueError, match="signal_scaling must be"): FirstLevelModel(mask_img=False, noise_model='ols', signal_scaling="foo") first_level = FirstLevelModel(mask_img=False, noise_model='ols', signal_scaling=False) fmri_data.append(Nifti1Image(np.zeros((1, 1, 1, 2)) + 6, np.eye(4))) first_level.fit(fmri_data, design_matrices=design_matrices) # trivial test of signal_scaling value assert first_level.signal_scaling is False # assert that our design matrix has one constant assert first_level.design_matrices_[0].equals( pd.DataFrame([1.0, 1.0], columns=['a'])) # assert that we only have one theta as there is only on voxel in our image assert first_level.results_[0][0].theta.shape == (1, 1) # assert that the theta is equal to the one voxel value assert_almost_equal(first_level.results_[0][0].theta[0, 0], 6.0, 2)
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_explicit_fixed_effects(): """ tests the fixed effects performed manually/explicitly""" with InTemporaryDirectory(): shapes, rk = ((7, 8, 7, 15), (7, 8, 7, 16)), 3 mask, fmri_data, design_matrices =\ write_fake_fmri_data_and_design(shapes, rk) contrast = np.eye(rk)[1] # session 1 multi_session_model = FirstLevelModel(mask_img=mask).fit( fmri_data[0], design_matrices=design_matrices[:1]) dic1 = multi_session_model.compute_contrast(contrast, output_type='all') # session 2 multi_session_model.fit(fmri_data[1], design_matrices=design_matrices[1:]) dic2 = multi_session_model.compute_contrast(contrast, output_type='all') # fixed effects model multi_session_model.fit(fmri_data, design_matrices=design_matrices) fixed_fx_dic = multi_session_model.compute_contrast(contrast, output_type='all') # manual version contrasts = [dic1['effect_size'], dic2['effect_size']] variance = [dic1['effect_variance'], dic2['effect_variance']] ( fixed_fx_contrast, fixed_fx_variance, fixed_fx_stat, ) = compute_fixed_effects(contrasts, variance, mask) assert_almost_equal(get_data(fixed_fx_contrast), get_data(fixed_fx_dic['effect_size'])) assert_almost_equal(get_data(fixed_fx_variance), get_data(fixed_fx_dic['effect_variance'])) assert_almost_equal(get_data(fixed_fx_stat), get_data(fixed_fx_dic['stat'])) # test without mask variable ( fixed_fx_contrast, fixed_fx_variance, fixed_fx_stat, ) = compute_fixed_effects(contrasts, variance) assert_almost_equal(get_data(fixed_fx_contrast), get_data(fixed_fx_dic['effect_size'])) assert_almost_equal(get_data(fixed_fx_variance), get_data(fixed_fx_dic['effect_variance'])) assert_almost_equal(get_data(fixed_fx_stat), get_data(fixed_fx_dic['stat'])) # ensure that using unbalanced effects size and variance images # raises an error with pytest.raises(ValueError): compute_fixed_effects(contrasts * 2, variance, mask) del mask, multi_session_model
def test_glm_sample_mask(): """Ensure the sample mask is performing correctly in GLM.""" shapes, rk = [(10, 10, 10, 25)], 3 mask, fmri_data, design_matrix =\ generate_fake_fmri_data_and_design(shapes, rk) model = FirstLevelModel(t_r=2.0, mask_img=mask, minimize_memory=False) sample_mask = np.arange(25)[3:] # censor the first three volumes model.fit(fmri_data, design_matrices=design_matrix, sample_masks=sample_mask) assert model.design_matrices_[0].shape[0] == 22 assert model.predicted[0].shape[-1] == 22
def test_first_level_residuals(): shapes, rk = [(10, 10, 10, 100)], 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, minimize_memory=False, noise_model='ols') model.fit(fmri_data, design_matrices=design_matrices) residuals = model.residuals[0] mean_residuals = model.masker_.transform(residuals).mean(0) assert_array_almost_equal(mean_residuals, 0)
def test_first_level_design_creation(): # Test processing of FMRI inputs with InTemporaryDirectory(): shapes = ((7, 8, 9, 10), ) mask, FUNCFILE, _ = write_fake_fmri_data_and_design(shapes) FUNCFILE = FUNCFILE[0] func_img = load(FUNCFILE) # basic test based on basic_paradigm and glover hrf t_r = 10.0 slice_time_ref = 0. events = basic_paradigm() model = FirstLevelModel(t_r, slice_time_ref, mask_img=mask, drift_model='polynomial', drift_order=3) model = model.fit(func_img, events) frame1, X1, names1 = check_design_matrix(model.design_matrices_[0]) # check design computation is identical n_scans = get_data(func_img).shape[3] start_time = slice_time_ref * t_r end_time = (n_scans - 1 + slice_time_ref) * t_r frame_times = np.linspace(start_time, end_time, n_scans) design = make_first_level_design_matrix(frame_times, events, drift_model='polynomial', drift_order=3) frame2, X2, names2 = check_design_matrix(design) assert_array_equal(frame1, frame2) assert_array_equal(X1, X2) assert_array_equal(names1, names2) # Delete objects attached to files to avoid WindowsError when deleting # temporary directory (in Windows) del FUNCFILE, mask, model, func_img
def test_get_voxelwise_attributes_should_return_as_many_as_design_matrices( shapes): mask, fmri_data, design_matrices =\ generate_fake_fmri_data_and_design(shapes) for i in range(len(design_matrices)): design_matrices[i].iloc[:, 0] = 1 model = FirstLevelModel(mask_img=mask, minimize_memory=False, noise_model='ols') model.fit(fmri_data, design_matrices=design_matrices) # Check that length of outputs is the same as the number of design matrices assert len(model._get_voxelwise_model_attribute("resid", True)) == \ len(shapes)
def report_flm_fiac(): # pragma: no cover data = datasets.func.fetch_fiac_first_level() fmri_img = [data['func1'], data['func2']] from nilearn.image import mean_img mean_img_ = mean_img(fmri_img[0]) design_files = [data['design_matrix1'], data['design_matrix2']] design_matrices = [pd.DataFrame(np.load(df)['X']) for df in design_files] fmri_glm = FirstLevelModel(mask_img=data['mask'], minimize_memory=True) fmri_glm = fmri_glm.fit(fmri_img, design_matrices=design_matrices) n_columns = design_matrices[0].shape[1] contrasts = { 'SStSSp_minus_DStDSp': _pad_vector([1, 0, 0, -1], n_columns), 'DStDSp_minus_SStSSp': _pad_vector([-1, 0, 0, 1], n_columns), 'DSt_minus_SSt': _pad_vector([-1, -1, 1, 1], n_columns), 'DSp_minus_SSp': _pad_vector([-1, 1, -1, 1], n_columns), 'DSt_minus_SSt_for_DSp': _pad_vector([0, -1, 0, 1], n_columns), 'DSp_minus_SSp_for_DSt': _pad_vector([0, 0, -1, 1], n_columns), 'Deactivation': _pad_vector([-1, -1, -1, -1, 4], n_columns), 'Effects_of_interest': np.eye(n_columns)[:5] } report = make_glm_report( fmri_glm, contrasts, bg_img=mean_img_, height_control='fdr', ) output_filename = 'generated_report_flm_fiac.html' output_filepath = os.path.join(REPORTS_DIR, output_filename) report.save_as_html(output_filepath) report.get_iframe()
def test_first_level_contrast_computation(): with InTemporaryDirectory(): shapes = ((7, 8, 9, 10),) mask, FUNCFILE, _ = write_fake_fmri_data_and_design(shapes) FUNCFILE = FUNCFILE[0] func_img = load(FUNCFILE) # basic test based on basic_paradigm and glover hrf t_r = 10.0 slice_time_ref = 0. events = basic_paradigm() # Ordinary Least Squares case model = FirstLevelModel(t_r, slice_time_ref, mask_img=mask, drift_model='polynomial', drift_order=3, minimize_memory=False) c1, c2, cnull = np.eye(7)[0], np.eye(7)[1], np.zeros(7) # asking for contrast before model fit gives error with pytest.raises(ValueError): model.compute_contrast(c1) # fit model model = model.fit([func_img, func_img], [events, events]) # Check that an error is raised for invalid contrast_def with pytest.raises(ValueError, match="contrast_def must be an array or str or list"): model.compute_contrast(37) # smoke test for different contrasts in fixed effects model.compute_contrast([c1, c2]) # smoke test for same contrast in fixed effects model.compute_contrast([c2, c2]) # smoke test for contrast that will be repeated model.compute_contrast(c2) model.compute_contrast(c2, 'F') model.compute_contrast(c2, 't', 'z_score') model.compute_contrast(c2, 't', 'stat') model.compute_contrast(c2, 't', 'p_value') model.compute_contrast(c2, None, 'effect_size') model.compute_contrast(c2, None, 'effect_variance') # formula should work (passing varible name directly) model.compute_contrast('c0') model.compute_contrast('c1') model.compute_contrast('c2') # smoke test for one null contrast in group model.compute_contrast([c2, cnull]) # only passing null contrasts should give back a value error with pytest.raises(ValueError): model.compute_contrast(cnull) with pytest.raises(ValueError): model.compute_contrast([cnull, cnull]) # passing wrong parameters with pytest.raises(ValueError): model.compute_contrast([]) with pytest.raises(ValueError): model.compute_contrast([c1, []]) with pytest.raises(ValueError): model.compute_contrast(c1, '', '') with pytest.raises(ValueError): model.compute_contrast(c1, '', []) # Delete objects attached to files to avoid WindowsError when deleting # temporary directory (in Windows) del func_img, FUNCFILE, model
def test_first_level_glm_computation_with_memory_caching(): with InTemporaryDirectory(): shapes = ((7, 8, 9, 10),) mask, FUNCFILE, _ = write_fake_fmri_data_and_design(shapes) FUNCFILE = FUNCFILE[0] func_img = load(FUNCFILE) # initialize FirstLevelModel with memory option enabled t_r = 10.0 slice_time_ref = 0. events = basic_paradigm() # Ordinary Least Squares case model = FirstLevelModel(t_r, slice_time_ref, mask_img=mask, drift_model='polynomial', drift_order=3, memory='nilearn_cache', memory_level=1, minimize_memory=False) model.fit(func_img, events) # Delete objects attached to files to avoid WindowsError when deleting # temporary directory (in Windows) del mask, func_img, FUNCFILE, model
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_first_level_with_scaling(): shapes, rk = [(3, 1, 1, 2)], 1 fmri_data = list() fmri_data.append(Nifti1Image(np.zeros((1, 1, 1, 2)) + 6, np.eye(4))) design_matrices = list() design_matrices.append( pd.DataFrame(np.ones((shapes[0][-1], rk)), columns=list('abcdefghijklmnopqrstuvwxyz')[:rk])) fmri_glm = FirstLevelModel(mask_img=False, noise_model='ols', signal_scaling=0, minimize_memory=True) assert fmri_glm.signal_scaling == 0 assert not fmri_glm.standardize with pytest.warns(DeprecationWarning, match="Deprecated. `scaling_axis` will be removed"): assert fmri_glm.scaling_axis == 0 glm_parameters = fmri_glm.get_params() test_glm = FirstLevelModel(**glm_parameters) fmri_glm = fmri_glm.fit(fmri_data, design_matrices=design_matrices) test_glm = test_glm.fit(fmri_data, design_matrices=design_matrices) assert glm_parameters['signal_scaling'] == 0
def report_flm_adhd_dmn(): # pragma: no cover t_r = 2. slice_time_ref = 0. n_scans = 176 pcc_coords = (0, -53, 26) adhd_dataset = nilearn.datasets.fetch_adhd(n_subjects=1) seed_masker = NiftiSpheresMasker([pcc_coords], radius=10, detrend=True, standardize=True, low_pass=0.1, high_pass=0.01, t_r=2., memory='nilearn_cache', memory_level=1, verbose=0) seed_time_series = seed_masker.fit_transform(adhd_dataset.func[0]) frametimes = np.linspace(0, (n_scans - 1) * t_r, n_scans) design_matrix = make_first_level_design_matrix(frametimes, hrf_model='spm', add_regs=seed_time_series, add_reg_names=["pcc_seed"]) dmn_contrast = np.array([1] + [0] * (design_matrix.shape[1] - 1)) contrasts = {'seed_based_glm': dmn_contrast} first_level_model = FirstLevelModel(t_r=t_r, slice_time_ref=slice_time_ref) first_level_model = first_level_model.fit(run_imgs=adhd_dataset.func[0], design_matrices=design_matrix) report = make_glm_report( first_level_model, contrasts=contrasts, title='ADHD DMN Report', cluster_threshold=15, height_control='bonferroni', min_distance=8., plot_type='glass', report_dims=(1200, 'a'), ) output_filename = 'generated_report_flm_adhd_dmn.html' output_filepath = os.path.join(REPORTS_DIR, output_filename) report.save_as_html(output_filepath) report.get_iframe()
################################ from nilearn.glm.first_level import FirstLevelModel from nilearn.glm.first_level import make_first_level_design_matrix import nibabel as ni bids_dir = os.path.join(path_bids, "derivatives", "pipeline-fidl") subjects = os.listdir(bids_dir) for subj in subjects: p = os.path.join(bids_dir, subj) files = os.listdir(os.path.join(bids_dir, subj)) files = [f for f in files if f.find("delayed") != -1] nii = [f for f in files if f.find('.nii') != -1] tsv = [f for f in files if f.find('.tsv') != -1][0] events = pd.read_csv(os.path.join(bids_dir, subj, tsv), delimiter="\t") events['trial_type'] = events['image'] first_level_model = FirstLevelModel(1.71, hrf_model='glover') nii.sort() fmri_list = [ni.load(os.path.join(p, f)).get_data() for f in nii] fmri_list = np.concatenate(fmri_list, 3) image = ni.Nifti1Image(fmri_list, np.eye(4)) first_level_model = first_level_model.fit(image, events=events)
events_file = data['events'] import pandas as pd events = pd.read_table(events_file) events ############################################################################### # Running a basic model # --------------------- # # First we specify a linear model. # The .fit() functionality of FirstLevelModel function creates the design # matrix and the beta maps. # from nilearn.glm.first_level import FirstLevelModel first_level_model = FirstLevelModel(t_r) first_level_model = first_level_model.fit(fmri_img, events=events) design_matrix = first_level_model.design_matrices_[0] ######################################################################### # Let us take a look at the design matrix: it has 10 main columns corresponding # to 10 experimental conditions, followed by 3 columns describing low-frequency # signals (drifts) and a constant regressor. from nilearn.plotting import plot_design_matrix plot_design_matrix(design_matrix) import matplotlib.pyplot as plt plt.show() ######################################################################### # Specification of the contrasts. # # For this, let's create a function that, given the design matrix, generates
verbose=0) seed_time_series = seed_masker.fit_transform(adhd_dataset.func[0]) frametimes = np.linspace(0, (n_scans - 1) * t_r, n_scans) design_matrix = make_first_level_design_matrix(frametimes, hrf_model='spm', add_regs=seed_time_series, add_reg_names=["pcc_seed"]) dmn_contrast = np.array([1] + [0] * (design_matrix.shape[1] - 1)) contrasts = {'seed_based_glm': dmn_contrast} ######################################################################### # Perform first level analysis # ---------------------------- # Setup and fit GLM. first_level_model = FirstLevelModel(t_r=t_r, slice_time_ref=slice_time_ref) first_level_model = first_level_model.fit(run_imgs=adhd_dataset.func[0], design_matrices=design_matrix) ######################################################################### # Estimate the contrast. print('Contrast seed_based_glm computed.') z_map = first_level_model.compute_contrast(contrasts['seed_based_glm'], output_type='z_score') # Saving snapshots of the contrasts filename = 'dmn_z_map.png' display = plotting.plot_stat_map(z_map, threshold=3.0, title='Seed based GLM', cut_coords=pcc_coords) display.add_markers(marker_coords=[pcc_coords], marker_color='g',
anat_file = results[0]['anat'] """specify contrasts""" _, matrix, names = check_design_matrix(design_matrix) contrasts = {} n_columns = len(names) I = np.eye(len(names)) for i in range(2): contrasts['%s' % names[2 * i]] = I[2 * i] """more interesting contrasts""" contrasts['EV1>EV2'] = contrasts['EV1'] - contrasts['EV2'] contrasts['EV2>EV1'] = contrasts['EV2'] - contrasts['EV1'] contrasts['effects_of_interest'] = contrasts['EV1'] + contrasts['EV2'] """fit GLM""" print('\r\nFitting a GLM (this takes time) ..') fmri_glm = FirstLevelModel() fmri_glm.fit(fmri_files, design_matrices=design_matrix) """save computed mask""" mask_path = os.path.join(subject_data.output_dir, "mask.nii.gz") print("Saving mask image %s" % mask_path) nibabel.save(fmri_glm.masker_.mask_img_, mask_path) # compute bg unto which activation will be projected mean_fmri_files = compute_mean_3D_image(fmri_files) print("Computing contrasts ..") z_maps = {} for contrast_id, contrast_val in contrasts.items(): print("\tcontrast id: %s" % contrast_id) z_map = fmri_glm.compute_contrast(contrasts[contrast_id], output_type='z_score') z_maps[contrast_id] = z_map
def run_subject(sub, out_dir): """ Runs pattern estimation for a single subject. """ print(f"INFO: Processing {sub}") # Define in- and output directories bids_dir = op.join(f'../{sub}') fprep_dir = op.join(f'../derivatives/fmriprep/{sub}') out_dir = op.join(out_dir, sub) funcs = sorted( glob(fprep_dir + '/ses-?/func/*task-face*space-MNI*desc-preproc_bold.nii.gz')) for func in funcs: t_r = nib.load(func).header['pixdim'][4] conf = func.split('_space')[0] + '_desc-confounds_timeseries.tsv' mask = func.replace('preproc_bold', 'brain_mask') events = bids_dir + func.split(fprep_dir)[1].split( '_space')[0] + '_events.tsv' flm = FirstLevelModel(t_r=t_r, slice_time_ref=0.5, hrf_model='glover', drift_model='cosine', high_pass=0.01, mask_img=mask, smoothing_fwhm=None, noise_model='ols', n_jobs=1, minimize_memory=False) # Select confounds conf = pd.read_csv(conf, sep='\t').loc[:, [ 'trans_x', 'trans_y', 'trans_z', 'rot_x', 'rot_y', 'rot_z', 'csf', 'white_matter' ]] # Redefine output dir this_out_dir = op.join(out_dir, func.split(fprep_dir)[1].split('/')[1]) for d in ['patterns', 'model', 'figures']: if not op.isdir(op.join(this_out_dir, d)): os.makedirs(op.join(this_out_dir, d), exist_ok=True) # Fit model flm.fit(run_imgs=func, events=events, confounds=conf) # Save some stuff! f_base = op.basename(func).split('preproc')[0] rsq_out = op.join(this_out_dir, 'model', f_base + 'model_r2.nii.gz') flm.r_square[0].to_filename(rsq_out) dm = flm.design_matrices_[0] dm_out = op.join(this_out_dir, 'model', f_base + 'design_matrix.tsv') dm.to_csv(dm_out, sep='\t', index=False) dmfig_out = op.join(this_out_dir, 'figures', f_base + 'design_matrix.png') plot_design_matrix(dm, output_file=dmfig_out) dmcorrfig_out = op.join(this_out_dir, 'figures', f_base + 'design_corr.png') labels = dm.columns.tolist()[:-1] ax = plot_design_matrix(dm.drop('constant', axis=1).corr()) ax.set_yticks(range(len(labels))) ax.set_yticklabels(labels) plt.savefig(dmcorrfig_out) plt.close() resids_out = op.join(this_out_dir, 'model', f_base + 'model_residuals.nii.gz') flm.residuals[0].to_filename(resids_out) trials = [l for l in labels if 'STIM' in l] b, vb = [], [] for trial in trials: dat = flm.compute_contrast(trial, stat_type='t', output_type='all') b.append(dat['effect_size']) vb.append(dat['effect_variance']) beta_out = op.join(this_out_dir, 'patterns', f_base + 'trial_beta.nii.gz') image.concat_imgs(b).to_filename(beta_out) varbeta_out = op.join(this_out_dir, 'patterns', f_base + 'trial_varbeta.nii.gz') image.concat_imgs(vb).to_filename(varbeta_out)
# Instantiate the glm glm = FirstLevelModel(t_r=TR, mask_img=haxby_dataset.mask, high_pass=.008, smoothing_fwhm=4, memory='nilearn_cache') ############################################################################## # Run the glm on data from each session # ------------------------------------- for session in unique_sessions: # grab the fmri data for that particular session fmri_session = index_img(func_filename, sessions == session) # fit the glm glm.fit(fmri_session, events=events[session]) # set up contrasts: one per condition conditions = events[session].trial_type.unique() for condition_ in conditions: z_maps.append(glm.compute_contrast(condition_)) condition_idx.append(condition_) session_idx.append(session) ######################################################################### # Generating a report # ------------------- # Since we have already computed the FirstLevelModel # and have the contrast, we can quickly create a summary report. from nilearn.image import mean_img from nilearn.reporting import make_glm_report
# * t_r=7(s) is the time of repetition of acquisitions # * noise_model='ar1' specifies the noise covariance model: a lag-1 dependence # * standardize=False means that we do not want to rescale the time series to mean 0, variance 1 # * hrf_model='spm' means that we rely on the SPM "canonical hrf" model (without time or dispersion derivatives) # * drift_model='cosine' means that we model the signal drifts as slow oscillating time functions # * high_pass=0.01(Hz) defines the cutoff frequency (inverse of the time period). fmri_glm = FirstLevelModel(t_r=7, noise_model='ar1', standardize=False, hrf_model='spm', drift_model='cosine', high_pass=.01) ############################################################################### # Now that we have specified the model, we can run it on the fMRI image fmri_glm = fmri_glm.fit(fmri_img, events) ############################################################################### # One can inspect the design matrix (rows represent time, and # columns contain the predictors). design_matrix = fmri_glm.design_matrices_[0] ############################################################################### # Formally, we have taken the first design matrix, because the model is # implictily meant to for multiple runs. from nilearn.reporting import plot_design_matrix plot_design_matrix(design_matrix) import matplotlib.pyplot as plt plt.show() ###############################################################################
design_files = [data['design_matrix1'], data['design_matrix2']] import pandas as pd import numpy as np design_matrices = [pd.DataFrame(np.load(df)['X']) for df in design_files] ######################################################################### # GLM estimation # ---------------------------------- # GLM specification. Note that the mask was provided in the dataset. So we use it. from nilearn.glm.first_level import FirstLevelModel fmri_glm = FirstLevelModel(mask_img=data['mask'], minimize_memory=True) ######################################################################### # Let's fit the GLM. fmri_glm = fmri_glm.fit(fmri_img, design_matrices=design_matrices) ######################################################################### # Compute fixed effects of the two runs and compute related images. # For this, we first define the contrasts as we would do for a single session. n_columns = design_matrices[0].shape[1] def pad_vector(contrast_, n_columns): """A small routine to append zeros in contrast vectors""" return np.hstack((contrast_, np.zeros(n_columns - len(contrast_)))) ######################################################################### # Contrast specification contrasts = {'SStSSp_minus_DStDSp': pad_vector([1, 0, 0, -1], n_columns), 'DStDSp_minus_SStSSp': pad_vector([-1, 0, 0, 1], n_columns),
def main(subject, session, sourcedata): runs = range(1, 5) behavior = [] for run in runs: behavior.append( pd.read_table( op.join( sourcedata, f'sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-mapper_run-{run}_events.tsv' ))) behavior = pd.concat(behavior, keys=runs, names=['run']) behavior['subject'] = subject behavior = behavior.reset_index().set_index( ['subject', 'run', 'trial_type']) ims = [ op.join( sourcedata, f'derivatives/fmriprep/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-mapper_run-{run}_space-T1w_desc-preproc_bold.nii.gz' ) for run in runs ] fmriprep_confounds_include = [ 'global_signal', 'dvars', 'framewise_displacement', 'trans_x', 'trans_y', 'trans_z', 'rot_x', 'rot_y', 'rot_z', 'a_comp_cor_00', 'a_comp_cor_01', 'a_comp_cor_02', 'a_comp_cor_03', 'cosine00', 'cosine01', 'cosine02', 'non_steady_state_outlier00', 'non_steady_state_outlier01', 'non_steady_state_outlier02' ] fmriprep_confounds = [ op.join( sourcedata, f'derivatives/fmriprep/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-mapper_run-{run}_desc-confounds_timeseries.tsv' ) for run in runs ] fmriprep_confounds = [ pd.read_table(cf)[fmriprep_confounds_include] for cf in fmriprep_confounds ] retroicor_confounds = [ op.join( sourcedata, f'derivatives/physiotoolbox/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-mapper_run-{run}_desc-retroicor_timeseries.tsv' ) for run in runs ] retroicor_confounds = [ pd.read_table(cf, header=None, usecols=range(18)) for cf in retroicor_confounds ] confounds = [ pd.concat((rcf, fcf), axis=1) for rcf, fcf in zip(retroicor_confounds, fmriprep_confounds) ] confounds = [c.fillna(method='bfill') for c in confounds] model = FirstLevelModel(t_r=2.3, slice_time_ref=.5, signal_scaling=False, drift_model=None, smoothing_fwhm=0.0) responses = behavior.xs( 'response', 0, 'trial_type', drop_level=False).reset_index('trial_type')[['onset', 'trial_type']] responses['duration'] = 0.0 responses = responses[responses.onset > 0] stimulation = behavior.xs('stimulation', 0, 'trial_type', drop_level=False).reset_index('trial_type')[[ 'onset', 'duration', 'n_dots', 'trial_type' ]] stimulation_mod = stimulation.copy() stimulation_mod['modulation'] = np.log(stimulation_mod['n_dots']) stimulation_mod['modulation'] = (stimulation_mod['modulation'] - stimulation_mod['modulation'].mean(0) ) / stimulation_mod['modulation'].std() stimulation_mod['trial_type'] = 'stimulation*n_dots' targets = behavior.xs('targets', 0, 'trial_type') hazard_regressor = targets[~targets.hazard1.isnull()].copy() hazard_regressor['modulation'] = hazard_regressor['hazard1'] hazard_regressor['modulation'] = (hazard_regressor['modulation'] - hazard_regressor['modulation'].mean() ) / hazard_regressor['modulation'].std() hazard_regressor['trial_type'] = 'hazard1' hazard_regressor['duration'] = 0.0 hazard_regressor = hazard_regressor[[ 'trial_type', 'duration', 'modulation', 'onset' ]] events = pd.concat( (responses, stimulation, stimulation_mod, hazard_regressor)) events['modulation'].fillna(1.0, inplace=True) model.fit(ims, [r for _, r in events.groupby(['run'])], confounds) zmaps = {} results_dir = op.join(sourcedata, 'derivatives', 'glm', 'simple_mapper', f'sub-{subject}', f'ses-{session}') if not op.exists(results_dir): os.makedirs(results_dir) for key in ['response', 'stimulation', 'stimulation*n_dots', 'hazard1']: zmaps[key] = model.compute_contrast(key) zmaps[key].to_filename( op.join(results_dir, f'sub-{subject}_ses-{session}_zmap_{key}.nii.gz'))
def main(subject, session, bids_folder, smoothed=False, pca_confounds=False, space='fsnative', n_jobs=14): derivatives = op.join(bids_folder, 'derivatives') runs = range(1, 9) ims = [ op.join( derivatives, f'fmriprep/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-{run}_space-T1w_desc-preproc_bold.nii.gz' ) for run in runs ] mask = op.join( derivatives, f'fmriprep/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-1_space-T1w_desc-brain_mask.nii.gz' ) base_dir = 'glm_stim1' if smoothed: base_dir += '.smoothed' if pca_confounds: base_dir += '.pca_confounds' base_dir = op.join(derivatives, base_dir, f'sub-{subject}', f'ses-{session}', 'func') if not op.exists(base_dir): os.makedirs(base_dir) behavior = [] for run in runs: behavior.append( pd.read_table( op.join( bids_folder, f'sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-{run}_events.tsv' ))) behavior = pd.concat(behavior, keys=runs, names=['run']) behavior = behavior.reset_index().set_index(['run', 'trial_type']) stimulus1 = behavior.xs( 'stimulus 1', 0, 'trial_type', drop_level=False).reset_index('trial_type')[['onset', 'trial_type']] stimulus1['duration'] = 0.6 stimulus2 = behavior.xs('stimulus 2', 0, 'trial_type', drop_level=False).reset_index('trial_type')[[ 'onset', 'trial_type', 'trial_nr' ]] stimulus2['duration'] = 0.6 stimulus2['trial_type'] = stimulus2.trial_nr.map( lambda trial: f'trial_{trial}') print(stimulus2) n1 = behavior.xs('stimulus 1', 0, 'trial_type', drop_level=False).reset_index('trial_type')[[ 'onset', 'trial_type', 'n1' ]] n1['duration'] = 0.6 def zscore(n): return (n - n.mean()) / n.std() n1['modulation'] = zscore(n1['n1']) n1['trial_type'] = 'n_dots1' p1 = behavior.xs('stimulus 1', 0, 'trial_type', drop_level=False).reset_index('trial_type')[[ 'onset', 'trial_type', 'prob1' ]] p1 = p1[p1.prob1 == 1.0] p1['duration'] = 0.6 p1['trial_type'] = 'certain1' events = pd.concat( (stimulus1, stimulus2, n1, p1)).set_index('trial_nr', append=True).sort_index() events['modulation'].fillna(1.0, inplace=True) print(events) fmriprep_confounds_include = [ 'global_signal', 'dvars', 'framewise_displacement', 'trans_x', 'trans_y', 'trans_z', 'rot_x', 'rot_y', 'rot_z', 'a_comp_cor_00', 'a_comp_cor_01', 'a_comp_cor_02', 'a_comp_cor_03', 'cosine00', 'cosine01', 'cosine02', 'cosine03', 'non_steady_state_outlier00', 'non_steady_state_outlier01', 'non_steady_state_outlier02' ] fmriprep_confounds = [ op.join( bids_folder, f'derivatives/fmriprep/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-{run}_desc-confounds_timeseries.tsv' ) for run in runs ] fmriprep_confounds = [ pd.read_table(cf)[fmriprep_confounds_include] for cf in fmriprep_confounds ] retroicor_confounds = [ op.join( bids_folder, f'derivatives/physiotoolbox/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-{run}_desc-retroicor_timeseries.tsv' ) for run in runs ] retroicor_confounds = [ pd.read_table(cf, header=None, usecols=range(18)) if op.exists(cf) else pd.DataFrame(np.zeros((160, 0))) for cf in retroicor_confounds ] confounds = [ pd.concat((rcf, fcf), axis=1) for rcf, fcf in zip(retroicor_confounds, fmriprep_confounds) ] confounds = [c.fillna(method='bfill') for c in confounds] t_r, n_scans = 2.3, 160 frame_times = t_r * (np.arange(n_scans) + .5) model = FirstLevelModel(t_r=2.3, slice_time_ref=.5, signal_scaling=False, drift_model=None, mask_img=mask, smoothing_fwhm=0.0) single_trial_betas = [] for run in runs: im = image.math_img('(im / im.mean(-1)[..., np.newaxis]) * 100 - 100', im=ims[run - 1]) model.fit(im, events.loc[run], confounds[run - 1]) for trial in range(1 + (run - 1) * 24, 1 + run * 24): print(trial) single_trial_betas.append( model.compute_contrast(f'trial_{trial}', output_type='effect_size')) single_trial_betas = image.concat_imgs(single_trial_betas) single_trial_betas.to_filename( op.join( base_dir, f'sub-{subject}_ses-{session}_task-task_space-T1w_desc-stims2_pe.nii.gz' ))
######################################################################### # Next solution is to try Finite Impulse Reponse (FIR) models: we just # say that the hrf is an arbitrary function that lags behind the # stimulus onset. In the present case, given that the numbers of # conditions is high, we should use a simple FIR model. # # Concretely, we set `hrf_model` to 'fir' and `fir_delays` to [1, 2, # 3] (scans) corresponding to a 3-step functions on the [1 * t_r, 4 * # t_r] seconds interval. # from nilearn.glm.first_level import FirstLevelModel from nilearn.reporting import plot_design_matrix, plot_contrast_matrix first_level_model = FirstLevelModel(t_r, hrf_model='fir', fir_delays=[1, 2, 3]) first_level_model = first_level_model.fit(fmri_img, events=events) design_matrix = first_level_model.design_matrices_[0] plot_design_matrix(design_matrix) ######################################################################### # We have to adapt contrast specification. We characterize the BOLD # response by the sum across the three time lags. It's a bit hairy, # sorry, but this is the price to pay for flexibility... import numpy as np contrast_matrix = np.eye(design_matrix.shape[1]) contrasts = dict([(column, contrast_matrix[i]) for i, column in enumerate(design_matrix.columns)]) conditions = events.trial_type.unique() for condition in conditions:
# beta maps into condition-wise beta series. # Transform the DataFrame for LSA lsa_events_df = events_df.copy() conditions = lsa_events_df['trial_type'].unique() condition_counter = {c: 0 for c in conditions} for i_trial, trial in lsa_events_df.iterrows(): trial_condition = trial['trial_type'] condition_counter[trial_condition] += 1 # We use a unique delimiter here (``__``) that shouldn't be in the # original condition names trial_name = f'{trial_condition}__{condition_counter[trial_condition]:03d}' lsa_events_df.loc[i_trial, 'trial_type'] = trial_name lsa_glm = FirstLevelModel(**glm_parameters) lsa_glm.fit(fmri_file, lsa_events_df) fig, ax = plt.subplots(figsize=(10, 10)) plotting.plot_design_matrix(lsa_glm.design_matrices_[0], ax=ax) fig.show() ############################################################################## # Aggregate beta maps from the LSA model based on condition # ````````````````````````````````````````````````````````` # Collect the parameter estimate maps lsa_beta_maps = {cond: [] for cond in events_df['trial_type'].unique()} trialwise_conditions = lsa_events_df['trial_type'].unique() for condition in trialwise_conditions: beta_map = lsa_glm.compute_contrast(condition, output_type='effect_size') # Drop the trial number from the condition name to get the original name condition_name = condition.split('__')[0]
# spanning the two conditions. contrasts = { 'faces-scrambled': basic_contrasts['faces'] - basic_contrasts['scrambled'], 'scrambled-faces': -basic_contrasts['faces'] + basic_contrasts['scrambled'], 'effects_of_interest': np.vstack((basic_contrasts['faces'], basic_contrasts['scrambled'])) } ######################################################################### # Fit the GLM for the 2 sessions by specifying a FirstLevelModel and then # fitting it. from nilearn.glm.first_level import FirstLevelModel print('Fitting a GLM') fmri_glm = FirstLevelModel() fmri_glm = fmri_glm.fit(fmri_img, design_matrices=design_matrices) ######################################################################### # Now we can compute contrast-related statistical maps (in z-scale), and plot # them. print('Computing contrasts') from nilearn import plotting # Iterate on contrasts for contrast_id, contrast_val in contrasts.items(): print("\tcontrast id: %s" % contrast_id) # compute the contrasts z_map = fmri_glm.compute_contrast( contrast_val, output_type='z_score') # plot the contrasts as soon as they're generated # the display is overlaid on the mean fMRI image
def main(subject, session, sourcedata): runs = range(1, 9) behavior = [] for run in runs: behavior.append(pd.read_table(op.join( sourcedata, f'sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task-{run}_events.tsv'))) behavior = pd.concat(behavior, keys=runs, names=['run']) behavior['subject'] = subject behavior = behavior.reset_index().set_index( ['subject', 'run', 'trial_type']) ims = [ op.join(sourcedata, f'derivatives/fmriprep/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-{run}_space-T1w_desc-preproc_bold.nii.gz') for run in runs] mask_img = op.join(sourcedata, f'derivatives/fmriprep/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-1_space-T1w_desc-brain_mask.nii.gz') fmriprep_confounds_include = ['global_signal', 'dvars', 'framewise_displacement', 'trans_x', 'trans_y', 'trans_z', 'rot_x', 'rot_y', 'rot_z', 'a_comp_cor_00', 'a_comp_cor_01', 'a_comp_cor_02', 'a_comp_cor_03', 'cosine00', 'cosine01', 'cosine02', 'cosine03', 'non_steady_state_outlier00', 'non_steady_state_outlier01', 'non_steady_state_outlier02'] fmriprep_confounds = [ op.join(sourcedata, f'derivatives/fmriprep/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-{run}_desc-confounds_timeseries.tsv') for run in runs] fmriprep_confounds = [pd.read_table( cf)[fmriprep_confounds_include] for cf in fmriprep_confounds] retroicor_confounds = [ op.join(sourcedata, f'derivatives/physiotoolbox/sub-{subject}/ses-{session}/func/sub-{subject}_ses-{session}_task-task_run-{run}_desc-retroicor_timeseries.tsv') for run in runs] retroicor_confounds = [pd.read_table( cf, header=None, usecols=range(18)) for cf in retroicor_confounds] confounds = [pd.concat((rcf, fcf), axis=1) for rcf, fcf in zip(retroicor_confounds, fmriprep_confounds)] confounds = [c.fillna(method='bfill') for c in confounds] print(behavior) print(confounds) model = FirstLevelModel(t_r=2.3, slice_time_ref=.5, signal_scaling=False, drift_model=None, mask_img=mask_img, smoothing_fwhm=0.0) stimulus1 = behavior.xs('stimulus 1', 0, 'trial_type', drop_level=False).reset_index('trial_type')[['onset', 'trial_type']] stimulus1['duration'] = 0.6 stimulus2 = behavior.xs('stimulus 2', 0, 'trial_type', drop_level=False).reset_index('trial_type')[['onset', 'trial_type']] stimulus2['duration'] = 0.6 n1 = behavior.xs('stimulus 1', 0, 'trial_type', drop_level=False).reset_index('trial_type')[['onset', 'trial_type', 'n1']] n1['duration'] = 0.6 def zscore(n): return (n - n.mean()) / n.std() n1['modulation'] = zscore(n1['n1']) n1['trial_type'] = 'n_dots1' n2 = behavior.xs('stimulus 2', 0, 'trial_type', drop_level=False).reset_index('trial_type')[['onset', 'trial_type', 'n2']] n2['duration'] = 0.6 def zscore(n): return (n - n.mean()) / n.std() n2['modulation'] = zscore(n2['n2']) n2['trial_type'] = 'n_dots2' p1 = behavior.xs('stimulus 1', 0, 'trial_type', drop_level=False).reset_index('trial_type')[['onset', 'trial_type', 'prob1']] p1 = p1[p1.prob1 == 1.0] p1['duration'] = 0.6 p1['trial_type'] = 'certain1' p2 = behavior.xs('stimulus 2', 0, 'trial_type', drop_level=False).reset_index('trial_type')[['onset', 'trial_type', 'prob2']] p2 = p2[p2.prob2 == 1.0] p2['duration'] = 0.6 p2['trial_type'] = 'certain2' events = pd.concat((stimulus1, stimulus2, n1, n2, p1, p2)).sort_values('onset') events['modulation'].fillna(1.0, inplace=True) print(events) model.fit(ims, [r for _, r in events.groupby(['run'])], confounds) zmaps = {} results_dir = op.join(sourcedata, 'derivatives', 'glm', 'simple_task', f'sub-{subject}', f'ses-{session}') if not op.exists(results_dir): os.makedirs(results_dir) for key in ['stimulus 1', 'stimulus 2', 'n_dots1', 'n_dots2', 'certain1', 'certain2']: zmaps[key] = model.compute_contrast(key) zmaps[key].to_filename(op.join(results_dir, f'sub-{subject}_ses-{session}_zmap_{key}.nii.gz'))