def nilearn_denoise(in_file, brain_mask, wm_mask, csf_mask, motreg_file, outlier_file, bandpass, tr ): """Clean time series using Nilearn high_variance_confounds to extract CompCor regressors and NiftiMasker for regression of all nuissance regressors, detrending, normalziation and bandpass filtering. """ import numpy as np import nibabel as nb import os from nilearn.image import high_variance_confounds from nilearn.input_data import NiftiMasker from nipype.utils.filemanip import split_filename # reload niftis to round affines so that nilearn doesn't complain wm_nii=nb.Nifti1Image(nb.load(wm_mask).get_data(), np.around(nb.load(wm_mask).get_affine(), 2), nb.load(wm_mask).get_header()) csf_nii=nb.Nifti1Image(nb.load(csf_mask).get_data(), np.around(nb.load(csf_mask).get_affine(), 2), nb.load(csf_mask).get_header()) time_nii=nb.Nifti1Image(nb.load(in_file).get_data(),np.around(nb.load(in_file).get_affine(), 2), nb.load(in_file).get_header()) # infer shape of confound array # not ideal confound_len = nb.load(in_file).get_data().shape[3] # create outlier regressors outlier_regressor = np.empty((confound_len,1)) try: outlier_val = np.genfromtxt(outlier_file) except IOError: outlier_val = np.empty((0)) for index in np.atleast_1d(outlier_val): outlier_vector = np.zeros((confound_len, 1)) outlier_vector[index] = 1 outlier_regressor = np.hstack((outlier_regressor, outlier_vector)) outlier_regressor = outlier_regressor[:,1::] # load motion regressors motion_regressor=np.genfromtxt(motreg_file) # extract high variance confounds in wm/csf masks from motion corrected data wm_regressor=high_variance_confounds(time_nii, mask_img=wm_nii, detrend=True) csf_regressor=high_variance_confounds(time_nii, mask_img=csf_nii, detrend=True) # create Nifti Masker for denoising denoiser=NiftiMasker(mask_img=brain_mask, standardize=True, detrend=True, high_pass=bandpass[1], low_pass=bandpass[0], t_r=tr) # denoise and return denoise data to img confounds=np.hstack((outlier_regressor,wm_regressor, csf_regressor, motion_regressor)) denoised_data=denoiser.fit_transform(in_file, confounds=confounds) denoised_img=denoiser.inverse_transform(denoised_data) # save _, base, _ = split_filename(in_file) img_fname = base + '_denoised.nii.gz' nb.save(denoised_img, img_fname) confound_fname = os.path.join(os.getcwd(), "all_confounds.txt") np.savetxt(confound_fname, confounds, fmt="%.10f") return os.path.abspath(img_fname), confound_fname
def runcompcor(inputimg, inputmask, prcntl, numc, detr): return image.high_variance_confounds(inputimg, mask_img=inputmask, percentile=prcntl, n_confounds=numc, detrend=detr)
def apply_mask(self, atlas="AAL"): if atlas == "AAL": # load atlas atlas_filename = datasets.fetch_atlas_aal(version="SPM12", verbose=0).maps elif atlas == "multiscale": raise NotImplementedError() else: raise ValueError("Altas should be 'AAL' or 'multiscale'") # set mask masker = NiftiLabelsMasker(labels_img=atlas_filename, standardize=True, detrend=True, low_pass=0.08, high_pass=0.01, t_r=3.7, memory="nilearn_cache", verbose=0) # apply mask to data confounds = high_variance_confounds(self.fmri_filename, n_confounds=1, detrend=True) ts_hvar = masker.fit_transform(self.fmri_filename, confounds=confounds) return ts_hvar
def nilearn_denoise(in_file, brain_mask, motreg_file, outlier_file, bandpass, tr): """Clean time series using Nilearn high_variance_confounds to extract CompCor regressors and NiftiMasker for regression of all nuissance regressors, detrending, normalziation and bandpass filtering. """ import numpy as np import nibabel as nb import os from nilearn.image import high_variance_confounds from nilearn.input_data import NiftiMasker from nipype.utils.filemanip import split_filename # reload niftis to round affines so that nilearn doesn't complain # csf_nii=nb.Nifti1Image(nb.load(csf_mask).get_data(), np.around(nb.load(csf_mask).get_affine(), 2), nb.load(csf_mask).get_header()) # time_nii=nb.Nifti1Image(nb.load(in_file).get_data(),np.around(nb.load(in_file).get_affine(), 2), nb.load(in_file).get_header()) # infer shape of confound array confound_len = nb.load(in_file).get_data().shape[3] # create outlier regressors outlier_regressor = np.empty((confound_len,1)) try: outlier_val = np.genfromtxt(outlier_file) except IOError: outlier_val = np.empty((0)) for index in np.atleast_1d(outlier_val): outlier_vector = np.zeros((confound_len, 1)) outlier_vector[int(index)] = 1 outlier_regressor = np.hstack((outlier_regressor, outlier_vector)) outlier_regressor = outlier_regressor[:,1::] # load motion regressors motion_regressor=np.genfromtxt(motreg_file) # extract high variance confounds in brain mask ~ global signal regressor #csf_regressor=high_variance_confounds(time_nii, mask_img=csf_nii, detrend=True) global_regressor=high_variance_confounds(in_file, mask_img=brain_mask, n_confounds=1, detrend=True) # create Nifti Masker for denoising denoiser=NiftiMasker(mask_img=brain_mask, standardize=True, detrend=True, high_pass=bandpass[1], low_pass=bandpass[0], t_r=tr) # denoise and return denoise data to img confounds=np.hstack((outlier_regressor, motion_regressor, global_regressor)) denoised_data=denoiser.fit_transform(in_file, confounds=confounds) denoised_img=denoiser.inverse_transform(denoised_data) # save _, base, _ = split_filename(in_file) img_fname = base + '_denoised.nii.gz' nb.save(denoised_img, img_fname) data_fname = base + '_denoised.npy' np.save(data_fname, denoised_data) confound_fname = os.path.join(os.getcwd(), "all_confounds.txt") np.savetxt(confound_fname, confounds, fmt="%.10f") return os.path.abspath(img_fname), os.path.abspath(data_fname), confound_fname
def test_high_variance_confounds(): rng = np.random.RandomState(42) img, mask, conf = _simu_img() hv_confounds = high_variance_confounds(img) masker1 = NiftiMasker(standardize=True, detrend=False, high_variance_confounds=False, mask_img=mask).fit() tseries1 = masker1.transform(img, confounds=[hv_confounds, conf]) masker2 = NiftiMasker(standardize=True, detrend=False, high_variance_confounds=True, mask_img=mask).fit() tseries2 = masker2.transform(img, confounds=conf) np.testing.assert_array_equal(tseries1, tseries2)
def compute_confounds(imgs, mask_img, n_confounds=5, get_randomized_svd=False, compute_not_mask=False): """ """ confounds = [] if not isinstance(imgs, collections.Iterable) or \ isinstance(imgs, _basestring): imgs = [imgs, ] img = _utils.check_niimg_4d(imgs[0]) shape = img.shape[:3] affine = get_affine(img) if isinstance(mask_img, _basestring): mask_img = _utils.check_niimg_3d(mask_img) if not _check_same_fov(img, mask_img): mask_img = resample_img( mask_img, target_shape=shape, target_affine=affine, interpolation='nearest') if compute_not_mask: print("Non mask based confounds extraction") not_mask_data = np.logical_not(mask_img.get_data().astype(np.int)) whole_brain_mask = masking.compute_multi_epi_mask(imgs) not_mask = np.logical_and(not_mask_data, whole_brain_mask.get_data()) mask_img = new_img_like(img, not_mask.astype(np.int), affine) for img in imgs: print("[Confounds Extraction] {0}".format(img)) img = _utils.check_niimg_4d(img) print("[Confounds Extraction] high ariance confounds computation]") high_variance = high_variance_confounds(img, mask_img=mask_img, n_confounds=n_confounds) if compute_not_mask and get_randomized_svd: signals = masking.apply_mask(img, mask_img) non_constant = np.any(np.diff(signals, axis=0) != 0, axis=0) signals = signals[:, non_constant] signals = signal.clean(signals, detrend=True) print("[Confounds Extraction] Randomized SVD computation") U, s, V = randomized_svd(signals, n_components=n_confounds, random_state=0) if high_variance is not None: confound_ = np.hstack((U, high_variance)) else: confound_ = U else: confound_ = high_variance confounds.append(confound_) return confounds
def extract_confounds(imgs, mask_img, n_confounds=10): """To extract confounds on list of subjects See nilearn.image.high_variance_confounds for technical details. Parameters ---------- imgs : list of Nifti images, either str or nibabel.Nifti1Image Functional images on which confounds should be extracted mask_img : str or nibabel.Nifti1Image Mask image with binary values. This image is imposed on each functional image for confounds extraction.. n_confounds : int, optional By default, 10 high variance confounds are extracted. Otherwise, confounds as specified are extracted. Returns ------- confounds : list of Numpy arrays. Each numpy array is a confound corresponding to imgs provided. Each numpy array will have shape (n_timepoints, n_confounds) """ confounds = [] if not isinstance(imgs, collections.Iterable) or \ isinstance(imgs, _basestring): imgs = [imgs, ] img = _utils.check_niimg_4d(imgs[0]) shape = img.shape[:3] affine = img.affine if isinstance(mask_img, _basestring): mask_img = _utils.check_niimg_3d(mask_img) if not _check_same_fov(img, mask_img): mask_img = resample_img( mask_img, target_shape=shape, target_affine=affine, interpolation='nearest') for img in imgs: print("[Confounds Extraction] Image selected {0}".format(img)) img = _utils.check_niimg_4d(img) print("Extracting high variance confounds") high_variance = high_variance_confounds(img, mask_img=mask_img, n_confounds=n_confounds) confounds.append(high_variance) return confounds
def confound_std(img: niimg_like) -> float: """Compute the standard deviation of a Nifti 4D file. This is the denominator of the second term of the SFS expression. In order to be completely independent of external sources, we will use nilearn to estimate noisy fluctuations.""" masker = NiftiMasker(mask_strategy="template") masker.fit( img ) # Side effect: computes a mask and stores it within the masker obj. # high_variance_confounds in Nilearn is kind of a tCompCor. cof = image.high_variance_confounds(img, n_confounds=3, mask_img=masker.mask_img_) # Take the std of all 3 confounds and average them. return cof.std(axis=0).mean()
def make_dmtx(events, fmri, mask_img, confounds=None, t_r=2, compcorr=False, task='audio', normalize=True): """ Generates the design matrix to fit the single GLM approach to a particular fmri session Parameters ---------- events: tsv file contains information about the onset, duration and condition of the images fmri: 4D nifti file neuroimaging data mask_img: nifti-like object mask image to compute high variance confounds confounds: txt file, default=None file with information about the confounds t_r: int, default=2 repetition time of the acquisition in seconds compcorr: bool, default=False whether to estimate high variance confounds or not normalize: bool, default=True If True, normalize the stim (i.e., give them arbitrary numbers from 0 to n) Returns ------- design_matrix: pandas.DataFrame object design matrix with one trial per column """ n_scans = nib.load(fmri).shape[3] # define the time stamps for different images frame_times = np.linspace(0, (n_scans - 1) * t_r, n_scans) if task == '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] frame_times = np.tile(cycle, n_cycles) +\ np.repeat(np.arange(n_cycles) * cycle_duration, mask.sum()) frame_times = frame_times[:-2] # for some reason... paradigm = read_csv(events, sep='\t') if normalize: paradigm['trial_type'] = [condition.split('_')[0] for condition in paradigm['trial_type']] if confounds: motion = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz'] conf = np.loadtxt(confounds) if compcorr: hv_conf = high_variance_confounds(fmri, mask_img=mask_img) conf = np.hstack((hv_conf, conf)) motion = ['conf_%d' % i for i in range(5)] + motion else: conf = None if normalize: trial_type = paradigm["trial_type"].values for condition in set(trial_type): n_conds = (trial_type == condition).sum() trial_type[trial_type == condition] = ['%s_%02d' % (condition, i) for i in range(n_conds)] paradigm["trial_type"] = trial_type dmtx = make_first_level_design_matrix(frame_times, events=paradigm, hrf_model='spm', add_regs=conf, add_reg_names=motion) return dmtx
fmri_img = load_img(func_fname) n_scans = fmri_img.shape[-1] ######################################################################### # Seed base GLM analysis # manage outputs glm_output_dir = os.path.join(output_dir, "seed_based_glm") if not os.path.exists(glm_output_dir): os.makedirs(glm_output_dir) stats_start_time = time.ctime() # extract high variance components print("Extract high variance components...") n_confounds = 5 hv_comps = high_variance_confounds(func_fname, n_confounds) # wm and csf masking print("Extracting the Cerebrospinal fluid (CSF)...") csf_filename = os.path.join("pypreprocess_output", "mwc2T1.nii.gz") csf_time_serie = NiftiMasker(mask_img=csf_filename).fit_transform(func_fname) print("Extracting the white matter (WM)...") wm_filename = os.path.join("pypreprocess_output", "mwc3T1.nii.gz") wm_time_serie = NiftiMasker(mask_img=wm_filename).fit_transform(func_fname) dirty_data = np.vstack([csf_time_serie, wm_time_serie]) # make design matrix of PC components print("Computing the PCA out of the CSF and the WM...") pca = PCA(n_components=2) pca.fit(dirty_data)
# A problematic feature of fMRI is the presence of uncontrolled # confounds in the data, due to scanner instabilities (spikes) or # physiological phenomena, such as motion, heart and # respiration-related blood oxygenation fluctuations. Side # measurements are sometimes acquired to characterize these # effects. Here we don't have access to those. What we can do instead # is to estimate confounding effects from the data themselves, using # the CompCor approach, and take those into account in the model. # # For this we rely on the so-called `high_variance_confounds`_ # routine of Nilearn. # # .. _high_variance_confounds: https://nilearn.github.io/modules/generated/nilearn.image.high_variance_confounds.html from nilearn.image import high_variance_confounds confounds = pd.DataFrame(high_variance_confounds(fmri_img, percentile=1)) first_level_model = FirstLevelModel(t_r, hrf_model='spm + derivative', slice_time_ref=0.5) first_level_model = first_level_model.fit(fmri_img, events=events, confounds=confounds) design_matrix = first_level_model.design_matrices_[0] plot_design_matrix(design_matrix) plot_contrast(first_level_model) plt.show() ######################################################################### # Note the five additional columns in the design matrix. # # The effect on the activation maps is complex: auditory/visual effects
def first_level(subject_dic, additional_regressors=None, compcorr=False, smooth=None, surface=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, whetherconfound estimation and removal should be carried out 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'] hfcut = subject_dic['hfcut'] drift_model = subject_dic['drift_model'] tr = subject_dic['TR'] if not surface 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']): # Guessing paradigm from file name # paradigm_id = session_id[:session_id.rfind('_')] #paradigm_id = session_id #for unwanted in ['_ap', '_pa'] + ['_run%d' % d for d in range(10)]: # paradigm_id = paradigm_id.replace(unwanted, '') paradigm_id = _session_id_to_task_id([session_id])[0] if surface: 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(0, (n_scans - 1) * tr, n_scans) if surface: 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, paradigm_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_design_matrix( frametimes, paradigm, hrf_model=hrf_model, drift_model=drift_model, period_cut=hfcut, add_regs=add_regs, add_reg_names=add_reg_names) _, dmtx, names = check_design_matrix(design_matrix) # create the relevant contrasts contrasts = make_contrasts(paradigm_id, names) if surface: subject_session_output_dir = os.path.join( subject_dic['output_dir'], 'res_surf_%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 surface: run_surface_glm( design_matrix, contrasts, fmri_path, subject_session_output_dir) else: z_maps = run_glm( design_matrix, contrasts, fmri_path, mask_img, subject_dic, subject_session_output_dir, tr=tr, 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') # paradigm_dict = paradigm.__dict__ if paradigm is not None else None if paradigm is not None: paradigm_dict = { 'onset': paradigm['onset'].values, 'name': paradigm['name'].values, 'duration': paradigm['duration'].values,} generate_subject_stats_report( stats_report_filename, contrasts, z_maps, mask_img, threshold=3., cluster_th=15, anat=anat_img, anat_affine=anat_img.get_affine(), design_matrices=[design_matrix], subject_id=subject_dic['subject_id'], start_time=start_time, title="GLM for subject %s" % session_id, # additional ``kwargs`` for more informative report # paradigm=paradigm_dict, TR=tr, n_scans=n_scans, hfcut=hfcut, frametimes=frametimes, drift_model=drift_model, hrf_model=hrf_model, ) if not surface: ProgressReport().finish_dir(subject_session_output_dir) print("Statistic report written to %s\r\n" % stats_report_filename)
def first_level(subject_dic, mask_img, compcorr=True, smooth=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, whetherconfound estimation and removal should be carried out or not smooth: float or None, optional, how much the data should spatially smoothed during masking """ import nibabel as nib import numpy as np from nistats.design_matrix import make_design_matrix from nilearn.image import high_variance_confounds import pandas as pd from nistats.first_level_model import FirstLevelModel # experimental paradigm meta-params motion_names = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz'] hrf_model = 'spm' hfcut = subject_dic['hfcut'] drift_model = subject_dic['drift_model'] tr = subject_dic['TR'] for session_id, fmri_path, onset, motion_path in zip( subject_dic['session_id'], subject_dic['func'], subject_dic['onset'], subject_dic['realignment_parameters']): 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(0, (n_scans - 1) * tr, n_scans) confounds = motion confound_names = motion_names 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 paradigm = pd.read_csv(onset, sep='\t') trial_type = paradigm.trial_type.values audio_right_hands = ['audio_right_hand_%d' % i for i in range(5)] audio_left_hands = ['audio_left_hand_%d' % i for i in range(5)] video_right_hands = ['video_right_hand_%d' % i for i in range(5)] video_left_hands = ['video_left_hand_%d' % i for i in range(5)] trial_type[trial_type == 'audio_right_hand'] = audio_right_hands trial_type[trial_type == 'audio_left_hand'] = audio_left_hands trial_type[trial_type == 'video_right_hand'] = video_right_hands trial_type[trial_type == 'video_left_hand'] = video_left_hands # create the design matrix design_matrix = make_design_matrix(frametimes, paradigm, hrf_model=hrf_model, drift_model=drift_model, period_cut=hfcut, add_regs=confounds, add_reg_names=confound_names) # create the relevant contrasts names = design_matrix.columns n_regressors = len(names) interest = audio_right_hands + audio_left_hands + video_right_hands + video_left_hands con = dict([(names[i], np.eye(n_regressors)[i]) for i in range(n_regressors)]) contrasts = dict([(contrast, con[contrast]) for contrast in interest]) 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) design_matrix.to_csv( os.path.join(subject_session_output_dir, 'design_matrix.npz')) fmri_glm = FirstLevelModel(mask=mask_img, t_r=tr, slice_time_ref=.5, smoothing_fwhm=smooth).fit( fmri_path, design_matrices=design_matrix) # compute contrasts for contrast_id, contrast_val in contrasts.iteritems(): print "\tcontrast id: %s" % contrast_id # store stat maps to disk for map_type in ['z_score']: stat_map = fmri_glm.compute_contrast(contrast_val, output_type=map_type) map_dir = os.path.join(subject_session_output_dir, '%s_maps' % map_type) if not os.path.exists(map_dir): os.makedirs(map_dir) map_path = os.path.join(map_dir, '%s.nii.gz' % contrast_id) print "\t\tWriting %s ..." % map_path stat_map.to_filename(map_path)
file_dict, INDI = check_indi(workpath) logging.info('Performing T1 preprocessing') T1prep_dict = FSL_T1_prep(mni152_brain_ff, file_dict) rest_prep_ff, friston24, TR = FSL_EPI_prep(file_dict) epi2std_ff, epi2struct_ff = FSL_EPI2struct(rest_prep_ff, T1prep_dict) # wEPI_ff = FSL_norm(rest_prep_ff,epi2stdb_ff,mni152_brain_ff) wEPI_ff = FSL_fnirt_applywarp(mni152_ff, rest_prep_ff, T1prep_dict['nl_str2stand'], premat_ff=epi2struct_ff) wm_ts = get_confound(wEPI_ff, T1prep_dict['wWM_ffname']) csf_ts = get_confound(wEPI_ff, T1prep_dict['wCSF_ffname']) gb_ts = get_confound(wEPI_ff, T1prep_dict['wbmask_ffname']) constant_ts = np.ones(wm_ts.size) linear_ts = np.arange(0.0,wm_ts.size) compcor5 = high_variance_confounds(wEPI_ff, n_confounds=5, mask_img=T1prep_dict['wWMCSF_ffname']) confound_ff = join(workpath, 'confound.csv') confound_GSR_ff = join(workpath, 'csf_wm_global.csv') fristonstr='' for ii in range(24):fristonstr+='f%s ' % (ii+1) confounds = np.hstack([np.array([csf_ts, wm_ts, constant_ts, linear_ts, linear_ts**2]).T, friston24, compcor5]) np.savetxt(confound_ff, confounds, header='csf wm constant linear quadratic ' + fristonstr + 'compcor1 compcor2 compcor3 compcor4 compcor5', comments='',fmt='%.10f') confounds = np.hstack([np.array([csf_ts, wm_ts,gb_ts,constant_ts, linear_ts, linear_ts**2]).T, friston24, compcor5])
def remove_confounds(timeseries, file): img = nib.load(file) confounds = high_variance_confounds(img, n_confounds=10) clean_timeseries = clean(timeseries, detrend=True, confounds=confounds) return clean_timeseries
# confounds in the data, sue to scanner instabilities (spikes) or # physiological phenomena, such as motion, heart and # respiration-related blood oxygenation flucturations. Side # measurements are sometimes acquired to charcterise these # effects. Here we don't have access to those. What we can do instead # is to estimate confounding effects from the data themselves, using # the compcorr approach, and take those into account in the model. # # For this we rely on the so-called `high_variance_confounds`_ # routine of Nilearn. # # .. _high_variance_confounds: https://nilearn.github.io/modules/generated/nilearn.image.high_variance_confounds.html from nilearn.image import high_variance_confounds confounds = pd.DataFrame(high_variance_confounds(fmri_img, percentile=1)) first_level_model = FirstLevelModel(t_r, hrf_model='spm + derivative', slice_time_ref=0.5) first_level_model = first_level_model.fit(fmri_img, events=events, confounds=confounds) design_matrix = first_level_model.design_matrices_[0] plot_design_matrix(design_matrix) plot_contrast(first_level_model) plt.show() ######################################################################### # Note the five additional columns in the design matrix # # The effect on activation maps is complex: auditory/visual effects # are killed, probably because they were somewhat colinear to the # confounds. On the other hand, some of the maps become cleaner (H-V,
outlier_val = np.genfromtxt(artefact_file) except IOError: outlier_val = np.empty((0)) for index in np.atleast_1d(outlier_val): outlier_vector = np.zeros((confound_len, 1)) outlier_vector[index] = 1 outlier_regressor = np.hstack((outlier_regressor, outlier_vector)) outlier_regressor = outlier_regressor[:,1::] # load motion regressors motion_regressor_12=np.genfromtxt(motion_file_12) #motion_regressor_24=np.genfromtxt(motion_file_24) # extract high variance confounds in wm/csf masks from motion corrected data wm_regressor=high_variance_confounds(moco_nii, mask_img=wm_nii, detrend=True) csf_regressor=high_variance_confounds(moco_nii, mask_img=csf_nii, detrend=True) # extract high variance confounds from unprocessed data highvar_regressor=high_variance_confounds(raw_file, detrend=True) # load compcor regressors #compcor_regressor=np.genfromtxt(compcor_file) # create Nifti Masker for denoising denoiser=NiftiMasker(mask_img=brain_mask, standardize=True, detrend=True, high_pass=0.01, low_pass=0.1, t_r=3.0) # nilearn wmcsf, moco 12 confounds=np.hstack((outlier_regressor,wm_regressor, csf_regressor,motion_regressor_12)) denoised_data=denoiser.fit_transform(moco_file, confounds=confounds) denoised_img=denoiser.inverse_transform(denoised_data)
def main(argv): ## this is input parsing try: opts, args = getopt.getopt(argv, "hi:", ["ifile="]) except getopt.GetoptError: print('single_subject_hitting_time3.py -i <sub_data>') sys.exit(2) for opt, arg in opts: if opt == '-h': print('single_subject_hitting_time3.py -i <sub_data>') sys.exit() elif opt in ("-i", "--ifile"): sub_data = arg print('sub_data is "', sub_data) ## atlas 3 atlas = "Schaefer200Yeo17Pauli" # msdl or haox or mmp schaefer_atlas = datasets.fetch_atlas_schaefer_2018( n_rois=200, yeo_networks=17, resolution_mm=1, data_dir=None, base_url=None, resume=True, verbose=1) #atlas_filename = "MMP1_rois.nii" #Glasser et al., 2016 schaefer_filename = schaefer_atlas.maps schaefer_labels = schaefer_atlas.labels schaefer_masker = NiftiLabelsMasker(labels_img=schaefer_filename, standardize=True, memory='nilearn_cache', verbose=5) pauli_atlas = datasets.fetch_atlas_pauli_2017() pauli_filename = pauli_atlas.maps pauli_labels = pauli_atlas.labels pauli_masker = NiftiMapsMasker(maps_img=pauli_filename, standardize=True, verbose=5) all_labels = np.hstack([schaefer_labels, pauli_labels]) print(all_labels) correlation_measure = ConnectivityMeasure(kind='correlation') #n_rois=len(schaefer_labels) + len(pauli_labels) #p_corr_all = np.zeros([n_rois, n_rois,len(sub_data)]) #H_all = np.zeros([n_rois, n_rois,len(sub_data)]) # generate subject number and position from sub_data subnum = sub_data.split(os.sep)[-4] #subnum_fmt = "{:06}".format(int(subnum)) out_base = os.sep.join(sub_data.split(os.sep)[:-3]) out_dir = out_base + os.sep + "deriv" + os.sep + "snag" if not os.path.exists(out_dir): os.makedirs(out_dir) #extract time series from a atlas(es) file_base = "_".join(sub_data.split(os.sep)[-1].split("_")[:-2]) adj_out_file = out_dir + os.sep + file_base + "_timeseries-corr_" + atlas + "_data_filt" if not (pathlib.Path(adj_out_file).exists()): #func_dir_in = sub_data #+ os.sep + 'restEPI' #directory with func images #funcs_filenames = glob.glob(func_dir_in + os.sep + '*.nii') #find all funcs in this directory confounds = high_variance_confounds(sub_data) #schafer cortical atlas schaefer_time_series = schaefer_masker.fit_transform( sub_data, confounds=confounds) #cortical segments print("schaefer ts shape: ") print(schaefer_time_series.shape) #subcortical atlas pauli_time_series = pauli_masker.fit_transform( sub_data, confounds=confounds) #subccortical segments print("pauli ts shape: ") print(pauli_time_series.shape) #stack time series and determine adjacency matrix from the resulting set of time series full_ts_set = np.hstack((schaefer_time_series, pauli_time_series)) print("concatenated ts shape: ") print(full_ts_set.shape) correlation_matrix = correlation_measure.fit_transform([full_ts_set ])[0] np.savetxt(adj_out_file, correlation_matrix, delimiter=",") print(correlation_matrix.shape[0], correlation_matrix.shape[1]) else: correlation_matrix = genfromtxt( adj_out_file, delimiter=',' ) #load the file if the correlation matrix was pre-computed correlation_matrix = abs( correlation_matrix ) #absolute value to make all transition probabilities positive np.fill_diagonal(correlation_matrix, 0) #set self connections to zero #p_corr_all[:,:,sub_ind] = correlation_matrix.copy() #stack correlation matrices for later analysis #build hitting time matrix H_out_file = out_dir + os.sep + file_base + "_normedH_" + atlas + "_corr" #file where hitting-time matrix will be saved print(H_out_file) if not (pathlib.Path(H_out_file).exists() ): #compute hitting time matrix if it isn't already saved H = hitting_matrix(correlation_matrix) #H_all[:,:,sub_ind] = H np.savetxt(H_out_file, H, delimiter=",") print("saved " + H_out_file)
############################################################################## # Statistical CompCor # ---------------------------------------------- # Retrieve the data from one subject from sammba import data_fetchers test_retest = data_fetchers.fetch_zurich_test_retest(subjects=[1]) fmri_filename = test_retest.func[0] ############################################################################### # We perform a PCA to extract the 98% most variant components. # This is done by the function **nilearn.image.high_variance_confounds**, from nilearn import image hv_array = image.high_variance_confounds(fmri_filename) print('Computed {0} confounds array.'.format(hv_array.shape[1])) ############################################################################### # Do my counfounds model noise properly? Voxel-to-voxel connectivity tells! # ------------------------------------------------------------------------- # Check the relevance of chosen confounds: The distribution of voxel-to-voxel # correlations should be tight and approximately centered to zero. # # Compute voxel-wise time series without confounds removal, using NiftiMasker. from nilearn.input_data import NiftiMasker brain_masker = NiftiMasker(detrend=True, memory='nilearn_cache', verbose=1) timeseries_raw = brain_masker.fit_transform(fmri_filename) ###############################################################################
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)
def extract_ts_parc(self): """ API for employing Nilearn's NiftiLabelsMasker to extract fMRI time-series data from spherical ROI's based on a given 3D atlas image of integer-based voxel intensities. The resulting time-series can then optionally be resampled using circular-block bootrapping. The final 2D m x n array is ultimately saved to file in .npy format. """ import pandas as pd from nilearn import input_data from pynets.fmri.estimation import fill_confound_nans self._parcel_masker = input_data.NiftiLabelsMasker( labels_img=self._net_parcels_map_nifti, background_label=0, standardize=True, smoothing_fwhm=float(self.smooth), low_pass=self.low_pass, high_pass=self.hpass, detrend=self._detrending, t_r=self._t_r, verbose=2, resampling_target="labels", dtype="auto", mask_img=self._mask_img, strategy=self.signal) if self.conf is not None: import os confounds = pd.read_csv(self.conf, sep="\t") cols = [ i for i in confounds.columns if 'motion_outlier' in i or i == 'framewise_displacement' or i == 'white_matter' or i == 'csf' or i == 'std_dvars' or i == 'rot_z' or i == 'rot_y' or i == 'rot_x' or i == 'trans_z' or i == 'trans_y' or i == 'trans_x' or 'non_steady_state_outlier' in i ] if len(confounds.index) == self._func_img.shape[-1]: if confounds.isnull().values.any(): conf_corr = fill_confound_nans(confounds, self.dir_path) conf_corr_df = pd.read_csv(conf_corr, sep="\t") cols = [i for i in cols if i in conf_corr_df.columns] self.ts_within_nodes = self._parcel_masker.fit_transform( self._func_img.slicer[:, :, :, 5:], confounds=conf_corr_df.loc[5:][cols].values) os.remove(conf_corr) else: self.ts_within_nodes = self._parcel_masker.fit_transform( self._func_img.slicer[:, :, :, 5:], confounds=pd.read_csv(self.conf, sep="\t").loc[5:][cols].values) else: from nilearn.image import high_variance_confounds print(f"Shape of confounds ({len(confounds.index)}) does not" f" equal the number of volumes " f"({self._func_img.shape[-1]}) in the time-series") self.ts_within_nodes = self._parcel_masker.fit_transform( self._func_img.slicer[:, :, :, 5:], confounds=pd.DataFrame( high_variance_confounds(self._func_img, percentile=1)).loc[5:].values) else: from nilearn.image import high_variance_confounds self.ts_within_nodes = self._parcel_masker.fit_transform( self._func_img.slicer[:, :, :, 5:], confounds=pd.DataFrame( high_variance_confounds(self._func_img, percentile=1)).loc[5:].values) self._func_img.uncache() if self.ts_within_nodes is None: raise RuntimeError("\nTime-series extraction failed!") else: self.node_radius = "parc" return
out_dir= out_base + os.sep + "deriv"+ os.sep + "snag" if not os.path.exists(out_dir): os.makedirs(out_dir) #extract time series from a atlas(es) file_base= "_".join(sub_data.split(os.sep)[-1].split("_")[:-2]) adj_out_file = out_dir + os.sep + file_base + "_timeseries-corr_" + atlas + "_data_filt" if not(pathlib.Path(adj_out_file).exists()): func_dir_in = sub_data #+ os.sep + 'restEPI' #directory with func images #funcs_filenames = glob.glob(func_dir_in + os.sep + '*.nii') #find all funcs in this directory confounds = high_variance_confounds(sub_data) #schafer cortical atlas schaefer_time_series = schaefer_masker.fit_transform(sub_data, confounds=confounds) #cortical segments print("schaefer ts shape: ") print(schaefer_time_series.shape) #subcortical atlas pauli_time_series = pauli_masker.fit_transform(sub_data, confounds=confounds) #subccortical segments print("pauli ts shape: ") print(pauli_time_series.shape) #stack time series and determine adjacency matrix from the resulting set of time series full_ts_set = np.hstack((schaefer_time_series, pauli_time_series)) print("concatenated ts shape: ") print(full_ts_set.shape) correlation_matrix = correlation_measure.fit_transform([full_ts_set])[0] np.savetxt(adj_out_file, correlation_matrix, delimiter=",")
def nilearn_denoise(in_file, gm_mask, wm_mask, csf_mask, motreg_file, outlier_file, bandpass, tr ): """Clean time series using Nilearn high_variance_confounds to extract CompCor regressors and NiftiMasker for regression of all nuissance regressors, detrending, normalziation and bandpass filtering. """ import numpy as np import nibabel as nb import os from nilearn.image import high_variance_confounds from nilearn.input_data import NiftiMasker from nipype.utils.filemanip import split_filename #import pdb print 'import complete' # reload niftis to round affines so that nilearn doesn't complain wm_nii=nb.Nifti1Image(nb.load(wm_mask).get_data(), np.around(nb.load(wm_mask).get_affine(), 2), nb.load(wm_mask).get_header()) print('loaded wm :\n\t{0}').format(wm_mask)# csf_nii=nb.Nifti1Image(nb.load(csf_mask).get_data(), np.around(nb.load(csf_mask).get_affine(), 2), nb.load(csf_mask).get_header()) csf_nii=nb.Nifti1Image(nb.load(csf_mask).get_data(), np.around(nb.load(wm_mask).get_affine(), 2), nb.load(csf_mask).get_header()) print('loaded csf :\n\t{0}').format(csf_mask) time_nii=nb.Nifti1Image(nb.load(in_file).get_data(), np.around(nb.load(wm_mask).get_affine(), 2), nb.load(in_file).get_header()) print 'timeseries' print 'niftis reloaded' # infer shape of confound array # not ideal confound_len = nb.load(in_file).get_data().shape[3] print 'infer shape of confound array complete' # create outlier regressors outlier_regressor = np.empty((confound_len,1)) try: outlier_val = np.genfromtxt(outlier_file) except IOError: outlier_val = np.empty((0)) for index in np.atleast_1d(outlier_val): outlier_vector = np.zeros((confound_len, 1)) outlier_vector[index] = 1 outlier_regressor = np.hstack((outlier_regressor, outlier_vector)) outlier_regressor = outlier_regressor[:,1::] print 'outlier regressors created' # load motion regressors motion_regressor=np.genfromtxt(motreg_file) print 'motion regressors loaded' # extract high variance confounds in wm/csf masks from motion corrected data wm_regressor=high_variance_confounds(time_nii, mask_img=wm_nii, detrend=True) csf_regressor=high_variance_confounds(time_nii, mask_img=csf_nii, detrend=True) print 'high variance confounds extracted' # create Nifti Masker for denoising denoiser=NiftiMasker(mask_img=gm_mask, standardize=True, detrend=True, high_pass=bandpass[1], low_pass=bandpass[0], t_r=tr) print 'NiftiMasker created' #save time_nii to see if its headers fault or nilearn nb.save(time_nii, "time_nii.nii.gz") # nb.save(time_nii, os.path.join('build','time_nii.nii.gz')) # nb.save(time_nii,motion_regressors) print 'saved1' # denoise and return denoise data to img #pdb.set_trace() confounds=np.hstack((outlier_regressor,wm_regressor, csf_regressor, motion_regressor)) denoised_data=denoiser.fit_transform(in_file, confounds=confounds) denoised_img=denoiser.inverse_transform(denoised_data) print 'denoised' # save _, base, _ = split_filename(in_file) img_fname = base + '_denoised.nii.gz' nb.save(denoised_img, img_fname) confound_fname = os.path.join(os.getcwd(), "all_confounds.txt") np.savetxt(confound_fname, confounds, fmt="%.10f") print 'saved' return os.path.abspath(img_fname), confound_fname
def make_correlation_matrix(path_to_fmriprep_data, path_to_save_connectivity_matrices, subject_name=False, path_to_save_ts=False, atlas='aal'): """ Process the fmriprep preprocessed functional MRI time-series into 2D correlation matrix as DataFrame using Nilearn lib. Takes `fmriprep/preproc` file as input, frequently with suffix "MNI152NLin2009cAsym_preproc.nii.gz". Saves in dedicated folder `path_to_save_connectivity_matrices`. Atlas: 'aal' or 'cc200' """ import os import pandas as pd import numpy as np import nilearn from nilearn import datasets from nilearn.image import concat_imgs from nilearn.input_data import NiftiLabelsMasker from nilearn.image import high_variance_confounds from nilearn.connectome import ConnectivityMeasure tr = tr_extractor(path_to_fmriprep_data) if subject_name == False: subject_name = path_to_fmriprep_data.split('/')[-1][4:11] if atlas == 'aal': dataset = datasets.fetch_atlas_aal(version='SPM12', data_dir='./datadir/', url=None, resume=True, verbose=0) atlas_filename = dataset.maps labels = dataset.labels elif atlas == 'cc200': dataset = datasets.fetch_atlas_craddock_2012(data_dir='./datadir/', url=None, resume=True, verbose=0) atlas_filename = './datadir/craddock_2012/cc200_roi_atlas.nii.gz' labels = list( pd.read_csv( '../data_preprocessing/datadir/craddock_2012/CC200_ROI_labels.csv' )['ROI number']) else: print('Atlas name is not recognized.') correlation_measure = ConnectivityMeasure(kind='correlation') img = concat_imgs(path_to_fmriprep_data, auto_resample=True, verbose=0) atlas = nilearn.image.resample_to_img(atlas_filename, img, interpolation='nearest', copy=True, order='F', clip=False) # filtering masker = NiftiLabelsMasker(labels_img=atlas, standardize=True, detrend=True, low_pass=0.08, high_pass=0.009, t_r=tr, memory='nilearn_cache', memory_level=1, verbose=0) confounds = high_variance_confounds(img, 1) time_series = masker.fit_transform(img, confounds) # Saves time series, for each ROI confound if path_to_save_ts: os.makedirs(path_to_save_ts, exist_ok=True) np.save(path_to_save_ts + '/' + subject_name, time_series) correlation_matrix = correlation_measure.fit_transform([time_series])[0] np.fill_diagonal(correlation_matrix, 1) df = pd.DataFrame(correlation_matrix) # Saves connectivity matrix os.makedirs(path_to_save_connectivity_matrices, exist_ok=True) output_path = os.path.join(path_to_save_connectivity_matrices, subject_name) df.to_csv(output_path + '.csv', sep=',') # print ('TR: ', tr, ' subject:', subject_name)