Dear AFNI experts,
I am in the process of inspecting the QC html output from subject-level preprocessing and analysis of an fMRI dataset using afni_proc.py. I would like to obtain the percentage of censored TRs in each of my task conditions. However, I have noticed what appears to be a strange discrepancy in the values provided in the censor fraction warnings section of the output, which lead me to believe that I either don’t understand the outlier volume censoring process or I have misspecified something in my analysis.
In a nutshell, I have an blocked-design fMRI task with 5 task regressors, which are specified with timing files and regress_basis_multi in afni_proc.py. Rest blocks are not modeled. I am using the default censor motion and censor outlier values from the Example 6b of afni_proc.py documentation. My fMRI scan contains 403 volumes. When I inspect the QC html output (generated by html_review_style pythonic), the General censor fraction warnings tells me the number of censored TRs/volumes out of my total 403 volumes in my scan. However, when I look at the Censor fraction warnings (per stim), the total TRs for each task regressor exceeds the number of TRs that should be associated with each task condition, and the sum of TRs across my 5 task regressors exceeds the 403 volumes in my scan. Additionally, the number of censored TRs per stim exceeds the censored TRs listed in the total General censor fraction warnings output.
I have confirmed that my timing files are accurate, and the X-matrix looks consistent with my timing files. I’m therefore not sure what is happening here. How is afni_proc.py assigning the TRs to different task regressors?
As a side question, I was hoping someone could clarify whether for each TR that exceeds a motion or outlier censor threshold, does afni censor just that TR or the pre/post TR as well?
The basic aspect that might not be clear is that the censor fractions are not based on stimulus timing, but on stimulus response timing. 3dDeconvolve writes a regression matrix of idealized BOLD response curves (or whatever one asks for), and it is the censored fractions of these curves that are reported with “num TRs censored per stim”. Note that “per stim” is really space-saving shorthand for either per regressor or per stimulus response, say. The fraction is with respect to the number of time points that a single regressor is non-zero, not the number of time points that are simply part of the stimulation time.
Even if the stimuli do not overlap, even per TR, the response curves typically do, and quite a bit. Add up the number of time points with non-zero regressor values, and it is often 5 to 20 times the number of time points.
Consider this, though the descriptions are short:
Regarding censoring singly or in pairs, the default for afni_proc.py is for outlier censoring to be only for those specific time points, however motion censoring comes in pairs. If nothing else, that is because motion censoring is based on the difference in position between 2 adjacent time points, and the program cannot tell during which the motion actually happened (possibly during one, possibly during both, almost impossibly between them).
Does this seem reasonable?
Thank you for these clarifications, I understand much better now. If the number of TRs per stim are based on stimulus response timing/BOLD response curves and therefore don’t reflect the actual timing of each task condition, is there a way estimate how much actual scanning time has been censored per task condition?
There is no automatic implementation of this, but it would be fairly easy to do using “timing_tool.py -timing_to_1D”.
See example 6a from “timing_tool.py -help”.
Then see an application of this in your @ss_review_basic script (search for “report per-stim censoring”).
How does that seem?
Thank you, Rick. I’ll try that out!