9 Tutorial Chapter 3: Read the fMRIPrep HTML report + decide inclusion
Time: 5-15 minutes per subject (real-world rate, after some practice). Prereqs: Chapter 2 done (you have a derivatives/fmriprep/sub-08.html).
This chapter is the most important one for manuscript credibility. It maps onto Andy’s Brain Book Tutorial #3 (“Examining Preprocessed Data”) but also adds our HALFpipe-inspired QC rater that turns “I looked at the reports” into a machine-readable inclusion TSV.
9.1 1. Open the HTML report
xdg-open data/ds000102/derivatives/fmriprep/sub-08.html # Linux
open data/ds000102/derivatives/fmriprep/sub-08.html # macOSOr just navigate to the file in your browser.
9.2 2. The 6 panels you must check
In order, top to bottom:
9.2.1 2a. Anatomical brain mask
What you see: Outline of the skull-stripped brain on each slice.
What good looks like: - Mask follows the brain’s outer surface, not the skull. - No “holes” mid-brain (those mean brain extraction ate signal). - Internal structures (ventricles, sulci) are clearly inside the mask.
What bad looks like: - Mask cuts through cortex (e.g. brain stem clipped, frontal pole excluded). - Mask leaks into skull/eyes/dura — common on sub-08’s slice 12 in our experience.
Decision: Rate as good/uncertain/bad for the skull_strip check.
9.2.2 2b. T1 → MNI normalization (GIF)
What you see: A GIF that toggles between the subject’s T1 and the MNI152 template, with a contour overlay showing where they disagree.
What good looks like: - Sulci and gyri match up across the toggle. - Ventricles in the same location. - Maybe a small (<5 mm) edge mismatch, especially anterior pole.
What bad looks like: - Whole-brain shift (≥10 mm). - Cortical folds rotated/sheared. - Ventricle position swapped across hemispheres.
Decision: Rate the t1_to_mni check.
9.2.3 2c. BOLD → T1 alignment (GIF)
What you see: GIF toggling between EPI (BOLD) and T1, contour overlay.
What good looks like: EPI gyri sit on T1 gyri, ventricles overlap, white-matter contour follows EPI signal boundaries.
What bad looks like: EPI shifted ≥3 mm in any direction; “checkerboard” misalignment from inhomogeneity-related distortion.
Decision: Rate the epi_to_t1 check.
9.2.4 2d. CompCor masks
What you see: Outlines of aCompCor (anatomy-based) and tCompCor (temporal) masks overlaid on the EPI.
What good looks like: aCompCor sits in white-matter + CSF, excluding grey matter. tCompCor catches high-variance voxels near edges (susceptibility-prone).
What bad looks like: aCompCor leaking into cortex (would remove neural signal as confound), or covering most of the brain (too liberal).
Decision: Rate the compcor_components check.
9.2.5 2e. Carpet plot
What you see: Voxels × TR matrix, color = signal intensity (z-scored). Below it: framewise displacement (FD) plot, DVARS plot, maybe physiological regressors.
What good looks like: - Most rows look like a textured grey carpet. - FD plot stays under 0.5 mm except for occasional spikes. - No “stripe” patterns vertically (would indicate motion-driven global signal swings).
What bad looks like: - Vertical stripes correlating with FD spikes (motion is contaminating signal). - Whole rows of bright/dark bands (common in subjects who fell asleep — physiological). - FD trace constantly above 0.5 mm.
Decision: Rate the carpet_correlation check.
9.2.6 2f. EPI → MNI normalization
What you see: EPI overlaid on MNI152 atlas, similar to 2b.
What good looks like: Same standards as 2b. EPI is lower resolution, so expect slightly more edge mismatch.
What bad looks like: Same as 2b but more severe (since EPI → MNI goes through both EPI → T1 and T1 → MNI, errors compound).
Decision: Rate the epi_normalization check.
9.3 3. Generate the QC rater for the cohort
Once you’ve looked at all subjects’ reports (or at least sub-08 for this tutorial), generate the rater:
make qc-rater \
SUBJECTS="sub-08 sub-09 sub-10" \
OUT=data/ds000102/derivatives/qc_rater.html
xdg-open data/ds000102/derivatives/qc_rater.htmlIn the browser: 1. For each subject row, click ✓ / ? / ✗ for each of the 6 checks. 2. Add notes if useful (e.g. “warp visible at occipital pole”). 3. The verdict column updates live: include / uncertain / exclude / unrated. 4. Click Download TSV when done. Save as data/ds000102/derivatives/qc_decisions.tsv.
Your ratings auto-save to localStorage, so you can close the page and resume.
9.4 4. Apply the inclusion rules
make qc-summarize \
TSV=data/ds000102/derivatives/qc_decisions.tsv \
MARKDOWN_OUT=data/ds000102/derivatives/qc_summary.md
cat data/ds000102/derivatives/qc_summary.mdExpected:
Included: 18
Uncertain: 3
Excluded: 2
Unrated: 3
The Markdown summary is manuscript-ready — paste into your Methods under “Inclusion criteria.”
9.5 5. Use the inclusion mask in downstream code
from libs.reporting import load_qc_decisions
from libs.paths import get_paths
paths = get_paths()
decisions = load_qc_decisions(paths.derivatives("qc_decisions.tsv"))
print(f"Group analysis on {len(decisions.included)} included subjects")
for sub in sorted(decisions.included):
# ... run group-level glm / connectomics / etc.
pass9.6 6. Why this is better than “spreadsheet QC”
The spreadsheet way: open every report, jot ratings in Excel, copy the include list into the GLM script.
The QC rater way: - Schema is fixed (6 checks, 3 levels, free-text notes). - Verdicts are reproducible from the TSV alone — anyone with the TSV can reconstruct your inclusion decisions. - The TSV is git-trackable; commit it to your project repo. - Downstream code parses the TSV, not free-form Excel. - Manuscript Methods can quote the per-check thresholds because they’re defined in libs.reporting.qc_rater._verdict_for.
This is the pattern HALFpipe pioneered. We’ve adopted it as a standalone module so it works with any fMRIPrep run, not just HALFpipe pipelines.
✅ Chapter 3 complete. Continue to 04_resting_state_derivatives.md to compute first-level derivatives on the included subjects.
9.7 What’s different from Andy’s Brain Book Tutorial #3
Brain Book teaches you what to look for. We teach you what to look for, plus how to capture your decisions in a machine-readable form. Brain Book ends with “now you know if your data are usable;” we end with “now you have a qc_decisions.tsv that gates every downstream analysis.” Same pedagogy, plus the inclusion-criteria contract that makes the analysis re-runnable.