14.2.1. Reynolds et al. (2024). Processing, evaluating and understanding FMRI data with afni_proc.py¶
Introduction¶
Here we present commands used in the following paper:
- Reynolds RC, Glen DR, Chen G, Saad ZS, Cox RW, Taylor PA (2024). Processing, evaluating and understanding FMRI data with afni_proc.py. arXiv:2406.05248 [q-bio.NC]
Abstract: FMRI data are noisy, complicated to acquire, and typically go through many steps of processing before they are used in a study or clinical practice. Being able to visualize and understand the data from the start through the completion of processing, while being confident that each intermediate step was successful, is challenging. AFNI’s afni_proc.py is a tool to create and run a processing pipeline for FMRI data. With its flexible features, afni_proc.py allows users to both control and evaluate their processing at a detailed level. It has been designed to keep users informed about all processing steps: it does not just process the data, but first outputs a fully commented processing script that the users can read, query, interpret and refer back to. Having this full provenance is important for being able to understand each step of processing; it also promotes transparency and reproducibility by keeping the record of individual-level processing and modeling specifics in a single, shareable place. Additionally, afni_proc.py creates pipelines that contain several automatic self-checks for potential problems during runtime. The output directory contains a dictionary of relevant quantities that can be programmatically queried for potential issues and a systematic, interactive quality control (QC) HTML. All of these features help users evaluate and understand their data and processing in detail. We describe these and other aspects of afni_proc.py here using a set of task-based and resting state FMRI example commands.
Study keywords: FMRI, EPI, MPRAGE, pipeline, reproducibility, understanding, quality control, visualization, multi-echo, surface processing
Main programs:
afni_proc.py
, sswarper2
, open_apqc.py
,
ap_run_simple_rest.tcsh
, ap_run_simple_rest_me.tcsh
Download scripts¶
Since there are several scripts, we recommend downloading directly from GitHub, such as by copy+pasting this into a terminal:
git clone https://github.com/afni/apaper_afni_proc.git
View scripts¶
These are just a couple examples of the “Desktop” scripts on GitHub, please see above for downloading all scripts (both the “Desktop” and “Biowulf” versions).
do_20_ap_simple.tcsh
¶
This script contains the “simple” afni_proc.py wrapper for ME-FMRI processing.
1#!/bin/tcsh
2
3# AP simple: run afni_proc.py for full FMRI processing (for initial QC)
4# -> run the ME-FMRI simple command here
5
6# Process a single subj+ses pair.
7
8# This is a Desktop script. Run it via swarm (see partner run*.tcsh).
9
10
11# initial exit code; we don't exit at fail, to copy partial results back
12set ecode = 0
13
14# ---------------------------------------------------------------------------
15# top level definitions (constant across demo)
16# ---------------------------------------------------------------------------
17
18# labels
19set subj = $1
20set ses = $2
21set ap_label = 20_ap_simple
22
23
24# upper directories
25set dir_inroot = ${PWD:h} # one dir above scripts/
26set dir_log = ${dir_inroot}/logs
27set dir_basic = ${dir_inroot}/data_00_basic
28set dir_fs = ${dir_inroot}/data_12_fs
29set dir_ssw = ${dir_inroot}/data_13_ssw
30set dir_physio = ${dir_inroot}/data_14_physio
31set dir_ap = ${dir_inroot}/data_${ap_label}
32
33# subject directories
34set sdir_basic = ${dir_basic}/${subj}/${ses}
35set sdir_func = ${sdir_basic}/func
36set sdir_anat = ${sdir_basic}/anat
37set sdir_fs = ${dir_fs}/${subj}/${ses}
38set sdir_suma = ${sdir_fs}/SUMA
39set sdir_ssw = ${dir_ssw}/${subj}/${ses}
40set sdir_physio = ${dir_physio}/${subj}/${ses}
41set sdir_ap = ${dir_ap}/${subj}/${ses}
42
43# supplementary directories and info
44set dir_suppl = ${dir_inroot}/supplements
45set template = ${dir_suppl}/MNI152_2009_template_SSW.nii.gz
46
47# set output directory
48set sdir_out = ${sdir_ap}
49set lab_out = AP
50
51# --------------------------------------------------------------------------
52# data and control variables
53# --------------------------------------------------------------------------
54
55setenv AFNI_COMPRESSOR GZIP
56
57# dataset inputs
58set task_label = task-rest_run-1
59
60set epi_radix = ${sdir_func}/${subj}_${ses}
61set dset_epi_e2 = ( ${epi_radix}_${task_label}_echo-2_bold.nii* )
62set dsets_epi_me = ( ${epi_radix}_${task_label}_echo-?_bold.nii* )
63set me_times = ( 12.5 27.6 42.7 )
64
65set dset_anat_00 = ${sdir_anat}/${subj}_${ses}_mprage_run-1_T1w.nii.gz
66
67# control variables
68set nt_rm = 4 # number of time points to remove at start
69#set blur_size = 6 # blur size to apply
70#set final_dxyz = 3 # final voxel size (isotropic dim)
71#set cen_motion = 0.2 # censor threshold for motion (enorm)
72#set cen_outliers = 0.05 # censor threshold for outlier frac
73
74
75# check available N_threads and report what is being used
76set nthr_avail = `afni_system_check.py -disp_num_cpu`
77set nthr_using = `afni_check_omp`
78
79echo "++ INFO: Using ${nthr_using} of available ${nthr_avail} threads"
80
81
82# ---------------------------------------------------------------------------
83# run programs
84# ---------------------------------------------------------------------------
85
86# make output directory and go to it
87\mkdir -p ${sdir_out}
88cd ${sdir_out}
89
90# create command script
91set run_script = ap.cmd.${subj}
92
93cat << EOF >! ${run_script}
94
95# AP, run simple
96#
97# multi-echo FMRI, simple processing for initial QC
98# anatomical has skull on
99
100ap_run_simple_rest_me.tcsh \
101 -run_ap \
102 -subjid ${subj} \
103 -nt_rm ${nt_rm} \
104 -anat ${dset_anat_00} \
105 -epi_me_run ${dsets_epi_me} \
106 -echo_times ${me_times} \
107 -template ${template}
108
109EOF
110
111if ( ${status} ) then
112 set ecode = 1
113 goto COPY_AND_EXIT
114endif
115
116
117# execute AP command to make processing script
118tcsh -xef ${run_script} |& tee output.ap.cmd.${subj}
119
120if ( ${status} ) then
121 set ecode = 2
122 goto COPY_AND_EXIT
123endif
124
125
126# execute the proc script, saving text info
127time tcsh -xef proc.${subj} |& tee output.proc.${subj}
128
129if ( ${status} ) then
130 set ecode = 3
131 goto COPY_AND_EXIT
132endif
133
134echo "++ FINISHED ${lab_out}"
135
136# ---------------------------------------------------------------------------
137
138COPY_AND_EXIT:
139
140
141if ( ${ecode} ) then
142 echo "++ BAD FINISH: ${lab_out} (ecode = ${ecode})"
143else
144 echo "++ GOOD FINISH: ${lab_out}"
145endif
146
147exit ${ecode}
do_23_ap_ex3_vol.tcsh
¶
1#!/bin/tcsh
2
3# AP-3: run afni_proc.py for full FMRI processing (Example 3)
4
5# Process a single subj+ses pair.
6
7# This is a Desktop script. Run it via swarm (see partner run*.tcsh).
8
9
10# initial exit code; we don't exit at fail, to copy partial results back
11set ecode = 0
12
13# ---------------------------------------------------------------------------
14# top level definitions (constant across demo)
15# ---------------------------------------------------------------------------
16
17# labels
18set subj = $1
19set ses = $2
20set ap_label = 23_ap_ex3_vol
21
22
23# upper directories
24set dir_inroot = ${PWD:h} # one dir above scripts/
25set dir_log = ${dir_inroot}/logs
26set dir_basic = ${dir_inroot}/data_00_basic
27set dir_fs = ${dir_inroot}/data_12_fs
28set dir_ssw = ${dir_inroot}/data_13_ssw
29set dir_physio = ${dir_inroot}/data_14_physio
30set dir_ap = ${dir_inroot}/data_${ap_label}
31
32# subject directories
33set sdir_basic = ${dir_basic}/${subj}/${ses}
34set sdir_func = ${sdir_basic}/func
35set sdir_anat = ${sdir_basic}/anat
36set sdir_fs = ${dir_fs}/${subj}/${ses}
37set sdir_suma = ${sdir_fs}/SUMA
38set sdir_ssw = ${dir_ssw}/${subj}/${ses}
39set sdir_physio = ${dir_physio}/${subj}/${ses}
40set sdir_ap = ${dir_ap}/${subj}/${ses}
41
42# supplementary directories and info
43set dir_suppl = ${dir_inroot}/supplements
44set template = ${dir_suppl}/MNI152_2009_template_SSW.nii.gz
45
46# set output directory
47set sdir_out = ${sdir_ap}
48set lab_out = AP
49
50# --------------------------------------------------------------------------
51# data and control variables
52# --------------------------------------------------------------------------
53
54setenv AFNI_COMPRESSOR GZIP
55
56# dataset inputs
57set task_label = task-rest_run-1
58
59set epi_radix = ${sdir_func}/${subj}_${ses}
60set dset_epi = ( ${epi_radix}_${task_label}_echo-2_bold.nii* ) # 2nd echo
61set dsets_epi_me = ( ${epi_radix}_${task_label}_echo-?_bold.nii* )
62set me_times = ( 12.5 27.6 42.7 )
63
64set blip_radix = ${sdir_func}/${subj}_${ses}_acq-blip
65set epi_forward = "${blip_radix}_dir-match_run-1_bold.nii.gz[0]"
66set epi_reverse = "${blip_radix}_dir-opp_run-1_bold.nii.gz[0]"
67
68set physio_radix = ${sdir_physio}/${subj}_${ses}
69set physio_regs = ${physio_radix}_${task_label}_physio_slibase.1D
70
71set anat_cp = ( ${sdir_ssw}/anatSS.${subj}.nii* )
72set anat_skull = ( ${sdir_ssw}/anatU.${subj}.nii* )
73
74set dsets_NL_warp = ( ${sdir_ssw}/anatQQ.${subj}.nii* \
75 ${sdir_ssw}/anatQQ.${subj}.aff12.1D \
76 ${sdir_ssw}/anatQQ.${subj}_WARP.nii* )
77
78set roi_all_2009 = ${sdir_suma}/aparc.a2009s+aseg_REN_all.nii.gz
79set roi_gmr_2009 = ${sdir_suma}/aparc.a2009s+aseg_REN_gmrois.nii.gz
80set roi_gmr_2000 = ${sdir_suma}/aparc+aseg_REN_gmrois.nii.gz
81set roi_FSvent = ${sdir_suma}/fs_ap_latvent.nii.gz
82set roi_FSWe = ${sdir_suma}/fs_ap_wm.nii.gz
83
84# control variables
85set nt_rm = 4 # number of time points to remove at start
86set blur_size = 5 # blur size in mm, usually based of voxel size
87set final_dxyz = 3 # final voxel size (isotropic dim)
88set cen_motion = 0.2 # censor threshold for motion (enorm)
89set cen_outliers = 0.05 # censor threshold for outlier frac
90
91
92# check available N_threads and report what is being used
93set nthr_avail = `afni_system_check.py -disp_num_cpu`
94set nthr_using = `afni_check_omp`
95
96echo "++ INFO: Using ${nthr_using} of available ${nthr_avail} threads"
97
98
99# ---------------------------------------------------------------------------
100# run programs
101# ---------------------------------------------------------------------------
102
103# make output directory and go to it
104\mkdir -p ${sdir_out}
105cd ${sdir_out}
106
107# create command script
108set run_script = ap.cmd.${subj}
109
110cat << EOF >! ${run_script}
111
112# AP, Example 3: for voxelwise analysis
113#
114# single echo FMRI
115# volumetric, voxelwise analysis, warped to standard space
116# include physio regressors
117# include follower GM-ROIs from FS 2009 parc
118
119# we do NOT include bandpassing here (see comments in text)
120
121afni_proc.py \
122 -subj_id ${subj} \
123 -dsets ${dset_epi} \
124 -copy_anat ${anat_cp} \
125 -anat_has_skull no \
126 -anat_follower anat_w_skull anat ${anat_skull} \
127 -anat_follower_ROI aagm09 anat ${roi_gmr_2009} \
128 -anat_follower_ROI aegm09 epi ${roi_gmr_2009} \
129 -blocks ricor tshift align tlrc volreg mask blur \
130 scale regress \
131 -radial_correlate_blocks tcat volreg regress \
132 -tcat_remove_first_trs ${nt_rm} \
133 -ricor_regs ${physio_regs} \
134 -ricor_regs_nfirst ${nt_rm} \
135 -ricor_regress_method per-run \
136 -align_unifize_epi local \
137 -align_opts_aea -cost lpc+ZZ -giant_move -check_flip \
138 -tlrc_base ${template} \
139 -tlrc_NL_warp \
140 -tlrc_NL_warped_dsets ${dsets_NL_warp} \
141 -volreg_align_to MIN_OUTLIER \
142 -volreg_align_e2a \
143 -volreg_tlrc_warp \
144 -volreg_warp_dxyz ${final_dxyz} \
145 -volreg_compute_tsnr yes \
146 -mask_epi_anat yes \
147 -blur_size ${blur_size} \
148 -regress_motion_per_run \
149 -regress_make_corr_vols aegm09 \
150 -regress_censor_motion ${cen_motion} \
151 -regress_censor_outliers ${cen_outliers} \
152 -regress_apply_mot_types demean deriv \
153 -regress_est_blur_epits \
154 -regress_est_blur_errts \
155 -html_review_style pythonic
156
157EOF
158
159if ( ${status} ) then
160 set ecode = 1
161 goto COPY_AND_EXIT
162endif
163
164
165# execute AP command to make processing script
166tcsh -xef ${run_script} |& tee output.ap.cmd.${subj}
167
168if ( ${status} ) then
169 set ecode = 2
170 goto COPY_AND_EXIT
171endif
172
173
174# execute the proc script, saving text info
175time tcsh -xef proc.${subj} |& tee output.proc.${subj}
176
177if ( ${status} ) then
178 set ecode = 3
179 goto COPY_AND_EXIT
180endif
181
182echo "++ FINISHED ${lab_out}"
183
184# ---------------------------------------------------------------------------
185
186COPY_AND_EXIT:
187
188
189if ( ${ecode} ) then
190 echo "++ BAD FINISH: ${lab_out} (ecode = ${ecode})"
191else
192 echo "++ GOOD FINISH: ${lab_out}"
193endif
194
195exit ${ecode}