Last active
June 3, 2020 14:01
-
-
Save emdupre/dad8c4f27fa992d02fd9a9292b4bbb66 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import numpy as np | |
| import pandas as pd | |
| import nibabel as nib | |
| from pathlib import Path, PurePath | |
| from nilearn import image | |
| from numpy.lib import recfunctions | |
| from nilearn.input_data import NiftiMasker | |
| from nistats.first_level_model import FirstLevelModel | |
| """ | |
| Utilities for postprocessing the data. | |
| """ | |
| def _subset_confounds(tsv): | |
| """ | |
| Only retain those confounds listed in `keep_confounds` | |
| Parameters | |
| ---------- | |
| tsv: str | |
| Local file path to the fMRIPrep generated confound files | |
| """ | |
| keep_confounds = ['trans_x', 'trans_y', 'trans_z', | |
| 'rot_x', 'rot_y', 'rot_z'] | |
| # load in tsv and subset to only include our desired regressors | |
| tsv = str(tsv) | |
| confounds = np.recfromcsv(tsv, delimiter='\t') | |
| selected_confounds = confounds[keep_confounds] | |
| return selected_confounds | |
| def _relabel_wm_events(events): | |
| """ | |
| Relabels trial types for working memory (WM) events, so that we will | |
| decode on object category rather than n-back level. | |
| Parameters | |
| ---------- | |
| events: str | |
| File-path to a BIDS-formatted events.tsv file in the CNeuroMod | |
| project | |
| """ | |
| df = pd.read_table(events) | |
| category = df.trial_type.str.split('_', expand=True)[1] | |
| df.trial_type = category | |
| return df | |
| def _generate_beta_maps(scans, confounds, events, conditions, mask, fname): | |
| """ | |
| Generates beta-maps for use in decoding | |
| Parameters | |
| ---------- | |
| scans: list | |
| A list of Niimg-like objects or file paths for the | |
| appropriate BOLD files collected during the task | |
| confounds: list | |
| Any confounds to correct for in the cleaned data set | |
| events: list | |
| A list of pd.DataFrames or file paths for BIDS-formatted | |
| events.tsv files | |
| conditions: list | |
| A list of conditions for which to generate beta maps. | |
| Must correspond to trial_types in provided events | |
| mask: str | |
| The mask within which to process data | |
| fname: str | |
| The filename with which to save the resulting maps. | |
| """ | |
| if len(scans) != len(events): | |
| err_msg = ("Number of event files does not match the " + | |
| "number of provided BOLD files. Please re-confirm the " + | |
| "file listings.") | |
| raise ValueError(err_msg) | |
| glm = FirstLevelModel(mask_img=mask, t_r=1.49, high_pass=0.01, | |
| smoothing_fwhm=5, standardize=True) | |
| z_maps, condition_idx, session_idx = [], [], [] | |
| for scan, event, confound in zip(scans, events, confounds): | |
| session = PurePath(scan).parts[2] # This is poorly designed, liable to break | |
| glm.fit(run_imgs=scan, events=event, confounds=confound) | |
| for condition in conditions: | |
| z_maps.append(glm.compute_contrast(condition)) | |
| condition_idx.append(condition) | |
| session_idx.append(session) | |
| sid = fname.split('_')[0] # safe since we set the filename | |
| nib.save(image.concat_imgs(z_maps), fname) | |
| np.savetxt('{}_labels.csv'.format(sid), condition_idx, fmt='%s') | |
| np.savetxt('{}_runs.csv'.format(sid), session_idx, fmt='%s') | |
| def postproc_task(subject, task_label, tpl_mask): | |
| """ | |
| Parameters | |
| ---------- | |
| subject: str | |
| The full subject identifier, e.g. 'sub-01' | |
| task_label: str | |
| The task label used in naming the files, dropping the 'task-' key, | |
| e.g., 'wm' | |
| tpl_mask: str | |
| The local file path to the grey matter mask derived from | |
| the template | |
| """ | |
| func = 'space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz' | |
| regr = 'desc-confounds_regressors.tsv' | |
| scans = sorted(Path('derivatives', 'fmriprep', subject).rglob( | |
| '*_task-{}*{}'.format(task_label, func))) | |
| regressors = sorted(Path('derivatives', 'fmriprep', subject).rglob( | |
| '*_task-{}*{}'.format(task_label, regr))) | |
| events = sorted(Path(subject).rglob( | |
| '*_task-{}*events.tsv'.format(task_label))) | |
| scans = [str(s) for s in scans] | |
| confounds = [pd.DataFrame.from_records(_subset_confounds(r)) | |
| for r in regressors] | |
| # we know that sub-05 only has nine sessions of the WM task | |
| # so we'll subset all subjects to the first 9 runs for balanced data | |
| # availability. This can be removed later once additional data is collected | |
| scans = scans[:9] | |
| confounds = confounds[:9] | |
| events = events[:9] | |
| if task_label == 'wm': | |
| events = [_relabel_wm_events(e) for e in events] | |
| else: | |
| events = [pd.read_table(e) for e in events] | |
| _generate_beta_maps( | |
| scans=scans, confounds=confounds, events=events, | |
| conditions=['body', 'face', 'place', 'tools'], | |
| mask=tpl_mask, fname='{}_task-{}_{}'.format( | |
| subject, task_label, func.replace('preproc', 'postproc'))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment