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_design_matrix0c(): # test design matrix creation when regressors are provided manually rng = np.random.RandomState(42) tr = 1.0 frame_times = np.linspace(0, 127 * tr, 128) ax = rng.standard_normal(size=(128, 4)) _, X, names = check_design_matrix( make_first_level_design_matrix(frame_times, drift_model='polynomial', drift_order=3, add_regs=ax)) assert_almost_equal(X[:, 0], ax[:, 0]) ax = rng.standard_normal(size=(127, 4)) with pytest.raises( AssertionError, match="Incorrect specification of additional regressors:."): make_first_level_design_matrix(frame_times, add_regs=ax) ax = rng.standard_normal(size=(128, 4)) with pytest.raises( ValueError, match="Incorrect number of additional regressor names."): make_first_level_design_matrix(frame_times, add_regs=ax, add_reg_names='') # with pandas Dataframe axdf = pd.DataFrame(ax) _, X1, names = check_design_matrix( make_first_level_design_matrix(frame_times, drift_model='polynomial', drift_order=3, add_regs=axdf)) assert_almost_equal(X1[:, 0], ax[:, 0]) assert_array_equal(names[:4], np.arange(4))
def test_design_matrix0(): # Test design matrix creation when no experimental paradigm is provided tr = 1.0 frame_times = np.linspace(0, 127 * tr, 128) _, X, names = check_design_matrix( make_first_level_design_matrix(frame_times, drift_model='polynomial', drift_order=3)) assert len(names) == 4 x = np.linspace(-0.5, .5, 128) assert_almost_equal(X[:, 0], x)
def test_csv_io(): # test the csv io on design matrices tr = 1.0 frame_times = np.linspace(0, 127 * tr, 128) events = modulated_event_paradigm() DM = make_first_level_design_matrix( frame_times, events, hrf_model='glover', drift_model='polynomial', drift_order=3, ) path = 'design_matrix.csv' with InTemporaryDirectory(): DM.to_csv(path) DM2 = pd.read_csv(path, index_col=0) _, matrix, names = check_design_matrix(DM) _, matrix_, names_ = check_design_matrix(DM2) assert_almost_equal(matrix, matrix_) assert names == names_
def test_design_matrix0d(): # test design matrix creation when regressors are provided manually tr = 1.0 frame_times = np.linspace(0, 127 * tr, 128) ax = np.random.randn(128, 4) _, X, names = check_design_matrix( make_first_level_design_matrix(frame_times, drift_model='polynomial', drift_order=3, add_regs=ax)) assert len(names) == 8 assert X.shape[1] == 8
def test_spm_2(): # Check that the nistats design matrix is close enough to the SPM one # (it cannot be identical, because the hrf shape is different) frame_times = np.linspace(0, 99, 100) conditions = ['c0', 'c0', 'c0', 'c1', 'c1', 'c1', 'c2', 'c2', 'c2'] onsets = [30, 50, 70, 10, 30, 80, 30, 40, 60] durations = 10 * np.ones(9) events = pd.DataFrame({ 'trial_type': conditions, 'onset': onsets, 'duration': durations }) X1 = make_first_level_design_matrix(frame_times, events, drift_model=None) spm_design_matrix = DESIGN_MATRIX['arr_1'] _, matrix, _ = check_design_matrix(X1) assert (((spm_design_matrix - matrix)**2).sum() / (spm_design_matrix**2).sum() < .1)
def design_matrix_light(frame_times, events=None, hrf_model='glover', drift_model='cosine', high_pass=.01, drift_order=1, fir_delays=None, add_regs=None, add_reg_names=None, min_onset=-24, path=None): """ Same as make_first_level_design_matrix, but only returns the computed matrix and associated name. """ fir_delays = fir_delays if fir_delays else [0] dmtx = make_first_level_design_matrix(frame_times, events, hrf_model, drift_model, high_pass, drift_order, fir_delays, add_regs, add_reg_names, min_onset) _, matrix, names = check_design_matrix(dmtx) return matrix, names
def test_design_matrix0c(): # test design matrix creation when regressors are provided manually tr = 1.0 frame_times = np.linspace(0, 127 * tr, 128) ax = np.random.randn(128, 4) _, X, names = check_design_matrix( make_first_level_design_matrix(frame_times, drift_model='polynomial', drift_order=3, add_regs=ax)) assert_almost_equal(X[:, 0], ax[:, 0]) ax = np.random.randn(127, 4) with pytest.raises( AssertionError, match="Incorrect specification of additional regressors:."): make_first_level_design_matrix(frame_times, add_regs=ax) ax = np.random.randn(128, 4) with pytest.raises( ValueError, match="Incorrect number of additional regressor names."): make_first_level_design_matrix(frame_times, add_regs=ax, add_reg_names='')
def first_level(subject_dic, additional_regressors=None, compcorr=False, smooth=None, mesh=False, mask_img=None): """ Run the first-level analysis (GLM fitting + statistical maps) in a given subject Parameters ---------- subject_dic: dict, exhaustive description of an individual acquisition additional_regressors: dict or None, additional regressors provided as an already sampled design_matrix dictionary keys are session_ids compcorr: Bool, optional, whether confound estimation and removal should be done or not smooth: float or None, optional, how much the data should spatially smoothed during masking """ start_time = time.ctime() # experimental paradigm meta-params motion_names = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz'] hrf_model = subject_dic['hrf_model'] high_pass = subject_dic['high_pass'] drift_model = subject_dic['drift_model'] tr = subject_dic['TR'] slice_time_ref = 1. if not mesh and (mask_img is None): mask_img = masking(subject_dic['func'], subject_dic['output_dir']) if additional_regressors is None: additional_regressors = dict([ (session_id, None) for session_id in subject_dic['session_id'] ]) for session_id, fmri_path, onset, motion_path in zip( subject_dic['session_id'], subject_dic['func'], subject_dic['onset'], subject_dic['realignment_parameters']): task_id = _session_id_to_task_id([session_id])[0] if mesh is not False: from nibabel.gifti import read n_scans = np.array( [darrays.data for darrays in read(fmri_path).darrays]).shape[0] else: n_scans = nib.load(fmri_path).shape[3] # motion parameters motion = np.loadtxt(motion_path) # define the time stamps for different images frametimes = np.linspace(slice_time_ref, (n_scans - 1 + slice_time_ref) * tr, n_scans) if task_id == 'audio': mask = np.array([1, 0, 1, 1, 0, 1, 1, 0, 1, 1]) n_cycles = 28 cycle_duration = 20 t_r = 2 cycle = np.arange(0, cycle_duration, t_r)[mask > 0] frametimes = np.tile(cycle, n_cycles) +\ np.repeat(np.arange(n_cycles) * cycle_duration, mask.sum()) frametimes = frametimes[:-2] # for some reason... if mesh is not False: compcorr = False # XXX Fixme if compcorr: confounds = high_variance_confounds(fmri_path, mask_img=mask_img) confounds = np.hstack((confounds, motion)) confound_names = ['conf_%d' % i for i in range(5)] + motion_names else: confounds = motion confound_names = motion_names if onset is None: warnings.warn('Onset file not provided. Trying to guess it') task = os.path.basename(fmri_path).split('task')[-1][4:] onset = os.path.join( os.path.split(os.path.dirname(fmri_path))[0], 'model001', 'onsets', 'task' + task + '_run001', 'task%s.csv' % task) if not os.path.exists(onset): warnings.warn('non-existant onset file. proceeding without it') paradigm = None else: paradigm = make_paradigm(onset, task_id) # handle manually supplied regressors add_reg_names = [] if additional_regressors[session_id] is None: add_regs = confounds else: df = read_csv(additional_regressors[session_id]) add_regs = [] for regressor in df: add_reg_names.append(regressor) add_regs.append(df[regressor]) add_regs = np.array(add_regs).T add_regs = np.hstack((add_regs, confounds)) add_reg_names += confound_names # create the design matrix design_matrix = make_first_level_design_matrix( frametimes, paradigm, hrf_model=hrf_model, drift_model=drift_model, high_pass=high_pass, add_regs=add_regs, add_reg_names=add_reg_names) _, dmtx, names = check_design_matrix(design_matrix) # create the relevant contrasts contrasts = make_contrasts(task_id, names) if mesh == 'fsaverage5': # this is low-resolution data subject_session_output_dir = os.path.join( subject_dic['output_dir'], 'res_fsaverage5_%s' % session_id) elif mesh == 'fsaverage7': subject_session_output_dir = os.path.join( subject_dic['output_dir'], 'res_fsaverage7_%s' % session_id) elif mesh == 'individual': subject_session_output_dir = os.path.join( subject_dic['output_dir'], 'res_individual_%s' % session_id) else: subject_session_output_dir = os.path.join( subject_dic['output_dir'], 'res_stats_%s' % session_id) if not os.path.exists(subject_session_output_dir): os.makedirs(subject_session_output_dir) np.savez(os.path.join(subject_session_output_dir, 'design_matrix.npz'), design_matrix=design_matrix) if mesh is not False: run_surface_glm(design_matrix, contrasts, fmri_path, subject_session_output_dir) else: z_maps, fmri_glm = run_glm(design_matrix, contrasts, fmri_path, mask_img, subject_dic, subject_session_output_dir, tr=tr, slice_time_ref=slice_time_ref, smoothing_fwhm=smooth) # do stats report anat_img = nib.load(subject_dic['anat']) stats_report_filename = os.path.join(subject_session_output_dir, 'report_stats.html') report = make_glm_report( fmri_glm, contrasts, threshold=3.0, bg_img=anat_img, cluster_threshold=15, title="GLM for subject %s" % session_id, ) report.save_as_html(stats_report_filename)
design_matrix = make_first_level_design_matrix(frametimes, paradigm, hrf_model=hrf_model, drift_model=drift_model, high_pass=hfcut) # plot and save design matrix ax = plot_design_matrix(design_matrix) ax.set_position([.05, .25, .9, .65]) ax.set_title('Design matrix') dmat_outfile = os.path.join(subject_data.output_dir, 'design_matrix.png') plt.savefig(dmat_outfile, bbox_inches="tight", dpi=200) # specify contrasts contrasts = {} _, matrix, names = check_design_matrix(design_matrix) contrast_matrix = np.eye(len(names)) for i in range(len(names)): contrasts[names[i]] = contrast_matrix[i] # more interesting contrasts""" contrasts = {'active-rest': contrasts['active'] - contrasts['rest']} # fit GLM print('\r\nFitting a GLM (this takes time) ..') fmri_glm = FirstLevelModel(noise_model='ar1', standardize=False, t_r=tr).fit( [nibabel.concat_images(subject_data.func[0])], design_matrices=design_matrix) # save computed mask mask_path = os.path.join(subject_data.output_dir, "mask.nii.gz")